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; |
