luaur_bytecode/methods/
call_inliner_migrate_blocks.rs1use 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 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 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 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}