https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/151377

This adds a new CIR type, cir.vptr, and generates a field of that type when a 
record is declared that requires a vptr member.

>From e6a0352f42818a13ece66f505d6cb107cb3dea0e Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Wed, 30 Jul 2025 11:43:02 -0700
Subject: [PATCH] [CIR] Add vptr type and generate vptr field when needed

This adds a new CIR type, cir.vptr, and generates a field of
that type when a record is declared that requires a vptr member.
---
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  | 31 ++++++++++++++++++-
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 13 ++++++--
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp         | 18 +++++++++++
 .../CIR/CodeGen/virtual-function-calls.cpp    | 13 ++++++++
 4 files changed, 71 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/virtual-function-calls.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index edd21b55640b9..4e8a8db091c7f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -281,6 +281,35 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// CIR_VPtrType
+//===----------------------------------------------------------------------===//
+
+def CIR_VPtrType : CIR_Type<"VPtr", "vptr",
+    [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+
+  let summary = "CIR type that is used for the vptr member of C++ objects";
+  let description = [{
+    `cir.vptr` is a special type used as the type for the vptr member of a C++
+    object. This avoids using arbitrary pointer types to declare vptr values
+    and allows stronger type-based checking for operations that use or provide
+    access to the vptr.
+
+    This type will be the element type of the 'vptr' member of structures that
+    require a vtable pointer. A pointer to this type is returned by the
+    `cir.vtable.address_point` and `cir.vtable.get_vptr` operations, and this
+    pointer may be passed to the `cir.vtable.get_virtual_fn_addr` operation to
+    get the address of a virtual function pointer.
+
+    The pointer may also be cast to other pointer types in order to perform
+    pointer arithmetic based on information encoded in the AST layout to get
+    the offset from a pointer to a dynamic object to the base object pointer,
+    the base object offset value from the vtable, or the type information
+    entry for an object.
+    TODO: We should have special operations to do that too.
+  }];
+}
+
 
//===----------------------------------------------------------------------===//
 // BoolType
 
//===----------------------------------------------------------------------===//
@@ -635,7 +664,7 @@ def CIRRecordType : Type<
 def CIR_AnyType : AnyTypeOf<[
   CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
   CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
-  CIR_ComplexType
+  CIR_ComplexType, CIR_VPtrType
 ]>;
 
 #endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp 
b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index e4ec380043689..170cd7583855f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -41,7 +41,7 @@ struct CIRRecordLowering final {
   // member type that ensures correct rounding.
   struct MemberInfo final {
     CharUnits offset;
-    enum class InfoKind { Field, Base } kind;
+    enum class InfoKind { VFPtr, Field, Base } kind;
     mlir::Type data;
     union {
       const FieldDecl *fieldDecl;
@@ -87,6 +87,8 @@ struct CIRRecordLowering final {
   accumulateBitFields(RecordDecl::field_iterator field,
                       RecordDecl::field_iterator fieldEnd);
 
+  mlir::Type getVFPtrType();
+
   bool isAAPCS() const {
     return astContext.getTargetInfo().getABI().starts_with("aapcs");
   }
@@ -802,9 +804,14 @@ void CIRRecordLowering::accumulateBases(const 
CXXRecordDecl *cxxRecordDecl) {
 
 void CIRRecordLowering::accumulateVPtrs() {
   if (astRecordLayout.hasOwnVFPtr())
-    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
-                                       "accumulateVPtrs: hasOwnVFPtr");
+    members.push_back(MemberInfo(CharUnits::Zero(), 
MemberInfo::InfoKind::VFPtr,
+                                 getVFPtrType()));
+
   if (astRecordLayout.hasOwnVBPtr())
     cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                        "accumulateVPtrs: hasOwnVBPtr");
 }
+
+mlir::Type CIRRecordLowering::getVFPtrType() {
+  return cir::VPtrType::get(builder.getContext());
+}
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 40da5e60a93f9..04c4660f03096 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -697,6 +697,24 @@ BoolType::getABIAlignment(const ::mlir::DataLayout 
&dataLayout,
   return 1;
 }
 
+//===----------------------------------------------------------------------===//
+//  VPtrType Definitions
+//===----------------------------------------------------------------------===//
+
+llvm::TypeSize
+VPtrType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
+                            ::mlir::DataLayoutEntryListRef params) const {
+  // FIXME: consider size differences under different ABIs
+  return llvm::TypeSize::getFixed(64);
+}
+
+uint64_t
+VPtrType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+                          ::mlir::DataLayoutEntryListRef params) const {
+  // FIXME: consider alignment differences under different ABIs
+  return 8;
+}
+
 
//===----------------------------------------------------------------------===//
 //  ArrayType Definitions
 
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/CodeGen/virtual-function-calls.cpp 
b/clang/test/CIR/CodeGen/virtual-function-calls.cpp
new file mode 100644
index 0000000000000..3e03b32ce1fd2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/virtual-function-calls.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+
+struct A {
+  virtual void f(char);
+};
+
+// This is just here to force the class definition to be emitted without
+// requiring any other support. It will be removed when more complete
+// vtable support is implemented.
+A *a;
+
+// CIR: !rec_A = !cir.record<struct "A" {!cir.vptr}>

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to