Skip to main content

luaur_code_gen/functions/
call_epilog_c.rs

1use luaur_common::macros::luau_assert::LUAU_ASSERT;
2use luaur_vm::macros::clvalue::clvalue;
3use luaur_vm::macros::setnilvalue::setnilvalue;
4use luaur_vm::macros::setobj_2_s::setobj2s;
5use luaur_vm::type_aliases::stk_id::StkId;
6use luaur_vm::type_aliases::t_value::TValue;
7
8use crate::type_aliases::lua_state::lua_State;
9
10#[allow(non_snake_case)]
11pub const LUA_MULTRET: i32 = luaur_vm::macros::lua_multret::LUA_MULTRET;
12
13pub unsafe fn call_epilog_c(L: *mut lua_State, nresults: i32, n: i32) {
14    let l_ptr = L as *mut luaur_vm::records::lua_state::lua_State;
15
16    // ci is our callinfo, cip is our parent
17    let ci = (*l_ptr).ci;
18    let cip = ci.offset(-1);
19
20    // copy return values into parent stack (but only up to nresults!), fill the rest with nil
21    // note: in MULTRET context nresults starts as -1 so i != 0 condition never activates intentionally
22    let mut res: StkId = (*ci).func;
23    let mut vali: StkId = (*l_ptr).top.offset(-n as isize);
24    let valend: StkId = (*l_ptr).top;
25
26    let mut i: i32 = nresults;
27    while i != 0 && vali < valend {
28        setobj2s!(l_ptr, res, vali);
29        res = res.add(1);
30        vali = vali.add(1);
31        i -= 1;
32    }
33
34    while i > 0 {
35        setnilvalue!(res);
36        res = res.add(1);
37        i -= 1;
38    }
39
40    // pop the stack frame
41    (*l_ptr).ci = cip;
42    (*l_ptr).base = (*cip).base;
43    (*l_ptr).top = if nresults == LUA_MULTRET {
44        res
45    } else {
46        (*cip).top
47    };
48}
49
50#[no_mangle]
51pub unsafe extern "C" fn callEpilogC(L: *mut lua_State, nresults: i32, n: i32) {
52    call_epilog_c(L, nresults, n);
53}