[llvm] [WebAssembly] Add assembly support for final EH proposal (PR #107917)
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 10 16:54:23 PDT 2024
================
@@ -0,0 +1,470 @@
+; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -verify-machineinstrs | FileCheck --implicit-check-not=ehgcr -allow-deprecated-dag-overlap %s
+; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -verify-machineinstrs -O0
+; RUN: llc < %s -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref
+
+target triple = "wasm32-unknown-unknown"
+
+%struct.Temp = type { i8 }
+
+ at _ZTIi = external dso_local constant ptr
+
+; CHECK: .tagtype __cpp_exception i32
+
+; CHECK-LABEL: throw:
+; CHECK: throw __cpp_exception
+; CHECK-NOT: unreachable
+define void @throw(ptr %p) {
+ call void @llvm.wasm.throw(i32 0, ptr %p)
+ ret void
+}
+
+; Simple test with a try-catch
+;
+; void foo();
+; void catch() {
+; try {
+; foo();
+; } catch (int) {
+; }
+; }
+
+; CHECK-LABEL: catch:
+; CHECK: global.get __stack_pointer
+; CHECK: local.set 0
+; CHECK: block
+; CHECK: block () -> (i32, exnref)
+; CHECK: try_table (catch_ref __cpp_exception 0)
+; CHECK: call foo
+; CHECK: br 2
+; CHECK: end_try_table
+; CHECK: end_block
+; CHECK: local.set 2
+; CHECK: local.get 0
+; CHECK: global.set __stack_pointer
+; CHECK: i32.store __wasm_lpad_context
+; CHECK: call _Unwind_CallPersonality
+; CHECK: block
+; CHECK: br_if 0
+; CHECK: call __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+; CHECK: br 1
+; CHECK: end_block
+; CHECK: local.get 2
+; CHECK: throw_ref
+; CHECK: end_block
+define void @catch() personality ptr @__gxx_wasm_personality_v0 {
+entry:
+ invoke void @foo()
+ to label %try.cont unwind label %catch.dispatch
+
+catch.dispatch: ; preds = %entry
+ %0 = catchswitch within none [label %catch.start] unwind to caller
+
+catch.start: ; preds = %catch.dispatch
+ %1 = catchpad within %0 [ptr @_ZTIi]
+ %2 = call ptr @llvm.wasm.get.exception(token %1)
+ %3 = call i32 @llvm.wasm.get.ehselector(token %1)
+ %4 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi)
+ %matches = icmp eq i32 %3, %4
+ br i1 %matches, label %catch, label %rethrow
+
+catch: ; preds = %catch.start
+ %5 = call ptr @__cxa_begin_catch(ptr %2) [ "funclet"(token %1) ]
+ call void @__cxa_end_catch() [ "funclet"(token %1) ]
+ catchret from %1 to label %try.cont
+
+rethrow: ; preds = %catch.start
+ call void @llvm.wasm.rethrow() [ "funclet"(token %1) ]
+ unreachable
+
+try.cont: ; preds = %catch, %entry
+ ret void
+}
+
+; Destructor (cleanup) test
+;
+; void foo();
+; struct Temp {
+; ~Temp() {}
+; };
+; void cleanup() {
+; Temp t;
+; foo();
+; }
+
+; CHECK-LABEL: cleanup:
+; CHECK: block
+; CHECK: block exnref
+; CHECK: try_table (catch_all_ref 0)
+; CHECK: call foo
+; CHECK: br 2
+; CHECK: end_try_table
+; CHECK: end_block
+; CHECK: local.set 1
+; CHECK: global.set __stack_pointer
+; CHECK: call _ZN4TempD2Ev
+; CHECK: local.get 1
+; CHECK: throw_ref
+; CHECK: end_block
+; CHECK: call _ZN4TempD2Ev
+define void @cleanup() personality ptr @__gxx_wasm_personality_v0 {
+entry:
+ %t = alloca %struct.Temp, align 1
+ invoke void @foo()
+ to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont: ; preds = %entry
+ %call = call ptr @_ZN4TempD2Ev(ptr %t)
+ ret void
+
+ehcleanup: ; preds = %entry
+ %0 = cleanuppad within none []
+ %call1 = call ptr @_ZN4TempD2Ev(ptr %t) [ "funclet"(token %0) ]
+ cleanupret from %0 unwind to caller
+}
+
+; Calling a function that may throw within a 'catch (...)' generates a
+; temrinatepad, because __cxa_end_catch() also can throw within 'catch (...)'.
----------------
dschuff wrote:
```suggestion
; terminatepad, because __cxa_end_catch() also can throw within 'catch (...)'.
```
https://github.com/llvm/llvm-project/pull/107917
More information about the llvm-commits
mailing list