diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 38 |
1 files changed, 22 insertions, 16 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.32 2000/05/24 13:54:49 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.33 2000/05/24 18:04:17 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 | */ |
@@ -69,16 +69,16 @@ static int luaK_getjump (FuncState *fs, int pc) { | |||
69 | 69 | ||
70 | 70 | ||
71 | /* | 71 | /* |
72 | ** discharge list of jumps to last target. | ||
73 | ** returns current `pc' and marks it as a jump target (to avoid wrong | 72 | ** returns current `pc' and marks it as a jump target (to avoid wrong |
74 | ** optimizations with consecutive instructions not in the same basic block). | 73 | ** optimizations with consecutive instructions not in the same basic block). |
74 | ** discharge list of jumps to last target. | ||
75 | */ | 75 | */ |
76 | int luaK_getlabel (FuncState *fs) { | 76 | int luaK_getlabel (FuncState *fs) { |
77 | if (fs->pc != fs->lasttarget) { | 77 | if (fs->pc != fs->lasttarget) { |
78 | int lasttarget = fs->lasttarget; | 78 | int lasttarget = fs->lasttarget; |
79 | fs->lasttarget = fs->pc; | 79 | fs->lasttarget = fs->pc; |
80 | luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ | 80 | luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ |
81 | fs->jlt = NO_JUMP; /* nobody jumps to this new label (till now) */ | 81 | fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ |
82 | } | 82 | } |
83 | return fs->pc; | 83 | return fs->pc; |
84 | } | 84 | } |
@@ -86,7 +86,7 @@ int luaK_getlabel (FuncState *fs) { | |||
86 | 86 | ||
87 | void luaK_deltastack (FuncState *fs, int delta) { | 87 | void luaK_deltastack (FuncState *fs, int delta) { |
88 | fs->stacklevel += delta; | 88 | fs->stacklevel += delta; |
89 | if (delta > 0 && fs->stacklevel > fs->f->maxstacksize) { | 89 | if (fs->stacklevel > fs->f->maxstacksize) { |
90 | if (fs->stacklevel > MAXSTACK) | 90 | if (fs->stacklevel > MAXSTACK) |
91 | luaK_error(fs->ls, "function or expression too complex"); | 91 | luaK_error(fs->ls, "function or expression too complex"); |
92 | fs->f->maxstacksize = fs->stacklevel; | 92 | fs->f->maxstacksize = fs->stacklevel; |
@@ -99,7 +99,7 @@ void luaK_kstr (LexState *ls, int c) { | |||
99 | } | 99 | } |
100 | 100 | ||
101 | 101 | ||
102 | static int real_constant (FuncState *fs, Number r) { | 102 | static int number_constant (FuncState *fs, Number r) { |
103 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | 103 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ |
104 | Proto *f = fs->f; | 104 | Proto *f = fs->f; |
105 | int c = f->nknum; | 105 | int c = f->nknum; |
@@ -116,17 +116,17 @@ static int real_constant (FuncState *fs, Number r) { | |||
116 | 116 | ||
117 | 117 | ||
118 | void luaK_number (FuncState *fs, Number f) { | 118 | void luaK_number (FuncState *fs, Number f) { |
119 | if (f <= (Number)MAXARG_S && (int)f == f) | 119 | if (f <= (Number)MAXARG_S && (Number)(int)f == f) |
120 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | 120 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ |
121 | else | 121 | else |
122 | luaK_code1(fs, OP_PUSHNUM, real_constant(fs, f)); | 122 | luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); |
123 | } | 123 | } |
124 | 124 | ||
125 | 125 | ||
126 | void luaK_adjuststack (FuncState *fs, int n) { | 126 | void luaK_adjuststack (FuncState *fs, int n) { |
127 | if (n > 0) | 127 | if (n > 0) |
128 | luaK_code1(fs, OP_POP, n); | 128 | luaK_code1(fs, OP_POP, n); |
129 | else if (n < 0) | 129 | else |
130 | luaK_code1(fs, OP_PUSHNIL, -n); | 130 | luaK_code1(fs, OP_PUSHNIL, -n); |
131 | } | 131 | } |
132 | 132 | ||
@@ -170,7 +170,7 @@ static int discharge (FuncState *fs, expdesc *var) { | |||
170 | 170 | ||
171 | static void discharge1 (FuncState *fs, expdesc *var) { | 171 | static void discharge1 (FuncState *fs, expdesc *var) { |
172 | discharge(fs, var); | 172 | discharge(fs, var); |
173 | /* if it has jumps it is already discharged */ | 173 | /* if it has jumps then it is already discharged */ |
174 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | 174 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) |
175 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | 175 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ |
176 | } | 176 | } |
@@ -275,12 +275,10 @@ static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | |||
275 | discharge1(fs, v); | 275 | discharge1(fs, v); |
276 | previous = &fs->f->code[fs->pc-1]; | 276 | previous = &fs->f->code[fs->pc-1]; |
277 | LUA_ASSERT(L, GET_OPCODE(*previous) != OP_SETLINE, "bad place to set line"); | 277 | LUA_ASSERT(L, GET_OPCODE(*previous) != OP_SETLINE, "bad place to set line"); |
278 | if (ISJUMP(GET_OPCODE(*previous))) { | 278 | if (!ISJUMP(GET_OPCODE(*previous))) |
279 | if (invert) | ||
280 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
281 | } | ||
282 | else | ||
283 | luaK_code1(fs, jump, NO_JUMP); | 279 | luaK_code1(fs, jump, NO_JUMP); |
280 | else if (invert) | ||
281 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
284 | luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */ | 282 | luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */ |
285 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | 283 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); |
286 | *golist = NO_JUMP; | 284 | *golist = NO_JUMP; |
@@ -431,12 +429,17 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
431 | break; | 429 | break; |
432 | 430 | ||
433 | case OP_SETTABLE: | 431 | case OP_SETTABLE: |
432 | delta = -arg2; | ||
433 | break; | ||
434 | |||
434 | case OP_SETLIST: | 435 | case OP_SETLIST: |
436 | if (arg2 == 0) return NO_JUMP; /* nothing to do */ | ||
435 | delta = -arg2; | 437 | delta = -arg2; |
436 | break; | 438 | break; |
437 | 439 | ||
438 | case OP_SETMAP: | 440 | case OP_SETMAP: |
439 | delta = -2*(arg1+1); | 441 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ |
442 | delta = -2*arg1; | ||
440 | break; | 443 | break; |
441 | 444 | ||
442 | case OP_RETURN: | 445 | case OP_RETURN: |
@@ -448,6 +451,7 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
448 | break; | 451 | break; |
449 | 452 | ||
450 | case OP_PUSHNIL: | 453 | case OP_PUSHNIL: |
454 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | ||
451 | delta = arg1; | 455 | delta = arg1; |
452 | switch(GET_OPCODE(i)) { | 456 | switch(GET_OPCODE(i)) { |
453 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | 457 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; |
@@ -456,6 +460,7 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
456 | break; | 460 | break; |
457 | 461 | ||
458 | case OP_POP: | 462 | case OP_POP: |
463 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | ||
459 | delta = -arg1; | 464 | delta = -arg1; |
460 | switch(GET_OPCODE(i)) { | 465 | switch(GET_OPCODE(i)) { |
461 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | 466 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; |
@@ -561,13 +566,14 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | |||
561 | fs->f->code[fs->pc-1] = i; /* change previous instruction */ | 566 | fs->f->code[fs->pc-1] = i; /* change previous instruction */ |
562 | return fs->pc-1; /* do not generate new instruction */ | 567 | return fs->pc-1; /* do not generate new instruction */ |
563 | } | 568 | } |
569 | /* build new instruction */ | ||
564 | switch ((enum Mode)luaK_opproperties[o].mode) { | 570 | switch ((enum Mode)luaK_opproperties[o].mode) { |
565 | case iO: i = CREATE_0(o); break; | 571 | case iO: i = CREATE_0(o); break; |
566 | case iU: i = CREATE_U(o, arg1); break; | 572 | case iU: i = CREATE_U(o, arg1); break; |
567 | case iS: i = CREATE_S(o, arg1); break; | 573 | case iS: i = CREATE_S(o, arg1); break; |
568 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | 574 | case iAB: i = CREATE_AB(o, arg1, arg2); break; |
569 | } | 575 | } |
570 | /* actually create the new instruction */ | 576 | /* put new instruction in code array */ |
571 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, | 577 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, |
572 | "code size overflow", MAX_INT); | 578 | "code size overflow", MAX_INT); |
573 | fs->f->code[fs->pc] = i; | 579 | fs->f->code[fs->pc] = i; |