Skip to main content

luaur_code_gen/functions/
get_reload_address.rs

1use crate::enums::address_kind_a_64::AddressKindA64;
2use crate::enums::ir_op_kind::IrOpKind;
3use crate::enums::kind_a_64::KindA64;
4use crate::functions::get_reload_offset::get_reload_offset;
5use crate::functions::vm_const_op::vm_const_op;
6use crate::functions::vm_reg_op::vm_reg_op;
7use crate::records::address_a_64::AddressA64;
8use crate::records::register_a_64::RegisterA64;
9use crate::records::value_restore_location::ValueRestoreLocation;
10use luaur_vm::type_aliases::t_value::TValue;
11
12const fn reg(kind: KindA64, index: u8) -> RegisterA64 {
13    RegisterA64 {
14        bits: kind as u8 | (index << RegisterA64::INDEX_SHIFT),
15    }
16}
17
18const R_BASE: RegisterA64 = reg(KindA64::x, 25);
19const R_CONSTANTS: RegisterA64 = reg(KindA64::x, 22);
20const XZR: RegisterA64 = reg(KindA64::x, 31);
21
22fn mem(base: RegisterA64, data: i32) -> AddressA64 {
23    AddressA64 {
24        kind: AddressKindA64::imm,
25        base,
26        offset: RegisterA64::noreg,
27        data,
28    }
29}
30
31pub fn get_reload_address(location: ValueRestoreLocation) -> AddressA64 {
32    let op = location.op;
33
34    if op.kind() == IrOpKind::VmReg {
35        let offset = vm_reg_op(op) as i32 * core::mem::size_of::<TValue>() as i32
36            + get_reload_offset(location.kind);
37        return mem(R_BASE, offset);
38    }
39
40    // loads are 4/8/16 bytes; we conservatively limit the offset to fit assuming a 4b index
41    if op.kind() == IrOpKind::VmConst
42        && (vm_const_op(op) as usize * core::mem::size_of::<TValue>() <= AddressA64::kMaxOffset * 4)
43    {
44        let offset = vm_const_op(op) as i32 * core::mem::size_of::<TValue>() as i32
45            + get_reload_offset(location.kind);
46        return mem(R_CONSTANTS, offset);
47    }
48
49    AddressA64::address_a_64_register_a_64_register_a_64(XZR, XZR)
50}