Skip to content

Commit

Permalink
[CIR] Add cir.resume op and use it in cir.catch
Browse files Browse the repository at this point in the history
- Add an extra CatchOp region to hold fallback (where EH usually resumes or
  rethrows as part of try/catch).
- Emit `cir.resume` on the fallback region.

Incremental step into the next assertion, still missing pieces before adding
the first testcase.
  • Loading branch information
bcardosolopes authored and lanza committed Apr 17, 2024
1 parent ae5e07b commit e4ef651
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
25 changes: 25 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,31 @@ def ContinueOp : CIR_Op<"continue", [Terminator]> {
let hasVerifier = 1;
}

//===----------------------------------------------------------------------===//
// Resume
//===----------------------------------------------------------------------===//

def ResumeOp : CIR_Op<"resume", [ReturnLike, Terminator,
ParentOneOf<["CatchOp"]>]> {
let summary = "Resumes execution after not catching exceptions";
let description = [{
The `cir.resume` operation terminates a region on `cir.catch`, "resuming"
or continuing the unwind process. The incoming argument is of !cir.eh_info
populated by `cir.try_call` and available in `cir.catch`.

Examples:
```mlir
cir.catch %4 {
...
fallback { cir.resume(%0) };
}
```
}];

let arguments = (ins ExceptionInfoPtr:$ptr);
let assemblyFormat = "$ptr attr-dict";
}

//===----------------------------------------------------------------------===//
// ScopeOp
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def ExceptionInfoPtr : Type<
]>, "void*">,
BuildableType<
"mlir::cir::PointerType::get($_builder.getContext(),"
"mlir::cir::ExceptionInfo::get($_builder.getContext()))"> {
"mlir::cir::ExceptionInfoType::get($_builder.getContext()))"> {
}

//===----------------------------------------------------------------------===//
Expand Down
52 changes: 49 additions & 3 deletions clang/lib/CIR/CodeGen/CIRGenException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,36 @@ void CIRGenFunction::buildAnyExprToExn(const Expr *e, Address addr) {
DeactivateCleanupBlock(cleanup, op);
}

mlir::Block *CIRGenFunction::getEHResumeBlock(bool isCleanup) {
// Just like some other try/catch related logic: return the basic block
// pointer but only use it to denote we're tracking things, but there
// shouldn't be any changes to that block after work done in this function.
auto catchOp = currExceptionInfo.catchOp;
assert(catchOp.getNumRegions() && "expected at least one region");
auto &fallbackRegion = catchOp.getRegion(catchOp.getNumRegions() - 1);

auto *resumeBlock = &fallbackRegion.getBlocks().back();
if (!resumeBlock->empty())
return resumeBlock;

auto ip = getBuilder().saveInsertionPoint();
getBuilder().setInsertionPointToStart(resumeBlock);

const EHPersonality &Personality = EHPersonality::get(*this);

// This can always be a call because we necessarily didn't find
// anything on the EH stack which needs our help.
const char *RethrowName = Personality.CatchallRethrowFn;
if (RethrowName != nullptr && !isCleanup) {
llvm_unreachable("NYI");
}

getBuilder().create<mlir::cir::ResumeOp>(catchOp.getLoc(),
currExceptionInfo.exceptionAddr);
getBuilder().restoreInsertionPoint(ip);
return resumeBlock;
}

mlir::LogicalResult CIRGenFunction::buildCXXTryStmt(const CXXTryStmt &S) {
const llvm::Triple &T = getTarget().getTriple();
// If we encounter a try statement on in an OpenMP target region offloaded to
Expand Down Expand Up @@ -288,7 +318,9 @@ mlir::LogicalResult CIRGenFunction::buildCXXTryStmt(const CXXTryStmt &S) {
[&](mlir::OpBuilder &b, mlir::Location loc,
mlir::OperationState &result) {
mlir::OpBuilder::InsertionGuard guard(b);
for (int i = 0, e = numHandlers; i != e; ++i) {
// Once for each handler and one for fallback (which could be a
// resume or rethrow).
for (int i = 0, e = numHandlers + 1; i != e; ++i) {
auto *r = result.addRegion();
builder.createBlock(r);
}
Expand Down Expand Up @@ -346,11 +378,25 @@ static void buildCatchDispatchBlock(CIRGenFunction &CGF,
// Check for address space mismatch: if (typeValue->getType() != argTy)
assert(!UnimplementedFeature::addressSpace());

bool nextIsEnd = false;
// If this is the last handler, we're at the end, and the next
// block is the block for the enclosing EH scope. Make sure to call
// getEHDispatchBlock for caching it.
if (i + 1 == e)
if (i + 1 == e) {
(void)CGF.getEHDispatchBlock(catchScope.getEnclosingEHScope());
nextIsEnd = true;

// If the next handler is a catch-all, we're at the end, and the
// next block is that handler.
} else if (catchScope.getHandler(i + 1).isCatchAll()) {
// Block already created when creating CatchOp, just mark this
// is the end.
nextIsEnd = true;
}

// If the next handler is a catch-all, we're completely done.
if (nextIsEnd)
return;
}
}

Expand Down Expand Up @@ -549,7 +595,7 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
// The dispatch block for the end of the scope chain is a block that
// just resumes unwinding.
if (si == EHStack.stable_end())
llvm_unreachable("NYI");
return getEHResumeBlock(true);

// Otherwise, we should look at the actual scope.
EHScope &scope = *EHStack.find(si);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1503,8 +1503,9 @@ class CIRGenFunction : public CIRGenTypeCache {
bool isConditional() const { return IsConditional; }
};

/// Emits landing pad information for the current EH stack.
/// Emits try/catch information for the current EH stack.
mlir::Operation *buildLandingPad();
mlir::Block *getEHResumeBlock(bool isCleanup);
mlir::Block *getEHDispatchBlock(EHScopeStack::stable_iterator scope);

mlir::Operation *getInvokeDestImpl();
Expand Down

0 comments on commit e4ef651

Please sign in to comment.