luaur_bytecode/methods/
bytecode_builder_fold_jumps.rs1use crate::records::bytecode_builder::BytecodeBuilder;
2use crate::records::jump::Jump;
3use luaur_common::enums::luau_opcode::LuauOpcode;
4use luaur_common::macros::luau_assert::LUAU_ASSERT;
5use luaur_common::macros::luau_insn_d::LUAU_INSN_D;
6use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
7
8impl BytecodeBuilder {
9 pub fn fold_jumps(&mut self) {
10 if self.has_long_jumps {
13 return;
14 }
15
16 for jump in &mut self.jumps {
17 let jump_label: u32 = jump.source;
18 let jump_insn: u32 = self.insns[jump_label as usize];
19
20 let mut target_label: i32 = jump_label as i32 + 1 + LUAU_INSN_D(jump_insn);
27 LUAU_ASSERT!((target_label as usize) < self.insns.len());
28 let mut target_insn: u32 = self.insns[target_label as usize];
29
30 while LUAU_INSN_OP(target_insn) == LuauOpcode::LOP_JUMP as u32
31 && LUAU_INSN_D(target_insn) >= 0
32 {
33 target_label = target_label + 1 + LUAU_INSN_D(target_insn);
34 LUAU_ASSERT!((target_label as usize) < self.insns.len());
35 target_insn = self.insns[target_label as usize];
36 }
37
38 let offset: i32 = target_label - jump_label as i32 - 1;
39
40 if LUAU_INSN_OP(jump_insn) == LuauOpcode::LOP_JUMP as u32
42 && LUAU_INSN_OP(target_insn) == LuauOpcode::LOP_RETURN as u32
43 {
44 self.insns[jump_label as usize] = target_insn;
45 } else if (offset as i16) as i32 == offset {
46 let mut insn = self.insns[jump_label as usize];
47 insn &= 0xffff;
48 insn |= ((offset as u16) as u32) << 16;
49 self.insns[jump_label as usize] = insn;
50 }
51
52 jump.target = target_label as u32;
53 }
54 }
55}