Skip to main content

luaur_code_gen/methods/
ir_builder_clone.rs

1use crate::enums::ir_cmd::IrCmd;
2use crate::enums::ir_op_kind::IrOpKind;
3use crate::functions::add_use::add_use;
4use crate::functions::is_pseudo::is_pseudo;
5use crate::functions::kill_ir_utils::kill_ir_function_ir_inst;
6use crate::macros::codegen_assert::CODEGEN_ASSERT;
7use crate::records::ir_builder::IrBuilder;
8use luaur_common::records::dense_hash_map::DenseHashMap;
9
10impl IrBuilder {
11    pub fn clone(&mut self, source_idxs: Vec<u32>, remove_current_terminator: bool) {
12        let mut inst_redir: DenseHashMap<u32, u32> = DenseHashMap::new(!0u32);
13
14        for source_idx in source_idxs {
15            let source = self.function.blocks[source_idx as usize];
16
17            if remove_current_terminator && self.in_terminated_block {
18                let finish = self.function.blocks[self.active_block_idx as usize].finish;
19                let term = &mut self.function.instructions[finish as usize] as *mut _;
20                unsafe {
21                    kill_ir_function_ir_inst(&mut self.function, &mut *term);
22                }
23                self.in_terminated_block = false;
24            }
25
26            const K_BLOCK_FLAG_SAFE_ENV_CHECK: u8 = 1 << 0;
27            if (source.flags & K_BLOCK_FLAG_SAFE_ENV_CHECK) != 0 {
28                CODEGEN_ASSERT!(source.startpc != crate::records::ir_block::kBlockNoStartPc);
29                let exit = self.vm_exit(source.startpc);
30                self.inst_ir_cmd_ir_op(IrCmd::CHECK_SAFE_ENV, exit);
31            }
32
33            for index in source.start..=source.finish {
34                CODEGEN_ASSERT!((index as usize) < self.function.instructions.len());
35                let mut clone = self.function.instructions[index as usize].clone();
36
37                if is_pseudo(clone.cmd) {
38                    CODEGEN_ASSERT!(clone.use_count == 0);
39                    continue;
40                }
41
42                for op in clone.ops.as_mut_slice() {
43                    if op.kind() == IrOpKind::Inst {
44                        if let Some(&new_index) = inst_redir.find(&op.index()) {
45                            *op = crate::records::ir_op::IrOp::ir_op_ir_op_kind_u32(
46                                IrOpKind::Inst,
47                                new_index,
48                            );
49                        } else {
50                            CODEGEN_ASSERT!(false);
51                        }
52                    }
53                }
54
55                for &op in clone.ops.as_slice() {
56                    add_use(&mut self.function, op);
57                }
58
59                *inst_redir.get_or_insert(index) = self.function.instructions.len() as u32;
60                self.inst_ir_cmd_ir_ops(clone.cmd, &clone.ops);
61            }
62        }
63    }
64}