Skip to content

Commit

Permalink
[CIR][CIRGen][NFC] Exceptions: Move the logic to create surrounding t…
Browse files Browse the repository at this point in the history
…ry to be close to call generation
  • Loading branch information
bcardosolopes committed Sep 14, 2024
1 parent 08bb891 commit fd3ba1d
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 54 deletions.
52 changes: 40 additions & 12 deletions clang/lib/CIR/CodeGen/CIRGenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,40 +450,69 @@ buildCallLikeOp(CIRGenFunction &CGF, mlir::Location callLoc,
mlir::cir::CallingConv callingConv,
mlir::cir::ExtraFuncAttributesAttr extraFnAttrs) {
auto &builder = CGF.getBuilder();
auto getOrCreateSurroundingTryOp = [&]() {
// In OG, we build the landing pad for this scope. In CIR, we emit a
// synthetic cir.try because this didn't come from codegenerating from a
// try/catch in C++.
auto op = CGF.currLexScope->getClosestTryParent();
if (op)
return op;

op = builder.create<mlir::cir::TryOp>(
*CGF.currSrcLoc, /*scopeBuilder=*/
[&](mlir::OpBuilder &b, mlir::Location loc) {},
// Don't emit the code right away for catch clauses, for
// now create the regions and consume the try scope result.
// Note that clauses are later populated in
// CIRGenFunction::buildLandingPad.
[&](mlir::OpBuilder &b, mlir::Location loc,
mlir::OperationState &result) {
// Since this didn't come from an explicit try, we only need one
// handler: unwind.
auto *r = result.addRegion();
builder.createBlock(r);
});
op.setSynthetic(true);
return op;
};

if (isInvoke) {
// This call can throw, few options:
// - If this call does not have an associated cir.try, use the
// one provided by InvokeDest,
// - User written try/catch clauses require calls to handle
// exceptions under cir.try.
auto *invokeDest = CGF.getInvokeDest();
auto tryOp = dyn_cast_if_present<mlir::cir::TryOp>(invokeDest);
auto tryOp = getOrCreateSurroundingTryOp();
assert(tryOp && "expected");

mlir::OpBuilder::InsertPoint ip = builder.saveInsertionPoint();
bool changeInsertion = tryOp && tryOp.getSynthetic();
if (changeInsertion) {
if (tryOp.getSynthetic()) {
mlir::Block *lastBlock = &tryOp.getTryRegion().back();
builder.setInsertionPointToStart(lastBlock);
} else {
assert(builder.getInsertionBlock() && "expected valid basic block");
}

mlir::cir::CallOp tryCallOp;
mlir::cir::CallOp callOpWithExceptions;
// TODO(cir): Set calling convention for `cir.try_call`.
assert(callingConv == mlir::cir::CallingConv::C && "NYI");
if (indirectFuncTy) {
tryCallOp = builder.createIndirectTryCallOp(callLoc, indirectFuncVal,
indirectFuncTy, CIRCallArgs);
callOpWithExceptions = builder.createIndirectTryCallOp(
callLoc, indirectFuncVal, indirectFuncTy, CIRCallArgs);
} else {
tryCallOp = builder.createTryCallOp(callLoc, directFuncOp, CIRCallArgs);
callOpWithExceptions =
builder.createTryCallOp(callLoc, directFuncOp, CIRCallArgs);
}
tryCallOp->setAttr("extra_attrs", extraFnAttrs);
callOpWithExceptions->setAttr("extra_attrs", extraFnAttrs);

auto *invokeDest = CGF.getInvokeDest(tryOp);
(void)invokeDest;

if (changeInsertion) {
if (tryOp.getSynthetic()) {
builder.create<mlir::cir::YieldOp>(tryOp.getLoc());
builder.restoreInsertionPoint(ip);
}
return tryCallOp;
return callOpWithExceptions;
}

assert(builder.getInsertionBlock() && "expected valid basic block");
Expand Down Expand Up @@ -731,7 +760,6 @@ RValue CIRGenFunction::buildCall(const CIRGenFunctionInfo &CallInfo,
noThrowAttr.getMnemonic()))
CannotThrow = true;
}
// mlir::Operation *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
bool isInvoke = CannotThrow ? false : isInvokeDest();

// TODO: UnusedReturnSizePtr
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (!RequiresNormalCleanup) {
// Mark CPP scope end for passed-by-value Arg temp
// per Windows ABI which is "normally" Cleanup in callee
if (IsEHa && getInvokeDest()) {
if (IsEHa && isInvokeDest()) {
// If we are deactivating a normal cleanup then we don't have a
// fallthrough. Restore original IP to emit CPP scope ends in the correct
// block.
Expand Down Expand Up @@ -319,7 +319,7 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (!Personality.isMSVCPersonality()) {
EHStack.pushTerminate();
PushedTerminate = true;
} else if (IsEHa && getInvokeDest()) {
} else if (IsEHa && isInvokeDest()) {
llvm_unreachable("NYI");
}

Expand Down
38 changes: 2 additions & 36 deletions clang/lib/CIR/CodeGen/CIRGenException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,12 +831,10 @@ bool CIRGenFunction::isInvokeDest() {
return true;
}

mlir::Operation *CIRGenFunction::getInvokeDestImpl() {
mlir::Operation *CIRGenFunction::getInvokeDestImpl(mlir::cir::TryOp tryOp) {
assert(EHStack.requiresLandingPad());
assert(!EHStack.empty());

if (!isInvokeDest())
return nullptr;
assert(isInvokeDest());

// Check the innermost scope for a cached landing pad. If this is
// a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
Expand All @@ -850,43 +848,11 @@ mlir::Operation *CIRGenFunction::getInvokeDestImpl() {
// if (!CurFn->hasPersonalityFn())
// CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality));

auto createSurroundingTryOp = [&]() {
// In OG, we build the landing pad for this scope. In CIR, we emit a
// synthetic cir.try because this didn't come from codegenerating from a
// try/catch in C++.
auto tryOp = builder.create<mlir::cir::TryOp>(
*currSrcLoc, /*scopeBuilder=*/
[&](mlir::OpBuilder &b, mlir::Location loc) {},
// Don't emit the code right away for catch clauses, for
// now create the regions and consume the try scope result.
// Note that clauses are later populated in
// CIRGenFunction::buildLandingPad.
[&](mlir::OpBuilder &b, mlir::Location loc,
mlir::OperationState &result) {
// Since this didn't come from an explicit try, we only need one
// handler: unwind.
auto *r = result.addRegion();
builder.createBlock(r);
});
tryOp.setSynthetic(true);
return tryOp;
};

if (Personality.usesFuncletPads()) {
// We don't need separate landing pads in the funclet model.
llvm::errs() << "PersonalityFn: " << Personality.PersonalityFn << "\n";
llvm_unreachable("NYI");
} else {
mlir::cir::TryOp tryOp = nullptr;
// Attempt to find a suitable existing parent try/catch, if none
// is available, create a synthetic cir.try in order to wrap the side
// effects of a potential throw.
if (currLexScope)
tryOp = currLexScope->getClosestTryParent();
if (!tryOp)
tryOp = createSurroundingTryOp();

assert(tryOp && "cir.try expected");
LP = buildLandingPad(tryOp);
}

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1759,13 +1759,13 @@ class CIRGenFunction : public CIRGenTypeCache {
/// parameters.
EHScopeStack::stable_iterator PrologueCleanupDepth;

mlir::Operation *getInvokeDestImpl();
mlir::Operation *getInvokeDest() {
mlir::Operation *getInvokeDestImpl(mlir::cir::TryOp tryOp);
mlir::Operation *getInvokeDest(mlir::cir::TryOp tryOp) {
if (!EHStack.requiresLandingPad())
return nullptr;
// Return the respective cir.try, this can be used to compute
// any other relevant information.
return getInvokeDestImpl();
return getInvokeDestImpl(tryOp);
}
bool isInvokeDest();

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2227,7 +2227,7 @@ void CIRGenItaniumCXXABI::buildThrow(CIRGenFunction &CGF,

// FIXME: When adding support for invoking, we should wrap the throw op
// below into a try, and let CFG flatten pass to generate a cir.try_call.
assert(!CGF.getInvokeDest() && "landing pad like logic NYI");
assert(!CGF.isInvokeDest() && "landing pad like logic NYI");

// Now throw the exception.
mlir::Location loc = CGF.getLoc(E->getSourceRange());
Expand Down

0 comments on commit fd3ba1d

Please sign in to comment.