cfallin opened PR #10919 from cfallin:lets-kick-back-and-unwind-a-bit to bytecodealliance:main:
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.<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
cfallin requested abrown for a review on PR #10919.
cfallin requested wasmtime-compiler-reviewers for a review on PR #10919.
cfallin requested dicej for a review on PR #10919.
cfallin requested wasmtime-core-reviewers for a review on PR #10919.
cfallin requested wasmtime-default-reviewers for a review on PR #10919.
cfallin requested fitzgen for a review on PR #10919.
cfallin updated PR #10919.
bjorn3 submitted PR review.
bjorn3 created PR review comment:
Making this a
return_call_indirectwould avoid the need to get any frame pointer, right? You only need to change the return address before returning from__cranelift_throw, not unwind the stack back to the caller of%throw.
bjorn3 submitted PR review.
bjorn3 created PR review comment:
nit: missing trailing newline
bjorn3 submitted PR review.
bjorn3 created PR review comment:
extern "C-unwind"otherwise unwinding out of this is UB (you are skipping past the aborting landingpad due to using a different unwinding mechanism).
bjorn3 edited PR review comment.
bjorn3 commented on PR #10919:
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 submitted PR review.
alexcrichton created PR review comment:
Not necessarily required for this PR, but could this be moved back to Wasmtime? It feels a bit odd to define it all the way over here when Pulley is defined somewhere else.
Placement-wise the only use of
UnwindPulleyis here so it might make sense to add anunwindermethod onstruct Interpreterwhich would enable moving all of this to this file (and a stub in this file)
alexcrichton created PR review comment:
Ideally I'd prefer to not duplicate this with the main Wasmtime crate as I suspect the two will diverge over time. For example on iOS we should probably disable cranelift by default despite having a backend for aarch64. Now that doesn't actually matter for this crate though since it'll still all compile just fine on iOS (in theory), it just wouldn't be useful to have at runtime.
Would it be possible to actually drop this build script entirely? For example the
archmodule would become naturally empty on unsupported architectures and structures likeUnwindHostwould only appear for supported architectures. That'd mean that this build script would basically fall out of thecfg-ifif/else branches for the arch support
alexcrichton created PR review comment:
FWIW you can use
&*to translate*const Tto&T, notransmutenecessary
alexcrichton created PR review comment:
It should be ok to skip this comment since the type system basically all guarantees that for us (or perhaps move this beforehand as a lead-in explanation for what the function's doing?)
alexcrichton created PR review comment:
FWIW if you're feeling enterprising IIRC the only reason we have this is
get_stack_pointeron s390x where inline assembly wasn't supported originally, but it is supported now, so a small inline assembly snippet would probably suffice for removing this crate dependency.
alexcrichton created PR review comment:
Could you elaborate on this? I was under the impression that
C-unwindhad to do with the system unwinder, or whatever the default is for the platform. For this unwinder landing pads aren't invoked no matter what, so by the same logicC-unwindis also UB because landing pads still aren't executed.To me it seems that the soundness of this function relies on there not actually being any landing pads, which is something we'd have to uphold?
alexcrichton created PR review comment:
I'm hesitating with this in that this feels like a new significant dependency edge that didn't exist prior, but I can't really articulate what exactly it is. Currently in all other locations though
cranelift-codegenis isolated towasmtime-cranelift/Winch and nowhere else. My assumption is that thewasmtimecrate will depend oncranelift-unwinder(and maybe also thewasmtime-craneliftcrate to pass in the cranelift data structures?). I realize thatwasmtimeitself won't enable this dependency, but WDYT about making this built-in to cranelift-codegen directly? Or maybe a separate crate?I don't feel too too strong about this, but I think it sort of depends on how exactly this'll get integrated in to Wasmtime as well.
alexcrichton created PR review comment:
I've written up more thoughts on this in https://github.com/bytecodealliance/wasmtime/issues/10923
alexcrichton submitted PR review.
fitzgen created PR review comment:
Maybe add an olive branch of documentation about the safety requirements here? We've been trying to improve this stuff in the core VM.
fitzgen created PR review comment:
I don't care too much what we name this crate, in some sense it could be either
wasmtime-unwinderorcranelift-unwinderbecause the dependency graph is a little convoluted here, but I think this description is a bit misleading. People who are writing a random Cranelift project could see this and think it is a solution to their unwinding issues -- especially since using Cranelift means pulling in a bunch ofcranelift-foodeps -- and mayyyybe it could be, but it is really tailored for Wasmtime's usage and isn't going to be very flexible to other use cases.We should probably make it clear in this description that this is an internal implementation detail of Wasmtime and Cranelift's unit testing.
fitzgen created PR review comment:
If this function is already monomorphized over
R, we might as well use an&impl Unwindinstead of a&dyn Unwind
fitzgen created PR review comment:
I had to read this pretty closely to understand how the below "expanded" representation corresponds to the above encoding example. I think what would have allowed me to understand at a relatively light skim would have been inline comments in the
rangesarray expanding what actualtags/handlersranges they represent, as well as having links the other way for thetagsandhandlers, something like this:callsites: [0x10, 0x50, 0xf0], ranges: [ // tag/handlers range for callsite 0x10: 0..2 2, // tag/handlers range for callsite 0x50: 2..4 4, // tag/handlers range for callsite 0xf0: 4..5 5, ] tags: [ // Tags for callsite 0x10 1, 5, // Tags for callsite 0x50 1, -1, // Tags for callsite 0xf0 -1 ], handlers: [ // Handlers for callsite 0x10 0x40, 0x42, // Handlers for callsite 0x50 0x6f, 0x71, // Handlers for callsite 0xf0 0xf5, ]Basically, it wasn't immediately clear to me at a glance which arrays were part of the "same struct" (in a struct-of-arrays vs array-of-structs isomorphism) and for the ones which had separate indexing, how that indexing worked, and I ended up having to read this comment closely a couple times.
fitzgen submitted PR review:
r=me with things we discussed in the cranelift meeting
cfallin updated PR #10919.
cfallin updated PR #10919.
cfallin updated PR #10919.
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Fixed, thanks!
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Updated to use
C-unwind-- thanks for catching this.
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Done as suggested in Cranelift meeting today -- there are now
pub uses to re-export with doc-comments attached.cfgs minimized and put right next to each other -- only the onecfg_ifchain for the implementations and one withcfg(any(...))to wrap all thepub uses and theUnwindHostimpl.I've verified that
wasmtime-unwinderchecks oni686-unknown-linux-gnu.
cfallin created PR review comment:
Yep, renamed to
wasmtime-unwinder-- thanks all for the feedback on this!
cfallin submitted PR review.
cfallin submitted PR review.
cfallin created PR review comment:
Interestingly, this ends up propagating all the way up to e.g.
store.unwinder()-- thedynis infectious and we'd have a monomorphize a bunch more to make this work (or build a proxy-to-dyn impl to monomorphize on). Since this seems like just an opportunistic thing, I'll leave it asdyn Unwindfor now...
cfallin submitted PR review.
cfallin created PR review comment:
Done!
bjorn3 submitted PR review.
bjorn3 created PR review comment:
Please make this an optional dependency. I don't want to pull this in for cg_clif.
bjorn3 submitted PR review.
bjorn3 created PR review comment:
pub fn lookup_wasmtime_exception_data<'a>(
cfallin submitted PR review.
cfallin created PR review comment:
Perhaps, but one of my goals here was to closely mirror how the trampolines work in Wasmtime, and also I don't know if we really need to optimize the testing infrastructure like this.
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Done!
alexcrichton submitted PR review.
alexcrichton created PR review comment:
Yeah changing this away from
dyn Unwind, while possible, I think is best to defer to later.
cfallin updated PR #10919.
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Sorry about that, didn't think through all the use-cases -- done!
cfallin submitted PR review.
cfallin created PR review comment:
Done!
cfallin submitted PR review.
cfallin created PR review comment:
Done!
cfallin submitted PR review.
cfallin created PR review comment:
Done!
cfallin submitted PR review.
cfallin created PR review comment:
Ah, right, much simpler -- done!
cfallin submitted PR review.
cfallin created PR review comment:
Now that the crate is called
wasmtime-unwinderI hesitate to put it as a dependency (even optional) ofcranelift-codegen; I suppose in the fullness of time we could have awasmtime-unwinder-craneliftto split off the translation-from-Cranelift-metadata functionality but I also don't feel too strongly about it. For now at least it's under a feature and optional. Happy to see this refactored later if we want to go that way or have other ideas.
cfallin updated PR #10919.
cfallin submitted PR review.
cfallin created PR review comment:
Updated, thanks -- I like this way of writing it out a lot better.
cfallin updated PR #10919.
cfallin updated PR #10919.
cfallin requested alexcrichton for a review on PR #10919.
cfallin requested wasmtime-fuzz-reviewers for a review on PR #10919.
cfallin updated PR #10919.
cfallin has enabled auto merge for PR #10919.
cfallin updated PR #10919.
cfallin has enabled auto merge for PR #10919.
cfallin commented on PR #10919:
This appears to have bounced off the merge queue because it raced with #10388 and lost; and that PR heavily modified backtracing as well...
cfallin updated PR #10919.
cfallin updated PR #10919.
alexcrichton commented on PR #10919:
github's not great about rendering all the time, but the failure was here (32-bit build)
cfallin updated PR #10919.
cfallin has enabled auto merge for PR #10919.
cfallin has disabled auto merge for PR #10919.
cfallin commented on PR #10919:
Grr, now there's another merge conflict because the version bump went in ahead of this one.
cfallin updated PR #10919.
cfallin has enabled auto merge for PR #10919.
cfallin commented on PR #10919:
Wow, CI really does not like this PR -- network error here downloading CMake.
cfallin merged PR #10919.
Last updated: Dec 06 2025 at 06:05 UTC