Skip to main content

luaur_code_gen/functions/
alloc_spill.rs

1use crate::enums::kind_a_64::KindA64;
2
3use crate::functions::countrz_bit_utils::countrz_u32;
4use crate::functions::countrz_bit_utils_alt_b::countrz_u64;
5
6pub fn alloc_spill(free: &mut u64, kind: KindA64) -> i32 {
7    // to support larger stack frames, we need to ensure qN is allocated at 16b boundary to fit in ldr/str encoding
8    const K_STACK_SIZE: u64 = 256;
9    assert!(K_STACK_SIZE <= 256);
10
11    let mut search = *free;
12
13    // qN registers use two consecutive slots
14    if kind == KindA64::q {
15        // Make sure bit N is set only if bit N+1 is also set
16        search = *free & (*free >> 1);
17
18        // Prevent qN from allocating at stack/extra spill storage boundary (by reserving last stack slot)
19        // In the original code this is (kSpillSlots - 1); we keep the same behavior with kSpillSlots=22.
20        const K_SPILL_SLOTS: u32 = 22;
21        search &= !(1u64 << (K_SPILL_SLOTS - 1));
22    }
23
24    let slot = countrz_u64(search);
25    if slot == 64 {
26        return -1;
27    }
28
29    let mask = (if kind == KindA64::q { 3u64 } else { 1u64 }) << (slot as u64);
30
31    // CODEGEN_ASSERT((free & mask) == mask)
32    assert!((*free & mask) == mask);
33
34    *free &= !mask;
35
36    slot
37}