Skip to content

Commit d8d87b5

Browse files
authored
[CIR] Add support for global member pointer values (#171888)
This adds the handling necessary to support global variables that are data member pointers in CIR.
1 parent e281800 commit d8d87b5

File tree

3 files changed

+62
-26
lines changed

3 files changed

+62
-26
lines changed

clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,24 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
18761876
mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
18771877
}
18781878
case APValue::MemberPointer: {
1879-
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
1880-
return {};
1879+
assert(!cir::MissingFeatures::cxxABI());
1880+
1881+
const ValueDecl *memberDecl = value.getMemberPointerDecl();
1882+
if (value.isMemberPointerToDerivedMember()) {
1883+
cgm.errorNYI(
1884+
"ConstExprEmitter::tryEmitPrivate member pointer to derived member");
1885+
return {};
1886+
}
1887+
1888+
if (isa<CXXMethodDecl>(memberDecl)) {
1889+
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer to method");
1890+
return {};
1891+
}
1892+
1893+
auto cirTy = mlir::cast<cir::DataMemberType>(cgm.convertType(destType));
1894+
1895+
const auto *fieldDecl = cast<FieldDecl>(memberDecl);
1896+
return builder.getDataMemberAttr(cirTy, fieldDecl->getFieldIndex());
18811897
}
18821898
case APValue::LValue:
18831899
return ConstantLValueEmitter(*this, value, destType).tryEmit();

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,18 @@ class CIRAttrToValue {
249249
public:
250250
CIRAttrToValue(mlir::Operation *parentOp,
251251
mlir::ConversionPatternRewriter &rewriter,
252-
const mlir::TypeConverter *converter)
253-
: parentOp(parentOp), rewriter(rewriter), converter(converter) {}
252+
const mlir::TypeConverter *converter,
253+
cir::LowerModule *lowerMod)
254+
: parentOp(parentOp), rewriter(rewriter), converter(converter),
255+
lowerMod(lowerMod) {}
254256

255257
mlir::Value visit(mlir::Attribute attr) {
256258
return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
257259
.Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
258260
cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
259-
cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
260-
cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
261-
[&](auto attrT) { return visitCirAttr(attrT); })
261+
cir::ConstPtrAttr, cir::DataMemberAttr, cir::GlobalViewAttr,
262+
cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
263+
cir::ZeroAttr>([&](auto attrT) { return visitCirAttr(attrT); })
262264
.Default([&](auto attrT) { return mlir::Value(); });
263265
}
264266

@@ -269,6 +271,7 @@ class CIRAttrToValue {
269271
mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
270272
mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
271273
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
274+
mlir::Value visitCirAttr(cir::DataMemberAttr attr);
272275
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
273276
mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
274277
mlir::Value visitCirAttr(cir::UndefAttr attr);
@@ -279,14 +282,16 @@ class CIRAttrToValue {
279282
mlir::Operation *parentOp;
280283
mlir::ConversionPatternRewriter &rewriter;
281284
const mlir::TypeConverter *converter;
285+
cir::LowerModule *lowerMod;
282286
};
283287

284288
/// Switches on the type of attribute and calls the appropriate conversion.
285289
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
286290
const mlir::Attribute attr,
287291
mlir::ConversionPatternRewriter &rewriter,
288-
const mlir::TypeConverter *converter) {
289-
CIRAttrToValue valueConverter(parentOp, rewriter, converter);
292+
const mlir::TypeConverter *converter,
293+
cir::LowerModule *lowerMod) {
294+
CIRAttrToValue valueConverter(parentOp, rewriter, converter, lowerMod);
290295
mlir::Value value = valueConverter.visit(attr);
291296
if (!value)
292297
llvm_unreachable("unhandled attribute type");
@@ -521,6 +526,15 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
521526
mlirValues));
522527
}
523528

529+
mlir::Value CIRAttrToValue::visitCirAttr(cir::DataMemberAttr attr) {
530+
assert(lowerMod && "lower module is not available");
531+
mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
532+
mlir::TypedAttr init =
533+
lowerMod->getCXXABI().lowerDataMemberConstant(attr, layout, *converter);
534+
// Recursively lower the CIR attribute produced by the C++ ABI.
535+
return visit(init);
536+
}
537+
524538
// GlobalViewAttr visitor.
525539
mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
526540
auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
@@ -1756,7 +1770,8 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
17561770
}
17571771
// Lower GlobalViewAttr to llvm.mlir.addressof
17581772
if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1759-
auto newOp = lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter());
1773+
auto newOp =
1774+
lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter(), lowerMod);
17601775
rewriter.replaceOp(op, newOp);
17611776
return mlir::success();
17621777
}
@@ -1776,32 +1791,33 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
17761791

