Skip to main content

luaur_code_gen/functions/
replace_ir_utils_alt_b.rs

1use crate::enums::ir_block_kind::IrBlockKind;
2use crate::functions::add_use::add_use;
3use crate::functions::is_block_terminator::is_block_terminator;
4use crate::functions::kill_ir_utils_alt_b::kill_ir_function_u32_u32;
5use crate::functions::remove_use::remove_use;
6use crate::macros::codegen_assert::CODEGEN_ASSERT;
7use crate::records::ir_block::IrBlock;
8use crate::records::ir_function::IrFunction;
9use crate::records::ir_inst::IrInst;
10use crate::records::ir_op::IrOp;
11
12pub fn replace_ir_function_ir_block_u32_ir_inst(
13    function: &mut IrFunction,
14    block: &mut IrBlock,
15    inst_idx: u32,
16    mut replacement: IrInst,
17) {
18    // Add uses before removing new ones if those are the last ones keeping target operand alive
19    let rn = replacement.ops.size();
20    for i in 0..rn {
21        let op: IrOp = replacement.ops.as_slice()[i as usize];
22        add_use(function, op);
23    }
24
25    // If we introduced an earlier terminating instruction, all following instructions become dead
26    let inst_cmd = function.instructions[inst_idx as usize].cmd;
27    if !is_block_terminator(inst_cmd) && is_block_terminator(replacement.cmd) {
28        // Block has has to be fully constructed before replacement is performed
29        CODEGEN_ASSERT!(block.finish != !0u32);
30        CODEGEN_ASSERT!(inst_idx + 1 <= block.finish);
31
32        kill_ir_function_u32_u32(function, inst_idx + 1, block.finish);
33
34        // If killing that range killed the current block we have to undo replacement instruction uses and exit
35        if block.kind == IrBlockKind::Dead {
36            for i in 0..rn {
37                let op: IrOp = replacement.ops.as_slice()[i as usize];
38                remove_use(function, op);
39            }
40            return;
41        }
42
43        block.finish = inst_idx;
44    }
45
46    // Before we remove old argument uses, we have to place our new instruction
47    let copy: IrInst = function.instructions[inst_idx as usize].clone();
48
49    // Inherit existing use count (last use is skipped as it will be defined later)
50    replacement.use_count = function.instructions[inst_idx as usize].use_count;
51
52    function.instructions[inst_idx as usize] = replacement;
53
54    let cn = copy.ops.size();
55    for i in 0..cn {
56        let op: IrOp = copy.ops.as_slice()[i as usize];
57        remove_use(function, op);
58    }
59}