diff options
Diffstat (limited to 'src/lcode.c')
-rw-r--r-- | src/lcode.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/src/lcode.c b/src/lcode.c index 72afce96..cfe4a210 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,16 +1,18 @@ /* -** $Id: lcode.c,v 2.90 2014/05/08 18:58:46 roberto Exp $ +** $Id: lcode.c,v 2.97 2014/11/24 14:59:22 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ +#define lcode_c +#define LUA_CORE + +#include "lprefix.h" + #include <math.h> #include <stdlib.h> -#define lcode_c -#define LUA_CORE - #include "lua.h" #include "lcode.h" @@ -27,7 +29,11 @@ #include "lvm.h" -/* test for x == -0 */ +/* Maximum number of registers in a Lua function */ +#define MAXREGS 250 + + +/* test for x == -0 ('signbit' needs 'math.h') */ #if defined(signbit) #define isminuszero(x) ((x) == 0.0 && signbit(x)) #else @@ -107,7 +113,7 @@ static void fixjump (FuncState *fs, int pc, int dest) { /* -** returns current `pc' and marks it as a jump target (to avoid wrong +** returns current 'pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). */ int luaK_getlabel (FuncState *fs) { @@ -230,7 +236,7 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ + dischargejpc(fs); /* 'pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); @@ -280,7 +286,7 @@ int luaK_codek (FuncState *fs, int reg, int k) { void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) + if (newstack >= MAXREGS) luaX_syntaxerror(fs->ls, "function or expression too complex"); fs->f->maxstacksize = cast_byte(newstack); } @@ -503,7 +509,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { static void exp2reg (FuncState *fs, expdesc *e, int reg) { discharge2reg(fs, e, reg); if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ if (hasjumps(e)) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ @@ -585,7 +591,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { } case VK: { vk: - if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ return RKASK(e->u.info); else break; } @@ -677,7 +683,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { break; } } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_concat(fs, &e->f, pc); /* insert last jump in 'f' list */ luaK_patchtohere(fs, e->t); e->t = NO_JUMP; } @@ -700,7 +706,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { break; } } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_concat(fs, &e->t, pc); /* insert last jump in 't' list */ luaK_patchtohere(fs, e->f); e->f = NO_JUMP; } @@ -762,12 +768,10 @@ static int validop (int op, TValue *v1, TValue *v2) { (cast_void(tonumber(v2, &b)), b))) return 0; switch (op) { - case LUA_OPIDIV: /* division by 0 and conversion errors */ - return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0); case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: /* conversion errors */ return (tointeger(v1, &i) && tointeger(v2, &i)); - case LUA_OPMOD: /* integer module by 0 */ + case LUA_OPIDIV: case LUA_OPMOD: /* integer division by 0 */ return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0); default: return 1; /* everything else is valid */ } @@ -797,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); } @@ -817,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); } } @@ -831,7 +846,7 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, freeexp(fs, e2); freeexp(fs, e1); if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ + int temp; /* exchange args to replace by '<' or '<=' */ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ cond = 1; } @@ -845,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; @@ -865,7 +880,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { break; } case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ break; } case OPR_ADD: case OPR_SUB: @@ -911,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; } @@ -919,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: { |