17771792
std::optional<mlir::Attribute> denseAttr;
17781793
if (constArr && hasTrailingZeros(constArr)) {
1779-
const mlir::Value newOp =
1780-
lowerCirAttrAsValue(op, constArr, rewriter, getTypeConverter());
1794+
const mlir::Value newOp = lowerCirAttrAsValue(
1795+
op, constArr, rewriter, getTypeConverter(), lowerMod);
17811796
rewriter.replaceOp(op, newOp);
17821797
return mlir::success();
17831798
} else if (constArr &&
17841799
(denseAttr = lowerConstArrayAttr(constArr, typeConverter))) {
17851800
attr = denseAttr.value();
17861801
} else {
1787-
const mlir::Value initVal =
1788-
lowerCirAttrAsValue(op, op.getValue(), rewriter, typeConverter);
1802+
const mlir::Value initVal = lowerCirAttrAsValue(
1803+
op, op.getValue(), rewriter, typeConverter, lowerMod);
17891804
rewriter.replaceOp(op, initVal);
17901805
return mlir::success();
17911806
}
17921807
} else if (const auto recordAttr =
17931808
mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1794-
auto initVal = lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter);
1809+
auto initVal =
1810+
lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter, lowerMod);
17951811
rewriter.replaceOp(op, initVal);
17961812
return mlir::success();
17971813
} else if (const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
17981814
rewriter.replaceOp(op, lowerCirAttrAsValue(op, op.getValue(), rewriter,
1799-
getTypeConverter()));
1815+
getTypeConverter(), lowerMod));
18001816
return mlir::success();
18011817
} else if (auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
18021818
if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
18031819
mlir::Value initVal =
1804-
lowerCirAttrAsValue(op, attr, rewriter, typeConverter);
1820+
lowerCirAttrAsValue(op, attr, rewriter, typeConverter, lowerMod);
18051821
rewriter.replaceOp(op, initVal);
18061822
return mlir::success();
18071823
}
@@ -2109,18 +2125,17 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
21092125
cir::GlobalOp op, mlir::Attribute init,
21102126
mlir::ConversionPatternRewriter &rewriter) const {
21112127
// TODO: Generalize this handling when more types are needed here.
2112-
assert(
2113-
(isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2114-
cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2115-
cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2116-
init)));
2128+
assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2129+
cir::ConstPtrAttr, cir::ConstComplexAttr, cir::DataMemberAttr,
2130+
cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2131+
cir::VTableAttr, cir::ZeroAttr>(init)));
21172132

21182133
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
21192134
// should be updated. For now, we use a custom op to initialize globals
21202135
// to the appropriate value.
21212136
const mlir::Location loc = op.getLoc();
21222137
setupRegionInitializedLLVMGlobalOp(op, rewriter);
2123-
CIRAttrToValue valueConverter(op, rewriter, typeConverter);
2138+
CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
21242139
mlir::Value value = valueConverter.visit(init);
21252140
mlir::LLVM::ReturnOp::create(rewriter, loc, value);
21262141
return mlir::success();
@@ -2169,9 +2184,9 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
21692184
}
21702185
} else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
21712186
cir::ConstRecordAttr, cir::ConstPtrAttr,
2172-
cir::ConstComplexAttr, cir::GlobalViewAttr,
2173-
cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2174-
cir::ZeroAttr>(init.value())) {
2187+
cir::ConstComplexAttr, cir::DataMemberAttr,
2188+
cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2189+
cir::VTableAttr, cir::ZeroAttr>(init.value())) {
21752190
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
21762191
// should be updated. For now, we use a custom op to initialize globals
21772192
// to the appropriate value.

clang/test/CIR/CodeGen/pointer-to-data-member.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ struct Point {
1111
int z;
1212
};
1313

14+
int Point::*pt_member = &Point::z;
15+
// CIR: cir.global external @pt_member = #cir.data_member<2> : !cir.data_member<!s32i in !rec_Point>
16+
// LLVM: @pt_member = global i64 8
17+
// OGCG: @pt_member = global i64 8
18+
1419
auto test1() -> int Point::* {
1520
return &Point::y;
1621
}

0 commit comments

Comments
 (0)