Skip to content

Commit 87bf5ee

Browse files
authored
[CIR] Add basic support for data member pointers (#170939)
This adds the minimum support for C++ data member pointer variables.
1 parent 019a294 commit 87bf5ee

26 files changed

+631
-12
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace cir {
3535
class ArrayType;
3636
class BoolType;
3737
class ComplexType;
38+
class DataMemberType;
3839
class IntType;
3940
class MethodType;
4041
class PointerType;

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,57 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
447447
}];
448448
}
449449

450+
//===----------------------------------------------------------------------===//
451+
// DataMemberAttr
452+
//===----------------------------------------------------------------------===//
453+
454+
def CIR_DataMemberAttr : CIR_Attr<"DataMember", "data_member", [
455+
TypedAttrInterface
456+
]> {
457+
let summary = "Holds a constant data member pointer value";
458+
let parameters = (ins AttributeSelfTypeParameter<
459+
"", "cir::DataMemberType">:$type,
460+
OptionalParameter<
461+
"std::optional<unsigned>">:$member_index);
462+
let description = [{
463+
A data member attribute is a literal attribute that represents a constant
464+
pointer-to-data-member value.
465+
466+
The `member_index` parameter represents the index of the pointed-to member
467+
within its containing record. It is an optional parameter; lack of this
468+
parameter indicates a null pointer-to-data-member value.
469+
470+
Example:
471+
```
472+
#ptr = #cir.data_member<1> : !cir.data_member<!s32i in !rec_22Point22>
473+
474+
#null = #cir.data_member<null> : !cir.data_member<!s32i in !rec_22Point22>
475+
```
476+
}];
477+
478+
let builders = [
479+
AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type), [{
480+
return $_get(type.getContext(), type, std::nullopt);
481+
}]>,
482+
AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type,
483+
"unsigned":$member_index), [{
484+
return $_get(type.getContext(), type, member_index);
485+
}]>,
486+
];
487+
488+
let genVerifyDecl = 1;
489+
490+
let assemblyFormat = [{
491+
`<` ($member_index^):(`null`)? `>`
492+
}];
493+
494+
let extraClassDeclaration = [{
495+
bool isNullPtr() const {
496+
return !getMemberIndex().has_value();
497+
}
498+
}];
499+
}
500+
450501
//===----------------------------------------------------------------------===//
451502
// GlobalViewAttr
452503
//===----------------------------------------------------------------------===//

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,13 @@ def CIR_AnyFloatOrVecOfFloatType
309309
let cppFunctionName = "isFPOrVectorOfFPType";
310310
}
311311

312+
//===----------------------------------------------------------------------===//
313+
// Data member type predicates
314+
//===----------------------------------------------------------------------===//
315+
316+
def CIR_AnyDataMemberType : CIR_TypeBase<"::cir::DataMemberType",
317+
"data member type">;
318+
312319
//===----------------------------------------------------------------------===//
313320
// VPtr type predicates
314321
//===----------------------------------------------------------------------===//
@@ -322,7 +329,8 @@ def CIR_PtrToVPtr : CIR_PtrToType<CIR_AnyVPtrType>;
322329
//===----------------------------------------------------------------------===//
323330

324331
defvar CIR_ScalarTypes = [
325-
CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType
332+
CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType,
333+
CIR_AnyDataMemberType, CIR_AnyVPtrType
326334
];
327335

328336
def CIR_AnyScalarType : AnyTypeOf<CIR_ScalarTypes, "cir scalar type"> {

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,36 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
305305
}];
306306
}
307307

308+
//===----------------------------------------------------------------------===//
309+
// CIR_DataMemberType
310+
//===----------------------------------------------------------------------===//
311+
312+
def CIR_DataMemberType : CIR_Type<"DataMember", "data_member",
313+
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]
314+
> {
315+
let summary = "CIR type that represents a pointer-to-data-member in C++";
316+
let description = [{
317+
`cir.data_member` models a pointer-to-data-member in C++. Values of this
318+
type are essentially offsets of the pointed-to member within one of its
319+
containing record.
320+
}];
321+
322+
let parameters = (ins "mlir::Type":$member_ty,
323+
"cir::RecordType":$class_ty);
324+
325+
let builders = [
326+
TypeBuilderWithInferredContext<(ins
327+
"mlir::Type":$member_ty, "cir::RecordType":$class_ty
328+
), [{
329+
return $_get(member_ty.getContext(), member_ty, class_ty);
330+
}]>,
331+
];
332+
333+
let assemblyFormat = [{
334+
`<` $member_ty `in` $class_ty `>`
335+
}];
336+
}
337+
308338
//===----------------------------------------------------------------------===//
309339
// CIR_VPtrType
310340
//===----------------------------------------------------------------------===//
@@ -693,7 +723,7 @@ def CIRRecordType : Type<
693723
def CIR_AnyType : AnyTypeOf<[
694724
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
695725
CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
696-
CIR_ComplexType, CIR_VPtrType
726+
CIR_ComplexType, CIR_VPtrType, CIR_DataMemberType
697727
]>;
698728

