diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 55 |
1 files changed, 39 insertions, 16 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.20 2000/04/05 17:51:58 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.21 2000/04/06 17:36:52 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 | */ |
@@ -88,9 +88,11 @@ static void luaK_minus (FuncState *fs) { | |||
88 | 88 | ||
89 | static void luaK_gettable (FuncState *fs) { | 89 | static void luaK_gettable (FuncState *fs) { |
90 | /* PUSHSTRING u; GETTABLE -> GETDOTTED u (t.x) */ | 90 | /* PUSHSTRING u; GETTABLE -> GETDOTTED u (t.x) */ |
91 | /* GETLOCAL u; GETTABLE -> GETINDEXED u (t[i]) */ | ||
91 | Instruction previous = prepare(fs, CREATE_0(OP_GETTABLE), -1); | 92 | Instruction previous = prepare(fs, CREATE_0(OP_GETTABLE), -1); |
92 | switch(GET_OPCODE(previous)) { | 93 | switch(GET_OPCODE(previous)) { |
93 | case OP_PUSHSTRING: SET_OPCODE(previous, OP_GETDOTTED); break; | 94 | case OP_PUSHSTRING: SET_OPCODE(previous, OP_GETDOTTED); break; |
95 | case OP_GETLOCAL: SET_OPCODE(previous, OP_GETINDEXED); break; | ||
94 | default: return; | 96 | default: return; |
95 | } | 97 | } |
96 | setprevious(fs, previous); | 98 | setprevious(fs, previous); |
@@ -123,22 +125,32 @@ static void luaK_sub (FuncState *fs) { | |||
123 | 125 | ||
124 | 126 | ||
125 | static void luaK_conc (FuncState *fs) { | 127 | static void luaK_conc (FuncState *fs) { |
126 | /* CONC u; CONC 2 -> CONC u+1 (a..b..c) */ | 128 | /* CONCAT u; CONCAT 2 -> CONCAT u+1 (a..b..c) */ |
127 | Instruction previous = prepare(fs, CREATE_U(OP_CONC, 2), -1); | 129 | Instruction previous = prepare(fs, CREATE_U(OP_CONCAT, 2), -1); |
128 | switch(GET_OPCODE(previous)) { | 130 | switch(GET_OPCODE(previous)) { |
129 | case OP_CONC: SETARG_U(previous, GETARG_U(previous)+1); break; | 131 | case OP_CONCAT: SETARG_U(previous, GETARG_U(previous)+1); break; |
130 | default: return; | 132 | default: return; |
131 | } | 133 | } |
132 | setprevious(fs, previous); | 134 | setprevious(fs, previous); |
133 | } | 135 | } |
134 | 136 | ||
135 | 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 | |||
136 | static void luaK_setlocal (FuncState *fs, int l) { | 148 | static void luaK_setlocal (FuncState *fs, int l) { |
137 | /* PUSHLOCAL l; ADDI k, SETLOCAL l -> INCLOCAL k, l ((local)a=a+k) */ | 149 | /* GETLOCAL l; ADDI k, SETLOCAL l -> INCLOCAL k, l ((local)a=a+k) */ |
138 | Instruction *code = fs->f->code; | 150 | Instruction *code = fs->f->code; |
139 | int pc = fs->pc; | 151 | int pc = fs->pc; |
140 | if (pc-1 > fs->lasttarget && /* no jumps in-between instructions? */ | 152 | if (pc-1 > fs->lasttarget && /* no jumps in-between instructions? */ |
141 | code[pc-2] == CREATE_U(OP_PUSHLOCAL, l) && | 153 | code[pc-2] == CREATE_U(OP_GETLOCAL, l) && |
142 | GET_OPCODE(code[pc-1]) == OP_ADDI && | 154 | GET_OPCODE(code[pc-1]) == OP_ADDI && |
143 | abs(GETARG_S(code[pc-1])) <= MAXARG_sA) { | 155 | abs(GETARG_S(code[pc-1])) <= MAXARG_sA) { |
144 | int inc = GETARG_S(code[pc-1]); | 156 | int inc = GETARG_S(code[pc-1]); |
@@ -147,7 +159,7 @@ static void luaK_setlocal (FuncState *fs, int l) { | |||
147 | luaK_deltastack(fs, -1); | 159 | luaK_deltastack(fs, -1); |
148 | } | 160 | } |
149 | else | 161 | else |
150 | luaK_U(fs, OP_SETLOCAL, l, -1); | 162 | luaK_AB(fs, OP_SETLOCAL, l, 1, -1); |
151 | } | 163 | } |
152 | 164 | ||
153 | 165 | ||
@@ -162,8 +174,8 @@ static void luaK_eq (FuncState *fs) { | |||
162 | 174 | ||
163 | 175 | ||
164 | static void luaK_neq (FuncState *fs) { | 176 | static void luaK_neq (FuncState *fs) { |
165 | /* PUSHNIL 1; JMPNEQ -> JMPT (a~=nil) */ | 177 | /* PUSHNIL 1; JMPNE -> JMPT (a~=nil) */ |
166 | Instruction previous = prepare(fs, CREATE_S(OP_JMPNEQ, NO_JUMP), -2); | 178 | Instruction previous = prepare(fs, CREATE_S(OP_JMPNE, NO_JUMP), -2); |
167 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { | 179 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { |
168 | setprevious(fs, CREATE_S(OP_JMPT, NO_JUMP)); | 180 | setprevious(fs, CREATE_S(OP_JMPT, NO_JUMP)); |
169 | } | 181 | } |
@@ -201,6 +213,17 @@ static void luaK_pushnil (FuncState *fs, int n) { | |||
201 | } | 213 | } |
202 | 214 | ||
203 | 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 | |||
204 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 227 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
205 | Instruction *jmp = &fs->f->code[pc]; | 228 | Instruction *jmp = &fs->f->code[pc]; |
206 | if (dest == NO_JUMP) | 229 | if (dest == NO_JUMP) |
@@ -280,7 +303,7 @@ void luaK_number (FuncState *fs, Number f) { | |||
280 | 303 | ||
281 | void luaK_adjuststack (FuncState *fs, int n) { | 304 | void luaK_adjuststack (FuncState *fs, int n) { |
282 | if (n > 0) | 305 | if (n > 0) |
283 | luaK_U(fs, OP_POP, n, -n); | 306 | luaK_pop(fs, n); |
284 | else if (n < 0) | 307 | else if (n < 0) |
285 | luaK_pushnil(fs, -n); | 308 | luaK_pushnil(fs, -n); |
286 | } | 309 | } |
@@ -311,7 +334,7 @@ static void assertglobal (FuncState *fs, int index) { | |||
311 | static int discharge (FuncState *fs, expdesc *var) { | 334 | static int discharge (FuncState *fs, expdesc *var) { |
312 | switch (var->k) { | 335 | switch (var->k) { |
313 | case VLOCAL: | 336 | case VLOCAL: |
314 | luaK_U(fs, OP_PUSHLOCAL, var->u.index, 1); | 337 | luaK_getlocal(fs, var->u.index); |
315 | break; | 338 | break; |
316 | case VGLOBAL: | 339 | case VGLOBAL: |
317 | luaK_U(fs, OP_GETGLOBAL, var->u.index, 1); | 340 | luaK_U(fs, OP_GETGLOBAL, var->u.index, 1); |
@@ -347,8 +370,8 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
347 | luaK_U(fs, OP_SETGLOBAL, var->u.index, -1); | 370 | luaK_U(fs, OP_SETGLOBAL, var->u.index, -1); |
348 | assertglobal(fs, var->u.index); /* make sure that there is a global */ | 371 | assertglobal(fs, var->u.index); /* make sure that there is a global */ |
349 | break; | 372 | break; |
350 | case VINDEXED: | 373 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ |
351 | luaK_0(fs, OP_SETTABLEPOP, -3); | 374 | luaK_AB(fs, OP_SETTABLE, 3, 3, -3); |
352 | break; | 375 | break; |
353 | default: | 376 | default: |
354 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); | 377 | LUA_INTERNALERROR(ls->L, "invalid var kind to store"); |
@@ -358,8 +381,8 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
358 | 381 | ||
359 | static OpCode invertjump (OpCode op) { | 382 | static OpCode invertjump (OpCode op) { |
360 | switch (op) { | 383 | switch (op) { |
361 | case OP_JMPNEQ: return OP_JMPEQ; | 384 | case OP_JMPNE: return OP_JMPEQ; |
362 | case OP_JMPEQ: return OP_JMPNEQ; | 385 | case OP_JMPEQ: return OP_JMPNE; |
363 | case OP_JMPLT: return OP_JMPGE; | 386 | case OP_JMPLT: return OP_JMPGE; |
364 | case OP_JMPLE: return OP_JMPGT; | 387 | case OP_JMPLE: return OP_JMPGT; |
365 | case OP_JMPGT: return OP_JMPLE; | 388 | case OP_JMPGT: return OP_JMPLE; |
@@ -566,7 +589,7 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
566 | case '*': luaK_0(fs, OP_MULT, -1); break; | 589 | case '*': luaK_0(fs, OP_MULT, -1); break; |
567 | case '/': luaK_0(fs, OP_DIV, -1); break; | 590 | case '/': luaK_0(fs, OP_DIV, -1); break; |
568 | case '^': luaK_0(fs, OP_POW, -1); break; | 591 | case '^': luaK_0(fs, OP_POW, -1); break; |
569 | case TK_CONC: luaK_conc(fs); break; | 592 | case TK_CONCAT: luaK_conc(fs); break; |
570 | case TK_EQ: luaK_eq(fs); break; | 593 | case TK_EQ: luaK_eq(fs); break; |
571 | case TK_NE: luaK_neq(fs); break; | 594 | case TK_NE: luaK_neq(fs); break; |
572 | case '>': luaK_S(fs, OP_JMPGT, NO_JUMP, -2); break; | 595 | case '>': luaK_S(fs, OP_JMPGT, NO_JUMP, -2); break; |