diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 223 |
1 files changed, 100 insertions, 123 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.3 2000/03/03 14:58:26 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 | */ |
@@ -20,12 +20,10 @@ void luaK_error (LexState *ls, const char *msg) { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | 22 | ||
23 | static Instruction *last_i (FuncState *fs) { | 23 | static Instruction *last_i (LexState *ls, expdesc *v) { |
24 | static Instruction dummy = SET_OPCODE(0, ENDCODE); | 24 | FuncState *fs = ls->fs; |
25 | if (fs->last_pc < 0) | 25 | int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1; |
26 | return &dummy; | 26 | return &fs->f->code[last_pc]; |
27 | else | ||
28 | return &fs->f->code[fs->last_pc]; | ||
29 | } | 27 | } |
30 | 28 | ||
31 | 29 | ||
@@ -37,58 +35,64 @@ int luaK_primitivecode (LexState *ls, Instruction i) { | |||
37 | } | 35 | } |
38 | 36 | ||
39 | 37 | ||
38 | static void luaK_minus (LexState *ls, expdesc *v) { | ||
39 | Instruction *last = last_i(ls, v); | ||
40 | switch(GET_OPCODE(*last)) { | ||
41 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return; | ||
42 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return; | ||
43 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return; | ||
44 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); | ||
45 | } | ||
46 | } | ||
40 | 47 | ||
41 | int luaK_code (LexState *ls, Instruction i) { | ||
42 | FuncState *fs = ls->fs; | ||
43 | Instruction *last = last_i(fs); | ||
44 | switch (GET_OPCODE(i)) { | ||
45 | |||
46 | case MINUSOP: | ||
47 | switch(GET_OPCODE(*last)) { | ||
48 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); break; | ||
49 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); break; | ||
50 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); break; | ||
51 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
52 | } | ||
53 | break; | ||
54 | 48 | ||
55 | case GETTABLE: | 49 | static void luaK_gettable (LexState *ls, expdesc *v) { |
56 | switch(GET_OPCODE(*last)) { | 50 | Instruction *last = last_i(ls, v); |
57 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; | 51 | luaK_deltastack(ls, -1); |
58 | default: fs->last_pc = luaK_primitivecode(ls, i); | 52 | switch(GET_OPCODE(*last)) { |
59 | } | 53 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; |
60 | break; | 54 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); |
55 | } | ||
56 | } | ||
61 | 57 | ||
62 | case RETCODE: | ||
63 | switch(GET_OPCODE(*last)) { | ||
64 | case CALL: | ||
65 | *last = SET_OPCODE(*last, TAILCALL); | ||
66 | *last = SETARG_B(*last, GETARG_U(i)); | ||
67 | break; | ||
68 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
69 | } | ||
70 | break; | ||
71 | 58 | ||
72 | case ADDOP: | 59 | static void luaK_add (LexState *ls, expdesc *v) { |
73 | switch(GET_OPCODE(*last)) { | 60 | Instruction *last = last_i(ls, v); |
74 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; | 61 | luaK_deltastack(ls, -1); |
75 | default: fs->last_pc = luaK_primitivecode(ls, i); | 62 | switch(GET_OPCODE(*last)) { |
76 | } | 63 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; |
77 | break; | 64 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); |
65 | } | ||
66 | } | ||
67 | |||
78 | 68 | ||
79 | case SUBOP: | 69 | static void luaK_sub (LexState *ls, expdesc *v) { |
80 | switch(GET_OPCODE(*last)) { | 70 | Instruction *last = last_i(ls, v); |
81 | case PUSHINT: | 71 | luaK_deltastack(ls, -1); |
82 | *last = SET_OPCODE(*last, ADDI); | 72 | switch(GET_OPCODE(*last)) { |
83 | *last = SETARG_S(*last, -GETARG_S(*last)); | 73 | case PUSHINT: |
84 | break; | 74 | *last = SET_OPCODE(*last, ADDI); |
85 | default: fs->last_pc = luaK_primitivecode(ls, i); | 75 | *last = SETARG_S(*last, -GETARG_S(*last)); |
86 | } | ||
87 | break; | 76 | break; |
77 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); | ||
78 | } | ||
79 | } | ||
88 | 80 | ||
89 | default: fs->last_pc = luaK_primitivecode(ls, i); | 81 | |
82 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { | ||
83 | if (e->n > 0 && luaK_iscall(ls, e->info)) { | ||
84 | Instruction *last = &ls->fs->f->code[ls->fs->pc-1]; | ||
85 | *last = SET_OPCODE(*last, TAILCALL); | ||
86 | *last = SETARG_B(*last, nlocals); | ||
90 | } | 87 | } |
91 | return fs->last_pc; | 88 | else |
89 | luaK_U(ls, RETCODE, nlocals, 0); | ||
90 | } | ||
91 | |||
92 | |||
93 | int luaK_code (LexState *ls, Instruction i, int delta) { | ||
94 | luaK_deltastack(ls, delta); | ||
95 | return luaK_primitivecode(ls, i); | ||
92 | } | 96 | } |
93 | 97 | ||
94 | 98 | ||
@@ -97,7 +101,6 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { | |||
97 | Instruction *jmp = &fs->f->code[pc]; | 101 | Instruction *jmp = &fs->f->code[pc]; |
98 | /* jump is relative to position following jump instruction */ | 102 | /* jump is relative to position following jump instruction */ |
99 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | 103 | *jmp = SETARG_S(*jmp, dest-(pc+1)); |
100 | fs->last_pc = pc; | ||
101 | } | 104 | } |
102 | 105 | ||
103 | 106 | ||
@@ -112,38 +115,8 @@ void luaK_deltastack (LexState *ls, int delta) { | |||
112 | } | 115 | } |
113 | 116 | ||
114 | 117 | ||
115 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { | 118 | void luaK_kstr (LexState *ls, int c) { |
116 | luaK_deltastack(ls, delta); | 119 | luaK_U(ls, PUSHSTRING, c, 1); |
117 | return luaK_code(ls, SET_OPCODE(i, op)); | ||
118 | } | ||
119 | |||
120 | |||
121 | int luaK_0 (LexState *ls, OpCode op, int delta) { | ||
122 | return aux_code(ls, op, 0, delta); | ||
123 | } | ||
124 | |||
125 | |||
126 | int luaK_U (LexState *ls, OpCode op, int u, int delta) { | ||
127 | Instruction i = SETARG_U(0, u); | ||
128 | return aux_code(ls, op, i, delta); | ||
129 | } | ||
130 | |||
131 | |||
132 | int luaK_S (LexState *ls, OpCode op, int s, int delta) { | ||
133 | Instruction i = SETARG_S(0, s); | ||
134 | return aux_code(ls, op, i, delta); | ||
135 | } | ||
136 | |||
137 | |||
138 | int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta) { | ||
139 | Instruction i = SETARG_A(0, a); | ||
140 | i = SETARG_B(i, b); | ||
141 | return aux_code(ls, op, i, delta); | ||
142 | } | ||
143 | |||
144 | |||
145 | int luaK_kstr (LexState *ls, int c) { | ||
146 | return luaK_U(ls, PUSHSTRING, c, 1); | ||
147 | } | 120 | } |
148 | 121 | ||
149 | 122 | ||
@@ -166,37 +139,40 @@ static int real_constant (LexState *ls, real r) { | |||
166 | } | 139 | } |
167 | 140 | ||
168 | 141 | ||
169 | int luaK_number (LexState *ls, real f) { | 142 | void luaK_number (LexState *ls, real f) { |
170 | if (f <= (real)MAXARG_S && (int)f == f) | 143 | if (f <= (real)MAXARG_S && (int)f == f) |
171 | return luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ | 144 | luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ |
172 | else | 145 | else |
173 | return luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); | 146 | luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); |
174 | } | 147 | } |
175 | 148 | ||
176 | 149 | ||
177 | int luaK_adjuststack (LexState *ls, int n) { | 150 | void luaK_adjuststack (LexState *ls, int n) { |
178 | if (n > 0) | 151 | if (n > 0) |
179 | return luaK_U(ls, POP, n, -n); | 152 | luaK_U(ls, POP, n, -n); |
180 | else if (n < 0) | 153 | else if (n < 0) |
181 | return luaK_U(ls, PUSHNIL, (-n)-1, -n); | 154 | luaK_U(ls, PUSHNIL, (-n)-1, -n); |
182 | else return 0; | ||
183 | } | 155 | } |
184 | 156 | ||
185 | 157 | ||
186 | int luaK_iscall (LexState *ls, int pc) { | 158 | int luaK_iscall (LexState *ls, int hasjumps) { |
187 | return (GET_OPCODE(ls->fs->f->code[pc]) == CALL); | 159 | if (hasjumps) return 0; /* a call cannot have internal jumps */ |
160 | else /* check whether last instruction is a function call */ | ||
161 | return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL); | ||
188 | } | 162 | } |
189 | 163 | ||
190 | 164 | ||
191 | void luaK_setcallreturns (LexState *ls, int pc, int nresults) { | 165 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { |
192 | if (luaK_iscall(ls, pc)) { /* expression is a function call? */ | 166 | if (!hasjumps) { /* if `hasjumps' cannot be a function call */ |
193 | Instruction *i = &ls->fs->f->code[pc]; | 167 | Instruction *i = &ls->fs->f->code[ls->fs->pc-1]; |
194 | int old_nresults = GETARG_B(*i); | 168 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ |
195 | if (old_nresults != MULT_RET) | 169 | int old_nresults = GETARG_B(*i); |
196 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ | 170 | if (old_nresults != MULT_RET) |
197 | *i = SETARG_B(*i, nresults); /* set nresults */ | 171 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ |
198 | if (nresults != MULT_RET) | 172 | *i = SETARG_B(*i, nresults); /* set nresults */ |
199 | luaK_deltastack(ls, nresults); /* push results */ | 173 | if (nresults != MULT_RET) |
174 | luaK_deltastack(ls, nresults); /* push results */ | ||
175 | } | ||
200 | } | 176 | } |
201 | } | 177 | } |
202 | 178 | ||
@@ -209,20 +185,21 @@ static void assertglobal (LexState *ls, int index) { | |||
209 | void luaK_2stack (LexState *ls, expdesc *var) { | 185 | void luaK_2stack (LexState *ls, expdesc *var) { |
210 | switch (var->k) { | 186 | switch (var->k) { |
211 | case VLOCAL: | 187 | case VLOCAL: |
212 | var->info = luaK_U(ls, PUSHLOCAL, var->info, 1); | 188 | luaK_U(ls, PUSHLOCAL, var->info, 1); |
213 | break; | 189 | break; |
214 | case VGLOBAL: | 190 | case VGLOBAL: |
191 | luaK_U(ls, GETGLOBAL, var->info, 1); | ||
215 | assertglobal(ls, var->info); /* make sure that there is a global */ | 192 | assertglobal(ls, var->info); /* make sure that there is a global */ |
216 | var->info = luaK_U(ls, GETGLOBAL, var->info, 1); | ||
217 | break; | 193 | break; |
218 | case VINDEXED: | 194 | case VINDEXED: |
219 | var->info = luaK_0(ls, GETTABLE, -1); | 195 | luaK_gettable(ls, var); |
220 | break; | 196 | break; |
221 | case VEXP: | 197 | case VEXP: |
222 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ | 198 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ |
223 | break; | 199 | return; /* does not change var->info */ |
224 | } | 200 | } |
225 | var->k = VEXP; | 201 | var->k = VEXP; |
202 | var->info = NOJUMPS; | ||
226 | } | 203 | } |
227 | 204 | ||
228 | 205 | ||
@@ -246,10 +223,9 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
246 | 223 | ||
247 | void luaK_prefix (LexState *ls, int op, expdesc *v) { | 224 | void luaK_prefix (LexState *ls, int op, expdesc *v) { |
248 | luaK_2stack(ls, v); | 225 | luaK_2stack(ls, v); |
249 | if (op == '-') | 226 | if (op == '-') luaK_minus(ls, v); |
250 | v->info = luaK_0(ls, MINUSOP, 0); | 227 | else luaK_0(ls, NOTOP, 0); |
251 | else | 228 | v->info = NOJUMPS; |
252 | v->info = luaK_0(ls, NOTOP, 0); | ||
253 | } | 229 | } |
254 | 230 | ||
255 | 231 | ||
@@ -267,19 +243,20 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
267 | switch (op) { | 243 | switch (op) { |
268 | case AND: case OR: | 244 | case AND: case OR: |
269 | luaK_fixjump(ls, v1->info, ls->fs->pc); | 245 | luaK_fixjump(ls, v1->info, ls->fs->pc); |
270 | break; | 246 | return; /* keep v1->info != NOJUMPS */ |
271 | case '+': v1->info = luaK_0(ls, ADDOP, -1); break; | 247 | case '+': luaK_add(ls, v2); break; |
272 | case '-': v1->info = luaK_0(ls, SUBOP, -1); break; | 248 | case '-': luaK_sub(ls, v2); break; |
273 | case '*': v1->info = luaK_0(ls, MULTOP, -1); break; | 249 | case '*': luaK_0(ls, MULTOP, -1); break; |
274 | case '/': v1->info = luaK_0(ls, DIVOP, -1); break; | 250 | case '/': luaK_0(ls, DIVOP, -1); break; |
275 | case '^': v1->info = luaK_0(ls, POWOP, -1); break; | 251 | case '^': luaK_0(ls, POWOP, -1); break; |
276 | case CONC: v1->info = luaK_0(ls, CONCOP, -1); break; | 252 | case CONC: luaK_0(ls, CONCOP, -1); break; |
277 | case EQ: v1->info = luaK_0(ls, EQOP, -1); break; | 253 | case EQ: luaK_0(ls, EQOP, -1); break; |
278 | case NE: v1->info = luaK_0(ls, NEQOP, -1); break; | 254 | case NE: luaK_0(ls, NEQOP, -1); break; |
279 | case '>': v1->info = luaK_0(ls, GTOP, -1); break; | 255 | case '>': luaK_0(ls, GTOP, -1); break; |
280 | case '<': v1->info = luaK_0(ls, LTOP, -1); break; | 256 | case '<': luaK_0(ls, LTOP, -1); break; |
281 | case GE: v1->info = luaK_0(ls, GEOP, -1); break; | 257 | case GE: luaK_0(ls, GEOP, -1); break; |
282 | case LE: v1->info = luaK_0(ls, LEOP, -1); break; | 258 | case LE: luaK_0(ls, LEOP, -1); break; |
283 | } | 259 | } |
260 | v1->info = NOJUMPS; | ||
284 | } | 261 | } |
285 | 262 | ||