Browse Source

bug ('#3' causes seg. fault in 5.3-beta) + comments + 'codearith' ->
'codeexpval' (confusion about what operations function accept was
one of the reasons for the bug)

Roberto Ierusalimschy 10 years ago
parent
commit
bf163ea7f0
1 changed files with 24 additions and 13 deletions
  1. 24 13
      lcode.c

+ 24 - 13
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.95 2014/11/02 19:19:04 roberto Exp roberto $
+** $Id: lcode.c,v 2.96 2014/11/21 12:15:57 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -801,19 +801,30 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
 }
 
 
-static void codearith (FuncState *fs, OpCode op,
-                       expdesc *e1, expdesc *e2, int line) {
-  if (!constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) {
+/*
+** Code for binary and unary expressions that "produce values"
+** (arithmetic operations, bitwise operations, concat, length). First
+** try to do constant folding (only for numeric [arithmetic and
+** bitwise] operations, which is what 'lua_arith' accepts).
+** Expression to produce final result will be encoded in 'e1'.
+*/
+static void codeexpval (FuncState *fs, OpCode op,
+                        expdesc *e1, expdesc *e2, int line) {
+  lua_assert(op >= OP_ADD);
+  if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2))
+    return;  /* result has been folded */
+  else {
     int o1, o2;
-    if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) {
-      o2 = 0;
+    /* move operands to registers (if needed) */
+    if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) {  /* unary op? */
+      o2 = 0;  /* no second expression */
       o1 = luaK_exp2anyreg(fs, e1);  /* cannot operate on constants */
     }
     else {  /* regular case (binary operators) */
-      o2 = luaK_exp2RK(fs, e2);
+      o2 = luaK_exp2RK(fs, e2);  /* both operands are "RK" */
       o1 = luaK_exp2RK(fs, e1);
     }
-    if (o1 > o2) {
+    if (o1 > o2) {  /* free registers in proper order */
       freeexp(fs, e1);
       freeexp(fs, e2);
     }
@@ -821,8 +832,8 @@ static void codearith (FuncState *fs, OpCode op,
       freeexp(fs, e2);
       freeexp(fs, e1);
     }
-    e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);
-    e1->k = VRELOCABLE;
+    e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);  /* generate opcode */
+    e1->k = VRELOCABLE;  /* all those operations are relocable */
     luaK_fixline(fs, line);
   }
 }
@@ -849,7 +860,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
   e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
   switch (op) {
     case OPR_MINUS: case OPR_BNOT: case OPR_LEN: {
-      codearith(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line);
+      codeexpval(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line);
       break;
     }
     case OPR_NOT: codenot(fs, e); break;
@@ -915,7 +926,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
       }
       else {
         luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
-        codearith(fs, OP_CONCAT, e1, e2, line);
+        codeexpval(fs, OP_CONCAT, e1, e2, line);
       }
       break;
     }
@@ -923,7 +934,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
     case OPR_IDIV: case OPR_MOD: case OPR_POW:
     case OPR_BAND: case OPR_BOR: case OPR_BXOR:
     case OPR_SHL: case OPR_SHR: {
-      codearith(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line);
+      codeexpval(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line);
       break;
     }
     case OPR_EQ: case OPR_LT: case OPR_LE: {