Rewrite setjmp/longjmp docs (#562)

* Provide flags for emitting the standard exception-handling
instructions.
* More further explain what flags are doing.
* Show a sample program that can be compiled both ways.
* Delegate running in a runtime to various runtimes, so remove the "run
the program" documentation here.
* Remove `wasm-opt` documentation since it's now documented how to emit
the standard instructions directly with LLVM.
main
Alex Crichton 1 week ago committed by GitHub
parent d43a936053
commit d90d7de10e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -3,80 +3,115 @@
WASI-SDK provides basic setjmp/longjmp support. WASI-SDK provides basic setjmp/longjmp support.
Note that it's still under active development and may change in Note that it's still under active development and may change in
future versions. future versions. The tl;dr; version of this document is to pass these flags to
the C compiler:
## Build an application ```
-mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=false
To build an application using setjmp/longjmp, you need two things: ```
* Enable the necessary LLVM translation (`-mllvm -wasm-enable-sjlj`) ## Implementation Primitives
Support for `setjmp` and `longjmp` is built on top of the
[exception-handling](https://github.com/WebAssembly/exception-handling)
WebAssembly proposal. This proposal is now [phase
5](https://github.com/WebAssembly/proposals) and becoming part of the official
specification. Note, however, that the exception-handling proposal has a long
history and has a "legacy" version which shipped in browsers as well. This means
that there are two different, but similar, sets of instructions that can be
emitted to support `setjmp` and `longjmp`. Clang 20 and later (wasi-sdk-26 and
later) is capable of emitting both at this time via `-mllvm
-wasm-use-legacy-eh={false,true}` compiler flags.
Another important point is that exception-handling only provides structured
control flow primitives for exceptions. This means it is not possible to purely
define `setjmp` in C as otherwise it must be a function that returns twice. This
means that support for `setjmp` and `longjmp` in WebAssembly relies on a
compiler pass to transform invocations of `setjmp` at a compiler IR level. This
means that the `setjmp` symbol is not defined in wasi-libc, for example, but
instead primitives used to implement `setjmp`, in conjunction with LLVM, are
found in wasi-libc.
* Link the setjmp library (`-lsetjmp`) ## Build an application
### Example without LTO To build an application using setjmp/longjmp, you need three sets of compiler
flags:
```shell 1. `-mllvm -wasm-enable-sjlj`: Enable LLVM compiler pass which replaces calls to
clang -Os -mllvm -wasm-enable-sjlj -o your_app.legacy.wasm your_app.c -lsetjmp `setjmp` and `longjmp` with a different implementation that wasi-libc
``` implements and hooks into.
2. `-lsetjmp`: Link the setjmp library that wasi-libc provides which contains
these hooks that LLVM uses.
2. `-mllvm -wasm-use-legacy-eh=false`: Specify which version of the
exception-handling instructions will be emitted. Note that if this is omitted
it currently defaults to `true` meaning that the legacy instructions are
emitted, not the standard instructions.
### Example with LTO In short, these flags are required to use `setjmp`/`longjmp`
```shell ```
clang -Os -flto=full -mllvm -wasm-enable-sjlj -Wl,-mllvm,-wasm-enable-sjlj -o your_app.legacy.wasm your_app.c -lsetjmp -mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=false
``` ```
## Run an application ### Examples
To run the application built as in the previous section, This source code:
you need to use a runtime with [exception handling proposal] support.
Unfortunately, there are two incompatible versions of ```c
[exception handling proposal], which is commonly implemented by runtimes. #include <assert.h>
#include <setjmp.h>
#include <stdbool.h>
#include <stdio.h>
* The latest version with `exnref` static jmp_buf env;
* The legacy [phase3] version static bool test_if_longjmp(void(*f)(void)) {
if (setjmp(env))
return true;
f();
return false;
}
### Example with the latest exception handling proposal static void do_not_longjmp() {
}
By default, the current version of WASI-SDK produces the legacy static void do_longjmp() {
"phase3" version of [exception handling proposal] instructions. longjmp(env, 1);
}
You can tell the llvm to produce the latest version of proposal by int main() {
specifying `-mllvm -wasm-use-legacy-eh=false`. This is expected bool longjmped = test_if_longjmp(do_not_longjmp);
to be the default in a future version. assert(!longjmped);
longjmped = test_if_longjmp(do_longjmp);
assert(longjmped);
return 0;
}
```
Alternatively, you can use binaryen `wasm-opt` command to convert can be compiled using the standard set of instructions as:
existing modules from the legacy "phase3" version to the "exnref" version.
```shell ```shell
wasm-opt --translate-to-exnref -all -o your_app.wasm your_app.legacy.wasm clang -Os -o test.wasm test.c \
-mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=false
``` ```
Then you can run it with a runtime supporting the "exnref" version of and then `test.wasm` can be executed in a WebAssembly runtime supporting WASI.
the proposal.
[toywasm] is an example of such runtimes. You can also compile for the legacy exceptions proposal with:
```shell ```shell
toywasm --wasi your_app.wasm clang -Os -o test.wasm test.c \
-mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=true
``` ```
(You may need to enable the support with `-D TOYWASM_ENABLE_WASM_EXCEPTION_HANDLING=ON`.)
### Example with the legacy phase3 exception handling proposal
If your runtime supports the legacy [phase3] version of and then `test.wasm` can be executed in a WebAssembly runtime supporting the
[exception handling proposal], which is the same version as what WASI-SDK legacy WebAssembly instructions.
currently produces by default, you can run the produced module as it is.
For example, the classic interpreter of [wasm-micro-runtime] is Note that when compiling with LTO you'll need to pass `-mllvm` flags to the
one of such runtimes. linker in addition to Clang itself, such as:
```shell ```shell
iwasm your_app.legacy.wasm clang -Os -flto=full -o test.wasm test.c \
-mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=false \
-Wl,-mllvm,-wasm-enable-sjlj,-mllvm,-wasm-use-legacy-eh=false
``` ```
(You may need to enable the support with `-D WAMR_BUILD_EXCE_HANDLING=1 -D WAMR_BUILD_FAST_INTERP=0`.)
[exception handling proposal]: https://github.com/WebAssembly/exception-handling/
[phase3]: https://github.com/WebAssembly/exception-handling/tree/main/proposals/exception-handling/legacy
[toywasm]: https://github.com/yamt/toywasm
[wasm-micro-runtime]: https://github.com/bytecodealliance/wasm-micro-runtime

Loading…
Cancel
Save