https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/205437
>From f385a01ae9eaebd9f07eddbf19aee8481a12a287 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Fri, 12 Jun 2026 17:18:56 -0700 Subject: [PATCH 1/5] [CIR] Handle label address difference This change adds handling for emitting AddrLabelDiff constants. These constants can be used to initialize static variables within a function by computing the difference between the addresses of two labels. These constant values are represented in the AST using the APValue class. The code generator needs to emit them as initializers for the global corresponding to the static variable. This change introduces a new CIR attribute type, BlockAddrDiffAttr to represent this constant value, deferring the label block address resolution until we lower the initializer to the LLVM dialect. Assisted-by: Cursor / claude-opus-4.8 --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 47 ++++++++++++ clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 20 ++++- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 9 ++- .../lib/CIR/Dialect/Transforms/GotoSolver.cpp | 8 ++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 72 +++++++++++++++--- clang/lib/CIR/Lowering/LoweringHelpers.cpp | 32 +++++++- clang/test/CIR/CodeGen/const-label-addr.c | 74 +++++++++++++++++++ 7 files changed, 242 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 253421ab764ff..1312a18ad1b2e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -1756,6 +1756,53 @@ def CIR_BlockAddrInfoAttr let canHaveIllegalCXXABIType = 0; } +//===----------------------------------------------------------------------===// +// CIR_BlockAddrDiffAttr +//===----------------------------------------------------------------------===// + +def CIR_BlockAddrDiffAttr + : CIR_ValueLikeAttr<"BlockAddrDiff", "block_addr_diff"> { + let summary = "Difference between two block addresses"; + let description = [{ + This attribute represents the constant difference between the addresses of + two basic blocks within the same function. It is produced for GCC's "labels + as values" extension when the difference of two label addresses appears in a + constant context, e.g. `&&lhs - &&rhs`. + + Both labels belong to the function referenced by `func`. The value is the + address of `lhs_label` minus the address of `rhs_label`, truncated to the + attribute's integer type. + + Example: + ``` + cir.global "private" internal @b.ar = + #cir.block_addr_diff<@b, "l2", "l1"> : !s32i + ``` + }]; + + let parameters = (ins + AttributeSelfTypeParameter<"", "cir::IntType">:$type, + "mlir::FlatSymbolRefAttr":$func, + "mlir::StringAttr":$lhs_label, + "mlir::StringAttr":$rhs_label); + + let assemblyFormat = "`<` $func `,` $lhs_label `,` $rhs_label `>`"; + + let builders = [ + AttrBuilder<(ins "cir::IntType":$type, + "llvm::StringRef":$func_name, + "llvm::StringRef":$lhs_label_name, + "llvm::StringRef":$rhs_label_name), [{ + return $_get($_ctxt, type, + mlir::FlatSymbolRefAttr::get($_ctxt, func_name), + mlir::StringAttr::get($_ctxt, lhs_label_name), + mlir::StringAttr::get($_ctxt, rhs_label_name)); + }]> + ]; + + let canHaveIllegalCXXABIType = 0; +} + //===----------------------------------------------------------------------===// // Side Effect //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 45868fba962aa..93d4fee235bad 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -1513,10 +1513,24 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value, cir::FPAttr::get(complexElemTy, imag)); } case APValue::FixedPoint: - case APValue::AddrLabelDiff: - cgm.errorNYI( - "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff"); + cgm.errorNYI("ConstExprEmitter::tryEmitPrivate fixed point"); return {}; + case APValue::AddrLabelDiff: { + const AddrLabelExpr *lhsExpr = value.getAddrLabelDiffLHS(); + const AddrLabelExpr *rhsExpr = value.getAddrLabelDiffRHS(); + + // Both labels belong to the function currently being emitted. The actual + // subtraction (ptrtoint of each block address, subtract, then truncate to + // the result type) is deferred to the LowerToLLVM pass, which is where + // block addresses are resolved to concrete basic blocks. + mlir::Type resultType = cgm.getTypes().convertType(destType); + auto intResultType = mlir::cast<cir::IntType>(resultType); + auto func = cast<cir::FuncOp>(cgf->curFn); + return cir::BlockAddrDiffAttr::get( + builder.getContext(), intResultType, func.getSymName(), + lhsExpr->getLabel()->getName(), rhsExpr->getLabel()->getName()); + } + case APValue::Matrix: cgm.errorNYI("ConstExprEmitter::tryEmitPrivate matrix"); return {}; diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 6b7724d3ea06a..903352b380c03 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -617,10 +617,11 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, return success(); } - if (mlir::isa<cir::BlockAddrInfoAttr, cir::ConstArrayAttr, - cir::ConstVectorAttr, cir::ConstComplexAttr, - cir::ConstRecordAttr, cir::GlobalViewAttr, cir::PoisonAttr, - cir::TypeInfoAttr, cir::VTableAttr>(attrType)) + if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, + cir::ConstArrayAttr, cir::ConstVectorAttr, + cir::ConstComplexAttr, cir::ConstRecordAttr, + cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr, + cir::VTableAttr>(attrType)) return success(); assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?"); diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp index 2ecef988ca58e..2981ec9af54e2 100644 --- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp +++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp @@ -128,6 +128,14 @@ void GotoSolverPass::runOnOperation() { globalBlockAddrLabels[info.getFunc().getValue()].insert( info.getLabel()); }); + // A block-address difference attribute references two labels in the same + // function; keep both alive. + namedAttr.getValue().walk([&](cir::BlockAddrDiffAttr diff) { + llvm::StringSet<> &labels = + globalBlockAddrLabels[diff.getFunc().getValue()]; + labels.insert(diff.getLhsLabel().getValue()); + labels.insert(diff.getRhsLabel().getValue()); + }); } }); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 56f2b4f5ffb7c..7e0580dc73b3b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -695,6 +695,58 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) { return blockAddressOp; } +/// BlockAddrDiffAttr visitor. +mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) { + assert(blockInfoAddr && + "block address lowering requires LLVMBlockAddressInfo"); + // A block-address difference initializer is lowered to the difference of the + // two block addresses: trunc(ptrtoint(lhs) - ptrtoint(rhs)). Just like a + // single block address, each referenced block tag may not have been emitted + // yet, in which case it is recorded as unresolved and patched up later in + // resolveBlockAddressOp. + mlir::Location loc = parentOp->getLoc(); + mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>()); + mlir::MLIRContext *ctx = rewriter.getContext(); + auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx); + + auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value { + auto info = cir::BlockAddrInfoAttr::get( + ctx, blockAddrDiff.getFunc().getValue(), label.getValue()); + mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info); + mlir::LLVM::BlockTagAttr tagAttr = + matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{}; + auto blkAddr = mlir::LLVM::BlockAddressAttr::get( + ctx, blockAddrDiff.getFunc(), tagAttr); + auto addrOp = + mlir::LLVM::BlockAddressOp::create(rewriter, loc, ptrTy, blkAddr); + if (!matchLabel) + blockInfoAddr->addUnresolvedBlockAddress(addrOp, info); + return addrOp; + }; + + mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel()); + mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel()); + + // Compute the difference in a pointer-sized integer, then truncate to the + // initializer's type. LLVM is sensitive about the exact format of the + // address-of-label difference, so the truncation must happen after the + // subtraction. + mlir::Type intptrTy = rewriter.getIntegerType( + layout.getTypeSizeInBits(ptrTy)); + mlir::Value lhsInt = + mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr); + mlir::Value rhsInt = + mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, rhsAddr); + mlir::Value diffVal = + mlir::LLVM::SubOp::create(rewriter, loc, lhsInt, rhsInt); + + mlir::Type resultTy = converter->convertType(blockAddrDiff.getType()); + mlir::Value result = diffVal; + if (resultTy != intptrTy) + result = mlir::LLVM::TruncOp::create(rewriter, loc, resultTy, diffVal); + return result; +} + // ConstArrayAttr visitor mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) { mlir::Type llvmTy = converter->convertType(attr.getType()); @@ -2840,10 +2892,11 @@ 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::BlockAddrInfoAttr, cir::ConstArrayAttr, cir::ConstRecordAttr, - cir::ConstVectorAttr, cir::ConstPtrAttr, cir::ConstComplexAttr, - cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr, - cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init))); + assert((isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, + cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr, + cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr, + cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr, + 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 @@ -2972,11 +3025,12 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( return mlir::success(); } return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter); - } else if (mlir::isa<cir::BlockAddrInfoAttr, cir::ConstVectorAttr, - cir::ConstRecordAttr, cir::ConstPtrAttr, - cir::ConstComplexAttr, cir::GlobalViewAttr, - cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr, - cir::VTableAttr, cir::ZeroAttr>(init.value())) { + } else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, + cir::ConstVectorAttr, cir::ConstRecordAttr, + cir::ConstPtrAttr, cir::ConstComplexAttr, + cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr, + cir::PoisonAttr, 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/lib/CIR/Lowering/LoweringHelpers.cpp b/clang/lib/CIR/Lowering/LoweringHelpers.cpp index 59677a1aacefd..cc5b89e9aa60e 100644 --- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp +++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp @@ -216,13 +216,32 @@ static bool containsPoison(mlir::Attribute attr) { return false; } +/// Block-address attributes (address-of-label and label differences) are +/// lowered to relocation expressions that cannot be materialized as part of a +/// dense/aggregate constant attribute; they require the per-element +/// insertvalue region lowering. Return true if \p attr contains any such +/// element. +static bool containsBlockAddress(mlir::Attribute attr) { + if (mlir::isa<cir::BlockAddrInfoAttr, cir::BlockAddrDiffAttr>(attr)) + return true; + if (auto elts = mlir::dyn_cast<mlir::ArrayAttr>(attr)) + return llvm::any_of(elts, containsBlockAddress); + if (auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) { + if (mlir::isa<mlir::StringAttr>(constArr.getElts())) + return false; + if (auto elts = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts())) + return llvm::any_of(elts, containsBlockAddress); + } + return false; +} + static std::optional<mlir::Attribute> lowerConstRecordMemberAttr( - mlir::Attribute attr, mlir::SymbolTableCollection &symbolTables, - const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp); + mlir::Attribute attr, mlir::SymbolTableCollection &symbolTables, + const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp); std::optional<mlir::Attribute> lowerConstArrayAttr( - cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, - const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp) { + cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, + const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp) { // Ensure ConstArrayAttr has a type. const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr); @@ -240,6 +259,11 @@ std::optional<mlir::Attribute> lowerConstArrayAttr( if (containsPoison(constArr)) return std::nullopt; + // Block-address initializers cannot be represented as a dense/aggregate + // constant attribute; fall back to the per-element insertvalue lowering. + if (containsBlockAddress(constArr)) + return std::nullopt; + if (mlir::isa<mlir::StringAttr>(constArr.getElts())) return convertStringAttrToDenseElementsAttr(constArr, converter->convertType(type)); diff --git a/clang/test/CIR/CodeGen/const-label-addr.c b/clang/test/CIR/CodeGen/const-label-addr.c index d820db4221b66..115183fc771a4 100644 --- a/clang/test/CIR/CodeGen/const-label-addr.c +++ b/clang/test/CIR/CodeGen/const-label-addr.c @@ -5,13 +5,19 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// CIR: cir.global "private" internal dso_local @f.s = #cir.const_record<{#cir.block_addr_diff<@f, "A", "B"> : !s32i, #cir.block_addr_diff<@f, "B", "A"> : !s32i}> : !rec_S2 +// CIR: cir.global "private" internal dso_local @e.arr = #cir.const_array<[#cir.block_addr_diff<@e, "l2", "l1"> : !s32i, #cir.block_addr_diff<@e, "l3", "l2"> : !s32i]> : !cir.array<!s32i x 2> // CIR: cir.global "private" internal dso_local @d.s = #cir.const_record<{#cir.block_addr_info<@d, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@d, "B"> : !cir.ptr<!void>}> : !rec_S // CIR: cir.global "private" internal dso_local @c.tbl = #cir.const_array<[#cir.block_addr_info<@c, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@c, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@c, "B"> : !cir.ptr<!void>]> : !cir.array<!cir.ptr<!void> x 3> +// CIR: cir.global "private" internal dso_local @b.ar = #cir.block_addr_diff<@b, "l2", "l1"> : !s32i // CIR: cir.global "private" internal dso_local @a.a = #cir.block_addr_info<@a, "A"> : !cir.ptr<!void> +// LLVM-DAG: @e.arr = internal global [2 x i32] [i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@e, %[[E_L2:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@e, %[[E_L1:.*]]) to i{{..}})) to i32), i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@e, %[[E_L3:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@e, %[[E_L2]]) to i{{..}})) to i32)], align 4 // LLVM-DAG: @a.a = internal global ptr blockaddress(@a, %[[A_BLOCK:.*]]), align 8 +// LLVM-DAG: @b.ar = internal global {{.*}} sub (i{{..}} ptrtoint (ptr blockaddress(@b, %[[LABEL_L2:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@b, %[[LABEL_L1:.*]]) to i{{..}})) // LLVM-DAG: @c.tbl = internal global [3 x ptr] [ptr blockaddress(@c, %[[C_A:.*]]), ptr blockaddress(@c, %[[C_A]]), ptr blockaddress(@c, %[[C_B:.*]])], align 16 // LLVM-DAG: @d.s = internal global %struct.S { ptr blockaddress(@d, %[[D_A:.*]]), ptr blockaddress(@d, %[[D_B:.*]]) }, align 8 +// LLVM-DAG: @f.s = internal global %struct.S2 { i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_A:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_B:.*]]) to i{{..}})) to i32), i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_B]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_A]]) to i{{..}})) to i32) }, align 4 void a(void) { A:; @@ -30,6 +36,27 @@ A:; // LLVM: [[A_BLOCK]]: // LLVM: ret void +// PR14005 +int b(void) { + static int ar = &&l2 - &&l1; +l1: + return 10; +l2: + return 11; +} + +// CIR: cir.func{{.*}} @b +// CIR: %[[B_AR:.*]] = cir.get_global @b.ar +// CIR: [[LABEL_L1:.*]]: +// CIR: cir.label "l1" +// CIR: [[LABEL_L2:.*]]: +// CIR: cir.label "l2" + +// LLVM: define dso_local i32 @b() +// LLVM: br label %[[LABEL_L1]] +// LLVM: [[LABEL_L1]]: +// LLVM: [[LABEL_L2]]: + void c(int x) { static void *tbl[3] = {&&A, &&A, &&B}; int idx = x > 2 ? 2 : x; @@ -76,3 +103,50 @@ B:; // LLVM: br label %[[D_B]] // LLVM: [[D_B]]: // LLVM: ret void + +int e(void) { + static int arr[2] = {&&l2 - &&l1, &&l3 - &&l2}; +l1: + return 10; +l2: + return 11; +l3: + return 11; +} + +// CIR: cir.func{{.*}} @e +// CIR: %[[E_ARR:.*]] = cir.get_global @e.arr +// CIR: [[E_L1:.*]]: +// CIR: cir.label "l1" +// CIR: [[E_L2:.*]]: +// CIR: cir.label "l2" +// CIR: [[E_L3:.*]]: +// CIR: cir.label "l3" + +// LLVM: define dso_local i32 @e() +// LLVM: br label %[[E_L1]] +// LLVM: [[E_L1]]: +// LLVM: [[E_L2]]: +// LLVM: [[E_L3]]: + +struct S2 { int a, b; }; +void f(void) { +A:; +B:; + static struct S2 s = {&&A - &&B, &&B - &&A}; +} + +// CIR: cir.func{{.*}} @f +// CIR: [[F_A:.*]]: +// CIR: cir.label "A" +// CIR: [[F_B:.*]]: +// CIR: cir.label "B" +// CIR: %[[S2:.*]] = cir.get_global @f.s +// CIR: cir.return + +// LLVM: define dso_local void @f() +// LLVM: br label %[[F_A]] +// LLVM: [[F_A]]: +// LLVM: br label %[[F_B]] +// LLVM: [[F_B]]: +// LLVM: ret void >From 0d0b81a023cd32278f242746e17c7dc4ba124e54 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Tue, 23 Jun 2026 15:36:38 -0700 Subject: [PATCH 2/5] Fix formatting --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 7e0580dc73b3b..e329d05ce1b01 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -698,7 +698,7 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) { /// BlockAddrDiffAttr visitor. mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) { assert(blockInfoAddr && - "block address lowering requires LLVMBlockAddressInfo"); + "block address lowering requires LLVMBlockAddressInfo"); // A block-address difference initializer is lowered to the difference of the // two block addresses: trunc(ptrtoint(lhs) - ptrtoint(rhs)). Just like a // single block address, each referenced block tag may not have been emitted @@ -731,8 +731,8 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) { // initializer's type. LLVM is sensitive about the exact format of the // address-of-label difference, so the truncation must happen after the // subtraction. - mlir::Type intptrTy = rewriter.getIntegerType( - layout.getTypeSizeInBits(ptrTy)); + mlir::Type intptrTy = + rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy)); mlir::Value lhsInt = mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr); mlir::Value rhsInt = @@ -2892,11 +2892,12 @@ 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::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, - cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr, - cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr, - cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr, - cir::VTableAttr, cir::ZeroAttr>(init))); + assert( + (isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, cir::ConstArrayAttr, + cir::ConstRecordAttr, cir::ConstVectorAttr, cir::ConstPtrAttr, + cir::ConstComplexAttr, cir::GlobalViewAttr, cir::TypeInfoAttr, + cir::UndefAttr, cir::PoisonAttr, 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 >From 1b625c9e57569631f14a9a43e80e3de7c1defeaf Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Wed, 12 Aug 2026 13:47:33 -0700 Subject: [PATCH 3/5] Update after rebasing --- clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp index 2981ec9af54e2..5f911f3de10a0 100644 --- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp +++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp @@ -131,7 +131,7 @@ void GotoSolverPass::runOnOperation() { // A block-address difference attribute references two labels in the same // function; keep both alive. namedAttr.getValue().walk([&](cir::BlockAddrDiffAttr diff) { - llvm::StringSet<> &labels = + llvm::SmallSetVector<StringRef, 4> &labels = globalBlockAddrLabels[diff.getFunc().getValue()]; labels.insert(diff.getLhsLabel().getValue()); labels.insert(diff.getRhsLabel().getValue()); >From 253b0f7ed8c3cd155139b2f9425d3046c5aae2c0 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Wed, 12 Aug 2026 13:47:56 -0700 Subject: [PATCH 4/5] Add long integer test case --- clang/test/CIR/CodeGen/const-label-addr.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/clang/test/CIR/CodeGen/const-label-addr.c b/clang/test/CIR/CodeGen/const-label-addr.c index 115183fc771a4..756569fe58020 100644 --- a/clang/test/CIR/CodeGen/const-label-addr.c +++ b/clang/test/CIR/CodeGen/const-label-addr.c @@ -5,6 +5,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// CIR: cir.global "private" internal dso_local @g.ar = #cir.block_addr_diff<@g, "l2", "l1"> : !s64i // CIR: cir.global "private" internal dso_local @f.s = #cir.const_record<{#cir.block_addr_diff<@f, "A", "B"> : !s32i, #cir.block_addr_diff<@f, "B", "A"> : !s32i}> : !rec_S2 // CIR: cir.global "private" internal dso_local @e.arr = #cir.const_array<[#cir.block_addr_diff<@e, "l2", "l1"> : !s32i, #cir.block_addr_diff<@e, "l3", "l2"> : !s32i]> : !cir.array<!s32i x 2> // CIR: cir.global "private" internal dso_local @d.s = #cir.const_record<{#cir.block_addr_info<@d, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@d, "B"> : !cir.ptr<!void>}> : !rec_S @@ -18,6 +19,7 @@ // LLVM-DAG: @c.tbl = internal global [3 x ptr] [ptr blockaddress(@c, %[[C_A:.*]]), ptr blockaddress(@c, %[[C_A]]), ptr blockaddress(@c, %[[C_B:.*]])], align 16 // LLVM-DAG: @d.s = internal global %struct.S { ptr blockaddress(@d, %[[D_A:.*]]), ptr blockaddress(@d, %[[D_B:.*]]) }, align 8 // LLVM-DAG: @f.s = internal global %struct.S2 { i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_A:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_B:.*]]) to i{{..}})) to i32), i32 trunc (i{{..}} sub (i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_B]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@f, %[[F_A]]) to i{{..}})) to i32) }, align 4 +// LLVM-DAG: @g.ar = internal global {{.*}} sub (i{{..}} ptrtoint (ptr blockaddress(@g, %[[LABEL_GL2:.*]]) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@g, %[[LABEL_GL1:.*]]) to i{{..}})) void a(void) { A:; @@ -150,3 +152,23 @@ B:; // LLVM: br label %[[F_B]] // LLVM: [[F_B]]: // LLVM: ret void + +int g(void) { + static long ar = &&l2 - &&l1; +l1: + return 10; +l2: + return 11; +} + +// CIR: cir.func{{.*}} @g +// CIR: %[[G_AR:.*]] = cir.get_global @g.ar +// CIR: [[LABEL_GL1:.*]]: +// CIR: cir.label "l1" +// CIR: [[LABEL_GL2:.*]]: +// CIR: cir.label "l2" + +// LLVM: define dso_local i32 @g() +// LLVM: br label %[[LABEL_GL1]] +// LLVM: [[LABEL_GL1]]: +// LLVM: [[LABEL_GL2]]: >From 824f5413c457c0e580435fa4f02bbeb7e0e75283 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Wed, 12 Aug 2026 13:48:38 -0700 Subject: [PATCH 5/5] Fix formatting --- clang/lib/CIR/Lowering/LoweringHelpers.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp b/clang/lib/CIR/Lowering/LoweringHelpers.cpp index cc5b89e9aa60e..3b927ad759c7a 100644 --- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp +++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp @@ -236,12 +236,12 @@ static bool containsBlockAddress(mlir::Attribute attr) { } static std::optional<mlir::Attribute> lowerConstRecordMemberAttr( - mlir::Attribute attr, mlir::SymbolTableCollection &symbolTables, - const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp); + mlir::Attribute attr, mlir::SymbolTableCollection &symbolTables, + const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp); std::optional<mlir::Attribute> lowerConstArrayAttr( - cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, - const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp) { + cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, + const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp) { // Ensure ConstArrayAttr has a type. const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
