[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