Skip to main content

luaur_code_gen/methods/
ir_reg_alloc_x_64_alloc_reg.rs

1use crate::enums::size_x_64::SizeX64;
2use crate::macros::codegen_assert::CODEGEN_ASSERT;
3use crate::records::ir_reg_alloc_x_64::IrRegAllocX64;
4use crate::records::register_x_64::RegisterX64;
5
6impl IrRegAllocX64 {
7    pub fn alloc_reg(&mut self, size: SizeX64, inst_idx: u32) -> RegisterX64 {
8        if luaur_common::FFlag::LuauCodegenVmExitSync.get() {
9            self.alloc_action_count += 1;
10        }
11
12        if size == SizeX64::xmmword {
13            for i in 0..self.usable_xmm_reg_count as usize {
14                if self.free_xmm_map[i] {
15                    self.free_xmm_map[i] = false;
16                    self.xmm_inst_users[i] = inst_idx;
17                    return RegisterX64 {
18                        bits: ((i as u8) << RegisterX64::INDEX_SHIFT) | (size as u8),
19                    };
20                }
21            }
22        } else {
23            for reg in crate::records::ir_reg_alloc_x_64::IrRegAllocX64::K_GPR_ALLOC_ORDER.iter() {
24                if self.free_gpr_map[reg.index() as usize] {
25                    self.free_gpr_map[reg.index() as usize] = false;
26                    self.gpr_inst_users[reg.index() as usize] = inst_idx;
27                    return RegisterX64 {
28                        bits: (reg.index() << RegisterX64::INDEX_SHIFT) | (size as u8),
29                    };
30                }
31            }
32        }
33
34        // Out of registers, spill the value with the furthest next use
35        let reg_inst_users = if size == SizeX64::xmmword {
36            &self.xmm_inst_users
37        } else {
38            &self.gpr_inst_users
39        };
40
41        let furthest_use_target = self.find_instruction_with_furthest_next_use(reg_inst_users);
42        if furthest_use_target != crate::records::ir_data::k_invalid_inst_idx {
43            let reg = unsafe {
44                let instructions = &(*self.function).instructions;
45                instructions[furthest_use_target as usize].reg_x64
46            };
47            let mut reg = reg;
48            reg.bits = (reg.index() << RegisterX64::INDEX_SHIFT) | (size as u8);
49
50            return self.take_reg(reg, inst_idx);
51        }
52
53        CODEGEN_ASSERT!(false, "Out of registers to allocate");
54        RegisterX64::noreg
55    }
56}