https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/190612
>From 1428bb5cbf931e8588856c8f3c83ada9dc277a91 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Mon, 6 Apr 2026 15:57:11 +0200 Subject: [PATCH 1/2] [CIR] Make BeginCatch target-independent --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 22 +++-- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 74 +++++------------ .../CIR/Dialect/Transforms/EHABILowering.cpp | 81 +++++++++++++++++-- .../CodeGen/try-catch-all-with-cleanup.cpp | 16 ++-- clang/test/CIR/CodeGen/try-catch.cpp | 65 ++++++--------- clang/test/CIR/IR/catch-param.cir | 4 +- clang/test/CIR/IR/eh-flat.cir | 20 +++-- clang/test/CIR/IR/try-catch.cir | 16 ++-- 8 files changed, 165 insertions(+), 133 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index b806800275c7b..1f0bbe5b507d7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -7333,6 +7333,14 @@ def CIR_EndCleanupOp : CIR_Op<"end_cleanup"> { // EH Operations: BeginCatchOp //===----------------------------------------------------------------------===// +def CIR_BeginCatchKind : CIR_I32EnumAttr<"BeginCatchKind", "beginCatchKind", [ + I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"LoadStore", 1, "load_store">, + I32EnumAttrCase<"Store", 2, "store">, + I32EnumAttrCase<"Memcopy", 3, "memcopy">, + I32EnumAttrCase<"Reference", 4, "reference">, +]>; + def CIR_BeginCatchOp : CIR_Op<"begin_catch"> { let summary = "Begin a catch handler"; let description = [{ @@ -7380,13 +7388,17 @@ def CIR_BeginCatchOp : CIR_Op<"begin_catch"> { ``` }]; - let arguments = (ins CIR_EhTokenType:$eh_token); - let results = (outs CIR_CatchTokenType:$catch_token, - CIR_PointerType:$exn_ptr); + let arguments = (ins + CIR_EhTokenType:$eh_token, + Optional<CIR_PointerType>:$exn_ptr, + CIR_BeginCatchKind:$kind + ); + + let results = (outs CIR_CatchTokenType:$catch_token); let assemblyFormat = [{ - $eh_token `:` type($eh_token) `->` `(` type($catch_token) `,` - qualified(type($exn_ptr)) `)` attr-dict + $kind $eh_token `:` type($eh_token) (`,` $exn_ptr^ `:` qualified(type($exn_ptr)))? + `->` type($catch_token) attr-dict }]; let hasLLVMLowering = false; diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 75658b23790bf..471c48da8d2b8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -2523,12 +2523,14 @@ struct CallEndCatch final : EHScopeStack::Cleanup { }; } // namespace -static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, - mlir::Type exnPtrTy, bool endMightThrow) { +static mlir::Value +callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Value exnPtr, + mlir::Type exnPtrTy, bool endMightThrow, + cir::BeginCatchKind kind = cir::BeginCatchKind::Default) { auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext()); - auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(), - cgf.getBuilder().getUnknownLoc(), - catchTokenTy, exnPtrTy, ehToken); + auto beginCatch = cir::BeginCatchOp::create( + cgf.getBuilder(), cgf.getBuilder().getUnknownLoc(), catchTokenTy, ehToken, + exnPtr, kind); cgf.ehStack.pushCleanup<CallEndCatch>( NormalAndEHCleanup, @@ -2553,8 +2555,8 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType(); bool endCatchMightThrow = caughtType->isRecordType(); - mlir::Value adjustedExn = - callBeginCatch(cgf, ehToken, cirCatchTy, endCatchMightThrow); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, + endCatchMightThrow, cir::BeginCatchKind::Reference); // We have no way to tell the personality function that we're // catching by reference, so if we're catching a pointer, @@ -2566,24 +2568,8 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, if (!pointeeType->isRecordType()) { cgf.cgm.errorNYI(loc, "initCatchParam: catching a pointer of non-record"); - } else { - // Pull the pointer for the reference type off. - mlir::Type ptrTy = cgf.convertTypeForMem(caughtType); - - // Create the temporary and write the adjusted pointer into it. - Address exnPtrTmp = cgf.createTempAlloca( - ptrTy, cgf.getPointerAlign(), cgf.getLoc(loc), "exn.byref.tmp"); - mlir::Value casted = cgf.getBuilder().createBitcast(adjustedExn, ptrTy); - cgf.getBuilder().createStore(cgf.getLoc(loc), casted, exnPtrTmp); - - // Bind the reference to the temporary. - adjustedExn = exnPtrTmp.emitRawPointer(); } } - - mlir::Value exnCast = - cgf.getBuilder().createBitcast(adjustedExn, cirCatchTy); - cgf.getBuilder().createStore(cgf.getLoc(loc), exnCast, paramAddr); return; } @@ -2594,8 +2580,8 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, // If the catch type is a pointer type, __cxa_begin_catch returns // the pointer by value. if (catchType->hasPointerRepresentation()) { - mlir::Value catchParam = - callBeginCatch(cgf, ehToken, cirCatchTy, /*endMightThrow=*/false); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, + /*endMightThrow=*/false, cir::BeginCatchKind::Store); switch (catchType.getQualifiers().getObjCLifetime()) { case Qualifiers::OCL_Strong: cgf.cgm.errorNYI(loc, @@ -2609,7 +2595,6 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, return; case Qualifiers::OCL_None: - cgf.getBuilder().createStore(cgf.getLoc(loc), catchParam, paramAddr); return; case Qualifiers::OCL_Weak: @@ -2622,44 +2607,21 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, // Otherwise, it returns a pointer into the exception object. mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); - mlir::Value catchParam = - callBeginCatch(cgf, ehToken, cgf.getBuilder().getPointerTo(cirCatchTy), - /*endMightThrow=*/false); - LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType); - LValue destLV = cgf.makeAddrLValue(paramAddr, catchType); - switch (tek) { - case cir::TEK_Complex: { - mlir::Value load = cgf.emitLoadOfComplex(srcLV, loc); - cgf.emitStoreOfComplex(cgf.getLoc(loc), load, destLV, /*isInit=*/true); - return; - } - case cir::TEK_Scalar: { - mlir::Value exnLoad = cgf.emitLoadOfScalar(srcLV, loc); - cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true); - return; - } - case cir::TEK_Aggregate: - llvm_unreachable("evaluation kind filtered out!"); - } - - llvm_unreachable("bad evaluation kind"); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), + cgf.getBuilder().getPointerTo(cirCatchTy), + /*endMightThrow=*/false, cir::BeginCatchKind::LoadStore); + return; } assert(isa<RecordType>(catchType) && "unexpected catch type!"); - auto *catchRD = catchType->getAsCXXRecordDecl(); - CharUnits caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD); // Check for a copy expression. If we don't have a copy expression, // that means a trivial copy is okay. const Expr *copyExpr = catchParam.getInit(); if (!copyExpr) { mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy); - mlir::Value rawAdjustedExn = - callBeginCatch(cgf, ehToken, cirCatchPtrTy, /*endMightThrow=*/true); - Address adjustedExn(rawAdjustedExn, cirCatchTy, caughtExnAlignment); - LValue dest = cgf.makeAddrLValue(paramAddr, catchType); - LValue src = cgf.makeAddrLValue(adjustedExn, catchType); - cgf.emitAggregateCopy(dest, src, catchType, AggValueSlot::DoesNotOverlap); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchPtrTy, + /*endMightThrow=*/true, cir::BeginCatchKind::Memcopy); return; } @@ -2696,7 +2658,7 @@ void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf, VarDecl *catchParam = catchStmt->getExceptionDecl(); if (!catchParam) { - callBeginCatch(cgf, ehToken, cgf.getBuilder().getVoidPtrTy(), + callBeginCatch(cgf, ehToken, {}, cgf.getBuilder().getVoidPtrTy(), /*endMightThrow=*/true); return; } diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp index abdc32951f857..771203213dc49 100644 --- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp @@ -395,13 +395,82 @@ void ItaniumEHLowering::lowerEhInitiate( builder, op.getLoc(), mlir::FlatSymbolRefAttr::get(beginCatchFunc), u8PtrType, mlir::ValueRange{exnPtr}); mlir::Value castResult = callOp.getResult(); - mlir::Type expectedPtrType = op.getExnPtr().getType(); - if (castResult.getType() != expectedPtrType) - castResult = - cir::CastOp::create(builder, op.getLoc(), expectedPtrType, - cir::CastKind::bitcast, callOp.getResult()); - op.getExnPtr().replaceAllUsesWith(castResult); + + mlir::TypedValue<cir::PointerType> exnPtrAddr = op.getExnPtr(); + if (exnPtrAddr) { + mlir::Type expectedPtrType = op.getExnPtr().getType(); + if (castResult.getType() != expectedPtrType) + castResult = + cir::CastOp::create(builder, op.getLoc(), expectedPtrType, + cir::CastKind::bitcast, callOp.getResult()); + op.getExnPtr().replaceAllUsesWith(castResult); + + switch (op.getKind()) { + case cir::BeginCatchKind::LoadStore: { + auto loadExnPtr = + cir::LoadOp::create(builder, op->getLoc(), castResult); + cir::StoreOp::create(builder, op.getLoc(), loadExnPtr, exnPtrAddr, + {}, {}, {}, {}); + break; + } + case cir::BeginCatchKind::Store: { + mlir::Type exceptionType = + mlir::cast<cir::PointerType>(expectedPtrType).getPointee(); + castResult = + cir::CastOp::create(builder, op.getLoc(), exceptionType, + cir::CastKind::bitcast, callOp.getResult()); + cir::StoreOp::create(builder, op.getLoc(), castResult, exnPtrAddr, + {}, {}, {}, {}); + break; + } + case cir::BeginCatchKind::Memcopy: { + cir::CopyOp::create(builder, op->getLoc(), exnPtrAddr, castResult); + break; + } + case cir::BeginCatchKind::Reference: { + mlir::Type exceptionType = + mlir::cast<cir::PointerType>(expectedPtrType).getPointee(); + mlir::Type exceptionTypePointee = + mlir::cast<cir::PointerType>(exceptionType).getPointee(); + bool isPointer = mlir::isa<cir::PointerType>(exceptionTypePointee); + if (isPointer) { + cir::FuncOp parentFunc = op->getParentOfType<cir::FuncOp>(); + mlir::Block *entryBlock = &parentFunc.getRegion().front(); + + mlir::Value exnPtrTmp; + { + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToStart(entryBlock); + exnPtrTmp = cir::AllocaOp::create( + builder, op->getLoc(), expectedPtrType, exceptionType, + "exn.byref.tmp", builder.getI64IntegerAttr(8)); + } + + castResult = cir::CastOp::create( + builder, op.getLoc(), exceptionType, cir::CastKind::bitcast, + callOp.getResult()); + + cir::StoreOp::create(builder, op.getLoc(), castResult, exnPtrTmp, + {}, {}, {}, {}); + + castResult = exnPtrTmp; + } + + castResult = + cir::CastOp::create(builder, op.getLoc(), exceptionType, + cir::CastKind::bitcast, castResult); + cir::StoreOp::create(builder, op.getLoc(), castResult, exnPtrAddr, + {}, {}, {}, {}); + break; + } + case cir::BeginCatchKind::Default: { + break; + } + } + } + op.erase(); + // Extra load and store } else if (auto op = mlir::dyn_cast<cir::EhDispatchOp>(user)) { // Read catch types from the dispatch and set them on the inflight op. mlir::ArrayAttr catchTypes = op.getCatchTypesAttr(); diff --git a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp index 3827275bfc1be..2e93d096237af 100644 --- a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp +++ b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp @@ -36,7 +36,7 @@ void test_catch_all_with_cleanup() { // CIR: } // CIR: cir.yield // CIR: } catch all (%{{.*}}: !cir.eh_token {{.*}}) { -// CIR: %{{.*}}, %{{.*}} = cir.begin_catch +// CIR: %{{.*}} = cir.begin_catch // CIR: cir.cleanup.scope { // CIR: cir.yield // CIR: } cleanup all { @@ -88,7 +88,7 @@ void test_catch_all_with_cleanup() { // // Catch handler. // CIR-FLAT: ^[[CATCH_ALL]](%[[CA_ET:.*]]: !cir.eh_token): -// CIR-FLAT: %{{.*}}, %{{.*}} = cir.begin_catch %[[CA_ET]] +// CIR-FLAT: %{{.*}} = cir.begin_catch default %[[CA_ET]] // CIR-FLAT: cir.end_catch // CIR-FLAT: cir.return @@ -161,10 +161,8 @@ void test_catch_all_and_specific_with_cleanup() { // CIR: } // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) { -// CIR: %{{.*}}, %[[EXN:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CIR: %{{.*}} = cir.begin_catch load_store %{{.*}} : !cir.eh_token, %[[E]] : !cir.ptr<!s32i> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: cir.load{{.*}} %[[EXN]] : !cir.ptr<!s32i>, !s32i -// CIR: cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i> // CIR: cir.yield // CIR: } cleanup all { // CIR: cir.end_catch %{{.*}} : !cir.catch_token @@ -172,7 +170,7 @@ void test_catch_all_and_specific_with_cleanup() { // CIR: } // CIR: cir.yield // CIR: } catch all (%{{.*}}: !cir.eh_token {{.*}}) { -// CIR: %{{.*}}, %{{.*}} = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CIR: %{{.*}} = cir.begin_catch default %{{.*}} : !cir.eh_token -> !cir.catch_token // CIR: cir.cleanup.scope { // CIR: cir.yield // CIR: } cleanup all { @@ -226,15 +224,13 @@ void test_catch_all_and_specific_with_cleanup() { // // Catch (int): bind e, end_catch, merge to return. // CIR-FLAT: ^[[CATCH_INT]](%{{.*}}: !cir.eh_token): -// CIR-FLAT: %{{.*}}, %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) -// CIR-FLAT: cir.load{{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i -// CIR-FLAT: cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i> +// CIR-FLAT: %{{.*}}= cir.begin_catch load_store %{{.*}} : !cir.eh_token, %[[E]] : !cir.ptr<!s32i> -> !cir.catch_token // CIR-FLAT: cir.end_catch %{{.*}} : !cir.catch_token // CIR-FLAT: cir.br ^{{.*}} // // Catch-all handler. // CIR-FLAT: ^[[CATCH_ALL]](%[[CA_ET:.*]]: !cir.eh_token): -// CIR-FLAT: %{{.*}}, %{{.*}} = cir.begin_catch %[[CA_ET]] +// CIR-FLAT: %{{.*}} = cir.begin_catch default %[[CA_ET]] // CIR-FLAT: cir.br ^{{.*}} // CIR-FLAT: cir.end_catch %{{.*}} : !cir.catch_token // CIR-FLAT: cir.br ^{{.*}} diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp index fd8b9294c9f92..1679a75ffe476 100644 --- a/clang/test/CIR/CodeGen/try-catch.cpp +++ b/clang/test/CIR/CodeGen/try-catch.cpp @@ -210,7 +210,7 @@ void call_function_inside_try_catch_all() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch all (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch default %[[EH_TOKEN]] : !cir.eh_token -> !cir.catch_token // CIR: cir.cleanup.scope { // CIR: cir.yield // CIR: } cleanup {{.*}} { @@ -296,10 +296,8 @@ void call_function_inside_try_catch_with_exception_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch load_store %[[EH_TOKEN]] : !cir.eh_token, %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i -// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i> // CIR: cir.yield // CIR: } cleanup {{.*}} { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -340,10 +338,10 @@ void call_function_inside_try_catch_with_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) -// LLVM: br label %[[CATCH_BODY:.*]] -// LLVM: [[CATCH_BODY]]: // LLVM: %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4 // LLVM: store i32 %[[LOAD]], ptr {{.*}}, align 4 +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -414,9 +412,8 @@ void call_function_inside_try_catch_with_ref_exception_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch reference %{{.*}} : !cir.eh_token, %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: cir.store {{.*}} %[[EXN_PTR]], %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> // CIR: cir.yield // CIR: } cleanup all { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -457,9 +454,9 @@ void call_function_inside_try_catch_with_ref_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) +// LLVM: store ptr %[[TOKEN]], ptr %{{.*}}, align 8 // LLVM: br label %[[CATCH_BODY:.*]] // LLVM: [[CATCH_BODY]]: -// LLVM: store ptr %[[TOKEN]], ptr %{{.*}}, align 8 // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -529,10 +526,8 @@ void call_function_inside_try_catch_with_complex_exception_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTICi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.complex<!s32i>>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch load_store %[[EH_TOKEN]] : !cir.eh_token, %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.complex<!s32i>> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> -// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> // CIR: cir.yield // CIR: } cleanup {{.*}} { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -573,10 +568,10 @@ void call_function_inside_try_catch_with_complex_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) -// LLVM: br label %[[CATCH_BODY:.*]] -// LLVM: [[CATCH_BODY]]: // LLVM: %[[LOAD:.*]] = load { i32, i32 }, ptr %[[TOKEN]], align 4 // LLVM: store { i32, i32 } %[[LOAD]], ptr {{.*}}, align 4 +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -653,9 +648,8 @@ void call_function_inside_try_catch_with_array_exception_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch store %[[EH_TOKEN]] : !cir.eh_token, %[[E_ADDR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: cir.store {{.*}} %[[EXN_PTR]], %[[E_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> // CIR: cir.yield // CIR: } cleanup {{.*}} { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -696,9 +690,9 @@ void call_function_inside_try_catch_with_array_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) +// LLVM: store ptr %[[TOKEN]], ptr {{.*}}, align 8 // LLVM: br label %[[CATCH_BODY:.*]] // LLVM: [[CATCH_BODY]]: -// LLVM: store ptr %[[TOKEN]], ptr {{.*}}, align 8 // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -769,10 +763,8 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch load_store %[[EH_TOKEN]] : !cir.eh_token, %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i -// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i> // CIR: cir.yield // CIR: } cleanup {{.*}} { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -780,7 +772,7 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() { // CIR: } // CIR: cir.yield // CIR: } catch all (%[[EH_TOKEN2:.*]]: !cir.eh_token{{.*}}) { -// CIR: %[[CATCH_TOKEN2:.*]], %{{.*}} = cir.begin_catch %[[EH_TOKEN2]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CIR: %[[CATCH_TOKEN2:.*]] = cir.begin_catch default %[[EH_TOKEN2]] : !cir.eh_token -> !cir.catch_token // CIR: cir.cleanup.scope { // CIR: cir.yield // CIR: } cleanup {{.*}} { @@ -820,10 +812,10 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) -// LLVM: br label %[[CATCH_BODY:.*]] -// LLVM: [[CATCH_BODY]]: // LLVM: %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4 // LLVM: store i32 %[[LOAD]], ptr {{.*}}, align 4 +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -912,7 +904,7 @@ void cleanup_inside_try_body() { // CIR: } // CIR: cir.yield // CIR: } catch all (%[[TOKEN:.*]]: !cir.eh_token {{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch default %[[TOKEN]] : !cir.eh_token -> !cir.catch_token // CIR: cir.cleanup.scope { // CIR: cir.yield // CIR: } cleanup all { @@ -1016,9 +1008,8 @@ void call_function_inside_try_catch_with_aggregate_exception_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef}) // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTI11CustomError> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!rec_CustomError>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch memcopy {{.*}} : !cir.eh_token, %[[E_ADDR]] : !cir.ptr<!rec_CustomError> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: cir.copy %[[EXN_PTR]] to %[[E_ADDR]] : !cir.ptr<!rec_CustomError> // CIR: cir.yield // CIR: } cleanup all { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -1059,9 +1050,9 @@ void call_function_inside_try_catch_with_aggregate_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) +// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %{{.*}}, ptr %[[TOKEN]], i64 4, i1 false) // LLVM: br label %[[CATCH_BODY:.*]] // LLVM: [[CATCH_BODY]]: -// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %{{.*}}, ptr %[[TOKEN]], i64 4, i1 false) // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -1131,16 +1122,12 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() { // CIR: cir.func {{.*}} @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev(){{.*}} personality(@__gxx_personality_v0) { // CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>, ["ref_ptr", const] -// CIR: %[[EXN_BYREF_TMP:.*]] = cir.alloca !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>, ["exn.byref.tmp"] // CIR: cir.try { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef}) // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIP6Record> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token {{.*}}) { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!rec_Record>>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch reference %[[EH_TOKEN]] : !cir.eh_token, %[[E_ADDR]] : !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: %[[EXN_PTR_REC_PTR:.*]] = cir.cast bitcast %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!rec_Record>> -> !cir.ptr<!rec_Record> -// CIR: cir.store {{.*}} %[[EXN_PTR_REC_PTR]], %[[EXN_BYREF_TMP]] : !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>> -// CIR: cir.store {{.*}} %[[EXN_BYREF_TMP]], %[[E_ADDR]] : !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>> // CIR: cir.yield // CIR: } cleanup all { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -1153,8 +1140,8 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() { // CIR: } // LLVM: define {{.*}} void @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev() {{.*}} personality ptr @__gxx_personality_v0 -// LLVM: %[[E_ADDR:.*]] = alloca ptr // LLVM: %[[EXN_BYREF_TMP:.*]] = alloca ptr +// LLVM: %[[E_ADDR:.*]] = alloca ptr // LLVM: br label %[[TRY_SCOPE:.*]] // LLVM: [[TRY_SCOPE]]: // LLVM: br label %[[TRY_BEGIN:.*]] @@ -1183,10 +1170,10 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) -// LLVM: br label %[[CATCH_BODY:.*]] -// LLVM: [[CATCH_BODY]]: // LLVM: store ptr %[[TOKEN]], ptr %[[EXN_BYREF_TMP]], align 8 // LLVM: store ptr %[[EXN_BYREF_TMP]], ptr %[[E_ADDR]], align 8 +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() @@ -1258,10 +1245,8 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() { // CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef}) // CIR: cir.yield // CIR: } catch [type #cir.global_view<@_ZTIM6Recordi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}} { -// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s64i>) +// CIR: %[[CATCH_TOKEN:.*]] = cir.begin_catch load_store %{{.*}} : !cir.eh_token, %[[E_ADDR]] : !cir.ptr<!s64i> -> !cir.catch_token // CIR: cir.cleanup.scope { -// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s64i>, !s64i -// CIR: cir.store {{.*}} %[[TMP]], %[[E_ADDR]] : !s64i, !cir.ptr<!s64i> // CIR: cir.yield // CIR: } cleanup all { // CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token @@ -1302,10 +1287,10 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() { // LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] // LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) -// LLVM: br label %[[CATCH_BODY:.*]] -// LLVM: [[CATCH_BODY]]: // LLVM: %[[LOAD:.*]] = load i64, ptr %[[TOKEN]], align 8 // LLVM: store i64 %[[LOAD]], ptr {{.*}}, align 8 +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: // LLVM: br label %[[END_CATCH:.*]] // LLVM: [[END_CATCH]]: // LLVM: call void @__cxa_end_catch() diff --git a/clang/test/CIR/IR/catch-param.cir b/clang/test/CIR/IR/catch-param.cir index 3734917c35877..6f1fb08cb66ae 100644 --- a/clang/test/CIR/IR/catch-param.cir +++ b/clang/test/CIR/IR/catch-param.cir @@ -10,7 +10,7 @@ cir.func @begin_catch_inside_catch() { cir.try { cir.yield } catch all (%eh_token : !cir.eh_token) { - %catch_token, %exception = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) + %catch_token = cir.begin_catch default %eh_token : !cir.eh_token -> !cir.catch_token cir.cleanup.scope { cir.yield } cleanup eh { @@ -28,7 +28,7 @@ cir.func @begin_catch_inside_catch() { // CHECK: cir.try { // CHECK: cir.yield // CHECK: } catch all (%[[EH_TOKEN:.*]]: !cir.eh_token) { -// CHECK: %[[CATCH_TOKEN:.*]], %[[EXCEPTION:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CHECK: %[[CATCH_TOKEN:.*]] = cir.begin_catch default %[[EH_TOKEN]] : !cir.eh_token -> !cir.catch_token // CHECK: cir.cleanup.scope { // CHECK: cir.yield // CHECK: } cleanup eh { diff --git a/clang/test/CIR/IR/eh-flat.cir b/clang/test/CIR/IR/eh-flat.cir index c6799dcda766c..b6aab9099f4bc 100644 --- a/clang/test/CIR/IR/eh-flat.cir +++ b/clang/test/CIR/IR/eh-flat.cir @@ -148,26 +148,28 @@ cir.func @cleanup_ops(%eh_token: !cir.eh_token) { // Test cir.begin_catch and cir.end_catch cir.func @catch_ops(%eh_token: !cir.eh_token) { - %catch_token, %exn_ptr = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) + %exn_addr = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64} + %catch_token = cir.begin_catch load_store %eh_token : !cir.eh_token, %exn_addr : !cir.ptr<!s32i> -> !cir.catch_token cir.end_catch %catch_token : !cir.catch_token cir.return } // CHECK: cir.func @catch_ops(%arg0: !cir.eh_token) { -// CHECK: %[[CATCH:.*]], %[[EXN:.*]] = cir.begin_catch %arg0 : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CHECK: %[[EXN_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64} +// CHECK: %[[CATCH:.*]] = cir.begin_catch load_store %arg0 : !cir.eh_token, %[[EXN_ADDR]] : !cir.ptr<!s32i> -> !cir.catch_token // CHECK: cir.end_catch %[[CATCH]] : !cir.catch_token // CHECK: cir.return // CHECK: } // Test cir.begin_catch with void pointer (catch all) cir.func @catch_all_ops(%eh_token: !cir.eh_token) { - %catch_token, %exn_ptr = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) + %catch_token = cir.begin_catch default %eh_token : !cir.eh_token -> !cir.catch_token cir.end_catch %catch_token : !cir.catch_token cir.return } // CHECK: cir.func @catch_all_ops(%arg0: !cir.eh_token) { -// CHECK: %[[CATCH:.*]], %[[EXN:.*]] = cir.begin_catch %arg0 : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CHECK: %[[CATCH:.*]] = cir.begin_catch default %arg0 : !cir.eh_token -> !cir.catch_token // CHECK: cir.end_catch %[[CATCH]] : !cir.catch_token // CHECK: cir.return // CHECK: } @@ -177,6 +179,7 @@ cir.func private @mayThrow() -> () cir.func private @destructor() -> () cir.func @complete_example() { + %exn_addr = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64} cir.try_call @mayThrow() ^bb1, ^bb2 : () -> () ^bb1: // Normal return cir.return @@ -190,16 +193,17 @@ cir.func @complete_example() { catch_all : ^catch_all ] ^catch_int: - %catch_token, %exn_ptr = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) + %catch_token = cir.begin_catch load_store %eh_token : !cir.eh_token, %exn_addr : !cir.ptr<!s32i> -> !cir.catch_token cir.end_catch %catch_token : !cir.catch_token cir.return ^catch_all: - %catch_token2, %exn_ptr2 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) + %catch_token2= cir.begin_catch default %eh_token : !cir.eh_token -> !cir.catch_token cir.end_catch %catch_token2 : !cir.catch_token cir.return } // CHECK: cir.func @complete_example() +// CHECK: %[[EXN_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] // CHECK: cir.try_call @mayThrow() ^bb1, ^bb2 : () -> () // CHECK: ^bb1: // CHECK: cir.return @@ -213,11 +217,11 @@ cir.func @complete_example() { // CHECK: catch_all : ^bb4 // CHECK: ] // CHECK: ^bb3: -// CHECK: %[[CATCH1:.*]], %{{.*}} = cir.begin_catch %[[EH]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CHECK: %[[CATCH1:.*]] = cir.begin_catch load_store %[[EH]] : !cir.eh_token, %[[EXN_ADDR]] : !cir.ptr<!s32i> -> !cir.catch_token // CHECK: cir.end_catch %[[CATCH1]] : !cir.catch_token // CHECK: cir.return // CHECK: ^bb4: -// CHECK: %[[CATCH2:.*]], %{{.*}} = cir.begin_catch %[[EH]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CHECK: %[[CATCH2:.*]] = cir.begin_catch default %[[EH]] : !cir.eh_token -> !cir.catch_token // CHECK: cir.end_catch %[[CATCH2]] : !cir.catch_token // CHECK: cir.return // CHECK: } diff --git a/clang/test/CIR/IR/try-catch.cir b/clang/test/CIR/IR/try-catch.cir index 203ec340d7f6e..d865038198bf5 100644 --- a/clang/test/CIR/IR/try-catch.cir +++ b/clang/test/CIR/IR/try-catch.cir @@ -14,7 +14,7 @@ cir.func dso_local @empty_try_block_with_catch_all() { cir.try { cir.yield } catch all (%eh_token : !cir.eh_token) { - %catch_token, %0 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) + %catch_token= cir.begin_catch default %eh_token : !cir.eh_token -> !cir.catch_token cir.cleanup.scope { cir.yield } cleanup eh { @@ -32,7 +32,7 @@ cir.func dso_local @empty_try_block_with_catch_all() { // CHECK: cir.try { // CHECK: cir.yield // CHECK: } catch all (%[[EH_TOKEN:.*]]: !cir.eh_token) { -// CHECK: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CHECK: %[[CATCH_TOKEN:.*]] = cir.begin_catch default %[[EH_TOKEN]] : !cir.eh_token -> !cir.catch_token // CHECK: cir.cleanup.scope { // CHECK: cir.yield // CHECK: } cleanup eh { @@ -68,11 +68,13 @@ cir.func dso_local @empty_try_block_with_catch_unwind() { // CHECK: } cir.func dso_local @empty_try_block_with_catch_ist() { + %exn_addr = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64} + %exn_addr_2 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["e2"] {alignment = 4 : i64} cir.scope { cir.try { cir.yield } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) { - %catch_token, %0 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) + %catch_token = cir.begin_catch load_store %eh_token : !cir.eh_token, %exn_addr : !cir.ptr<!s32i> -> !cir.catch_token cir.cleanup.scope { cir.yield } cleanup eh { @@ -81,7 +83,7 @@ cir.func dso_local @empty_try_block_with_catch_ist() { } cir.yield } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] (%eh_token_1 : !cir.eh_token) { - %catch_token_1, %1 = cir.begin_catch %eh_token_1 : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!u8i>>) + %catch_token_1 = cir.begin_catch store %eh_token_1 : !cir.eh_token, %exn_addr_2 : !cir.ptr<!cir.ptr<!u8i>> -> !cir.catch_token cir.cleanup.scope { cir.yield } cleanup eh { @@ -97,11 +99,13 @@ cir.func dso_local @empty_try_block_with_catch_ist() { } // CHECK: cir.func dso_local @empty_try_block_with_catch_ist() { +// CHECK: %[[EXN_ADDR1:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] +// CHECK: %[[EXN_ADDR2:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>> // CHECK: cir.scope { // CHECK: cir.try { // CHECK: cir.yield // CHECK: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH1:.*]]: !cir.eh_token) { -// CHECK: %[[CT1:.*]], %{{.*}} = cir.begin_catch %[[EH1]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>) +// CHECK: %[[CT1:.*]] = cir.begin_catch load_store %[[EH1]] : !cir.eh_token, %[[EXN_ADDR1]] : !cir.ptr<!s32i> -> !cir.catch_token // CHECK: cir.cleanup.scope { // CHECK: cir.yield // CHECK: } cleanup eh { @@ -110,7 +114,7 @@ cir.func dso_local @empty_try_block_with_catch_ist() { // CHECK: } // CHECK: cir.yield // CHECK: } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] (%[[EH2:.*]]: !cir.eh_token) { -// CHECK: %[[CT2:.*]], %{{.*}} = cir.begin_catch %[[EH2]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!u8i>>) +// CHECK: %[[CT2:.*]] = cir.begin_catch store %[[EH2]] : !cir.eh_token, %[[EXN_ADDR2]] : !cir.ptr<!cir.ptr<!u8i>> -> !cir.catch_token // CHECK: cir.cleanup.scope { // CHECK: cir.yield // CHECK: } cleanup eh { >From 1868e1146abcecd649a601c7366a27b2e07e7711 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Fri, 10 Apr 2026 19:55:04 +0200 Subject: [PATCH 2/2] Move initCatchParam out of CIRGenItaniumCXXABI --- clang/lib/CIR/CodeGen/CIRGenCXXABI.h | 4 - clang/lib/CIR/CodeGen/CIRGenException.cpp | 200 +++++++++++++++++- clang/lib/CIR/CodeGen/CIRGenFunction.h | 3 + clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 200 ------------------ 4 files changed, 202 insertions(+), 205 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index 614d62fda44a5..bb100f7afd929 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -134,10 +134,6 @@ class CIRGenCXXABI { virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0; - virtual void emitBeginCatch(CIRGenFunction &cgf, - const CXXCatchStmt *catchStmt, - mlir::Value ehToken) = 0; - virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty) = 0; diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index c80f292553a1c..e2bc3aa75d784 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -273,6 +273,204 @@ void CIRGenFunction::addCatchHandlerAttr( } } +namespace { +/// From traditional LLVM, useful info for LLVM lowering support: +/// A cleanup to call __cxa_end_catch. In many cases, the caught +/// exception type lets us state definitively that the thrown exception +/// type does not have a destructor. In particular: +/// - Catch-alls tell us nothing, so we have to conservatively +/// assume that the thrown exception might have a destructor. +/// - Catches by reference behave according to their base types. +/// - Catches of non-record types will only trigger for exceptions +/// of non-record types, which never have destructors. +/// - Catches of record types can trigger for arbitrary subclasses +/// of the caught type, so we have to assume the actual thrown +/// exception type might have a throwing destructor, even if the +/// caught type's destructor is trivial or nothrow. +struct CallEndCatch final : EHScopeStack::Cleanup { + CallEndCatch(bool mightThrow, mlir::Value catchToken) + : mightThrow(mightThrow), catchToken(catchToken) {} + bool mightThrow; + mlir::Value catchToken; + + void emit(CIRGenFunction &cgf, Flags flags) override { + // Traditional LLVM codegen would emit a call to __cxa_end_catch + // here. For CIR, just let it pass since the cleanup is going + // to be emitted on a later pass when lowering the catch region. + // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM)); + cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken); + cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc); + } +}; +} // namespace + +static mlir::Value +callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Value exnPtr, + mlir::Type exnPtrTy, bool endMightThrow, + cir::BeginCatchKind kind = cir::BeginCatchKind::Default) { + auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext()); + auto beginCatch = cir::BeginCatchOp::create( + cgf.getBuilder(), cgf.getBuilder().getUnknownLoc(), catchTokenTy, ehToken, + exnPtr, kind); + + cgf.ehStack.pushCleanup<CallEndCatch>( + NormalAndEHCleanup, + endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor, + beginCatch.getCatchToken()); + + return beginCatch.getExnPtr(); +} + +/// A "special initializer" callback for initializing a catch +/// parameter during catch initialization. +static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, + const VarDecl &catchParam, Address paramAddr, + SourceLocation loc) { + CanQualType catchType = + cgf.cgm.getASTContext().getCanonicalType(catchParam.getType()); + mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); + + // If we're catching by reference, we can just cast the object + // pointer to the appropriate pointer. + if (isa<ReferenceType>(catchType)) { + QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType(); + bool endCatchMightThrow = caughtType->isRecordType(); + + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, + endCatchMightThrow, cir::BeginCatchKind::Reference); + + // We have no way to tell the personality function that we're + // catching by reference, so if we're catching a pointer, + // __cxa_begin_catch will actually return that pointer by value. + if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) { + QualType pointeeType = pt->getPointeeType(); + // When catching by reference, generally we should just ignore + // this by-value pointer and use the exception object instead. + if (!pointeeType->isRecordType()) { + cgf.cgm.errorNYI(loc, + "initCatchParam: catching a pointer of non-record"); + } + } + 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()) { + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, + /*endMightThrow=*/false, cir::BeginCatchKind::Store); + switch (catchType.getQualifiers().getObjCLifetime()) { + case Qualifiers::OCL_Strong: + cgf.cgm.errorNYI(loc, + "initCatchParam: PointerRepresentation OCL_Strong"); + return; + + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation " + "OCL_ExplicitNone & OCL_Autoreleasing"); + return; + + case Qualifiers::OCL_None: + return; + + case Qualifiers::OCL_Weak: + cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak"); + return; + } + + llvm_unreachable("bad ownership qualifier!"); + } + + // Otherwise, it returns a pointer into the exception object. + mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), + cgf.getBuilder().getPointerTo(cirCatchTy), + /*endMightThrow=*/false, cir::BeginCatchKind::LoadStore); + return; + } + + assert(isa<RecordType>(catchType) && "unexpected catch type!"); + + // Check for a copy expression. If we don't have a copy expression, + // that means a trivial copy is okay. + const Expr *copyExpr = catchParam.getInit(); + if (!copyExpr) { + mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy); + callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchPtrTy, + /*endMightThrow=*/true, cir::BeginCatchKind::Memcopy); + return; + } + + cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy"); +} + +/// Begins a catch statement by initializing the catch variable and +/// calling __cxa_begin_catch. +void CIRGenFunction::emitBeginCatch(CIRGenFunction &cgf, + const CXXCatchStmt *catchStmt, + mlir::Value ehToken) { + // We have to be very careful with the ordering of cleanups here: + // C++ [except.throw]p4: + // The destruction [of the exception temporary] occurs + // immediately after the destruction of the object declared in + // the exception-declaration in the handler. + // + // So the precise ordering is: + // 1. Construct catch variable. + // 2. __cxa_begin_catch + // 3. Enter __cxa_end_catch cleanup + // 4. Enter dtor cleanup + // + // We do this by using a slightly abnormal initialization process. + // Delegation sequence: + // - ExitCXXTryStmt opens a RunCleanupsScope + // - EmitAutoVarAlloca creates the variable and debug info + // - InitCatchParam initializes the variable from the exception + // - CallBeginCatch calls __cxa_begin_catch + // - CallBeginCatch enters the __cxa_end_catch cleanup + // - EmitAutoVarCleanups enters the variable destructor cleanup + // - EmitCXXTryStmt emits the code for the catch body + // - EmitCXXTryStmt close the RunCleanupsScope + + VarDecl *catchParam = catchStmt->getExceptionDecl(); + if (!catchParam) { + callBeginCatch(cgf, ehToken, {}, cgf.getBuilder().getVoidPtrTy(), + /*endMightThrow=*/true); + return; + } + + 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, ehToken, *catchParam, var.getObjectAddress(cgf), + catchStmt->getBeginLoc()); + cgf.emitAutoVarCleanups(var); +} + mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback) { @@ -384,7 +582,7 @@ CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s, // Initialize the catch variable. // TODO(cir): Move this out of CXXABI. assert(!cir::MissingFeatures::currentFuncletPad()); - cgm.getCXXABI().emitBeginCatch(*this, catchStmt, ehToken); + emitBeginCatch(*this, catchStmt, ehToken); // Emit the PGO counter increment. assert(!cir::MissingFeatures::incrementProfileCounter()); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 88c7996eab569..aa25ad9ca5905 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1635,6 +1635,9 @@ class CIRGenFunction : public CIRGenTypeCache { virtual ~cxxTryBodyEmitter() = default; }; + void emitBeginCatch(CIRGenFunction &cgf, const CXXCatchStmt *catchStmt, + mlir::Value ehToken); + mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback); mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s); diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 471c48da8d2b8..7e48277688473 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -82,8 +82,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI { void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override; void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override; - void emitBeginCatch(CIRGenFunction &cgf, const CXXCatchStmt *catchStmt, - mlir::Value ehToken) override; bool useThunkForDtorVariant(const CXXDestructorDecl *dtor, CXXDtorType dt) const override { @@ -2492,204 +2490,6 @@ Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf, return Address(finalPtr, newPtr.getElementType(), finalAlignment); } -namespace { -/// From traditional LLVM, useful info for LLVM lowering support: -/// A cleanup to call __cxa_end_catch. In many cases, the caught -/// exception type lets us state definitively that the thrown exception -/// type does not have a destructor. In particular: -/// - Catch-alls tell us nothing, so we have to conservatively -/// assume that the thrown exception might have a destructor. -/// - Catches by reference behave according to their base types. -/// - Catches of non-record types will only trigger for exceptions -/// of non-record types, which never have destructors. -/// - Catches of record types can trigger for arbitrary subclasses -/// of the caught type, so we have to assume the actual thrown -/// exception type might have a throwing destructor, even if the -/// caught type's destructor is trivial or nothrow. -struct CallEndCatch final : EHScopeStack::Cleanup { - CallEndCatch(bool mightThrow, mlir::Value catchToken) - : mightThrow(mightThrow), catchToken(catchToken) {} - bool mightThrow; - mlir::Value catchToken; - - void emit(CIRGenFunction &cgf, Flags flags) override { - // Traditional LLVM codegen would emit a call to __cxa_end_catch - // here. For CIR, just let it pass since the cleanup is going - // to be emitted on a later pass when lowering the catch region. - // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM)); - cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken); - cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc); - } -}; -} // namespace - -static mlir::Value -callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Value exnPtr, - mlir::Type exnPtrTy, bool endMightThrow, - cir::BeginCatchKind kind = cir::BeginCatchKind::Default) { - auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext()); - auto beginCatch = cir::BeginCatchOp::create( - cgf.getBuilder(), cgf.getBuilder().getUnknownLoc(), catchTokenTy, ehToken, - exnPtr, kind); - - cgf.ehStack.pushCleanup<CallEndCatch>( - NormalAndEHCleanup, - endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor, - beginCatch.getCatchToken()); - - return beginCatch.getExnPtr(); -} - -/// A "special initializer" callback for initializing a catch -/// parameter during catch initialization. -static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, - const VarDecl &catchParam, Address paramAddr, - SourceLocation loc) { - CanQualType catchType = - cgf.cgm.getASTContext().getCanonicalType(catchParam.getType()); - mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); - - // If we're catching by reference, we can just cast the object - // pointer to the appropriate pointer. - if (isa<ReferenceType>(catchType)) { - QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType(); - bool endCatchMightThrow = caughtType->isRecordType(); - - callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, - endCatchMightThrow, cir::BeginCatchKind::Reference); - - // We have no way to tell the personality function that we're - // catching by reference, so if we're catching a pointer, - // __cxa_begin_catch will actually return that pointer by value. - if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) { - QualType pointeeType = pt->getPointeeType(); - // When catching by reference, generally we should just ignore - // this by-value pointer and use the exception object instead. - if (!pointeeType->isRecordType()) { - cgf.cgm.errorNYI(loc, - "initCatchParam: catching a pointer of non-record"); - } - } - 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()) { - callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchTy, - /*endMightThrow=*/false, cir::BeginCatchKind::Store); - switch (catchType.getQualifiers().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - cgf.cgm.errorNYI(loc, - "initCatchParam: PointerRepresentation OCL_Strong"); - return; - - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation " - "OCL_ExplicitNone & OCL_Autoreleasing"); - return; - - case Qualifiers::OCL_None: - return; - - case Qualifiers::OCL_Weak: - cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak"); - return; - } - - llvm_unreachable("bad ownership qualifier!"); - } - - // Otherwise, it returns a pointer into the exception object. - mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType); - callBeginCatch(cgf, ehToken, paramAddr.getPointer(), - cgf.getBuilder().getPointerTo(cirCatchTy), - /*endMightThrow=*/false, cir::BeginCatchKind::LoadStore); - return; - } - - assert(isa<RecordType>(catchType) && "unexpected catch type!"); - - // Check for a copy expression. If we don't have a copy expression, - // that means a trivial copy is okay. - const Expr *copyExpr = catchParam.getInit(); - if (!copyExpr) { - mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy); - callBeginCatch(cgf, ehToken, paramAddr.getPointer(), cirCatchPtrTy, - /*endMightThrow=*/true, cir::BeginCatchKind::Memcopy); - return; - } - - cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy"); -} - -/// Begins a catch statement by initializing the catch variable and -/// calling __cxa_begin_catch. -void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf, - const CXXCatchStmt *catchStmt, - mlir::Value ehToken) { - // We have to be very careful with the ordering of cleanups here: - // C++ [except.throw]p4: - // The destruction [of the exception temporary] occurs - // immediately after the destruction of the object declared in - // the exception-declaration in the handler. - // - // So the precise ordering is: - // 1. Construct catch variable. - // 2. __cxa_begin_catch - // 3. Enter __cxa_end_catch cleanup - // 4. Enter dtor cleanup - // - // We do this by using a slightly abnormal initialization process. - // Delegation sequence: - // - ExitCXXTryStmt opens a RunCleanupsScope - // - EmitAutoVarAlloca creates the variable and debug info - // - InitCatchParam initializes the variable from the exception - // - CallBeginCatch calls __cxa_begin_catch - // - CallBeginCatch enters the __cxa_end_catch cleanup - // - EmitAutoVarCleanups enters the variable destructor cleanup - // - EmitCXXTryStmt emits the code for the catch body - // - EmitCXXTryStmt close the RunCleanupsScope - - VarDecl *catchParam = catchStmt->getExceptionDecl(); - if (!catchParam) { - callBeginCatch(cgf, ehToken, {}, cgf.getBuilder().getVoidPtrTy(), - /*endMightThrow=*/true); - return; - } - - 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, ehToken, *catchParam, var.getObjectAddress(cgf), - catchStmt->getBeginLoc()); - cgf.emitAutoVarCleanups(var); -} - bool CIRGenItaniumCXXABI::hasAnyUnusedVirtualInlineFunction( const CXXRecordDecl *rd) const { const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
