summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-29 17:49:21 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-29 17:49:21 -0300
commit3b19af44b05ce5e7f7db3708d052cca25fe6d7d3 (patch)
treef4575f972c8f780e64d935ff211ebd5cd8f9a3cf
parent3390f9a35ac66d01c7bb0114083a4cb384783ff5 (diff)
downloadlua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.tar.gz
lua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.tar.bz2
lua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.zip
new method to handle tests without values (negative values)
-rw-r--r--lcode.c69
-rw-r--r--lcode.h3
-rw-r--r--lopcodes.c6
-rw-r--r--lopcodes.h5
-rw-r--r--lparser.c7
-rw-r--r--lvm.c8
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 @@
1/* 1/*
2** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $ 2** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 roberto Exp $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) {
53} 53}
54 54
55 55
56void luaK_ret (FuncState *fs, int first, int nret) {
57 luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
58}
59
60
56static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { 61static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
57 luaK_codeABC(fs, op, A, B, C); 62 luaK_codeABC(fs, op, A, B, C);
58 return luaK_jump(fs); 63 return luaK_jump(fs);
@@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
101** check whether list has any jump that do not produce a value 106** check whether list has any jump that do not produce a value
102** (or produce an inverted value) 107** (or produce an inverted value)
103*/ 108*/
104static int need_value (FuncState *fs, int list, int cond) { 109static int need_value (FuncState *fs, int list) {
105 for (; list != NO_JUMP; list = getjump(fs, list)) { 110 for (; list != NO_JUMP; list = getjump(fs, list)) {
106 Instruction i = *getjumpcontrol(fs, list); 111 Instruction i = *getjumpcontrol(fs, list);
107 if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; 112 if (GET_OPCODE(i) != OP_TESTSET) return 1;
108 } 113 }
109 return 0; /* not found */ 114 return 0; /* not found */
110} 115}
111 116
112 117
113static void patchtestreg (Instruction *i, int reg) { 118static void patchtestreg (Instruction *i, int reg) {
114 if (reg == NO_REG) reg = GETARG_B(*i); 119 if (reg != NO_REG)
115 SETARG_A(*i, reg); 120 SETARG_A(*i, reg);
121 else /* no register to put value; change TESTSET to TEST */
122 *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
116} 123}
117 124
118 125
119static void patchlistaux (FuncState *fs, int list, 126static void removevalues (FuncState *fs, int list) {
120 int ttarget, int treg, int ftarget, int freg, int dtarget) { 127 for (; list != NO_JUMP; list = getjump(fs, list)) {
128 Instruction *i = getjumpcontrol(fs, list);
129 if (GET_OPCODE(*i) == OP_TESTSET)
130 patchtestreg(i, NO_REG);
131 }
132}
133
134
135static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
136 int dtarget) {
121 while (list != NO_JUMP) { 137 while (list != NO_JUMP) {
122 int next = getjump(fs, list); 138 int next = getjump(fs, list);
123 Instruction *i = getjumpcontrol(fs, list); 139 Instruction *i = getjumpcontrol(fs, list);
124 if (GET_OPCODE(*i) != OP_TEST) { 140 if (GET_OPCODE(*i) == OP_TESTSET) {
125 lua_assert(dtarget != NO_JUMP); 141 patchtestreg(i, reg);
126 fixjump(fs, list, dtarget); /* jump to default target */ 142 fixjump(fs, list, vtarget);
127 }
128 else {
129 if (GETARG_C(*i)) {
130 lua_assert(ttarget != NO_JUMP);
131 patchtestreg(i, treg);
132 fixjump(fs, list, ttarget);
133 }
134 else {
135 lua_assert(ftarget != NO_JUMP);
136 patchtestreg(i, freg);
137 fixjump(fs, list, ftarget);
138 }
139 } 143 }
144 else
145 fixjump(fs, list, dtarget); /* jump to default target */
140 list = next; 146 list = next;
141 } 147 }
142} 148}
143 149
144 150
145static void dischargejpc (FuncState *fs) { 151static void dischargejpc (FuncState *fs) {
146 patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); 152 patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
147 fs->jpc = NO_JUMP; 153 fs->jpc = NO_JUMP;
148} 154}
149 155
@@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
153 luaK_patchtohere(fs, list); 159 luaK_patchtohere(fs, list);
154 else { 160 else {
155 lua_assert(target < fs->pc); 161 lua_assert(target < fs->pc);
156 patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); 162 patchlistaux(fs, list, target, NO_REG, target);
157 } 163 }
158} 164}
159 165
@@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
373 int final; /* position after whole expression */ 379 int final; /* position after whole expression */
374 int p_f = NO_JUMP; /* position of an eventual LOAD false */ 380 int p_f = NO_JUMP; /* position of an eventual LOAD false */
375 int p_t = NO_JUMP; /* position of an eventual LOAD true */ 381 int p_t = NO_JUMP; /* position of an eventual LOAD true */
376 if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { 382 if (need_value(fs, e->t) || need_value(fs, e->f)) {
377 int fj = NO_JUMP; /* first jump (over LOAD ops.) */ 383 int fj = NO_JUMP; /* first jump (over LOAD ops.) */
378 if (e->k != VJMP) 384 if (e->k != VJMP)
379 fj = luaK_jump(fs); 385 fj = luaK_jump(fs);
@@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
382 luaK_patchtohere(fs, fj); 388 luaK_patchtohere(fs, fj);
383 } 389 }
384 final = luaK_getlabel(fs); 390 final = luaK_getlabel(fs);
385 patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); 391 patchlistaux(fs, e->f, final, reg, p_f);
386 patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); 392 patchlistaux(fs, e->t, final, reg, p_t);
387 } 393 }
388 e->f = e->t = NO_JUMP; 394 e->f = e->t = NO_JUMP;
389 e->info = reg; 395 e->info = reg;
@@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
492 498
493static void invertjump (FuncState *fs, expdesc *e) { 499static void invertjump (FuncState *fs, expdesc *e) {
494 Instruction *pc = getjumpcontrol(fs, e->info); 500 Instruction *pc = getjumpcontrol(fs, e->info);
495 lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST); 501 lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
502 GET_OPCODE(*pc) != OP_TEST);
496 SETARG_A(*pc, !(GETARG_A(*pc))); 503 SETARG_A(*pc, !(GETARG_A(*pc)));
497} 504}
498 505
@@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
502 Instruction ie = getcode(fs, e); 509 Instruction ie = getcode(fs, e);
503 if (GET_OPCODE(ie) == OP_NOT) { 510 if (GET_OPCODE(ie) == OP_NOT) {
504 fs->pc--; /* remove previous OP_NOT */ 511 fs->pc--; /* remove previous OP_NOT */
505 return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); 512 return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
506 } 513 }
507 /* else go through */ 514 /* else go through */
508 } 515 }
509 discharge2anyreg(fs, e); 516 discharge2anyreg(fs, e);
510 freeexp(fs, e); 517 freeexp(fs, e);
511 return condjump(fs, OP_TEST, NO_REG, e->info, cond); 518 return condjump(fs, OP_TESTSET, NO_REG, e->info, cond);
512} 519}
513 520
514 521
@@ -597,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) {
597 } 604 }
598 /* interchange true and false lists */ 605 /* interchange true and false lists */
599 { int temp = e->f; e->f = e->t; e->t = temp; } 606 { int temp = e->f; e->f = e->t; e->t = temp; }
607 removevalues(fs, e->f);
608 removevalues(fs, e->t);
600} 609}
601 610
602 611
diff --git a/lcode.h b/lcode.h
index a83411e4..5a61b603 100644
--- a/lcode.h
+++ b/lcode.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.h,v 1.43 2005/04/25 19:24:10 roberto Exp roberto $ 2** $Id: lcode.h,v 1.44 2005/05/20 15:53:42 roberto Exp $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -65,6 +65,7 @@ LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
65LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); 65LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
66LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); 66LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
67LUAI_FUNC int luaK_jump (FuncState *fs); 67LUAI_FUNC int luaK_jump (FuncState *fs);
68LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
68LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); 69LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
69LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); 70LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
70LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); 71LUAI_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 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.33 2005/05/04 20:42:28 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.34 2005/05/20 15:53:42 roberto Exp $
3** See Copyright Notice in lua.h 3** See Copyright Notice in lua.h
4*/ 4*/
5 5
@@ -43,6 +43,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
43 "LT", 43 "LT",
44 "LE", 44 "LE",
45 "TEST", 45 "TEST",
46 "TESTSET",
46 "CALL", 47 "CALL",
47 "TAILCALL", 48 "TAILCALL",
48 "RETURN", 49 "RETURN",
@@ -87,7 +88,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
87 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ 88 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
88 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ 89 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
89 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ 90 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
90 ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ 91 ,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */
92 ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
91 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ 93 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
92 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ 94 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
93 ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ 95 ,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 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.120 2005/05/20 15:53:42 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.121 2005/06/06 13:30:25 roberto Exp $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -186,7 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
186OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ 186OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
187OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ 187OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
188 188
189OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ 189OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
190OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
190 191
191OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ 192OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
192OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ 193OP_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 @@
1/* 1/*
2** $Id: lparser.c,v 2.33 2005/08/22 18:54:32 roberto Exp roberto $ 2** $Id: lparser.c,v 2.34 2005/08/24 17:41:10 roberto Exp $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -375,7 +375,7 @@ static void close_func (LexState *ls) {
375 FuncState *fs = ls->fs; 375 FuncState *fs = ls->fs;
376 Proto *f = fs->f; 376 Proto *f = fs->f;
377 removevars(ls, 0); 377 removevars(ls, 0);
378 luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ 378 luaK_ret(fs, 0, 0); /* final return */
379 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); 379 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
380 f->sizecode = fs->pc; 380 f->sizecode = fs->pc;
381 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); 381 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
@@ -981,7 +981,6 @@ static int cond (LexState *ls) {
981 expdesc v; 981 expdesc v;
982 expr(ls, &v); /* read condition */ 982 expr(ls, &v); /* read condition */
983 if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ 983 if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
984 else if (v.k == VK) v.k = VTRUE; /* 'trues' too */
985 luaK_goiftrue(ls->fs, &v); 984 luaK_goiftrue(ls->fs, &v);
986 return v.f; 985 return v.f;
987} 986}
@@ -1279,7 +1278,7 @@ static void retstat (LexState *ls) {
1279 } 1278 }
1280 } 1279 }
1281 } 1280 }
1282 luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); 1281 luaK_ret(fs, first, nret);
1283} 1282}
1284 1283
1285 1284
diff --git a/lvm.c b/lvm.c
index 455feda1..42d27761 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.52 2005/08/22 18:54:49 roberto Exp roberto $ 2** $Id: lvm.c,v 2.53 2005/08/24 16:15:49 roberto Exp $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -592,6 +592,12 @@ void luaV_execute (lua_State *L, int nexeccalls) {
592 continue; 592 continue;
593 } 593 }
594 case OP_TEST: { 594 case OP_TEST: {
595 if (l_isfalse(ra) == GETARG_C(i)) pc++;
596 else
597 dojump(L, pc, GETARG_sBx(*pc) + 1);
598 continue;
599 }
600 case OP_TESTSET: {
595 TValue *rb = RB(i); 601 TValue *rb = RB(i);
596 if (l_isfalse(rb) == GETARG_C(i)) pc++; 602 if (l_isfalse(rb) == GETARG_C(i)) pc++;
597 else { 603 else {