Skip to main content

luaur_bytecode/methods/
call_inliner_migrate_blocks.rs

1use crate::enums::bc_block_flag::BcBlockFlag;
2use crate::enums::bc_op_kind::BcOpKind;
3use crate::records::bc_block::BcBlock;
4use crate::records::bc_block_edge::BcBlockEdge;
5use crate::records::bc_op::BcOp;
6use crate::records::bc_ref::BcRef;
7use crate::records::call_inliner::CallInliner;
8use luaur_common::enums::luau_opcode::LuauOpcode;
9
10impl<'a> CallInliner<'a> {
11    pub fn migrate_blocks(&mut self, next_block: &mut BcRef<'a, BcBlock>) -> bool {
12        let call_block = self.call.base.operator_deref().block;
13        let call_block_ref = self.caller.block(call_block);
14        let insn_block_sort_key = call_block_ref.operator_deref().sortkey;
15        let insn_block_chain_key = call_block_ref.operator_deref().chainkey;
16        let mut max_chain_key = 0;
17
18        for i in 0..self.target.blocks.len() {
19            let target_block_sortkey = self.target.blocks[i].sortkey;
20            let target_block_ops: Vec<BcOp> = self.target.blocks[i].ops.iter().cloned().collect();
21
22            let caller_block_idx = (self.caller_blocks_size_before_inline + i as u32) as usize;
23            let caller_block_op = BcOp::bc_op_bc_op_kind_u32(
24                BcOpKind::Block,
25                self.caller_blocks_size_before_inline + i as u32,
26            );
27
28            if i as u32 == self.target.exit_block.index {
29                let caller_block = &mut self.caller.blocks[caller_block_idx];
30                caller_block.sortkey = BcBlock::K_BLOCK_NO_START_PC;
31                caller_block.flags |= BcBlockFlag::Dead as u8;
32                continue;
33            }
34
35            {
36                let caller_block = &mut self.caller.blocks[caller_block_idx];
37                caller_block.sortkey = insn_block_sort_key;
38                caller_block.chainkey = insn_block_chain_key + target_block_sortkey;
39                max_chain_key = std::cmp::max(caller_block.chainkey, max_chain_key);
40            }
41
42            // Migrate successors
43            let target_successors = self.target.blocks[i].successors.clone();
44            for e in &target_successors {
45                if e.target != self.target.exit_block {
46                    let mapped_target = self.map_block_op(e.target);
47                    let caller_block = &mut self.caller.blocks[caller_block_idx];
48                    caller_block.successors.push_back(BcBlockEdge {
49                        kind: e.kind,
50                        target: mapped_target,
51                    });
52                }
53            }
54
55            // Migrate predecessors
56            let target_predecessors = self.target.blocks[i].predecessors.clone();
57            for e in &target_predecessors {
58                let mapped_target = self.map_block_op(e.target);
59                let caller_block = &mut self.caller.blocks[caller_block_idx];
60                caller_block.predecessors.push_back(BcBlockEdge {
61                    kind: e.kind,
62                    target: mapped_target,
63                });
64            }
65
66            // Migrate instructions
67            for op in target_block_ops {
68                let inst_op_code = self.target.inst_op(op).op;
69                if inst_op_code == LuauOpcode::LOP_GETVARARGS {
70                    self.replace_get_var_arg(caller_block_op, op);
71                } else if inst_op_code == LuauOpcode::LOP_RETURN {
72                    if !self.replace_return(next_block, caller_block_op, op) {
73                        return false;
74                    }
75                } else {
76                    let caller_inst_op = self.map_inst_op(op);
77                    self.caller.blocks[caller_block_idx].append_instruction(caller_inst_op);
78                    self.caller.inst_op(caller_inst_op).block = caller_block_op;
79                }
80            }
81        }
82
83        self.caller.block(call_block).operator_deref_mut().chainkey = max_chain_key + 1;
84        next_block.operator_deref_mut().chainkey = max_chain_key + 2;
85
86        true
87    }
88}