bytecodealliance / bytecodealliance/wasmtime

Cranelift: use spillslots only as large as actual values, not registers

Open
#3,647 0 comments 0 reactions 0 assignees View on GitHub
cranelift cranelift:area:regalloc enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.