return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1);
}
+static LJ_AINLINE int bc_isret_or_tail(BCOp op)
+{
+ return (op == BC_CALLMT || op == BC_CALLT || bc_isret(op));
+}
+
LJ_DATA const uint16_t lj_bc_mode[];
LJ_DATA const uint16_t lj_bc_ofs[];
#endif
-/* Check if bytecode op returns. */
-static int bcopisret(BCOp op)
-{
- switch (op) {
- case BC_CALLMT: case BC_CALLT:
- case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
- return 1;
- default:
- return 0;
- }
-}
-
/* Fixup return instruction for prototype. */
static void fs_fixup_ret(FuncState *fs)
{
BCPos lastpc = fs->pc;
- if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) {
+ if (lastpc <= fs->lasttarget || !bc_isret_or_tail(bc_op(fs->bcbase[lastpc-1].ins))) {
if ((fs->bl->flags & FSCOPE_UPVAL))
bcemit_AJ(fs, BC_UCLO, 0, 0);
bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
const BCIns *pc = snap_pc(map[nent]);
lua_State *L = J->L;
- /* Set interpreter PC to the next PC to get correct error messages. */
- setcframe_pc(L->cframe, pc+1);
+ /* Set interpreter PC to the next PC to get correct error messages.
+ ** But not for returns or tail calls, since pc+1 may be out-of-range.
+ */
+ setcframe_pc(L->cframe, bc_isret_or_tail(bc_op(*pc)) ? pc : pc+1);
setcframe_pc(cframe_raw(cframe_prev(L->cframe)), pc);
/* Make sure the stack is big enough for the slots from the snapshot. */