luaur-code-gen 0.1.3

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::functions::propagate_tags_from_predecessors::propagate_tags_from_predecessors;
use crate::functions::try_get_luau_tag_for_bc_type::try_get_luau_tag_for_bc_type;
use crate::records::bytecode_type_info::BytecodeTypeInfo;
use crate::records::cfg_info::CfgInfo;
use crate::records::const_prop_state::ConstPropState;
use crate::records::ir_block::IrBlock;
use crate::records::ir_builder::IrBuilder;
use crate::records::ir_function::IrFunction;
use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;

fn luau_bytecode_type_optional_bit() -> u8 {
    LuauBytecodeType::LBC_TYPE_OPTIONAL_BIT.0 as u8
}

pub fn setup_block_entry_state_ir_builder_ir_function_ir_block_const_prop_state(
    build: &mut IrBuilder,
    function: &mut IrFunction,
    block: &IrBlock,
    state: &mut ConstPropState,
) {
    let block_flags = block.flags;
    let entry_arg_check_bit = 1u8 << 2;
    if (block_flags & entry_arg_check_bit) != 0 {
        return;
    }

    let type_info: &BytecodeTypeInfo = &function.bc_original_type_info;

    for i in 0..type_info.argument_types.len() {
        let et = type_info.argument_types[i];
        let tag = et & !luau_bytecode_type_optional_bit();

        if tag == LuauBytecodeType::LBC_TYPE_ANY.0 as u8
            || (et & luau_bytecode_type_optional_bit()) != 0
        {
            continue;
        }

        let cfg: &CfgInfo = &function.cfg;
        if (cfg.written.regs[i / 64] & (1u64 << (i % 64))) != 0 {
            continue;
        }

        if cfg.written.vararg_seq && i >= cfg.written.vararg_start as usize {
            continue;
        }

        if (cfg.captured.regs[i / 64] & (1u64 << (i % 64))) != 0 {
            continue;
        }

        if let Some(vm_tag) =
            try_get_luau_tag_for_bc_type(tag, /* ignore_optional_part */ true)
        {
            let op = build.vm_reg(i as u8);
            state.update_tag(op, vm_tag);
        }
    }

    let state_ptr = state as *mut ConstPropState;
    let build_ptr = build as *mut IrBuilder;
    propagate_tags_from_predecessors(
        function,
        block,
        Box::new(move |i: usize| unsafe { (*state_ptr).regs[i].tag }),
        Box::new(move |i: usize, tag: u8| unsafe {
            let op = (*build_ptr).vm_reg(i as u8);
            (*state_ptr).update_tag(op, tag);
        }),
    );
}