Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/llvm/clangir into rethrow
Browse files Browse the repository at this point in the history
  • Loading branch information
bruteforceboy committed Jan 27, 2025
2 parents 5dff443 + 7bdf358 commit 309a87c
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 26 deletions.
14 changes: 10 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1066,23 +1066,29 @@ def ScopeOp : CIR_Op<"scope", [
The blocks can be terminated by `cir.yield`, `cir.return` or `cir.throw`.
If `cir.scope` yields no value, the `cir.yield` can be left out, and
will be inserted implicitly.

The scope might also have an associated `cleanup` region, providing code
that run destruction of automatic variables. Note that in order to lower the
cleanup region while keeping C++ semantics, all immediate control-flow
breaking operations not under a children scope should jump to this cleanup
code.
}];

let results = (outs Optional<CIR_AnyType>:$results);
let regions = (region AnyRegion:$scopeRegion);
let regions = (region AnyRegion:$scopeRegion, AnyRegion:$cleanupRegion);

let hasVerifier = 1;
let skipDefaultBuilders = 1;
let assemblyFormat = [{
custom<OmittedTerminatorRegion>($scopeRegion) (`:` type($results)^)? attr-dict
custom<OmittedTerminatorRegion>($scopeRegion, $cleanupRegion) (`:` type($results)^)? attr-dict
}];

let extraClassDeclaration = [{
/// Determine whether the scope is empty, meaning it contains a single block
/// terminated by a cir.yield.
bool isEmpty() {
auto &entry = getRegion().front();
return getRegion().hasOneBlock() &&
auto &entry = getScopeRegion().front();
return getScopeRegion().hasOneBlock() &&
llvm::isa<YieldOp>(entry.front());
}
}];
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2840,7 +2840,7 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
if (auto tryOp =
llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {
if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))
entryBlock = &scopeOp.getRegion().front();
entryBlock = &scopeOp.getScopeRegion().front();
}

