diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-07 16:35:20 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-04-07 16:35:20 -0300 |
commit | 54dd5cc7fd42a8b073f64b7d16efdb1ed01e2dd5 (patch) | |
tree | 01c0e573c486173dcafc3ea0d0d45185f52aa19a | |
parent | 031978798cc404c2c6757c564675d43a7da129ee (diff) | |
download | lua-54dd5cc7fd42a8b073f64b7d16efdb1ed01e2dd5.tar.gz lua-54dd5cc7fd42a8b073f64b7d16efdb1ed01e2dd5.tar.bz2 lua-54dd5cc7fd42a8b073f64b7d16efdb1ed01e2dd5.zip |
reorganization of lcode.c
-rw-r--r-- | lcode.c | 460 | ||||
-rw-r--r-- | lcode.h | 11 | ||||
-rw-r--r-- | lparser.c | 33 |
3 files changed, 252 insertions, 252 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.21 2000/04/06 17:36:52 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.22 2000/04/07 13:13:11 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 | */ |
@@ -23,8 +23,9 @@ void luaK_error (LexState *ls, const char *msg) { | |||
23 | luaX_error(ls, msg, ls->token); | 23 | luaX_error(ls, msg, ls->token); |
24 | } | 24 | } |
25 | 25 | ||
26 | |||
26 | /* | 27 | /* |
27 | ** Returns the the previous instruction, for optimizations. | 28 | ** Returns the the previous instruction, for optimizations. |
28 | ** If there is a jump target between this and the current instruction, | 29 | ** If there is a jump target between this and the current instruction, |
29 | ** returns a dummy instruction to avoid wrong optimizations. | 30 | ** returns a dummy instruction to avoid wrong optimizations. |
30 | */ | 31 | */ |
@@ -36,154 +37,8 @@ static Instruction previous_instruction (FuncState *fs) { | |||
36 | } | 37 | } |
37 | 38 | ||
38 | 39 | ||
39 | int luaK_code (FuncState *fs, Instruction i, int delta) { | ||
40 | luaK_deltastack(fs, delta); | ||
41 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAX_INT); | ||
42 | fs->f->code[fs->pc] = i; | ||
43 | return fs->pc++; | ||
44 | } | ||
45 | |||
46 | int luaK_0(FuncState *fs, OpCode o, int d) { | ||
47 | return luaK_code(fs, CREATE_0(o), d); | ||
48 | } | ||
49 | |||
50 | int luaK_U(FuncState *fs, OpCode o, int u, int d) { | ||
51 | return luaK_code(fs, CREATE_U(o,u), d); | ||
52 | } | ||
53 | |||
54 | int luaK_S(FuncState *fs, OpCode o, int s, int d) { | ||
55 | return luaK_code(fs, CREATE_S(o,s), d); | ||
56 | } | ||
57 | |||
58 | int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d) { | ||
59 | return luaK_code(fs, CREATE_AB(o,a,b), d); | ||
60 | } | ||
61 | |||
62 | |||
63 | static Instruction prepare (FuncState *fs, Instruction i, int delta) { | ||
64 | Instruction previous = previous_instruction(fs); | ||
65 | luaK_code(fs, i, delta); | ||
66 | return previous; | ||
67 | } | ||
68 | |||
69 | |||
70 | static void setprevious (FuncState *fs, Instruction i) { | ||
71 | fs->pc--; /* remove last instruction */ | ||
72 | fs->f->code[fs->pc-1] = i; /* change previous instruction */ | ||
73 | } | ||
74 | |||
75 | |||
76 | static void luaK_minus (FuncState *fs) { | ||
77 | /* PUSHINT s; MINUS -> PUSHINT -s (-k) */ | ||
78 | /* PUSHNUM u; MINUS -> PUSHNEGNUM u (-k) */ | ||
79 | Instruction previous = prepare(fs, CREATE_0(OP_MINUS), 0); | ||
80 | switch(GET_OPCODE(previous)) { | ||
81 | case OP_PUSHINT: SETARG_S(previous, -GETARG_S(previous)); break; | ||
82 | case OP_PUSHNUM: SET_OPCODE(previous, OP_PUSHNEGNUM); break; | ||
83 | default: return; | ||
84 | } | ||
85 | setprevious(fs, previous); | ||
86 | } | ||
87 | |||
88 | |||
89 | static void luaK_gettable (FuncState *fs) { | ||
90 | /* PUSHSTRING u; GETTABLE -> GETDOTTED u (t.x) */ | ||
91 | /* GETLOCAL u; GETTABLE -> GETINDEXED u (t[i]) */ | ||
92 | Instruction previous = prepare(fs, CREATE_0(OP_GETTABLE), -1); | ||
93 | switch(GET_OPCODE(previous)) { | ||
94 | case OP_PUSHSTRING: SET_OPCODE(previous, OP_GETDOTTED); break; | ||
95 | case OP_GETLOCAL: SET_OPCODE(previous, OP_GETINDEXED); break; | ||
96 | default: return; | ||
97 | } | ||
98 | setprevious(fs, previous); | ||
99 | } | ||
100 | |||
101 | |||
102 | static void luaK_add (FuncState *fs) { | ||
103 | /* PUSHINT s; ADD -> ADDI s (a+k) */ | ||
104 | Instruction previous = prepare(fs, CREATE_0(OP_ADD), -1); | ||
105 | switch(GET_OPCODE(previous)) { | ||
106 | case OP_PUSHINT: SET_OPCODE(previous, OP_ADDI); break; | ||
107 | default: return; | ||
108 | } | ||
109 | setprevious(fs, previous); | ||
110 | } | ||
111 | |||
112 | |||
113 | static void luaK_sub (FuncState *fs) { | ||
114 | /* PUSHINT s; SUB -> ADDI -s (a-k) */ | ||
115 | Instruction previous = prepare(fs, CREATE_0(OP_SUB), -1); | ||
116 | switch(GET_OPCODE(previous)) { | ||
117 | case OP_PUSHINT: | ||
118 | SET_OPCODE(previous, OP_ADDI); | ||
119 | SETARG_S(previous, -GETARG_S(previous)); | ||
120 | break; | ||
121 | default: return; | ||
122 | } | ||
123 | setprevious(fs, previous); | ||
124 | } | ||
125 | |||
126 | |||
127 | static void luaK_conc (FuncState *fs) { | ||
128 | /* CONCAT u; CONCAT 2 -> CONCAT u+1 (a..b..c) */ | ||
129 | Instruction previous = prepare(fs, CREATE_U(OP_CONCAT, 2), -1); | ||
130 | switch(GET_OPCODE(previous)) { | ||
131 | case OP_CONCAT: SETARG_U(previous, GETARG_U(previous)+1); break; | ||
132 | default: return; | ||
133 | } | ||
134 | setprevious(fs, previous); | ||
135 | } | ||
136 | |||
137 | |||
138 | static void luaK_getlocal (FuncState *fs, int l) { | ||
139 | /* SETLOCAL l 1; GETLOCAL l -> SETLOCAL l 0 */ | ||
140 | Instruction previous = prepare(fs, CREATE_U(OP_GETLOCAL, l), 1); | ||
141 | if (previous == CREATE_AB(OP_SETLOCAL, l, 1)) { | ||
142 | SETARG_B(previous, 0); | ||
143 | setprevious(fs, previous); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | |||
148 | static void luaK_setlocal (FuncState *fs, int l) { | ||
149 | /* GETLOCAL l; ADDI k, SETLOCAL l -> INCLOCAL k, l ((local)a=a+k) */ | ||
150 | Instruction *code = fs->f->code; | ||
151 | int pc = fs->pc; | ||
152 | if (pc-1 > fs->lasttarget && /* no jumps in-between instructions? */ | ||
153 | code[pc-2] == CREATE_U(OP_GETLOCAL, l) && | ||
154 | GET_OPCODE(code[pc-1]) == OP_ADDI && | ||
155 | abs(GETARG_S(code[pc-1])) <= MAXARG_sA) { | ||
156 | int inc = GETARG_S(code[pc-1]); | ||
157 | fs->pc = pc-1; | ||
158 | code[pc-2] = CREATE_sAB(OP_INCLOCAL, inc, l); | ||
159 | luaK_deltastack(fs, -1); | ||
160 | } | ||
161 | else | ||
162 | luaK_AB(fs, OP_SETLOCAL, l, 1, -1); | ||
163 | } | ||
164 | |||
165 | |||
166 | static void luaK_eq (FuncState *fs) { | ||
167 | /* PUSHNIL 1; JMPEQ -> NOT (a==nil) */ | ||
168 | Instruction previous = prepare(fs, CREATE_S(OP_JMPEQ, NO_JUMP), -2); | ||
169 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { | ||
170 | setprevious(fs, CREATE_0(OP_NOT)); | ||
171 | luaK_deltastack(fs, 1); /* undo delta from `prepare' */ | ||
172 | } | ||
173 | } | ||
174 | |||
175 | |||
176 | static void luaK_neq (FuncState *fs) { | ||
177 | /* PUSHNIL 1; JMPNE -> JMPT (a~=nil) */ | ||
178 | Instruction previous = prepare(fs, CREATE_S(OP_JMPNE, NO_JUMP), -2); | ||
179 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { | ||
180 | setprevious(fs, CREATE_S(OP_JMPT, NO_JUMP)); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | |||
185 | int luaK_jump (FuncState *fs) { | 40 | int luaK_jump (FuncState *fs) { |
186 | int j = luaK_S(fs, OP_JMP, NO_JUMP, 0); | 41 | int j = luaK_code1(fs, OP_JMP, NO_JUMP); |
187 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 42 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ |
188 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 43 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ |
189 | fs->jlt = NO_JUMP; | 44 | fs->jlt = NO_JUMP; |
@@ -192,38 +47,6 @@ int luaK_jump (FuncState *fs) { | |||
192 | } | 47 | } |
193 | 48 | ||
194 | 49 | ||
195 | void luaK_retcode (FuncState *fs, int nlocals, int nexps) { | ||
196 | Instruction previous = prepare(fs, CREATE_U(OP_RETURN, nlocals), 0); | ||
197 | if (nexps > 0 && GET_OPCODE(previous) == OP_CALL) { | ||
198 | LUA_ASSERT(fs->L, GETARG_B(previous) == MULT_RET, "call should be open"); | ||
199 | SET_OPCODE(previous, OP_TAILCALL); | ||
200 | SETARG_B(previous, nlocals); | ||
201 | setprevious(fs, previous); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | |||
206 | static void luaK_pushnil (FuncState *fs, int n) { | ||
207 | Instruction previous = prepare(fs, CREATE_U(OP_PUSHNIL, n), n); | ||
208 | switch(GET_OPCODE(previous)) { | ||
209 | case OP_PUSHNIL: SETARG_U(previous, GETARG_U(previous)+n); break; | ||
210 | default: return; | ||
211 | } | ||
212 | setprevious(fs, previous); | ||
213 | } | ||
214 | |||
215 | |||
216 | static void luaK_pop (FuncState *fs, int n) { | ||
217 | Instruction previous = prepare(fs, CREATE_U(OP_POP, n), -n); | ||
218 | switch(GET_OPCODE(previous)) { | ||
219 | case OP_SETTABLE: SETARG_B(previous, GETARG_B(previous)+n); break; | ||
220 | case OP_SETLOCAL: SETARG_B(previous, GETARG_B(previous)+n); break; | ||
221 | default: return; | ||
222 | } | ||
223 | setprevious(fs, previous); | ||
224 | } | ||
225 | |||
226 | |||
227 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 50 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
228 | Instruction *jmp = &fs->f->code[pc]; | 51 | Instruction *jmp = &fs->f->code[pc]; |
229 | if (dest == NO_JUMP) | 52 | if (dest == NO_JUMP) |
@@ -274,7 +97,7 @@ void luaK_deltastack (FuncState *fs, int delta) { | |||
274 | 97 | ||
275 | 98 | ||
276 | void luaK_kstr (LexState *ls, int c) { | 99 | void luaK_kstr (LexState *ls, int c) { |
277 | luaK_U(ls->fs, OP_PUSHSTRING, c, 1); | 100 | luaK_code1(ls->fs, OP_PUSHSTRING, c); |
278 | } | 101 | } |
279 | 102 | ||
280 | 103 | ||
@@ -295,17 +118,17 @@ static int real_constant (FuncState *fs, Number r) { | |||
295 | 118 | ||
296 | void luaK_number (FuncState *fs, Number f) { | 119 | void luaK_number (FuncState *fs, Number f) { |
297 | if (f <= (Number)MAXARG_S && (int)f == f) | 120 | if (f <= (Number)MAXARG_S && (int)f == f) |
298 | luaK_S(fs, OP_PUSHINT, (int)f, 1); /* f has a short integer value */ | 121 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ |
299 | else | 122 | else |
300 | luaK_U(fs, OP_PUSHNUM, real_constant(fs, f), 1); | 123 | luaK_code1(fs, OP_PUSHNUM, real_constant(fs, f)); |
301 | } | 124 | } |
302 | 125 | ||
303 | 126 | ||
304 | void luaK_adjuststack (FuncState *fs, int n) { | 127 | void luaK_adjuststack (FuncState *fs, int n) { |
305 | if (n > 0) | 128 | if (n > 0) |
306 | luaK_pop(fs, n); | 129 | luaK_code1(fs, OP_POP, n); |
307 | else if (n < 0) | 130 | else if (n < 0) |
308 | luaK_pushnil(fs, -n); | 131 | luaK_code1(fs, OP_PUSHNIL, -n); |
309 | } | 132 | } |
310 | 133 | ||
311 | 134 | ||
@@ -334,14 +157,14 @@ static void assertglobal (FuncState *fs, int index) { | |||
334 | static int discharge (FuncState *fs, expdesc *var) { | 157 | static int discharge (FuncState *fs, expdesc *var) { |
335 | switch (var->k) { | 158 | switch (var->k) { |
336 | case VLOCAL: | 159 | case VLOCAL: |
337 | luaK_getlocal(fs, var->u.index); | 160 | luaK_code1(fs, OP_GETLOCAL, var->u.index); |
338 | break; | 161 | break; |
339 | case VGLOBAL: | 162 | case VGLOBAL: |
340 | luaK_U(fs, OP_GETGLOBAL, var->u.index, 1); | 163 | luaK_code1(fs, OP_GETGLOBAL, var->u.index); |
341 | assertglobal(fs, var->u.index); /* make sure that there is a global */ | 164 | assertglobal(fs, var->u.index); /* make sure that there is a global */ |
342 | break; | 165 | break; |
343 | case VINDEXED: | 166 | case VINDEXED: |
344 | luaK_gettable(fs); | 167 | luaK_code0(fs, OP_GETTABLE); |
345 | break; | 168 | break; |
346 | case VEXP: | 169 | case VEXP: |
347 | return 0; /* nothing to do */ | 170 | return 0; /* nothing to do */ |
@@ -358,20 +181,20 @@ static void discharge1 (FuncState *fs, expdesc *var) { | |||
358 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | 181 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) |
359 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | 182 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ |
360 | } | 183 | } |
361 | 184 | ||
362 | 185 | ||
363 | void luaK_storevar (LexState *ls, const expdesc *var) { | 186 | void luaK_storevar (LexState *ls, const expdesc *var) { |
364 | FuncState *fs = ls->fs; | 187 | FuncState *fs = ls->fs; |
365 | switch (var->k) { | 188 | switch (var->k) { |
366 | case VLOCAL: | 189 | case VLOCAL: |
367 | luaK_setlocal(fs, var->u.index); | 190 | luaK_code1(fs, OP_SETLOCAL, var->u.index); |
368 | break; | 191 | break; |
369 | case VGLOBAL: | 192 | case VGLOBAL: |
370 | luaK_U(fs, OP_SETGLOBAL, var->u.index, -1); | 193 | luaK_code1(fs, OP_SETGLOBAL, var->u.index); |
371 | assertglobal(fs, var->u.index); /* make sure that there is a global */ | 194 | assertglobal(fs, var->u.index); /* make sure that there is a global */ |
372 | break; | 195 | break; |
373 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | 196 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ |
374 | luaK_AB(fs, OP_SETTABLE, 3, 3, -3); | 197 | luaK_code2(fs, OP_SETTABLE, 3, 3); |
375 | break; | 198 | break; |
376 | default: | 199 | default: |
377 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); | 200 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); |
@@ -396,16 +219,6 @@ static OpCode invertjump (OpCode op) { | |||
396 | } | 219 | } |
397 | 220 | ||
398 | 221 | ||
399 | static void luaK_condjump (FuncState *fs, OpCode jump) { | ||
400 | Instruction previous = prepare(fs, CREATE_S(jump, NO_JUMP), -1); | ||
401 | switch (GET_OPCODE(previous)) { | ||
402 | case OP_NOT: previous = CREATE_S(invertjump(jump), NO_JUMP); break; | ||
403 | default: return; | ||
404 | } | ||
405 | setprevious(fs, previous); | ||
406 | } | ||
407 | |||
408 | |||
409 | static void luaK_patchlistaux (FuncState *fs, int list, int target, | 222 | static void luaK_patchlistaux (FuncState *fs, int list, int target, |
410 | OpCode special, int special_target) { | 223 | OpCode special, int special_target) { |
411 | Instruction *code = fs->f->code; | 224 | Instruction *code = fs->f->code; |
@@ -475,7 +288,7 @@ static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | |||
475 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 288 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); |
476 | } | 289 | } |
477 | else | 290 | else |
478 | luaK_condjump(fs, jump); | 291 | luaK_code0(fs, jump); |
479 | luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */ | 292 | luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */ |
480 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | 293 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); |
481 | *golist = NO_JUMP; | 294 | *golist = NO_JUMP; |
@@ -508,23 +321,25 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | |||
508 | int final; /* position after whole expression */ | 321 | int final; /* position after whole expression */ |
509 | if (ISJUMP(previous)) { | 322 | if (ISJUMP(previous)) { |
510 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in true list */ | 323 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in true list */ |
511 | p_nil = luaK_0(fs, OP_PUSHNILJMP, 0); | 324 | p_nil = luaK_code0(fs, OP_PUSHNILJMP); |
512 | p_1 = luaK_S(fs, OP_PUSHINT, 1, 1); | 325 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); |
513 | } | 326 | } |
514 | else { /* still may need a PUSHNIL or a PUSHINT */ | 327 | else { /* still may need a PUSHNIL or a PUSHINT */ |
515 | int need_nil = need_value(fs, v->u.l.f, OP_JMPONF); | 328 | int need_nil = need_value(fs, v->u.l.f, OP_JMPONF); |
516 | int need_1 = need_value(fs, v->u.l.t, OP_JMPONT); | 329 | int need_1 = need_value(fs, v->u.l.t, OP_JMPONT); |
517 | if (need_nil && need_1) { | 330 | if (need_nil && need_1) { |
518 | luaK_S(fs, OP_JMP, 2, 0); /* skip both pushes */ | 331 | luaK_code1(fs, OP_JMP, 2); /* skip both pushes */ |
519 | p_nil = luaK_0(fs, OP_PUSHNILJMP, 0); | 332 | p_nil = luaK_code0(fs, OP_PUSHNILJMP); |
520 | p_1 = luaK_S(fs, OP_PUSHINT, 1, 0); | 333 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); |
334 | luaK_deltastack(fs, -1); /* previous PUSHINT may be skipped */ | ||
521 | } | 335 | } |
522 | else if (need_nil || need_1) { | 336 | else if (need_nil || need_1) { |
523 | luaK_S(fs, OP_JMP, 1, 0); /* skip one push */ | 337 | luaK_code1(fs, OP_JMP, 1); /* skip one push */ |
524 | if (need_nil) | 338 | if (need_nil) |
525 | p_nil = luaK_U(fs, OP_PUSHNIL, 1, 0); | 339 | p_nil = luaK_code1(fs, OP_PUSHNIL, 1); |
526 | else /* need_1 */ | 340 | else /* need_1 */ |
527 | p_1 = luaK_S(fs, OP_PUSHINT, 1, 0); | 341 | p_1 = luaK_code1(fs, OP_PUSHINT, 1); |
342 | luaK_deltastack(fs, -1); /* previous PUSHs may be skipped */ | ||
528 | } | 343 | } |
529 | } | 344 | } |
530 | final = luaK_getlabel(fs); | 345 | final = luaK_getlabel(fs); |
@@ -540,7 +355,7 @@ void luaK_prefix (LexState *ls, int op, expdesc *v) { | |||
540 | FuncState *fs = ls->fs; | 355 | FuncState *fs = ls->fs; |
541 | if (op == '-') { | 356 | if (op == '-') { |
542 | luaK_tostack(ls, v, 1); | 357 | luaK_tostack(ls, v, 1); |
543 | luaK_minus(fs); | 358 | luaK_code0(fs, OP_MINUS); |
544 | } | 359 | } |
545 | else { /* op == NOT */ | 360 | else { /* op == NOT */ |
546 | Instruction *previous; | 361 | Instruction *previous; |
@@ -549,7 +364,7 @@ void luaK_prefix (LexState *ls, int op, expdesc *v) { | |||
549 | if (ISJUMP(GET_OPCODE(*previous))) | 364 | if (ISJUMP(GET_OPCODE(*previous))) |
550 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 365 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); |
551 | else | 366 | else |
552 | luaK_0(fs, OP_NOT, 0); | 367 | luaK_code0(fs, OP_NOT); |
553 | /* interchange true and false lists */ | 368 | /* interchange true and false lists */ |
554 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | 369 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } |
555 | } | 370 | } |
@@ -564,7 +379,7 @@ void luaK_infix (LexState *ls, int op, expdesc *v) { | |||
564 | luaK_goiffalse(fs, v, 1); | 379 | luaK_goiffalse(fs, v, 1); |
565 | else | 380 | else |
566 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | 381 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ |
567 | } | 382 | } |
568 | 383 | ||
569 | 384 | ||
570 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | 385 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { |
@@ -584,19 +399,210 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
584 | else { | 399 | else { |
585 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | 400 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ |
586 | switch (op) { | 401 | switch (op) { |
587 | case '+': luaK_add(fs); break; | 402 | case '+': luaK_code0(fs, OP_ADD); break; |
588 | case '-': luaK_sub(fs); break; | 403 | case '-': luaK_code0(fs, OP_SUB); break; |
589 | case '*': luaK_0(fs, OP_MULT, -1); break; | 404 | case '*': luaK_code0(fs, OP_MULT); break; |
590 | case '/': luaK_0(fs, OP_DIV, -1); break; | 405 | case '/': luaK_code0(fs, OP_DIV); break; |
591 | case '^': luaK_0(fs, OP_POW, -1); break; | 406 | case '^': luaK_code0(fs, OP_POW); break; |
592 | case TK_CONCAT: luaK_conc(fs); break; | 407 | case TK_CONCAT: luaK_code1(fs, OP_CONCAT, 2); break; |
593 | case TK_EQ: luaK_eq(fs); break; | 408 | case TK_EQ: luaK_code0(fs, OP_JMPEQ); break; |
594 | case TK_NE: luaK_neq(fs); break; | 409 | case TK_NE: luaK_code0(fs, OP_JMPNE); break; |
595 | case '>': luaK_S(fs, OP_JMPGT, NO_JUMP, -2); break; | 410 | case '>': luaK_code0(fs, OP_JMPGT); break; |
596 | case '<': luaK_S(fs, OP_JMPLT, NO_JUMP, -2); break; | 411 | case '<': luaK_code0(fs, OP_JMPLT); break; |
597 | case TK_GE: luaK_S(fs, OP_JMPGE, NO_JUMP, -2); break; | 412 | case TK_GE: luaK_code0(fs, OP_JMPGE); break; |
598 | case TK_LE: luaK_S(fs, OP_JMPLE, NO_JUMP, -2); break; | 413 | case TK_LE: luaK_code0(fs, OP_JMPLE); break; |
599 | } | 414 | } |
600 | } | 415 | } |
601 | } | 416 | } |
602 | 417 | ||
418 | |||
419 | int luaK_code0 (FuncState *fs, OpCode o) { | ||
420 | return luaK_code2(fs, o, 0, 0); | ||
421 | } | ||
422 | |||
423 | |||
424 | int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | ||
425 | return luaK_code2(fs, o, arg1, 0); | ||
426 | } | ||
427 | |||
428 | |||
429 | |||
430 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | ||
431 | Instruction i = previous_instruction(fs); | ||
432 | int delta = 0; | ||
433 | enum {iO, iU, iS, iAB, iP} mode; /* instruction format (or iP to optimize) */ | ||
434 | mode = iP; | ||
435 | switch (o) { | ||
436 | |||
437 | case OP_JMP: delta = 0; mode = iS; break; | ||
438 | case OP_CLOSURE: delta = -arg2+1; mode = iAB; break; | ||
439 | case OP_SETLINE: mode = iU; break; | ||
440 | case OP_CALL: mode = iAB; break; | ||
441 | case OP_PUSHINT: delta = 1; mode = iS; break; | ||
442 | case OP_SETGLOBAL: delta = -1; mode = iU; break; | ||
443 | case OP_SETTABLE: delta = -arg2; mode = iAB; break; | ||
444 | case OP_SETLIST: delta = -(arg2+1); mode = iAB; break; | ||
445 | case OP_SETMAP: delta = -2*(arg1+1); mode = iU; break; | ||
446 | |||
447 | case OP_END: case OP_PUSHNILJMP: case OP_NOT: | ||
448 | mode = iO; break; | ||
449 | |||
450 | case OP_PUSHSTRING: case OP_PUSHNUM: | ||
451 | case OP_PUSHNEGNUM: case OP_PUSHUPVALUE: | ||
452 | case OP_GETGLOBAL: case OP_PUSHSELF: case OP_CREATETABLE: | ||
453 | delta = 1; mode = iU; break; | ||
454 | |||
455 | case OP_JMPLT: case OP_JMPLE: case OP_JMPGT: case OP_JMPGE: | ||
456 | delta = -2; arg1 = NO_JUMP; mode = iS; break; | ||
457 | |||
458 | case OP_MULT: case OP_DIV: case OP_POW: | ||
459 | delta = -1; mode = iO; break; | ||
460 | |||
461 | case OP_RETURN: | ||
462 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { | ||
463 | SET_OPCODE(i, OP_TAILCALL); | ||
464 | SETARG_B(i, arg1); | ||
465 | } | ||
466 | else mode = iU; | ||
467 | break; | ||
468 | |||
469 | case OP_PUSHNIL: | ||
470 | delta = arg1; | ||
471 | switch(GET_OPCODE(i)) { | ||
472 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); break; | ||
473 | default: mode = iU; break; | ||
474 | } | ||
475 | break; | ||
476 | |||
477 | case OP_POP: | ||
478 | delta = -arg1; | ||
479 | switch(GET_OPCODE(i)) { | ||
480 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); break; | ||
481 | case OP_SETLOCAL: SETARG_B(i, GETARG_B(i)+arg1); break; | ||
482 | default: mode = iU; break; | ||
483 | } | ||
484 | break; | ||
485 | |||
486 | case OP_GETLOCAL: | ||
487 | delta = 1; | ||
488 | if (i == CREATE_AB(OP_SETLOCAL, arg1, 1)) | ||
489 | SETARG_B(i, 0); | ||
490 | else mode = iU; | ||
491 | break; | ||
492 | |||
493 | case OP_GETTABLE: | ||
494 | delta = -1; | ||
495 | switch(GET_OPCODE(i)) { | ||
496 | case OP_PUSHSTRING: SET_OPCODE(i, OP_GETDOTTED); break; /* `t.x' */ | ||
497 | case OP_GETLOCAL: SET_OPCODE(i, OP_GETINDEXED); break; /* `t[i]' */ | ||
498 | default: mode = iO; break; | ||
499 | } | ||
500 | break; | ||
501 | |||
502 | case OP_SETLOCAL: { | ||
503 | int pc = fs->pc; | ||
504 | Instruction *code = fs->f->code; | ||
505 | delta = -1; | ||
506 | if (pc-1 > fs->lasttarget && /* no jumps in-between instructions? */ | ||
507 | code[pc-2] == CREATE_U(OP_GETLOCAL, arg1) && | ||
508 | GET_OPCODE(i) == OP_ADDI && abs(GETARG_S(i)) <= MAXARG_sA) { | ||
509 | /* `local=local+k' */ | ||
510 | fs->pc = pc-1; | ||
511 | code[pc-2] = CREATE_sAB(OP_INCLOCAL, GETARG_S(i), arg1); | ||
512 | luaK_deltastack(fs, delta); | ||
513 | return pc-1; | ||
514 | } | ||
515 | else { | ||
516 | arg2 = 1; /* `setlocal' default pops one value */ | ||
517 | mode = iAB; | ||
518 | } | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | case OP_ADD: | ||
523 | delta = -1; | ||
524 | switch(GET_OPCODE(i)) { | ||
525 | case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); break; /* `a+k' */ | ||
526 | default: mode = iO; break; | ||
527 | } | ||
528 | break; | ||
529 | |||
530 | case OP_SUB: | ||
531 | delta = -1; | ||
532 | switch(GET_OPCODE(i)) { | ||
533 | case OP_PUSHINT: i = CREATE_S(OP_ADDI, -GETARG_S(i)); break; /* `a-k' */ | ||
534 | default: mode = iO; break; | ||
535 | } | ||
536 | break; | ||
537 | |||
538 | case OP_CONCAT: | ||
539 | delta = -arg1+1; | ||
540 | switch(GET_OPCODE(i)) { | ||
541 | case OP_CONCAT: SETARG_U(i, GETARG_U(i)+1); break; /* `a..b..c' */ | ||
542 | default: mode = iU; break; | ||
543 | } | ||
544 | break; | ||
545 | |||
546 | case OP_MINUS: | ||
547 | switch(GET_OPCODE(i)) { | ||
548 | case OP_PUSHINT: SETARG_S(i, -GETARG_S(i)); break; /* `-k' */ | ||
549 | case OP_PUSHNUM: SET_OPCODE(i, OP_PUSHNEGNUM); break; /* `-k' */ | ||
550 | default: mode = iO; break; | ||
551 | } | ||
552 | break; | ||
553 | |||
554 | case OP_JMPNE: | ||
555 | delta = -2; | ||
556 | if (i == CREATE_U(OP_PUSHNIL, 1)) /* `a~=nil' */ | ||
557 | i = CREATE_S(OP_JMPT, NO_JUMP); | ||
558 | else { | ||
559 | arg1 = NO_JUMP; | ||
560 | mode = iS; | ||
561 | } | ||
562 | break; | ||
563 | |||
564 | case OP_JMPEQ: | ||
565 | delta = -2; | ||
566 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | ||
567 | i = CREATE_0(OP_NOT); | ||
568 | delta = -1; /* just undo effect of previous PUSHNIL */ | ||
569 | } | ||
570 | else { | ||
571 | arg1 = NO_JUMP; | ||
572 | mode = iS; | ||
573 | } | ||
574 | break; | ||
575 | |||
576 | case OP_JMPT: case OP_JMPF: case OP_JMPONT: case OP_JMPONF: | ||
577 | delta = -1; | ||
578 | arg1 = NO_JUMP; | ||
579 | switch (GET_OPCODE(i)) { | ||
580 | case OP_NOT: i = CREATE_S(invertjump(o), NO_JUMP); break; | ||
581 | default: mode = iS; break; | ||
582 | } | ||
583 | break; | ||
584 | |||
585 | case OP_GETDOTTED: case OP_GETINDEXED: | ||
586 | case OP_TAILCALL: case OP_INCLOCAL: | ||
587 | case OP_ADDI: | ||
588 | LUA_INTERNALERROR(L, "instruction used only for optimizations"); | ||
589 | return 0; /* to avoid warnings */ | ||
590 | |||
591 | } | ||
592 | luaK_deltastack(fs, delta); | ||
593 | switch (mode) { /* handle instruction formats */ | ||
594 | case iO: i = CREATE_0(o); break; | ||
595 | case iU: i = CREATE_U(o, arg1); break; | ||
596 | case iS: i = CREATE_S(o, arg1); break; | ||
597 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | ||
598 | case iP: { /* optimize: put instruction in place of last one */ | ||
599 | fs->f->code[fs->pc-1] = i; /* change previous instruction */ | ||
600 | return fs->pc-1; | ||
601 | } | ||
602 | } | ||
603 | /* actually create the new instruction */ | ||
604 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAX_INT); | ||
605 | fs->f->code[fs->pc] = i; | ||
606 | return fs->pc++; | ||
607 | } | ||
608 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.9 2000/03/17 13:09:46 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.10 2000/04/05 17:51:58 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 | */ |
@@ -17,12 +17,9 @@ | |||
17 | 17 | ||
18 | 18 | ||
19 | void luaK_error (LexState *ls, const char *msg); | 19 | void luaK_error (LexState *ls, const char *msg); |
20 | int luaK_0(FuncState *fs, OpCode o, int d); | 20 | int luaK_code0 (FuncState *fs, OpCode o); |
21 | int luaK_U(FuncState *fs, OpCode o, int u, int d); | 21 | int luaK_code1 (FuncState *fs, OpCode o, int arg1); |
22 | int luaK_S(FuncState *fs, OpCode o, int s, int d); | 22 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); |
23 | int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d); | ||
24 | int luaK_code (FuncState *fs, Instruction i, int delta); | ||
25 | void luaK_retcode (FuncState *fs, int nlocals, int nexps); | ||
26 | int luaK_jump (FuncState *fs); | 23 | int luaK_jump (FuncState *fs); |
27 | void luaK_patchlist (FuncState *fs, int list, int target); | 24 | void luaK_patchlist (FuncState *fs, int list, int target); |
28 | void luaK_concat (FuncState *fs, int *l1, int l2); | 25 | void luaK_concat (FuncState *fs, int *l1, int l2); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.77 2000/04/06 17:36:52 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.78 2000/04/07 13:13:11 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -91,7 +91,7 @@ static void setline (LexState *ls) { | |||
91 | FuncState *fs = ls->fs; | 91 | FuncState *fs = ls->fs; |
92 | if (ls->L->debug && ls->linenumber != fs->lastsetline) { | 92 | if (ls->L->debug && ls->linenumber != fs->lastsetline) { |
93 | checklimit(ls, ls->linenumber, MAXARG_U, "lines in a chunk"); | 93 | checklimit(ls, ls->linenumber, MAXARG_U, "lines in a chunk"); |
94 | luaK_U(fs, OP_SETLINE, ls->linenumber, 0); | 94 | luaK_code1(fs, OP_SETLINE, ls->linenumber); |
95 | fs->lastsetline = ls->linenumber; | 95 | fs->lastsetline = ls->linenumber; |
96 | } | 96 | } |
97 | } | 97 | } |
@@ -260,7 +260,7 @@ static void pushupvalue (LexState *ls, TString *n) { | |||
260 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); | 260 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); |
261 | if (aux_localname(ls->fs, n) >= 0) | 261 | if (aux_localname(ls->fs, n) >= 0) |
262 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); | 262 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); |
263 | luaK_U(fs, OP_PUSHUPVALUE, indexupvalue(ls, n), 1); | 263 | luaK_code1(fs, OP_PUSHUPVALUE, indexupvalue(ls, n)); |
264 | } | 264 | } |
265 | 265 | ||
266 | 266 | ||
@@ -339,8 +339,7 @@ static void func_onstack (LexState *ls, FuncState *func) { | |||
339 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, Proto *, | 339 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, Proto *, |
340 | constantEM, MAXARG_A); | 340 | constantEM, MAXARG_A); |
341 | f->kproto[f->nkproto++] = func->f; | 341 | f->kproto[f->nkproto++] = func->f; |
342 | luaK_deltastack(fs, 1); /* CLOSURE puts one extra element before popping */ | 342 | luaK_code2(fs, OP_CLOSURE, f->nkproto-1, func->nupvalues); |
343 | luaK_AB(fs, OP_CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues); | ||
344 | } | 343 | } |
345 | 344 | ||
346 | 345 | ||
@@ -373,7 +372,7 @@ static void close_func (LexState *ls) { | |||
373 | lua_State *L = ls->L; | 372 | lua_State *L = ls->L; |
374 | FuncState *fs = ls->fs; | 373 | FuncState *fs = ls->fs; |
375 | Proto *f = fs->f; | 374 | Proto *f = fs->f; |
376 | luaK_0(fs, OP_END, 0); | 375 | luaK_code0(fs, OP_END); |
377 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 376 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
378 | luaM_reallocvector(L, f->code, fs->pc, Instruction); | 377 | luaM_reallocvector(L, f->code, fs->pc, Instruction); |
379 | luaM_reallocvector(L, f->kstr, f->nkstr, TString *); | 378 | luaM_reallocvector(L, f->kstr, f->nkstr, TString *); |
@@ -469,7 +468,7 @@ static void funcargs (LexState *ls, int slf) { | |||
469 | break; | 468 | break; |
470 | } | 469 | } |
471 | fs->stacklevel = slevel; /* call will remove function and arguments */ | 470 | fs->stacklevel = slevel; /* call will remove function and arguments */ |
472 | luaK_AB(fs, OP_CALL, slevel, MULT_RET, 0); | 471 | luaK_code2(fs, OP_CALL, slevel, MULT_RET); |
473 | } | 472 | } |
474 | 473 | ||
475 | 474 | ||
@@ -496,7 +495,7 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
496 | next(ls); | 495 | next(ls); |
497 | name = checkname(ls); | 496 | name = checkname(ls); |
498 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 497 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ |
499 | luaK_U(ls->fs, OP_PUSHSELF, name, 1); | 498 | luaK_code1(ls->fs, OP_PUSHSELF, name); |
500 | funcargs(ls, 1); | 499 | funcargs(ls, 1); |
501 | v->k = VEXP; | 500 | v->k = VEXP; |
502 | v->u.l.t = v->u.l.f = NO_JUMP; | 501 | v->u.l.t = v->u.l.f = NO_JUMP; |
@@ -569,12 +568,12 @@ static int recfields (LexState *ls) { | |||
569 | recfield(ls); | 568 | recfield(ls); |
570 | n++; | 569 | n++; |
571 | if (++mod_n == RFIELDS_PER_FLUSH) { | 570 | if (++mod_n == RFIELDS_PER_FLUSH) { |
572 | luaK_U(fs, OP_SETMAP, RFIELDS_PER_FLUSH-1, -2*RFIELDS_PER_FLUSH); | 571 | luaK_code1(fs, OP_SETMAP, RFIELDS_PER_FLUSH-1); |
573 | mod_n = 0; | 572 | mod_n = 0; |
574 | } | 573 | } |
575 | } | 574 | } |
576 | if (mod_n) | 575 | if (mod_n) |
577 | luaK_U(fs, OP_SETMAP, mod_n-1, -2*mod_n); | 576 | luaK_code1(fs, OP_SETMAP, mod_n-1); |
578 | return n; | 577 | return n; |
579 | } | 578 | } |
580 | 579 | ||
@@ -593,13 +592,12 @@ static int listfields (LexState *ls) { | |||
593 | checklimit(ls, n, MAXARG_A*LFIELDS_PER_FLUSH, | 592 | checklimit(ls, n, MAXARG_A*LFIELDS_PER_FLUSH, |
594 | "items in a list initializer"); | 593 | "items in a list initializer"); |
595 | if (++mod_n == LFIELDS_PER_FLUSH) { | 594 | if (++mod_n == LFIELDS_PER_FLUSH) { |
596 | luaK_AB(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH-1, | 595 | luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH-1); |
597 | -LFIELDS_PER_FLUSH); | ||
598 | mod_n = 0; | 596 | mod_n = 0; |
599 | } | 597 | } |
600 | } | 598 | } |
601 | if (mod_n > 0) | 599 | if (mod_n > 0) |
602 | luaK_AB(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH, mod_n-1, -mod_n); | 600 | luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH, mod_n-1); |
603 | return n; | 601 | return n; |
604 | } | 602 | } |
605 | 603 | ||
@@ -649,7 +647,7 @@ static void constructor (LexState *ls) { | |||
649 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ | 647 | /* constructor -> '{' constructor_part [';' constructor_part] '}' */ |
650 | FuncState *fs = ls->fs; | 648 | FuncState *fs = ls->fs; |
651 | int line = ls->linenumber; | 649 | int line = ls->linenumber; |
652 | int pc = luaK_U(fs, OP_CREATETABLE, 0, 1); | 650 | int pc = luaK_code1(fs, OP_CREATETABLE, 0); |
653 | int nelems; | 651 | int nelems; |
654 | Constdesc cd; | 652 | Constdesc cd; |
655 | check(ls, '{'); | 653 | check(ls, '{'); |
@@ -835,7 +833,7 @@ static int assignment (LexState *ls, expdesc *v, int nvars) { | |||
835 | if (v->k != VINDEXED) | 833 | if (v->k != VINDEXED) |
836 | luaK_storevar(ls, v); | 834 | luaK_storevar(ls, v); |
837 | else { /* there may be garbage between table-index and value */ | 835 | else { /* there may be garbage between table-index and value */ |
838 | luaK_AB(ls->fs, OP_SETTABLE, left+nvars+2, 1, -1); | 836 | luaK_code2(ls->fs, OP_SETTABLE, left+nvars+2, 1); |
839 | left += 2; | 837 | left += 2; |
840 | } | 838 | } |
841 | return left; | 839 | return left; |
@@ -1099,10 +1097,9 @@ static void ret (LexState *ls) { | |||
1099 | FuncState *fs = ls->fs; | 1097 | FuncState *fs = ls->fs; |
1100 | switch (ls->token) { | 1098 | switch (ls->token) { |
1101 | case TK_RETURN: { | 1099 | case TK_RETURN: { |
1102 | int nexps; /* number of expressions returned */ | ||
1103 | setline_and_next(ls); /* skip RETURN */ | 1100 | setline_and_next(ls); /* skip RETURN */ |
1104 | nexps = explist(ls); | 1101 | explist(ls); |
1105 | luaK_retcode(fs, ls->fs->nlocalvar, nexps); | 1102 | luaK_code1(fs, OP_RETURN, ls->fs->nlocalvar); |
1106 | fs->stacklevel = fs->nlocalvar; /* removes all temp values */ | 1103 | fs->stacklevel = fs->nlocalvar; /* removes all temp values */ |
1107 | optional(ls, ';'); | 1104 | optional(ls, ';'); |
1108 | break; | 1105 | break; |