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