luaur-code-gen 0.1.0

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::enums::condition_x_64::ConditionX64;
use crate::enums::size_x_64::SizeX64;
use crate::records::ir_block::IrBlock;
use crate::records::ir_lowering_x_64::IrLoweringX64;
use crate::records::ir_op::IrOp;
use crate::records::operand_x_64::OperandX64;
use crate::records::register_x_64::RegisterX64;
use crate::records::scoped_reg_x_64::ScopedRegX64;
use luaur_vm::records::closure::Closure;
use luaur_vm::type_aliases::lua_table::LuaTable;

const K_STACK_OFFSET_TO_LOCALS: i32 = 16 + 32;

fn s_closure() -> OperandX64 {
    OperandX64::mem(
        SizeX64::qword,
        RegisterX64::noreg,
        1,
        RegisterX64::rsp,
        K_STACK_OFFSET_TO_LOCALS,
    )
}

fn mem(size: SizeX64, base: RegisterX64, disp: i32) -> OperandX64 {
    OperandX64::mem(size, RegisterX64::noreg, 1, base, disp)
}

impl IrLoweringX64 {
    pub fn check_safe_env(&mut self, target: IrOp, index: u32, next: &IrBlock) {
        unsafe {
            let mut tmp = ScopedRegX64 {
                owner: &mut self.regs,
                reg: RegisterX64::noreg,
            };
            tmp.alloc(SizeX64::qword);

            (*self.build).mov(OperandX64::reg(tmp.reg), s_closure());
            (*self.build).mov(
                OperandX64::reg(tmp.reg),
                mem(
                    SizeX64::qword,
                    tmp.reg,
                    core::mem::offset_of!(Closure, env) as i32,
                ),
            );
            (*self.build).cmp(
                mem(
                    SizeX64::byte,
                    tmp.reg,
                    core::mem::offset_of!(LuaTable, safeenv) as i32,
                ),
                OperandX64::imm(0),
            );
        }

        self.jump_or_abort_on_undef_condition_x_64_ir_op_u32_ir_block(
            ConditionX64::Equal,
            target,
            index,
            next,
        );
    }
}