Author: Andy Kaylor
Date: 2025-08-01T12:10:04-07:00
New Revision: c188e1db6a4c469f5ad92c4ce088fd113335410f

URL: 
https://github.com/llvm/llvm-project/commit/c188e1db6a4c469f5ad92c4ce088fd113335410f
DIFF: 
https://github.com/llvm/llvm-project/commit/c188e1db6a4c469f5ad92c4ce088fd113335410f.diff

LOG: [CIR] Add vptr type and generate vptr field when needed (#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.

Added: 
    clang/test/CIR/CodeGen/virtual-function-calls.cpp

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIRTypes.td
    clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
    clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index edd21b55640b9..a258df79a6184 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 0c8ff4bd807ad..8b01d41a8a354 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");
   }
@@ -902,9 +904,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..4fecb0108e001 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -697,6 +697,23 @@ 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 
diff erences under 
diff erent ABIs
+  return llvm::TypeSize::getFixed(64);
+}
+
+uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout,
+                                   mlir::DataLayoutEntryListRef params) const {
+  // FIXME: consider alignment 
diff erences under 
diff erent 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