Skip to content

Commit da85b2a

Browse files
authored
[WebAssembly] Generate __clang_call_terminate for Emscripten EH (#129020)
When an exception thrown ends up calling `std::terminate`, for example, because an exception is thrown within a `noexcept` function or an exception is thrown from `__cxa_end_catch` during handling the previous exception, the libc++abi spec says we are supposed to call `__cxa_begin_catch` before `std::terminate`: https://libcxxabi.llvm.org/spec.html > When the personality routine encounters a termination condition, it will call `__cxa_begin_catch()` to mark the exception as handled and then call `terminate()`, which shall not return to its caller. The default Itanium ABI generates a call to `__clang_call_terminate()`, which is a function that calls `__cxa_begin_catch` and then `std::terminate`: ```ll define void @__clang_call_terminate(ptr noundef %0) { %2 = call ptr @__cxa_begin_catch(ptr %0) call void @_ZSt9terminatev() unreachable } ``` But we replaced this with just a call to `std::terminate` in 561abd8 because this caused some tricky transformation problems for Wasm EH. The detailed explanation why is in the commit description, but the summary is for Wasm EH it needed a `try` with both `catch` and `catch_all` and it was tricky to deal with. But that commit replaced `__clang_call_terminate` with `std::terminate` for all Wasm programs and not only the ones that use Wasm EH. So Emscripten EH was also affected by that commit. Emscripten EH is not able to catch foreign exceptions anyway, so this is unnecessary compromise. This makes we use `__clang_call_terminate` as in the default Itanium EH for Emscripten EH. We may later fix Wasm EH too but that requires more efforts in the backend. Related issue: emscripten-core/emscripten#23720
1 parent 51dc526 commit da85b2a

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5150,9 +5150,14 @@ WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
51505150
// Itanium ABI calls __clang_call_terminate(), which __cxa_begin_catch() on
51515151
// the violating exception to mark it handled, but it is currently hard to do
51525152
// with wasm EH instruction structure with catch/catch_all, we just call
5153-
// std::terminate and ignore the violating exception as in CGCXXABI.
5153+
// std::terminate and ignore the violating exception as in CGCXXABI in Wasm EH
5154+
// and call __clang_call_terminate only in Emscripten EH.
51545155
// TODO Consider code transformation that makes calling __clang_call_terminate
5155-
// possible.
5156+
// in Wasm EH possible.
5157+
if (Exn && !EHPersonality::get(CGF).isWasmPersonality()) {
5158+
assert(CGF.CGM.getLangOpts().CPlusPlus);
5159+
return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn);
5160+
}
51565161
return CGCXXABI::emitTerminateForUnexpectedException(CGF, Exn);
51575162
}
51585163

clang/test/CodeGenCXX/wasm-eh.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
77
// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s
88

9+
// Test code generation for Wasm EH using WebAssembly EH proposal.
10+
// (https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md)
11+
912
void may_throw();
1013
void dont_throw() noexcept;
1114

@@ -381,6 +384,15 @@ void test8() {
381384

382385
// CHECK: unreachable
383386

387+
void noexcept_throw() noexcept {
388+
throw 3;
389+
}
390+
391+
// CATCH-LABEL: define void @_Z14noexcept_throwv()
392+
// CHECK: %{{.*}} = cleanuppad within none []
393+
// CHECK-NEXT: call void @_ZSt9terminatev()
394+
395+
384396
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-DEFAULT
385397
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -Wwasm-exception-spec -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-ON
386398
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -exception-model=wasm -target-feature +exception-handling -Wno-wasm-exception-spec -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=WARNING-OFF

clang/test/CodeGenCXX/wasm-em-eh.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 %s -triple wasm32-unknown-emscripten -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 2>&1 | FileCheck %s
2+
3+
// Test code generation for Wasm's Emscripten (JavaScript-style) EH.
4+
5+
void noexcept_throw() noexcept {
6+
throw 3;
7+
}
8+
9+
// CATCH-LABEL: define void @_Z14noexcept_throwv()
10+
// CHECK: %[[LPAD:.*]] = landingpad { ptr, i32 }
11+
// CHECK-NEXT: catch ptr null
12+
// CHECK-NEXT: %[[EXN:.*]] = extractvalue { ptr, i32 } %[[LPAD]], 0
13+
// CHECK-NEXT: call void @__clang_call_terminate(ptr %[[EXN]])

0 commit comments

Comments
 (0)