https://github.com/Andres-Salamanca updated https://github.com/llvm/llvm-project/pull/168151
>From f370cf6048c10df86159d5272a2d3dc463247110 Mon Sep 17 00:00:00 2001 From: Andres Salamanca <[email protected]> Date: Fri, 14 Nov 2025 18:30:22 -0500 Subject: [PATCH 1/2] [CIR] Upstream the initial BlockAddressOp implementation --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 25 ++++++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 33 ++++++++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 9 +++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 29 ++++++- .../lib/CIR/Dialect/Transforms/GotoSolver.cpp | 17 ++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 ++ clang/test/CIR/CodeGen/label-values.c | 76 +++++++++++++++++++ clang/test/CIR/IR/block-adress.cir | 34 +++++++++ clang/test/CIR/IR/invalid-block-address.cir | 21 +++++ clang/test/CIR/Transforms/goto_solver.cir | 62 +++++++++++++++ clang/tools/cir-opt/cir-opt.cpp | 4 + 11 files changed, 311 insertions(+), 5 deletions(-) create mode 100644 clang/test/CIR/CodeGen/label-values.c create mode 100644 clang/test/CIR/IR/block-adress.cir create mode 100644 clang/test/CIR/IR/invalid-block-address.cir create mode 100644 clang/test/CIR/Transforms/goto_solver.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 1e0fb038b19d8..47ff9389e8028 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -1026,4 +1026,29 @@ def CIR_UnwindAttr : CIR_UnitAttr<"Unwind", "unwind"> { let storageType = [{ CatchUnwind }]; } +//===----------------------------------------------------------------------===// +// CIR_BlockAddrInfoAttr +//===----------------------------------------------------------------------===// + +def CIR_BlockAddrInfoAttr : CIR_Attr<"BlockAddrInfo", "block_addr_info"> { + let summary = "Block Addres attribute"; + let description = [{ + This attribute is used to represent the address of a basic block + within a function. It combines the symbol reference to a function + with the name of a label inside that function. + }]; + let parameters = (ins "mlir::FlatSymbolRefAttr":$func, + "mlir::StringAttr":$label); + + let assemblyFormat = "`<` $func `,` $label `>`"; + let builders = [ + AttrBuilder<(ins "llvm::StringRef":$func_name, + "llvm::StringRef":$label_name + ), [{ + return $_get($_ctxt, mlir::FlatSymbolRefAttr::get($_ctxt, func_name), + mlir::StringAttr::get($_ctxt, label_name)); + }]> + ]; +} + #endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 16258513239d9..d7270bc81b68a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4800,4 +4800,37 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> { }]; } +//===----------------------------------------------------------------------===// +// BlockAddressOp +//===----------------------------------------------------------------------===// + +def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> { + let summary = "Get the address of a cir.label within a function"; + let description = [{ + The `cir.blockaddress` operation takes a function name and a label and + produces a pointer value that represents the address of that cir.label within + the specified function. + + This operation models GCC's "labels as values" extension (`&&label`), which + allows taking the address of a local label and using it as a computed + jump target (e.g., with `goto *addr;`). + + Example: + ```mlir + %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} + %addr = cir.blockaddress("foo", "label") -> !cir.ptr<!cir.void> + cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> + cir.br ^bb1 + ^bb1: + cir.label "label" + ``` + }]; + + let arguments = (ins CIR_BlockAddrInfoAttr:$blockAddrInfo); + let results = (outs CIR_VoidPtrType:$addr); + let assemblyFormat = [{ + $blockAddrInfo `->` qualified(type($addr)) attr-dict + }]; +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 4461875fcf678..e3e8f2827d841 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -166,6 +166,15 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { return emitLoadOfLValue(e); } + mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) { + auto func = cast<cir::FuncOp>(cgf.curFn); + auto blockInfoAttr = cir::BlockAddrInfoAttr::get( + &cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName()); + return cir::BlockAddressOp::create(builder, cgf.getLoc(e->getSourceRange()), + cgf.convertType(e->getType()), + blockInfoAttr); + } + mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) { mlir::Type type = cgf.convertType(e->getType()); return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()), diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 7ba03ce40140c..95dfcc7ce1c13 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1902,22 +1902,45 @@ mlir::LogicalResult cir::FuncOp::verify() { llvm::SmallSet<llvm::StringRef, 16> labels; llvm::SmallSet<llvm::StringRef, 16> gotos; - + llvm::SmallSet<llvm::StringRef, 16> blockAddresses; + bool invalidBlockAddress = false; getOperation()->walk([&](mlir::Operation *op) { if (auto lab = dyn_cast<cir::LabelOp>(op)) { labels.insert(lab.getLabel()); } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) { gotos.insert(goTo.getLabel()); + } else if (auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) { + if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) { + // Stop the walk early, no need to continue + invalidBlockAddress = true; + return mlir::WalkResult::interrupt(); + } + blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel()); } + return mlir::WalkResult::advance(); }); + if (invalidBlockAddress) + return emitOpError() << "blockaddress references a different function"; + + llvm::SmallSet<llvm::StringRef, 16> mismatched; if (!labels.empty() || !gotos.empty()) { - llvm::SmallSet<llvm::StringRef, 16> mismatched = - llvm::set_difference(gotos, labels); + mismatched = llvm::set_difference(gotos, labels); if (!mismatched.empty()) return emitOpError() << "goto/label mismatch"; } + + mismatched.clear(); + + if (!labels.empty() || !blockAddresses.empty()) { + mismatched = llvm::set_difference(blockAddresses, labels); + + if (!mismatched.empty()) + return emitOpError() + << "expects an existing label target in the referenced function"; + } + return success(); } diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp index 00972b6976295..d590ccce1f540 100644 --- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp +++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp @@ -8,6 +8,7 @@ #include "PassDetail.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/Passes.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/TimeProfiler.h" #include <memory> @@ -30,17 +31,29 @@ static void process(cir::FuncOp func) { mlir::OpBuilder rewriter(func.getContext()); llvm::StringMap<Block *> labels; llvm::SmallVector<cir::GotoOp, 4> gotos; + llvm::SmallSet<StringRef, 4> blockAddrLabel; func.getBody().walk([&](mlir::Operation *op) { if (auto lab = dyn_cast<cir::LabelOp>(op)) { - // Will construct a string copy inplace. Safely erase the label labels.try_emplace(lab.getLabel(), lab->getBlock()); - lab.erase(); } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) { gotos.push_back(goTo); + } else if (auto blockAddr = dyn_cast<cir::BlockAddressOp>(op)) { + blockAddrLabel.insert(blockAddr.getBlockAddrInfo().getLabel()); } }); + for (auto &lab : labels) { + StringRef labelName = lab.getKey(); + Block *block = lab.getValue(); + if (!blockAddrLabel.contains(labelName)) { + // erase the LabelOp inside the block if safe + if (auto lab = dyn_cast<cir::LabelOp>(&block->front())) { + lab.erase(); + } + } + } + for (auto goTo : gotos) { mlir::OpBuilder::InsertionGuard guard(rewriter); rewriter.setInsertionPoint(goTo); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b4afed7019417..13835949789ce 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3778,6 +3778,12 @@ mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite( + cir::BlockAddressOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + return mlir::failure(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/test/CIR/CodeGen/label-values.c b/clang/test/CIR/CodeGen/label-values.c new file mode 100644 index 0000000000000..20042ce1e6e8b --- /dev/null +++ b/clang/test/CIR/CodeGen/label-values.c @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR + +void A(void) { + void *ptr = &&A; +A: + return; +} +// CIR: cir.func dso_local @A +// CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} +// CIR: [[BLOCK:%.*]] = cir.blockaddress <@A, "A"> -> !cir.ptr<!void> +// CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: cir.br ^bb1 +// CIR: ^bb1: // pred: ^bb0 +// CIR: cir.label "A" +// CIR: cir.return + +void B(void) { +B: + void *ptr = &&B; +} + +// CIR: cir.func dso_local @B() +// CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} +// CIR: cir.br ^bb1 +// CIR: ^bb1: +// CIR: cir.label "B" +// CIR: [[BLOCK:%.*]] = cir.blockaddress <@B, "B"> -> !cir.ptr<!void> +// CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: cir.return + +void C(int x) { + void *ptr = (x == 0) ? &&A : &&B; +A: + return; +B: + return; +} + +// CIR: cir.func dso_local @C +// CIR: [[BLOCK1:%.*]] = cir.blockaddress <@C, "A"> -> !cir.ptr<!void> +// CIR: [[BLOCK2:%.*]] = cir.blockaddress <@C, "B"> -> !cir.ptr<!void> +// CIR: [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else [[BLOCK2]] : (!cir.bool, !cir.ptr<!void>, !cir.ptr<!void>) -> !cir.ptr<!void> +// CIR: cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: cir.br ^bb1 +// CIR: ^bb1: // pred: ^bb0 +// CIR: cir.label "A" +// CIR: cir.br ^bb2 +// CIR: ^bb2: // 2 preds: ^bb1, ^bb3 +// CIR: cir.return +// CIR: ^bb3: // no predecessors +// CIR: cir.label "B" +// CIR: cir.br ^bb2 + +void D(void) { + void *ptr = &&A; + void *ptr2 = &&A; +A: + void *ptr3 = &&A; + return; +} + +// CIR: cir.func dso_local @D +// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] +// CIR: %[[PTR2:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr2", init] +// CIR: %[[PTR3:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr3", init] +// CIR: %[[BLK1:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: %[[BLK2:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: cir.br ^bb1 +// CIR: ^bb1: // pred: ^bb0 +// CIR: cir.label "A" +// CIR: %[[BLK3:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CIR: cir.return diff --git a/clang/test/CIR/IR/block-adress.cir b/clang/test/CIR/IR/block-adress.cir new file mode 100644 index 0000000000000..ae9662461d08f --- /dev/null +++ b/clang/test/CIR/IR/block-adress.cir @@ -0,0 +1,34 @@ +// RUN: cir-opt %s | cir-opt | FileCheck %s + +!void = !cir.void + +module { + cir.func @block_address(){ + %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void> + cir.br ^bb1 + ^bb1: + cir.label "label" + cir.return + } +// CHECK: cir.func @block_address +// CHECK: %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void> +// CHECK: cir.br ^bb1 +// CHECK: ^bb1: +// CHECK: cir.label "label" +// CHECK: cir.return + +cir.func @block_address_inside_scope() -> () { + cir.scope{ + %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr<!void> + } + cir.br ^bb1 +^bb1: + cir.label "label" + cir.return +} +// CHECK: cir.func @block_address_inside_scope +// CHECK: cir.scope +// CHECK: %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr<!void> +// CHECK: cir.label "label" +// CHECK: cir.return +} diff --git a/clang/test/CIR/IR/invalid-block-address.cir b/clang/test/CIR/IR/invalid-block-address.cir new file mode 100644 index 0000000000000..c3545406bfcff --- /dev/null +++ b/clang/test/CIR/IR/invalid-block-address.cir @@ -0,0 +1,21 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!void = !cir.void + +// expected-error@+1 {{expects an existing label target in the referenced function}} +cir.func @bad_block_address() -> () { + %0 = cir.blockaddress <@bad_block_address, "label"> -> !cir.ptr<!void> + cir.br ^bb1 + ^bb1: + cir.label "wrong_label" + cir.return +} + +// expected-error@+1 {{blockaddress references a different function}} +cir.func @bad_block_func() -> () { + %0 = cir.blockaddress <@mismatch_func, "label"> -> !cir.ptr<!void> + cir.br ^bb1 + ^bb1: + cir.label "label" + cir.return +} diff --git a/clang/test/CIR/Transforms/goto_solver.cir b/clang/test/CIR/Transforms/goto_solver.cir new file mode 100644 index 0000000000000..13ec4b8d79006 --- /dev/null +++ b/clang/test/CIR/Transforms/goto_solver.cir @@ -0,0 +1,62 @@ +// RUN: cir-opt %s -cir-goto-solver -o - | FileCheck %s + +!void = !cir.void + +cir.func @a(){ + %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} + %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void> + cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> + cir.br ^bb1 +^bb1: + cir.label "label1" + cir.br ^bb2 +^bb2: + // This label is not referenced by any blockaddressOp, so it should be removed + cir.label "label2" + cir.return +} + +// CHECK: cir.func @a() +// CHECK: %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void> +// CHECK: ^bb1: +// CHECK: cir.label "label1" +// CHECK: cir.br ^bb2 +// CHECK: ^bb2: +// CHECK-NOT: cir.label "label2" + +cir.func @b(){ + %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} + %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void> + cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> + cir.goto "label2" +^bb1: + cir.label "label1" + cir.br ^bb2 +^bb2: + // This label is not referenced by any blockaddressOp, so it should be removed + cir.label "label2" + cir.return +} + +// CHECK: cir.func @b() { +// CHECK: %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void> +// CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> +// CHECK: cir.br ^bb2 +// CHECK: ^bb1: +// CHECK: cir.label "label1" +// CHECK: cir.br ^bb2 +// CHECK: ^bb2: +// CHECK-NOT: cir.label "label2" + +cir.func @c() { + cir.label "label1" + %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} + %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void> + cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> + cir.return +} + +// CHECK: cir.func @c +// CHECK: cir.label "label1" +// CHECK: %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void> +// CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp index c4d29a2117c75..ee42015bb38e9 100644 --- a/clang/tools/cir-opt/cir-opt.cpp +++ b/clang/tools/cir-opt/cir-opt.cpp @@ -58,6 +58,10 @@ int main(int argc, char **argv) { return mlir::createHoistAllocasPass(); }); + ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { + return mlir::createGotoSolverPass(); + }); + mlir::registerTransformsPasses(); return mlir::asMainReturnCode(MlirOptMain( >From 1ba292553639ff83f3bc2c2a816987ebf4876c2c Mon Sep 17 00:00:00 2001 From: Andres Salamanca <[email protected]> Date: Sat, 15 Nov 2025 17:59:15 -0500 Subject: [PATCH 2/2] Apply review --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 15 ++++--- clang/test/CIR/CodeGen/label-values.c | 46 ++++++++++---------- clang/test/CIR/IR/block-adress.cir | 10 ++--- clang/test/CIR/IR/invalid-block-address.cir | 6 +-- clang/test/CIR/Transforms/goto_solver.cir | 14 +++--- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index d7270bc81b68a..10c801c4762ea 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4804,12 +4804,12 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> { // BlockAddressOp //===----------------------------------------------------------------------===// -def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> { +def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> { let summary = "Get the address of a cir.label within a function"; let description = [{ The `cir.blockaddress` operation takes a function name and a label and - produces a pointer value that represents the address of that cir.label within - the specified function. + produces a pointer value that represents the address of that cir.label + within the specified function. This operation models GCC's "labels as values" extension (`&&label`), which allows taking the address of a local label and using it as a computed @@ -4817,8 +4817,9 @@ def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> { Example: ```mlir - %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} - %addr = cir.blockaddress("foo", "label") -> !cir.ptr<!cir.void> + %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] + {alignment = 8 : i64} + %addr = cir.block_address <@c, "label1"> : !cir.ptr<!cir.void> cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> cir.br ^bb1 ^bb1: @@ -4826,10 +4827,10 @@ def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> { ``` }]; - let arguments = (ins CIR_BlockAddrInfoAttr:$blockAddrInfo); + let arguments = (ins CIR_BlockAddrInfoAttr:$block_addr_info); let results = (outs CIR_VoidPtrType:$addr); let assemblyFormat = [{ - $blockAddrInfo `->` qualified(type($addr)) attr-dict + $block_addr_info `:` qualified(type($addr)) attr-dict }]; } diff --git a/clang/test/CIR/CodeGen/label-values.c b/clang/test/CIR/CodeGen/label-values.c index 20042ce1e6e8b..41178e3f62f20 100644 --- a/clang/test/CIR/CodeGen/label-values.c +++ b/clang/test/CIR/CodeGen/label-values.c @@ -2,61 +2,61 @@ // RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR void A(void) { - void *ptr = &&A; -A: + void *ptr = &&LABEL_A; +LABEL_A: return; } // CIR: cir.func dso_local @A // CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} -// CIR: [[BLOCK:%.*]] = cir.blockaddress <@A, "A"> -> !cir.ptr<!void> +// CIR: [[BLOCK:%.*]] = cir.block_address <@A, "LABEL_A"> : !cir.ptr<!void> // CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CIR: cir.br ^bb1 // CIR: ^bb1: // pred: ^bb0 -// CIR: cir.label "A" +// CIR: cir.label "LABEL_A" // CIR: cir.return void B(void) { -B: - void *ptr = &&B; +LABEL_B: + void *ptr = &&LABEL_B; } // CIR: cir.func dso_local @B() // CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} // CIR: cir.br ^bb1 // CIR: ^bb1: -// CIR: cir.label "B" -// CIR: [[BLOCK:%.*]] = cir.blockaddress <@B, "B"> -> !cir.ptr<!void> +// CIR: cir.label "LABEL_B" +// CIR: [[BLOCK:%.*]] = cir.block_address <@B, "LABEL_B"> : !cir.ptr<!void> // CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CIR: cir.return void C(int x) { - void *ptr = (x == 0) ? &&A : &&B; -A: + void *ptr = (x == 0) ? &&LABEL_A : &&LABEL_B; +LABEL_A: return; -B: +LABEL_B: return; } // CIR: cir.func dso_local @C -// CIR: [[BLOCK1:%.*]] = cir.blockaddress <@C, "A"> -> !cir.ptr<!void> -// CIR: [[BLOCK2:%.*]] = cir.blockaddress <@C, "B"> -> !cir.ptr<!void> +// CIR: [[BLOCK1:%.*]] = cir.block_address <@C, "LABEL_A"> : !cir.ptr<!void> +// CIR: [[BLOCK2:%.*]] = cir.block_address <@C, "LABEL_B"> : !cir.ptr<!void> // CIR: [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else [[BLOCK2]] : (!cir.bool, !cir.ptr<!void>, !cir.ptr<!void>) -> !cir.ptr<!void> // CIR: cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CIR: cir.br ^bb1 // CIR: ^bb1: // pred: ^bb0 -// CIR: cir.label "A" +// CIR: cir.label "LABEL_A" // CIR: cir.br ^bb2 // CIR: ^bb2: // 2 preds: ^bb1, ^bb3 // CIR: cir.return // CIR: ^bb3: // no predecessors -// CIR: cir.label "B" +// CIR: cir.label "LABEL_B" // CIR: cir.br ^bb2 void D(void) { - void *ptr = &&A; - void *ptr2 = &&A; -A: - void *ptr3 = &&A; + void *ptr = &&LABEL_A; + void *ptr2 = &&LABEL_A; +LABEL_A: + void *ptr3 = &&LABEL_A; return; } @@ -64,13 +64,13 @@ void D(void) { // CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] // CIR: %[[PTR2:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr2", init] // CIR: %[[PTR3:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr3", init] -// CIR: %[[BLK1:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: %[[BLK1:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void> // CIR: cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> -// CIR: %[[BLK2:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: %[[BLK2:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void> // CIR: cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CIR: cir.br ^bb1 // CIR: ^bb1: // pred: ^bb0 -// CIR: cir.label "A" -// CIR: %[[BLK3:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void> +// CIR: cir.label "LABEL_A" +// CIR: %[[BLK3:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void> // CIR: cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CIR: cir.return diff --git a/clang/test/CIR/IR/block-adress.cir b/clang/test/CIR/IR/block-adress.cir index ae9662461d08f..9d6840819c2d4 100644 --- a/clang/test/CIR/IR/block-adress.cir +++ b/clang/test/CIR/IR/block-adress.cir @@ -1,17 +1,17 @@ -// RUN: cir-opt %s | cir-opt | FileCheck %s +// RUN: cir-opt %s --verify-roundtrip | FileCheck %s !void = !cir.void module { cir.func @block_address(){ - %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void> + %0 = cir.block_address <@block_address, "label"> : !cir.ptr<!void> cir.br ^bb1 ^bb1: cir.label "label" cir.return } // CHECK: cir.func @block_address -// CHECK: %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void> +// CHECK: %0 = cir.block_address <@block_address, "label"> : !cir.ptr<!void> // CHECK: cir.br ^bb1 // CHECK: ^bb1: // CHECK: cir.label "label" @@ -19,7 +19,7 @@ module { cir.func @block_address_inside_scope() -> () { cir.scope{ - %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr<!void> + %0 = cir.block_address <@block_address_inside_scope, "label"> : !cir.ptr<!void> } cir.br ^bb1 ^bb1: @@ -28,7 +28,7 @@ cir.func @block_address_inside_scope() -> () { } // CHECK: cir.func @block_address_inside_scope // CHECK: cir.scope -// CHECK: %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr<!void> +// CHECK: %0 = cir.block_address <@block_address_inside_scope, "label"> : !cir.ptr<!void> // CHECK: cir.label "label" // CHECK: cir.return } diff --git a/clang/test/CIR/IR/invalid-block-address.cir b/clang/test/CIR/IR/invalid-block-address.cir index c3545406bfcff..fc9b4a902e2f4 100644 --- a/clang/test/CIR/IR/invalid-block-address.cir +++ b/clang/test/CIR/IR/invalid-block-address.cir @@ -1,10 +1,10 @@ -// RUN: cir-opt %s -verify-diagnostics -split-input-file +// RUN: cir-opt %s -verify-diagnostics -split-input-file --verify-roundtrip !void = !cir.void // expected-error@+1 {{expects an existing label target in the referenced function}} cir.func @bad_block_address() -> () { - %0 = cir.blockaddress <@bad_block_address, "label"> -> !cir.ptr<!void> + %0 = cir.block_address <@bad_block_address, "label"> : !cir.ptr<!void> cir.br ^bb1 ^bb1: cir.label "wrong_label" @@ -13,7 +13,7 @@ cir.func @bad_block_address() -> () { // expected-error@+1 {{blockaddress references a different function}} cir.func @bad_block_func() -> () { - %0 = cir.blockaddress <@mismatch_func, "label"> -> !cir.ptr<!void> + %0 = cir.block_address <@mismatch_func, "label"> : !cir.ptr<!void> cir.br ^bb1 ^bb1: cir.label "label" diff --git a/clang/test/CIR/Transforms/goto_solver.cir b/clang/test/CIR/Transforms/goto_solver.cir index 13ec4b8d79006..6ae019b44a39e 100644 --- a/clang/test/CIR/Transforms/goto_solver.cir +++ b/clang/test/CIR/Transforms/goto_solver.cir @@ -1,10 +1,10 @@ -// RUN: cir-opt %s -cir-goto-solver -o - | FileCheck %s +// RUN: cir-opt %s -cir-goto-solver --verify-roundtrip -o - | FileCheck %s !void = !cir.void cir.func @a(){ %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void> + %1 = cir.block_address <@a, "label1"> : !cir.ptr<!void> cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> cir.br ^bb1 ^bb1: @@ -17,7 +17,7 @@ cir.func @a(){ } // CHECK: cir.func @a() -// CHECK: %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void> +// CHECK: %1 = cir.block_address <@a, "label1"> : !cir.ptr<!void> // CHECK: ^bb1: // CHECK: cir.label "label1" // CHECK: cir.br ^bb2 @@ -26,7 +26,7 @@ cir.func @a(){ cir.func @b(){ %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void> + %1 = cir.block_address <@b, "label1"> : !cir.ptr<!void> cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> cir.goto "label2" ^bb1: @@ -39,7 +39,7 @@ cir.func @b(){ } // CHECK: cir.func @b() { -// CHECK: %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void> +// CHECK: %1 = cir.block_address <@b, "label1"> : !cir.ptr<!void> // CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> // CHECK: cir.br ^bb2 // CHECK: ^bb1: @@ -51,12 +51,12 @@ cir.func @b(){ cir.func @c() { cir.label "label1" %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void> + %1 = cir.block_address <@c, "label1"> : !cir.ptr<!void> cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> cir.return } // CHECK: cir.func @c // CHECK: cir.label "label1" -// CHECK: %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void> +// CHECK: %1 = cir.block_address <@c, "label1"> : !cir.ptr<!void> // CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
