diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-10 16:22:11 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-10 16:22:11 -0300 |
| commit | 2dadc8182282afa4b1fe6e6287704a54cd8e5123 (patch) | |
| tree | 933eef764dba4636de1e8afcde10e0dc9a052f33 /lcode.c | |
| parent | b487975344ee90c0410e79e1af08461bdbc0f3da (diff) | |
| download | lua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.tar.gz lua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.tar.bz2 lua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.zip | |
cleaner implementation of code generation for jumps
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 65 |
1 files changed, 28 insertions, 37 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.100 2002/05/09 14:14:34 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.101 2002/05/10 17:02:32 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 | */ |
| @@ -39,58 +39,48 @@ void luaK_nil (FuncState *fs, int from, int n) { | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | 41 | ||
| 42 | void luaK_moveexp (expdesc *e, int offset) { | ||
| 43 | if (e->t != NO_JUMP) e->t += offset; | ||
| 44 | if (e->f != NO_JUMP) e->f += offset; | ||
| 45 | if (e->k == VRELOCABLE || e->k == VJMP) e->info += offset; | ||
| 46 | } | ||
| 47 | |||
| 48 | |||
| 49 | int luaK_jump (FuncState *fs) { | 42 | int luaK_jump (FuncState *fs) { |
| 50 | int j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); | 43 | int jpc = fs->jpc; /* save list of jumps to here */ |
| 51 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 44 | int j; |
| 52 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 45 | fs->jpc = NO_JUMP; |
| 53 | fs->jlt = NO_JUMP; | 46 | j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); |
| 54 | } | 47 | luaK_concat(fs, &j, jpc); /* keep them on hold */ |
| 55 | return j; | 48 | return j; |
| 56 | } | 49 | } |
| 57 | 50 | ||
| 58 | 51 | ||
| 59 | static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { | 52 | static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { |
| 60 | luaK_codeABC(fs, op, A, B, C); | 53 | luaK_codeABC(fs, op, A, B, C); |
| 61 | return luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); | 54 | return luaK_jump(fs); |
| 62 | } | 55 | } |
| 63 | 56 | ||
| 64 | 57 | ||
| 65 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 58 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
| 66 | Instruction *jmp = &fs->f->code[pc]; | 59 | Instruction *jmp = &fs->f->code[pc]; |
| 67 | if (dest == NO_JUMP) | 60 | int offset = dest-(pc+1); |
| 68 | SETARG_sBx(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 61 | lua_assert(dest != NO_JUMP); |
| 69 | else { /* jump is relative to position following jump instruction */ | 62 | if (abs(offset) > MAXARG_sBx) |
| 70 | int offset = dest-(pc+1); | 63 | luaX_syntaxerror(fs->ls, "control structure too long"); |
| 71 | if (abs(offset) > MAXARG_sBx) | 64 | SETARG_sBx(*jmp, offset); |
| 72 | luaX_syntaxerror(fs->ls, "control structure too long"); | ||
| 73 | SETARG_sBx(*jmp, offset); | ||
| 74 | } | ||
| 75 | } | 65 | } |
| 76 | 66 | ||
| 77 | 67 | ||
| 78 | /* | 68 | /* |
| 79 | ** returns current `pc' and marks it as a jump target (to avoid wrong | 69 | ** returns current `pc' and marks it as a jump target (to avoid wrong |
| 80 | ** optimizations with consecutive instructions not in the same basic block). | 70 | ** optimizations with consecutive instructions not in the same basic block). |
| 81 | ** discharge list of jumps to last target. | ||
| 82 | */ | 71 | */ |
| 83 | int luaK_getlabel (FuncState *fs) { | 72 | int luaK_getlabel (FuncState *fs) { |
| 84 | if (fs->pc != fs->lasttarget) { | 73 | fs->lasttarget = fs->pc; |
| 85 | int lasttarget = fs->lasttarget; | ||
| 86 | fs->lasttarget = fs->pc; | ||
| 87 | luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ | ||
| 88 | fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ | ||
| 89 | } | ||
| 90 | return fs->pc; | 74 | return fs->pc; |
| 91 | } | 75 | } |
| 92 | 76 | ||
| 93 | 77 | ||
| 78 | void luaK_dischargejpc (FuncState *fs) { | ||
| 79 | luaK_patchlist(fs, fs->jpc, fs->pc); /* discharge old list `jpc' */ | ||
| 80 | fs->jpc = NO_JUMP; | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 94 | static int luaK_getjump (FuncState *fs, int pc) { | 84 | static int luaK_getjump (FuncState *fs, int pc) { |
| 95 | int offset = GETARG_sBx(fs->f->code[pc]); | 85 | int offset = GETARG_sBx(fs->f->code[pc]); |
| 96 | if (offset == NO_JUMP) /* point to itself represents end of list */ | 86 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
| @@ -155,20 +145,20 @@ static void luaK_patchlistaux (FuncState *fs, int list, | |||
| 155 | 145 | ||
| 156 | 146 | ||
| 157 | void luaK_patchlist (FuncState *fs, int list, int target) { | 147 | void luaK_patchlist (FuncState *fs, int list, int target) { |
| 158 | if (target == fs->lasttarget) /* same target that list `jlt'? */ | 148 | lua_assert(target <= fs->pc); |
| 159 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | 149 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); |
| 160 | else | ||
| 161 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); | ||
| 162 | } | 150 | } |
| 163 | 151 | ||
| 164 | 152 | ||
| 165 | void luaK_patchtohere (FuncState *fs, int list) { | 153 | void luaK_patchtohere (FuncState *fs, int list) { |
| 166 | luaK_patchlist(fs, list, luaK_getlabel(fs)); | 154 | luaK_getlabel(fs); |
| 155 | luaK_concat(fs, &fs->jpc, list); | ||
| 167 | } | 156 | } |
| 168 | 157 | ||
| 169 | 158 | ||
| 170 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 159 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
| 171 | if (*l1 == NO_JUMP) | 160 | if (l2 == NO_JUMP) return; |
| 161 | else if (*l1 == NO_JUMP) | ||
| 172 | *l1 = l2; | 162 | *l1 = l2; |
| 173 | else { | 163 | else { |
| 174 | int list = *l1; | 164 | int list = *l1; |
| @@ -508,7 +498,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
| 508 | break; | 498 | break; |
| 509 | } | 499 | } |
| 510 | case VFALSE: { | 500 | case VFALSE: { |
| 511 | pc = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); /* always jump */ | 501 | pc = luaK_jump(fs); /* always jump */ |
| 512 | break; | 502 | break; |
| 513 | } | 503 | } |
| 514 | case VJMP: { | 504 | case VJMP: { |
| @@ -534,7 +524,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
| 534 | break; | 524 | break; |
| 535 | } | 525 | } |
| 536 | case VTRUE: { | 526 | case VTRUE: { |
| 537 | pc = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); /* always jump */ | 527 | pc = luaK_jump(fs); /* always jump */ |
| 538 | break; | 528 | break; |
| 539 | } | 529 | } |
| 540 | case VJMP: { | 530 | case VJMP: { |
| @@ -737,6 +727,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |||
| 737 | int luaK_code (FuncState *fs, Instruction i, int line) { | 727 | int luaK_code (FuncState *fs, Instruction i, int line) { |
| 738 | Proto *f = fs->f; | 728 | Proto *f = fs->f; |
| 739 | int oldsize = f->sizecode; | 729 | int oldsize = f->sizecode; |
| 730 | luaK_dischargejpc(fs); /* `pc' will change */ | ||
| 740 | /* put new instruction in code array */ | 731 | /* put new instruction in code array */ |
| 741 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | 732 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, |
| 742 | MAX_INT, "code size overflow"); | 733 | MAX_INT, "code size overflow"); |
