Skip to main content

luaur_bytecode/methods/
bytecode_graph_serializer_get_register.rs

1use crate::enums::bc_op_kind::BcOpKind;
2use crate::records::bc_op::BcOp;
3use crate::records::bc_phi::BcPhi;
4use crate::type_aliases::reg::Reg;
5
6use luaur_common::macros::luau_assert::LUAU_ASSERT;
7use luaur_common::macros::luau_unreachable::LUAU_UNREACHABLE;
8
9impl<'a> crate::records::bytecode_graph_serializer::BytecodeGraphSerializer<'a> {
10    pub fn get_register(&mut self, op: BcOp) -> Reg {
11        match op.kind {
12            BcOpKind::Phi => {
13                // Avoid holding `&mut` to `self.func` while recursively calling `self.get_register`.
14                let ops_len;
15                let first_op;
16                {
17                    let phi: &mut BcPhi = self.func.phi_op(op);
18                    LUAU_ASSERT!(phi.ops.len() > 0);
19                    LUAU_ASSERT!(phi.ops[0] != op);
20
21                    ops_len = phi.ops.len();
22                    first_op = phi.ops[0];
23
24                    // Additional assert: all phi operands map to the same register.
25                    // We snapshot the operands count now to iterate after recursion.
26                }
27
28                let res = self.get_register(first_op);
29
30                let mut i = 0usize;
31                loop {
32                    if i >= ops_len {
33                        break;
34                    }
35
36                    let phi_op = {
37                        let phi: &mut BcPhi = self.func.phi_op(op);
38                        phi.ops[i]
39                    };
40
41                    LUAU_ASSERT!(res == self.get_register(phi_op));
42                    i += 1;
43                }
44
45                res
46            }
47            BcOpKind::Inst => {
48                let res = self.func.regs.get(&op);
49                LUAU_ASSERT!(res.is_some());
50                *res.unwrap()
51            }
52            BcOpKind::Proj => {
53                // Avoid holding `&mut` to `self.func` while recursively calling `self.get_register`.
54                let proj = {
55                    let proj: &mut crate::records::bc_proj::BcProj = self.func.proj_op(op);
56                    *proj
57                };
58                let base = self.get_register(proj.op);
59                base + proj.index as Reg
60            }
61            BcOpKind::VmReg => op.index as Reg,
62            _ => {
63                LUAU_UNREACHABLE!();
64            }
65        }
66    }
67}