aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/lcode.c b/lcode.c
index f53722ff..ded49b0e 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.66 2013/04/26 13:07:53 roberto Exp roberto $ 2** $Id: lcode.c,v 2.67 2013/04/29 16:57:48 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*/
@@ -29,8 +29,18 @@
29#define hasjumps(e) ((e)->t != (e)->f) 29#define hasjumps(e) ((e)->t != (e)->f)
30 30
31 31
32static int isnumeral(expdesc *e) { 32static int tonumeral(expdesc *e, TValue *v) {
33 return (e->k == VKFLT && e->t == NO_JUMP && e->f == NO_JUMP); 33 if (e->t != NO_JUMP || e->f != NO_JUMP)
34 return 0; /* not a numeral */
35 switch (e->k) {
36 case VKINT:
37 if (v) setivalue(v, e->u.ival);
38 return 1;
39 case VKFLT:
40 if (v) setnvalue(v, e->u.nval);
41 return 1;
42 default: return 0;
43 }
34} 44}
35 45
36 46
@@ -730,21 +740,28 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
730 740
731 741
732static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { 742static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
733 lua_Number r; 743 TValue v1, v2, res;
734 if (!isnumeral(e1) || !isnumeral(e2)) return 0; 744 lua_Integer i2;
735 if ((op == OP_DIV || op == OP_IDIV || op == OP_MOD) && e2->u.nval == 0) 745 if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2))
736 return 0; /* do not attempt to divide by 0 */ 746 return 0;
737 r = luaO_numarith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); 747 if ((op == OP_IDIV || op == OP_MOD) && tointeger(&v2, &i2) && i2 == 0)
738 e1->u.nval = r; 748 return 0; /* avoid division by 0 at compile time */
749 luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res);
750 if (ttisinteger(&res)) {
751 e1->k = VKINT;
752 e1->u.ival = ivalue(&res);
753 }
754 else {
755 e1->k = VKFLT;
756 e1->u.nval = fltvalue(&res);
757 }
739 return 1; 758 return 1;
740} 759}
741 760
742 761
743static void codearith (FuncState *fs, OpCode op, 762static void codearith (FuncState *fs, OpCode op,
744 expdesc *e1, expdesc *e2, int line) { 763 expdesc *e1, expdesc *e2, int line) {
745 if (constfolding(op, e1, e2)) 764 if (!constfolding(op, e1, e2)) { /* could not fold operation? */
746 return;
747 else {
748 int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; 765 int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
749 int o1 = luaK_exp2RK(fs, e1); 766 int o1 = luaK_exp2RK(fs, e1);
750 if (o1 > o2) { 767 if (o1 > o2) {
@@ -783,9 +800,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
783 e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; 800 e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0;
784 switch (op) { 801 switch (op) {
785 case OPR_MINUS: { 802 case OPR_MINUS: {
786 if (isnumeral(e)) /* minus constant? */ 803 if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */
787 e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */
788 else {
789 luaK_exp2anyreg(fs, e); 804 luaK_exp2anyreg(fs, e);
790 codearith(fs, OP_UNM, e, &e2, line); 805 codearith(fs, OP_UNM, e, &e2, line);
791 } 806 }
@@ -819,7 +834,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
819 case OPR_ADD: case OPR_SUB: 834 case OPR_ADD: case OPR_SUB:
820 case OPR_MUL: case OPR_DIV: case OPR_IDIV: 835 case OPR_MUL: case OPR_DIV: case OPR_IDIV:
821 case OPR_MOD: case OPR_POW: { 836 case OPR_MOD: case OPR_POW: {
822 if (!isnumeral(v)) luaK_exp2RK(fs, v); 837 if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
823 break; 838 break;
824 } 839 }
825 default: { 840 default: {