luaur_code_gen/functions/execute_forgprep.rs
1//! Node: `cxx:Function:Luau.CodeGen:CodeGen/src/CodeGenUtils.cpp:762:execute_forgprep`
2//! Source: `CodeGen/src/CodeGenUtils.cpp`
3//! Graph edges:
4//! - declared_by: source_file CodeGen/src/CodeGenUtils.cpp
5//! - source_includes:
6//! - includes -> source_file CodeGen/src/CodeGenUtils.h
7//! - includes -> source_file VM/src/lvm.h
8//! - includes -> source_file VM/src/lbuiltins.h
9//! - includes -> source_file VM/src/lbytecode.h
10//! - includes -> source_file VM/src/ldebug.h
11//! - includes -> source_file VM/src/ldo.h
12//! - includes -> source_file VM/src/lfunc.h
13//! - includes -> source_file VM/src/lgc.h
14//! - includes -> source_file VM/src/lmem.h
15//! - includes -> source_file VM/src/lnumutils.h
16//! - includes -> source_file VM/src/lstate.h
17//! - includes -> source_file VM/src/lstring.h
18//! - includes -> source_file VM/src/ltable.h
19//! - includes -> source_file VM/src/ludata.h
20//! - incoming:
21//! - declares <- source_file CodeGen/src/CodeGenUtils.cpp
22//! - outgoing:
23//! - type_ref -> type_alias lua_State (CodeGen/include/luacodegen.h)
24//! - type_ref -> type_alias StkId (VM/src/lobject.h)
25//! - type_ref -> type_alias TValue (VM/src/lobject.h)
26//! - calls -> macro clvalue (VM/src/lobject.h)
27//! - calls -> macro VM_REG (CodeGen/src/CodeGenUtils.cpp)
28//! - reads_global -> macro VM_REG (CodeGen/src/CodeGenUtils.cpp)
29//! - calls -> macro LUAU_INSN_A (Common/include/Luau/Bytecode.h)
30//! - reads_global -> macro LUAU_INSN_A (Common/include/Luau/Bytecode.h)
31//! - calls -> macro ttisfunction (VM/src/lobject.h)
32//! - calls -> macro ttistable (VM/src/lobject.h)
33//! - calls -> macro hvalue (VM/src/lobject.h)
34//! - calls -> macro ttisuserdata (VM/src/lobject.h)
35//! - calls -> macro uvalue (VM/src/lobject.h)
36//! - calls -> macro cast_to (VM/src/lcommon.h)
37//! - calls -> macro fasttm (VM/src/ltm.h)
38//! - calls -> macro setobj2s (VM/src/lobject.h)
39//! - calls -> macro LUAU_ASSERT (Common/include/Luau/Common.h)
40//! - reads_global -> macro LUAU_ASSERT (Common/include/Luau/Common.h)
41//! - calls -> macro VM_PROTECT (CodeGen/src/CodeGenUtils.cpp)
42//! - reads_global -> macro VM_PROTECT (CodeGen/src/CodeGenUtils.cpp)
43//! - calls -> function luaD_call (VM/src/ldo.cpp)
44//! - calls -> macro ttisnil (VM/src/lobject.h)
45//! - calls -> macro VM_PROTECT_PC (CodeGen/src/CodeGenUtils.cpp)
46//! - reads_global -> macro VM_PROTECT_PC (CodeGen/src/CodeGenUtils.cpp)
47//! - calls -> macro luaG_typeerror (VM/src/ldebug.h)
48//! - calls -> macro setpvalue (VM/src/lobject.h)
49//! - reads_global -> macro LU_TAG_ITERATOR (VM/src/lobject.h)
50//! - calls -> macro setnilvalue (VM/src/lobject.h)
51//! - calls -> macro LUAU_INSN_D (Common/include/Luau/Bytecode.h)
52//! - reads_global -> macro LUAU_INSN_D (Common/include/Luau/Bytecode.h)
53//! - translates_to -> rust_item executeFORGPREP
54
55use luaur_vm::macros::clvalue::clvalue;
56use luaur_vm::macros::fasttm::fasttm;
57use luaur_vm::macros::hvalue::hvalue;
58use luaur_vm::macros::lu_tag_iterator::LU_TAG_ITERATOR;
59use luaur_vm::macros::setnilvalue::setnilvalue;
60use luaur_vm::macros::setobj_2_s::setobj2s;
61use luaur_vm::macros::setpvalue::setpvalue;
62use luaur_vm::macros::ttisfunction::ttisfunction;
63use luaur_vm::macros::ttisnil::ttisnil;
64use luaur_vm::macros::ttistable::ttistable;
65use luaur_vm::macros::ttisuserdata::ttisuserdata;
66use luaur_vm::macros::uvalue::uvalue;
67use luaur_vm::records::lua_table::LuaTable;
68use luaur_vm::type_aliases::stk_id::StkId;
69use luaur_vm::type_aliases::t_value::TValue;
70use luaur_vm::type_aliases::tms::TMS;
71
72use crate::macros::vm_protect::vm_protect;
73use crate::macros::vm_protect_pc::VM_PROTECT_PC;
74use crate::macros::vm_reg::VM_REG;
75use crate::type_aliases::instruction_ir_builder::Instruction;
76use crate::type_aliases::lua_state::lua_State;
77
78use luaur_common::macros::luau_insn_a::LUAU_INSN_A;
79use luaur_common::macros::luau_insn_d::LUAU_INSN_D;
80
81pub unsafe fn execute_forgprep(
82 L: *mut lua_State,
83 pc: *const Instruction,
84 mut base: StkId,
85 _k: *mut TValue,
86) -> *const Instruction {
87 let _cl = clvalue!((*(*L).ci).func);
88
89 let mut pc = pc;
90 let insn = *pc;
91 pc = pc.add(1);
92
93 let mut ra = VM_REG!(LUAU_INSN_A!(insn) as i32, L, base) as *mut TValue;
94
95 if ttisfunction!(ra) {
96 // will be called during FORGLOOP
97 } else {
98 let mt: *mut LuaTable = if ttistable!(ra) {
99 (*hvalue!(ra)).metatable
100 } else if ttisuserdata!(ra) {
101 (*uvalue!(ra as *const TValue)).metatable
102 } else {
103 core::ptr::null_mut()
104 };
105
106 let fn_iter = fasttm(L, mt, TMS::TM_ITER as i32);
107
108 if !fn_iter.is_null() {
109 setobj2s!(L, ra.add(1), ra);
110 setobj2s!(L, ra, fn_iter);
111
112 (*L).top = ra.add(2); // func + self arg
113
114 vm_protect!(L, pc, base, lua_d_call_protected(L, ra));
115 (*L).top = (*(*L).ci).top;
116
117 // recompute ra since stack might have been reallocated
118 ra = VM_REG!(LUAU_INSN_A!(insn) as i32, L, base) as *mut TValue;
119
120 // protect against __iter returning nil
121 if ttisnil!(ra) {
122 VM_PROTECT_PC(L, pc as *const u32);
123 luaur_vm::functions::lua_g_typeerror_l::lua_g_typeerror_l(
124 L,
125 ra as *const TValue,
126 c"call".as_ptr(),
127 );
128 }
129 } else if !fasttm(L, mt, TMS::TM_CALL as i32).is_null() {
130 // table or userdata with __call, will be called during FORGLOOP
131 } else if ttistable!(ra) {
132 // set up registers for builtin iteration
133 setobj2s!(L, ra.add(1), ra);
134 setpvalue!(ra.add(2), core::ptr::null_mut(), LU_TAG_ITERATOR);
135 setnilvalue!(ra);
136 } else {
137 VM_PROTECT_PC(L, pc as *const u32);
138 luaur_vm::functions::lua_g_typeerror_l::lua_g_typeerror_l(
139 L,
140 ra as *const TValue,
141 c"iterate over".as_ptr(),
142 );
143 }
144 }
145
146 pc = pc.offset(LUAU_INSN_D!(insn) as isize);
147 pc
148}
149
150#[inline]
151unsafe fn lua_d_call_protected(L: *mut lua_State, ra: StkId) {
152 luaur_vm::functions::lua_d_call::lua_d_call(L, ra, 3);
153}
154
155#[no_mangle]
156pub unsafe extern "C" fn executeFORGPREP(
157 L: *mut lua_State,
158 pc: *const Instruction,
159 base: StkId,
160 k: *mut TValue,
161) -> *const Instruction {
162 execute_forgprep(L, pc, base, k)
163}