aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/lcode.c b/lcode.c
index eccb8380..1005f1b7 100644
--- a/lcode.c
+++ b/lcode.c
@@ -52,7 +52,7 @@ l_noret luaK_semerror (LexState *ls, const char *msg) {
52** If expression is a numeric constant, fills 'v' with its value 52** If expression is a numeric constant, fills 'v' with its value
53** and returns 1. Otherwise, returns 0. 53** and returns 1. Otherwise, returns 0.
54*/ 54*/
55static int tonumeral(const expdesc *e, TValue *v) { 55int luaK_tonumeral (FuncState *fs, const expdesc *e, TValue *v) {
56 if (hasjumps(e)) 56 if (hasjumps(e))
57 return 0; /* not a numeral */ 57 return 0; /* not a numeral */
58 switch (e->k) { 58 switch (e->k) {
@@ -62,12 +62,42 @@ static int tonumeral(const expdesc *e, TValue *v) {
62 case VKFLT: 62 case VKFLT:
63 if (v) setfltvalue(v, e->u.nval); 63 if (v) setfltvalue(v, e->u.nval);
64 return 1; 64 return 1;
65 case VUPVAL: { /* may be a constant */
66 Vardesc *vd = luaY_getvardesc(&fs, e);
67 if (v && vd && !ttisnil(&vd->val)) {
68 setobj(fs->ls->L, v, &vd->val);
69 return 1;
70 } /* else */
71 } /* FALLTHROUGH */
65 default: return 0; 72 default: return 0;
66 } 73 }
67} 74}
68 75
69 76
70/* 77/*
78** If expression 'e' is a constant, change 'e' to represent
79** the constant value.
80*/
81static int const2exp (FuncState *fs, expdesc *e) {
82 Vardesc *vd = luaY_getvardesc(&fs, e);
83 if (vd) {
84 TValue *v = &vd->val;
85 switch (ttypetag(v)) {
86 case LUA_TNUMINT:
87 e->k = VKINT;
88 e->u.ival = ivalue(v);
89 return 1;
90 case LUA_TNUMFLT:
91 e->k = VKFLT;
92 e->u.nval = fltvalue(v);
93 return 1;
94 }
95 }
96 return 0;
97}
98
99
100/*
71** Return the previous instruction of the current code. If there 101** Return the previous instruction of the current code. If there
72** may be a jump target between the current instruction and the 102** may be a jump target between the current instruction and the
73** previous one, return an invalid instruction (to avoid wrong 103** previous one, return an invalid instruction (to avoid wrong
@@ -683,8 +713,10 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
683 break; 713 break;
684 } 714 }
685 case VUPVAL: { /* move value to some (pending) register */ 715 case VUPVAL: { /* move value to some (pending) register */
686 e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.var.idx, 0); 716 if (!const2exp(fs, e)) {
687 e->k = VRELOC; 717 e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.var.idx, 0);
718 e->k = VRELOC;
719 }
688 break; 720 break;
689 } 721 }
690 case VINDEXUP: { 722 case VINDEXUP: {
@@ -1218,9 +1250,11 @@ static int validop (int op, TValue *v1, TValue *v2) {
1218** (In this case, 'e1' has the final result.) 1250** (In this case, 'e1' has the final result.)
1219*/ 1251*/
1220static int constfolding (FuncState *fs, int op, expdesc *e1, 1252static int constfolding (FuncState *fs, int op, expdesc *e1,
1221 const expdesc *e2) { 1253 const expdesc *e2) {
1222 TValue v1, v2, res; 1254 TValue v1, v2, res;
1223 if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) 1255 if (!luaK_tonumeral(fs, e1, &v1) ||
1256 !luaK_tonumeral(fs, e2, &v2) ||
1257 !validop(op, &v1, &v2))
1224 return 0; /* non-numeric operands or not safe to fold */ 1258 return 0; /* non-numeric operands or not safe to fold */
1225 luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ 1259 luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */
1226 if (ttisinteger(&res)) { 1260 if (ttisinteger(&res)) {
@@ -1307,7 +1341,7 @@ static void codearith (FuncState *fs, OpCode op,
1307 expdesc *e1, expdesc *e2, int flip, int line) { 1341 expdesc *e1, expdesc *e2, int flip, int line) {
1308 if (isSCint(e2)) /* immediate operand? */ 1342 if (isSCint(e2)) /* immediate operand? */
1309 codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); 1343 codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line);
1310 else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ 1344 else if (luaK_tonumeral(fs, e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */
1311 int v2 = e2->u.info; /* K index */ 1345 int v2 = e2->u.info; /* K index */
1312 op = cast(OpCode, op - OP_ADD + OP_ADDK); 1346 op = cast(OpCode, op - OP_ADD + OP_ADDK);
1313 finishbinexpval(fs, e1, e2, op, v2, flip, line); 1347 finishbinexpval(fs, e1, e2, op, v2, flip, line);
@@ -1328,7 +1362,7 @@ static void codearith (FuncState *fs, OpCode op,
1328static void codecommutative (FuncState *fs, OpCode op, 1362static void codecommutative (FuncState *fs, OpCode op,
1329 expdesc *e1, expdesc *e2, int line) { 1363 expdesc *e1, expdesc *e2, int line) {
1330 int flip = 0; 1364 int flip = 0;
1331 if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ 1365 if (luaK_tonumeral(fs, e1, NULL)) { /* is first operand a numeric constant? */
1332 swapexps(e1, e2); /* change order */ 1366 swapexps(e1, e2); /* change order */
1333 flip = 1; 1367 flip = 1;
1334 } 1368 }
@@ -1451,7 +1485,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
1451 case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ 1485 case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */
1452 if (constfolding(fs, op + LUA_OPUNM, e, &ef)) 1486 if (constfolding(fs, op + LUA_OPUNM, e, &ef))
1453 break; 1487 break;
1454 /* FALLTHROUGH */ 1488 /* else */ /* FALLTHROUGH */
1455 case OPR_LEN: 1489 case OPR_LEN:
1456 codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); 1490 codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
1457 break; 1491 break;
@@ -1466,6 +1500,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
1466** 2nd operand. 1500** 2nd operand.
1467*/ 1501*/
1468void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { 1502void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
1503 luaK_dischargevars(fs, v);
1469 switch (op) { 1504 switch (op) {
1470 case OPR_AND: { 1505 case OPR_AND: {
1471 luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ 1506 luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */
@@ -1484,13 +1519,13 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
1484 case OPR_MOD: case OPR_POW: 1519 case OPR_MOD: case OPR_POW:
1485 case OPR_BAND: case OPR_BOR: case OPR_BXOR: 1520 case OPR_BAND: case OPR_BOR: case OPR_BXOR:
1486 case OPR_SHL: case OPR_SHR: { 1521 case OPR_SHL: case OPR_SHR: {
1487 if (!tonumeral(v, NULL)) 1522 if (!luaK_tonumeral(fs, v, NULL))
1488 luaK_exp2anyreg(fs, v); 1523 luaK_exp2anyreg(fs, v);
1489 /* else keep numeral, which may be folded with 2nd operand */ 1524 /* else keep numeral, which may be folded with 2nd operand */
1490 break; 1525 break;
1491 } 1526 }
1492 case OPR_EQ: case OPR_NE: { 1527 case OPR_EQ: case OPR_NE: {
1493 if (!tonumeral(v, NULL)) 1528 if (!luaK_tonumeral(fs, v, NULL))
1494 luaK_exp2RK(fs, v); 1529 luaK_exp2RK(fs, v);
1495 /* else keep numeral, which may be an immediate operand */ 1530 /* else keep numeral, which may be an immediate operand */
1496 break; 1531 break;
@@ -1535,17 +1570,16 @@ static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) {
1535*/ 1570*/
1536void luaK_posfix (FuncState *fs, BinOpr opr, 1571void luaK_posfix (FuncState *fs, BinOpr opr,
1537 expdesc *e1, expdesc *e2, int line) { 1572 expdesc *e1, expdesc *e2, int line) {
1573 luaK_dischargevars(fs, e2);
1538 switch (opr) { 1574 switch (opr) {
1539 case OPR_AND: { 1575 case OPR_AND: {
1540 lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ 1576 lua_assert(e1->t == NO_JUMP); /* list closed by 'luaK_infix' */
1541 luaK_dischargevars(fs, e2);
1542 luaK_concat(fs, &e2->f, e1->f); 1577 luaK_concat(fs, &e2->f, e1->f);
1543 *e1 = *e2; 1578 *e1 = *e2;
1544 break; 1579 break;
1545 } 1580 }
1546 case OPR_OR: { 1581 case OPR_OR: {
1547 lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ 1582 lua_assert(e1->f == NO_JUMP); /* list closed by 'luaK_infix' */
1548 luaK_dischargevars(fs, e2);
1549 luaK_concat(fs, &e2->t, e1->t); 1583 luaK_concat(fs, &e2->t, e1->t);
1550 *e1 = *e2; 1584 *e1 = *e2;
1551 break; 1585 break;