diff --git a/lcode.c b/lcode.c index 04b534e2..521f597a 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.145 2017/12/15 18:53:48 roberto Exp roberto $ +** $Id: lcode.c,v 2.146 2017/12/18 15:44:44 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -618,12 +618,11 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) { ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). */ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getinstruction(fs, e), nresults + 1); - } + Instruction *pc = &getinstruction(fs, e); + if (e->k == VCALL) /* expression is an open function call? */ + SETARG_C(*pc, nresults + 1); else if (e->k == VVARARG) { - Instruction *pc = &getinstruction(fs, e); - SETARG_B(*pc, nresults + 1); + SETARG_C(*pc, nresults + 1); SETARG_A(*pc, fs->freereg); luaK_reserveregs(fs, 1); } @@ -649,7 +648,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { e->u.info = GETARG_A(getinstruction(fs, e)); } else if (e->k == VVARARG) { - SETARG_B(getinstruction(fs, e), 2); + SETARG_C(getinstruction(fs, e), 2); e->k = VRELOC; /* can relocate its simple result */ } } @@ -1623,6 +1622,7 @@ void luaK_finish (FuncState *fs) { Proto *p = fs->f; for (i = 0; i < fs->pc; i++) { Instruction *pc = &p->code[i]; + lua_assert(isOT(*pc) == isIT(*(pc + 1))); switch (GET_OPCODE(*pc)) { case OP_RETURN: case OP_RETURN0: case OP_RETURN1: case OP_TAILCALL: { diff --git a/lopcodes.c b/lopcodes.c index f5896ba0..a5867d23 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.73 2017/12/13 18:32:09 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -97,80 +97,80 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A mode opcode */ - opmode(0, 1, iABC) /* OP_MOVE */ - ,opmode(0, 1, iAsBx) /* OP_LOADI */ - ,opmode(0, 1, iAsBx) /* OP_LOADF */ - ,opmode(0, 1, iABx) /* OP_LOADK */ - ,opmode(0, 1, iABx) /* OP_LOADKX */ - ,opmode(0, 1, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, iABC) /* OP_GETUPVAL */ - ,opmode(0, 0, iABC) /* OP_SETUPVAL */ - ,opmode(0, 1, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, iABC) /* OP_GETTABLE */ - ,opmode(0, 1, iABC) /* OP_GETI */ - ,opmode(0, 1, iABC) /* OP_GETFIELD */ - ,opmode(0, 0, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, iABC) /* OP_SETTABLE */ - ,opmode(0, 0, iABC) /* OP_SETI */ - ,opmode(0, 0, iABC) /* OP_SETFIELD */ - ,opmode(0, 1, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, iABC) /* OP_SELF */ - ,opmode(0, 1, iABC) /* OP_ADDI */ - ,opmode(0, 1, iABC) /* OP_SUBI */ - ,opmode(0, 1, iABC) /* OP_MULI */ - ,opmode(0, 1, iABC) /* OP_MODI */ - ,opmode(0, 1, iABC) /* OP_POWI */ - ,opmode(0, 1, iABC) /* OP_DIVI */ - ,opmode(0, 1, iABC) /* OP_IDIVI */ - ,opmode(0, 1, iABC) /* OP_BANDK */ - ,opmode(0, 1, iABC) /* OP_BORK */ - ,opmode(0, 1, iABC) /* OP_BXORK */ - ,opmode(0, 1, iABC) /* OP_SHRI */ - ,opmode(0, 1, iABC) /* OP_SHLI */ - ,opmode(0, 1, iABC) /* OP_ADD */ - ,opmode(0, 1, iABC) /* OP_SUB */ - ,opmode(0, 1, iABC) /* OP_MUL */ - ,opmode(0, 1, iABC) /* OP_MOD */ - ,opmode(0, 1, iABC) /* OP_POW */ - ,opmode(0, 1, iABC) /* OP_DIV */ - ,opmode(0, 1, iABC) /* OP_IDIV */ - ,opmode(0, 1, iABC) /* OP_BAND */ - ,opmode(0, 1, iABC) /* OP_BOR */ - ,opmode(0, 1, iABC) /* OP_BXOR */ - ,opmode(0, 1, iABC) /* OP_SHL */ - ,opmode(0, 1, iABC) /* OP_SHR */ - ,opmode(0, 1, iABC) /* OP_UNM */ - ,opmode(0, 1, iABC) /* OP_BNOT */ - ,opmode(0, 1, iABC) /* OP_NOT */ - ,opmode(0, 1, iABC) /* OP_LEN */ - ,opmode(0, 1, iABC) /* OP_CONCAT */ - ,opmode(0, 0, iABC) /* OP_CLOSE */ - ,opmode(0, 0, isJ) /* OP_JMP */ - ,opmode(1, 0, iABC) /* OP_EQ */ - ,opmode(1, 0, iABC) /* OP_LT */ - ,opmode(1, 0, iABC) /* OP_LE */ - ,opmode(1, 0, iABC) /* OP_EQK */ - ,opmode(1, 0, iABC) /* OP_EQI */ - ,opmode(1, 0, iABC) /* OP_LTI */ - ,opmode(1, 0, iABC) /* OP_LEI */ - ,opmode(1, 0, iABC) /* OP_TEST */ - ,opmode(1, 1, iABC) /* OP_TESTSET */ - ,opmode(0, 1, iABC) /* OP_CALL */ - ,opmode(0, 1, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, iABC) /* OP_RETURN */ - ,opmode(0, 0, iABC) /* OP_RETURN0 */ - ,opmode(0, 0, iABC) /* OP_RETURN1 */ - ,opmode(0, 1, iABx) /* OP_FORLOOP1 */ - ,opmode(0, 1, iABx) /* OP_FORPREP1 */ - ,opmode(0, 1, iABx) /* OP_FORLOOP */ - ,opmode(0, 1, iABx) /* OP_FORPREP */ - ,opmode(0, 0, iABC) /* OP_TFORCALL */ - ,opmode(0, 1, iABx) /* OP_TFORLOOP */ - ,opmode(0, 0, iABC) /* OP_SETLIST */ - ,opmode(0, 1, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, iABC) /* OP_VARARG */ - ,opmode(0, 0, iAx) /* OP_EXTRAARG */ +/* OT IT T A mode opcode */ + opmode(0, 0, 0, 1, iABC) /* OP_MOVE */ + ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADI */ + ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADF */ + ,opmode(0, 0, 0, 1, iABx) /* OP_LOADK */ + ,opmode(0, 0, 0, 1, iABx) /* OP_LOADKX */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LOADBOOL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LOADNIL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETUPVAL */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABUP */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_GETFIELD */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABLE */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETI */ + ,opmode(0, 0, 0, 0, iABC) /* OP_SETFIELD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_NEWTABLE */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SELF */ + ,opmode(0, 0, 0, 1, iABC) /* OP_ADDI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SUBI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MULI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MODI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_POWI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_DIVI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHRI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHLI */ + ,opmode(0, 0, 0, 1, iABC) /* OP_ADD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SUB */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MUL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MOD */ + ,opmode(0, 0, 0, 1, iABC) /* OP_POW */ + ,opmode(0, 0, 0, 1, iABC) /* OP_DIV */ + ,opmode(0, 0, 0, 1, iABC) /* OP_IDIV */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BAND */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BOR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BXOR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHL */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SHR */ + ,opmode(0, 0, 0, 1, iABC) /* OP_UNM */ + ,opmode(0, 0, 0, 1, iABC) /* OP_BNOT */ + ,opmode(0, 0, 0, 1, iABC) /* OP_NOT */ + ,opmode(0, 0, 0, 1, iABC) /* OP_LEN */ + ,opmode(0, 0, 0, 1, iABC) /* OP_CONCAT */ + ,opmode(0, 0, 0, 0, iABC) /* OP_CLOSE */ + ,opmode(0, 0, 0, 0, isJ) /* OP_JMP */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQ */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LT */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LE */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQK */ + ,opmode(0, 0, 1, 0, iABC) /* OP_EQI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LTI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_LEI */ + ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ + ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ + ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ + ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ + ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ + ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */ + ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP1 */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP */ + ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP */ + ,opmode(0, 0, 0, 0, iABC) /* OP_TFORCALL */ + ,opmode(0, 0, 0, 1, iABx) /* OP_TFORLOOP */ + ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ + ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ + ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ + ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ }; diff --git a/lopcodes.h b/lopcodes.h index ec880703..eae0dfaf 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.179 2017/12/15 18:53:48 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.180 2017/12/18 17:49:31 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -282,7 +282,7 @@ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ -OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+B-2) = vararg(C) */ +OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ } OpCode; @@ -298,8 +298,8 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'. - (*) In OP_VARARG, if (B == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). C is the vararg parameter. + (*) In OP_VARARG, if (C == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). B is the vararg parameter. (*) In OP_RETURN, if (B == 0) then return up to 'top'. @@ -330,6 +330,8 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ ** bits 0-2: op mode ** bit 3: instruction set register A ** bit 4: operator is a test (next instruction must be a jump) +** bit 5: instruction sets 'L->top' for next instruction (when C == 0) +** bit 6: instruction uses 'L->top' set by previous instruction (when B == 0) */ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; @@ -337,8 +339,16 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7)) #define testAMode(m) (luaP_opmodes[m] & (1 << 3)) #define testTMode(m) (luaP_opmodes[m] & (1 << 4)) +#define testOTMode(m) (luaP_opmodes[m] & (1 << 5)) +#define testITMode(m) (luaP_opmodes[m] & (1 << 6)) -#define opmode(t,a,m) (((t)<<4) | ((a)<<3) | (m)) +/* "out top" (set top for next instruction) */ +#define isOT(i) (testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) + +/* "in top" (uses top from previous instruction) */ +#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) + +#define opmode(ot,it,t,a,m) (((ot)<<5) | ((it)<<6) | ((t)<<4) | ((a)<<3) | (m)) LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ diff --git a/lparser.c b/lparser.c index 6317a788..e99b33ff 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.173 2017/12/18 12:33:54 roberto Exp roberto $ +** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -977,7 +977,7 @@ static void simpleexp (LexState *ls, expdesc *v) { int lastparam = fs->f->numparams; check_condition(ls, fs->f->is_vararg, "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, lastparam)); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, lastparam, 1)); break; } case '{': { /* constructor */ diff --git a/lvm.c b/lvm.c index 8039770e..89646d24 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.327 2017/12/19 16:18:04 roberto Exp roberto $ +** $Id: lvm.c,v 2.328 2017/12/20 14:58:05 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1688,9 +1688,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) { vmbreak; } vmcase(OP_VARARG) { - int b = GETARG_B(i) - 1; /* required results */ - TValue *vtab = vRC(i); /* vararg table */ - Protect(luaT_getvarargs(L, vtab, ra, b)); + int n = GETARG_C(i) - 1; /* required results */ + TValue *vtab = vRB(i); /* vararg table */ + Protect(luaT_getvarargs(L, vtab, ra, n)); vmbreak; } vmcase(OP_EXTRAARG) {