-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[CIR] Add support for global member pointer values #171888
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
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This adds the handling necessary to support global variables that are data member pointers in CIR.
Member
|
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesThis adds the handling necessary to support global variables that are data member pointers in CIR. Full diff: https://github.com/llvm/llvm-project/pull/171888.diff 3 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 329fd08bc8914..a474defb7f627 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1876,8 +1876,24 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
}
case APValue::MemberPointer: {
- cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
- return {};
+ assert(!cir::MissingFeatures::cxxABI());
+
+ const ValueDecl *memberDecl = value.getMemberPointerDecl();
+ if (value.isMemberPointerToDerivedMember()) {
+ cgm.errorNYI(
+ "ConstExprEmitter::tryEmitPrivate member pointer to derived member");
+ return {};
+ }
+
+ if (isa<CXXMethodDecl>(memberDecl)) {
+ cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer to method");
+ return {};
+ }
+
+ auto cirTy = mlir::cast<cir::DataMemberType>(cgm.convertType(destType));
+
+ const auto *fieldDecl = cast<FieldDecl>(memberDecl);
+ return builder.getDataMemberAttr(cirTy, fieldDecl->getFieldIndex());
}
case APValue::LValue:
return ConstantLValueEmitter(*this, value, destType).tryEmit();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 00307df62ce5a..c01b2c1487709 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -249,16 +249,18 @@ class CIRAttrToValue {
public:
CIRAttrToValue(mlir::Operation *parentOp,
mlir::ConversionPatternRewriter &rewriter,
- const mlir::TypeConverter *converter)
- : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
+ const mlir::TypeConverter *converter,
+ cir::LowerModule *lowerMod)
+ : parentOp(parentOp), rewriter(rewriter), converter(converter),
+ lowerMod(lowerMod) {}
mlir::Value visit(mlir::Attribute attr) {
return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
.Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
- cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
- cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
- [&](auto attrT) { return visitCirAttr(attrT); })
+ cir::ConstPtrAttr, cir::DataMemberAttr, cir::GlobalViewAttr,
+ cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
+ cir::ZeroAttr>([&](auto attrT) { return visitCirAttr(attrT); })
.Default([&](auto attrT) { return mlir::Value(); });
}
@@ -269,6 +271,7 @@ class CIRAttrToValue {
mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
+ mlir::Value visitCirAttr(cir::DataMemberAttr attr);
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
mlir::Value visitCirAttr(cir::UndefAttr attr);
@@ -279,14 +282,16 @@ class CIRAttrToValue {
mlir::Operation *parentOp;
mlir::ConversionPatternRewriter &rewriter;
const mlir::TypeConverter *converter;
+ cir::LowerModule *lowerMod;
};
/// Switches on the type of attribute and calls the appropriate conversion.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
const mlir::Attribute attr,
mlir::ConversionPatternRewriter &rewriter,
- const mlir::TypeConverter *converter) {
- CIRAttrToValue valueConverter(parentOp, rewriter, converter);
+ const mlir::TypeConverter *converter,
+ cir::LowerModule *lowerMod) {
+ CIRAttrToValue valueConverter(parentOp, rewriter, converter, lowerMod);
mlir::Value value = valueConverter.visit(attr);
if (!value)
llvm_unreachable("unhandled attribute type");
@@ -521,6 +526,15 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
mlirValues));
}
+mlir::Value CIRAttrToValue::visitCirAttr(cir::DataMemberAttr attr) {
+ assert(lowerMod && "lower module is not available");
+ mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
+ mlir::TypedAttr init =
+ lowerMod->getCXXABI().lowerDataMemberConstant(attr, layout, *converter);
+ // Recursively lower the CIR attribute produced by the C++ ABI.
+ return visit(init);
+}
+
// GlobalViewAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
@@ -1756,7 +1770,8 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
}
// Lower GlobalViewAttr to llvm.mlir.addressof
if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
- auto newOp = lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter());
+ auto newOp =
+ lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter(), lowerMod);
rewriter.replaceOp(op, newOp);
return mlir::success();
}
@@ -1776,32 +1791,33 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
std::optional<mlir::Attribute> denseAttr;
if (constArr && hasTrailingZeros(constArr)) {
- const mlir::Value newOp =
- lowerCirAttrAsValue(op, constArr, rewriter, getTypeConverter());
+ const mlir::Value newOp = lowerCirAttrAsValue(
+ op, constArr, rewriter, getTypeConverter(), lowerMod);
rewriter.replaceOp(op, newOp);
return mlir::success();
} else if (constArr &&
(denseAttr = lowerConstArrayAttr(constArr, typeConverter))) {
attr = denseAttr.value();
} else {
- const mlir::Value initVal =
- lowerCirAttrAsValue(op, op.getValue(), rewriter, typeConverter);
+ const mlir::Value initVal = lowerCirAttrAsValue(
+ op, op.getValue(), rewriter, typeConverter, lowerMod);
rewriter.replaceOp(op, initVal);
return mlir::success();
}
} else if (const auto recordAttr =
mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
- auto initVal = lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter);
+ auto initVal =
+ lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter, lowerMod);
rewriter.replaceOp(op, initVal);
return mlir::success();
} else if (const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
rewriter.replaceOp(op, lowerCirAttrAsValue(op, op.getValue(), rewriter,
- getTypeConverter()));
+ getTypeConverter(), lowerMod));
return mlir::success();
} else if (auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
mlir::Value initVal =
- lowerCirAttrAsValue(op, attr, rewriter, typeConverter);
+ lowerCirAttrAsValue(op, attr, rewriter, typeConverter, lowerMod);
rewriter.replaceOp(op, initVal);
return mlir::success();
}
@@ -2109,18 +2125,17 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
cir::GlobalOp op, mlir::Attribute init,
mlir::ConversionPatternRewriter &rewriter) const {
// TODO: Generalize this handling when more types are needed here.
- assert(
- (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
- cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
- cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
- init)));
+ assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
+ cir::ConstPtrAttr, cir::ConstComplexAttr, cir::DataMemberAttr,
+ cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
+ cir::VTableAttr, cir::ZeroAttr>(init)));
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
// should be updated. For now, we use a custom op to initialize globals
// to the appropriate value.
const mlir::Location loc = op.getLoc();
setupRegionInitializedLLVMGlobalOp(op, rewriter);
- CIRAttrToValue valueConverter(op, rewriter, typeConverter);
+ CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
mlir::Value value = valueConverter.visit(init);
mlir::LLVM::ReturnOp::create(rewriter, loc, value);
return mlir::success();
@@ -2169,9 +2184,9 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
}
} else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstRecordAttr, cir::ConstPtrAttr,
- cir::ConstComplexAttr, cir::GlobalViewAttr,
- cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
- cir::ZeroAttr>(init.value())) {
+ cir::ConstComplexAttr, cir::DataMemberAttr,
+ cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
+ cir::VTableAttr, cir::ZeroAttr>(init.value())) {
// TODO(cir): once LLVM's dialect has proper equivalent attributes this
// should be updated. For now, we use a custom op to initialize globals
// to the appropriate value.
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index 14d1befeed67f..bee6562e59b8e 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -11,6 +11,11 @@ struct Point {
int z;
};
+int Point::*pt_member = &Point::z;
+// CIR: cir.global external @pt_member = #cir.data_member<2> : !cir.data_member<!s32i in !rec_Point>
+// LLVM: @pt_member = global i64 8
+// OGCG: @pt_member = global i64 8
+
auto test1() -> int Point::* {
return &Point::y;
}
|
xlauko
approved these changes
Dec 11, 2025
Contributor
xlauko
left a comment
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This adds the handling necessary to support global variables that are data member pointers in CIR.