diff options
Diffstat (limited to 'src/lcode.c')
-rw-r--r-- | src/lcode.c | 85 |
1 files changed, 47 insertions, 38 deletions
diff --git a/src/lcode.c b/src/lcode.c index 1e8d80fb..04838f33 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.12 2005/03/16 16:59:21 roberto Exp $ +** $Id: lcode.c,v 2.16 2005/08/29 20:49:21 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) { } +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs); @@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { ** check whether list has any jump that do not produce a value ** (or produce an inverted value) */ -static int need_value (FuncState *fs, int list, int cond) { +static int need_value (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; + if (GET_OPCODE(i) != OP_TESTSET) return 1; } return 0; /* not found */ } static void patchtestreg (Instruction *i, int reg) { - if (reg == NO_REG) reg = GETARG_B(*i); - SETARG_A(*i, reg); + if (reg != NO_REG) + SETARG_A(*i, reg); + else /* no register to put value; change TESTSET to TEST */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); } -static void patchlistaux (FuncState *fs, int list, - int ttarget, int treg, int ftarget, int freg, int dtarget) { +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction *i = getjumpcontrol(fs, list); + if (GET_OPCODE(*i) == OP_TESTSET) + patchtestreg(i, NO_REG); + } +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { while (list != NO_JUMP) { int next = getjump(fs, list); Instruction *i = getjumpcontrol(fs, list); - if (GET_OPCODE(*i) != OP_TEST) { - lua_assert(dtarget != NO_JUMP); - fixjump(fs, list, dtarget); /* jump to default target */ - } - else { - if (GETARG_C(*i)) { - lua_assert(ttarget != NO_JUMP); - patchtestreg(i, treg); - fixjump(fs, list, ttarget); - } - else { - lua_assert(ftarget != NO_JUMP); - patchtestreg(i, freg); - fixjump(fs, list, ftarget); - } + if (GET_OPCODE(*i) == OP_TESTSET) { + patchtestreg(i, reg); + fixjump(fs, list, vtarget); } + else + fixjump(fs, list, dtarget); /* jump to default target */ list = next; } } static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP; } @@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) { luaK_patchtohere(fs, list); else { lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); + patchlistaux(fs, list, target, NO_REG, target); } } @@ -223,7 +229,7 @@ static int addk (FuncState *fs, TValue *k, TValue *v) { MAXARG_Bx, "constant table overflow"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[fs->nk], v); - luaC_barriert(L, f, v); + luaC_barrier(L, f, v); return fs->nk++; } } @@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { + if (need_value(fs, e->t) || need_value(fs, e->f)) { int fj = NO_JUMP; /* first jump (over LOAD ops.) */ if (e->k != VJMP) fj = luaK_jump(fs); @@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { luaK_patchtohere(fs, fj); } final = luaK_getlabel(fs); - patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); } e->f = e->t = NO_JUMP; e->info = reg; @@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { static void invertjump (FuncState *fs, expdesc *e) { Instruction *pc = getjumpcontrol(fs, e->info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); SETARG_A(*pc, !(GETARG_A(*pc))); } @@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { Instruction ie = getcode(fs, e); if (GET_OPCODE(ie) == OP_NOT) { fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); } /* else go through */ } discharge2anyreg(fs, e); freeexp(fs, e); - return condjump(fs, OP_TEST, NO_REG, e->info, cond); + return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); } @@ -535,6 +542,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { } } luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; } @@ -560,6 +569,8 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { } } luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; } @@ -593,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) { } /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); } @@ -607,7 +620,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { case OPR_MINUS: { luaK_exp2val(fs, e); if (e->k == VK && ttisnumber(&fs->f->k[e->info])) - e->info = luaK_numberK(fs, luai_numunm(nvalue(&fs->f->k[e->info]))); + e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); else { luaK_exp2anyreg(fs, e); freeexp(fs, e); @@ -620,10 +633,10 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { codenot(fs, e); break; } - case OPR_SIZE: { + case OPR_LEN: { luaK_exp2anyreg(fs, e); freeexp(fs, e); - e->info = luaK_codeABC(fs, OP_SIZ, 0, e->info, 0); + e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0); e->k = VRELOCABLE; break; } @@ -636,14 +649,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { switch (op) { case OPR_AND: { luaK_goiftrue(fs, v); - luaK_patchtohere(fs, v->t); - v->t = NO_JUMP; break; } case OPR_OR: { luaK_goiffalse(fs, v); - luaK_patchtohere(fs, v->f); - v->f = NO_JUMP; break; } case OPR_CONCAT: { |