Hendrik =?utf-8?q?Hübner?= <[email protected]>,
Hendrik =?utf-8?q?Hübner?= <[email protected]>,
Hendrik =?utf-8?q?Hübner?= <[email protected]>,
Hendrik =?utf-8?q?Hübner?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>
================
@@ -182,61 +195,122 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction
&CGF,
Handler.TypeInfo = GetEHType(CatchDecl->getType());
}
+ // Create a new catch scope
EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags },
Handlers[I].Block);
}
- if (useFunclets)
+ if (IsMSVC) {
if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
- CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
- if (!CGF.CurSEHParent)
- CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
- // Outline the finally block.
- const Stmt *FinallyBlock = Finally->getFinallyBody();
- HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock);
-
- // Emit the original filter expression, convert to i32, and return.
- HelperCGF.EmitStmt(FinallyBlock);
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (!CGF.CurSEHParent)
+ CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
+ // Outline the finally block.
+ const Stmt *FinallyBlock = Finally->getFinallyBody();
+ HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/ false, FinallyBlock);
- HelperCGF.FinishFunction(FinallyBlock->getEndLoc());
+ // Emit the original filter expression, convert to i32, and return.
+ HelperCGF.EmitStmt(FinallyBlock);
- llvm::Function *FinallyFunc = HelperCGF.CurFn;
+ HelperCGF.FinishFunction(FinallyBlock->getEndLoc());
+ llvm::Function *FinallyFunc = HelperCGF.CurFn;
- // Push a cleanup for __finally blocks.
- CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
+ // Push a cleanup for __finally blocks.
+ CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
}
-
+ }
// Emit the try body.
CGF.EmitStmt(S.getTryBody());
+ // lpad or catch.dispatch (the dispatch block) has now been emitted
+ //
+ // Here an example:
+ // void may_throw();
+ // @try {
+ // may_throw();
+ // } @catch(id a) {
+ // } @catch(id b) {
+ // [...]
+ //
+ // With funclet-based exception handling, the dispatch block is created in
+ // getEHDispatchBlock() <- getInvokeDestImpl() <- EmitCall().
+ // The following IR is emitted in this case:
+ // On aarch64-linux-gnu (landing-pad based)
+ // %call = invoke i32 @may_throw()
+ // to label %invoke.cont unwind label %lpad, !dbg !19
+ // On aarch64-pc-windows-msvc (funclet based)
+ // %call = invoke i32 @may_throw()
+ // to label %invoke.cont unwind label %catch.dispatch, !dbg !17
+
// Leave the try.
- if (S.getNumCatchStmts())
- CGF.popCatchScope();
+ llvm::BasicBlock *DispatchBlock = nullptr;
+ if (S.getNumCatchStmts()) {
+ // The dispatch block that was created during the emission of the try block
+ // was cached. We retrieve it when popping the current catch scope.
+ DispatchBlock = CGF.popCatchScope();
+ }
+
+ // On Windows and WASM, the new exception handling instructions are used.
+ //
+ // Continuing with the previous example, on Windows, we emit one catchpad for
+ // every catch handler. This is not the case for WASM where all catch
handlers
+ // merged into one big catchpad:
+ //
+ // catch.dispatch:
+ // %0 = catchswitch within none [label %catch.start] unwind to caller
+ // catch.start:
+ // %1 = catchpad within %0 [ptr @__objc_id_type_info, ptr null]
+ // [...]
+ // br i1 %matches, label %catch, label %catch2
+ //
+ // We save the old funclet pad here before we traverse each catch handler.
+ SaveAndRestore RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
+ llvm::BasicBlock *WasmCatchStartBlock = nullptr;
+ llvm::CatchPadInst *CPI = nullptr;
+ if (!!DispatchBlock && IsWasm) {
+ auto *CatchSwitch =
+ cast<llvm::CatchSwitchInst>(DispatchBlock->getFirstNonPHIIt());
+ WasmCatchStartBlock = CatchSwitch->hasUnwindDest()
+ ? CatchSwitch->getSuccessor(1)
+ : CatchSwitch->getSuccessor(0);
+ CPI = cast<llvm::CatchPadInst>(WasmCatchStartBlock->getFirstNonPHIIt());
+ CGF.CurrentFuncletPad = CPI;
+ }
// Remember where we were.
CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
- // Emit the handlers.
+ // Emit the handlers. If there is no catch-all handler, we need to emit a
+ // fallthrough block in WASM. We therefore need to know if we have a
+ // catch-all handler in this catch scope.
+ bool HasCatchAll = false;
for (CatchHandler &Handler : Handlers) {
+ HasCatchAll |= Handler.TypeInfo == nullptr;
CGF.EmitBlock(Handler.Block);
CodeGenFunction::LexicalScope Cleanups(CGF,
Handler.Body->getSourceRange());
SaveAndRestore RevertAfterScope(CGF.CurrentFuncletPad);
- if (useFunclets) {
+ if (IsMSVC) {
llvm::BasicBlock::iterator CPICandidate =
Handler.Block->getFirstNonPHIIt();
if (CPICandidate != Handler.Block->end()) {
- if (auto *CPI = dyn_cast_or_null<llvm::CatchPadInst>(CPICandidate)) {
+ CPI = dyn_cast_or_null<llvm::CatchPadInst>(CPICandidate);
+ if (!!CPI) {
CGF.CurrentFuncletPad = CPI;
CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF));
- CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
}
}
}
+ if (!!CPI) {
----------------
aheejin wrote:
```suggestion
if (CPI) {
```
Do we need `!!`?
https://github.com/llvm/llvm-project/pull/215562
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits