Browse Source

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.)
pull/23/head
Roberto Ierusalimschy 5 years ago
parent
commit
df13f25948
  1. 46
      lcode.c
  2. 21
      ldebug.c
  3. 3
      ljumptab.h
  4. 3
      lopcodes.c
  5. 4
      lopcodes.h
  6. 3
      lopnames.h
  7. 4
      ltm.c
  8. 2
      ltm.h
  9. 85
      lvm.c
  10. 63
      testes/code.lua
  11. 2
      testes/coroutine.lua

46
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);

21
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 */
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 */
case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
tm = cast(TMS, GETARG_C(i));
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;

3
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,

3
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 */

4
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) */

3
lopnames.h

@ -60,6 +60,9 @@ static const char *const opnames[] = {
"BXOR",
"SHL",
"SHR",
"MMBIN",
"MMBINI",
"MMBINK",
"UNM",
"BNOT",
"NOT",

4
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);
}

2
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,

85
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) {
}
/* }================================================================== */

63
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,

2
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")

Loading…
Cancel
Save