From e6a0352f42818a13ece66f505d6cb107cb3dea0e Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Wed, 30 Jul 2025 11:43:02 -0700 Subject: [PATCH 1/3] [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]> { + + 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 From 790c766ce5973c4eebe3aa86fc0a19a040cf5532 Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Fri, 1 Aug 2025 09:28:14 -0700 Subject: [PATCH 2/3] Address review feedback --- clang/include/clang/CIR/Dialect/IR/CIRTypes.td | 6 +++--- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 4e8a8db091c7f..a258df79a6184 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -285,9 +285,9 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ // CIR_VPtrType //===----------------------------------------------------------------------===// -def CIR_VPtrType : CIR_Type<"VPtr", "vptr", - [DeclareTypeInterfaceMethods]> { - +def CIR_VPtrType : CIR_Type<"VPtr", "vptr", [ + DeclareTypeInterfaceMethods +]> { 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++ diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 04c4660f03096..db527f232021e 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -702,15 +702,15 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout, //===----------------------------------------------------------------------===// llvm::TypeSize -VPtrType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, - ::mlir::DataLayoutEntryListRef params) const { +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 { +VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout, + mlir::DataLayoutEntryListRef params) const { // FIXME: consider alignment differences under different ABIs return 8; } From 59c836df3af0300ce2bd20f80fb109b4f56d96ca Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Fri, 1 Aug 2025 10:10:56 -0700 Subject: [PATCH 3/3] Fix formatting --- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index db527f232021e..4fecb0108e001 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -708,9 +708,8 @@ VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout, return llvm::TypeSize::getFixed(64); } -uint64_t -VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout, - mlir::DataLayoutEntryListRef params) const { +uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout, + mlir::DataLayoutEntryListRef params) const { // FIXME: consider alignment differences under different ABIs return 8; }