Skip to content

Commit c4ead2d

Browse files
committed
[CIR] Upstream non-empty Try block with catch all
1 parent 240fe7e commit c4ead2d

File tree

8 files changed

+434
-8
lines changed

8 files changed

+434
-8
lines changed

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,48 @@ static cir::CIRCallOpInterface
465465
emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
466466
cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
467467
cir::FuncOp directFuncOp,
468-
const SmallVectorImpl<mlir::Value> &cirCallArgs,
468+
const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
469469
const mlir::NamedAttrList &attrs) {
470470
CIRGenBuilderTy &builder = cgf.getBuilder();
471471

472472
assert(!cir::MissingFeatures::opCallSurroundingTry());
473-
assert(!cir::MissingFeatures::invokeOp());
473+
474+
if (isInvoke) {
475+
// This call can throw, few options:
476+
// - If this call does not have an associated cir.try, use the
477+
// one provided by InvokeDest,
478+
// - User written try/catch clauses require calls to handle
479+
// exceptions under cir.try.
480+
481+
// In OG, we build the landing pad for this scope. In CIR, we emit a
482+
// synthetic cir.try because this didn't come from code generating from a
483+
// try/catch in C++.
484+
assert(cgf.curLexScope && "expected scope");
485+
cir::TryOp tryOp = cgf.curLexScope->getClosestTryParent();
486+
if (!tryOp) {
487+
cgf.cgm.errorNYI(
488+
"emitCallLikeOp: call does not have an associated cir.try");
489+
return {};
490+
}
491+
492+
if (tryOp.getSynthetic()) {
493+
cgf.cgm.errorNYI("emitCallLikeOp: tryOp synthetic");
494+
return {};
495+
}
496+
497+
cir::CallOp callOpWithExceptions;
498+
if (indirectFuncTy) {
499+
cgf.cgm.errorNYI("emitCallLikeOp: indirect function type");
500+
return {};
501+
}
502+
503+
callOpWithExceptions =
504+
builder.createTryCallOp(callLoc, directFuncOp, cirCallArgs);
505+
506+
(void)cgf.getInvokeDest(tryOp);
507+
508+
return callOpWithExceptions;
509+
}
474510

475511
assert(builder.getInsertionBlock() && "expected valid basic block");
476512

@@ -628,10 +664,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
628664
indirectFuncVal = calleePtr->getResult(0);
629665
}
630666

667+
// TODO(cir): currentFunctionUsesSEHTry
668+
// TODO(cir): check for MSVCXXPersonality
669+
// TODO(cir): Create NoThrowAttr
670+
bool cannotThrow = attrs.getNamed("nothrow").has_value();
671+
bool isInvoke = !cannotThrow && isInvokeDest();
672+
631673
mlir::Location callLoc = loc;
632674
cir::CIRCallOpInterface theCall =
633675
emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
634-
cirCallArgs, attrs);
676+
cirCallArgs, isInvoke, attrs);
635677

636678
if (callOp)
637679
*callOp = theCall;

clang/lib/CIR/CodeGen/CIRGenCleanup.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,17 @@ void EHScopeStack::popCleanup() {
188188
}
189189
}
190190

191+
bool EHScopeStack::requiresLandingPad() const {
192+
for (stable_iterator si = getInnermostEHScope(); si != stable_end();) {
193+
// TODO(cir): Skip lifetime markers.
194+
assert(!cir::MissingFeatures::emitLifetimeMarkers());
195+
return true;
196+
}
197+
return false;
198+
}
199+
191200
EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) {
192201
char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers));
193-
assert(!cir::MissingFeatures::innermostEHScope());
194202
EHCatchScope *scope =
195203
new (buffer) EHCatchScope(numHandlers, innermostEHScope);
196204
innermostEHScope = stable_begin();

clang/lib/CIR/CodeGen/CIRGenCleanup.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class EHScope {
3838
};
3939
enum { NumCommonBits = 3 };
4040

41+
bool isScopeMayThrow;
42+
4143
protected:
4244
class CatchBitFields {
4345
friend class EHCatchScope;
@@ -92,10 +94,11 @@ class EHScope {
9294
// Traditional LLVM codegen also checks for `!block->use_empty()`, but
9395
// in CIRGen the block content is not important, just used as a way to
9496
// signal `hasEHBranches`.
95-
assert(!cir::MissingFeatures::ehstackBranches());
96-
return false;
97+
return isScopeMayThrow;
9798
}
9899

100+
void setMayThrow(bool mayThrow) { isScopeMayThrow = mayThrow; }
101+
99102
EHScopeStack::stable_iterator getEnclosingEHScope() const {
100103
return enclosingEHScope;
101104
}

0 commit comments

Comments
 (0)