return emitAlloca(name, ty, loc, alignment,
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,13 +826,16 @@ void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &CGF,
auto getCatchParamAllocaIP = [&]() {
auto currIns = CGF.getBuilder().saveInsertionPoint();
auto currParent = currIns.getBlock()->getParentOp();
mlir::Operation *scopeLikeOp = currParent->getParentOfType<cir::ScopeOp>();
if (!scopeLikeOp)
scopeLikeOp = currParent->getParentOfType<cir::FuncOp>();
assert(scopeLikeOp && "unknown outermost scope-like parent");
assert(scopeLikeOp->getNumRegions() == 1 && "expected single region");

auto *insertBlock = &scopeLikeOp->getRegion(0).getBlocks().back();
mlir::Block *insertBlock = nullptr;
if (auto scopeOp = currParent->getParentOfType<cir::ScopeOp>()) {
insertBlock = &scopeOp.getScopeRegion().getBlocks().back();
} else if (auto fnOp = currParent->getParentOfType<cir::FuncOp>()) {
insertBlock = &fnOp.getRegion().getBlocks().back();
} else {
llvm_unreachable("unknown outermost scope-like parent");
}

return CGF.getBuilder().getBestAllocaInsertPoint(insertBlock);
};

Expand Down
47 changes: 37 additions & 10 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,22 +276,41 @@ void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility) {
// CIR Custom Parsers/Printers
//===----------------------------------------------------------------------===//

static mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser,
mlir::Region &region) {
static mlir::ParseResult
parseOmittedTerminatorRegion(mlir::OpAsmParser &parser,
mlir::Region &scopeRegion,
mlir::Region &cleanupRegion) {
auto regionLoc = parser.getCurrentLocation();
if (parser.parseRegion(region))
if (parser.parseRegion(scopeRegion))
return failure();
if (ensureRegionTerm(parser, region, regionLoc).failed())
if (ensureRegionTerm(parser, scopeRegion, regionLoc).failed())
return failure();

// Parse optional cleanup region.
if (parser.parseOptionalKeyword("cleanup").succeeded()) {
if (parser.parseRegion(cleanupRegion, /*arguments=*/{}, /*argTypes=*/{}))
return failure();
if (ensureRegionTerm(parser, cleanupRegion, regionLoc).failed())
return failure();
}

return success();
}

static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer,
cir::ScopeOp &op,
mlir::Region &region) {
printer.printRegion(region,
mlir::Region &scopeRegion,
mlir::Region &cleanupRegion) {
printer.printRegion(scopeRegion,
/*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/!omitRegionTerm(region));
/*printBlockTerminators=*/!omitRegionTerm(scopeRegion));
if (!op.getCleanupRegion().empty()) {
printer << " cleanup ";
printer.printRegion(
cleanupRegion,
/*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/!omitRegionTerm(cleanupRegion));
}
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1251,6 +1270,7 @@ void cir::ScopeOp::getSuccessorRegions(

// If the condition isn't constant, both regions may be executed.
regions.push_back(RegionSuccessor(&getScopeRegion()));
regions.push_back(RegionSuccessor(&getCleanupRegion()));
}

void cir::ScopeOp::build(
Expand All @@ -1261,6 +1281,8 @@ void cir::ScopeOp::build(
OpBuilder::InsertionGuard guard(builder);
Region *scopeRegion = result.addRegion();
builder.createBlock(scopeRegion);
// cleanup region, do not eagarly create blocks, do it upon demand.
(void)result.addRegion();

mlir::Type yieldTy;
scopeBuilder(builder, yieldTy, result.location);
Expand All @@ -1276,17 +1298,22 @@ void cir::ScopeOp::build(
OpBuilder::InsertionGuard guard(builder);
Region *scopeRegion = result.addRegion();
builder.createBlock(scopeRegion);
// cleanup region, do not eagarly create blocks, do it upon demand.
(void)result.addRegion();
scopeBuilder(builder, result.location);
}

LogicalResult cir::ScopeOp::verify() {
if (getRegion().empty()) {
if (getScopeRegion().empty()) {
return emitOpError() << "cir.scope must not be empty since it should "
"include at least an implicit cir.yield ";
}

if (getRegion().back().empty() ||
!getRegion().back().getTerminator()->hasTrait<OpTrait::IsTerminator>())
if (getScopeRegion().back().empty() ||
!getScopeRegion()
.back()
.getTerminator()
->hasTrait<OpTrait::IsTerminator>())
return emitOpError() << "last block of cir.scope must be terminated";
return success();
}
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ class CIRScopeOpFlattening : public mlir::OpRewritePattern<cir::ScopeOp> {
continueBlock->addArguments(scopeOp.getResultTypes(), loc);

// Inline body region.
auto *beforeBody = &scopeOp.getRegion().front();
auto *afterBody = &scopeOp.getRegion().back();
rewriter.inlineRegionBefore(scopeOp.getRegion(), continueBlock);
auto *beforeBody = &scopeOp.getScopeRegion().front();
auto *afterBody = &scopeOp.getScopeRegion().back();
rewriter.inlineRegionBefore(scopeOp.getScopeRegion(), continueBlock);

// Save stack and then branch into the body of the region.
rewriter.setInsertionPointToEnd(currentBlock);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ class CIRScopeOpLowering : public mlir::OpConversionPattern<cir::ScopeOp> {
return mlir::success();
}

for (auto &block : scopeOp.getRegion()) {
for (auto &block : scopeOp.getScopeRegion()) {
rewriter.setInsertionPointToEnd(&block);
auto *terminator = block.getTerminator();
rewriter.replaceOpWithNewOp<mlir::memref::AllocaScopeReturnOp>(
Expand Down
32 changes: 31 additions & 1 deletion clang/test/CIR/IR/scope.cir
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

module {
// Should properly print/parse scope with implicit empty yield.
// CHECK-LABEL: implicit_yield
cir.func @implicit_yield() {
cir.scope {
}
// CHECK: cir.scope {
// CHECK: }
// CHECK-NEXT: }
// CHECK-NEXT: cir.return
cir.return
}

// Should properly print/parse scope with explicit yield.
// CHECK-LABEL: explicit_yield
cir.func @explicit_yield() {
%0 = cir.scope {
%1 = cir.alloca !u32i, !cir.ptr<!u32i>, ["a", init] {alignment = 4 : i64}
Expand All @@ -24,4 +27,31 @@ module {
// CHECK: } : !cir.ptr<!u32i>
cir.return
}

// Handle optional cleanup presence
// CHECK-LABEL: empty_cleanup
cir.func @empty_cleanup() {
cir.scope {
} cleanup {
}
// CHECK: cir.scope {
// CHECK-NEXT: } cleanup {
// CHECK-NEXT: }
// CHECK-NEXT: cir.return
cir.return
}

// Handle optional cleanup presence
// CHECK-LABEL: some_cleanup
cir.func @some_cleanup() {
cir.scope {
} cleanup {
%1 = cir.alloca !u32i, !cir.ptr<!u32i>, ["a", init] {alignment = 4 : i64}
}
// CHECK: cir.scope {
// CHECK: } cleanup {
// CHECK: cir.alloca
// CHECK: }
cir.return
}
}

0 comments on commit 309a87c

Please sign in to comment.