From 3b19af44b05ce5e7f7db3708d052cca25fe6d7d3 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 29 Aug 2005 17:49:21 -0300 Subject: new method to handle tests without values (negative values) --- lcode.c | 69 +++++++++++++++++++++++++++++++++++--------------------------- lcode.h | 3 ++- lopcodes.c | 6 ++++-- lopcodes.h | 5 +++-- lparser.c | 7 +++---- lvm.c | 8 +++++++- 6 files changed, 58 insertions(+), 40 deletions(-) diff --git a/lcode.c b/lcode.c index 7f30bea4..0683c23f 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $ +** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 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); } } @@ -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); } @@ -597,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); } diff --git a/lcode.h b/lcode.h index a83411e4..5a61b603 100644 --- a/lcode.h +++ b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.43 2005/04/25 19:24:10 roberto Exp roberto $ +** $Id: lcode.h,v 1.44 2005/05/20 15:53:42 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -65,6 +65,7 @@ LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); diff --git a/lopcodes.c b/lopcodes.c index 542fa620..91c334e0 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.33 2005/05/04 20:42:28 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.34 2005/05/20 15:53:42 roberto Exp $ ** See Copyright Notice in lua.h */ @@ -43,6 +43,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { "LT", "LE", "TEST", + "TESTSET", "CALL", "TAILCALL", "RETURN", @@ -87,7 +88,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ diff --git a/lopcodes.h b/lopcodes.h index 8d199ea7..080c4a1c 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.120 2005/05/20 15:53:42 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.121 2005/06/06 13:30:25 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -186,7 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ diff --git a/lparser.c b/lparser.c index 351340be..15a906c1 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.33 2005/08/22 18:54:32 roberto Exp roberto $ +** $Id: lparser.c,v 2.34 2005/08/24 17:41:10 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -375,7 +375,7 @@ static void close_func (LexState *ls) { FuncState *fs = ls->fs; Proto *f = fs->f; removevars(ls, 0); - luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ + luaK_ret(fs, 0, 0); /* final return */ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); @@ -981,7 +981,6 @@ static int cond (LexState *ls) { expdesc v; expr(ls, &v); /* read condition */ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ - else if (v.k == VK) v.k = VTRUE; /* 'trues' too */ luaK_goiftrue(ls->fs, &v); return v.f; } @@ -1279,7 +1278,7 @@ static void retstat (LexState *ls) { } } } - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); + luaK_ret(fs, first, nret); } diff --git a/lvm.c b/lvm.c index 455feda1..42d27761 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.52 2005/08/22 18:54:49 roberto Exp roberto $ +** $Id: lvm.c,v 2.53 2005/08/24 16:15:49 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -592,6 +592,12 @@ void luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_TEST: { + if (l_isfalse(ra) == GETARG_C(i)) pc++; + else + dojump(L, pc, GETARG_sBx(*pc) + 1); + continue; + } + case OP_TESTSET: { TValue *rb = RB(i); if (l_isfalse(rb) == GETARG_C(i)) pc++; else { -- cgit v1.2.3-55-g6feb