Skip to main content

luaur_code_gen/functions/
setup_block_entry_state_optimize_const_prop.rs

1use crate::functions::propagate_tags_from_predecessors::propagate_tags_from_predecessors;
2use crate::functions::try_get_luau_tag_for_bc_type::try_get_luau_tag_for_bc_type;
3use crate::records::bytecode_type_info::BytecodeTypeInfo;
4use crate::records::cfg_info::CfgInfo;
5use crate::records::const_prop_state::ConstPropState;
6use crate::records::ir_block::IrBlock;
7use crate::records::ir_builder::IrBuilder;
8use crate::records::ir_function::IrFunction;
9use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
10
11fn luau_bytecode_type_optional_bit() -> u8 {
12    LuauBytecodeType::LBC_TYPE_OPTIONAL_BIT.0 as u8
13}
14
15pub fn setup_block_entry_state_ir_builder_ir_function_ir_block_const_prop_state(
16    build: &mut IrBuilder,
17    function: &mut IrFunction,
18    block: &IrBlock,
19    state: &mut ConstPropState,
20) {
21    let block_flags = block.flags;
22    let entry_arg_check_bit = 1u8 << 2;
23    if (block_flags & entry_arg_check_bit) != 0 {
24        return;
25    }
26
27    let type_info: &BytecodeTypeInfo = &function.bc_original_type_info;
28
29    for i in 0..type_info.argument_types.len() {
30        let et = type_info.argument_types[i];
31        let tag = et & !luau_bytecode_type_optional_bit();
32
33        if tag == LuauBytecodeType::LBC_TYPE_ANY.0 as u8
34            || (et & luau_bytecode_type_optional_bit()) != 0
35        {
36            continue;
37        }
38
39        let cfg: &CfgInfo = &function.cfg;
40        if (cfg.written.regs[i / 64] & (1u64 << (i % 64))) != 0 {
41            continue;
42        }
43
44        if cfg.written.vararg_seq && i >= cfg.written.vararg_start as usize {
45            continue;
46        }
47
48        if (cfg.captured.regs[i / 64] & (1u64 << (i % 64))) != 0 {
49            continue;
50        }
51
52        if let Some(vm_tag) =
53            try_get_luau_tag_for_bc_type(tag, /* ignore_optional_part */ true)
54        {
55            let op = build.vm_reg(i as u8);
56            state.update_tag(op, vm_tag);
57        }
58    }
59
60    let state_ptr = state as *mut ConstPropState;
61    let build_ptr = build as *mut IrBuilder;
62    propagate_tags_from_predecessors(
63        function,
64        block,
65        Box::new(move |i: usize| unsafe { (*state_ptr).regs[i].tag }),
66        Box::new(move |i: usize, tag: u8| unsafe {
67            let op = (*build_ptr).vm_reg(i as u8);
68            (*state_ptr).update_tag(op, tag);
69        }),
70    );
71}