diff options
Diffstat (limited to 'llvm/test/CodeGen/WebAssembly')
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/annotations.mir | 94 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll | 122 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.mir | 322 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/exception.ll | 124 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/wasmehprepare.ll | 46 |
5 files changed, 163 insertions, 545 deletions
diff --git a/llvm/test/CodeGen/WebAssembly/annotations.mir b/llvm/test/CodeGen/WebAssembly/annotations.mir deleted file mode 100644 index 1ae2db82484..00000000000 --- a/llvm/test/CodeGen/WebAssembly/annotations.mir +++ /dev/null @@ -1,94 +0,0 @@ -# RUN: llc -mtriple=wasm32-unknown-unknown -start-after xray-instrumentation -wasm-keep-registers %s -o - | FileCheck %s - ---- -# Tests if block/loop/try/catch/end instructions are correctly printed with -# their annotations. - -# CHECK: test0: -# CHECK: block -# CHECK: try -# CHECK: br 0 # 0: down to label1 -# CHECK: catch_all # catch0: -# CHECK: block -# CHECK: br_if 0, 1 # 0: down to label2 -# CHECK: loop # label3: -# CHECK: br_if 0, 1 # 0: up to label3 -# CHECK: end_loop -# CHECK: end_block # label2: -# CHECK: try -# CHECK: rethrow 0 # 0: down to catch1 -# CHECK: catch_all # catch1: -# CHECK: block -# CHECK: try -# CHECK: br 0 # 0: down to label6 -# CHECK: catch_all # catch2: -# CHECK: unreachable -# CHECK: end_try # label6: -# CHECK: end_block # label5: -# CHECK: rethrow 0 # 0: to caller -# CHECK: end_try # label4: -# CHECK: end_try # label1: -# CHECK: end_block # label0: - -name: test0 -liveins: - - { reg: '$arguments', reg: '$value_stack' } -body: | - bb.0: - successors: %bb.7, %bb.1 - BLOCK 64, implicit-def $value_stack, implicit $value_stack - TRY 64, implicit-def $value_stack, implicit $value_stack - BR 0, implicit-def $arguments - - bb.1 (landing-pad): - ; predecessors: %bb.0 - successors: %bb.2, %bb.3 - - CATCH_ALL implicit-def $arguments - BLOCK 64, implicit-def $value_stack, implicit $value_stack - BR_IF 0, 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack - - bb.2: - ; predecessors: %bb.1, %bb.2 - successors: %bb.2, %bb.3 - - LOOP 64, implicit-def $value_stack, implicit $value_stack - BR_IF 0, 1, implicit-def $arguments - - bb.3: - ; predecessors: %bb.1, %bb.2 - successors: %bb.4 - - END_LOOP implicit-def $value_stack, implicit $value_stack - END_BLOCK implicit-def $value_stack, implicit $value_stack - TRY 64, implicit-def $value_stack, implicit $value_stack - RETHROW 0, implicit-def $arguments - - bb.4 (landing-pad): - ; predecessors: %bb.3 - successors: %bb.6, %bb.5 - - CATCH_ALL implicit-def $arguments - BLOCK 64, implicit-def $value_stack, implicit $value_stack - TRY 64, implicit-def $value_stack, implicit $value_stack - BR 0, implicit-def $arguments - - bb.5 (landing-pad): - ; predecessors: %bb.4 - CATCH_ALL implicit-def $arguments - UNREACHABLE implicit-def dead $arguments - - bb.6: - ; predecessors: %bb.4 - END_TRY implicit-def $value_stack, implicit $value_stack - END_BLOCK implicit-def $value_stack, implicit $value_stack - RETHROW 0, implicit-def $arguments - - bb.7: - ; predecessors: %bb.0 - END_TRY implicit-def $value_stack, implicit $value_stack - END_TRY implicit-def $value_stack, implicit $value_stack - END_BLOCK implicit-def $value_stack, implicit $value_stack - FALLTHROUGH_RETURN_VOID implicit-def dead $arguments - END_FUNCTION implicit-def $value_stack, implicit $value_stack -... diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll index e3c34f87e13..037730141b3 100644 --- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -7,21 +7,25 @@ target triple = "wasm32-unknown-unknown" @_ZTId = external constant i8* ; Simple test case with two catch clauses +; void test0() { +; try { +; foo(); +; } catch (int n) { +; bar(); +; } catch (double d) { +; } +; } ; CHECK-LABEL: test0 +; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: .LBB0_1: -; CHECK: i32.catch +; CHECK: catch $[[EXCEPT_REF:[0-9]+]]= +; CHECK: block i32 +; CHECK: br_on_exn 0, __cpp_exception@EVENT, $[[EXCEPT_REF]] +; CHECK: rethrow +; CHECK: end_block ; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION -; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION -; CHECK: call bar@FUNCTION -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB0_3: -; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB0_5: -; CHECK: call __cxa_rethrow@FUNCTION -; CHECK: .LBB0_6: +; CHECK: end_try ; CHECK: return define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: @@ -68,39 +72,45 @@ try.cont: ; preds = %entry, %catch, %cat } ; Nested try-catches within a catch +; void test1() { +; try { +; foo(); +; } catch (int n) { +; try { +; foo(); +; } catch (int n) { +; foo(); +; } +; } +; } ; CHECK-LABEL: test1 +; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: .LBB1_1: -; CHECK: i32.catch $0=, 0 -; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $0 -; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION, $0 -; CHECK: call foo@FUNCTION -; CHECK: .LBB1_3: -; CHECK: i32.catch $0=, 0 -; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $0 -; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION, $0 +; CHECK: catch +; CHECK: br_on_exn 0, __cpp_exception@EVENT +; CHECK: rethrow +; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION +; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: .LBB1_5: -; CHECK: catch_all -; CHECK: call __cxa_end_catch@FUNCTION +; CHECK: catch +; CHECK: br_on_exn 0, __cpp_exception@EVENT ; CHECK: rethrow -; CHECK: .LBB1_6: -; CHECK: call __cxa_rethrow@FUNCTION +; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION +; CHECK: try +; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION +; CHECK: try +; CHECK: call foo@FUNCTION +; CHECK: catch $drop= ; CHECK: rethrow -; CHECK: .LBB1_7: -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB1_8: -; CHECK: catch_all -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB1_9: -; CHECK: call __cxa_rethrow@FUNCTION +; CHECK: end_try +; CHECK: catch $drop= ; CHECK: rethrow -; CHECK: .LBB1_10: -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB1_11: +; CHECK: end_try +; CHECK: end_try +; CHECK: end_try ; CHECK: return -define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { +define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: invoke void @foo() to label %try.cont11 unwind label %catch.dispatch @@ -175,30 +185,38 @@ unreachable: ; preds = %rethrow5 } ; Nested loop within a catch clause +; void test2() { +; try { +; foo(); +; } catch (...) { +; for (int i = 0; i < 50; i++) +; foo(); +; } +; } ; CHECK-LABEL: test2 +; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: .LBB2_1: -; CHECK: i32.catch -; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION -; CHECK: .LBB2_2: +; CHECK: catch +; CHECK: br_on_exn 0, __cpp_exception@EVENT +; CHECK: rethrow +; CHECK: loop +; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: .LBB2_4: -; CHECK: catch_all +; CHECK: catch $drop= +; CHECK: try ; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB2_5: -; CHECK: i32.catch -; CHECK: call __clang_call_terminate@FUNCTION +; CHECK: catch +; CHECK: br_on_exn 0, __cpp_exception@EVENT +; CHECK: call __clang_call_terminate@FUNCTION, 0 ; CHECK: unreachable -; CHECK: .LBB2_6: -; CHECK: catch_all -; CHECK: call _ZSt9terminatev@FUNCTION +; CHECK: call __clang_call_terminate@FUNCTION ; CHECK: unreachable -; CHECK: .LBB2_7: +; CHECK: end_try ; CHECK: rethrow -; CHECK: .LBB2_8: -; CHECK: call __cxa_end_catch@FUNCTION -; CHECK: .LBB2_10: +; CHECK: end_try +; CHECK: end_loop +; CHECK: end_try ; CHECK: return define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.mir b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.mir deleted file mode 100644 index 11d9aaf5f0e..00000000000 --- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.mir +++ /dev/null @@ -1,322 +0,0 @@ -# RUN: llc -mtriple=wasm32-unknown-unknown -exception-model=wasm -run-pass wasm-cfg-stackify %s -o - | FileCheck %s - ---- | - target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" - target triple = "wasm32-unknown-unknown" - - @__wasm_lpad_context = external global { i32, i8*, i32 } - - declare void @may_throw() - ; Function Attrs: nounwind - declare void @dont_throw() #0 - declare i8* @__cxa_begin_catch(i8*) - declare void @__cxa_end_catch() - declare void @__cxa_rethrow() - ; Function Attrs: nounwind - declare i32 @__gxx_wasm_personality_v0(...) - declare i32 @_Unwind_CallPersonality(i8*) #0 - - define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { - unreachable - } - define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { - unreachable - } - define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { - unreachable - } - define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { - unreachable - } - - attributes #0 = { nounwind } - ---- -# Simplest try-catch -# try { -# may_throw(); -# } catch (...) { -# } -name: test0 -# CHECK-LABEL: name: test0 -liveins: - - { reg: '$arguments', reg: '$value_stack' } -body: | - bb.0: - successors: %bb.2, %bb.1 - - CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.2, implicit-def $arguments - ; CHECK-LABEL: bb.0: - ; CHECK: TRY - ; CHECK-NEXT: CALL_VOID @may_throw - - bb.1 (landing-pad): - ; predecessors: %bb.0 - successors: %bb.2 - - %2:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %3:i32 = CALL_I32 @__cxa_begin_catch, %2:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack - DROP_I32 killed %3:i32, implicit-def $arguments - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - - bb.2: - ; predecessors: %bb.0, %bb.1 - - RETURN_VOID implicit-def dead $arguments - ; CHECK-LABEL: bb.2: - ; CHECK-NEXT: END_TRY - ; CHECK: RETURN_VOID -... ---- - -# Nested try-catch inside another catch -# try { -# may_throw(); -# } catch (int n) { -# try { -# may_throw(); -# } catch (int n) { -# } -# } -name: test1 -# CHECK-LABEL: name: test1 -liveins: - - { reg: '$arguments', reg: '$value_stack' } -body: | - bb.0: - successors: %bb.9, %bb.1 - - CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.9, implicit-def $arguments - ; CHECK-LABEL: bb.0: - ; CHECK: TRY - ; CHECK-NEXT: CALL_VOID @may_throw - - bb.1 (landing-pad): - ; predecessors: %bb.0 - successors: %bb.2, %bb.7 - - %30:i32 = CATCH_I32 0, implicit-def dead $arguments - LOCAL_SET_I32 0, %30:i32, implicit-def $arguments - %16:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %27:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - STORE_I32 2, @__wasm_lpad_context + 4, %16:i32, %27:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i8** getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 1)`) - %26:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %25:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - STORE_I32 2, @__wasm_lpad_context, %26:i32, %25:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`) - %32:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %31:i32 = CALL_I32 @_Unwind_CallPersonality, %32:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - DROP_I32 killed %31:i32, implicit-def $arguments - %24:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %17:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %24:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`) - %18:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %19:i32 = NE_I32 %17:i32, %18:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_IF %bb.7, %19:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack - - bb.2: - ; predecessors: %bb.1 - successors: %bb.8, %bb.3, %bb.6 - - %34:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %33:i32 = CALL_I32 @__cxa_begin_catch, %34:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - DROP_I32 killed %33:i32, implicit-def $arguments - CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.8, implicit-def $arguments - ; CHECK-LABEL: bb.2: - ; CHECK: DROP_I32 - ; CHECK-NEXT: TRY - ; CHECK-NEXT: TRY - ; CHECK-NEXT: CALL_VOID @may_throw - - bb.3 (landing-pad): - ; predecessors: %bb.2 - successors: %bb.4, %bb.5 - - %35:i32 = CATCH_I32 0, implicit-def dead $arguments - LOCAL_SET_I32 0, %35:i32, implicit-def $arguments - %21:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %20:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - STORE_I32 2, @__wasm_lpad_context, %21:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`) - %37:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %36:i32 = CALL_I32 @_Unwind_CallPersonality, %37:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - DROP_I32 killed %36:i32, implicit-def $arguments - %29:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %22:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %29:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`) - %28:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %23:i32 = NE_I32 %22:i32, %28:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_IF %bb.5, %23:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack - - bb.4: - ; predecessors: %bb.3 - successors: %bb.8 - - %39:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %38:i32 = CALL_I32 @__cxa_begin_catch, %39:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - DROP_I32 killed %38:i32, implicit-def $arguments - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.8, implicit-def $arguments - - bb.5: - ; predecessors: %bb.3 - successors: %bb.6 - - CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - RETHROW %bb.6, implicit-def $arguments - - bb.6 (landing-pad): - ; predecessors: %bb.2, %bb.5 - - CATCH_ALL implicit-def $arguments - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - RETHROW_TO_CALLER implicit-def $arguments - ; CHECK-LABEL: bb.6 (landing-pad): - ; CHECK-NEXT: END_TRY - - bb.7: - ; predecessors: %bb.1 - - CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - RETHROW_TO_CALLER implicit-def $arguments - ; CHECK-LABEL: bb.7: - ; CHECK-NEXT: END_TRY - ; CHECK: RETHROW 0 - - bb.8: - ; predecessors: %bb.2, %bb.4 - successors: %bb.9 - - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - - bb.9: - ; predecessors: %bb.0, %bb.8 - - RETURN_VOID implicit-def dead $arguments - ; CHECK-LABEL: bb.9: - ; CHECK-NEXT: END_TRY -... ---- - -# A loop within a try. -# try { -# for (int i = 0; i < n; ++i) -# may_throw(); -# } catch (...) { -# } -name: test2 -# CHECK-LABEL: name: test2 -liveins: - - { reg: '$arguments', reg: '$value_stack' } -body: | - bb.0: - successors: %bb.1, %bb.4 - - %18:i32 = CONST_I32 0, implicit-def dead $arguments - LOCAL_SET_I32 1, %18:i32, implicit-def $arguments - %14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %19:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %9:i32 = GE_S_I32 %14:i32, %19:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_IF %bb.4, %9:i32, implicit-def $arguments - - bb.1: - ; predecessors: %bb.0, %bb.3 - successors: %bb.3, %bb.2 - - CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.3, implicit-def $arguments - ; CHECK-LABEL: bb.1: - ; CHECK: LOOP - ; CHECK: TRY - ; CHECK-NEXT: CALL_VOID @may_throw - - bb.2 (landing-pad): - ; predecessors: %bb.1 - successors: %bb.4 - - %11:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %22:i32 = CALL_I32 @__cxa_begin_catch, %11:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack - DROP_I32 killed %22:i32, implicit-def $arguments - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.4, implicit-def $arguments - - bb.3: - ; predecessors: %bb.1 - successors: %bb.1, %bb.4 - - %20:i32 = LOCAL_GET_I32 1, implicit-def $arguments - %17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %16:i32 = ADD_I32 %20:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %15:i32 = LOCAL_TEE_I32 1, %16:i32, implicit-def $arguments - %21:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %10:i32 = GE_S_I32 %15:i32, %21:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_UNLESS %bb.1, %10:i32, implicit-def $arguments - ; CHECK-LABEL: bb.3: - ; CHECK: END_TRY - - bb.4: - ; predecessors: %bb.2, %bb.0, %bb.3 - - RETURN_VOID implicit-def dead $arguments -... ---- - -# A loop within a catch -# try { -# may_throw(); -# } catch (...) { -# for (int i = 0; i < n; ++i) -# dont_throw(); -# } -name: test3 -# CHECK-LABEL: name: test3 -liveins: - - { reg: '$arguments', reg: '$value_stack' } -body: | - bb.0: - successors: %bb.4, %bb.1 - - CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - BR %bb.4, implicit-def $arguments - ; CHECK-LABEL: bb.0: - ; CHECK: TRY - ; CHECK-NEXT: CALL_VOID @may_throw - - bb.1 (landing-pad): - ; predecessors: %bb.0 - successors: %bb.2, %bb.3 - - %9:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %18:i32 = CALL_I32 @__cxa_begin_catch, %9:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack - DROP_I32 killed %18:i32, implicit-def $arguments - %19:i32 = CONST_I32 0, implicit-def dead $arguments - LOCAL_SET_I32 1, %19:i32, implicit-def $arguments - %14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %20:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %10:i32 = GE_S_I32 %14:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_IF %bb.3, %10:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack - - bb.2: - ; predecessors: %bb.1, %bb.2 - successors: %bb.2, %bb.3 - - CALL_VOID @dont_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - %21:i32 = LOCAL_GET_I32 1, implicit-def $arguments - %17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %16:i32 = ADD_I32 %21:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - %15:i32 = LOCAL_TEE_I32 1, %16:i32, implicit-def $arguments - %22:i32 = LOCAL_GET_I32 0, implicit-def $arguments - %11:i32 = GE_S_I32 %15:i32, %22:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack - BR_UNLESS %bb.2, %11:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack - - bb.3: - ; predecessors: %bb.1, %bb.2 - successors: %bb.4 - - CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64 - - bb.4: - ; predecessors: %bb.0, %bb.3 - - RETURN_VOID implicit-def dead $arguments - ; CHECK-LABEL: bb.4: - ; CHECK: END_TRY diff --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll index de2d0615a17..46ec46837af 100644 --- a/llvm/test/CodeGen/WebAssembly/exception.ll +++ b/llvm/test/CodeGen/WebAssembly/exception.ll @@ -1,5 +1,5 @@ ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck -allow-deprecated-dag-overlap %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck -allow-deprecated-dag-overlap %s ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" @@ -9,30 +9,39 @@ target triple = "wasm32-unknown-unknown" @_ZTIi = external constant i8* -declare void @llvm.wasm.throw(i32, i8*) - ; CHECK-LABEL: test_throw: -; CHECK: local.get $push0=, 0 -; CHECK-NEXT: throw __cpp_exception@EVENT, $pop0 +; CHECK: throw __cpp_exception@EVENT, $0 ; CHECK-NOT: unreachable define void @test_throw(i8* %p) { call void @llvm.wasm.throw(i32 0, i8* %p) ret void } +; CHECK-LABEL: test_rethrow: +; CHECK: rethrow +; CHECK-NOT: unreachable +define void @test_rethrow(i8* %p) { + call void @llvm.wasm.rethrow() + ret void +} + ; CHECK-LABEL: test_catch_rethrow: -; CHECK: global.get $push{{.+}}=, __stack_pointer@GLOBAL +; CHECK: global.get ${{.+}}=, __stack_pointer@GLOBAL ; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: i32.catch $push{{.+}}=, 0 +; CHECK: catch $[[EXCEPT_REF:[0-9]+]]= +; CHECK: block i32 +; CHECK: br_on_exn 0, __cpp_exception@EVENT, $[[EXCEPT_REF]] +; CHECK: rethrow +; CHECK: end_block +; CHECK: extract_exception $[[EXN:[0-9]+]]= ; CHECK: global.set __stack_pointer@GLOBAL ; CHECK-DAG: i32.store __wasm_lpad_context ; CHECK-DAG: i32.store __wasm_lpad_context+4 -; CHECK: i32.call $push{{.+}}=, _Unwind_CallPersonality@FUNCTION -; CHECK: i32.call $push{{.+}}=, __cxa_begin_catch@FUNCTION +; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $[[EXN]] +; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION ; CHECK: call __cxa_end_catch@FUNCTION ; CHECK: call __cxa_rethrow@FUNCTION -; CHECK-NEXT: rethrow ; CHECK: end_try define void @test_catch_rethrow() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: @@ -66,9 +75,9 @@ try.cont: ; preds = %entry, %catch ; CHECK-LABEL: test_cleanup: ; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: catch_all +; CHECK: catch ; CHECK: global.set __stack_pointer@GLOBAL -; CHECK: i32.call $push{{.+}}=, _ZN7CleanupD1Ev@FUNCTION +; CHECK: i32.call $drop=, _ZN7CleanupD1Ev@FUNCTION ; CHECK: rethrow ; CHECK: end_try define void @test_cleanup() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { @@ -87,71 +96,51 @@ ehcleanup: ; preds = %entry cleanupret from %0 unwind to caller } -; - Tests multple terminate pads are merged into one -; - Tests a catch_all terminate pad is created after a catch terminate pad - ; CHECK-LABEL: test_terminatepad -; CHECK: i32.catch -; CHECK: call __clang_call_terminate@FUNCTION -; CHECK: unreachable -; CHECK: catch_all -; CHECK: call _ZSt9terminatev@FUNCTION -; CHECK-NOT: call __clang_call_terminate@FUNCTION -define hidden i32 @test_terminatepad() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { +; CHECK: catch +; CHECK: block i32 +; CHECK: br_on_exn 0, __cpp_exception@EVENT +; CHECK: call __clang_call_terminate@FUNCTION, 0 +; CHECK: unreachable +; CHECK: end_block +; CHECK: extract_exception +; CHECK: call __clang_call_terminate@FUNCTION +; CHECK: unreachable +define void @test_terminatepad() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: - %c = alloca %struct.Cleanup, align 1 - %c1 = alloca %struct.Cleanup, align 1 invoke void @foo() - to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - %call = invoke %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %c1) to label %try.cont unwind label %catch.dispatch -ehcleanup: ; preds = %entry - %0 = cleanuppad within none [] - %call4 = invoke %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %c1) [ "funclet"(token %0) ] - to label %invoke.cont3 unwind label %terminate - -invoke.cont3: ; preds = %ehcleanup - cleanupret from %0 unwind label %catch.dispatch - -catch.dispatch: ; preds = %invoke.cont3, %invoke.cont - %1 = catchswitch within none [label %catch.start] unwind label %ehcleanup7 +catch.dispatch: ; preds = %entry + %0 = catchswitch within none [label %catch.start] unwind to caller catch.start: ; preds = %catch.dispatch - %2 = catchpad within %1 [i8* null] - %3 = call i8* @llvm.wasm.get.exception(token %2) - %4 = call i32 @llvm.wasm.get.ehselector(token %2) - %5 = call i8* @__cxa_begin_catch(i8* %3) [ "funclet"(token %2) ] - invoke void @__cxa_end_catch() [ "funclet"(token %2) ] - to label %invoke.cont5 unwind label %ehcleanup7 + %1 = catchpad within %0 [i8* null] + %2 = call i8* @llvm.wasm.get.exception(token %1) + %3 = call i32 @llvm.wasm.get.ehselector(token %1) + %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ] + invoke void @foo() [ "funclet"(token %1) ] + to label %invoke.cont1 unwind label %ehcleanup -invoke.cont5: ; preds = %catch.start - catchret from %2 to label %try.cont +invoke.cont1: ; preds = %catch.start + call void @__cxa_end_catch() [ "funclet"(token %1) ] + catchret from %1 to label %try.cont -try.cont: ; preds = %invoke.cont5, %invoke.cont - %call6 = call %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %c) - ret i32 0 +try.cont: ; preds = %entry, %invoke.cont1 + ret void -ehcleanup7: ; preds = %catch.start, %catch.dispatch - %6 = cleanuppad within none [] - %call9 = invoke %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* %c) [ "funclet"(token %6) ] - to label %invoke.cont8 unwind label %terminate10 +ehcleanup: ; preds = %catch.start + %5 = cleanuppad within %1 [] + invoke void @__cxa_end_catch() [ "funclet"(token %5) ] + to label %invoke.cont2 unwind label %terminate -invoke.cont8: ; preds = %ehcleanup7 - cleanupret from %6 unwind to caller +invoke.cont2: ; preds = %ehcleanup + cleanupret from %5 unwind to caller terminate: ; preds = %ehcleanup - %7 = cleanuppad within %0 [] - %8 = call i8* @llvm.wasm.get.exception(token %7) - call void @__clang_call_terminate(i8* %8) [ "funclet"(token %7) ] - unreachable - -terminate10: ; preds = %ehcleanup7 - %9 = cleanuppad within %6 [] - %10 = call i8* @llvm.wasm.get.exception(token %9) - call void @__clang_call_terminate(i8* %10) [ "funclet"(token %9) ] + %6 = cleanuppad within %5 [] + %7 = call i8* @llvm.wasm.get.exception(token %6) + call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ] unreachable } @@ -164,12 +153,12 @@ terminate10: ; preds = %ehcleanup7 ; CHECK-LABEL: test_no_prolog_epilog_in_ehpad ; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: i32.catch +; CHECK: catch ; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer@GLOBAL ; CHECK: global.set __stack_pointer@GLOBAL ; CHECK: try ; CHECK: call foo@FUNCTION -; CHECK: catch_all +; CHECK: catch ; CHECK-NOT: global.get $push{{.+}}=, __stack_pointer@GLOBAL ; CHECK: global.set __stack_pointer@GLOBAL ; CHECK: call __cxa_end_catch@FUNCTION @@ -251,6 +240,8 @@ try.cont: ; preds = %entry, %catch.start declare void @foo() declare void @bar(i32*) declare i32 @__gxx_wasm_personality_v0(...) +declare void @llvm.wasm.throw(i32, i8*) +declare void @llvm.wasm.rethrow() declare i8* @llvm.wasm.get.exception(token) declare i32 @llvm.wasm.get.ehselector(token) declare i32 @llvm.eh.typeid.for(i8*) @@ -258,7 +249,6 @@ declare i8* @__cxa_begin_catch(i8*) declare void @__cxa_end_catch() declare void @__cxa_rethrow() declare void @__clang_call_terminate(i8*) -declare void @_ZSt9terminatev() declare %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* returned) ; CHECK: __cpp_exception: diff --git a/llvm/test/CodeGen/WebAssembly/wasmehprepare.ll b/llvm/test/CodeGen/WebAssembly/wasmehprepare.ll index 6df7175b1ca..09013a0a754 100644 --- a/llvm/test/CodeGen/WebAssembly/wasmehprepare.ll +++ b/llvm/test/CodeGen/WebAssembly/wasmehprepare.ll @@ -29,7 +29,7 @@ catch.start: ; preds = %catch.dispatch br i1 %matches, label %catch, label %rethrow ; CHECK: catch.start: ; CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad -; CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.catch(i32 0) +; CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.extract.exception() ; CHECK-NEXT: call void @llvm.wasm.landingpad.index(token %[[CATCHPAD]], i32 0) ; CHECK-NEXT: store i32 0, i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0) ; CHECK-NEXT: %[[LSDA:.*]] = call i8* @llvm.wasm.lsda() @@ -76,7 +76,6 @@ catch.start: ; preds = %catch.dispatch catchret from %1 to label %try.cont ; CHECK: catch.start: ; CHECK-NEXT: catchpad within %0 [i8* null] -; CHECK-NEXT: call i8* @llvm.wasm.catch(i32 0) ; CHECK-NOT: call void @llvm.wasm.landingpad.index ; CHECK-NOT: store {{.*}} @__wasm_lpad_context ; CHECK-NOT: call i8* @llvm.wasm.lsda() @@ -178,7 +177,6 @@ ehcleanup: ; preds = %rethrow5, %catch.di cleanupret from %12 unwind to caller ; CHECK: ehcleanup: ; CHECK-NEXT: cleanuppad -; CHECK-NOT: call i8* @llvm.wasm.catch(i32 0) ; CHECK-NOT: call void @llvm.wasm.landingpad.index ; CHECK-NOT: store {{.*}} @__wasm_lpad_context ; CHECK-NOT: call i8* @llvm.wasm.lsda() @@ -191,7 +189,7 @@ unreachable: ; preds = %rethrow5 ; A cleanuppad with a call to __clang_call_terminate(). ; A call to wasm.catch() should be generated after the cleanuppad. -define hidden void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { +define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { ; CHECK-LABEL: @test3 entry: invoke void @foo() @@ -230,14 +228,14 @@ terminate: ; preds = %ehcleanup unreachable ; CHECK: terminate: ; CHECK-NEXT: cleanuppad -; CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.catch(i32 0) +; CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.extract.exception ; CHECK-NEXT: call void @__clang_call_terminate(i8* %[[EXN]]) } ; PHI demotion test. Only the phi before catchswitch should be demoted; the phi ; before cleanuppad should NOT. -define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { -; CHECK-LABEL: @test5 +define void @test4() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { +; CHECK-LABEL: @test4 entry: %c = alloca %struct.Cleanup, align 1 invoke void @foo() @@ -301,8 +299,8 @@ try.cont10: ; preds = %invoke.cont3, %catc ; Tests if instructions after a call to @llvm.wasm.throw are deleted and the ; BB's dead children are deleted. -; CHECK-LABEL: @test6 -define i32 @test6(i1 %b, i8* %p) { +; CHECK-LABEL: @test5 +define i32 @test5(i1 %b, i8* %p) { entry: br i1 %b, label %bb.true, label %bb.false @@ -326,6 +324,34 @@ merge: ; preds = %bb.true.0, %bb.fals ret i32 0 } +; Tests if instructions after a call to @llvm.wasm.rethrow are deleted and the +; BB's dead children are deleted. + +; CHECK-LABEL: @test6 +define i32 @test6(i1 %b, i8* %p) { +entry: + br i1 %b, label %bb.true, label %bb.false + +; CHECK: bb.true: +; CHECK-NEXT: call void @llvm.wasm.rethrow() +; CHECK-NEXT: unreachable +bb.true: ; preds = %entry + call void @llvm.wasm.rethrow() + br label %bb.true.0 + +; CHECK-NOT: bb.true.0 +bb.true.0: ; preds = %bb.true + br label %merge + +; CHECK: bb.false +bb.false: ; preds = %entry + br label %merge + +; CHECK: merge +merge: ; preds = %bb.true.0, %bb.false + ret i32 0 +} + declare void @foo() declare void @func(i32) declare %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* returned) @@ -334,12 +360,12 @@ declare i8* @llvm.wasm.get.exception(token) declare i32 @llvm.wasm.get.ehselector(token) declare i32 @llvm.eh.typeid.for(i8*) declare void @llvm.wasm.throw(i32, i8*) +declare void @llvm.wasm.rethrow() declare i8* @__cxa_begin_catch(i8*) declare void @__cxa_end_catch() declare void @__cxa_rethrow() declare void @__clang_call_terminate(i8*) -; CHECK-DAG: declare i8* @llvm.wasm.catch(i32) ; CHECK-DAG: declare void @llvm.wasm.landingpad.index(token, i32) ; CHECK-DAG: declare i8* @llvm.wasm.lsda() ; CHECK-DAG: declare i32 @_Unwind_CallPersonality(i8*) |

