diff --git a/lcode.c b/lcode.c index f72bcdb3..26a90430 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.100 2002/05/09 14:14:34 roberto Exp roberto $ +** $Id: lcode.c,v 1.101 2002/05/10 17:02:32 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -39,58 +39,48 @@ void luaK_nil (FuncState *fs, int from, int n) { } -void luaK_moveexp (expdesc *e, int offset) { - if (e->t != NO_JUMP) e->t += offset; - if (e->f != NO_JUMP) e->f += offset; - if (e->k == VRELOCABLE || e->k == VJMP) e->info += offset; -} - - int luaK_jump (FuncState *fs) { - int j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - if (j == fs->lasttarget) { /* possible jumps to this jump? */ - luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ - fs->jlt = NO_JUMP; - } + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ return j; } static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); - return luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + return luaK_jump(fs); } static void luaK_fixjump (FuncState *fs, int pc, int dest) { Instruction *jmp = &fs->f->code[pc]; - if (dest == NO_JUMP) - SETARG_sBx(*jmp, NO_JUMP); /* point to itself to represent end of list */ - else { /* jump is relative to position following jump instruction */ - int offset = dest-(pc+1); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); - } + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); } /* ** returns current `pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). -** discharge list of jumps to last target. */ int luaK_getlabel (FuncState *fs) { - if (fs->pc != fs->lasttarget) { - int lasttarget = fs->lasttarget; - fs->lasttarget = fs->pc; - luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ - fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ - } + fs->lasttarget = fs->pc; return fs->pc; } +void luaK_dischargejpc (FuncState *fs) { + luaK_patchlist(fs, fs->jpc, fs->pc); /* discharge old list `jpc' */ + fs->jpc = NO_JUMP; +} + + static int luaK_getjump (FuncState *fs, int pc) { int offset = GETARG_sBx(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ @@ -155,20 +145,20 @@ static void luaK_patchlistaux (FuncState *fs, int list, void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->lasttarget) /* same target that list `jlt'? */ - luaK_concat(fs, &fs->jlt, list); /* delay fixing */ - else - luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); + lua_assert(target <= fs->pc); + luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); } void luaK_patchtohere (FuncState *fs, int list) { - luaK_patchlist(fs, list, luaK_getlabel(fs)); + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); } void luaK_concat (FuncState *fs, int *l1, int l2) { - if (*l1 == NO_JUMP) + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) *l1 = l2; else { int list = *l1; @@ -508,7 +498,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { break; } case VFALSE: { - pc = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); /* always jump */ + pc = luaK_jump(fs); /* always jump */ break; } case VJMP: { @@ -534,7 +524,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { break; } case VTRUE: { - pc = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); /* always jump */ + pc = luaK_jump(fs); /* always jump */ break; } case VJMP: { @@ -737,6 +727,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { int luaK_code (FuncState *fs, Instruction i, int line) { Proto *f = fs->f; int oldsize = f->sizecode; + luaK_dischargejpc(fs); /* `pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "code size overflow"); diff --git a/lcode.h b/lcode.h index 7d46ca43..ba1d282b 100644 --- a/lcode.h +++ b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.33 2002/05/07 17:36:56 roberto Exp roberto $ +** $Id: lcode.h,v 1.34 2002/05/10 17:02:32 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -55,12 +55,12 @@ void luaK_exp2val (FuncState *fs, expdesc *e); int luaK_exp2RK (FuncState *fs, expdesc *e); void luaK_self (FuncState *fs, expdesc *e, expdesc *key); void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -void luaK_moveexp (expdesc *e, int offset); void luaK_goiftrue (FuncState *fs, expdesc *e); void luaK_goiffalse (FuncState *fs, expdesc *e); void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); int luaK_jump (FuncState *fs); +void luaK_dischargejpc (FuncState *fs); void luaK_patchlist (FuncState *fs, int list, int target); void luaK_patchtohere (FuncState *fs, int list); void luaK_concat (FuncState *fs, int *l1, int l2); diff --git a/lparser.c b/lparser.c index eaf0bc8a..c24b5412 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.179 2002/05/07 17:36:56 roberto Exp roberto $ +** $Id: lparser.c,v 1.180 2002/05/10 17:02:32 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -367,7 +367,7 @@ static void open_func (LexState *ls, FuncState *fs) { ls->fs = fs; fs->pc = 0; fs->lasttarget = 0; - fs->jlt = NO_JUMP; + fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; fs->h = luaH_new(ls->L, 0, 0); @@ -391,7 +391,6 @@ static void close_func (LexState *ls) { Proto *f = fs->f; removevars(ls, 0); luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ - luaK_getlabel(fs); /* close eventual list of pending jumps */ lua_assert(G(L)->roottable == fs->h); G(L)->roottable = fs->h->next; luaH_free(L, fs->h); @@ -977,30 +976,33 @@ static void whilestat (LexState *ls, int line) { int i; int sizeexp; FuncState *fs = ls->fs; - int while_init = luaK_getlabel(fs); + int whileinit, blockinit, expinit; expdesc v; BlockCnt bl; next(ls); + whileinit = luaK_jump(fs); + expinit = luaK_getlabel(fs); expr(ls, &v); if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ lineexp = ls->linenumber; luaK_goiffalse(fs, &v); - sizeexp = fs->pc - while_init; + luaK_dischargejpc(fs); + sizeexp = fs->pc - expinit; if (sizeexp > MAXEXPWHILE) luaX_syntaxerror(ls, "while condition too complex"); - fs->pc = while_init; /* remove `exp' code */ - luaK_getlabel(fs); for (i = 0; i < sizeexp; i++) /* save `exp' code */ - codeexp[i] = fs->f->code[while_init + i]; - luaK_jump(fs); + codeexp[i] = fs->f->code[expinit + i]; + fs->pc = expinit; /* remove `exp' code */ enterblock(fs, &bl, 1); check(ls, TK_DO); + blockinit = luaK_getlabel(fs); block(ls); - luaK_patchtohere(fs, while_init); /* initial jump jumps to here */ - luaK_moveexp(&v, fs->pc - while_init); /* correct pointers */ + luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ + if (v.t != NO_JUMP) v.t += fs->pc - expinit; + if (v.f != NO_JUMP) v.f += fs->pc - expinit; for (i=0; i