Skip to content

Conversation

yamt
Copy link
Contributor

@yamt yamt commented Mar 15, 2024

Add setjmp/longjump support based on Wasm EH proposal.

It's provided as a separate library (libsetjmp) from libc so that runtimes w/o EH support can still load libc.so.

To use this setjmp/longjmp implementation, an application should be compiled with -mllvm -wasm-enable-sjlj and linked with -lsetjmp. (You need an LLVM with the change mentioned below.)

Also, you need a runtime with EH support to run such an application.

If you want to use the latest EH instructions, you can use binaryen --translate-eh-old-to-new on your application.

Note: You don't need to translate libsetjmp.a/so to the new EH. While LLVM currently produces bytecode for an old version of the EH proposal, luckily for us, the bytecode used in this library (ie. the tag definition and the "throw" instruction) is compatible with the latest version of the proposal.

The runtime logic is basically copy-and-paste from:
https://github.com/yamt/garbage/tree/wasm-sjlj-alt2/wasm/longjmp

The corresponding LLVM change:
llvm/llvm-project#84137
(Note: you need this change to build setjmp/longjmp using code.
otoh, you don't need this to build libsetjmp.)

A similar change for emscripten:
emscripten-core/emscripten#21502

An older version of this PR, which doesn't require LLVM changes:
#467

Discussion:
https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit

An example to use the latest EH instructions:

clang -mllvm -wasm-enable-sjlj -o your_app.wasm your_app.c -lsetjmp
wasm-opt --translate-eh-old-to-new -o your_app.wasm your_app.wasm
toywasm --wasi your_app.wasm

Note: use toywasm built with -DTOYWASM_ENABLE_WASM_EXCEPTION_HANDLING=ON.

An example to use the older EH instructions, which LLVM currently produces:

clang -mllvm -wasm-enable-sjlj -o your_app.wasm your_app.c -lsetjmp
iwasm your_app.wasm

Note: use wasm-micro-runtime built with -DWAMR_BUILD_EXCE_HANDLING=1.
Note: as of writing this, only the classic interpreter supports EH.

yamt added 3 commits March 15, 2024 16:31
Add setjmp/longjump support based on Wasm EH proposal.

It's provided as a separate library (libsetjmp) from libc so that
runtimes w/o EH support can still load libc.so.

To use this setjmp/longjmp implementation, an application should
be compiled with `-mllvm -wasm-enable-sjlj` and linked with `-lsetjmp`.
(You need an LLVM with the change mentioned below.)

Also, you need a runtime with EH support to run such an application.

If you want to use the latest EH instructions, you can use
`binaryen --translate-eh-old-to-new` on your application.

Note: You don't need to translate libsetjmp.a/so to the new EH.
While LLVM currently produces bytecode for an old version of the EH
proposal, luckily for us, the bytecode used in this library (ie. the tag
definition and the "throw" instruction) is compatible with the latest
version of the proposal.

The runtime logic is basically copy-and-paste from:
    https://github.com/yamt/garbage/tree/wasm-sjlj-alt2/wasm/longjmp

The corresponding LLVM change:
    llvm/llvm-project#84137
    (Note: you need this change to build setjmp/longjmp using code.
    otoh, you don't need this to build libsetjmp.)

A similar change for emscripten:
    emscripten-core/emscripten#21502

An older version of this PR, which doesn't require LLVM changes:
    WebAssembly#467

Discussion:
    https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit

An example to use the latest EH instructions:
```
clang -mllvm -wasm-enable-sjlj -o your_app.wasm your_app.c -lsetjmp
wasm-opt --translate-eh-old-to-new -o your_app.wasm your_app.wasm
toywasm --wasi your_app.wasm
```
Note: use toywasm built with `-DTOYWASM_ENABLE_WASM_EXCEPTION_HANDLING=ON`.

An example to use the older EH instructions, which LLVM currently produces:
```
clang -mllvm -wasm-enable-sjlj -o your_app.wasm your_app.c -lsetjmp
iwasm your_app.wasm
```
Note: use wasm-micro-runtime built with `-DWAMR_BUILD_EXCE_HANDLING=1`.
Note: as of writing this, only the classic interpreter supports EH.
@yamt yamt marked this pull request as ready for review March 15, 2024 07:32
@leddoo
Copy link

leddoo commented Mar 15, 2024

this looks really cool!
i was just trying to add sjlj support myself, but couldn't find any docs for -wasm-enable-sjlj.

i don't know how to propose changes to a PR, so i'll just write a comment.
the setjmp.h header is broken.

  • the #include <bits/setjmp.h> include should not have been removed, __jmp_buf is undefined.
  • i think you forgot to remove the #else #warning setjmp is not yet implemented for WASI bit at the bottom. that errors because the #ifndef __wasilibc_unmodified_upstream is already closed above.

@yamt
Copy link
Contributor Author

yamt commented Mar 16, 2024

this looks really cool! i was just trying to add sjlj support myself, but couldn't find any docs for -wasm-enable-sjlj.

i don't know how to propose changes to a PR, so i'll just write a comment. the setjmp.h header is broken.

* the `#include <bits/setjmp.h>` include should not have been removed, `__jmp_buf` is undefined.

* i think you forgot to remove the `#else #warning setjmp is not yet implemented for WASI` bit at the bottom. that errors because the `#ifndef __wasilibc_unmodified_upstream` is already closed above.

oops. fixed. thank you.

yamt added a commit to yamt/garbage that referenced this pull request Mar 16, 2024
Copy link
Member

@sunfishcode sunfishcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me; just one note below:

/*
* a runtime implementation for
* https://github.com/llvm/llvm-project/pull/84137
* https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we should copy the content of this into the tool-conventions repo. Would you be interested in doing this, or would you mind if I did it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree we should document in the tool-conventions repo.
i think i can write something next month.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aheejin pushed a commit to llvm/llvm-project that referenced this pull request Mar 26, 2024
…jlj (#84137)

Instead of maintaining per-function-invocation malloc()'ed tables to track which functions each label belongs to, store the equivalent info in jump buffers (jmp_buf) themselves.

Also, use a less emscripten-looking ABI symbols:
```
    saveSetjmp     -> __wasm_setjmp
    testSetjmp      -> __wasm_setjmp_test
    getTempRet0    -> (removed)
    __wasm_longjmp  -> (no change)
```

While I want to use this for WASI, it should work for emscripten as well.

An example runtime and a few tests:
https://github.com/yamt/garbage/tree/wasm-sjlj-alt2/wasm/longjmp

wasi-libc version of the runtime:
WebAssembly/wasi-libc#483

emscripten version of the runtime:
emscripten-core/emscripten#21502

Discussion:
https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
@sunfishcode
Copy link
Member

Thanks for filing that. This looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants