================
@@ -382,5 +410,279 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s,
bool isFnTryBlock) {
return;
}
- cgm.errorNYI("exitCXXTryStmt: Required catch");
+ // Emit the structure of the EH dispatch for this catch.
+ emitCatchDispatchBlock(*this, catchScope, tryOp);
+
+ // Copy the handler blocks off before we pop the EH stack. Emitting
+ // the handlers might scribble on this memory.
+ SmallVector<EHCatchScope::Handler, 8> handlers(
+ catchScope.begin(), catchScope.begin() + numHandlers);
+
+ ehStack.popCatch();
+
+ // Determine if we need an implicit rethrow for all these catch handlers;
+ // see the comment below.
+ bool doImplicitRethrow =
+ isFnTryBlock && isa<CXXDestructorDecl, CXXConstructorDecl>(curCodeDecl);
+
+ // Wasm uses Windows-style EH instructions, but merges all catch clauses into
+ // one big catchpad. So we save the old funclet pad here before we traverse
+ // each catch handler.
+ if (EHPersonality::get(*this).isWasmPersonality()) {
+ cgm.errorNYI("exitCXXTryStmt: WASM personality");
+ return;
+ }
+
+ bool hasCatchAll = false;
+ for (unsigned i = numHandlers; i != 0; --i) {
+ hasCatchAll |= handlers[i - 1].isCatchAll();
+ mlir::Region *catchRegion = handlers[i - 1].region;
+
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointToStart(&catchRegion->front());
+
+ const CXXCatchStmt *catchStmt = s.getHandler(i - 1);
+
+ // Enter a cleanup scope, including the catch variable and the
+ // end-catch.
+ RunCleanupsScope catchScope(*this);
+
+ // Initialize the catch variable and set up the cleanups.
+ // TODO: emitBeginCatch
+
+ // Emit the PGO counter increment.
+ assert(!cir::MissingFeatures::incrementProfileCounter());
+
+ // Perform the body of the catch.
+ mlir::LogicalResult emitResult =
+ emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
+ assert(emitResult.succeeded() && "failed to emit catch handler block");
+
+ // TODO(cir): This yeild should replaced by CatchParamOp once it upstreamed
+ cir::YieldOp::create(builder, tryOp->getLoc());
+
+ // [except.handle]p11:
+ // The currently handled exception is rethrown if control
+ // reaches the end of a handler of the function-try-block of a
+ // constructor or destructor.
+
+ // It is important that we only do this on fallthrough and not on
+ // return. Note that it's illegal to put a return in a
+ // constructor function-try-block's catch handler (p14), so this
+ // really only applies to destructors.
+ if (doImplicitRethrow) {
+ cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");
+ return;
+ }
+
+ // Fall out through the catch cleanups.
+ catchScope.forceCleanup();
+ }
+
+ // Because in wasm we merge all catch clauses into one big catchpad, in case
+ // none of the types in catch handlers matches after we test against each of
+ // them, we should unwind to the next EH enclosing scope. We generate a call
+ // to rethrow function here to do that.
+ if (EHPersonality::get(*this).isWasmPersonality() && !hasCatchAll) {
+ cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");
+ }
+
+ assert(!cir::MissingFeatures::incrementProfileCounter());
+}
+
+mlir::Operation *CIRGenFunction::emitLandingPad(cir::TryOp tryOp) {
+ assert(ehStack.requiresLandingPad());
+ assert(!cgm.getLangOpts().IgnoreExceptions &&
+ "LandingPad should not be emitted when -fignore-exceptions are in "
+ "effect.");
+
+ EHScope &innermostEHScope = *ehStack.find(ehStack.getInnermostEHScope());
+ switch (innermostEHScope.getKind()) {
+ case EHScope::Terminate:
+ cgm.errorNYI("emitLandingPad: terminate");
+ return {};
+
+ case EHScope::Catch:
+ case EHScope::Cleanup:
+ case EHScope::Filter:
+ // CIR does not cache landing pads.
+ break;
+ }
+
+ // If there's an existing TryOp, it means we got a `cir.try` scope
+ // that leads to this "landing pad" creation site. Otherwise, exceptions
+ // are enabled but a throwing function is called anyways (common pattern
+ // with function local static initializers).
+ mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
+ if (!handlerTypesAttr || handlerTypesAttr.empty()) {
+ // Accumulate all the handlers in scope.
+ bool hasCatchAll = false;
+ llvm::SmallVector<mlir::Attribute, 4> handlerAttrs;
+ for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;
+ ++i) {
+ switch (i->getKind()) {
+ case EHScope::Cleanup: {
+ cgm.errorNYI("emitLandingPad: Cleanup");
+ return {};
+ }
+
+ case EHScope::Filter: {
+ cgm.errorNYI("emitLandingPad: Filter");
+ return {};
+ }
+
+ case EHScope::Terminate: {
+ cgm.errorNYI("emitLandingPad: Terminate");
+ return {};
+ }
+
+ case EHScope::Catch:
+ break;
+ }
+
+ EHCatchScope &catchScope = cast<EHCatchScope>(*i);
+ for (unsigned handlerIdx = 0, he = catchScope.getNumHandlers();
+ handlerIdx != he; ++handlerIdx) {
+ EHCatchScope::Handler handler = catchScope.getHandler(handlerIdx);
+ assert(handler.type.flags == 0 &&
+ "landingpads do not support catch handler flags");
+
+ // If this is a catch-all, register that and abort.
+ if (handler.isCatchAll()) {
+ assert(!hasCatchAll);
+ hasCatchAll = true;
+ goto done;
+ }
+
+ cgm.errorNYI("emitLandingPad: non catch-all");
+ return {};
+ }
+
+ goto done;
+ }
+
+ done:
+ if (hasCatchAll) {
+ handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
+ } else {
+ cgm.errorNYI("emitLandingPad: non catch-all");
+ return {};
+ }
+
+ // Add final array of clauses into TryOp.
+ tryOp.setHandlerTypesAttr(
+ mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
+ }
+
+ // In traditional LLVM codegen. this tells the backend how to generate the
+ // landing pad by generating a branch to the dispatch block. In CIR,
+ // getEHDispatchBlock is used to populate blocks for later filing during
+ // cleanup handling.
+ (void)getEHDispatchBlock(ehStack.getInnermostEHScope(), tryOp);
+
+ return tryOp;
+}
+
+// Differently from LLVM traditional codegen, there are no dispatch blocks
+// to look at given cir.try_call does not jump to blocks like invoke does.
+// However, we keep this around since other parts of CIRGen use
+// getCachedEHDispatchBlock to infer state.
----------------
AmrDeveloper wrote:
Yes, this part about using it in other places should be removed. I already
removed those uses
https://github.com/llvm/llvm-project/pull/165158
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits