Skip to main content

luaur_code_gen/methods/
ir_builder_rebuild_bytecode_basic_blocks.rs

1use crate::enums::ir_block_kind::IrBlockKind;
2use crate::functions::build_bytecode_blocks::build_bytecode_blocks;
3use crate::functions::get_jump_target::get_jump_target;
4use crate::functions::get_op_length::get_op_length;
5use crate::functions::is_fast_call::is_fast_call;
6use crate::records::ir_builder::IrBuilder;
7use crate::type_aliases::instruction_ir_builder::Instruction;
8use alloc::vec::Vec;
9use luaur_common::enums::luau_opcode::LuauOpcode;
10use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
11
12impl IrBuilder {
13    pub fn rebuild_bytecode_basic_blocks(&mut self, proto: *mut luaur_vm::records::proto::Proto) {
14        unsafe {
15            let sizecode = (*proto).sizecode as usize;
16            let code = (*proto).code;
17
18            self.inst_index_to_block.resize(sizecode, u32::MAX);
19
20            let mut jump_targets = Vec::with_capacity(sizecode);
21            jump_targets.resize(sizecode, 0u8);
22
23            let mut i: usize = 0;
24            while i < sizecode {
25                let pc: *const Instruction = code.add(i);
26                let op = LuauOpcode::from(LUAU_INSN_OP(*pc) as u8);
27
28                let target = get_jump_target(*pc, i as u32);
29
30                if target >= 0 && !is_fast_call(op) {
31                    jump_targets[target as usize] = 1;
32                }
33
34                i += get_op_length(op) as usize;
35                debug_assert!(i <= sizecode);
36            }
37
38            jump_targets[0] = 1;
39
40            for j in 0..sizecode {
41                if jump_targets[j] != 0 {
42                    let b = self.block(IrBlockKind::Bytecode);
43                    self.inst_index_to_block[j] = b.index();
44                }
45            }
46
47            build_bytecode_blocks(&mut self.function, &jump_targets);
48        }
49    }
50}