Skip to main content

luaur_code_gen/functions/
get_next_inst_use.rs

1use crate::enums::ir_block_kind::IrBlockKind;
2use crate::enums::ir_op_kind::IrOpKind;
3use crate::functions::is_pseudo::is_pseudo;
4use crate::macros::codegen_assert::CODEGEN_ASSERT;
5use crate::records::ir_function::IrFunction;
6use crate::records::ir_op::IrOp;
7use luaur_common::FFlag;
8
9pub fn get_next_inst_use(
10    function: &mut IrFunction,
11    target_inst_idx: u32,
12    start_inst_idx: u32,
13    in_vm_exit_sync: &mut bool,
14) -> u32 {
15    CODEGEN_ASSERT!((start_inst_idx as usize) < function.instructions.len());
16
17    let target_last_use = function.instructions[target_inst_idx as usize].last_use;
18
19    for inst_idx in start_inst_idx..=target_last_use {
20        let inst = function.instructions[inst_idx as usize].clone();
21
22        if is_pseudo(inst.cmd) {
23            continue;
24        }
25
26        if FFlag::LuauCodegenVmExitSync.get() {
27            for op in inst.ops.as_slice() {
28                if is_inst_use_for_op(function, inst_idx, target_inst_idx, *op, in_vm_exit_sync) {
29                    return inst_idx;
30                }
31            }
32        } else {
33            for op in inst.ops.as_slice() {
34                if op.kind() == IrOpKind::Inst && op.index() == target_inst_idx {
35                    return inst_idx;
36                }
37            }
38        }
39    }
40
41    CODEGEN_ASSERT!(false);
42    target_last_use
43}
44
45fn is_inst_use_for_op(
46    function: &mut IrFunction,
47    inst_idx: u32,
48    target_inst_idx: u32,
49    op: IrOp,
50    in_vm_exit_sync: &mut bool,
51) -> bool {
52    if op.kind() == IrOpKind::Inst {
53        return op.index() == target_inst_idx;
54    }
55
56    if op.kind() == IrOpKind::Block
57        && function.blocks[op.index() as usize].kind == IrBlockKind::ExitSync
58    {
59        if let Some(sync_info) = function.vm_exit_info.find(&inst_idx) {
60            for arg_op in sync_info.arg_ops.as_slice() {
61                CODEGEN_ASSERT!(arg_op.kind() == IrOpKind::Inst);
62
63                if arg_op.index() == target_inst_idx {
64                    *in_vm_exit_sync = true;
65                    return true;
66                }
67            }
68        }
69    }
70
71    false
72}