luaur_compiler/methods/
compiler_compile_stat_for.rs1use crate::records::compiler::Compiler;
2use crate::records::reg_scope::RegScope;
3use luaur_ast::records::ast_stat_for::AstStatFor;
4use luaur_common::enums::luau_opcode::LuauOpcode;
5
6impl Compiler {
7 pub fn compile_stat_for(&mut self, stat: *mut AstStatFor) {
8 unsafe {
9 let stat_ref = &*stat;
10 let mut rs = self.reg_scope_compiler();
11
12 if self.options.optimization_level >= 2
13 && self.is_constant(stat_ref.to)
14 && self.is_constant(stat_ref.from)
15 && (stat_ref.step.is_null() || self.is_constant(stat_ref.step))
16 {
17 if self.try_compile_unrolled_for(
22 stat,
23 luaur_common::FInt::LuauCompileLoopUnrollThreshold.get(),
24 luaur_common::FInt::LuauCompileLoopUnrollThresholdMaxBoost.get(),
25 ) {
26 return;
27 }
28 }
29
30 let old_locals = self.local_stack.len();
31 let old_jumps = self.loop_jumps.len();
32
33 self.loops.push(crate::records::r#loop::Loop {
34 local_offset: old_locals,
35 local_offset_continue: old_locals,
36 continue_used: core::ptr::null_mut(),
37 });
38 self.has_loops = true;
39
40 let regs = self.alloc_reg(stat as *mut _, 3);
41 let varregallocpc = (*self.bytecode).get_debug_pc();
42 let mut varreg = regs + 2;
43
44 if let Some(il) = self.variables.find(&stat_ref.var) {
45 if il.written {
46 varreg = self.alloc_reg(stat as *mut _, 1);
47 }
48 }
49
50 self.compile_expr_temp(stat_ref.from, regs + 2);
51 self.compile_expr_temp(stat_ref.to, regs + 0);
52
53 if !stat_ref.step.is_null() {
54 self.compile_expr_temp(stat_ref.step, regs + 1);
55 } else {
56 (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADN, regs + 1, 1, 0);
57 }
58
59 let for_label = (*self.bytecode).emit_label();
60 (*self.bytecode).emit_ad(LuauOpcode::LOP_FORNPREP, regs, 0);
61 let loop_label = (*self.bytecode).emit_label();
62
63 if varreg != regs + 2 {
64 (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, varreg, regs + 2, 0);
65 }
66
67 self.push_local(stat_ref.var, varreg, varregallocpc);
68 self.compile_stat(stat_ref.body as *mut _);
69
70 self.close_locals(old_locals);
71 self.pop_locals(old_locals);
72 self.set_debug_line_ast_node(stat as *mut _);
73
74 let cont_label = (*self.bytecode).emit_label();
75 let back_label = (*self.bytecode).emit_label();
76 (*self.bytecode).emit_ad(LuauOpcode::LOP_FORNLOOP, regs, 0);
77 let end_label = (*self.bytecode).emit_label();
78
79 self.patch_jump(stat as *mut _, for_label, end_label);
80 self.patch_jump(stat as *mut _, back_label, loop_label);
81
82 self.patch_loop_jumps(stat as *mut _, old_jumps, end_label, cont_label);
83 self.loop_jumps.resize(
84 old_jumps,
85 crate::records::loop_jump::LoopJump {
86 r#type: crate::enums::type_compiler::Type::Break,
87 label: 0,
88 },
89 );
90
91 self.loops.pop();
92 }
93 }
94}