Skip to main content

luaur_bytecode/methods/
bytecode_graph_serializer_emit_bytecode.rs

1use crate::enums::bc_block_edge_kind::BcBlockEdgeKind;
2use crate::enums::bc_op_kind::BcOpKind;
3use crate::records::bc_block::BcBlock;
4use crate::records::bc_function::VmConst;
5use crate::records::bc_inst_helper::BcInstHelper;
6use crate::records::bc_jump::BcJump;
7use crate::records::bc_op::BcOp;
8use crate::records::bytecode_graph_serializer::BytecodeGraphSerializer;
9use alloc::vec::Vec;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl<'a> BytecodeGraphSerializer<'a> {
13    pub fn emit_bytecode(&mut self) -> Vec<u32> {
14        let schedule = self.reschedule();
15        let mut insns_pc: Vec<u32> = Vec::new();
16        insns_pc.resize(self.func.instructions.len(), 0);
17
18        for i in 0..schedule.len() {
19            let block_op = schedule[i as usize];
20            let fallthrough = {
21                let block: &BcBlock = &self.func.blocks[block_op.index as usize];
22                block
23                    .successors
24                    .iter()
25                    .find(|edge| edge.kind == BcBlockEdgeKind::Fallthrough)
26                    .map(|edge| edge.target)
27            };
28            if let Some(fallthrough_op) = fallthrough {
29                if fallthrough_op != self.func.exit_block
30                    && (i + 1 >= schedule.len() || fallthrough_op != schedule[(i + 1) as usize])
31                {
32                    let mut jump = BcJump::<VmConst>::create(self.func);
33                    jump.set_target(fallthrough_op);
34                    jump.append_to(block_op);
35                    insns_pc.resize(self.func.instructions.len(), 0);
36                }
37            }
38            let ops = {
39                let block: &mut BcBlock = self.func.block_op(block_op);
40                block.startpc = self.bcb.get_debug_pc();
41                block.ops.iter().cloned().collect::<Vec<_>>()
42            };
43            for op in ops {
44                LUAU_ASSERT!(op.kind == BcOpKind::Inst);
45                insns_pc[op.index as usize] = self.bcb.get_debug_pc();
46                self.emit_instruction(op);
47            }
48        }
49
50        let mut jumps = core::mem::take(&mut self.jumps);
51        for jump in jumps.iter_mut() {
52            self.patch_jump(jump);
53        }
54        self.jumps = jumps;
55
56        if self.error {
57            Vec::new()
58        } else {
59            insns_pc
60        }
61    }
62}