Skip to content

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

@cfallin

Description

@cfallin

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions