diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 5d171aaf5ddc..a05609405e9b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -1506,6 +1506,31 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", "address_point"> { }]; } +//===----------------------------------------------------------------------===// +// 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)); + }]> + ]; +} + include "clang/CIR/Dialect/IR/CIRTBAAAttrs.td" include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td" diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a70a9ce976a4..f3f24fff08c6 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6144,10 +6144,10 @@ def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> { ``` }]; - let arguments = (ins FlatSymbolRefAttr:$func, StrAttr:$label); + let arguments = (ins CIR_BlockAddrInfoAttr:$blockAddrInfo); let results = (outs CIR_VoidPtrType:$addr); let assemblyFormat = [{ - `(` $func `,` $label `)` `->` qualified(type($addr)) attr-dict + $blockAddrInfo `->` qualified(type($addr)) attr-dict }]; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index e39622cace79..faae8608b1a5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -229,15 +229,11 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) { auto func = cast(CGF.CurFn); - llvm::StringRef symName = func.getSymName(); - mlir::FlatSymbolRefAttr funName = - mlir::FlatSymbolRefAttr::get(&CGF.getMLIRContext(), symName); - mlir::StringAttr labelName = - mlir::StringAttr::get(&CGF.getMLIRContext(), e->getLabel()->getName()); + 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()), funName, - labelName); - ; + CGF.convertType(e->getType()), + blockInfoAttr); } mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *E) { llvm_unreachable("NYI"); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index ee1005bc8bb8..dcc6464aed74 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2939,12 +2939,12 @@ LogicalResult cir::FuncOp::verify() { } else if (auto goTo = dyn_cast(op)) { gotos.insert(goTo.getLabel()); } else if (auto blkAdd = dyn_cast(op)) { - if (blkAdd.getFunc() != getSymName()) { + if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) { // Stop the walk early, no need to continue invalidBlockAddress = true; return mlir::WalkResult::interrupt(); } - blockAddresses.insert(blkAdd.getLabel()); + blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel()); } return mlir::WalkResult::advance(); }); diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp index e2d07c4ff433..0389d8f5840e 100644 --- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp +++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp @@ -33,7 +33,7 @@ static void process(cir::FuncOp func) { } else if (auto goTo = dyn_cast(op)) { gotos.push_back(goTo); } else if (auto blockAddr = dyn_cast(op)) { - blockAddrLabel.insert(blockAddr.getLabel()); + blockAddrLabel.insert(blockAddr.getBlockAddrInfo().getLabel()); } }); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index fc7242d318c3..9c717cecefec 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4518,7 +4518,9 @@ mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite( auto blockTagOp = mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr); auto func = op->getParentOfType(); - blockInfoAddr.mapBlockTag(func.getSymName(), op.getLabel(), blockTagOp); + auto blockInfoAttr = + cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel()); + blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp); rewriter.eraseOp(op); return mlir::success(); @@ -4530,7 +4532,7 @@ mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite( mlir::MLIRContext *ctx = rewriter.getContext(); mlir::LLVM::BlockTagOp matchLabel = - blockInfoAddr.lookupBlockTag(op.getFunc(), op.getLabel()); + blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr()); mlir::LLVM::BlockTagAttr tagAttr; if (!matchLabel) // If the BlockTagOp has not been emitted yet, use a placeholder. @@ -4540,13 +4542,13 @@ mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite( else tagAttr = matchLabel.getTag(); - auto blkAddr = mlir::LLVM::BlockAddressAttr::get(rewriter.getContext(), - op.getFuncAttr(), tagAttr); + auto blkAddr = mlir::LLVM::BlockAddressAttr::get( + rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr); rewriter.setInsertionPoint(op); auto newOp = mlir::LLVM::BlockAddressOp::create( rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr); if (!matchLabel) - blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getFunc(), op.getLabel()); + blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr()); rewriter.replaceOp(op, newOp); return mlir::success(); } @@ -5058,10 +5060,9 @@ void ConvertCIRToLLVMPass::resolveBlockAddressOp( for (auto &[blockAddOp, blockInfo] : blockInfoAddr.getUnresolvedBlockAddress()) { mlir::LLVM::BlockTagOp resolvedLabel = - blockInfoAddr.lookupBlockTag(blockInfo.first, blockInfo.second); + blockInfoAddr.lookupBlockTag(blockInfo); assert(resolvedLabel && "expected BlockTagOp to already be emitted"); - auto fnSym = - mlir::FlatSymbolRefAttr::get(module.getContext(), blockInfo.first); + auto fnSym = blockInfo.getFunc(); auto blkAddTag = mlir::LLVM::BlockAddressAttr::get( opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr()); blockAddOp.setBlockAddrAttr(blkAddTag); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 21f3e3ae4157..f13c37106665 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -49,29 +49,26 @@ struct LLVMBlockAddressInfo { // Get the next tag index uint32_t getTagIndex() { return blockTagOpIndex++; } - void mapBlockTag(llvm::StringRef func, llvm::StringRef label, - mlir::LLVM::BlockTagOp tagOp) { - auto result = blockInfoToTagOp.try_emplace({func, label}, tagOp); + void mapBlockTag(cir::BlockAddrInfoAttr info, mlir::LLVM::BlockTagOp tagOp) { + auto result = blockInfoToTagOp.try_emplace(info, tagOp); assert(result.second && "attempting to map a BlockTag operation that is already mapped"); } // Lookup a BlockTagOp, may return nullptr if not yet registered. - mlir::LLVM::BlockTagOp lookupBlockTag(llvm::StringRef func, - llvm::StringRef label) const { - return blockInfoToTagOp.lookup({func, label}); + mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const { + return blockInfoToTagOp.lookup(info); } // Record an unresolved BlockAddressOp that needs patching later. void addUnresolvedBlockAddress(mlir::LLVM::BlockAddressOp op, - llvm::StringRef func, llvm::StringRef label) { - unresolvedBlockAddressOp.try_emplace(op, std::make_pair(func, label)); + cir::BlockAddrInfoAttr info) { + unresolvedBlockAddressOp.try_emplace(op, info); } void clearUnresolvedMap() { unresolvedBlockAddressOp.clear(); } - llvm::DenseMap> & + llvm::DenseMap & getUnresolvedBlockAddress() { return unresolvedBlockAddressOp; } @@ -79,15 +76,13 @@ struct LLVMBlockAddressInfo { private: // Maps a (function name, label name) pair to the corresponding BlockTagOp. // Used to resolve CIR LabelOps into their LLVM BlockTagOp. - llvm::DenseMap, - mlir::LLVM::BlockTagOp> + llvm::DenseMap blockInfoToTagOp; // Tracks BlockAddressOps that could not yet be fully resolved because // their BlockTagOp was not available at the time of lowering. The map // stores the unresolved BlockAddressOp along with its (function name, label // name) pair so it can be patched later. - llvm::DenseMap> + llvm::DenseMap unresolvedBlockAddressOp; int32_t blockTagOpIndex; }; diff --git a/clang/test/CIR/CodeGen/label-values.c b/clang/test/CIR/CodeGen/label-values.c index ee402f5b4957..97be5cda9224 100644 --- a/clang/test/CIR/CodeGen/label-values.c +++ b/clang/test/CIR/CodeGen/label-values.c @@ -12,7 +12,7 @@ void A(void) { } // CIR: cir.func dso_local @A // CIR: [[PTR:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["ptr", init] {alignment = 8 : i64} -// CIR: [[BLOCK:%.*]] = cir.blockaddress(@A, "A") -> !cir.ptr +// CIR: [[BLOCK:%.*]] = cir.blockaddress <@A, "A"> -> !cir.ptr // CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr, !cir.ptr> // CIR: cir.br ^bb1 // CIR: ^bb1: // pred: ^bb0 @@ -43,7 +43,7 @@ void B(void) { // CIR: cir.func dso_local @B() // CIR: cir.label "B" // CIR: [[PTR:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["ptr", init] {alignment = 8 : i64} -// CIR: [[BLOCK:%.*]] = cir.blockaddress(@B, "B") -> !cir.ptr +// CIR: [[BLOCK:%.*]] = cir.blockaddress <@B, "B"> -> !cir.ptr // CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr, !cir.ptr> // CIR: cir.return @@ -72,8 +72,8 @@ void C(int x) { } // CIR: cir.func dso_local @C -// CIR: [[BLOCK1:%.*]] = cir.blockaddress(@C, "A") -> !cir.ptr -// CIR: [[BLOCK2:%.*]] = cir.blockaddress(@C, "B") -> !cir.ptr +// CIR: [[BLOCK1:%.*]] = cir.blockaddress <@C, "A"> -> !cir.ptr +// CIR: [[BLOCK2:%.*]] = cir.blockaddress <@C, "B"> -> !cir.ptr // CIR: [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else [[BLOCK2]] : (!cir.bool, !cir.ptr, !cir.ptr) -> !cir.ptr // CIR: cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr, !cir.ptr> // CIR: cir.br ^bb2 @@ -122,14 +122,14 @@ void D(void) { // CIR: %[[PTR:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["ptr", init] // CIR: %[[PTR2:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["ptr2", init] // CIR: %[[PTR3:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["ptr3", init] -// CIR: %[[BLK1:.*]] = cir.blockaddress(@D, "A") -> !cir.ptr +// CIR: %[[BLK1:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr // CIR: cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr, !cir.ptr> -// CIR: %[[BLK2:.*]] = cir.blockaddress(@D, "A") -> !cir.ptr +// CIR: %[[BLK2:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr // CIR: cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr, !cir.ptr> // CIR: cir.br ^bb1 // CIR: ^bb1: // pred: ^bb0 // CIR: cir.label "A" -// CIR: %[[BLK3:.*]] = cir.blockaddress(@D, "A") -> !cir.ptr +// CIR: %[[BLK3:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr // CIR: cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr, !cir.ptr> // CIR: cir.return diff --git a/clang/test/CIR/IR/block-adress.cir b/clang/test/CIR/IR/block-adress.cir index 1b72bce3df41..ae9662461d08 100644 --- a/clang/test/CIR/IR/block-adress.cir +++ b/clang/test/CIR/IR/block-adress.cir @@ -4,14 +4,14 @@ module { cir.func @block_address(){ - %0 = cir.blockaddress(@block_address, "label") -> !cir.ptr + %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr cir.br ^bb1 ^bb1: cir.label "label" cir.return } // CHECK: cir.func @block_address -// CHECK: %0 = cir.blockaddress(@block_address, "label") -> !cir.ptr +// CHECK: %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr // 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 + %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr } 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 +// CHECK: %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> !cir.ptr // 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 26ffa1a14568..c3545406bfcf 100644 --- a/clang/test/CIR/IR/invalid-block-address.cir +++ b/clang/test/CIR/IR/invalid-block-address.cir @@ -4,7 +4,7 @@ // 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 + %0 = cir.blockaddress <@bad_block_address, "label"> -> !cir.ptr 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 + %0 = cir.blockaddress <@mismatch_func, "label"> -> !cir.ptr 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 177a8ce652e0..2adae1eb7459 100644 --- a/clang/test/CIR/Transforms/goto_solver.cir +++ b/clang/test/CIR/Transforms/goto_solver.cir @@ -4,7 +4,7 @@ cir.func @a(){ %0 = cir.alloca !cir.ptr, !cir.ptr>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress(@a, "label1") -> !cir.ptr + %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr cir.store align(8) %1, %0 : !cir.ptr, !cir.ptr> cir.br ^bb1 ^bb1: @@ -17,7 +17,7 @@ cir.func @a(){ } // CHECK: cir.func @a() -// CHECK: %1 = cir.blockaddress(@a, "label1") -> !cir.ptr +// CHECK: %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr // 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, !cir.ptr>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress(@b, "label1") -> !cir.ptr + %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr cir.store align(8) %1, %0 : !cir.ptr, !cir.ptr> cir.goto "label2" ^bb1: @@ -39,7 +39,7 @@ cir.func @b(){ } // CHECK: cir.func @b() { -// CHECK: %1 = cir.blockaddress(@b, "label1") -> !cir.ptr +// CHECK: %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr // CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr, !cir.ptr> // CHECK: cir.br ^bb2 // CHECK: ^bb1: @@ -51,13 +51,13 @@ cir.func @b(){ cir.func @c() { cir.label "label1" %0 = cir.alloca !cir.ptr, !cir.ptr>, ["ptr", init] {alignment = 8 : i64} - %1 = cir.blockaddress(@c, "label1") -> !cir.ptr + %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr cir.store align(8) %1, %0 : !cir.ptr, !cir.ptr> cir.return } // CHECK: cir.func @c // CHECK: cir.label "label1" -// CHECK: %1 = cir.blockaddress(@c, "label1") -> !cir.ptr +// CHECK: %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr // CHECK: cir.store align(8) %1, {{.*}} : !cir.ptr, !cir.ptr>