diff options
| -rw-r--r-- | lcode.c | 65 | ||||
| -rw-r--r-- | lcode.h | 4 | ||||
| -rw-r--r-- | lparser.c | 26 | ||||
| -rw-r--r-- | lparser.h | 4 |
4 files changed, 46 insertions, 53 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"); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.h,v 1.33 2002/05/07 17:36:56 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.34 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 | */ |
| @@ -55,12 +55,12 @@ void luaK_exp2val (FuncState *fs, expdesc *e); | |||
| 55 | int luaK_exp2RK (FuncState *fs, expdesc *e); | 55 | int luaK_exp2RK (FuncState *fs, expdesc *e); |
| 56 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | 56 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key); |
| 57 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | 57 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); |
| 58 | void luaK_moveexp (expdesc *e, int offset); | ||
| 59 | void luaK_goiftrue (FuncState *fs, expdesc *e); | 58 | void luaK_goiftrue (FuncState *fs, expdesc *e); |
| 60 | void luaK_goiffalse (FuncState *fs, expdesc *e); | 59 | void luaK_goiffalse (FuncState *fs, expdesc *e); |
| 61 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | 60 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); |
| 62 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | 61 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); |
| 63 | int luaK_jump (FuncState *fs); | 62 | int luaK_jump (FuncState *fs); |
| 63 | void luaK_dischargejpc (FuncState *fs); | ||
| 64 | void luaK_patchlist (FuncState *fs, int list, int target); | 64 | void luaK_patchlist (FuncState *fs, int list, int target); |
| 65 | void luaK_patchtohere (FuncState *fs, int list); | 65 | void luaK_patchtohere (FuncState *fs, int list); |
| 66 | void luaK_concat (FuncState *fs, int *l1, int l2); | 66 | void luaK_concat (FuncState *fs, int *l1, int l2); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.179 2002/05/07 17:36:56 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.180 2002/05/10 17:02:32 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -367,7 +367,7 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
| 367 | ls->fs = fs; | 367 | ls->fs = fs; |
| 368 | fs->pc = 0; | 368 | fs->pc = 0; |
| 369 | fs->lasttarget = 0; | 369 | fs->lasttarget = 0; |
| 370 | fs->jlt = NO_JUMP; | 370 | fs->jpc = NO_JUMP; |
| 371 | fs->freereg = 0; | 371 | fs->freereg = 0; |
| 372 | fs->nk = 0; | 372 | fs->nk = 0; |
| 373 | fs->h = luaH_new(ls->L, 0, 0); | 373 | fs->h = luaH_new(ls->L, 0, 0); |
| @@ -391,7 +391,6 @@ static void close_func (LexState *ls) { | |||
| 391 | Proto *f = fs->f; | 391 | Proto *f = fs->f; |
| 392 | removevars(ls, 0); | 392 | removevars(ls, 0); |
| 393 | luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ | 393 | luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ |
| 394 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | ||
| 395 | lua_assert(G(L)->roottable == fs->h); | 394 | lua_assert(G(L)->roottable == fs->h); |
| 396 | G(L)->roottable = fs->h->next; | 395 | G(L)->roottable = fs->h->next; |
| 397 | luaH_free(L, fs->h); | 396 | luaH_free(L, fs->h); |
| @@ -977,30 +976,33 @@ static void whilestat (LexState *ls, int line) { | |||
| 977 | int i; | 976 | int i; |
| 978 | int sizeexp; | 977 | int sizeexp; |
| 979 | FuncState *fs = ls->fs; | 978 | FuncState *fs = ls->fs; |
| 980 | int while_init = luaK_getlabel(fs); | 979 | int whileinit, blockinit, expinit; |
| 981 | expdesc v; | 980 | expdesc v; |
| 982 | BlockCnt bl; | 981 | BlockCnt bl; |
| 983 | next(ls); | 982 | next(ls); |
| 983 | whileinit = luaK_jump(fs); | ||
| 984 | expinit = luaK_getlabel(fs); | ||
| 984 | expr(ls, &v); | 985 | expr(ls, &v); |
| 985 | if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ | 986 | if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ |
| 986 | lineexp = ls->linenumber; | 987 | lineexp = ls->linenumber; |
| 987 | luaK_goiffalse(fs, &v); | 988 | luaK_goiffalse(fs, &v); |
| 988 | sizeexp = fs->pc - while_init; | 989 | luaK_dischargejpc(fs); |
| 990 | sizeexp = fs->pc - expinit; | ||
| 989 | if (sizeexp > MAXEXPWHILE) | 991 | if (sizeexp > MAXEXPWHILE) |
| 990 | luaX_syntaxerror(ls, "while condition too complex"); | 992 | luaX_syntaxerror(ls, "while condition too complex"); |
| 991 | fs->pc = while_init; /* remove `exp' code */ | ||
| 992 | luaK_getlabel(fs); | ||
| 993 | for (i = 0; i < sizeexp; i++) /* save `exp' code */ | 993 | for (i = 0; i < sizeexp; i++) /* save `exp' code */ |
| 994 | codeexp[i] = fs->f->code[while_init + i]; | 994 | codeexp[i] = fs->f->code[expinit + i]; |
| 995 | luaK_jump(fs); | 995 | fs->pc = expinit; /* remove `exp' code */ |
| 996 | enterblock(fs, &bl, 1); | 996 | enterblock(fs, &bl, 1); |
| 997 | check(ls, TK_DO); | 997 | check(ls, TK_DO); |
| 998 | blockinit = luaK_getlabel(fs); | ||
| 998 | block(ls); | 999 | block(ls); |
| 999 | luaK_patchtohere(fs, while_init); /* initial jump jumps to here */ | 1000 | luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ |
| 1000 | luaK_moveexp(&v, fs->pc - while_init); /* correct pointers */ | 1001 | if (v.t != NO_JUMP) v.t += fs->pc - expinit; |
| 1002 | if (v.f != NO_JUMP) v.f += fs->pc - expinit; | ||
| 1001 | for (i=0; i<sizeexp; i++) | 1003 | for (i=0; i<sizeexp; i++) |
| 1002 | luaK_code(fs, codeexp[i], lineexp); | 1004 | luaK_code(fs, codeexp[i], lineexp); |
| 1003 | luaK_patchlist(fs, v.t, while_init+1); | 1005 | luaK_patchlist(fs, v.t, blockinit); |
| 1004 | luaK_patchtohere(fs, v.f); | 1006 | luaK_patchtohere(fs, v.f); |
| 1005 | check_match(ls, TK_END, TK_WHILE, line); | 1007 | check_match(ls, TK_END, TK_WHILE, line); |
| 1006 | leaveblock(fs); | 1008 | leaveblock(fs); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.41 2002/03/25 17:47:14 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.42 2002/05/09 18:00:38 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -63,7 +63,7 @@ typedef struct FuncState { | |||
| 63 | struct BlockCnt *bl; /* chain of current blocks */ | 63 | struct BlockCnt *bl; /* chain of current blocks */ |
| 64 | int pc; /* next position to code (equivalent to `ncode') */ | 64 | int pc; /* next position to code (equivalent to `ncode') */ |
| 65 | int lasttarget; /* `pc' of last `jump target' */ | 65 | int lasttarget; /* `pc' of last `jump target' */ |
| 66 | int jlt; /* list of jumps to `lasttarget' */ | 66 | int jpc; /* list of jumps to `pc' */ |
| 67 | int freereg; /* first free register */ | 67 | int freereg; /* first free register */ |
| 68 | int defaultglob; /* where to look for non-declared globals */ | 68 | int defaultglob; /* where to look for non-declared globals */ |
| 69 | int nk; /* number of elements in `k' */ | 69 | int nk; /* number of elements in `k' */ |
