aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c61
1 files changed, 29 insertions, 32 deletions
diff --git a/lcode.c b/lcode.c
index bc86793a..abb8a811 100644
--- a/lcode.c
+++ b/lcode.c
@@ -359,12 +359,12 @@ static void removelastlineinfo (FuncState *fs) {
359 Proto *f = fs->f; 359 Proto *f = fs->f;
360 int pc = fs->pc - 1; /* last instruction coded */ 360 int pc = fs->pc - 1; /* last instruction coded */
361 if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ 361 if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */
362 fs->previousline -= f->lineinfo[pc]; /* last line saved */ 362 fs->previousline -= f->lineinfo[pc]; /* correct last line saved */
363 fs->iwthabs--; 363 fs->iwthabs--; /* undo previous increment */
364 } 364 }
365 else { /* absolute line information */ 365 else { /* absolute line information */
366 lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc);
366 fs->nabslineinfo--; /* remove it */ 367 fs->nabslineinfo--; /* remove it */
367 lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc);
368 fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ 368 fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */
369 } 369 }
370} 370}
@@ -626,12 +626,12 @@ static int nilK (FuncState *fs) {
626 626
627 627
628/* 628/*
629** Check whether 'i' can be stored in an 'sC' operand. 629** Check whether 'i' can be stored in an 'sC' operand. Equivalent to
630** Equivalent to (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) 630** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of
631** but without risk of overflows in the addition. 631** overflows in the hidden addition inside 'int2sC'.
632*/ 632*/
633static int fitsC (lua_Integer i) { 633static int fitsC (lua_Integer i) {
634 return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC); 634 return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C));
635} 635}
636 636
637 637
@@ -1213,15 +1213,6 @@ static int isSCint (expdesc *e) {
1213 1213
1214 1214
1215/* 1215/*
1216** Check whether expression 'e' and its negation are literal integers
1217** in proper range to fit in register sC
1218*/
1219static int isSCintN (expdesc *e) {
1220 return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival);
1221}
1222
1223
1224/*
1225** Check whether expression 'e' is a literal integer or float in 1216** Check whether expression 'e' is a literal integer or float in
1226** proper range to fit in a register (sB or sC). 1217** proper range to fit in a register (sB or sC).
1227*/ 1218*/
@@ -1382,15 +1373,25 @@ static void codebini (FuncState *fs, OpCode op,
1382} 1373}
1383 1374
1384 1375
1385/* Code binary operators negating the immediate operand for the 1376/* Try to code a binary operator negating its second operand.
1386** opcode. For the metamethod, 'v2' must keep its original value. 1377** For the metamethod, 2nd operand must keep its original value.
1387*/ 1378*/
1388static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, 1379static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
1389 OpCode op, int line, TMS event) { 1380 OpCode op, int line, TMS event) {
1390 int v2 = cast_int(e2->u.ival); 1381 if (!luaK_isKint(e2))
1391 finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); 1382 return 0; /* not an integer constant */
1392 /* correct metamethod argument */ 1383 else {
1393 SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); 1384 lua_Integer i2 = e2->u.ival;
1385 if (!(fitsC(i2) && fitsC(-i2)))
1386 return 0; /* not in the proper range */
1387 else { /* operating a small integer constant */
1388 int v2 = cast_int(i2);
1389 finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
1390 /* correct metamethod argument */
1391 SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
1392 return 1; /* successfully coded */
1393 }
1394 }
1394} 1395}
1395 1396
1396 1397
@@ -1647,11 +1648,8 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1647 break; 1648 break;
1648 } 1649 }
1649 case OPR_SUB: { 1650 case OPR_SUB: {
1650 if (isSCintN(e2)) { /* subtracting a small integer constant? */ 1651 if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB))
1651 /* code it as (r1 + -I) */ 1652 break; /* coded as (r1 + -I) */
1652 finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB);
1653 break;
1654 }
1655 /* ELSE *//* FALLTHROUGH */ 1653 /* ELSE *//* FALLTHROUGH */
1656 } 1654 }
1657 case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { 1655 case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: {
@@ -1667,16 +1665,15 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1667 swapexps(e1, e2); 1665 swapexps(e1, e2);
1668 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ 1666 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */
1669 } 1667 }
1670 else if (isSCintN(e2)) { /* shifting by a small integer constant? */ 1668 else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) {
1671 /* code it as (r1 >> -I) */ 1669 /* coded as (r1 >> -I) */;
1672 finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL);
1673 } 1670 }
1674 else /* regular case (two registers) */ 1671 else /* regular case (two registers) */
1675 codebinexpval(fs, OP_SHL, e1, e2, line); 1672 codebinexpval(fs, OP_SHL, e1, e2, line);
1676 break; 1673 break;
1677 } 1674 }
1678 case OPR_SHR: { 1675 case OPR_SHR: {
1679 if (isSCintN(e2)) 1676 if (isSCint(e2))
1680 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ 1677 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */
1681 else /* regular case (two registers) */ 1678 else /* regular case (two registers) */
1682 codebinexpval(fs, OP_SHR, e1, e2, line); 1679 codebinexpval(fs, OP_SHR, e1, e2, line);