Skip to main content

luaur_code_gen/functions/
get_loop_step_k.rs

1use crate::enums::ir_cmd::IrCmd;
2use crate::enums::ir_op_kind::IrOpKind;
3use crate::macros::op_a::op_a;
4use crate::macros::op_b::op_b;
5use crate::records::ir_builder::IrBuilder;
6use crate::records::ir_op::IrOp;
7use luaur_vm::enums::lua_type::lua_Type;
8
9pub fn get_loop_step_k(build: &mut IrBuilder, ra: i32) -> IrOp {
10    let active_block_idx = build.active_block_idx as usize;
11    let active = &build.function.blocks[active_block_idx];
12
13    if active.start + 2 <= build.function.instructions.len() as u32 {
14        let instructions_size = build.function.instructions.len();
15        let mut sv = build.function.instructions[instructions_size - 2].clone();
16        let mut st = build.function.instructions[instructions_size - 1].clone();
17
18        // We currently expect to match IR generated from LOADN/LOADK so we match a particular sequence of opcodes
19        // In the future this can be extended to cover opposite STORE order as well as STORE_SPLIT_TVALUE
20        if sv.cmd == IrCmd::STORE_DOUBLE
21            && op_a(&mut sv).kind() == IrOpKind::VmReg
22            && op_a(&mut sv).index() == (ra + 1) as u32
23            && op_b(sv.clone()).kind() == IrOpKind::Constant
24            && st.cmd == IrCmd::STORE_TAG
25            && op_a(&mut st).kind() == IrOpKind::VmReg
26            && op_a(&mut st).index() == (ra + 1) as u32
27            && build.function.tag_op(op_b(st.clone())) == lua_Type::LUA_TNUMBER as u8
28        {
29            return op_b(sv);
30        }
31    }
32
33    build.undef()
34}