https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/171888
This adds the handling necessary to support global variables that are data member pointers in CIR. >From 4e49554b10c2d6e594967784537578e37f0c80ac Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Tue, 9 Dec 2025 14:24:53 -0800 Subject: [PATCH] [CIR] Add support for global member pointer values This adds the handling necessary to support global variables that are data member pointers in CIR. --- clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 20 +++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 63 ++++++++++++------- .../CIR/CodeGen/pointer-to-data-member.cpp | 5 ++ 3 files changed, 62 insertions(+), 26 deletions(-) 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; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
