Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SH] Changes to compile with wasi-sdk #1589

Open
wants to merge 1 commit into
base: static_h
Choose a base branch
from

Conversation

tmikov
Copy link
Contributor

@tmikov tmikov commented Dec 30, 2024

Wasi-sdk is much less Unix-like than the environment provided by Emscripten and requires more profound changes for support.

Unix mman emulation requires:

  • -lwasi-emulated-mman

Unfortunately JS and C++ exceptions are both a mess.

Wasi-sdk does not support C++ exceptions yet.

We can live with that, since Hermes for the most part compiles with exceptions disabled anyway. However JSI relies on exceptions and it is part of the compiled library. To get things working one needs to rely on the following hack (which isn't included in this commit):

extern "C" void __cxa_throw(void* thrown_exception,
    std::type_info* tinfo,
    void (*dest)(void*)) {
  llvh::report_fatal_error("C++ exceptions not supported on Wasi");
}

extern "C" void* __cxa_allocate_exception(size_t) {
  llvh::report_fatal_error("C++ exceptions not supported on Wasi");
}

This causes any JSI exception to simply abort.

JS exceptions work fine with the bytecode interpreter, however code produced by the native backend relies on setjmp/longjmp. Alas, setjmp/longjmp are not well supported by Wasm. This fact was hidden by Emscripten, which used its own JS shim and exceptions to implement them. That, however, does not work with standalone WASI.

According to the Wasi-sdk documentation, setjmp/longjmp can be supported, using the Wasm exception handling proposal.

This requires:

  • -mllvm -wasm-enable-sjlj
  • -lsetjmp

I was able to successfully compile the shermes-generated code to a Wasm binary with the following flags, however I was not able to find a single standalone runtime that was able to run it out of the box!

Wasmtime and Wasmer refused to load the module with the error "exceptions proposal not enabled". Iwasm failed to load it some error about Wasm operand stack.

I am sure that it is possible to either find or configure a Wasm runtime to support the exceptions proposal, but since none of the major runtimes support if out of the box, I consider it useless for now. Sadly.

I am sure v8 supports it, but what's the point of using v8 for this? First, v8 already supports JS, and second, Emscripten has that covered already.

There is an experimental followup commit which turns setjmp() into noop and longjmp() into abort(). That at least allows natively compiled JS to run, until the first exception...

Summary

Test Plan

Wasi-sdk is much less Unix-like than the environment provided by
Emscripten and requires more profound changes for support.

Unix mman emulation requires:
- `-lwasi-emulated-mman`

Unfortunately JS and C++ exceptions are both a mess.

Wasi-sdk [does not support C++ exceptions yet](https://github.com/WebAssembly/wasi-sdk/tree/a4d918fa119c9beb712bf08bbb8fa9996aab0a71?tab=readme-ov-file#notable-limitations).

We can live with that, since Hermes for the most part compiles with
exceptions disabled anyway. However JSI relies on exceptions and it is
part of the compiled library. To get things working one needs to rely
on the following hack (which isn't included in this commit):

```c++

extern "C" void __cxa_throw(void* thrown_exception,
    std::type_info* tinfo,
    void (*dest)(void*)) {
  llvh::report_fatal_error("C++ exceptions not supported on Wasi");
}

extern "C" void* __cxa_allocate_exception(size_t) {
  llvh::report_fatal_error("C++ exceptions not supported on Wasi");
}
```

This causes any JSI exception to simply abort.

JS exceptions work fine with the bytecode interpreter, however code
produced by the *native backend* relies on `setjmp/longjmp`. Alas,
`setjmp/longjmp` are not well supported by Wasm. This fact was hidden by
Emscripten, which used its own JS shim and exceptions to implement them.
That, however, does not work with standalone WASI.

According to the [Wasi-sdk documentation](https://github.com/WebAssembly/wasi-sdk/blob/a4d918fa119c9beb712bf08bbb8fa9996aab0a71/SetjmpLongjmp.md), `setjmp/longjmp` can be supported,
using the Wasm exception handling proposal.

This requires:
- `-mllvm -wasm-enable-sjlj`
- `-lsetjmp`

I was able to successfully compile the shermes-generated code to a Wasm
binary with the following flags, however I was **not** able to find a
single standalone runtime that was able to run it out of the box!

Wasmtime and Wasmer refused to load the module with the error
"exceptions proposal not enabled". Iwasm failed to load it some error
about Wasm operand stack.

I am sure that it is possible to either find or configure a Wasm runtime
to support the exceptions proposal, but since none of the major runtimes
support if out of the box, I consider it useless for now. Sadly.

I am sure v8 supports it, but what's the point of using v8 for this?
First, v8 already supports JS, and second, Emscripten has that covered
already.

There is an experimental followup commit which turns setjmp() into noop
and longjmp() into abort(). That at least allows natively compiled JS to
run, until the first exception...
@facebook-github-bot facebook-github-bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Dec 30, 2024
@facebook-github-bot
Copy link
Contributor

@tmikov has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Do not delete this pull request or issue due to inactivity.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants