-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[CIR] Add vptr type and generate vptr field when needed #151377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesThis adds a new CIR type, cir.vptr, and generates a field of that type when a record is declared that requires a vptr member. Full diff: https://github.com/llvm/llvm-project/pull/151377.diff 4 Files Affected:
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}>
|
Corresponding changes at llvm/clangir#1745 show how I intend to use this type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
def CIR_VPtrType : CIR_Type<"VPtr", "vptr", | ||
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, to align with style of the rest:
def CIR_VPtrType : CIR_Type<"VPtr", "vptr", | |
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> { | |
def CIR_VPtrType : CIR_Type<"VPtr", "vptr", [ | |
DeclareTypeInterfaceMethods<DataLayoutTypeInterface> | |
]> { |
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason these have ::mlir
not just mlir
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. I copied this code from another type, and I guess it had the scoping that way. I'll fix it.
✅ With the latest revision this PR passed the C/C++ code formatter. |
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.