/* Setup call to metamethod to be run by Assembler VM. */ static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo, cTValue *a, cTValue *b) { /* ** |-- framesize -> top top+1 top+2 top+3 ** before: [func slots ...] ** mm setup: [func slots ...] [cont|?] [mo|tmtype] [a] [b] ** in asm: [func slots ...] [cont|PC] [mo|delta] [a] [b] ** ^-- func base ^-- mm base ** after mm: [func slots ...] [result] ** ^-- copy to base[PC_RA] --/ for lj_cont_ra ** istruecond + branch for lj_cont_cond* ** ignore for lj_cont_nop ** next PC: [func slots ...] */ TValue *top = L->top; if (curr_funcisL(L)) top = curr_topL(L); setcont(top++, cont); /* Assembler VM stores PC in upper word or FR2. */ if (LJ_FR2) setnilV(top++); copyTV(L, top++, mo); /* Store metamethod and two arguments. */ if (LJ_FR2) setnilV(top++); copyTV(L, top, a); copyTV(L, top+1, b); return top; /* Return new base. */ }
/* Formatted runtime error message. */ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) { const char *msg; va_list argp; va_start(argp, em); if (curr_funcisL(L)) L->top = curr_topL(L); msg = lj_str_pushvf(L, err2msg(em), argp); va_end(argp); lj_debug_addloc(L, msg, L->base-1, NULL); lj_err_run(L); }
/* Typecheck error for operands. */ LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm) { const char *tname = typename(o); const char *opname = err2msg(opm); if (curr_funcisL(L)) { GCproto *pt = curr_proto(L); const BCIns *pc = cframe_Lpc(L) - 1; const char *oname = NULL; const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname); if (kind) err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname); } err_msgv(L, LJ_ERR_BADOPRV, opname, tname); }