699729
#endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ struct MissingFeatures {
189189
static bool globalCtorLexOrder() { return false; }
190190
static bool globalCtorAssociatedData() { return false; }
191191

192+
// LowerModule handling
193+
static bool lowerModuleCodeGenOpts() { return false; }
194+
static bool lowerModuleLangOpts() { return false; }
195+
192196
// Misc
193197
static bool aarch64SIMDIntrinsics() { return false; }
194198
static bool aarch64SMEIntrinsics() { return false; }
@@ -292,6 +296,7 @@ struct MissingFeatures {
292296
static bool lowerModeOptLevel() { return false; }
293297
static bool loweringPrepareX86CXXABI() { return false; }
294298
static bool loweringPrepareAArch64XXABI() { return false; }
299+
static bool makeTripleAlwaysPresent() { return false; }
295300
static bool maybeHandleStaticInExternC() { return false; }
296301
static bool mergeAllConstants() { return false; }
297302
static bool metaDataNode() { return false; }

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
189189
return getType<cir::RecordType>(nameAttr, kind);
190190
}
191191

192+
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty,
193+
unsigned memberIndex) {
194+
return cir::DataMemberAttr::get(ty, memberIndex);
195+
}
196+
192197
// Return true if the value is a null constant such as null pointer, (+0.0)
193198
// for floating-point or zero initializer
194199
bool isNullValue(mlir::Attribute attr) const {

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
731731
}
732732

733733
mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
734-
if (llvm::isa<MemberPointerType>(e->getType())) {
735-
cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer");
736-
return builder.getNullPtr(cgf.convertType(e->getType()),
737-
cgf.getLoc(e->getExprLoc()));
738-
}
734+
if (llvm::isa<MemberPointerType>(e->getType()))
735+
return cgf.cgm.emitMemberPointerConstant(e);
739736

740737
return cgf.emitLValue(e->getSubExpr()).getPointer();
741738
}

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,26 @@ void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
14641464
"emitExplicitCastExprType");
14651465
}
14661466

1467+
mlir::Value CIRGenModule::emitMemberPointerConstant(const UnaryOperator *e) {
1468+
assert(!cir::MissingFeatures::cxxABI());
1469+
1470+
mlir::Location loc = getLoc(e->getSourceRange());
1471+
1472+
const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1473+
1474+
// A member function pointer.
1475+
if (isa<CXXMethodDecl>(decl)) {
1476+
errorNYI(e->getSourceRange(), "emitMemberPointerConstant: method pointer");
1477+
return {};
1478+
}
1479+
1480+
// Otherwise, a member data pointer.
1481+
auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1482+
const auto *fieldDecl = cast<FieldDecl>(decl);
1483+
return cir::ConstantOp::create(
1484+
builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1485+
}
1486+
14671487
void CIRGenModule::emitDeclContext(const DeclContext *dc) {
14681488
for (Decl *decl : dc->decls()) {
14691489
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,8 @@ class CIRGenModule : public CIRGenTypeCache {
497497
/// the given type. This is usually, but not always, an LLVM null constant.
498498
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record);
499499

500+
mlir::Value emitMemberPointerConstant(const UnaryOperator *e);
501+
500502
llvm::StringRef getMangledName(clang::GlobalDecl gd);
501503

502504
void emitTentativeDefinition(const VarDecl *d);

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,21 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
482482
break;
483483
}
484484

485+
case Type::MemberPointer: {
486+
const auto *mpt = cast<MemberPointerType>(ty);
487+
488+
mlir::Type memberTy = convertType(mpt->getPointeeType());
489+
auto clsTy = mlir::cast<cir::RecordType>(
490+
convertType(QualType(mpt->getQualifier().getAsType(), 0)));
491+
if (mpt->isMemberDataPointer()) {
492+
resultType = cir::DataMemberType::get(memberTy, clsTy);
493+
} else {
494+
assert(!cir::MissingFeatures::methodType());
495+
cgm.errorNYI(SourceLocation(), "MethodType");
496+
}
497+
break;
498+
}
499+
485500
case Type::FunctionNoProto:
486501
case Type::FunctionProto:
487502
resultType = convertFunctionTypeInternal(type);

0 commit comments

Comments
 (0)