Skip to content

Commit c188e1d

Browse files
authored
[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.
1 parent 4820b18 commit c188e1d

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,35 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
281281
}];
282282
}
283283

284+
//===----------------------------------------------------------------------===//
285+
// CIR_VPtrType
286+
//===----------------------------------------------------------------------===//
287+
288+
def CIR_VPtrType : CIR_Type<"VPtr", "vptr", [
289+
DeclareTypeInterfaceMethods<DataLayoutTypeInterface>
290+
]> {
291+
let summary = "CIR type that is used for the vptr member of C++ objects";
292+
let description = [{
293+
`cir.vptr` is a special type used as the type for the vptr member of a C++
294+
object. This avoids using arbitrary pointer types to declare vptr values
295+
and allows stronger type-based checking for operations that use or provide
296+
access to the vptr.
297+
298+
This type will be the element type of the 'vptr' member of structures that
299+
require a vtable pointer. A pointer to this type is returned by the
300+
`cir.vtable.address_point` and `cir.vtable.get_vptr` operations, and this
301+
pointer may be passed to the `cir.vtable.get_virtual_fn_addr` operation to
302+
get the address of a virtual function pointer.
303+
304+
The pointer may also be cast to other pointer types in order to perform
305+
pointer arithmetic based on information encoded in the AST layout to get
306+
the offset from a pointer to a dynamic object to the base object pointer,
307+
the base object offset value from the vtable, or the type information
308+
entry for an object.
309+
TODO: We should have special operations to do that too.
310+
}];
311+
}
312+
284313
//===----------------------------------------------------------------------===//
285314
// BoolType
286315
//===----------------------------------------------------------------------===//
@@ -635,7 +664,7 @@ def CIRRecordType : Type<
635664
def CIR_AnyType : AnyTypeOf<[
636665
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
637666
CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
638-
CIR_ComplexType
667+
CIR_ComplexType, CIR_VPtrType
639668
]>;
640669

641670
#endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD

clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct CIRRecordLowering final {
4141
// member type that ensures correct rounding.
4242
struct MemberInfo final {
4343
CharUnits offset;
44-
enum class InfoKind { Field, Base } kind;
44+
enum class InfoKind { VFPtr, Field, Base } kind;
4545
mlir::Type data;
4646
union {
4747
const FieldDecl *fieldDecl;
@@ -87,6 +87,8 @@ struct CIRRecordLowering final {
8787
accumulateBitFields(RecordDecl::field_iterator field,
8888
RecordDecl::field_iterator fieldEnd);
8989

90+
mlir::Type getVFPtrType();
91+
9092
bool isAAPCS() const {
9193
return astContext.getTargetInfo().getABI().starts_with("aapcs");
9294
}
@@ -902,9 +904,14 @@ void CIRRecordLowering::accumulateBases(const CXXRecordDecl *cxxRecordDecl) {
902904

903905
void CIRRecordLowering::accumulateVPtrs() {
904906
if (astRecordLayout.hasOwnVFPtr())
905-
cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
906-
"accumulateVPtrs: hasOwnVFPtr");
907+
members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::InfoKind::VFPtr,
908+
getVFPtrType()));
909+
907910
if (astRecordLayout.hasOwnVBPtr())
908911
cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
909912
"accumulateVPtrs: hasOwnVBPtr");
910913
}
914+
915+
mlir::Type CIRRecordLowering::getVFPtrType() {
916+
return cir::VPtrType::get(builder.getContext());
917+
}

clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,23 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
697697
return 1;
698698
}
699699

700+
//===----------------------------------------------------------------------===//
701+
// VPtrType Definitions
702+
//===----------------------------------------------------------------------===//
703+
704+
llvm::TypeSize
705+
VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
706+
mlir::DataLayoutEntryListRef params) const {
707+
// FIXME: consider size differences under different ABIs
708+
return llvm::TypeSize::getFixed(64);
709+
}
710+
711+
uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout,
712+
mlir::DataLayoutEntryListRef params) const {
713+
// FIXME: consider alignment differences under different ABIs
714+
return 8;
715+
}
716+
700717
//===----------------------------------------------------------------------===//
701718
// ArrayType Definitions
702719
//===----------------------------------------------------------------------===//
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
4+
struct A {
5+
virtual void f(char);
6+
};
7+
8+
// This is just here to force the class definition to be emitted without
9+
// requiring any other support. It will be removed when more complete
10+
// vtable support is implemented.
11+
A *a;
12+
13+
// CIR: !rec_A = !cir.record<struct "A" {!cir.vptr}>

0 commit comments

Comments
 (0)