luaur_code_gen/functions/
execute_namecall.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::functions::lua_g_methoderror::luaG_methoderror;
13use luaur_vm::functions::lua_v_gettable::lua_v_gettable;
14use luaur_vm::macros::clvalue::clvalue;
15use luaur_vm::macros::fasttm::fasttm;
16use luaur_vm::macros::gkey::{gkey, gval};
17use luaur_vm::macros::hvalue::hvalue;
18use luaur_vm::macros::setobj_2_s::setobj_2_s as setobj2s;
19use luaur_vm::macros::tsvalue::tsvalue;
20use luaur_vm::macros::ttisnil::ttisnil;
21use luaur_vm::macros::ttisstring::ttisstring;
22use luaur_vm::macros::ttistable::ttistable;
23use luaur_vm::macros::ttisuserdata::ttisuserdata;
24use luaur_vm::macros::ttype::ttype;
25use luaur_vm::macros::uvalue::uvalue;
26use luaur_vm::type_aliases::stk_id::StkId;
27use luaur_vm::type_aliases::t_value::TValue;
28use luaur_vm::type_aliases::tms::TMS;
29
30#[inline]
31unsafe fn vm_kv(
32 i: u32,
33 cl: *mut luaur_vm::records::closure::Closure,
34 k: *mut TValue,
35) -> *mut TValue {
36 let p = {
37 let l = &(*cl).inner.l;
38 l.p
39 };
40 luaur_common::LUAU_ASSERT!(i < (*p).sizek as u32);
41 k.add(i as usize)
42}
43
44pub unsafe fn execute_namecall(
45 L: *mut lua_State,
46 pc: *const Instruction,
47 mut base: StkId,
48 k: *mut TValue,
49) -> *const Instruction {
50 let cl = clvalue!((*(*L).ci).func);
51 let mut pc_ptr = pc;
52 let insn = *pc_ptr;
53 pc_ptr = pc_ptr.add(1);
54 let op = LUAU_INSN_OP(insn);
55 let mut ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
56 let rb = VM_REG!(LUAU_INSN_B(insn) as i32, L, base) as *mut TValue;
57 let aux = *pc_ptr;
58 pc_ptr = pc_ptr.add(1);
59 let kv = vm_kv(
60 if op == LuauOpcode::LOP_NAMECALLUDATA as u32 {
61 LUAU_INSN_AUX_KV16(aux)
62 } else {
63 aux
64 },
65 cl,
66 k,
67 );
68 luaur_common::LUAU_ASSERT!(ttisstring!(kv as *const TValue));
69
70 if ttistable!(rb as *const TValue) {
71 setobj2s!(L, ra.add(1), rb as *const TValue);
72 (*L).cachedslot = LUAU_INSN_C(insn) as i32;
73 vm_protect!(L, pc_ptr, base, {
74 lua_v_gettable(L, rb as *const TValue, kv, ra);
75 });
76 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
77
78 ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
79 if ttisnil!(ra as *const TValue) {
80 luaG_methoderror(L, ra.add(1) as *const TValue, tsvalue!(kv as *const TValue));
81 }
82 } else {
83 let mt = if ttisuserdata!(rb as *const TValue) {
84 (*uvalue!(rb as *const TValue)).metatable
85 } else {
86 (*(*L).global).mt[ttype!(rb as *const TValue) as usize]
87 };
88
89 let fn_nc = fasttm(L, mt, TMS::TM_NAMECALL as i32);
90 if !fn_nc.is_null() {
91 setobj2s!(L, ra.add(1), rb as *const TValue);
92 setobj2s!(L, ra, fn_nc);
93
94 (*L).namecall = tsvalue!(kv as *const TValue) as *mut _;
95 } else {
96 let tmi = fasttm(L, mt, TMS::TM_INDEX as i32);
97 if !tmi.is_null() && ttistable!(tmi) {
98 let h = hvalue!(tmi);
99 let slot = (LUAU_INSN_C(insn) as i32) & (*h).nodemask8 as i32;
100 let n = (*h).node.add(slot as usize);
101
102 if ttisstring!(gkey!(n) as *const TValue)
103 && tsvalue!(gkey!(n) as *const TValue) == tsvalue!(kv as *const TValue)
104 && !ttisnil!(gval!(n))
105 {
106 setobj2s!(L, ra.add(1), rb as *const TValue);
107 setobj2s!(L, ra, gval!(n));
108 } else {
109 setobj2s!(L, ra.add(1), rb as *const TValue);
110 (*L).cachedslot = slot;
111 vm_protect!(L, pc_ptr, base, {
112 lua_v_gettable(L, rb as *const TValue, kv, ra);
113 });
114 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
115
116 ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
117 if ttisnil!(ra as *const TValue) {
118 luaG_methoderror(
119 L,
120 ra.add(1) as *const TValue,
121 tsvalue!(kv as *const TValue),
122 );
123 }
124 }
125 } else {
126 setobj2s!(L, ra.add(1), rb as *const TValue);
127 vm_protect!(L, pc_ptr, base, {
128 lua_v_gettable(L, rb as *const TValue, kv, ra);
129 });
130
131 ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
132 if ttisnil!(ra as *const TValue) {
133 luaG_methoderror(L, ra.add(1) as *const TValue, tsvalue!(kv as *const TValue));
134 }
135 }
136 }
137 }
138
139 luaur_common::LUAU_ASSERT!(
140 LUAU_INSN_OP(*pc_ptr) == LuauOpcode::LOP_CALL as u32
141 || LUAU_INSN_OP(*pc_ptr) == LuauOpcode::LOP_CALLFB as u32
142 );
143 pc_ptr
144}
145
146#[no_mangle]
147pub unsafe extern "C" fn executeNAMECALL(
148 L: *mut lua_State,
149 pc: *const Instruction,
150 base: StkId,
151 k: *mut TValue,
152) -> *const Instruction {
153 execute_namecall(L, pc, base, k)
154}