luaur-code-gen 0.1.0

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::enums::ir_cmd::IrCmd;
use crate::enums::ir_op_kind::IrOpKind;
use crate::macros::op_a::op_a;
use crate::macros::op_b::op_b;
use crate::macros::opt_op_a::OPT_OP_A;
use crate::macros::opt_op_b::OPT_OP_B;
use crate::records::buffer_access_base::BufferAccessBase;
use crate::records::const_prop_state::ConstPropState;
use crate::records::ir_op::IrOp;

impl ConstPropState {
    pub fn get_offset_base(&mut self, value: IrOp) -> BufferAccessBase {
        let mut base = BufferAccessBase {
            op: value,
            scale: 1,
            offset: 0,
        };

        loop {
            if base.op.kind() != IrOpKind::Inst {
                break;
            }

            let inst = unsafe { (*self.function).inst_op(base.op).clone() };
            let lhs_num = unsafe { (*self.function).as_double_op(OPT_OP_A(inst.clone())) };
            let rhs_num = unsafe { (*self.function).as_double_op(OPT_OP_B(inst.clone())) };
            let lhs_int = unsafe { (*self.function).as_int_op(OPT_OP_A(inst.clone())) };
            let rhs_int = unsafe { (*self.function).as_int_op(OPT_OP_B(inst.clone())) };

            if inst.cmd == IrCmd::ADD_NUM
                && lhs_num.is_some()
                && self.is_valid_double_for_immediate(lhs_num.unwrap())
            {
                base.offset += (lhs_num.unwrap() as i32) * base.scale;
                base.op = op_b(inst);
            } else if inst.cmd == IrCmd::ADD_NUM
                && rhs_num.is_some()
                && self.is_valid_double_for_immediate(rhs_num.unwrap())
            {
                base.offset += (rhs_num.unwrap() as i32) * base.scale;
                base.op = op_a(&mut inst.clone());
            } else if inst.cmd == IrCmd::SUB_NUM
                && rhs_num.is_some()
                && self.is_valid_double_for_immediate(rhs_num.unwrap())
            {
                base.offset -= (rhs_num.unwrap() as i32) * base.scale;
                base.op = op_a(&mut inst.clone());
            } else if inst.cmd == IrCmd::MUL_NUM
                && lhs_num.is_some()
                && self.is_valid_double_for_immediate(lhs_num.unwrap())
            {
                base.scale *= lhs_num.unwrap() as i32;
                base.op = op_b(inst);
            } else if inst.cmd == IrCmd::MUL_NUM
                && rhs_num.is_some()
                && self.is_valid_double_for_immediate(rhs_num.unwrap())
            {
                base.scale *= rhs_num.unwrap() as i32;
                base.op = op_a(&mut inst.clone());
            } else if inst.cmd == IrCmd::ADD_INT
                && lhs_int.is_some()
                && self.is_valid_integer_for_immediate(lhs_int.unwrap())
            {
                base.offset += lhs_int.unwrap() * base.scale;
                base.op = op_b(inst);
            } else if inst.cmd == IrCmd::ADD_INT
                && rhs_int.is_some()
                && self.is_valid_integer_for_immediate(rhs_int.unwrap())
            {
                base.offset += rhs_int.unwrap() * base.scale;
                base.op = op_a(&mut inst.clone());
            } else if inst.cmd == IrCmd::SUB_INT
                && rhs_int.is_some()
                && self.is_valid_integer_for_immediate(rhs_int.unwrap())
            {
                base.offset -= rhs_int.unwrap() * base.scale;
                base.op = op_a(&mut inst.clone());
            } else if inst.cmd == IrCmd::TRUNCATE_UINT {
                base.op = op_a(&mut inst.clone());
            } else {
                break;
            }

            if !self.is_valid_integer_for_immediate(base.offset)
                || !self.is_valid_integer_for_immediate(base.scale)
            {
                break;
            }
        }

        base
    }
}