From df13f259487459f3a28d31d76c890aa6c2d061e0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 27 Aug 2019 13:59:39 -0300 Subject: [PATCH] First version of OP_MMBIN opcodes In arithmetic/bitwise operators, the call to metamethods is made in a separate opcode following the main one. (The main opcode skips this next one when the operation succeeds.) This change reduces slightly the size of the binary and the complexity of the arithmetic/bitwise opcodes. It also simplfies the treatment of errors and yeld/resume in these operations, as there are much fewer cases to consider. (Only OP_MMBIN/OP_MMBINI/OP_MMBINK, instead of all variants of all arithmetic/bitwise operators.) --- lcode.c | 46 ++++++++++++++---------- ldebug.c | 21 ++++------- ljumptab.h | 3 ++ lopcodes.c | 3 ++ lopcodes.h | 4 +++ lopnames.h | 3 ++ ltm.c | 4 +-- ltm.h | 2 +- lvm.c | 85 ++++++++++++++++++++++++-------------------- testes/code.lua | 63 +++++++++++++++++--------------- testes/coroutine.lua | 2 +- 11 files changed, 132 insertions(+), 104 deletions(-) diff --git a/lcode.c b/lcode.c index c2b5fc6d..a1b27a00 100644 --- a/lcode.c +++ b/lcode.c @@ -1337,18 +1337,20 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { ** (everything but logical operators 'and'/'or' and comparison ** operators). ** Expression to produce final result will be encoded in 'e1'. -** Because 'luaK_exp2anyreg' can free registers, its calls must be -** in "stack order" (that is, first on 'e2', which may have more -** recent registers to be released). */ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, - OpCode op, int v2, int k, int line) { + OpCode op, int v2, int k, int line, + OpCode mmop, TMS event) { int v1 = luaK_exp2anyreg(fs, e1); int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); freeexps(fs, e1, e2); e1->u.info = pc; e1->k = VRELOC; /* all those operations are relocatable */ luaK_fixline(fs, line); +if (event != TM_SHL && event != TM_SHR) { + luaK_codeABCk(fs, mmop, v1, v2, event, k); /* to call metamethod */ + luaK_fixline(fs, line); +} } @@ -1359,7 +1361,9 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, static void codebinexpval (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ - finishbinexpval(fs, e1, e2, op, v2, 0, line); + lua_assert(OP_ADD <= op && op <= OP_SHR); + finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, + cast(TMS, (op - OP_ADD) + TM_ADD)); } @@ -1367,9 +1371,10 @@ static void codebinexpval (FuncState *fs, OpCode op, ** Code binary operators ('+', '-', ...) with immediate operands. */ static void codebini (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int k, int line) { + expdesc *e1, expdesc *e2, int k, int line, + TMS event) { int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ - finishbinexpval(fs, e1, e2, op, v2, k, line); + finishbinexpval(fs, e1, e2, op, v2, k, line, OP_MMBINI, event); } @@ -1383,16 +1388,18 @@ static void swapexps (expdesc *e1, expdesc *e2) { ** constant in the proper range, use variant opcodes with immediate ** operands or K operands. */ -static void codearith (FuncState *fs, OpCode op, +static void codearith (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int flip, int line) { + TMS event = cast(TMS, opr + TM_ADD); if (isSCint(e2)) /* immediate operand? */ - codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); + codebini(fs, cast(OpCode, opr + OP_ADDI), e1, e2, flip, line, event); else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ int v2 = e2->u.info; /* K index */ - op = cast(OpCode, op - OP_ADD + OP_ADDK); - finishbinexpval(fs, e1, e2, op, v2, flip, line); + OpCode op = cast(OpCode, opr + OP_ADDK); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); } else { /* 'e2' is neither an immediate nor a K operand */ + OpCode op = cast(OpCode, opr + OP_ADD); if (flip) swapexps(e1, e2); /* back to original order */ codebinexpval(fs, op, e1, e2, line); /* use standard operators */ @@ -1405,7 +1412,7 @@ static void codearith (FuncState *fs, OpCode op, ** numeric constant, change order of operands to try to use an ** immediate or K operator. */ -static void codecommutative (FuncState *fs, OpCode op, +static void codecommutative (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2, int line) { int flip = 0; if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ @@ -1430,14 +1437,15 @@ static void codebitwise (FuncState *fs, BinOpr opr, inv = 1; } else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ - op = cast(OpCode, opr - OPR_BAND + OP_BAND); + op = cast(OpCode, opr + OP_ADD); codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ return; } v2 = e2->u.info; /* index in K array */ - op = cast(OpCode, opr - OPR_BAND + OP_BANDK); + op = cast(OpCode, opr + OP_ADDK); lua_assert(ttisinteger(&fs->f->k[v2])); - finishbinexpval(fs, e1, e2, op, v2, inv, line); + finishbinexpval(fs, e1, e2, op, v2, inv, line, OP_MMBINK, + cast(TMS, opr + TM_ADD)); } @@ -1453,7 +1461,7 @@ static void codeshift (FuncState *fs, OpCode op, changedir = 1; e2->u.ival = -(e2->u.ival); } - codebini(fs, OP_SHRI, e1, e2, changedir, line); + codebini(fs, OP_SHRI, e1, e2, changedir, line, TM_SHL); } else codebinexpval(fs, op, e1, e2, line); @@ -1638,13 +1646,13 @@ void luaK_posfix (FuncState *fs, BinOpr opr, } case OPR_ADD: case OPR_MUL: { if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) - codecommutative(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); + codecommutative(fs, opr, e1, e2, line); break; } case OPR_SUB: case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) - codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); + codearith(fs, opr, e1, e2, 0, line); break; } case OPR_BAND: case OPR_BOR: case OPR_BXOR: { @@ -1656,7 +1664,7 @@ void luaK_posfix (FuncState *fs, BinOpr opr, if (!constfolding(fs, LUA_OPSHL, e1, e2)) { if (isSCint(e1)) { swapexps(e1, e2); - codebini(fs, OP_SHLI, e1, e2, 1, line); + codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); } else codeshift(fs, OP_SHL, e1, e2, line); diff --git a/ldebug.c b/ldebug.c index 9593039b..4e1dc6b9 100644 --- a/ldebug.c +++ b/ldebug.c @@ -471,6 +471,10 @@ static int findsetreg (const Proto *p, int lastpc, int reg) { int pc; int setreg = -1; /* keep last instruction that changed 'reg' */ int jmptarget = 0; /* any code before this address is conditional */ + if (GET_OPCODE(p->code[lastpc]) == OP_MMBIN || + GET_OPCODE(p->code[lastpc]) == OP_MMBINI || + GET_OPCODE(p->code[lastpc]) == OP_MMBINK) + lastpc--; for (pc = 0; pc < lastpc; pc++) { Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); @@ -620,22 +624,11 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: tm = TM_NEWINDEX; break; - case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI: - case OP_POWI: case OP_DIVI: case OP_IDIVI: { - int offset = GET_OPCODE(i) - OP_ADDI; /* ORDER OP */ - tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ + case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { + tm = cast(TMS, GETARG_C(i)); break; } - case OP_ADDK: case OP_SUBK: case OP_MULK: case OP_MODK: - case OP_POWK: case OP_DIVK: case OP_IDIVK: - case OP_BANDK: case OP_BORK: case OP_BXORK: { - int offset = GET_OPCODE(i) - OP_ADDK; /* ORDER OP */ - tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ - break; - } - case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: - case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: - case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { + case OP_SHL: case OP_SHR: { int offset = GET_OPCODE(i) - OP_ADD; /* ORDER OP */ tm = cast(TMS, offset + TM_ADD); /* ORDER TM */ break; diff --git a/ljumptab.h b/ljumptab.h index 2d4cf28b..1832c809 100644 --- a/ljumptab.h +++ b/ljumptab.h @@ -75,6 +75,9 @@ static void *disptab[NUM_OPCODES] = { &&L_OP_BXOR, &&L_OP_SHL, &&L_OP_SHR, +&&L_OP_MMBIN, +&&L_OP_MMBINI, +&&L_OP_MMBINK, &&L_OP_UNM, &&L_OP_BNOT, &&L_OP_NOT, diff --git a/lopcodes.c b/lopcodes.c index ee795786..aede93a5 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -69,6 +69,9 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,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, 0, iABC) /* OP_MMBIN */ + ,opmode(0, 0, 0, 0, iABC) /* OP_MMBINI*/ + ,opmode(0, 0, 0, 0, iABC) /* OP_MMBINK*/ ,opmode(0, 0, 0, 1, iABC) /* OP_UNM */ ,opmode(0, 0, 0, 1, iABC) /* OP_BNOT */ ,opmode(0, 0, 0, 1, iABC) /* OP_NOT */ diff --git a/lopcodes.h b/lopcodes.h index 26b1850d..fd578c68 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -255,6 +255,10 @@ OP_BXOR,/* A B C R(A) := R(B) ~ R(C) */ OP_SHL,/* A B C R(A) := R(B) << R(C) */ OP_SHR,/* A B C R(A) := R(B) >> R(C) */ +OP_MMBIN,/* A B C call B metamethod for previous bin. operation */ +OP_MMBINI,/* A B C call B metamethod for previous binI. operation */ +OP_MMBINK,/* A B C call B metamethod for previous binK. operation */ + OP_UNM,/* A B R(A) := -R(B) */ OP_BNOT,/* A B R(A) := ~R(B) */ OP_NOT,/* A B R(A) := not R(B) */ diff --git a/lopnames.h b/lopnames.h index 28535fe2..0fc1da1f 100644 --- a/lopnames.h +++ b/lopnames.h @@ -60,6 +60,9 @@ static const char *const opnames[] = { "BXOR", "SHL", "SHR", + "MMBIN", + "MMBINI", + "MMBINK", "UNM", "BNOT", "NOT", diff --git a/ltm.c b/ltm.c index 19233a87..991e62c1 100644 --- a/ltm.c +++ b/ltm.c @@ -173,7 +173,7 @@ void luaT_tryconcatTM (lua_State *L) { void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, int flip, TMS event) { + int flip, StkId res, TMS event) { if (flip) luaT_trybinTM(L, p2, p1, res, event); else @@ -185,7 +185,7 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, int flip, StkId res, TMS event) { TValue aux; setivalue(&aux, i2); - luaT_trybinassocTM(L, p1, &aux, res, flip, event); + luaT_trybinassocTM(L, p1, &aux, flip, res, event); } diff --git a/ltm.h b/ltm.h index 51dfe793..9621e68e 100644 --- a/ltm.h +++ b/ltm.h @@ -77,7 +77,7 @@ LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event); LUAI_FUNC void luaT_tryconcatTM (lua_State *L); LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, - const TValue *p2, StkId res, int inv, TMS event); + const TValue *p2, int inv, StkId res, TMS event); LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, int inv, StkId res, TMS event); LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, diff --git a/lvm.c b/lvm.c index 907417e3..a9e8455e 100644 --- a/lvm.c +++ b/lvm.c @@ -717,18 +717,11 @@ void luaV_finishOp (lua_State *L) { Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ - case OP_ADDI: case OP_SUBI: - case OP_MULI: case OP_DIVI: case OP_IDIVI: - case OP_MODI: case OP_POWI: - case OP_ADDK: case OP_SUBK: - case OP_MULK: case OP_DIVK: case OP_IDIVK: - case OP_MODK: case OP_POWK: - case OP_ADD: case OP_SUB: - case OP_MUL: case OP_DIV: case OP_IDIV: - case OP_BANDK: case OP_BORK: case OP_BXORK: - case OP_BAND: case OP_BOR: case OP_BXOR: + case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { + setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top); + break; + } case OP_SHLI: case OP_SHRI: case OP_SHL: case OP_SHR: - case OP_MOD: case OP_POW: case OP_UNM: case OP_BNOT: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: case OP_GETFIELD: case OP_SELF: { @@ -804,10 +797,8 @@ void luaV_finishOp (lua_State *L) { lua_Number nb; \ if (tonumberns(v1, nb)) { \ lua_Number fimm = cast_num(imm); \ - setfltvalue(s2v(ra), fop(L, nb, fimm)); \ - } \ - else \ - ProtectNT(luaT_trybiniTM(L, v1, imm, flip, ra, tm)); } + pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \ + }} /* @@ -827,7 +818,7 @@ void luaV_finishOp (lua_State *L) { int imm = GETARG_sC(i); \ if (ttisinteger(v1)) { \ lua_Integer iv1 = ivalue(v1); \ - setivalue(s2v(ra), iop(L, iv1, imm)); \ + pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \ } \ else op_arithfI_aux(L, v1, imm, fop, tm, flip); } @@ -839,10 +830,8 @@ void luaV_finishOp (lua_State *L) { #define op_arithf_aux(L,v1,v2,fop,tm) { \ lua_Number n1; lua_Number n2; \ if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ - setfltvalue(s2v(ra), fop(L, n1, n2)); \ - } \ - else \ - ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } + pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \ + }} /* @@ -862,7 +851,7 @@ void luaV_finishOp (lua_State *L) { TValue *v2 = vRC(i); \ if (ttisinteger(v1) && ttisinteger(v2)) { \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ - setivalue(s2v(ra), iop(L, i1, i2)); \ + pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ } \ else op_arithf_aux(L, v1, v2, fop, tm); } @@ -875,15 +864,13 @@ void luaV_finishOp (lua_State *L) { TValue *v2 = KC(i); \ if (ttisinteger(v1) && ttisinteger(v2)) { \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ - setivalue(s2v(ra), iop(L, i1, i2)); \ + pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ } \ else { \ lua_Number n1; lua_Number n2; \ if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ - setfltvalue(s2v(ra), fop(L, n1, n2)); \ - } \ - else \ - ProtectNT(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } } + pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \ + }}} /* @@ -894,10 +881,8 @@ void luaV_finishOp (lua_State *L) { TValue *v2 = KC(i); \ lua_Number n1; lua_Number n2; \ if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ - setfltvalue(s2v(ra), fop(L, n1, n2)); \ - } \ - else \ - ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } + pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \ + }} /* @@ -909,10 +894,8 @@ void luaV_finishOp (lua_State *L) { lua_Integer i1; \ lua_Integer i2 = ivalue(v2); \ if (tointegerns(v1, &i1)) { \ - setivalue(s2v(ra), op(L, i1, i2)); \ - } \ - else \ - ProtectNT(luaT_trybiniTM(L, v1, i2, TESTARG_k(i), ra, tm)); } + pc++; setivalue(s2v(ra), op(L, i1, i2)); \ + }} /* @@ -923,10 +906,8 @@ void luaV_finishOp (lua_State *L) { TValue *v2 = vRC(i); \ lua_Integer i1; lua_Integer i2; \ if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) { \ - setivalue(s2v(ra), op(L, i1, i2)); \ - } \ - else \ - ProtectNT(luaT_trybinTM(L, v1, v2, ra, tm)); } + pc++; setivalue(s2v(ra), op(L, i1, i2)); \ + }} /* @@ -1443,6 +1424,33 @@ void luaV_execute (lua_State *L, CallInfo *ci) { ProtectNT(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); vmbreak; } + vmcase(OP_MMBIN) { + Instruction pi = *(pc - 2); /* original arith. expression */ + TValue *rb = vRB(i); + TMS tm = (TMS)GETARG_C(i); + StkId result = RA(pi); + lua_assert(OP_ADD <= GET_OPCODE(pi) && GET_OPCODE(pi) <= OP_SHR); + ProtectNT(luaT_trybinTM(L, s2v(ra), rb, result, tm)); + vmbreak; + } + vmcase(OP_MMBINI) { + Instruction pi = *(pc - 2); /* original arith. expression */ + int imm = GETARG_sB(i); + TMS tm = (TMS)GETARG_C(i); + int flip = GETARG_k(i); + StkId result = RA(pi); + ProtectNT(luaT_trybiniTM(L, s2v(ra), imm, flip, result, tm)); + vmbreak; + } + vmcase(OP_MMBINK) { + Instruction pi = *(pc - 2); /* original arith. expression */ + TValue *imm = KB(i); + TMS tm = (TMS)GETARG_C(i); + int flip = GETARG_k(i); + StkId result = RA(pi); + ProtectNT(luaT_trybinassocTM(L, s2v(ra), imm, flip, result, tm)); + vmbreak; + } vmcase(OP_UNM) { TValue *rb = vRB(i); lua_Number nb; @@ -1826,4 +1834,3 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } /* }================================================================== */ - diff --git a/testes/code.lua b/testes/code.lua index 3b768f33..fcb5c309 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -156,9 +156,9 @@ check(function () c.x, a[b] = -((a + d/b - a[b]) ^ a.x), b end, 'LOADNIL', - 'MUL', - 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETFIELD', 'POW', - 'UNM', 'SETTABLE', 'SETFIELD', 'RETURN0') + 'MUL', 'MMBIN', + 'DIV', 'MMBIN', 'ADD', 'MMBIN', 'GETTABLE', 'SUB', 'MMBIN', + 'GETFIELD', 'POW', 'MMBIN', 'UNM', 'SETTABLE', 'SETFIELD', 'RETURN0') -- direct access to constants @@ -188,7 +188,7 @@ check(function () b = a/a b = 5-4 end, - 'LOADNIL', 'SUB', 'DIV', 'LOADI', 'RETURN0') + 'LOADNIL', 'SUB', 'MMBIN', 'DIV', 'MMBIN', 'LOADI', 'RETURN0') check(function () local a,b @@ -292,38 +292,45 @@ checkK(function () return -(border + 1) end, -(sbx + 1.0)) -- immediate operands -checkR(function (x) return x + k1 end, 10, 11, 'ADDI', 'RETURN1') -checkR(function (x) return 128 + x end, 0.0, 128.0, 'ADDI', 'RETURN1') -checkR(function (x) return x * -127 end, -1.0, 127.0, 'MULI', 'RETURN1') -checkR(function (x) return 20 * x end, 2, 40, 'MULI', 'RETURN1') -checkR(function (x) return x ^ -2 end, 2, 0.25, 'POWI', 'RETURN1') -checkR(function (x) return x / 40 end, 40, 1.0, 'DIVI', 'RETURN1') -checkR(function (x) return x // 1 end, 10.0, 10.0, 'IDIVI', 'RETURN1') -checkR(function (x) return x % (100 - 10) end, 91, 1, 'MODI', 'RETURN1') +checkR(function (x) return x + k1 end, 10, 11, 'ADDI', 'MMBINI', 'RETURN1') +checkR(function (x) return 128 + x end, 0.0, 128.0, + 'ADDI', 'MMBINI', 'RETURN1') +checkR(function (x) return x * -127 end, -1.0, 127.0, + 'MULI', 'MMBINI', 'RETURN1') +checkR(function (x) return 20 * x end, 2, 40, 'MULI', 'MMBINI', 'RETURN1') +checkR(function (x) return x ^ -2 end, 2, 0.25, 'POWI', 'MMBINI', 'RETURN1') +checkR(function (x) return x / 40 end, 40, 1.0, 'DIVI', 'MMBINI', 'RETURN1') +checkR(function (x) return x // 1 end, 10.0, 10.0, + 'IDIVI', 'MMBINI', 'RETURN1') +checkR(function (x) return x % (100 - 10) end, 91, 1, + 'MODI', 'MMBINI', 'RETURN1') checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'RETURN1') checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'RETURN1') checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'RETURN1') -checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'RETURN1') -checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'RETURN1') -checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'RETURN1') +checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1') +checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1') +checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1') -- K operands in arithmetic operations -checkR(function (x) return x + 0.0 end, 1, 1.0, 'ADDK', 'RETURN1') --- check(function (x) return 128 + x end, 'ADDK', 'RETURN1') -checkR(function (x) return x * -10000 end, 2, -20000, 'MULK', 'RETURN1') --- check(function (x) return 20 * x end, 'MULK', 'RETURN1') -checkR(function (x) return x ^ 0.5 end, 4, 2.0, 'POWK', 'RETURN1') -checkR(function (x) return x / 2.0 end, 4, 2.0, 'DIVK', 'RETURN1') -checkR(function (x) return x // 10000 end, 10000, 1, 'IDIVK', 'RETURN1') -checkR(function (x) return x % (100.0 - 10) end, 91, 1.0, 'MODK', 'RETURN1') +checkR(function (x) return x + 0.0 end, 1, 1.0, 'ADDK', 'MMBINK', 'RETURN1') +-- check(function (x) return 128 + x end, 'ADDK', 'MMBINK', 'RETURN1') +checkR(function (x) return x * -10000 end, 2, -20000, + 'MULK', 'MMBINK', 'RETURN1') +-- check(function (x) return 20 * x end, 'MULK', 'MMBINK', 'RETURN1') +checkR(function (x) return x ^ 0.5 end, 4, 2.0, 'POWK', 'MMBINK', 'RETURN1') +checkR(function (x) return x / 2.0 end, 4, 2.0, 'DIVK', 'MMBINK', 'RETURN1') +checkR(function (x) return x // 10000 end, 10000, 1, + 'IDIVK', 'MMBINK', 'RETURN1') +checkR(function (x) return x % (100.0 - 10) end, 91, 1.0, + 'MODK', 'MMBINK', 'RETURN1') -- no foldings (and immediate operands) check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1') -check(function () return k3/0 end, 'LOADI', 'DIVI', 'RETURN1') -check(function () return 0%0 end, 'LOADI', 'MODI', 'RETURN1') -check(function () return -4//0 end, 'LOADI', 'IDIVI', 'RETURN1') +check(function () return k3/0 end, 'LOADI', 'DIVI', 'MMBINI', 'RETURN1') +check(function () return 0%0 end, 'LOADI', 'MODI', 'MMBINI', 'RETURN1') +check(function () return -4//0 end, 'LOADI', 'IDIVI', 'MMBINI', 'RETURN1') check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'RETURN1') -check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'RETURN1') +check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1') -- basic 'for' loops check(function () for i = -10, 10.5 do end end, @@ -379,7 +386,7 @@ check(function (a, b) if b then break else a = a + 1 end end end, -'TEST', 'JMP', 'TEST', 'JMP', 'ADDI', 'JMP', 'RETURN0') +'TEST', 'JMP', 'TEST', 'JMP', 'ADDI', 'MMBINI', 'JMP', 'RETURN0') checkequal( function (a) while a < 10 do a = a + 1 end end, diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 48f4c5bf..81d848a3 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua @@ -751,7 +751,7 @@ assert(run(function () return a >> 2 end, {"shr"}) == 10 >> 2) assert(run(function () return 1 >> a end, {"shr"}) == 1 >> 10) assert(run(function () return a << 2 end, {"shl"}) == 10 << 2) assert(run(function () return 1 << a end, {"shl"}) == 1 << 10) -assert(run(function () return a ~ 2 end, {"bxor"}) == 10 ~ 2) +assert(run(function () return 2 ~ a end, {"bxor"}) == 2 ~ 10) assert(run(function () return a..b end, {"concat"}) == "1012")