diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-21 12:49:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-21 12:49:32 -0300 |
commit | 212095a601ee68e99065b553f7b6bc216056d82e (patch) | |
tree | 3843f9dde40eeb71c56ac8a0be8d77c78272f6ef | |
parent | c67603fafba7f982e92eb870ff4da6c6433c2a85 (diff) | |
download | lua-212095a601ee68e99065b553f7b6bc216056d82e.tar.gz lua-212095a601ee68e99065b553f7b6bc216056d82e.tar.bz2 lua-212095a601ee68e99065b553f7b6bc216056d82e.zip |
new opcodes OP_GTI/OP_GEI
-rw-r--r-- | lcode.c | 30 | ||||
-rw-r--r-- | lopcodes.c | 6 | ||||
-rw-r--r-- | lopcodes.h | 9 | ||||
-rw-r--r-- | ltm.c | 5 | ||||
-rw-r--r-- | lvm.c | 45 |
5 files changed, 50 insertions, 45 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.155 2018/02/17 19:20:00 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.156 2018/02/21 12:54:26 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -171,8 +171,8 @@ void luaK_ret (FuncState *fs, int first, int nret) { | |||
171 | ** Code a "conditional jump", that is, a test or comparison opcode | 171 | ** Code a "conditional jump", that is, a test or comparison opcode |
172 | ** followed by a jump. Return jump position. | 172 | ** followed by a jump. Return jump position. |
173 | */ | 173 | */ |
174 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { | 174 | static int condjump (FuncState *fs, OpCode op, int A, int B, int k) { |
175 | luaK_codeABCk(fs, op, A, B, C, k); | 175 | luaK_codeABCk(fs, op, A, B, 0, k); |
176 | return luaK_jump(fs); | 176 | return luaK_jump(fs); |
177 | } | 177 | } |
178 | 178 | ||
@@ -979,13 +979,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
979 | Instruction ie = getinstruction(fs, e); | 979 | Instruction ie = getinstruction(fs, e); |
980 | if (GET_OPCODE(ie) == OP_NOT) { | 980 | if (GET_OPCODE(ie) == OP_NOT) { |
981 | fs->pc--; /* remove previous OP_NOT */ | 981 | fs->pc--; /* remove previous OP_NOT */ |
982 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); | 982 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); |
983 | } | 983 | } |
984 | /* else go through */ | 984 | /* else go through */ |
985 | } | 985 | } |
986 | discharge2anyreg(fs, e); | 986 | discharge2anyreg(fs, e); |
987 | freeexp(fs, e); | 987 | freeexp(fs, e); |
988 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); | 988 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); |
989 | } | 989 | } |
990 | 990 | ||
991 | 991 | ||
@@ -1338,16 +1338,12 @@ static void codeshift (FuncState *fs, OpCode op, | |||
1338 | 1338 | ||
1339 | /* | 1339 | /* |
1340 | ** Emit code for order comparisons. | 1340 | ** Emit code for order comparisons. |
1341 | ** When the first operand is an integral value in the proper range, | 1341 | ** When the first operand A is an integral value in the proper range, |
1342 | ** change (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) so that | 1342 | ** change (A < B) to (B > A) and (A <= B) to (B >= A) so that |
1343 | ** it can use an immediate operand. In this case, C indicates this | 1343 | ** it can use an immediate operand. |
1344 | ** change, for cases that cannot assume a total order (NaN and | ||
1345 | ** metamethods). | ||
1346 | */ | 1344 | */ |
1347 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | 1345 | static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { |
1348 | int r1, r2; | 1346 | int r1, r2; |
1349 | int cond = 1; | ||
1350 | int C = 0; | ||
1351 | lua_Integer im; | 1347 | lua_Integer im; |
1352 | if (isSCnumber(e2, &im)) { | 1348 | if (isSCnumber(e2, &im)) { |
1353 | /* use immediate operand */ | 1349 | /* use immediate operand */ |
@@ -1356,19 +1352,17 @@ static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |||
1356 | op = cast(OpCode, (op - OP_LT) + OP_LTI); | 1352 | op = cast(OpCode, (op - OP_LT) + OP_LTI); |
1357 | } | 1353 | } |
1358 | else if (isSCnumber(e1, &im)) { | 1354 | else if (isSCnumber(e1, &im)) { |
1359 | /* transform (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) */ | 1355 | /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ |
1360 | r1 = luaK_exp2anyreg(fs, e2); | 1356 | r1 = luaK_exp2anyreg(fs, e2); |
1361 | r2 = cast_int(im); | 1357 | r2 = cast_int(im); |
1362 | op = (op == OP_LT) ? OP_LEI : OP_LTI; | 1358 | op = (op == OP_LT) ? OP_GTI : OP_GEI; |
1363 | cond = 0; /* negate original test */ | ||
1364 | C = 1; /* indication that it used the transformations */ | ||
1365 | } | 1359 | } |
1366 | else { /* regular case, compare two registers */ | 1360 | else { /* regular case, compare two registers */ |
1367 | r1 = luaK_exp2anyreg(fs, e1); | 1361 | r1 = luaK_exp2anyreg(fs, e1); |
1368 | r2 = luaK_exp2anyreg(fs, e2); | 1362 | r2 = luaK_exp2anyreg(fs, e2); |
1369 | } | 1363 | } |
1370 | freeexps(fs, e1, e2); | 1364 | freeexps(fs, e1, e2); |
1371 | e1->u.info = condjump(fs, op, r1, r2, C, cond); | 1365 | e1->u.info = condjump(fs, op, r1, r2, 1); |
1372 | e1->k = VJMP; | 1366 | e1->k = VJMP; |
1373 | } | 1367 | } |
1374 | 1368 | ||
@@ -1399,7 +1393,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1399 | r2 = luaK_exp2anyreg(fs, e2); | 1393 | r2 = luaK_exp2anyreg(fs, e2); |
1400 | } | 1394 | } |
1401 | freeexps(fs, e1, e2); | 1395 | freeexps(fs, e1, e2); |
1402 | e1->u.info = condjump(fs, op, r1, r2, 0, (opr == OPR_EQ)); | 1396 | e1->u.info = condjump(fs, op, r1, r2, (opr == OPR_EQ)); |
1403 | e1->k = VJMP; | 1397 | e1->k = VJMP; |
1404 | } | 1398 | } |
1405 | 1399 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.77 2018/02/09 15:16:06 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.78 2018/02/15 15:34:29 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -75,6 +75,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
75 | "EQI", | 75 | "EQI", |
76 | "LTI", | 76 | "LTI", |
77 | "LEI", | 77 | "LEI", |
78 | "GTI", | ||
79 | "GEI", | ||
78 | "TEST", | 80 | "TEST", |
79 | "TESTSET", | 81 | "TESTSET", |
80 | "CALL", | 82 | "CALL", |
@@ -156,6 +158,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
156 | ,opmode(0, 0, 1, 0, iABC) /* OP_EQI */ | 158 | ,opmode(0, 0, 1, 0, iABC) /* OP_EQI */ |
157 | ,opmode(0, 0, 1, 0, iABC) /* OP_LTI */ | 159 | ,opmode(0, 0, 1, 0, iABC) /* OP_LTI */ |
158 | ,opmode(0, 0, 1, 0, iABC) /* OP_LEI */ | 160 | ,opmode(0, 0, 1, 0, iABC) /* OP_LEI */ |
161 | ,opmode(0, 0, 1, 0, iABC) /* OP_GTI */ | ||
162 | ,opmode(0, 0, 1, 0, iABC) /* OP_GEI */ | ||
159 | ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ | 163 | ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */ |
160 | ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ | 164 | ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */ |
161 | ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ | 165 | ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.187 2018/02/09 15:16:06 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.188 2018/02/15 15:34:29 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -260,6 +260,8 @@ OP_EQK,/* A B if ((R(A) == K(B)) ~= k) then pc++ */ | |||
260 | OP_EQI,/* A sB if ((R(A) == sB) ~= k) then pc++ */ | 260 | OP_EQI,/* A sB if ((R(A) == sB) ~= k) then pc++ */ |
261 | OP_LTI,/* A sB if ((R(A) < sB) ~= k) then pc++ */ | 261 | OP_LTI,/* A sB if ((R(A) < sB) ~= k) then pc++ */ |
262 | OP_LEI,/* A sB if ((R(A) <= sB) ~= k) then pc++ */ | 262 | OP_LEI,/* A sB if ((R(A) <= sB) ~= k) then pc++ */ |
263 | OP_GTI,/* A sB if ((R(A) > sB) ~= k) then pc++ */ | ||
264 | OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */ | ||
263 | 265 | ||
264 | OP_TEST,/* A if (not R(A) == k) then pc++ */ | 266 | OP_TEST,/* A if (not R(A) == k) then pc++ */ |
265 | OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ | 267 | OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ |
@@ -317,11 +319,6 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
317 | (*) For comparisons, k specifies what condition the test should accept | 319 | (*) For comparisons, k specifies what condition the test should accept |
318 | (true or false). | 320 | (true or false). |
319 | 321 | ||
320 | (*) For OP_LTI/OP_LEI, C indicates that the transformations | ||
321 | (A<B) => (!(B<=A)) or (A<=B) => (!(B<A)) were used to put the constant | ||
322 | operator on the right side. (Non-total orders with NaN or metamethods | ||
323 | use this indication to correct their behavior.) | ||
324 | |||
325 | (*) All 'skips' (pc++) assume that next instruction is a jump. | 322 | (*) All 'skips' (pc++) assume that next instruction is a jump. |
326 | 323 | ||
327 | (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the | 324 | (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.61 2018/02/15 15:34:29 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.62 2018/02/17 19:20:00 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -208,11 +208,10 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | |||
208 | setivalue(&aux, v2); | 208 | setivalue(&aux, v2); |
209 | if (inv) { /* arguments were exchanged? */ | 209 | if (inv) { /* arguments were exchanged? */ |
210 | p2 = p1; p1 = &aux; /* correct them */ | 210 | p2 = p1; p1 = &aux; /* correct them */ |
211 | event = (event == TM_LE) ? TM_LT : TM_LE; | ||
212 | } | 211 | } |
213 | else | 212 | else |
214 | p2 = &aux; | 213 | p2 = &aux; |
215 | return (luaT_callorderTM(L, p1, p2, event) != inv); | 214 | return luaT_callorderTM(L, p1, p2, event); |
216 | } | 215 | } |
217 | 216 | ||
218 | 217 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.343 2018/02/21 12:54:26 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.344 2018/02/21 13:47:03 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -731,18 +731,15 @@ void luaV_finishOp (lua_State *L) { | |||
731 | } | 731 | } |
732 | case OP_LT: case OP_LE: | 732 | case OP_LT: case OP_LE: |
733 | case OP_LTI: case OP_LEI: | 733 | case OP_LTI: case OP_LEI: |
734 | case OP_GTI: case OP_GEI: | ||
734 | case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ | 735 | case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ |
735 | int res = !l_isfalse(s2v(L->top - 1)); | 736 | int res = !l_isfalse(s2v(L->top - 1)); |
736 | L->top--; | 737 | L->top--; |
737 | if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ | 738 | if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ |
738 | lua_assert(op == OP_LE || | ||
739 | (op == OP_LTI && GETARG_C(inst)) || | ||
740 | (op == OP_LEI && !GETARG_C(inst))); | ||
741 | ci->callstatus ^= CIST_LEQ; /* clear mark */ | 739 | ci->callstatus ^= CIST_LEQ; /* clear mark */ |
742 | res = !res; /* negate result */ | 740 | res = !res; /* negate result */ |
743 | } | 741 | } |
744 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); | 742 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); |
745 | if (GETARG_C(inst)) res = !res; | ||
746 | if (res != GETARG_k(inst)) /* condition failed? */ | 743 | if (res != GETARG_k(inst)) /* condition failed? */ |
747 | ci->u.l.savedpc++; /* skip jump instruction */ | 744 | ci->u.l.savedpc++; /* skip jump instruction */ |
748 | break; | 745 | break; |
@@ -1473,26 +1470,40 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1473 | int im = GETARG_sB(i); | 1470 | int im = GETARG_sB(i); |
1474 | if (ttisinteger(vra)) | 1471 | if (ttisinteger(vra)) |
1475 | cond = (ivalue(vra) < im); | 1472 | cond = (ivalue(vra) < im); |
1476 | else if (ttisfloat(vra)) { | 1473 | else if (ttisfloat(vra)) |
1477 | lua_Number f = fltvalue(vra); | 1474 | cond = luai_numlt(fltvalue(vra), cast_num(im)); |
1478 | cond = (!luai_numisnan(f)) ? luai_numlt(f, cast_num(im)) | ||
1479 | : GETARG_C(i); /* NaN */ | ||
1480 | } | ||
1481 | else | 1475 | else |
1482 | Protect(cond = luaT_callorderiTM(L, vra, im, GETARG_C(i), TM_LT)); | 1476 | Protect(cond = luaT_callorderiTM(L, vra, im, 0, TM_LT)); |
1483 | goto condjump; | 1477 | goto condjump; |
1484 | } | 1478 | } |
1485 | vmcase(OP_LEI) { | 1479 | vmcase(OP_LEI) { |
1486 | int im = GETARG_sB(i); | 1480 | int im = GETARG_sB(i); |
1487 | if (ttisinteger(vra)) | 1481 | if (ttisinteger(vra)) |
1488 | cond = (ivalue(vra) <= im); | 1482 | cond = (ivalue(vra) <= im); |
1489 | else if (ttisfloat(vra)) { | 1483 | else if (ttisfloat(vra)) |
1490 | lua_Number f = fltvalue(vra); | 1484 | cond = luai_numle(fltvalue(vra), cast_num(im)); |
1491 | cond = (!luai_numisnan(f)) ? luai_numle(f, cast_num(im)) | 1485 | else |
1492 | : GETARG_C(i); /* NaN? */ | 1486 | Protect(cond = luaT_callorderiTM(L, vra, im, 0, TM_LE)); |
1493 | } | 1487 | goto condjump; |
1488 | } | ||
1489 | vmcase(OP_GTI) { | ||
1490 | int im = GETARG_sB(i); | ||
1491 | if (ttisinteger(vra)) | ||
1492 | cond = (im < ivalue(vra)); | ||
1493 | else if (ttisfloat(vra)) | ||
1494 | cond = luai_numlt(cast_num(im), fltvalue(vra)); | ||
1495 | else | ||
1496 | Protect(cond = luaT_callorderiTM(L, vra, im, 1, TM_LT)); | ||
1497 | goto condjump; | ||
1498 | } | ||
1499 | vmcase(OP_GEI) { | ||
1500 | int im = GETARG_sB(i); | ||
1501 | if (ttisinteger(vra)) | ||
1502 | cond = (im <= ivalue(vra)); | ||
1503 | else if (ttisfloat(vra)) | ||
1504 | cond = luai_numle(cast_num(im), fltvalue(vra)); | ||
1494 | else | 1505 | else |
1495 | Protect(cond = luaT_callorderiTM(L, vra, im, GETARG_C(i), TM_LE)); | 1506 | Protect(cond = luaT_callorderiTM(L, vra, im, 1, TM_LE)); |
1496 | goto condjump; | 1507 | goto condjump; |
1497 | } | 1508 | } |
1498 | vmcase(OP_TEST) { | 1509 | vmcase(OP_TEST) { |