llvm-project/clang/test/CIR/CodeGen/try-catch-tmp.cpp
Andy Kaylor 375d65ee8d
[CIR] Implement EH lowering to Itanium form and LLVM IR (#184386)
This introduces a new pass to lower from a flattened, target-independent
form of CIR to a form that uses Itanium-specific representation for
exception handling. It also includes a small amount of code needed to
lower the Itanium form to LLVM IR.

Substantial amounts of this PR were created using agentic AI tools, but
I have carefully reviewed the code, comments, and tests and made changes
as needed.
2026-03-03 20:09:49 +00:00

696 lines
33 KiB
C++

// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
// TODO(cir): Merge this with try-catch.cpp.
int division();
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()
// 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: cir.cleanup.scope {
// CIR: cir.yield
// CIR: } cleanup {{.*}} {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z34call_function_inside_try_catch_allv() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr null
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[BEGIN_CATCH:.*]]
// LLVM: [[BEGIN_CATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI1]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// 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()
// OGCG: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// OGCG: [[INVOKE_CONT]]:
// OGCG: br label %[[TRY_CONT:.*]]
// OGCG: [[LANDING_PAD]]:
// OGCG: %[[LP:.*]] = landingpad { ptr, i32 }
// OGCG: catch ptr null
// OGCG: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// OGCG: store ptr %[[EXN_OBJ]], ptr %[[EXN_OBJ_ADDR]], align 8
// OGCG: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// OGCG: store i32 %[[EH_SELECTOR_VAL]], ptr %[[EH_SELECTOR_ADDR]], align 4
// OGCG: br label %[[CATCH:.*]]
// OGCG: [[CATCH]]:
// OGCG: %[[EXN_OBJ:.*]] = load ptr, ptr %[[EXN_OBJ_ADDR]], align 8
// OGCG: %[[CATCH_BEGIN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ]])
// OGCG: call void @__cxa_end_catch()
// 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()
// 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: 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
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: } unwind (%{{.*}}: !cir.eh_token{{.*}}) {
// CIR: cir.resume %{{.*}} : !cir.eh_token
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z50call_function_inside_try_catch_with_exception_typev() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr @_ZTIi
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[DISPATCH:.*]]
// LLVM: [[DISPATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
// LLVM: [[BEGIN_CATCH]]:
// 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 %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[RESUME]]:
// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// 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_complex_exception_type() {
try {
division();
} catch (int _Complex e) {
}
}
// CIR: cir.func {{.*}} @_Z58call_function_inside_try_catch_with_complex_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["e"]
// CIR: cir.try {
// 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: 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
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: } unwind (%{{.*}}: !cir.eh_token{{.*}}) {
// CIR: cir.resume %{{.*}} : !cir.eh_token
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z58call_function_inside_try_catch_with_complex_exception_typev() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr @_ZTICi
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[DISPATCH:.*]]
// LLVM: [[DISPATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTICi)
// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
// LLVM: [[BEGIN_CATCH]]:
// 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 %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[RESUME]]:
// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// OGCG: define {{.*}} void @_Z58call_function_inside_try_catch_with_complex_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, 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 @_ZTICi
// 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 @_ZTICi)
// 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: %[[EXCEPTION_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[BEGIN_CATCH]], i32 0, i32 0
// OGCG: %[[EXCEPTION_REAL:.*]] = load i32, ptr %[[EXCEPTION_REAL_PTR]], align 4
// OGCG: %[[EXCEPTION_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[BEGIN_CATCH]], i32 0, i32 1
// OGCG: %[[EXCEPTION_IMAG:.*]] = load i32, ptr %[[EXCEPTION_IMAG_PTR]], align 4
// OGCG: %[[E_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[E_ADDR]], i32 0, i32 0
// OGCG: %[[E_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[E_ADDR]], i32 0, i32 1
// OGCG: store i32 %[[EXCEPTION_REAL]], ptr %[[E_REAL_PTR]], align 4
// OGCG: store i32 %[[EXCEPTION_IMAG]], ptr %[[E_IMAG_PTR]], 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_array_exception_type() {
try {
division();
} catch (int e[]) {
}
}
// CIR: cir.func {{.*}} @_Z56call_function_inside_try_catch_with_array_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["e"]
// CIR: cir.try {
// 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: 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
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: } unwind (%{{.*}}: !cir.eh_token{{.*}}) {
// CIR: cir.resume %{{.*}} : !cir.eh_token
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z56call_function_inside_try_catch_with_array_exception_typev() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr @_ZTIPi
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[DISPATCH:.*]]
// LLVM: [[DISPATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
// LLVM: [[BEGIN_CATCH]]:
// 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 {{.*}}, align 8
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[RESUME]]:
// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// OGCG: define {{.*}} void @_Z56call_function_inside_try_catch_with_array_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 ptr, align 8
// 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 @_ZTIPi
// 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 %ehselector.slot, align 4
// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
// 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: store ptr %[[BEGIN_CATCH]], ptr %[[E_ADDR]], align 8
// 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()
// 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: 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
// CIR: cir.yield
// 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: cir.cleanup.scope {
// CIR: cir.yield
// CIR: } cleanup {{.*}} {
// CIR: cir.end_catch %[[CATCH_TOKEN2]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: catch ptr @_ZTIi
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[DISPATCH:.*]]
// LLVM: [[DISPATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[CATCH_ALL:.*]]
// LLVM: [[BEGIN_CATCH]]:
// 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 %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[CATCH_ALL]]:
// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
// LLVM: %[[TOKEN2:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI3]])
// LLVM: br label %[[CATCH_ALL_BODY:.*]]
// LLVM: [[CATCH_ALL_BODY]]:
// LLVM: br label %[[END_CATCH2:.*]]
// LLVM: [[END_CATCH2]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH2:.*]]
// LLVM: [[END_DISPATCH2]]:
// LLVM: br label %[[END_TRY2:.*]]
// LLVM: [[END_TRY2]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// 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]]
struct S {
~S();
};
void cleanup_inside_try_body() {
try {
S s;
division();
} catch (...) {
}
}
// CIR: cir.func {{.*}} @_Z23cleanup_inside_try_bodyv(){{.*}} personality(@__gxx_personality_v0) {
// CIR: cir.scope {
// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s"]
// CIR: cir.try {
// CIR: cir.cleanup.scope {
// CIR: cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.call @_ZN1SD1Ev(%[[S]])
// CIR: cir.yield
// 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: cir.cleanup.scope {
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
// CIR: cir.yield
// CIR: }
// CIR: }
// LLVM: define {{.*}} void @_Z23cleanup_inside_try_bodyv() {{.*}} personality ptr @__gxx_personality_v0
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
// LLVM: [[TRY_BEGIN]]:
// LLVM: br label %[[CLEANUP_SCOPE:.*]]
// LLVM: [[CLEANUP_SCOPE]]:
// LLVM: %[[CALL:.*]] = invoke i32 @_Z8divisionv()
// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// LLVM: [[INVOKE_CONT]]:
// LLVM: br label %[[CLEANUP:.*]]
// LLVM: [[CLEANUP]]:
// LLVM: call void @_ZN1SD1Ev(ptr {{.*}})
// LLVM: br label %[[END_CLEANUP:.*]]
// LLVM: [[END_CLEANUP]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[LANDING_PAD]]:
// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
// LLVM: cleanup
// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
// LLVM: br label %[[CLEANUP_LANDING:.*]]
// LLVM: [[CLEANUP_LANDING]]:
// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: call void @_ZN1SD1Ev(ptr {{.*}})
// LLVM: br label %[[CATCH:.*]]
// LLVM: [[CATCH]]:
// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CLEANUP_LANDING:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CLEANUP_LANDING:.*]] ]
// LLVM: br label %[[BEGIN_CATCH:.*]]
// LLVM: [[BEGIN_CATCH]]:
// LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[CATCH:.*]] ]
// LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[CATCH:.*]] ]
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
// LLVM: br label %[[END_DISPATCH:.*]]
// LLVM: [[END_DISPATCH]]:
// LLVM: br label %[[END_TRY:.*]]
// LLVM: [[END_TRY]]:
// LLVM: br label %[[TRY_CONT:.*]]
// LLVM: [[TRY_CONT]]:
// LLVM: br label %[[DONE:.*]]
// LLVM: [[DONE]]:
// LLVM: ret void
// OGCG: define {{.*}} void @_Z23cleanup_inside_try_bodyv() {{.*}} personality ptr @__gxx_personality_v0 {
// OGCG: %[[S:.*]] = alloca %struct.S
// OGCG: %[[EXN_SLOT:.*]] = alloca ptr
// OGCG: %[[EHSELECTOR_SLOT:.*]] = alloca i32
// OGCG: %[[CALL:.*]] = invoke {{.*}} i32 @_Z8divisionv()
// OGCG: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
// OGCG: [[INVOKE_CONT]]:
// OGCG: call void @_ZN1SD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[S]])
// OGCG: br label %[[TRY_CONT:.*]]
// OGCG: [[LANDING_PAD]]:
// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 }
// OGCG: catch ptr null
// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0
// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXN_SLOT]]
// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1
// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EHSELECTOR_SLOT]]
// OGCG: call void @_ZN1SD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[S]])
// OGCG: br label %[[CATCH:.*]]
// OGCG: [[CATCH]]:
// OGCG: %[[EXCEPTION:.*]] = load ptr, ptr %[[EXN_SLOT]]
// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXCEPTION]])
// OGCG: call void @__cxa_end_catch()
// OGCG: br label %[[TRY_CONT]]