Author: Amr Hesham Date: 2025-12-16T19:52:44+01:00 New Revision: 18b38cf546a2561057f4ac39175ee77f5e858ae7
URL: https://github.com/llvm/llvm-project/commit/18b38cf546a2561057f4ac39175ee77f5e858ae7 DIFF: https://github.com/llvm/llvm-project/commit/18b38cf546a2561057f4ac39175ee77f5e858ae7.diff LOG: [CIR] Support Try catch with handler for specific type (#171042) Add support for try-catch with a handler for a specific exception type Issue https://github.com/llvm/llvm-project/issues/154992 Added: Modified: clang/include/clang/CIR/Dialect/IR/CIROps.td clang/include/clang/CIR/MissingFeatures.h clang/lib/CIR/CodeGen/CIRGenCXXABI.h clang/lib/CIR/CodeGen/CIRGenException.cpp clang/lib/CIR/CodeGen/CIRGenFunction.h clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp clang/test/CIR/CodeGen/try-catch-tmp.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 240459428b22c..0e91d008dc52d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3032,6 +3032,8 @@ def CIR_CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { let results = (outs Optional<CIR_AnyType>:$result); let arguments = commonArgs; + let skipDefaultBuilders = 1; + let builders = [ OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, "mlir::ValueRange":$operands), [{ diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ad8c7ca7336e6..a5b04d305b3e7 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -263,6 +263,7 @@ struct MissingFeatures { static bool ehCleanupScope() { return false; } static bool ehCleanupScopeRequiresEHCleanup() { return false; } static bool ehCleanupBranchFixups() { return false; } + static bool ehScopeFilter() { return false; } static bool ehstackBranches() { return false; } static bool emitBranchThroughCleanup() { return false; } static bool emitCheckedInBoundsGEP() { return false; } @@ -376,7 +377,6 @@ struct MissingFeatures { static bool tryOp() { return false; } static bool vecTernaryOp() { return false; } static bool zextOp() { return false; } - static bool catchParamOp() { return false; } // Future CIR attributes static bool optInfoAttr() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index b96d656b91e62..1d5fce3036bf4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -161,6 +161,9 @@ class CIRGenCXXABI { /// Loads the incoming C++ this pointer as it was passed by the caller. mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf); + virtual CatchTypeInfo + getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty, + QualType catchHandlerType) = 0; virtual CatchTypeInfo getCatchAllTypeInfo(); /// Get the implicit (second) parameter that comes after the "this" pointer, diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 70812452ed999..b84b3a3c92015 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -244,6 +244,29 @@ void CIRGenFunction::emitAnyExprToExn(const Expr *e, Address addr) { assert(!cir::MissingFeatures::ehCleanupScope()); } +void CIRGenFunction::populateUnwindResumeBlock(bool isCleanup, + cir::TryOp tryOp) { + 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) { + cgm.errorNYI("populateUnwindResumeBlock CatchallRethrowFn"); + return; + } + + unsigned regionsNum = tryOp->getNumRegions(); + mlir::Region *unwindRegion = &tryOp->getRegion(regionsNum - 1); + mlir::Block *unwindResumeBlock = &unwindRegion->front(); + if (!unwindResumeBlock->empty()) + return; + + // Emit cir.resume into the unwind region last block + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToStart(unwindResumeBlock); + cir::ResumeOp::create(builder, tryOp.getLoc()); +} + mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) { if (s.getTryBlock()->body_empty()) return mlir::LogicalResult::success(); @@ -344,21 +367,63 @@ CIRGenFunction::emitCXXTryStmtUnderScope(const CXXTryStmt &s) { return mlir::success(); } +/// Emit the structure of the dispatch block for the given catch scope. +/// It is an invariant that the dispatch block already exists. +static void emitCatchDispatchBlock(CIRGenFunction &cgf, + EHCatchScope &catchScope, cir::TryOp tryOp) { + if (EHPersonality::get(cgf).isWasmPersonality()) { + cgf.cgm.errorNYI("emitCatchDispatchBlock: WasmPersonality"); + return; + } + + if (EHPersonality::get(cgf).usesFuncletPads()) { + cgf.cgm.errorNYI("emitCatchDispatchBlock: usesFuncletPads"); + return; + } + + assert(std::find_if(catchScope.begin(), catchScope.end(), + [](const auto &handler) { + return !handler.type.rtti && handler.type.flags != 0; + }) == catchScope.end() && + "catch handler without type value or with not supported flags"); + + // There was no catch all handler, populate th EH regions for the + // enclosing scope. + if (!std::prev(catchScope.end())->isCatchAll()) + cgf.populateEHCatchRegions(catchScope.getEnclosingEHScope(), tryOp); +} + void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp, bool isFnTryBlock) { unsigned numHandlers = s.getNumHandlers(); EHCatchScope *catchScope = ehStack.pushCatch(numHandlers); for (unsigned i = 0; i != numHandlers; ++i) { const CXXCatchStmt *catchStmt = s.getHandler(i); + mlir::Region *handler = &tryOp.getHandlerRegions()[i]; if (catchStmt->getExceptionDecl()) { - cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl"); - return; - } + // FIXME: Dropping the reference type on the type into makes it + // impossible to correctly implement catch-by-reference + // semantics for pointers. Unfortunately, this is what all + // existing compilers do, and it's not clear that the standard + // personality routine is capable of doing this right. See C++ DR 388: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 + Qualifiers caughtTypeQuals; + QualType caughtType = cgm.getASTContext().getUnqualifiedArrayType( + catchStmt->getCaughtType().getNonReferenceType(), caughtTypeQuals); + if (caughtType->isObjCObjectPointerType()) { + cgm.errorNYI("enterCXXTryStmt: caughtType ObjCObjectPointerType"); + return; + } - // No exception decl indicates '...', a catch-all. - mlir::Region *handler = &tryOp.getHandlerRegions()[i]; - catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler, - s.getHandler(i)); + CatchTypeInfo typeInfo = cgm.getCXXABI().getAddrOfCXXCatchHandlerType( + getLoc(catchStmt->getSourceRange()), caughtType, + catchStmt->getCaughtType()); + catchScope->setHandler(i, typeInfo, handler, catchStmt); + } else { + // No exception decl indicates '...', a catch-all. + catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler, + s.getHandler(i)); + } // Under async exceptions, catch(...) needs to catch HW exception too // Mark scope with SehTryBegin as a SEH __try scope @@ -397,6 +462,9 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) { return; } + // 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> handlers(catchScope.begin(), @@ -442,9 +510,6 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) { emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true); assert(emitResult.succeeded() && "failed to emit catch handler block"); - assert(!cir::MissingFeatures::catchParamOp()); - 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 @@ -501,7 +566,8 @@ void CIRGenFunction::populateCatchHandlers(cir::TryOp tryOp) { if (!handlerTypesAttr || handlerTypesAttr.empty()) { // Accumulate all the handlers in scope. bool hasCatchAll = false; - llvm::SmallVector<mlir::Attribute, 4> handlerAttrs; + llvm::SmallPtrSet<mlir::Attribute, 4> catchTypes; + llvm::SmallVector<mlir::Attribute> handlerAttrs; for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e; ++i) { switch (i->getKind()) { @@ -534,20 +600,25 @@ void CIRGenFunction::populateCatchHandlers(cir::TryOp tryOp) { break; } - cgm.errorNYI("emitLandingPad: non catch-all"); - return; + // Check whether we already have a handler for this type. + // If not, keep track to later add to catch op. + if (catchTypes.insert(handler.type.rtti).second) + handlerAttrs.push_back(handler.type.rtti); } if (hasCatchAll) break; } - if (hasCatchAll) { + if (hasCatchAll) handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext())); - } else { - cgm.errorNYI("emitLandingPad: non catch-all"); - return; - } + + assert(!cir::MissingFeatures::ehScopeFilter()); + + // If there's no catch_all, attach the unwind region. This needs to be the + // last region in the TryOp catch list. + if (!hasCatchAll) + handlerAttrs.push_back(cir::UnwindAttr::get(&getMLIRContext())); // Add final array of clauses into TryOp. tryOp.setHandlerTypesAttr( @@ -571,6 +642,13 @@ void CIRGenFunction::populateEHCatchRegions(EHScopeStack::stable_iterator scope, return; } + // The dispatch block for the end of the scope chain is a block that + // just resumes unwinding. + if (scope == ehStack.stable_end()) { + populateUnwindResumeBlock(/*isCleanup=*/true, tryOp); + return; + } + // Otherwise, we should look at the actual scope. EHScope &ehScope = *ehStack.find(scope); bool mayThrow = ehScope.mayThrow(); @@ -588,16 +666,19 @@ void CIRGenFunction::populateEHCatchRegions(EHScopeStack::stable_iterator scope, if (!mayThrow) { switch (ehScope.getKind()) { case EHScope::Catch: { + mayThrow = true; + // LLVM does some optimization with branches here, CIR just keep track of // the corresponding calls. EHCatchScope &catchScope = cast<EHCatchScope>(ehScope); if (catchScope.getNumHandlers() == 1 && catchScope.getHandler(0).isCatchAll()) { - mayThrow = true; break; } - cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all"); - return; + + // TODO(cir): In the incubator we create a new basic block with YieldOp + // inside the attached cleanup region, but this part will be redesigned + break; } case EHScope::Cleanup: { cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup"); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index a2023caf36d3b..aff36d255b33d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -974,6 +974,7 @@ class CIRGenFunction : public CIRGenTypeCache { return false; } + void populateUnwindResumeBlock(bool isCleanup, cir::TryOp tryOp); void populateEHCatchRegions(EHScopeStack::stable_iterator scope, cir::TryOp tryOp); diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 56a735e0410d7..0d0d6c34a255a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -121,6 +121,13 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI { mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty) override; + CatchTypeInfo + getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty, + QualType catchHandlerType) override { + auto rtti = dyn_cast<cir::GlobalViewAttr>(getAddrOfRTTIDescriptor(loc, ty)); + assert(rtti && "expected GlobalViewAttr"); + return CatchTypeInfo{rtti, 0}; + } bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override { return true; @@ -2310,7 +2317,6 @@ struct CallEndCatch final : EHScopeStack::Cleanup { static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Type paramTy, bool endMightThrow) { - auto catchParam = cir::CatchParamOp::create( cgf.getBuilder(), cgf.getBuilder().getUnknownLoc(), paramTy); @@ -2321,6 +2327,56 @@ static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Type paramTy, return catchParam.getParam(); } +/// A "special initializer" callback for initializing a catch +/// parameter during catch initialization. +static void initCatchParam(CIRGenFunction &cgf, const VarDecl &catchParam, + Address paramAddr, SourceLocation loc) { + CanQualType catchType = + cgf.cgm.getASTContext().getCanonicalType(catchParam.getType()); + // If we're catching by reference, we can just cast the object + // pointer to the appropriate pointer. + if (isa<ReferenceType>(catchType)) { + cgf.cgm.errorNYI(loc, "initCatchParam: ReferenceType"); + return; + } + + // Scalars and complexes. + cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType); + if (tek != cir::TEK_Aggregate) { + // Notes for LLVM lowering: + // If the catch type is a pointer type, __cxa_begin_catch returns + // the pointer by value. + if (catchType->hasPointerRepresentation()) { + cgf.cgm.errorNYI(loc, "initCatchParam: hasPointerRepresentation"); + return; + } + + mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); + mlir::Value catchParam = + callBeginCatch(cgf, cgf.getBuilder().getPointerTo(cirCatchTy), false); + LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType); + LValue destLV = cgf.makeAddrLValue(paramAddr, catchType); + switch (tek) { + case cir::TEK_Complex: { + cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Complex"); + return; + } + case cir::TEK_Scalar: { + auto exnLoad = cgf.emitLoadOfScalar(srcLV, loc); + cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true); + return; + } + case cir::TEK_Aggregate: + llvm_unreachable("evaluation kind filtered out!"); + } + + // Otherwise, it returns a pointer into the exception object. + llvm_unreachable("bad evaluation kind"); + } + + cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate"); +} + /// Begins a catch statement by initializing the catch variable and /// calling __cxa_begin_catch. void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf, @@ -2355,5 +2411,29 @@ void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf, return; } - cgf.cgm.errorNYI("emitBeginCatch: catch with exception decl"); + auto getCatchParamAllocaIP = [&]() { + cir::CIRBaseBuilderTy::InsertPoint currIns = + cgf.getBuilder().saveInsertionPoint(); + mlir::Operation *currParent = currIns.getBlock()->getParentOp(); + + mlir::Block *insertBlock = nullptr; + if (auto scopeOp = currParent->getParentOfType<cir::ScopeOp>()) { + insertBlock = &scopeOp.getScopeRegion().getBlocks().back(); + } else if (auto fnOp = currParent->getParentOfType<cir::FuncOp>()) { + insertBlock = &fnOp.getRegion().getBlocks().back(); + } else { + llvm_unreachable("unknown outermost scope-like parent"); + } + return cgf.getBuilder().getBestAllocaInsertPoint(insertBlock); + }; + + // Emit the local. Make sure the alloca's superseed the current scope, since + // these are going to be consumed by `cir.catch`, which is not within the + // current scope. + + CIRGenFunction::AutoVarEmission var = + cgf.emitAutoVarAlloca(*catchParam, getCatchParamAllocaIP()); + initCatchParam(cgf, *catchParam, var.getObjectAddress(cgf), + catchStmt->getBeginLoc()); + cgf.emitAutoVarCleanups(var); } diff --git a/clang/test/CIR/CodeGen/try-catch-tmp.cpp b/clang/test/CIR/CodeGen/try-catch-tmp.cpp index baf5d102a8b74..78d8567e0760f 100644 --- a/clang/test/CIR/CodeGen/try-catch-tmp.cpp +++ b/clang/test/CIR/CodeGen/try-catch-tmp.cpp @@ -5,13 +5,14 @@ int division(); -void calling_division_inside_try_block() { +void call_function_inside_try_catch_all() { try { division(); } catch (...) { } } +// CIR: cir.func {{.*}} @_Z34call_function_inside_try_catch_allv() personality(@__gxx_personality_v0) // CIR: cir.scope { // CIR: cir.try { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i @@ -22,6 +23,8 @@ void calling_division_inside_try_block() { // CIR: } // CIR: } + +// OGCG: define {{.*}} void @_Z34call_function_inside_try_catch_allv() #0 personality ptr @__gxx_personality_v0 // OGCG: %[[EXN_OBJ_ADDR:.*]] = alloca ptr, align 8 // OGCG: %[[EH_SELECTOR_ADDR:.*]] = alloca i32, align 4 // OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv() @@ -43,3 +46,124 @@ void calling_division_inside_try_block() { // OGCG: br label %[[TRY_CONT]] // OGCG: [[TRY_CONT]]: // OGCG: ret void + +void call_function_inside_try_catch_with_exception_type() { + try { + division(); + } catch (int e) { + } +} + +// CIR: cir.func {{.*}} @_Z50call_function_inside_try_catch_with_exception_typev() personality(@__gxx_personality_v0) +// CIR: cir.scope { +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] +// CIR: cir.try { +// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i +// CIR: cir.yield +// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] { +// CIR: %[[CATCH_PARAM:.*]] = cir.catch_param : !cir.ptr<!s32i> +// CIR %[[TMP_CATCH_PARAM:.*]] = cir.load {{.*}} %[[CATCH_PRAM]] : !cir.ptr<!s32i>, !s32i +// CIR cir.store {{.*}} %[[TMP_CATCH_PARAM]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i> +// CIR: cir.yield +// CIR: } unwind { +// CIR: cir.resume +// CIR: } +// CIR: } + +// OGCG: define {{.*}} void @_Z50call_function_inside_try_catch_with_exception_typev() #0 personality ptr @__gxx_personality_v0 +// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[E_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv() +// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]] +// OGCG: [[INVOKE_NORMAL]]: +// OGCG: br label %try.cont +// OGCG: [[INVOKE_UNWIND]]: +// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 } +// OGCG: catch ptr @_ZTIi +// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0 +// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1 +// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: br label %[[CATCH_DISPATCH:.*]] +// OGCG: [[CATCH_DISPATCH]]: +// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) +// OGCG: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]] +// OGCG: br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]] +// OGCG: [[CATCH_EXCEPTION]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]]) +// OGCG: %[[TMP_BEGIN_CATCH:.*]] = load i32, ptr %[[BEGIN_CATCH]], align 4 +// OGCG: store i32 %[[TMP_BEGIN_CATCH]], ptr %[[E_ADDR]], align 4 +// OGCG: call void @__cxa_end_catch() +// OGCG: br label %[[TRY_CONT:.*]] +// OGCG: [[TRY_CONT]]: +// OGCG: ret void +// OGCG: [[EH_RESUME]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0 +// OGCG: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1 +// OGCG: resume { ptr, i32 } %[[EXCEPTION_INFO]] + +void call_function_inside_try_catch_with_exception_type_and_catch_all() { + try { + division(); + } catch (int e) { + } catch (...) { + } +} + +// CIR: cir.func {{.*}} @_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() personality(@__gxx_personality_v0) +// CIR: cir.scope { +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] +// CIR: cir.try { +// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i +// CIR: cir.yield +// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] { +// CIR: %[[CATCH_PARAM:.*]] = cir.catch_param : !cir.ptr<!s32i> +// CIR %[[TMP_CATCH_PARAM:.*]] = cir.load {{.*}} %[[CATCH_PRAM]] : !cir.ptr<!s32i>, !s32i +// CIR cir.store {{.*}} %[[TMP_CATCH_PARAM]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i> +// CIR: cir.yield +// CIR: } catch all { +// CIR: %[[CATCH_PARAM]] = cir.catch_param : !cir.ptr<!void> +// CIR: cir.yield +// CIR: } +// CIR: } + +// OGCG: define {{.*}} void @_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() #0 personality ptr @__gxx_personality_v0 +// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[E_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv() +// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]] +// OGCG: [[INVOKE_NORMAL]]: +// OGCG: br label %try.cont +// OGCG: [[INVOKE_UNWIND]]: +// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 } +// OGCG: catch ptr @_ZTIi +// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0 +// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1 +// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: br label %[[CATCH_DISPATCH:.*]] +// OGCG: [[CATCH_DISPATCH]]: +// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) +// OGCG: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]] +// OGCG: br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[CATCH_ALL:.*]] +// OGCG: [[CATCH_EXCEPTION]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]]) +// OGCG: %[[TMP_BEGIN_CATCH:.*]] = load i32, ptr %[[BEGIN_CATCH]], align 4 +// OGCG: store i32 %[[TMP_BEGIN_CATCH]], ptr %[[E_ADDR]], align 4 +// OGCG: call void @__cxa_end_catch() +// OGCG: br label %[[TRY_CONT:.*]] +// OGCG: [[TRY_CONT]]: +// OGCG: ret void +// OGCG: [[CATCH_ALL]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]]) +// OGCG: call void @__cxa_end_catch() +// OGCG: br label %[[TRY_CONT]] _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
