luaur_code_gen/functions/
execute_settableks.rs1use crate::macros::vm_patch_c::VM_PATCH_C;
2use crate::macros::vm_protect::vm_protect;
3use crate::macros::vm_protect_pc::VM_PROTECT_PC;
4use crate::macros::vm_reg::VM_REG;
5use crate::type_aliases::instruction_ir_builder::Instruction;
6use crate::type_aliases::lua_state::lua_State;
7use luaur_common::enums::luau_opcode::LuauOpcode;
8use luaur_common::macros::luau_insn_a::LUAU_INSN_A;
9use luaur_common::macros::luau_insn_aux_kv_16::LUAU_INSN_AUX_KV16;
10use luaur_common::macros::luau_insn_b::LUAU_INSN_B;
11use luaur_common::macros::luau_insn_c::LUAU_INSN_C;
12use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
13use luaur_vm::functions::lua_h_setstr::lua_h_setstr as luaH_setstr;
14use luaur_vm::functions::lua_v_call_tm::lua_v_call_tm;
15use luaur_vm::functions::lua_v_settable::lua_v_settable;
16use luaur_vm::macros::clvalue::clvalue;
17use luaur_vm::macros::fastnotm::fastnotm;
18use luaur_vm::macros::fasttm::fasttm;
19use luaur_vm::macros::gval_2_slot::gval2slot;
20use luaur_vm::macros::hvalue::hvalue;
21use luaur_vm::macros::lua_c_barriert::luaC_barriert;
22use luaur_vm::macros::setobj_2_s::setobj_2_s as setobj2s;
23use luaur_vm::macros::setobj_2_t::setobj2t;
24use luaur_vm::macros::tsvalue::tsvalue;
25use luaur_vm::macros::ttisfunction::ttisfunction;
26use luaur_vm::macros::ttisstring::ttisstring;
27use luaur_vm::macros::ttistable::ttistable;
28use luaur_vm::macros::ttisuserdata::ttisuserdata;
29use luaur_vm::macros::uvalue::uvalue;
30use luaur_vm::type_aliases::stk_id::StkId;
31use luaur_vm::type_aliases::t_value::TValue;
32use luaur_vm::type_aliases::tms::TMS;
33
34#[inline]
35unsafe fn vm_kv(
36 i: u32,
37 cl: *mut luaur_vm::records::closure::Closure,
38 k: *mut TValue,
39) -> *mut TValue {
40 let p = {
41 let l = &(*cl).inner.l;
42 l.p
43 };
44 luaur_common::LUAU_ASSERT!(i < (*p).sizek as u32);
45 k.add(i as usize)
46}
47
48pub unsafe fn execute_settableks(
49 L: *mut lua_State,
50 pc: *const Instruction,
51 mut base: StkId,
52 k: *mut TValue,
53) -> *const Instruction {
54 let cl = clvalue!((*(*L).ci).func);
55 let mut pc_ptr = pc;
56 let insn = *pc_ptr;
57 pc_ptr = pc_ptr.add(1);
58 let op = LUAU_INSN_OP(insn);
59 let ra = VM_REG!(LUAU_INSN_A(insn) as i32, L, base) as *mut TValue;
60 let rb = VM_REG!(LUAU_INSN_B(insn) as i32, L, base) as *mut TValue;
61 let aux = *pc_ptr;
62 pc_ptr = pc_ptr.add(1);
63 let kv = vm_kv(
64 if op == LuauOpcode::LOP_SETUDATAKS as u32 {
65 LUAU_INSN_AUX_KV16(aux)
66 } else {
67 aux
68 },
69 cl,
70 k,
71 );
72 luaur_common::LUAU_ASSERT!(ttisstring!(kv as *const TValue));
73
74 if ttistable!(rb as *const TValue) {
75 let h = hvalue!(rb as *const TValue);
76
77 if fastnotm((*h).metatable, TMS::TM_NEWINDEX as i32) && (*h).readonly == 0 {
78 VM_PROTECT_PC(L, pc_ptr);
79
80 let res = luaH_setstr(L, h, tsvalue!(kv as *const TValue) as *mut _);
81 VM_PATCH_C(pc_ptr.sub(2), gval2slot!(h, res as *const TValue));
82 setobj2t!(L, res, ra as *const TValue);
83 luaC_barriert!(L, h, ra as *const TValue);
84 return pc_ptr;
85 }
86
87 let slot = (LUAU_INSN_C(insn) as i32) & (*h).nodemask8 as i32;
88 (*L).cachedslot = slot;
89 vm_protect!(L, pc_ptr, base, {
90 lua_v_settable(L, rb as *const TValue, kv, ra);
91 });
92 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
93 return pc_ptr;
94 }
95
96 let mut fn_tm: *const TValue = core::ptr::null();
97 if ttisuserdata!(rb as *const TValue)
98 && {
99 fn_tm = fasttm(
100 L,
101 (*uvalue!(rb as *const TValue)).metatable,
102 TMS::TM_NEWINDEX as i32,
103 );
104 !fn_tm.is_null()
105 }
106 && ttisfunction!(fn_tm)
107 && (*clvalue!(fn_tm)).isC != 0
108 {
109 luaur_common::LUAU_ASSERT!((*L).top.add(4) < (*L).stack.add((*L).stacksize as usize));
110 let top = (*L).top;
111 setobj2s!(L, top.add(0), fn_tm);
112 setobj2s!(L, top.add(1), rb as *const TValue);
113 setobj2s!(L, top.add(2), kv as *const TValue);
114 setobj2s!(L, top.add(3), ra as *const TValue);
115 (*L).top = top.add(4);
116
117 (*L).cachedslot = LUAU_INSN_C(insn) as i32;
118 vm_protect!(L, pc_ptr, base, {
119 lua_v_call_tm(L, 3, -1);
120 });
121 VM_PATCH_C(pc_ptr.sub(2), (*L).cachedslot);
122 return pc_ptr;
123 }
124
125 vm_protect!(L, pc_ptr, base, {
126 lua_v_settable(L, rb as *const TValue, kv, ra);
127 });
128 pc_ptr
129}
130
131#[no_mangle]
132pub unsafe extern "C" fn executeSETTABLEKS(
133 L: *mut lua_State,
134 pc: *const Instruction,
135 base: StkId,
136 k: *mut TValue,
137) -> *const Instruction {
138 execute_settableks(L, pc, base, k)
139}