Cranelift: implement an "unwinder" crate and exception throws in filetests.#10919
Merged
cfallin merged 1 commit intobytecodealliance:mainfrom Jun 5, 2025
Merged
Conversation
c29d873 to
24b71a8
Compare
bjorn3
reviewed
Jun 4, 2025
bjorn3
reviewed
Jun 4, 2025
bjorn3
reviewed
Jun 4, 2025
Contributor
|
By the way why is the unwind info format defined in the cranelift-unwinder crate? It is Wasmtime specific and I would assume that Winch and Pulley will reuse the same format. |
alexcrichton
reviewed
Jun 4, 2025
fitzgen
approved these changes
Jun 4, 2025
Member
fitzgen
left a comment
There was a problem hiding this comment.
r=me with things we discussed in the cranelift meeting
12673ed to
2ed32f9
Compare
bjorn3
reviewed
Jun 4, 2025
bjorn3
reviewed
Jun 4, 2025
1006ae6 to
d624489
Compare
Member
Author
|
Grr, now there's another merge conflict because the version bump went in ahead of this one. |
…tests.
This commit introduces the next major piece of machinery (after the
previously-landed `try_call` support) that we will eventually use to
implement Wasm exceptions in Wasmtime. In particular, it implements a
generic unwinder as a new crate that supports (i) walking a stack
produced by Cranelift code, (ii) serializing Cranelift exception
metadata to compact tables (in a way very similar to address maps in
Wasmtime, so they will be mappable directly from disk), (iii) using
these serialized tables to find handlers during a stack-walk, and (iv)
jumping to handlers (i.e., actually unwinding). This crate is currently
used in the filetests runner, and will next be used in Wasmtime.
The commit first performs code-motion: it moves stack-walking code from
Wasmtime to `cranelift-unwinder`. This itself has no functional effect,
but isolates the code that understands contiguous sequences of Cranelift
frames ("activations") from that which is specific to Wasmtime's
activation delimiters and metadata.
It then implements a compact exception-table format. This format uses
the `object` crate's mechanisms for directly referencing in-memory
arrays of little-endian `u32`s in a way that will allow us to find
handlers when mapping exception metadata directly from an ELF section in
a `.cwasm` (for example). The format consists of four sorted `u32`
arrays in a way that allows us to look up a callsite first, then search
its sorted array of handler offsets by tags.
It next implements the actual unwind control flow: it contains an
assembly stub for each supported architecture that transfers control to
a PC, SP, and FP value "up the stack", with payload values placed in the
payload registers we have defined per our exception ABI in Cranelift.
Finally, it puts these pieces together in the filetest runner. Note that
the runtest does a lot "by hand": we don't have entry and exit
trampolines as we do in Wasmtime, so the filetest contains three
functions, with the middle one invoking the "throw hostcall" and entry
and exit trampolines around it grabbing the appropriate entry/exit FPs
and exit PC. The dance to call back to host code is also somewhat
delicate, as we haven't done this before. The `JITModule`'s linking +
relocation support does not seem sufficient to properly define a symbol,
so instead we scan for `func_addr` instructions referencing a well-known
name (`__cranelift_throw`) and replace them with `iconst`s with the
function address at runtime, baking it in. This is somewhat ugly, but it
works. All of these filetest-specific details will be handled much more
nicely in the Wasmtime version of this functionality, as we have proper
abstractions for entry/exit trampolines and hostcalls.
08478b3 to
40a317e
Compare
Member
Author
|
Wow, CI really does not like this PR -- network error here downloading CMake. |
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 25, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Jul 26, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 12, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 12, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 15, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 15, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 19, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 19, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 19, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 19, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 20, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 20, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
cfallin
added a commit
to cfallin/wasmtime
that referenced
this pull request
Aug 20, 2025
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This commit introduces the next major piece of machinery (after the previously-landed
try_callsupport) that we will eventually use to implement Wasm exceptions in Wasmtime. In particular, it implements a generic unwinder as a new crate that supports (i) walking a stack produced by Cranelift code, (ii) serializing Cranelift exception metadata to compact tables (in a way very similar to address maps in Wasmtime, so they will be mappable directly from disk), (iii) using these serialized tables to find handlers during a stack-walk, and (iv) jumping to handlers (i.e., actually unwinding). This crate is currently used in the filetests runner, and will next be used in Wasmtime.The commit first performs code-motion: it moves stack-walking code from Wasmtime to
cranelift-unwinder. This itself has no functional effect, but isolates the code that understands contiguous sequences of Cranelift frames ("activations") from that which is specific to Wasmtime's activation delimiters and metadata.It then implements a compact exception-table format. This format uses the
objectcrate's mechanisms for directly referencing in-memory arrays of little-endianu32s in a way that will allow us to find handlers when mapping exception metadata directly from an ELF section in a.cwasm(for example). The format consists of four sortedu32arrays in a way that allows us to look up a callsite first, then search its sorted array of handler offsets by tags.It next implements the actual unwind control flow: it contains an assembly stub for each supported architecture that transfers control to a PC, SP, and FP value "up the stack", with payload values placed in the payload registers we have defined per our exception ABI in Cranelift.
Finally, it puts these pieces together in the filetest runner. Note that the runtest does a lot "by hand": we don't have entry and exit trampolines as we do in Wasmtime, so the filetest contains three functions, with the middle one invoking the "throw hostcall" and entry and exit trampolines around it grabbing the appropriate entry/exit FPs and exit PC. The dance to call back to host code is also somewhat delicate, as we haven't done this before. The
JITModule's linking + relocation support does not seem sufficient to properly define a symbol, so instead we scan forfunc_addrinstructions referencing a well-known name (__cranelift_throw) and replace them withiconsts with the function address at runtime, baking it in. This is somewhat ugly, but it works. All of these filetest-specific details will be handled much more nicely in the Wasmtime version of this functionality, as we have proper abstractions for entry/exit trampolines and hostcalls.