-
Notifications
You must be signed in to change notification settings - Fork 75
Description
There's been some recent activity on __cpp_exception, where it's defined, etc, and I've encountered a new issues today which prompts me to raise a question here to get some broader feedback.
As a bit of background, my understanding is that the @llvm.wasm.throw intrinsic in LLVM takes an argument of "what type should be thrown", and this type is either 0 meaning "a C++ exception" or 1 meaning "a C longjmp exception". There is currently no ability to decide to throw some other kind of exception meaning that when an exception is thrown it must mean that either __cpp_exception or __c_longjmp is reference as a tag. Historically I believe wasm-ld would define __cpp_exception and __c_longjmp weakly in a all objects, but that (somewhat) recently changed to not doing so. LLVM switched to defining these two symbols in compiler-rt, but I sent PRs to remove those from compiler-rt under the rationale of "not suitable to link twice in multiple shared objects" since there should only be one definition of these symbols. This leaves us today with the current state of affairs: __c_longjmp is defined, for example, in wasi-libc and __cpp_exception is defined in libunwind.
The issue/question that prompted me to raise this here is this comment, which is: what should Rust do for its panics? A panic in Rust is similar (ish) to a C++ exception, and for Rust panics right now they're implemented with __cpp_exception. With these changes about the definition of __cpp_exception, it's not clear to me how this should work in Rust. Thus the crux of this question here: for languages that aren't C++, and for implementations that aren't longjmp, how should exceptions be thrown?
Some various ideas I have are:
- LLVM should have a language-specific exception tag definition for all languages that want to throw exceptions. For example LLVM should grow knowledge of
__rust_panicas an exception tag that is suitable for use in Rust. I don't know off the top of my head, however, how much this affects catch-style blocks and how much those currently assume C++ vs being able to switch out to using some other kind of tag. - All other languages should use
__cpp_exception, and that should move its definition to a "libc-likelocation", e.g. wasi-libc or Emscripten's libc, instead of libunwind. That way languages can all use LLVM's support for__cpp_exceptionwithout necessarily using libunwind. - All languages should use
__cpp_exception, specifically through libunwind. For example Rust's custom implementation of throw/etc for wasm should be removed in favor of delegating to libunwind (similar to how native platforms work).
Each of these seems somewhat equally viable to me. Rust for example doesn't have a strong need to use a custom exception implementation, but at the same time it's also kind of nice not needing to distribute/build/etc libunwind. Nevertheless I wanted to open up the question here and see if others have thoughts, and I could very well be forgetting something here which would mean "nah there's just one answer".