diff options
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 69 |
1 files changed, 39 insertions, 30 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 roberto Exp $ |
| 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 | */ |
| @@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | void luaK_ret (FuncState *fs, int first, int nret) { | ||
| 57 | luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); | ||
| 58 | } | ||
| 59 | |||
| 60 | |||
| 56 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { | 61 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { |
| 57 | luaK_codeABC(fs, op, A, B, C); | 62 | luaK_codeABC(fs, op, A, B, C); |
| 58 | return luaK_jump(fs); | 63 | return luaK_jump(fs); |
| @@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { | |||
| 101 | ** check whether list has any jump that do not produce a value | 106 | ** check whether list has any jump that do not produce a value |
| 102 | ** (or produce an inverted value) | 107 | ** (or produce an inverted value) |
| 103 | */ | 108 | */ |
| 104 | static int need_value (FuncState *fs, int list, int cond) { | 109 | static int need_value (FuncState *fs, int list) { |
| 105 | for (; list != NO_JUMP; list = getjump(fs, list)) { | 110 | for (; list != NO_JUMP; list = getjump(fs, list)) { |
| 106 | Instruction i = *getjumpcontrol(fs, list); | 111 | Instruction i = *getjumpcontrol(fs, list); |
| 107 | if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; | 112 | if (GET_OPCODE(i) != OP_TESTSET) return 1; |
| 108 | } | 113 | } |
| 109 | return 0; /* not found */ | 114 | return 0; /* not found */ |
| 110 | } | 115 | } |
| 111 | 116 | ||
| 112 | 117 | ||
| 113 | static void patchtestreg (Instruction *i, int reg) { | 118 | static void patchtestreg (Instruction *i, int reg) { |
| 114 | if (reg == NO_REG) reg = GETARG_B(*i); | 119 | if (reg != NO_REG) |
| 115 | SETARG_A(*i, reg); | 120 | SETARG_A(*i, reg); |
| 121 | else /* no register to put value; change TESTSET to TEST */ | ||
| 122 | *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); | ||
| 116 | } | 123 | } |
| 117 | 124 | ||
| 118 | 125 | ||
| 119 | static void patchlistaux (FuncState *fs, int list, | 126 | static void removevalues (FuncState *fs, int list) { |
| 120 | int ttarget, int treg, int ftarget, int freg, int dtarget) { | 127 | for (; list != NO_JUMP; list = getjump(fs, list)) { |
| 128 | Instruction *i = getjumpcontrol(fs, list); | ||
| 129 | if (GET_OPCODE(*i) == OP_TESTSET) | ||
| 130 | patchtestreg(i, NO_REG); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | |||
| 135 | static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, | ||
| 136 | int dtarget) { | ||
| 121 | while (list != NO_JUMP) { | 137 | while (list != NO_JUMP) { |
| 122 | int next = getjump(fs, list); | 138 | int next = getjump(fs, list); |
| 123 | Instruction *i = getjumpcontrol(fs, list); | 139 | Instruction *i = getjumpcontrol(fs, list); |
| 124 | if (GET_OPCODE(*i) != OP_TEST) { | 140 | if (GET_OPCODE(*i) == OP_TESTSET) { |
| 125 | lua_assert(dtarget != NO_JUMP); | 141 | patchtestreg(i, reg); |
| 126 | fixjump(fs, list, dtarget); /* jump to default target */ | 142 | fixjump(fs, list, vtarget); |
| 127 | } | ||
| 128 | else { | ||
| 129 | if (GETARG_C(*i)) { | ||
| 130 | lua_assert(ttarget != NO_JUMP); | ||
| 131 | patchtestreg(i, treg); | ||
| 132 | fixjump(fs, list, ttarget); | ||
| 133 | } | ||
| 134 | else { | ||
| 135 | lua_assert(ftarget != NO_JUMP); | ||
| 136 | patchtestreg(i, freg); | ||
| 137 | fixjump(fs, list, ftarget); | ||
| 138 | } | ||
| 139 | } | 143 | } |
| 144 | else | ||
| 145 | fixjump(fs, list, dtarget); /* jump to default target */ | ||
| 140 | list = next; | 146 | list = next; |
| 141 | } | 147 | } |
| 142 | } | 148 | } |
| 143 | 149 | ||
| 144 | 150 | ||
| 145 | static void dischargejpc (FuncState *fs) { | 151 | static void dischargejpc (FuncState *fs) { |
| 146 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); | 152 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); |
| 147 | fs->jpc = NO_JUMP; | 153 | fs->jpc = NO_JUMP; |
| 148 | } | 154 | } |
| 149 | 155 | ||
| @@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
| 153 | luaK_patchtohere(fs, list); | 159 | luaK_patchtohere(fs, list); |
| 154 | else { | 160 | else { |
| 155 | lua_assert(target < fs->pc); | 161 | lua_assert(target < fs->pc); |
| 156 | patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); | 162 | patchlistaux(fs, list, target, NO_REG, target); |
| 157 | } | 163 | } |
| 158 | } | 164 | } |
| 159 | 165 | ||
| @@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 373 | int final; /* position after whole expression */ | 379 | int final; /* position after whole expression */ |
| 374 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 380 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
| 375 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ | 381 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
| 376 | if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { | 382 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
| 377 | int fj = NO_JUMP; /* first jump (over LOAD ops.) */ | 383 | int fj = NO_JUMP; /* first jump (over LOAD ops.) */ |
| 378 | if (e->k != VJMP) | 384 | if (e->k != VJMP) |
| 379 | fj = luaK_jump(fs); | 385 | fj = luaK_jump(fs); |
| @@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 382 | luaK_patchtohere(fs, fj); | 388 | luaK_patchtohere(fs, fj); |
| 383 | } | 389 | } |
| 384 | final = luaK_getlabel(fs); | 390 | final = luaK_getlabel(fs); |
| 385 | patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); | 391 | patchlistaux(fs, e->f, final, reg, p_f); |
| 386 | patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); | 392 | patchlistaux(fs, e->t, final, reg, p_t); |
| 387 | } | 393 | } |
| 388 | e->f = e->t = NO_JUMP; | 394 | e->f = e->t = NO_JUMP; |
| 389 | e->info = reg; | 395 | e->info = reg; |
| @@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
| 492 | 498 | ||
| 493 | static void invertjump (FuncState *fs, expdesc *e) { | 499 | static void invertjump (FuncState *fs, expdesc *e) { |
| 494 | Instruction *pc = getjumpcontrol(fs, e->info); | 500 | Instruction *pc = getjumpcontrol(fs, e->info); |
| 495 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST); | 501 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
| 502 | GET_OPCODE(*pc) != OP_TEST); | ||
| 496 | SETARG_A(*pc, !(GETARG_A(*pc))); | 503 | SETARG_A(*pc, !(GETARG_A(*pc))); |
| 497 | } | 504 | } |
| 498 | 505 | ||
| @@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
| 502 | Instruction ie = getcode(fs, e); | 509 | Instruction ie = getcode(fs, e); |
| 503 | if (GET_OPCODE(ie) == OP_NOT) { | 510 | if (GET_OPCODE(ie) == OP_NOT) { |
| 504 | fs->pc--; /* remove previous OP_NOT */ | 511 | fs->pc--; /* remove previous OP_NOT */ |
| 505 | return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); | 512 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); |
| 506 | } | 513 | } |
| 507 | /* else go through */ | 514 | /* else go through */ |
| 508 | } | 515 | } |
| 509 | discharge2anyreg(fs, e); | 516 | discharge2anyreg(fs, e); |
| 510 | freeexp(fs, e); | 517 | freeexp(fs, e); |
| 511 | return condjump(fs, OP_TEST, NO_REG, e->info, cond); | 518 | return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); |
| 512 | } | 519 | } |
| 513 | 520 | ||
| 514 | 521 | ||
| @@ -597,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
| 597 | } | 604 | } |
| 598 | /* interchange true and false lists */ | 605 | /* interchange true and false lists */ |
| 599 | { int temp = e->f; e->f = e->t; e->t = temp; } | 606 | { int temp = e->f; e->f = e->t; e->t = temp; } |
| 607 | removevalues(fs, e->f); | ||
| 608 | removevalues(fs, e->t); | ||
| 600 | } | 609 | } |
| 601 | 610 | ||
| 602 | 611 | ||
