bytecodealliance / bytecodealliance/wasmtime
Cranelift: use spillslots only as large as actual values, not registers
- Dominant language
- Rust
- Stars
- 18.6k
- Forks
- 1.8k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 121
Description
In #3645, we switched the spillslot logic to use a spillslot as large as the full register to be spilled, rather than the type we think is stored in the register. This was due to some sloppiness in actually tracking the types; in at least one fuzzbug, a 128-bit-vector-sized value was stored into a 64-bit spillslot.
The root cause of this issue is that the register allocator creates equivalence classes of all vregs linked by move instructions (in order to perform move elision), and when allocating a spillslot for this equivalence class, asks for the size of an *arbitrary* vreg in the class. If we emit moves between vregs of different types (e.g., 128-bit to 32-bit, if we know we just want the lower bits), then this could return an incorrect type.
To solve this, we need to enforce type discipline in move instructions (and thus have special pseudo-moves that do *not* participate in move elision). Probably the best way of doing this would be to accept an arbitrary IR-level type in the regalloc interface for every virtual register, and check that moves do not occur between registers of different types. Once we do this, and are free of panics caused by violations of this invariant, then we can revert to the more efficient spillslot allocation scheme.
Contributor guide
Assessment
This issue has not been assessed yet.