aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-10 16:22:11 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-10 16:22:11 -0300
commit2dadc8182282afa4b1fe6e6287704a54cd8e5123 (patch)
tree933eef764dba4636de1e8afcde10e0dc9a052f33
parentb487975344ee90c0410e79e1af08461bdbc0f3da (diff)
downloadlua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.tar.gz
lua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.tar.bz2
lua-2dadc8182282afa4b1fe6e6287704a54cd8e5123.zip
cleaner implementation of code generation for jumps
-rw-r--r--lcode.c65
-rw-r--r--lcode.h4
-rw-r--r--lparser.c26
-rw-r--r--lparser.h4
4 files changed, 46 insertions, 53 deletions
diff --git a/lcode.c b/lcode.c
index f72bcdb3..26a90430 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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
42void 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
49int luaK_jump (FuncState *fs) { 42int 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
59static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { 52static 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
65static void luaK_fixjump (FuncState *fs, int pc, int dest) { 58static 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*/
83int luaK_getlabel (FuncState *fs) { 72int 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
78void luaK_dischargejpc (FuncState *fs) {
79 luaK_patchlist(fs, fs->jpc, fs->pc); /* discharge old list `jpc' */
80 fs->jpc = NO_JUMP;
81}
82
83
94static int luaK_getjump (FuncState *fs, int pc) { 84static 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
157void luaK_patchlist (FuncState *fs, int list, int target) { 147void 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
165void luaK_patchtohere (FuncState *fs, int list) { 153void 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
170void luaK_concat (FuncState *fs, int *l1, int l2) { 159void 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) {
737int luaK_code (FuncState *fs, Instruction i, int line) { 727int 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");
diff --git a/lcode.h b/lcode.h
index 7d46ca43..ba1d282b 100644
--- a/lcode.h
+++ b/lcode.h
@@ -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);
55int luaK_exp2RK (FuncState *fs, expdesc *e); 55int luaK_exp2RK (FuncState *fs, expdesc *e);
56void luaK_self (FuncState *fs, expdesc *e, expdesc *key); 56void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
57void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); 57void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
58void luaK_moveexp (expdesc *e, int offset);
59void luaK_goiftrue (FuncState *fs, expdesc *e); 58void luaK_goiftrue (FuncState *fs, expdesc *e);
60void luaK_goiffalse (FuncState *fs, expdesc *e); 59void luaK_goiffalse (FuncState *fs, expdesc *e);
61void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); 60void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
62void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); 61void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
63int luaK_jump (FuncState *fs); 62int luaK_jump (FuncState *fs);
63void luaK_dischargejpc (FuncState *fs);
64void luaK_patchlist (FuncState *fs, int list, int target); 64void luaK_patchlist (FuncState *fs, int list, int target);
65void luaK_patchtohere (FuncState *fs, int list); 65void luaK_patchtohere (FuncState *fs, int list);
66void luaK_concat (FuncState *fs, int *l1, int l2); 66void luaK_concat (FuncState *fs, int *l1, int l2);
diff --git a/lparser.c b/lparser.c
index eaf0bc8a..c24b5412 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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);
diff --git a/lparser.h b/lparser.h
index 81003c21..51ceb895 100644
--- a/lparser.h
+++ b/lparser.h
@@ -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' */