diff options
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"); |