Skip to main content

luaur_code_gen/methods/
ir_reg_alloc_a_64_alloc_temp.rs

1use crate::enums::kind_a_64::KindA64;
2use crate::functions::countlz_bit_utils::countlz_u32;
3use crate::functions::countrz_bit_utils::countrz_u32;
4use crate::macros::codegen_assert::CODEGEN_ASSERT;
5use crate::records::ir_reg_alloc_a_64::IrRegAllocA64;
6use crate::records::register_a_64::RegisterA64;
7use crate::records::set::Set;
8use luaur_common::FFlag;
9
10impl IrRegAllocA64 {
11    pub fn alloc_temp(&mut self, kind: KindA64) -> RegisterA64 {
12        if FFlag::LuauCodegenVmExitSync.get() {
13            self.alloc_action_count += 1;
14        }
15
16        let set = self.get_set(kind) as *mut Set;
17
18        if unsafe { (*set).free } == 0 {
19            // Try to find and spill a register that is not used in the current instruction and has the furthest next use
20            let furthest_use_target =
21                unsafe { self.find_instruction_with_furthest_next_use(&mut *set) };
22            if furthest_use_target != Self::kInvalidInstIdx {
23                unsafe {
24                    self.spill_set_u32_u32(&mut *set, self.curr_inst_idx, furthest_use_target)
25                };
26                CODEGEN_ASSERT!(unsafe { (*set).free } != 0);
27            } else {
28                self.error = true;
29                return RegisterA64 {
30                    bits: (kind as u8) & RegisterA64::KIND_MASK,
31                };
32            }
33        }
34
35        let mut reg = 31 - countlz_u32(unsafe { (*set).free }) as i32;
36
37        if FFlag::DebugCodegenChaosA64.get() {
38            reg = countrz_u32(unsafe { (*set).free }) as i32; // allocate from low end; this causes extra conflicts for calls
39        }
40
41        unsafe {
42            (*set).free &= !(1u32 << reg);
43            (*set).temp |= 1u32 << reg;
44            CODEGEN_ASSERT!((*set).defs[reg as usize] == Self::kInvalidInstIdx);
45        }
46
47        RegisterA64 {
48            bits: ((kind as u8) & RegisterA64::KIND_MASK)
49                | ((reg as u8) << RegisterA64::INDEX_SHIFT),
50        }
51    }
52}