Skip to content

Cranelift: fix the interaction of preserve_all and stack probes+limits. - #14648

Queued
cfallin wants to merge 2 commits into
bytecodealliance:mainfrom
cfallin:fix-preserve-all
Queued

cfallin wants to merge 2 commits into
bytecodealliance:mainfrom
cfallin:fix-preserve-all

Conversation

@cfallin

@cfallin cfallin commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

The preserve_all ABI specifies that a function may not clobber any registers (all registers are callee-saved).

However, Cranelift has two features that cause code to be inserted into the prologue that may sometimes clobber registers: stack-limit checks, and stack probes. Both of these happen before clobbered registers are saved, so normally use caller-saved (volatile) registers. In preserve_all, no such registers exist. We previously used volatiles consistent with SysV/tail, erroneously assuming they would be volatile in all ABIs.

(In Wasmtime, preserve_all is needed for the guest-debug breakpoint trampoline to which calls are patched in from sequence-point NOP areas. We don't spill registers around these areas, so all registers really must be preserved.)

This PR fixes the interaction two ways:

  • Stack limits are simply disallowed in preserve_all functions. (This is compatible with Wasmtime's trampoline, the one preserve_all use-case we have in-tree.)
  • Stack probes are only supported with an "unrolled" strategy, where we decrement RSP and store to it in one-page-sized steps. This strategy does not use any registers (other than RSP) so is still safe in this context.

(Note that practically speaking, this has no current impact on Wasmtime because, in that one use-case above, the trampoline has effectively no stack frame so does not emit any stack probes. But the theoretical problem still exists and should be handled or rejected.)

This PR also fixes something else found while looking at preserve_all: on Pulley, we need 16 bytes, not 8, to save a 128-bit vector register (!). That is a correctness bug reachable from Wasmtime, but only when doing guest debugging on Pulley, neither of which is tier-1.

…its.

The `preserve_all` ABI specifies that a function may not clobber any
registers (all registers are callee-saved).

However, Cranelift has two features that cause code to be inserted
into the prologue that may sometimes clobber registers: stack-limit
checks, and stack probes. Both of these happen before clobbered
registers are saved, so normally use caller-saved (volatile)
registers. In `preserve_all`, no such registers exist. We previously
used volatiles consistent with SysV/tail, erroneously assuming they
would be volatile in all ABIs.

(In Wasmtime, `preserve_all` is needed for the guest-debug breakpoint
trampoline to which calls are patched in from sequence-point NOP
areas. We don't spill registers around these areas, so all registers
really must be preserved.)

This PR fixes the interaction two ways:

- Stack limits are simply disallowed in `preserve_all` functions. (This
  is compatible with Wasmtime's trampoline, the one `preserve_all`
  use-case we have in-tree.)
- Stack probes are only supported with an "unrolled" strategy, where
  we decrement RSP and store to it in one-page-sized steps. This
  strategy does not use any registers (other than RSP) so is still safe
  in this context.
@cfallin
cfallin requested a review from a team as a code owner October 10, 2026 00:19
@cfallin
cfallin requested review from fitzgen and removed request for a team October 10, 2026 00:19
- riscv64 as well, same issue (need unrolled version of probetack).
- Pulley: allocate appropriate amount of space, not constant 8 bytes,
  for preserve-all clobber-save slots.
@alexcrichton
alexcrichton added this pull request to the merge queue Oct 10, 2026
@github-actions github-actions Bot added cranelift Issues related to the Cranelift code generator cranelift:area:x64 Issues related to x64 codegen labels Oct 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cranelift:area:x64 Issues related to x64 codegen cranelift Issues related to the Cranelift code generator

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants