From 84e32ad2ebd6bd160c1320456743a5b1d8f233e9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 23 Nov 2018 12:23:45 -0200 Subject: Added opcodes for arithmetic with K operands Added opcodes for all seven arithmetic operators with K operands (that is, operands that are numbers in the array of constants of the function). They cover the cases of constant float operands (e.g., 'x + .0.0', 'x^0.5') and large integer operands (e.g., 'x % 10000'). --- lcode.c | 126 +++++++++++++++++++++++++++++++----------------------- ldebug.c | 10 ++++- ljumptab.h | 7 +++ lopcodes.c | 7 +++ lopcodes.h | 10 +++++ lopnames.h | 7 +++ ltests.h | 1 - lvm.c | 61 ++++++++++++++++++++++++++ testes/code.lua | 82 +++++++++++++++++++++-------------- testes/db.lua | 2 + testes/events.lua | 2 + 11 files changed, 228 insertions(+), 87 deletions(-) diff --git a/lcode.c b/lcode.c index 054b28fd..1872ede2 100644 --- a/lcode.c +++ b/lcode.c @@ -371,10 +371,6 @@ int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { } -#define codeABsC(fs,o,a,b,c,k) luaK_codeABCk(fs,o,a,b,((c) + OFFSET_sC),k) - - - /* ** Format and emit an 'iABx' instruction. */ @@ -884,31 +880,46 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { } +/* +** Try to make 'e' a K expression with an index in the range of R/K +** indices. Return true iff succeeded. +*/ +static int luaK_exp2K (FuncState *fs, expdesc *e) { + if (!hasjumps(e)) { + int info; + switch (e->k) { /* move constants to 'k' */ + case VTRUE: info = boolK(fs, 1); break; + case VFALSE: info = boolK(fs, 0); break; + case VNIL: info = nilK(fs); break; + case VKINT: info = luaK_intK(fs, e->u.ival); break; + case VKFLT: info = luaK_numberK(fs, e->u.nval); break; + case VK: info = e->u.info; break; + default: return 0; /* not a constant */ + } + if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ + e->k = VK; /* make expression a 'K' expression */ + e->u.info = info; + return 1; + } + } + /* else, expression doesn't fit; leave it unchanged */ + return 0; +} + + /* ** Ensures final expression result is in a valid R/K index ** (that is, it is either in a register or in 'k' with an index ** in the range of R/K indices). -** Returns 1 if expression is K, 0 otherwise. +** Returns 1 iff expression is K. */ int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { /* move constants to 'k' */ - case VTRUE: e->u.info = boolK(fs, 1); goto vk; - case VFALSE: e->u.info = boolK(fs, 0); goto vk; - case VNIL: e->u.info = nilK(fs); goto vk; - case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; - case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; - case VK: - vk: - e->k = VK; - if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ - return 1; - else break; - default: break; + if (luaK_exp2K(fs, e)) + return 1; + else { /* not a constant in the right range: put it in a register */ + luaK_exp2anyreg(fs, e); + return 0; } - /* not a constant in the right range: put it in a register */ - luaK_exp2anyreg(fs, e); - return 0; } @@ -1232,8 +1243,19 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { } +/* +** Emit code for binary expressions that "produce values" +** (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, - int pc, int line) { + OpCode op, int v2, int k, int line) { + 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 */ @@ -1242,20 +1264,13 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, /* -** Emit code for binary expressions that "produce values" -** (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). +** Emit code for binary expressions that "produce values" over +** two registers. */ static void codebinexpval (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ - int v1 = luaK_exp2anyreg(fs, e1); - int pc = luaK_codeABC(fs, op, 0, v1, v2); /* generate opcode */ - finishbinexpval(fs, e1, e2, pc, line); + finishbinexpval(fs, e1, e2, op, v2, 0, line); } @@ -1264,41 +1279,48 @@ static void codebinexpval (FuncState *fs, OpCode op, */ static void codebini (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int k, int line) { - int v2 = cast_int(e2->u.ival); /* immediate operand */ - int v1 = luaK_exp2anyreg(fs, e1); - int pc = codeABsC(fs, op, 0, v1, v2, k); /* generate opcode */ - finishbinexpval(fs, e1, e2, pc, line); + int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ + finishbinexpval(fs, e1, e2, op, v2, k, line); +} + + +static void swapexps (expdesc *e1, expdesc *e2) { + expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ } /* ** Code arithmetic operators ('+', '-', ...). If second operand is a ** constant in the proper range, use variant opcodes with immediate -** operands. +** operands or K operands. */ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int flip, int line) { - if (!isSCint(e2)) - codebinexpval(fs, op, e1, e2, line); /* use standard operators */ - else /* use immediate operators */ + if (isSCint(e2)) /* immediate operand? */ codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); -} - - -static void swapexps (expdesc *e1, expdesc *e2) { - expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ + 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); + } + else { /* 'e2' is neither an immediate nor a K operand */ + if (flip) + swapexps(e1, e2); /* back to original order */ + codebinexpval(fs, op, e1, e2, line); /* use standard operators */ + } } /* ** Code commutative operators ('+', '*'). If first operand is a -** constant, change order of operands to use immediate operator. +** numeric constant, change order of operands to try to use an +** immediate or K operator. */ static void codecommutative (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { int flip = 0; - if (isSCint(e1)) { - swapexps(e1, e2); + if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ + swapexps(e1, e2); /* change order */ flip = 1; } codearith(fs, op, e1, e2, flip, line); @@ -1312,7 +1334,7 @@ static void codecommutative (FuncState *fs, OpCode op, static void codebitwise (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { int inv = 0; - int v1, v2, pc; + int v2; OpCode op; if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { swapexps(e1, e2); /* 'e2' will be the constant operand */ @@ -1323,12 +1345,10 @@ static void codebitwise (FuncState *fs, BinOpr opr, codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ return; } - v1 = luaK_exp2anyreg(fs, e1); v2 = e2->u.info; /* index in K array */ op = cast(OpCode, opr - OPR_BAND + OP_BANDK); lua_assert(ttisinteger(&fs->f->k[v2])); - pc = luaK_codeABCk(fs, op, 0, v1, v2, inv); - finishbinexpval(fs, e1, e2, pc, line); + finishbinexpval(fs, e1, e2, op, v2, inv, line); } diff --git a/ldebug.c b/ldebug.c index ee1b87d9..766a5231 100644 --- a/ldebug.c +++ b/ldebug.c @@ -610,12 +610,18 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 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: - case OP_BANDK: case OP_BORK: case OP_BXORK: { + 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 */ 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: { diff --git a/ljumptab.h b/ljumptab.h index 6767e95b..0af997d0 100644 --- a/ljumptab.h +++ b/ljumptab.h @@ -51,6 +51,13 @@ static void *disptab[] = { &&L_OP_POWI, &&L_OP_DIVI, &&L_OP_IDIVI, +&&L_OP_ADDK, +&&L_OP_SUBK, +&&L_OP_MULK, +&&L_OP_MODK, +&&L_OP_POWK, +&&L_OP_DIVK, +&&L_OP_IDIVK, &&L_OP_BANDK, &&L_OP_BORK, &&L_OP_BXORK, diff --git a/lopcodes.c b/lopcodes.c index 11a73c29..3f0d551a 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -45,6 +45,13 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,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_ADDK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_SUBK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MULK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_MODK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_POWK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_DIVK */ + ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVK */ ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */ ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */ ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */ diff --git a/lopcodes.h b/lopcodes.h index 7bb83a1e..d7403caf 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -221,6 +221,14 @@ OP_POWI,/* A B sC R(A) := R(B) ^ C */ OP_DIVI,/* A B sC R(A) := R(B) / C */ OP_IDIVI,/* A B sC R(A) := R(B) // C */ +OP_ADDK,/* A B C R(A) := R(B) + K(C) */ +OP_SUBK,/* A B C R(A) := R(B) - K(C) */ +OP_MULK,/* A B C R(A) := R(B) * K(C) */ +OP_MODK,/* A B C R(A) := R(B) % K(C) */ +OP_POWK,/* A B C R(A) := R(B) ^ K(C) */ +OP_DIVK,/* A B C R(A) := R(B) / K(C) */ +OP_IDIVK,/* A B C R(A) := R(B) // K(C) */ + OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */ OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ @@ -235,11 +243,13 @@ OP_MOD,/* A B C R(A) := R(B) % R(C) */ OP_POW,/* A B C R(A) := R(B) ^ R(C) */ OP_DIV,/* A B C R(A) := R(B) / R(C) */ OP_IDIV,/* A B C R(A) := R(B) // R(C) */ + OP_BAND,/* A B C R(A) := R(B) & R(C) */ OP_BOR,/* A B C R(A) := R(B) | R(C) */ 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_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 b2c4fe21..96d901ac 100644 --- a/lopnames.h +++ b/lopnames.h @@ -36,6 +36,13 @@ static const char *const opnames[] = { "POWI", "DIVI", "IDIVI", + "ADDK", + "SUBK", + "MULK", + "MODK", + "POWK", + "DIVK", + "IDIVK", "BANDK", "BORK", "BXORK", diff --git a/ltests.h b/ltests.h index d44974a4..9d409c8d 100644 --- a/ltests.h +++ b/ltests.h @@ -119,7 +119,6 @@ LUA_API void *debug_realloc (void *ud, void *block, #undef LUAL_BUFFERSIZE #define LUAL_BUFFERSIZE 23 #define MINSTRTABSIZE 2 -#define MAXINDEXRK 1 #define MAXIWTHABS 3 diff --git a/lvm.c b/lvm.c index ece7d77a..27ef68cf 100644 --- a/lvm.c +++ b/lvm.c @@ -855,6 +855,39 @@ void luaV_finishOp (lua_State *L) { else op_arithf_aux(L, v1, v2, fop, tm); } +/* +** Arithmetic operations with K operands. +*/ +#define op_arithK(L,iop,fop,tm,flip) { \ + TValue *v1 = vRB(i); \ + 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)); \ + } \ + else { \ + lua_Number n1; lua_Number n2; \ + if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ + setfltvalue(s2v(ra), fop(L, n1, n2)); \ + } \ + else \ + Protect(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } } + + +/* +** Arithmetic operations with K operands for floats. +*/ +#define op_arithfK(L,fop,tm) { \ + TValue *v1 = vRB(i); \ + 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 \ + Protect(luaT_trybinTM(L, v1, v2, ra, tm)); } + + /* ** Bitwise operations with constant operand. */ @@ -1219,6 +1252,34 @@ void luaV_execute (lua_State *L, CallInfo *ci) { op_arithI(L, luaV_idiv, luai_numidiv, TM_IDIV, 0); vmbreak; } + vmcase(OP_ADDK) { + op_arithK(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i)); + vmbreak; + } + vmcase(OP_SUBK) { + op_arithK(L, l_subi, luai_numsub, TM_SUB, 0); + vmbreak; + } + vmcase(OP_MULK) { + op_arithK(L, l_muli, luai_nummul, TM_MUL, GETARG_k(i)); + vmbreak; + } + vmcase(OP_MODK) { + op_arithK(L, luaV_mod, luaV_modf, TM_MOD, 0); + vmbreak; + } + vmcase(OP_POWK) { + op_arithfK(L, luai_numpow, TM_POW); + vmbreak; + } + vmcase(OP_DIVK) { + op_arithfK(L, luai_numdiv, TM_DIV); + vmbreak; + } + vmcase(OP_IDIVK) { + op_arithK(L, luaV_idiv, luai_numidiv, TM_IDIV, 0); + vmbreak; + } vmcase(OP_ADD) { op_arith(L, l_addi, luai_numadd, TM_ADD); vmbreak; diff --git a/testes/code.lua b/testes/code.lua index 4d44fa6a..834ff5e2 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -40,6 +40,7 @@ checkKlist(foo, {3.78/4, -3.78/4, -3.79/4}) -- testing opcodes +-- check that 'f' opcodes match '...' function check (f, ...) local arg = {...} local c = T.listcode(f) @@ -52,9 +53,19 @@ function check (f, ...) end +-- check that 'f' opcodes match '...' and that 'f(p) == r'. +function checkR (f, p, r, ...) + local r1 = f(p) + assert(r == r1 and math.type(r) == math.type(r1)) + check(f, ...) +end + + +-- check that 'a' and 'b' has the same opcodes function checkequal (a, b) a = T.listcode(a) b = T.listcode(b) + assert(#a == #b) for i = 1, #a do a[i] = string.gsub(a[i], '%b()', '') -- remove line number b[i] = string.gsub(b[i], '%b()', '') -- remove line number @@ -165,65 +176,64 @@ end, -- equalities -check(function (a) if a == 1 then return 2 end end, +checkR(function (a) if a == 1 then return 2 end end, 1, 2, 'EQI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if -4.0 == a then return 2 end end, +checkR(function (a) if -4.0 == a then return 2 end end, -4, 2, 'EQI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if a == "hi" then return 2 end end, +checkR(function (a) if a == "hi" then return 2 end end, 10, nil, 'EQK', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if a == 10000 then return 2 end end, +checkR(function (a) if a == 10000 then return 2 end end, 1, nil, 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large -check(function (a) if -10000 == a then return 2 end end, +checkR(function (a) if -10000 == a then return 2 end end, -10000, 2, 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large -- comparisons -check(function (a) if -10 <= a then return 2 end end, +checkR(function (a) if -10 <= a then return 2 end end, -10, 2, 'GEI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if 128.0 > a then return 2 end end, +checkR(function (a) if 128.0 > a then return 2 end end, 129, nil, 'LTI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if -127.0 < a then return 2 end end, +checkR(function (a) if -127.0 < a then return 2 end end, -127, nil, 'GTI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if 10 < a then return 2 end end, +checkR(function (a) if 10 < a then return 2 end end, 11, 2, 'GTI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if 129 < a then return 2 end end, +checkR(function (a) if 129 < a then return 2 end end, 130, 2, 'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if a >= 23.0 then return 2 end end, +checkR(function (a) if a >= 23.0 then return 2 end end, 25, 2, 'GEI', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if a >= 23.1 then return 2 end end, +checkR(function (a) if a >= 23.1 then return 2 end end, 0, nil, 'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1') -check(function (a) if a > 2300.0 then return 2 end end, +checkR(function (a) if a > 2300.0 then return 2 end end, 0, nil, 'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1') -- constant folding local function checkK (func, val) check(func, 'LOADK', 'RETURN1') - local k = T.listk(func) - assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) + checkKlist(func, {val}) assert(func() == val) end local function checkI (func, val) check(func, 'LOADI', 'RETURN1') - assert(#T.listk(func) == 0) + checkKlist(func, {}) assert(func() == val) end local function checkF (func, val) check(func, 'LOADF', 'RETURN1') - assert(#T.listk(func) == 0) + checkKlist(func, {}) assert(func() == val) end @@ -258,20 +268,30 @@ checkK(function () return -65536.0 end, -(sbx + 1.0)) -- immediate operands -check(function (x) return x + 1 end, 'ADDI', 'RETURN1') -check(function (x) return 128 + x end, 'ADDI', 'RETURN1') -check(function (x) return x * -127 end, 'MULI', 'RETURN1') -check(function (x) return 20 * x end, 'MULI', 'RETURN1') -check(function (x) return x ^ -2 end, 'POWI', 'RETURN1') -check(function (x) return x / 40 end, 'DIVI', 'RETURN1') -check(function (x) return x // 1 end, 'IDIVI', 'RETURN1') -check(function (x) return x % (100 - 10) end, 'MODI', 'RETURN1') -check(function (x) return 1 << x end, 'SHLI', 'RETURN1') -check(function (x) return x << 2 end, 'SHRI', 'RETURN1') -check(function (x) return x >> 2 end, 'SHRI', 'RETURN1') -check(function (x) return x & 1 end, 'BANDK', 'RETURN1') -check(function (x) return 10 | x end, 'BORK', 'RETURN1') -check(function (x) return -10 ~ x end, 'BXORK', 'RETURN1') +checkR(function (x) return x + 1 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 1 << 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') + +-- 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') -- no foldings (and immediate operands) check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1') diff --git a/testes/db.lua b/testes/db.lua index 9da68210..5b243c39 100644 --- a/testes/db.lua +++ b/testes/db.lua @@ -794,6 +794,8 @@ assert(a[3] == "index" and a^3 == "pow" and a..a == "concat") assert(a/3 == "div" and 3%a == "mod") assert(a+3 == "add" and 3-a == "sub" and a*3 == "mul" and -a == "unm" and #a == "len" and a&3 == "band") +assert(a + 30000 == "add" and a - 3.0 == "sub" and a * 3.0 == "mul" and + -a == "unm" and #a == "len" and a & 3 == "band") assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shift" and a>>1 == "shift") assert (a==b and a.op == "eq") diff --git a/testes/events.lua b/testes/events.lua index b071c2a3..ac630d89 100644 --- a/testes/events.lua +++ b/testes/events.lua @@ -144,6 +144,8 @@ t.__bnot = f("bnot") -- when the constant table is very small. assert(b+5 == b) assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==undef) +assert(5.2 + b == 5.2) +assert(cap[0] == "add" and cap[1] == 5.2 and cap[2] == b and cap[3]==undef) assert(b+'5' == b) assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==undef) assert(5+b == 5) -- cgit v1.2.1