luaur_code_gen/functions/
build_bytecode_blocks.rs1use crate::functions::get_jump_target::get_jump_target;
2use crate::functions::get_op_length::get_op_length;
3use crate::functions::is_fast_call::is_fast_call;
4use crate::records::bytecode_block::BytecodeBlock;
5use crate::records::ir_function::IrFunction;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
8
9macro_rules! CODEGEN_ASSERT {
10 ($expr:expr) => {
11 assert!($expr);
12 };
13}
14
15pub fn build_bytecode_blocks(function: &mut IrFunction, jump_targets: &[u8]) {
16 CODEGEN_ASSERT!(!function.proto.is_null());
17
18 let proto = unsafe { &*function.proto };
19 let bc_blocks = &mut function.bc_blocks;
20
21 bc_blocks.push(BytecodeBlock {
23 startpc: 0,
24 finishpc: -1,
25 });
26
27 let mut previ = 0;
28 let mut i = 0;
29
30 while i < proto.sizecode {
31 let pc_val = unsafe { *proto.code.add(i as usize) };
32 let op_val = LUAU_INSN_OP(pc_val) as u8;
33 let op: LuauOpcode = unsafe { core::mem::transmute(op_val) };
34
35 let nexti = i + get_op_length(op);
36
37 if i != 0 && jump_targets[i as usize] != 0 {
39 if let Some(last) = bc_blocks.last_mut() {
40 last.finishpc = previ;
41 }
42 bc_blocks.push(BytecodeBlock {
43 startpc: i,
44 finishpc: -1,
45 });
46 }
47
48 let target = get_jump_target(pc_val, i as u32);
49
50 if target >= 0 && !is_fast_call(op) {
52 if let Some(last) = bc_blocks.last_mut() {
53 last.finishpc = i;
54 }
55
56 if jump_targets[nexti as usize] == 0 {
58 bc_blocks.push(BytecodeBlock {
59 startpc: nexti,
60 finishpc: -1,
61 });
62 }
63 }
64 else if op == LuauOpcode::LOP_RETURN {
66 if let Some(last) = bc_blocks.last_mut() {
67 last.finishpc = i;
68 }
69 }
70
71 previ = i;
72 i = nexti;
73 CODEGEN_ASSERT!(i <= proto.sizecode);
74 }
75}