luaur_bytecode/methods/
bytecode_graph_serializer_emit_bytecode.rs1use 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}