diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
commit | 762d059a13d83eb367238a6115bbb4f5f13fcb49 (patch) | |
tree | f35fdf0675b791865d0d4800522b172903b34803 /lcode.c | |
parent | 572a69b6afbd368beab8844bc876b0f9690b5253 (diff) | |
download | lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.gz lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.bz2 lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.zip |
new implementation for the Virtual Machine
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 1045 |
1 files changed, 566 insertions, 479 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.67 2001/04/06 18:25:00 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 roberto Exp roberto $ |
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 | */ |
@@ -11,6 +11,7 @@ | |||
11 | #include "lua.h" | 11 | #include "lua.h" |
12 | 12 | ||
13 | #include "lcode.h" | 13 | #include "lcode.h" |
14 | #include "ldebug.h" | ||
14 | #include "ldo.h" | 15 | #include "ldo.h" |
15 | #include "llex.h" | 16 | #include "llex.h" |
16 | #include "lmem.h" | 17 | #include "lmem.h" |
@@ -19,6 +20,12 @@ | |||
19 | #include "lparser.h" | 20 | #include "lparser.h" |
20 | 21 | ||
21 | 22 | ||
23 | #define hasjumps(e) ((e)->t != (e)->f) | ||
24 | |||
25 | #define getcode(fs,e) ((fs)->f->code[(e)->u.i.info]) | ||
26 | |||
27 | |||
28 | |||
22 | void luaK_error (LexState *ls, const l_char *msg) { | 29 | void luaK_error (LexState *ls, const l_char *msg) { |
23 | luaX_error(ls, msg, ls->t.token); | 30 | luaX_error(ls, msg, ls->t.token); |
24 | } | 31 | } |
@@ -33,12 +40,27 @@ static Instruction previous_instruction (FuncState *fs) { | |||
33 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
34 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ | 41 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ |
35 | else | 42 | else |
36 | return CREATE_0(-1); /* no optimizations after an invalid instruction */ | 43 | return (Instruction)(-1);/* no optimizations after an invalid instruction */ |
44 | } | ||
45 | |||
46 | |||
47 | void luaK_nil (FuncState *fs, int from, int n) { | ||
48 | Instruction previous = previous_instruction(fs); | ||
49 | if (GET_OPCODE(previous) == OP_LOADNIL) { | ||
50 | int pfrom = GETARG_A(previous); | ||
51 | int pto = GETARG_B(previous); | ||
52 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | ||
53 | if (from+n-1 > pto) | ||
54 | SETARG_B(fs->f->code[fs->pc-1], from+n-1); | ||
55 | return; | ||
56 | } | ||
57 | } | ||
58 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | ||
37 | } | 59 | } |
38 | 60 | ||
39 | 61 | ||
40 | int luaK_jump (FuncState *fs) { | 62 | int luaK_jump (FuncState *fs) { |
41 | int j = luaK_code1(fs, OP_JMP, NO_JUMP); | 63 | int j = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); |
42 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 64 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ |
43 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 65 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ |
44 | fs->jlt = NO_JUMP; | 66 | fs->jlt = NO_JUMP; |
@@ -47,36 +69,33 @@ int luaK_jump (FuncState *fs) { | |||
47 | } | 69 | } |
48 | 70 | ||
49 | 71 | ||
72 | static int luaK_condjump (FuncState *fs, OpCode op, int B, int C) { | ||
73 | luaK_codeABC(fs, op, NO_REG, B, C); | ||
74 | return luaK_codeAsBc(fs, OP_CJMP, 0, NO_JUMP); | ||
75 | } | ||
76 | |||
77 | |||
50 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 78 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
51 | Instruction *jmp = &fs->f->code[pc]; | 79 | Instruction *jmp = &fs->f->code[pc]; |
52 | if (dest == NO_JUMP) | 80 | if (dest == NO_JUMP) |
53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 81 | SETARG_sBc(*jmp, NO_JUMP); /* point to itself to represent end of list */ |
54 | else { /* jump is relative to position following jump instruction */ | 82 | else { /* jump is relative to position following jump instruction */ |
55 | int offset = dest-(pc+1); | 83 | int offset = dest-(pc+1); |
56 | if (abs(offset) > MAXARG_S) | 84 | if (abs(offset) > MAXARG_sBc) |
57 | luaK_error(fs->ls, l_s("control structure too long")); | 85 | luaK_error(fs->ls, l_s("control structure too long")); |
58 | SETARG_S(*jmp, offset); | 86 | SETARG_sBc(*jmp, offset); |
59 | } | 87 | } |
60 | } | 88 | } |
61 | 89 | ||
62 | 90 | ||
63 | /* | 91 | /* |
64 | ** prep-for instructions (OP_FORPREP & OP_LFORPREP) have a negated jump, | 92 | ** prep-for instructions (OP_FORPREP & OP_TFORPREP) have a negated jump, |
65 | ** as they simulate the real jump... | 93 | ** as they simulate the real jump... |
66 | */ | 94 | */ |
67 | void luaK_fixfor (FuncState *fs, int pc, int dest) { | 95 | void luaK_fixfor (FuncState *fs, int pc, int dest) { |
68 | Instruction *jmp = &fs->f->code[pc]; | 96 | Instruction *jmp = &fs->f->code[pc]; |
69 | int offset = dest-(pc+1); | 97 | int offset = dest-(pc+1); |
70 | SETARG_S(*jmp, -offset); | 98 | SETARG_sBc(*jmp, -offset); |
71 | } | ||
72 | |||
73 | |||
74 | static int luaK_getjump (FuncState *fs, int pc) { | ||
75 | int offset = GETARG_S(fs->f->code[pc]); | ||
76 | if (offset == NO_JUMP) /* point to itself represents end of list */ | ||
77 | return NO_JUMP; /* end of list */ | ||
78 | else | ||
79 | return (pc+1)+offset; /* turn offset into absolute position */ | ||
80 | } | 99 | } |
81 | 100 | ||
82 | 101 | ||
@@ -96,609 +115,677 @@ int luaK_getlabel (FuncState *fs) { | |||
96 | } | 115 | } |
97 | 116 | ||
98 | 117 | ||
99 | void luaK_deltastack (FuncState *fs, int delta) { | 118 | static int luaK_getjump (FuncState *fs, int pc) { |
100 | fs->stacklevel += delta; | 119 | int offset = GETARG_sBc(fs->f->code[pc]); |
101 | if (fs->stacklevel > fs->f->maxstacksize) { | 120 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
102 | if (fs->stacklevel > MAXSTACK) | 121 | return NO_JUMP; /* end of list */ |
103 | luaK_error(fs->ls, l_s("function or expression too complex")); | 122 | else |
104 | fs->f->maxstacksize = (short)fs->stacklevel; | 123 | return (pc+1)+offset; /* turn offset into absolute position */ |
105 | } | ||
106 | } | 124 | } |
107 | 125 | ||
108 | 126 | ||
109 | void luaK_kstr (LexState *ls, int c) { | 127 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { |
110 | luaK_code1(ls->fs, OP_PUSHSTRING, c); | 128 | Instruction *pi = &fs->f->code[pc]; |
129 | OpCode op = GET_OPCODE(*pi); | ||
130 | if (op == OP_CJMP) | ||
131 | return pi-1; | ||
132 | else { | ||
133 | lua_assert(op == OP_JMP || op == OP_FORLOOP || op == OP_TFORLOOP); | ||
134 | return pi; | ||
135 | } | ||
111 | } | 136 | } |
112 | 137 | ||
113 | 138 | ||
114 | static int number_constant (FuncState *fs, lua_Number r) { | 139 | static int need_value (FuncState *fs, int list, OpCode op) { |
115 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | 140 | /* check whether list has any jump different from `op' */ |
116 | Proto *f = fs->f; | 141 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) |
117 | int c = fs->nknum; | 142 | if (GET_OPCODE(*getjumpcontrol(fs, list)) != op) return 1; |
118 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; | 143 | return 0; /* not found */ |
119 | while (--c >= lim) | ||
120 | if (f->knum[c] == r) return c; | ||
121 | /* not found; create a new entry */ | ||
122 | luaM_growvector(fs->L, f->knum, fs->nknum, f->sizeknum, lua_Number, | ||
123 | MAXARG_U, l_s("constant table overflow")); | ||
124 | c = fs->nknum++; | ||
125 | f->knum[c] = r; | ||
126 | return c; | ||
127 | } | 144 | } |
128 | 145 | ||
129 | 146 | ||
130 | void luaK_number (FuncState *fs, lua_Number f) { | 147 | static void luaK_patchlistaux (FuncState *fs, int list, |
131 | if (f <= (lua_Number)MAXARG_S && (lua_Number)(int)f == f) | 148 | int ttarget, int treg, int ftarget, int freg, int dtarget) { |
132 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | 149 | while (list != NO_JUMP) { |
133 | else | 150 | int next = luaK_getjump(fs, list); |
134 | luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); | 151 | Instruction *i = getjumpcontrol(fs, list); |
152 | switch (GET_OPCODE(*i)) { | ||
153 | case OP_TESTT: { | ||
154 | SETARG_A(*i, treg); | ||
155 | luaK_fixjump(fs, list, ttarget); | ||
156 | break; | ||
157 | } | ||
158 | case OP_TESTF: { | ||
159 | SETARG_A(*i, freg); | ||
160 | luaK_fixjump(fs, list, ftarget); | ||
161 | break; | ||
162 | } | ||
163 | default: { | ||
164 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | list = next; | ||
169 | } | ||
135 | } | 170 | } |
136 | 171 | ||
137 | 172 | ||
138 | void luaK_adjuststack (FuncState *fs, int n) { | 173 | void luaK_patchlist (FuncState *fs, int list, int target) { |
139 | if (n > 0) | 174 | if (target == fs->lasttarget) /* same target that list `jlt'? */ |
140 | luaK_code1(fs, OP_POP, n); | 175 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ |
141 | else | 176 | else |
142 | luaK_code1(fs, OP_PUSHNIL, -n); | 177 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); |
143 | } | 178 | } |
144 | 179 | ||
145 | 180 | ||
146 | int luaK_lastisopen (FuncState *fs) { | 181 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
147 | /* check whether last instruction is an open function call */ | 182 | if (*l1 == NO_JUMP) |
148 | Instruction i = previous_instruction(fs); | 183 | *l1 = l2; |
149 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) | 184 | else { |
150 | return 1; | 185 | int list = *l1; |
151 | else return 0; | 186 | int next; |
187 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | ||
188 | list = next; | ||
189 | luaK_fixjump(fs, list, l2); | ||
190 | } | ||
152 | } | 191 | } |
153 | 192 | ||
154 | 193 | ||
155 | void luaK_setcallreturns (FuncState *fs, int nresults) { | 194 | void luaK_reserveregs (FuncState *fs, int n) { |
156 | if (luaK_lastisopen(fs)) { /* expression is an open function call? */ | 195 | fs->freereg += n; |
157 | SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ | 196 | if (fs->freereg > fs->f->maxstacksize) { |
158 | luaK_deltastack(fs, nresults); /* push results */ | 197 | if (fs->freereg >= MAXSTACK) |
198 | luaK_error(fs->ls, l_s("function or expression too complex")); | ||
199 | fs->f->maxstacksize = (short)fs->freereg; | ||
159 | } | 200 | } |
160 | } | 201 | } |
161 | 202 | ||
162 | 203 | ||
163 | static int discharge (FuncState *fs, expdesc *var) { | 204 | static void freereg (FuncState *fs, int reg) { |
164 | switch (var->k) { | 205 | if (reg >= fs->nactloc && reg < MAXSTACK) { |
165 | case VLOCAL: | 206 | fs->freereg--; |
166 | luaK_code1(fs, OP_GETLOCAL, var->u.index); | 207 | lua_assert(reg == fs->freereg); |
167 | break; | ||
168 | case VGLOBAL: | ||
169 | luaK_code1(fs, OP_GETGLOBAL, var->u.index); | ||
170 | break; | ||
171 | case VINDEXED: | ||
172 | luaK_code0(fs, OP_GETTABLE); | ||
173 | break; | ||
174 | case VEXP: | ||
175 | return 0; /* nothing to do */ | ||
176 | } | 208 | } |
177 | var->k = VEXP; | ||
178 | var->u.l.t = var->u.l.f = NO_JUMP; | ||
179 | return 1; | ||
180 | } | 209 | } |
181 | 210 | ||
182 | 211 | ||
183 | static void discharge1 (FuncState *fs, expdesc *var) { | 212 | static void freeexp (FuncState *fs, expdesc *e) { |
184 | discharge(fs, var); | 213 | if (e->k == VNONRELOC) |
185 | /* if it has jumps then it is already discharged */ | 214 | freereg(fs, e->u.i.info); |
186 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | ||
187 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
188 | } | 215 | } |
189 | 216 | ||
190 | 217 | ||
191 | void luaK_storevar (LexState *ls, const expdesc *var) { | 218 | static int addk (FuncState *fs, TObject *k) { |
192 | FuncState *fs = ls->fs; | 219 | Proto *f = fs->f; |
193 | switch (var->k) { | 220 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
194 | case VLOCAL: | 221 | MAXARG_Bc, l_s("constant table overflow")); |
195 | luaK_code1(fs, OP_SETLOCAL, var->u.index); | 222 | setobj(&f->k[fs->nk], k); |
196 | break; | 223 | return fs->nk++; |
197 | case VGLOBAL: | 224 | } |
198 | luaK_code1(fs, OP_SETGLOBAL, var->u.index); | 225 | |
199 | break; | 226 | |
200 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | 227 | int luaK_stringk (FuncState *fs, TString *s) { |
201 | luaK_code2(fs, OP_SETTABLE, 3, 3); | 228 | Proto *f = fs->f; |
202 | break; | 229 | int c = s->u.s.constindex; |
203 | default: | 230 | if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) { |
204 | lua_assert(0); /* invalid var kind to store */ | 231 | TObject o; |
232 | setsvalue(&o, s); | ||
233 | c = addk(fs, &o); | ||
234 | s->u.s.constindex = c; /* hint for next time */ | ||
205 | } | 235 | } |
236 | return c; | ||
206 | } | 237 | } |
207 | 238 | ||
208 | 239 | ||
209 | static OpCode invertjump (OpCode op) { | 240 | static int number_constant (FuncState *fs, lua_Number r) { |
210 | switch (op) { | 241 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ |
211 | case OP_JMPNE: return OP_JMPEQ; | 242 | TObject o; |
212 | case OP_JMPEQ: return OP_JMPNE; | 243 | Proto *f = fs->f; |
213 | case OP_JMPLT: return OP_JMPGE; | 244 | int c = fs->nk; |
214 | case OP_JMPLE: return OP_JMPGT; | 245 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; |
215 | case OP_JMPGT: return OP_JMPLE; | 246 | while (--c >= lim) { |
216 | case OP_JMPGE: return OP_JMPLT; | 247 | if (ttype(&f->k[c]) == LUA_TNUMBER && nvalue(&f->k[c]) == r) |
217 | case OP_JMPT: case OP_JMPONT: return OP_JMPF; | 248 | return c; |
218 | case OP_JMPF: case OP_JMPONF: return OP_JMPT; | ||
219 | default: | ||
220 | lua_assert(0); /* invalid jump instruction */ | ||
221 | return OP_JMP; /* to avoid warnings */ | ||
222 | } | 249 | } |
250 | /* not found; create a new entry */ | ||
251 | setnvalue(&o, r); | ||
252 | return addk(fs, &o); | ||
223 | } | 253 | } |
224 | 254 | ||
225 | 255 | ||
226 | static void luaK_patchlistaux (FuncState *fs, int list, int target, | 256 | void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { |
227 | OpCode special, int special_target) { | 257 | if (e->k == VCALL) { /* expression is an open function call? */ |
228 | Instruction *code = fs->f->code; | 258 | SETARG_C(getcode(fs, e), nresults); /* set number of results */ |
229 | while (list != NO_JUMP) { | 259 | if (nresults == 1) { /* `regular' expression? */ |
230 | int next = luaK_getjump(fs, list); | 260 | e->k = VNONRELOC; |
231 | Instruction *i = &code[list]; | 261 | e->u.i.info = GETARG_A(getcode(fs, e)); |
232 | OpCode op = GET_OPCODE(*i); | ||
233 | if (op == special) /* this `op' already has a value */ | ||
234 | luaK_fixjump(fs, list, special_target); | ||
235 | else { | ||
236 | luaK_fixjump(fs, list, target); /* do the patch */ | ||
237 | if (op == OP_JMPONT) /* remove eventual values */ | ||
238 | SET_OPCODE(*i, OP_JMPT); | ||
239 | else if (op == OP_JMPONF) | ||
240 | SET_OPCODE(*i, OP_JMPF); | ||
241 | } | 262 | } |
242 | list = next; | ||
243 | } | 263 | } |
244 | } | 264 | } |
245 | 265 | ||
246 | 266 | ||
247 | void luaK_patchlist (FuncState *fs, int list, int target) { | 267 | static void dischargevars (FuncState *fs, expdesc *e) { |
248 | if (target == fs->lasttarget) /* same target that list `jlt'? */ | 268 | switch (e->k) { |
249 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | 269 | case VLOCAL: { |
250 | else | 270 | e->k = VNONRELOC; |
251 | luaK_patchlistaux(fs, list, target, OP_ADD, 0); | 271 | break; |
272 | } | ||
273 | case VGLOBAL: { | ||
274 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); | ||
275 | e->k = VRELOCABLE; | ||
276 | break; | ||
277 | } | ||
278 | case VINDEXED: { | ||
279 | freereg(fs, e->u.i.aux); | ||
280 | freereg(fs, e->u.i.info); | ||
281 | e->u.i.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.i.info, e->u.i.aux); | ||
282 | e->k = VRELOCABLE; | ||
283 | break; | ||
284 | } | ||
285 | case VCALL: { | ||
286 | luaK_setcallreturns(fs, e, 1); | ||
287 | break; | ||
288 | } | ||
289 | default: break; /* there is one value available (somewhere) */ | ||
290 | } | ||
252 | } | 291 | } |
253 | 292 | ||
254 | 293 | ||
255 | static int need_value (FuncState *fs, int list, OpCode hasvalue) { | 294 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { |
256 | /* check whether list has a jump without a value */ | 295 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
257 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) | 296 | return luaK_codeAsBc(fs, op, A, sBc); |
258 | if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; | ||
259 | return 0; /* not found */ | ||
260 | } | 297 | } |
261 | 298 | ||
262 | 299 | ||
263 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 300 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { |
264 | if (*l1 == NO_JUMP) | 301 | if (hasjumps(e)) { |
265 | *l1 = l2; | 302 | int final; /* position after whole expression */ |
266 | else { | 303 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ |
267 | int list = *l1; | 304 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ |
268 | int next; | 305 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { |
269 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | 306 | /* expression needs values */ |
270 | list = next; | 307 | if (e->k != VJMP) |
271 | luaK_fixjump(fs, list, l2); | 308 | code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
309 | p_nil = code_label(fs, OP_NILJMP, reg, 0); | ||
310 | p_1 = code_label(fs, OP_LOADINT, reg, 1); | ||
311 | } | ||
312 | final = luaK_getlabel(fs); | ||
313 | luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); | ||
314 | luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); | ||
272 | } | 315 | } |
316 | e->f = e->t = NO_JUMP; | ||
273 | } | 317 | } |
274 | 318 | ||
275 | 319 | ||
276 | static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | 320 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
277 | int prevpos; /* position of last instruction */ | 321 | dischargevars(fs, e); |
278 | Instruction *previous; | 322 | switch (e->k) { |
279 | int *golist, *exitlist; | 323 | case VNIL: { |
280 | if (!invert) { | 324 | luaK_nil(fs, reg, 1); |
281 | golist = &v->u.l.f; /* go if false */ | 325 | break; |
282 | exitlist = &v->u.l.t; /* exit if true */ | 326 | } |
283 | } | 327 | case VNUMBER: { |
284 | else { | 328 | lua_Number f = e->u.n; |
285 | golist = &v->u.l.t; /* go if true */ | 329 | int i = (int)f; |
286 | exitlist = &v->u.l.f; /* exit if false */ | 330 | if ((lua_Number)i == f && -MAXARG_sBc <= i && i <= MAXARG_sBc) |
331 | luaK_codeAsBc(fs, OP_LOADINT, reg, i); /* f has a small int value */ | ||
332 | else | ||
333 | luaK_codeABc(fs, OP_LOADK, reg, number_constant(fs, f)); | ||
334 | break; | ||
335 | } | ||
336 | case VK: { | ||
337 | luaK_codeABc(fs, OP_LOADK, reg, e->u.i.info); | ||
338 | break; | ||
339 | } | ||
340 | case VRELOCABLE: { | ||
341 | Instruction *pc = &getcode(fs, e); | ||
342 | SETARG_A(*pc, reg); | ||
343 | break; | ||
344 | } | ||
345 | default: return; | ||
287 | } | 346 | } |
288 | discharge1(fs, v); | 347 | e->u.i.info = reg; |
289 | prevpos = fs->pc-1; | 348 | e->k = VNONRELOC; |
290 | previous = &fs->f->code[prevpos]; | 349 | } |
291 | lua_assert(*previous==previous_instruction(fs)); /* no jump allowed here */ | 350 | |
292 | if (!ISJUMP(GET_OPCODE(*previous))) | 351 | |
293 | prevpos = luaK_code1(fs, jump, NO_JUMP); | 352 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
294 | else { /* last instruction is already a jump */ | 353 | if (e->k != VNONRELOC) { |
295 | if (invert) | 354 | luaK_reserveregs(fs, 1); |
296 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 355 | discharge2reg(fs, e, fs->freereg-1); |
297 | } | 356 | } |
298 | luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ | ||
299 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | ||
300 | *golist = NO_JUMP; | ||
301 | } | 357 | } |
302 | 358 | ||
303 | 359 | ||
304 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { | 360 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { |
305 | luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); | 361 | discharge2reg(fs, e, reg); |
362 | switch (e->k) { | ||
363 | case VVOID: { | ||
364 | return; /* nothing to do... */ | ||
365 | } | ||
366 | case VNONRELOC: { | ||
367 | if (reg != e->u.i.info) | ||
368 | luaK_codeABC(fs, OP_MOVE, reg, e->u.i.info, 0); | ||
369 | break; | ||
370 | } | ||
371 | case VJMP: { | ||
372 | luaK_concat(fs, &e->t, e->u.i.info); /* put this jump in `t' list */ | ||
373 | break; | ||
374 | } | ||
375 | default: { | ||
376 | lua_assert(0); /* cannot happen */ | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | dischargejumps(fs, e, reg); | ||
381 | e->u.i.info = reg; | ||
382 | e->k = VNONRELOC; | ||
306 | } | 383 | } |
307 | 384 | ||
308 | 385 | ||
309 | static void luaK_goiffalse (FuncState *fs, expdesc *v) { | 386 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
310 | luaK_testgo(fs, v, 0, OP_JMPONT); | 387 | int reg; |
388 | dischargevars(fs, e); | ||
389 | freeexp(fs, e); | ||
390 | reg = fs->freereg; | ||
391 | luaK_reserveregs(fs, 1); | ||
392 | luaK_exp2reg(fs, e, reg); | ||
311 | } | 393 | } |
312 | 394 | ||
313 | 395 | ||
314 | static int code_label (FuncState *fs, OpCode op, int arg) { | 396 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
315 | luaK_getlabel(fs); /* those instructions may be jump targets */ | 397 | dischargevars(fs, e); |
316 | return luaK_code1(fs, op, arg); | 398 | if (e->k == VNONRELOC) { |
317 | } | 399 | if (!hasjumps(e)) return e->u.i.info; /* exp is already in a register */ |
318 | 400 | if (e->u.i.info >= fs->nactloc) { /* reg. is not a local? */ | |
319 | 401 | dischargejumps(fs, e, e->u.i.info); /* put value on it */ | |
320 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | 402 | return e->u.i.info; |
321 | FuncState *fs = ls->fs; | ||
322 | if (!discharge(fs, v)) { /* `v' is an expression? */ | ||
323 | OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); | ||
324 | if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { | ||
325 | /* expression has no jumps */ | ||
326 | if (onlyone) | ||
327 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
328 | } | ||
329 | else { /* expression has jumps */ | ||
330 | int final; /* position after whole expression */ | ||
331 | int j = NO_JUMP; /* eventual jump over values */ | ||
332 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | ||
333 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | ||
334 | if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) | ||
335 | || need_value(fs, v->u.l.t, OP_JMPONT)) { | ||
336 | /* expression needs values */ | ||
337 | if (ISJUMP(previous)) | ||
338 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ | ||
339 | else { | ||
340 | j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ | ||
341 | /* correct stack for compiler and symbolic execution */ | ||
342 | luaK_adjuststack(fs, 1); | ||
343 | } | ||
344 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
345 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
346 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
347 | } | ||
348 | final = luaK_getlabel(fs); | ||
349 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
350 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
351 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
352 | } | 403 | } |
353 | } | 404 | } |
405 | luaK_exp2nextreg(fs, e); /* default */ | ||
406 | return e->u.i.info; | ||
354 | } | 407 | } |
355 | 408 | ||
356 | 409 | ||
357 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { | 410 | void luaK_exp2val (FuncState *fs, expdesc *e) { |
358 | FuncState *fs = ls->fs; | 411 | if (hasjumps(e)) |
359 | if (op == OPR_MINUS) { | 412 | luaK_exp2anyreg(fs, e); |
360 | luaK_tostack(ls, v, 1); | 413 | else |
361 | luaK_code0(fs, OP_MINUS); | 414 | dischargevars(fs, e); |
362 | } | ||
363 | else { /* op == NOT */ | ||
364 | Instruction *previous; | ||
365 | discharge1(fs, v); | ||
366 | previous = &fs->f->code[fs->pc-1]; | ||
367 | if (ISJUMP(GET_OPCODE(*previous))) | ||
368 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
369 | else | ||
370 | luaK_code0(fs, OP_NOT); | ||
371 | /* interchange true and false lists */ | ||
372 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | ||
373 | } | ||
374 | } | 415 | } |
375 | 416 | ||
376 | 417 | ||
377 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { | 418 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
378 | FuncState *fs = ls->fs; | 419 | luaK_exp2val(fs, e); |
379 | switch (op) { | 420 | if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { |
380 | case OPR_AND: | 421 | e->u.i.info = number_constant(fs, e->u.n); |
381 | luaK_goiftrue(fs, v, 1); | 422 | e->k = VK; |
382 | break; | ||
383 | case OPR_OR: | ||
384 | luaK_goiffalse(fs, v); | ||
385 | break; | ||
386 | default: | ||
387 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | ||
388 | } | 423 | } |
424 | else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) | ||
425 | luaK_exp2anyreg(fs, e); /* not a constant in the right range */ | ||
426 | return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; | ||
389 | } | 427 | } |
390 | 428 | ||
391 | 429 | ||
392 | 430 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |
393 | static const struct { | 431 | switch (var->k) { |
394 | OpCode opcode; /* opcode for each binary operator */ | 432 | case VLOCAL: { |
395 | int arg; /* default argument for the opcode */ | 433 | freeexp(fs, exp); |
396 | } codes[] = { /* ORDER OPR */ | 434 | luaK_exp2reg(fs, exp, var->u.i.info); |
397 | {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, | ||
398 | {OP_POW, 0}, {OP_CONCAT, 2}, | ||
399 | {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, | ||
400 | {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, | ||
401 | {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} | ||
402 | }; | ||
403 | |||
404 | |||
405 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { | ||
406 | FuncState *fs = ls->fs; | ||
407 | switch (op) { | ||
408 | case OPR_AND: { | ||
409 | lua_assert(v1->u.l.t == NO_JUMP); /* list must be closed */ | ||
410 | discharge1(fs, v2); | ||
411 | v1->u.l.t = v2->u.l.t; | ||
412 | luaK_concat(fs, &v1->u.l.f, v2->u.l.f); | ||
413 | break; | 435 | break; |
414 | } | 436 | } |
415 | case OPR_OR: { | 437 | case VGLOBAL: { |
416 | lua_assert(v1->u.l.f == NO_JUMP); /* list must be closed */ | 438 | int e = luaK_exp2anyreg(fs, exp); |
417 | discharge1(fs, v2); | 439 | freereg(fs, e); |
418 | v1->u.l.f = v2->u.l.f; | 440 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->u.i.info); |
419 | luaK_concat(fs, &v1->u.l.t, v2->u.l.t); | 441 | break; |
442 | } | ||
443 | case VINDEXED: { | ||
444 | int e = luaK_exp2anyreg(fs, exp); | ||
445 | freereg(fs, e); | ||
446 | luaK_codeABC(fs, OP_SETTABLE, e, var->u.i.info, var->u.i.aux); | ||
420 | break; | 447 | break; |
421 | } | 448 | } |
422 | default: { | 449 | default: { |
423 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | 450 | lua_assert(0); /* invalid var kind to store */ |
424 | luaK_code1(fs, codes[op].opcode, codes[op].arg); | 451 | break; |
425 | } | 452 | } |
426 | } | 453 | } |
427 | } | 454 | } |
428 | 455 | ||
429 | 456 | ||
430 | static void codelineinfo (FuncState *fs) { | 457 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
431 | Proto *f = fs->f; | 458 | luaK_exp2anyreg(fs, e); |
432 | LexState *ls = fs->ls; | 459 | freeexp(fs, e); |
433 | if (ls->lastline > fs->lastline) { | 460 | luaK_reserveregs(fs, 2); |
434 | if (ls->lastline > fs->lastline+1) { | 461 | luaK_codeABC(fs, OP_SELF, fs->freereg-2, e->u.i.info, luaK_exp2RK(fs, key)); |
435 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 462 | e->u.i.info = fs->freereg-2; |
436 | MAX_INT, l_s("line info overflow")); | 463 | e->k = VNONRELOC; |
437 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | 464 | } |
438 | } | 465 | |
439 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 466 | |
440 | MAX_INT, l_s("line info overflow")); | 467 | static OpCode invertoperator (OpCode op) { |
441 | f->lineinfo[fs->nlineinfo++] = fs->pc; | 468 | switch (op) { |
442 | fs->lastline = ls->lastline; | 469 | case OP_TESTNE: return OP_TESTEQ; |
470 | case OP_TESTEQ: return OP_TESTNE; | ||
471 | case OP_TESTLT: return OP_TESTGE; | ||
472 | case OP_TESTLE: return OP_TESTGT; | ||
473 | case OP_TESTGT: return OP_TESTLE; | ||
474 | case OP_TESTGE: return OP_TESTLT; | ||
475 | case OP_TESTT: return OP_TESTF; | ||
476 | case OP_TESTF: return OP_TESTT; | ||
477 | default: lua_assert(0); return op; /* invalid jump instruction */ | ||
443 | } | 478 | } |
444 | } | 479 | } |
445 | 480 | ||
446 | 481 | ||
447 | int luaK_code0 (FuncState *fs, OpCode o) { | 482 | static void invertjump (FuncState *fs, expdesc *e) { |
448 | return luaK_code2(fs, o, 0, 0); | 483 | Instruction *pc = getjumpcontrol(fs, e->u.i.info); |
484 | *pc = SET_OPCODE(*pc, invertoperator(GET_OPCODE(*pc))); | ||
449 | } | 485 | } |
450 | 486 | ||
451 | 487 | ||
452 | int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | 488 | static int jumponcond (FuncState *fs, expdesc *e, OpCode op) { |
453 | return luaK_code2(fs, o, arg1, 0); | 489 | if (e->k == VRELOCABLE) { |
490 | Instruction ie = getcode(fs, e); | ||
491 | if (GET_OPCODE(ie) == OP_NOT) { | ||
492 | op = invertoperator(op); | ||
493 | fs->pc--; /* remove previous OP_NOT */ | ||
494 | return luaK_condjump(fs, op, GETARG_B(ie), 0); | ||
495 | } | ||
496 | /* else go through */ | ||
497 | } | ||
498 | discharge2anyreg(fs, e); | ||
499 | freeexp(fs, e); | ||
500 | return luaK_condjump(fs, op, e->u.i.info, 0); | ||
454 | } | 501 | } |
455 | 502 | ||
456 | 503 | ||
457 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | 504 | void luaK_goiftrue (FuncState *fs, expdesc *e) { |
458 | Proto *f; | 505 | int pc; /* pc of last jump */ |
459 | Instruction i = previous_instruction(fs); | 506 | dischargevars(fs, e); |
460 | int push = (int)luaK_opproperties[o].push; | 507 | switch (e->k) { |
461 | int pop = (int)luaK_opproperties[o].pop; | 508 | case VK: case VNUMBER: { |
462 | int optm = 0; /* 1 when there is an optimization */ | 509 | pc = NO_JUMP; /* always true; do nothing */ |
463 | switch (o) { | ||
464 | case OP_CLOSURE: { | ||
465 | pop = arg2; | ||
466 | break; | 510 | break; |
467 | } | 511 | } |
468 | case OP_SETTABLE: { | 512 | case VNIL: { |
469 | pop = arg2; | 513 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
470 | break; | 514 | break; |
471 | } | 515 | } |
472 | case OP_SETLIST: { | 516 | case VJMP: { |
473 | pop = fs->stacklevel - 1 - arg2; | 517 | invertjump(fs, e); |
518 | pc = e->u.i.info; | ||
474 | break; | 519 | break; |
475 | } | 520 | } |
476 | case OP_SETMAP: { | 521 | case VRELOCABLE: |
477 | pop = fs->stacklevel - 1 - arg1; | 522 | case VNONRELOC: { |
523 | pc = jumponcond(fs, e, OP_TESTF); | ||
478 | break; | 524 | break; |
479 | } | 525 | } |
480 | case OP_PUSHNIL: { | 526 | default: { |
481 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 527 | pc = 0; /* to avoid warnings */ |
482 | push = arg1; | 528 | lua_assert(0); /* cannot happen */ |
483 | switch(GET_OPCODE(i)) { | ||
484 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | ||
485 | default: break; | ||
486 | } | ||
487 | break; | 529 | break; |
488 | } | 530 | } |
489 | case OP_POP: { | 531 | } |
490 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 532 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
491 | pop = arg1; | 533 | luaK_patchlist(fs, e->t, luaK_getlabel(fs)); |
492 | switch(GET_OPCODE(i)) { | 534 | e->t = NO_JUMP; |
493 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | 535 | } |
494 | default: break; | 536 | |
495 | } | 537 | |
538 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | ||
539 | int pc; /* pc of last jump */ | ||
540 | dischargevars(fs, e); | ||
541 | switch (e->k) { | ||
542 | case VNIL: { | ||
543 | pc = NO_JUMP; /* always false; do nothing */ | ||
496 | break; | 544 | break; |
497 | } | 545 | } |
498 | case OP_GETTABLE: { | 546 | case VJMP: { |
499 | switch(GET_OPCODE(i)) { | 547 | pc = e->u.i.info; |
500 | case OP_PUSHSTRING: /* `t.x' */ | ||
501 | SET_OPCODE(i, OP_GETDOTTED); | ||
502 | optm = 1; | ||
503 | break; | ||
504 | case OP_GETLOCAL: /* `t[i]' */ | ||
505 | SET_OPCODE(i, OP_GETINDEXED); | ||
506 | optm = 1; | ||
507 | break; | ||
508 | default: break; | ||
509 | } | ||
510 | break; | 548 | break; |
511 | } | 549 | } |
512 | case OP_ADD: { | 550 | case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ |
513 | switch(GET_OPCODE(i)) { | 551 | case VRELOCABLE: |
514 | case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ | 552 | case VNONRELOC: { |
515 | default: break; | 553 | pc = jumponcond(fs, e, OP_TESTT); |
516 | } | ||
517 | break; | 554 | break; |
518 | } | 555 | } |
519 | case OP_SUB: { | 556 | default: { |
520 | switch(GET_OPCODE(i)) { | 557 | pc = 0; /* to avoid warnings */ |
521 | case OP_PUSHINT: /* `a-k' */ | 558 | lua_assert(0); /* cannot happen */ |
522 | i = CREATE_S(OP_ADDI, -GETARG_S(i)); | ||
523 | optm = 1; | ||
524 | break; | ||
525 | default: break; | ||
526 | } | ||
527 | break; | 559 | break; |
528 | } | 560 | } |
529 | case OP_CONCAT: { | 561 | } |
530 | pop = arg1; | 562 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
531 | switch(GET_OPCODE(i)) { | 563 | luaK_patchlist(fs, e->f, luaK_getlabel(fs)); |
532 | case OP_CONCAT: /* `a..b..c' */ | 564 | e->f = NO_JUMP; |
533 | SETARG_U(i, GETARG_U(i)+1); | 565 | } |
534 | optm = 1; | 566 | |
535 | break; | 567 | |
536 | default: break; | 568 | static void codenot (FuncState *fs, expdesc *e) { |
537 | } | 569 | dischargevars(fs, e); |
570 | switch (e->k) { | ||
571 | case VNIL: { | ||
572 | e->u.n = 1; | ||
573 | e->k = VNUMBER; | ||
538 | break; | 574 | break; |
539 | } | 575 | } |
540 | case OP_MINUS: { | 576 | case VK: case VNUMBER: { |
541 | switch(GET_OPCODE(i)) { | 577 | e->k = VNIL; |
542 | case OP_PUSHINT: /* `-k' */ | ||
543 | SETARG_S(i, -GETARG_S(i)); | ||
544 | optm = 1; | ||
545 | break; | ||
546 | case OP_PUSHNUM: /* `-k' */ | ||
547 | SET_OPCODE(i, OP_PUSHNEGNUM); | ||
548 | optm = 1; | ||
549 | break; | ||
550 | default: break; | ||
551 | } | ||
552 | break; | 578 | break; |
553 | } | 579 | } |
554 | case OP_JMPNE: { | 580 | case VJMP: { |
555 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ | 581 | invertjump(fs, e); |
556 | i = CREATE_S(OP_JMPT, NO_JUMP); | ||
557 | optm = 1; | ||
558 | } | ||
559 | break; | 582 | break; |
560 | } | 583 | } |
561 | case OP_JMPEQ: { | 584 | case VRELOCABLE: |
562 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | 585 | case VNONRELOC: { |
563 | i = CREATE_0(OP_NOT); | 586 | discharge2anyreg(fs, e); |
564 | pop = 1; /* just undo effect of previous PUSHNIL */ | 587 | freeexp(fs, e); |
565 | optm = 1; | 588 | e->u.i.info = luaK_codeABC(fs, OP_NOT, 0, e->u.i.info, 0); |
566 | } | 589 | e->k = VRELOCABLE; |
567 | break; | 590 | break; |
568 | } | 591 | } |
569 | case OP_JMPT: | 592 | default: { |
570 | case OP_JMPONT: { | 593 | lua_assert(0); /* cannot happen */ |
571 | switch (GET_OPCODE(i)) { | ||
572 | case OP_NOT: { | ||
573 | i = CREATE_S(OP_JMPF, NO_JUMP); | ||
574 | optm = 1; | ||
575 | break; | ||
576 | } | ||
577 | case OP_PUSHINT: { | ||
578 | if (o == OP_JMPT) { /* JMPONT must keep original integer value */ | ||
579 | i = CREATE_S(OP_JMP, NO_JUMP); | ||
580 | optm = 1; | ||
581 | } | ||
582 | break; | ||
583 | } | ||
584 | case OP_PUSHNIL: { | ||
585 | if (GETARG_U(i) == 1) { | ||
586 | fs->pc--; /* erase previous instruction */ | ||
587 | luaK_deltastack(fs, -1); /* correct stack */ | ||
588 | return NO_JUMP; | ||
589 | } | ||
590 | break; | ||
591 | } | ||
592 | default: break; | ||
593 | } | ||
594 | break; | 594 | break; |
595 | } | 595 | } |
596 | case OP_JMPF: | 596 | } |
597 | case OP_JMPONF: { | 597 | /* interchange true and false lists */ |
598 | switch (GET_OPCODE(i)) { | 598 | { int temp = e->f; e->f = e->t; e->t = temp; } |
599 | case OP_NOT: { | 599 | } |
600 | i = CREATE_S(OP_JMPT, NO_JUMP); | 600 | |
601 | optm = 1; | 601 | |
602 | break; | 602 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
603 | } | 603 | t->u.i.aux = luaK_exp2RK(fs, k); |
604 | case OP_PUSHINT: { /* `while 1 do ...' */ | 604 | t->k = VINDEXED; |
605 | fs->pc--; /* erase previous instruction */ | 605 | } |
606 | luaK_deltastack(fs, -1); /* correct stack */ | 606 | |
607 | return NO_JUMP; | 607 | |
608 | } | 608 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
609 | case OP_PUSHNIL: { /* `repeat ... until nil' */ | 609 | if (op == OPR_MINUS) { |
610 | if (GETARG_U(i) == 1) { | 610 | luaK_exp2val(fs, e); |
611 | i = CREATE_S(OP_JMP, NO_JUMP); | 611 | if (e->k == VNUMBER) |
612 | optm = 1; | 612 | e->u.n = -e->u.n; |
613 | } | 613 | else { |
614 | break; | 614 | luaK_exp2anyreg(fs, e); |
615 | } | 615 | freeexp(fs, e); |
616 | default: break; | 616 | e->u.i.info = luaK_codeABC(fs, OP_UNM, 0, e->u.i.info, 0); |
617 | } | 617 | e->k = VRELOCABLE; |
618 | } | ||
619 | } | ||
620 | else /* op == NOT */ | ||
621 | codenot(fs, e); | ||
622 | } | ||
623 | |||
624 | |||
625 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | ||
626 | switch (op) { | ||
627 | case OPR_AND: { | ||
628 | luaK_goiftrue(fs, v); | ||
629 | break; | ||
630 | } | ||
631 | case OPR_OR: { | ||
632 | luaK_goiffalse(fs, v); | ||
633 | break; | ||
634 | } | ||
635 | case OPR_CONCAT: { | ||
636 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | ||
618 | break; | 637 | break; |
619 | } | 638 | } |
620 | case OP_GETDOTTED: | 639 | case OPR_SUB: case OPR_DIV: case OPR_POW: { |
621 | case OP_GETINDEXED: | 640 | /* non-comutative operators */ |
622 | case OP_ADDI: { | 641 | luaK_exp2anyreg(fs, v); /* first operand must be a register */ |
623 | lua_assert(0); /* instruction used only for optimizations */ | ||
624 | break; | 642 | break; |
625 | } | 643 | } |
626 | default: { | 644 | default: { |
645 | luaK_exp2RK(fs, v); | ||
627 | break; | 646 | break; |
628 | } | 647 | } |
629 | } | 648 | } |
630 | f = fs->f; | 649 | } |
631 | lua_assert(push != VD); | 650 | |
632 | lua_assert(pop != VD); | 651 | |
633 | luaK_deltastack(fs, push); | 652 | |
634 | luaK_deltastack(fs, -pop); | 653 | /* opcode for each binary operator */ |
635 | if (optm) { /* optimize: put instruction in place of last one */ | 654 | static const OpCode codes[] = { /* ORDER OPR */ |
636 | f->code[fs->pc-1] = i; /* change previous instruction */ | 655 | OP_ADD, OP_SUB, OP_MUL, OP_DIV, |
637 | return fs->pc-1; /* do not generate new instruction */ | 656 | OP_POW, OP_CONCAT, |
657 | OP_TESTNE, OP_TESTEQ, | ||
658 | OP_TESTLT, OP_TESTLE, OP_TESTGT, OP_TESTGE | ||
659 | }; | ||
660 | |||
661 | |||
662 | /* `inverted' opcode for each binary operator */ | ||
663 | /* ( -1 means operator has no inverse) */ | ||
664 | static const OpCode invcodes[] = { /* ORDER OPR */ | ||
665 | OP_ADD, (OpCode)-1, OP_MUL, (OpCode)-1, | ||
666 | (OpCode)-1, (OpCode)-1, | ||
667 | OP_TESTNE, OP_TESTEQ, | ||
668 | OP_TESTGT, OP_TESTGE, OP_TESTLT, OP_TESTLE | ||
669 | }; | ||
670 | |||
671 | |||
672 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | ||
673 | switch (op) { | ||
674 | case OPR_AND: { | ||
675 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | ||
676 | dischargevars(fs, e2); | ||
677 | luaK_concat(fs, &e1->f, e2->f); | ||
678 | e1->k = e2->k; e1->u = e2->u; e1->t = e2->t; | ||
679 | break; | ||
680 | } | ||
681 | case OPR_OR: { | ||
682 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | ||
683 | dischargevars(fs, e2); | ||
684 | luaK_concat(fs, &e1->t, e2->t); | ||
685 | e1->k = e2->k; e1->u = e2->u; e1->f = e2->f; | ||
686 | break; | ||
687 | } | ||
688 | case OPR_CONCAT: { | ||
689 | luaK_exp2val(fs, e2); | ||
690 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | ||
691 | lua_assert(e1->u.i.info == GETARG_B(getcode(fs, e2))-1); | ||
692 | freeexp(fs, e1); | ||
693 | SETARG_B(getcode(fs, e2), e1->u.i.info); | ||
694 | e1->k = e2->k; e1->u.i.info = e2->u.i.info; | ||
695 | } | ||
696 | else { | ||
697 | luaK_exp2nextreg(fs, e2); | ||
698 | freeexp(fs, e2); | ||
699 | freeexp(fs, e1); | ||
700 | e1->u.i.info = luaK_codeABC(fs, codes[op], 0, e1->u.i.info, | ||
701 | e2->u.i.info); | ||
702 | e1->k = VRELOCABLE; | ||
703 | } | ||
704 | break; | ||
705 | } | ||
706 | case OPR_EQ: case OPR_NE: { | ||
707 | luaK_exp2val(fs, e2); | ||
708 | if (e2->k == VNIL) { /* exp x= nil ? */ | ||
709 | if (e1->k == VK) { /* constant x= nil ? */ | ||
710 | if (op == OPR_EQ) /* constant == nil ? */ | ||
711 | e1->k = VNIL; /* always false */ | ||
712 | /* else always true (leave the constant itself) */ | ||
713 | } | ||
714 | else { | ||
715 | OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; | ||
716 | e1->u.i.info = jumponcond(fs, e1, opc); | ||
717 | e1->k = VJMP; | ||
718 | } | ||
719 | break; | ||
720 | } | ||
721 | /* else go through */ | ||
722 | } | ||
723 | default: { | ||
724 | int o1, o2; | ||
725 | OpCode opc; | ||
726 | if (e1->k != VK) { /* not a constant operator? */ | ||
727 | o1 = e1->u.i.info; | ||
728 | o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */ | ||
729 | opc = codes[op]; | ||
730 | } | ||
731 | else { /* invert operands */ | ||
732 | o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */ | ||
733 | o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */ | ||
734 | opc = invcodes[op]; /* use inverted operator */ | ||
735 | } | ||
736 | freeexp(fs, e2); | ||
737 | freeexp(fs, e1); | ||
738 | if (op < OPR_NE) { /* ORDER OPR */ | ||
739 | e1->u.i.info = luaK_codeABC(fs, opc, 0, o1, o2); | ||
740 | e1->k = VRELOCABLE; | ||
741 | } | ||
742 | else { /* jump */ | ||
743 | e1->u.i.info = luaK_condjump(fs, opc, o1, o2); | ||
744 | e1->k = VJMP; | ||
745 | } | ||
746 | } | ||
638 | } | 747 | } |
639 | /* else build new instruction */ | 748 | } |
640 | switch ((enum Mode)luaK_opproperties[o].mode) { | 749 | |
641 | case iO: i = CREATE_0(o); break; | 750 | |
642 | case iU: i = CREATE_U(o, arg1); break; | 751 | static void codelineinfo (FuncState *fs) { |
643 | case iS: i = CREATE_S(o, arg1); break; | 752 | Proto *f = fs->f; |
644 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | 753 | LexState *ls = fs->ls; |
754 | if (ls->lastline > fs->lastline) { | ||
755 | if (ls->lastline > fs->lastline+1) { | ||
756 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
757 | MAX_INT, l_s("line info overflow")); | ||
758 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | ||
759 | } | ||
760 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
761 | MAX_INT, l_s("line info overflow")); | ||
762 | f->lineinfo[fs->nlineinfo++] = fs->pc; | ||
763 | fs->lastline = ls->lastline; | ||
645 | } | 764 | } |
765 | } | ||
766 | |||
767 | |||
768 | static int luaK_code (FuncState *fs, Instruction i) { | ||
769 | Proto *f; | ||
646 | codelineinfo(fs); | 770 | codelineinfo(fs); |
771 | f = fs->f; | ||
647 | /* put new instruction in code array */ | 772 | /* put new instruction in code array */ |
648 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | 773 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, |
649 | MAX_INT, l_s("code size overflow")); | 774 | MAX_INT, l_s("code size overflow")); |
650 | f->code[fs->pc] = i; | 775 | f->code[fs->pc] = i; |
776 | /*printf("free: %d ", fs->freereg); printopcode(f, fs->pc);*/ | ||
651 | return fs->pc++; | 777 | return fs->pc++; |
652 | } | 778 | } |
653 | 779 | ||
654 | 780 | ||
655 | const OpProperties luaK_opproperties[] = { | 781 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { |
656 | {iU, 0, 0}, /* OP_RETURN */ | 782 | lua_assert(getOpMode(o) == iABC); |
657 | {iAB, 0, 0}, /* OP_CALL */ | 783 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); |
658 | {iU, VD, 0}, /* OP_PUSHNIL */ | 784 | } |
659 | {iU, 0, VD}, /* OP_POP */ | 785 | |
660 | {iS, 1, 0}, /* OP_PUSHINT */ | 786 | |
661 | {iU, 1, 0}, /* OP_PUSHSTRING */ | 787 | int luaK_codeABc (FuncState *fs, OpCode o, int a, int bc) { |
662 | {iU, 1, 0}, /* OP_PUSHNUM */ | 788 | lua_assert(getOpMode(o) == iABc || getOpMode(o) == iAsBc); |
663 | {iU, 1, 0}, /* OP_PUSHNEGNUM */ | 789 | return luaK_code(fs, CREATE_ABc(o, a, bc)); |
664 | {iU, 1, 0}, /* OP_PUSHUPVALUE */ | 790 | } |
665 | {iU, 1, 0}, /* OP_GETLOCAL */ | ||
666 | {iU, 1, 0}, /* OP_GETGLOBAL */ | ||
667 | {iO, 1, 2}, /* OP_GETTABLE */ | ||
668 | {iU, 1, 1}, /* OP_GETDOTTED */ | ||
669 | {iU, 1, 1}, /* OP_GETINDEXED */ | ||
670 | {iU, 2, 1}, /* OP_PUSHSELF */ | ||
671 | {iU, 1, 0}, /* OP_CREATETABLE */ | ||
672 | {iU, 0, 1}, /* OP_SETLOCAL */ | ||
673 | {iU, 0, 1}, /* OP_SETGLOBAL */ | ||
674 | {iAB, 0, VD}, /* OP_SETTABLE */ | ||
675 | {iAB, 0, VD}, /* OP_SETLIST */ | ||
676 | {iU, 0, VD}, /* OP_SETMAP */ | ||
677 | {iO, 1, 2}, /* OP_ADD */ | ||
678 | {iS, 1, 1}, /* OP_ADDI */ | ||
679 | {iO, 1, 2}, /* OP_SUB */ | ||
680 | {iO, 1, 2}, /* OP_MULT */ | ||
681 | {iO, 1, 2}, /* OP_DIV */ | ||
682 | {iO, 1, 2}, /* OP_POW */ | ||
683 | {iU, 1, VD}, /* OP_CONCAT */ | ||
684 | {iO, 1, 1}, /* OP_MINUS */ | ||
685 | {iO, 1, 1}, /* OP_NOT */ | ||
686 | {iS, 0, 2}, /* OP_JMPNE */ | ||
687 | {iS, 0, 2}, /* OP_JMPEQ */ | ||
688 | {iS, 0, 2}, /* OP_JMPLT */ | ||
689 | {iS, 0, 2}, /* OP_JMPLE */ | ||
690 | {iS, 0, 2}, /* OP_JMPGT */ | ||
691 | {iS, 0, 2}, /* OP_JMPGE */ | ||
692 | {iS, 0, 1}, /* OP_JMPT */ | ||
693 | {iS, 0, 1}, /* OP_JMPF */ | ||
694 | {iS, 0, 1}, /* OP_JMPONT */ | ||
695 | {iS, 0, 1}, /* OP_JMPONF */ | ||
696 | {iS, 0, 0}, /* OP_JMP */ | ||
697 | {iO, 0, 0}, /* OP_PUSHNILJMP */ | ||
698 | {iS, 0, 0}, /* OP_FORPREP */ | ||
699 | {iS, 0, 3}, /* OP_FORLOOP */ | ||
700 | {iS, 3, 0}, /* OP_LFORPREP */ | ||
701 | {iS, 0, 4}, /* OP_LFORLOOP */ | ||
702 | {iAB, 1, VD} /* OP_CLOSURE */ | ||
703 | }; | ||
704 | 791 | ||