luaur-code-gen 0.1.3

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::enums::ir_block_kind::IrBlockKind;
use crate::enums::ir_op_kind::IrOpKind;
use crate::functions::is_pseudo::is_pseudo;
use crate::macros::codegen_assert::CODEGEN_ASSERT;
use crate::records::ir_function::IrFunction;
use crate::records::ir_op::IrOp;
use luaur_common::FFlag;

pub fn get_next_inst_use(
    function: &mut IrFunction,
    target_inst_idx: u32,
    start_inst_idx: u32,
    in_vm_exit_sync: &mut bool,
) -> u32 {
    CODEGEN_ASSERT!((start_inst_idx as usize) < function.instructions.len());

    let target_last_use = function.instructions[target_inst_idx as usize].last_use;

    for inst_idx in start_inst_idx..=target_last_use {
        let inst = function.instructions[inst_idx as usize].clone();

        if is_pseudo(inst.cmd) {
            continue;
        }

        if FFlag::LuauCodegenVmExitSync.get() {
            for op in inst.ops.as_slice() {
                if is_inst_use_for_op(function, inst_idx, target_inst_idx, *op, in_vm_exit_sync) {
                    return inst_idx;
                }
            }
        } else {
            for op in inst.ops.as_slice() {
                if op.kind() == IrOpKind::Inst && op.index() == target_inst_idx {
                    return inst_idx;
                }
            }
        }
    }

    CODEGEN_ASSERT!(false);
    target_last_use
}

fn is_inst_use_for_op(
    function: &mut IrFunction,
    inst_idx: u32,
    target_inst_idx: u32,
    op: IrOp,
    in_vm_exit_sync: &mut bool,
) -> bool {
    if op.kind() == IrOpKind::Inst {
        return op.index() == target_inst_idx;
    }

    if op.kind() == IrOpKind::Block
        && function.blocks[op.index() as usize].kind == IrBlockKind::ExitSync
    {
        if let Some(sync_info) = function.vm_exit_info.find(&inst_idx) {
            for arg_op in sync_info.arg_ops.as_slice() {
                CODEGEN_ASSERT!(arg_op.kind() == IrOpKind::Inst);

                if arg_op.index() == target_inst_idx {
                    *in_vm_exit_sync = true;
                    return true;
                }
            }
        }
    }

    false
}