luaur_code_gen/functions/
execute_gettableks.rs1use crate::macros::vm_patch_c::VM_PATCH_C;
2use crate::macros::vm_protect::vm_protect;
3use crate::macros::vm_reg::VM_REG;
4use crate::type_aliases::instruction_ir_builder::Instruction;
5use crate::type_aliases::lua_state::lua_State;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7use luaur_common::macros::luau_insn_a::LUAU_INSN_A;
8use luaur_common::macros::luau_insn_aux_kv_16::LUAU_INSN_AUX_KV16;
9use luaur_common::macros::luau_insn_b::LUAU_INSN_B;
10use luaur_common::macros::luau_insn_c::LUAU_INSN_C;
11use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
12use luaur_vm::enums::lua_type::lua_Type;
13use luaur_vm::functions::lua_h_getstr::luaH_getstr;
14use luaur_vm::functions::lua_v_call_tm::lua_v_call_tm;
15use luaur_vm::functions::lua_v_gettable::lua_v_gettable;
16use luaur_vm::macros::clvalue::clvalue;
17use luaur_vm::macros::fasttm::fasttm;
18use luaur_vm::macros::getstr::getstr;
19use luaur_vm::macros::gkey::{gkey, gval};
20use luaur_vm::macros::gval_2_slot::gval2slot;
21use luaur_vm::macros::hvalue::hvalue;
22use luaur_vm::macros::lua_o_nilobject::luaO_nilobject;
23use luaur_vm::macros::pvalue::pvalue;
24use luaur_vm::macros::setnvalue::setnvalue;
25use luaur_vm::macros::setobj_2_s::setobj_2_s as setobj2s;
26use luaur_vm::macros::tsvalue::tsvalue;
27use luaur_vm::macros::ttisfunction::ttisfunction;
28use luaur_vm::macros::ttisnil::ttisnil;
29use luaur_vm::macros::ttisstring::ttisstring;
30use luaur_vm::macros::ttistable::ttistable;
31use luaur_vm::macros::ttisuserdata::ttisuserdata;
32use luaur_vm::macros::ttisvector::ttisvector;
33use luaur_vm::macros::uvalue::uvalue;
34use luaur_vm::macros::vvalue::vvalue;
35use luaur_vm::type_aliases::stk_id::StkId;
36use luaur_vm::type_aliases::t_value::TValue;
37use luaur_vm::type_aliases::tms::TMS;
38
39#[inline]
40unsafe fn vm_kv(
41 i: u32,
42 cl: *mut luaur_vm::records::closure::Closure,
43 k: *mut TValue,
44) -> *mut TValue {
45 let p = {
46 let l = &(*cl).inner.l;
47 l.p
48 };
49 luaur_common::LUAU_ASSERT!(i < (*p).sizek as u32);
50 k.add(i as usize)
51}
52
53pub unsafe fn execute_gettableks(
54 L: *mut lua_State,
55 pc: *const Instruction,
56 mut base: StkId,
57 k: *mut TValue,
58) -> *const Instruction {
59 let cl = clvalue!((*(*L).ci).func);
60 let mut pc_ptr = pc;
61 let insn = *pc_ptr;
62 pc_ptr = pc_ptr.add(1);
63 let op = LUAU_INSN_OP(insn);
64 let ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
65 let rb = VM_REG!(LUAU_INSN_B(insn) as i32, L, base) as *mut TValue;
66 let aux = *pc_ptr;
67 pc_ptr = pc_ptr.add(1);
68 let kv = vm_kv(
69 if op == LuauOpcode::LOP_GETUDATAKS as u32 {
70 LUAU_INSN_AUX_KV16(aux)
71 } else {
72 aux
73 },
74 cl,
75 k,
76 );
77 luaur_common::LUAU_ASSERT!(ttisstring!(kv as *const TValue));
78
79 if ttistable!(rb as *const TValue) {
80 let h = hvalue!(rb as *const TValue);
81
82 if (*h).metatable.is_null() {
83 let res = luaH_getstr(h, tsvalue!(kv as *const TValue) as *mut _);
84
85 if res != luaO_nilobject {
86 VM_PATCH_C(pc_ptr.sub(2), gval2slot!(h, res));
87 }
88
89 setobj2s!(L, ra, res);
90 return pc_ptr;
91 }
92
93 let slot = (LUAU_INSN_C(insn) as i32) & (*h).nodemask8 as i32;
94 (*L).cachedslot = slot;
95 vm_protect!(L, pc_ptr, base, {
96 lua_v_gettable(L, rb as *const TValue, kv, ra);
97 });
98 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
99 return pc_ptr;
100 }
101
102 if luaur_common::FFlag::LuauDirectFieldGet.get() && ttisuserdata!(rb as *const TValue) {
103 let dispatch = {
104 let u = uvalue!(rb as *const TValue);
105 (*(*L).global).udatadirectfields[u.tag as usize]
106 };
107
108 if !dispatch.is_null() {
109 let slot = (LUAU_INSN_C(insn) as i32) & (*dispatch).nodemask8 as i32;
110 let n = (*dispatch).node.add(slot as usize);
111
112 if ttisstring!(gkey!(n) as *const TValue)
113 && tsvalue!(gkey!(n) as *const TValue) == tsvalue!(kv as *const TValue)
114 && !ttisnil!(gval!(n))
115 {
116 let f: unsafe extern "C" fn(*mut core::ffi::c_void, *mut core::ffi::c_void) =
117 core::mem::transmute(pvalue!(gval!(n) as *const TValue));
118 let u = uvalue!(rb as *const TValue);
119 f(
120 u.data.as_ptr() as *mut core::ffi::c_void,
121 ra as *mut core::ffi::c_void,
122 );
123 return pc_ptr;
124 }
125
126 let fptr = luaH_getstr(dispatch, tsvalue!(kv as *const TValue) as *mut _);
127 if !ttisnil!(fptr) {
128 VM_PATCH_C(pc_ptr.sub(2), gval2slot!(dispatch, fptr));
129 let f: unsafe extern "C" fn(*mut core::ffi::c_void, *mut core::ffi::c_void) =
130 core::mem::transmute(pvalue!(fptr));
131 let u = uvalue!(rb as *const TValue);
132 f(
133 u.data.as_ptr() as *mut core::ffi::c_void,
134 ra as *mut core::ffi::c_void,
135 );
136 return pc_ptr;
137 }
138 }
139 }
140
141 let mut fn_tm: *const TValue = core::ptr::null();
142 if ttisuserdata!(rb as *const TValue)
143 && {
144 fn_tm = fasttm(
145 L,
146 (*uvalue!(rb as *const TValue)).metatable,
147 TMS::TM_INDEX as i32,
148 );
149 !fn_tm.is_null()
150 }
151 && ttisfunction!(fn_tm)
152 && (*clvalue!(fn_tm)).isC != 0
153 {
154 luaur_common::LUAU_ASSERT!((*L).top.add(3) < (*L).stack.add((*L).stacksize as usize));
155 let top = (*L).top;
156 setobj2s!(L, top.add(0), fn_tm);
157 setobj2s!(L, top.add(1), rb as *const TValue);
158 setobj2s!(L, top.add(2), kv as *const TValue);
159 (*L).top = top.add(3);
160
161 (*L).cachedslot = LUAU_INSN_C(insn) as i32;
162 vm_protect!(L, pc_ptr, base, {
163 lua_v_call_tm(L, 2, LUAU_INSN_A(insn) as i32);
164 });
165 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
166 return pc_ptr;
167 } else if ttisvector!(rb as *const TValue) {
168 let name = getstr(tsvalue!(kv as *const TValue));
169 let ic = ((*name.add(0)) as u8 | b' ') as i32 - b'x' as i32;
170
171 if (ic as u32) < luaur_vm::macros::lua_vector_size::LUA_VECTOR_SIZE as u32
172 && *name.add(1) == 0
173 {
174 let v = vvalue!(rb as *const TValue).as_ptr();
175 setnvalue!(ra, *v.add(ic as usize) as f64);
176 return pc_ptr;
177 }
178
179 fn_tm = fasttm(
180 L,
181 (*(*L).global).mt[lua_Type::LUA_TVECTOR as usize],
182 TMS::TM_INDEX as i32,
183 );
184
185 if !fn_tm.is_null() && ttisfunction!(fn_tm) && (*clvalue!(fn_tm)).isC != 0 {
186 luaur_common::LUAU_ASSERT!((*L).top.add(3) < (*L).stack.add((*L).stacksize as usize));
187 let top = (*L).top;
188 setobj2s!(L, top.add(0), fn_tm);
189 setobj2s!(L, top.add(1), rb as *const TValue);
190 setobj2s!(L, top.add(2), kv as *const TValue);
191 (*L).top = top.add(3);
192
193 (*L).cachedslot = LUAU_INSN_C(insn) as i32;
194 vm_protect!(L, pc_ptr, base, {
195 lua_v_call_tm(L, 2, LUAU_INSN_A(insn) as i32);
196 });
197 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
198 return pc_ptr;
199 }
200 }
201
202 vm_protect!(L, pc_ptr, base, {
203 lua_v_gettable(L, rb as *const TValue, kv, ra);
204 });
205 pc_ptr
206}
207
208#[no_mangle]
209pub unsafe extern "C" fn executeGETTABLEKS(
210 L: *mut lua_State,
211 pc: *const Instruction,
212 base: StkId,
213 k: *mut TValue,
214) -> *const Instruction {
215 execute_gettableks(L, pc, base, k)
216}