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)
This commit is contained in:
Roberto Ierusalimschy 2014-11-24 12:59:22 -02:00
parent 075661ffde
commit bf163ea7f0
1 changed files with 24 additions and 13 deletions

37
lcode.c
View File

@ -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 ** Code generator for Lua
** See Copyright Notice in lua.h ** 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) { ** Code for binary and unary expressions that "produce values"
if (!constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) { ** (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; int o1, o2;
if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { /* move operands to registers (if needed) */
o2 = 0; 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 */ o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */
} }
else { /* regular case (binary operators) */ else { /* regular case (binary operators) */
o2 = luaK_exp2RK(fs, e2); o2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
o1 = luaK_exp2RK(fs, e1); o1 = luaK_exp2RK(fs, e1);
} }
if (o1 > o2) { if (o1 > o2) { /* free registers in proper order */
freeexp(fs, e1); freeexp(fs, e1);
freeexp(fs, e2); freeexp(fs, e2);
} }
@ -821,8 +832,8 @@ static void codearith (FuncState *fs, OpCode op,
freeexp(fs, e2); freeexp(fs, e2);
freeexp(fs, e1); freeexp(fs, e1);
} }
e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */
e1->k = VRELOCABLE; e1->k = VRELOCABLE; /* all those operations are relocable */
luaK_fixline(fs, line); 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; e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
switch (op) { switch (op) {
case OPR_MINUS: case OPR_BNOT: case OPR_LEN: { 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; break;
} }
case OPR_NOT: codenot(fs, e); break; case OPR_NOT: codenot(fs, e); break;
@ -915,7 +926,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
} }
else { else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ 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; break;
} }
@ -923,7 +934,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
case OPR_IDIV: case OPR_MOD: case OPR_POW: case OPR_IDIV: case OPR_MOD: case OPR_POW:
case OPR_BAND: case OPR_BOR: case OPR_BXOR: case OPR_BAND: case OPR_BOR: case OPR_BXOR:
case OPR_SHL: case OPR_SHR: { 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; break;
} }
case OPR_EQ: case OPR_LT: case OPR_LE: { case OPR_EQ: case OPR_LT: case OPR_LE: {