diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
| commit | 762d059a13d83eb367238a6115bbb4f5f13fcb49 (patch) | |
| tree | f35fdf0675b791865d0d4800522b172903b34803 /lcode.c | |
| parent | 572a69b6afbd368beab8844bc876b0f9690b5253 (diff) | |
| download | lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.gz lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.bz2 lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.zip | |
new implementation for the Virtual Machine
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 1045 |
1 files changed, 566 insertions, 479 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.67 2001/04/06 18:25:00 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 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 | */ |
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "lua.h" | 11 | #include "lua.h" |
| 12 | 12 | ||
| 13 | #include "lcode.h" | 13 | #include "lcode.h" |
| 14 | #include "ldebug.h" | ||
| 14 | #include "ldo.h" | 15 | #include "ldo.h" |
| 15 | #include "llex.h" | 16 | #include "llex.h" |
| 16 | #include "lmem.h" | 17 | #include "lmem.h" |
| @@ -19,6 +20,12 @@ | |||
| 19 | #include "lparser.h" | 20 | #include "lparser.h" |
| 20 | 21 | ||
| 21 | 22 | ||
| 23 | #define hasjumps(e) ((e)->t != (e)->f) | ||
| 24 | |||
| 25 | #define getcode(fs,e) ((fs)->f->code[(e)->u.i.info]) | ||
| 26 | |||
| 27 | |||
| 28 | |||
| 22 | void luaK_error (LexState *ls, const l_char *msg) { | 29 | void luaK_error (LexState *ls, const l_char *msg) { |
| 23 | luaX_error(ls, msg, ls->t.token); | 30 | luaX_error(ls, msg, ls->t.token); |
| 24 | } | 31 | } |
| @@ -33,12 +40,27 @@ static Instruction previous_instruction (FuncState *fs) { | |||
| 33 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
| 34 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ | 41 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ |
| 35 | else | 42 | else |
| 36 | return CREATE_0(-1); /* no optimizations after an invalid instruction */ | 43 | return (Instruction)(-1);/* no optimizations after an invalid instruction */ |
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | void luaK_nil (FuncState *fs, int from, int n) { | ||
| 48 | Instruction previous = previous_instruction(fs); | ||
| 49 | if (GET_OPCODE(previous) == OP_LOADNIL) { | ||
| 50 | int pfrom = GETARG_A(previous); | ||
| 51 | int pto = GETARG_B(previous); | ||
| 52 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | ||
| 53 | if (from+n-1 > pto) | ||
| 54 | SETARG_B(fs->f->code[fs->pc-1], from+n-1); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | ||
| 37 | } | 59 | } |
| 38 | 60 | ||
| 39 | 61 | ||
| 40 | int luaK_jump (FuncState *fs) { | 62 | int luaK_jump (FuncState *fs) { |
| 41 | int j = luaK_code1(fs, OP_JMP, NO_JUMP); | 63 | int j = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); |
| 42 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 64 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ |
| 43 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 65 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ |
| 44 | fs->jlt = NO_JUMP; | 66 | fs->jlt = NO_JUMP; |
| @@ -47,36 +69,33 @@ int luaK_jump (FuncState *fs) { | |||
| 47 | } | 69 | } |
| 48 | 70 | ||
| 49 | 71 | ||
| 72 | static int luaK_condjump (FuncState *fs, OpCode op, int B, int C) { | ||
| 73 | luaK_codeABC(fs, op, NO_REG, B, C); | ||
| 74 | return luaK_codeAsBc(fs, OP_CJMP, 0, NO_JUMP); | ||
| 75 | } | ||
| 76 | |||
| 77 | |||
| 50 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 78 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
| 51 | Instruction *jmp = &fs->f->code[pc]; | 79 | Instruction *jmp = &fs->f->code[pc]; |
| 52 | if (dest == NO_JUMP) | 80 | if (dest == NO_JUMP) |
| 53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 81 | SETARG_sBc(*jmp, NO_JUMP); /* point to itself to represent end of list */ |
| 54 | else { /* jump is relative to position following jump instruction */ | 82 | else { /* jump is relative to position following jump instruction */ |
| 55 | int offset = dest-(pc+1); | 83 | int offset = dest-(pc+1); |
| 56 | if (abs(offset) > MAXARG_S) | 84 | if (abs(offset) > MAXARG_sBc) |
| 57 | luaK_error(fs->ls, l_s("control structure too long")); | 85 | luaK_error(fs->ls, l_s("control structure too long")); |
| 58 | SETARG_S(*jmp, offset); | 86 | SETARG_sBc(*jmp, offset); |
| 59 | } | 87 | } |
| 60 | } | 88 | } |
| 61 | 89 | ||
| 62 | 90 | ||
| 63 | /* | 91 | /* |
| 64 | ** prep-for instructions (OP_FORPREP & OP_LFORPREP) have a negated jump, | 92 | ** prep-for instructions (OP_FORPREP & OP_TFORPREP) have a negated jump, |
| 65 | ** as they simulate the real jump... | 93 | ** as they simulate the real jump... |
| 66 | */ | 94 | */ |
| 67 | void luaK_fixfor (FuncState *fs, int pc, int dest) { | 95 | void luaK_fixfor (FuncState *fs, int pc, int dest) { |
| 68 | Instruction *jmp = &fs->f->code[pc]; | 96 | Instruction *jmp = &fs->f->code[pc]; |
| 69 | int offset = dest-(pc+1); | 97 | int offset = dest-(pc+1); |
| 70 | SETARG_S(*jmp, -offset); | 98 | SETARG_sBc(*jmp, -offset); |
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | static int luaK_getjump (FuncState *fs, int pc) { | ||
| 75 | int offset = GETARG_S(fs->f->code[pc]); | ||
| 76 | if (offset == NO_JUMP) /* point to itself represents end of list */ | ||
| 77 | return NO_JUMP; /* end of list */ | ||
| 78 | else | ||
| 79 | return (pc+1)+offset; /* turn offset into absolute position */ | ||
| 80 | } | 99 | } |
| 81 | 100 | ||
| 82 | 101 | ||
| @@ -96,609 +115,677 @@ int luaK_getlabel (FuncState *fs) { | |||
| 96 | } | 115 | } |
| 97 | 116 | ||
| 98 | 117 | ||
| 99 | void luaK_deltastack (FuncState *fs, int delta) { | 118 | static int luaK_getjump (FuncState *fs, int pc) { |
| 100 | fs->stacklevel += delta; | 119 | int offset = GETARG_sBc(fs->f->code[pc]); |
| 101 | if (fs->stacklevel > fs->f->maxstacksize) { | 120 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
| 102 | if (fs->stacklevel > MAXSTACK) | 121 | return NO_JUMP; /* end of list */ |
| 103 | luaK_error(fs->ls, l_s("function or expression too complex")); | 122 | else |
| 104 | fs->f->maxstacksize = (short)fs->stacklevel; | 123 | return (pc+1)+offset; /* turn offset into absolute position */ |
| 105 | } | ||
| 106 | } | 124 | } |
| 107 | 125 | ||
| 108 | 126 | ||
| 109 | void luaK_kstr (LexState *ls, int c) { | 127 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { |
| 110 | luaK_code1(ls->fs, OP_PUSHSTRING, c); | 128 | Instruction *pi = &fs->f->code[pc]; |
| 129 | OpCode op = GET_OPCODE(*pi); | ||
| 130 | if (op == OP_CJMP) | ||
| 131 | return pi-1; | ||
| 132 | else { | ||
| 133 | lua_assert(op == OP_JMP || op == OP_FORLOOP || op == OP_TFORLOOP); | ||
| 134 | return pi; | ||
| 135 | } | ||
| 111 | } | 136 | } |
| 112 | 137 | ||
| 113 | 138 | ||
| 114 | static int number_constant (FuncState *fs, lua_Number r) { | 139 | static int need_value (FuncState *fs, int list, OpCode op) { |
| 115 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | 140 | /* check whether list has any jump different from `op' */ |
| 116 | Proto *f = fs->f; | 141 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) |
| 117 | int c = fs->nknum; | 142 | if (GET_OPCODE(*getjumpcontrol(fs, list)) != op) return 1; |
| 118 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; | 143 | return 0; /* not found */ |
| 119 | while (--c >= lim) | ||
| 120 | if (f->knum[c] == r) return c; | ||
| 121 | /* not found; create a new entry */ | ||
| 122 | luaM_growvector(fs->L, f->knum, fs->nknum, f->sizeknum, lua_Number, | ||
| 123 | MAXARG_U, l_s("constant table overflow")); | ||
| 124 | c = fs->nknum++; | ||
| 125 | f->knum[c] = r; | ||
| 126 | return c; | ||
| 127 | } | 144 | } |
| 128 | 145 | ||
| 129 | 146 | ||
| 130 | void luaK_number (FuncState *fs, lua_Number f) { | 147 | static void luaK_patchlistaux (FuncState *fs, int list, |
| 131 | if (f <= (lua_Number)MAXARG_S && (lua_Number)(int)f == f) | 148 | int ttarget, int treg, int ftarget, int freg, int dtarget) { |
| 132 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | 149 | while (list != NO_JUMP) { |
| 133 | else | 150 | int next = luaK_getjump(fs, list); |
| 134 | luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); | 151 | Instruction *i = getjumpcontrol(fs, list); |
| 152 | switch (GET_OPCODE(*i)) { | ||
| 153 | case OP_TESTT: { | ||
| 154 | SETARG_A(*i, treg); | ||
| 155 | luaK_fixjump(fs, list, ttarget); | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | case OP_TESTF: { | ||
| 159 | SETARG_A(*i, freg); | ||
| 160 | luaK_fixjump(fs, list, ftarget); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | default: { | ||
| 164 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | list = next; | ||
| 169 | } | ||
| 135 | } | 170 | } |
| 136 | 171 | ||
| 137 | 172 | ||
| 138 | void luaK_adjuststack (FuncState *fs, int n) { | 173 | void luaK_patchlist (FuncState *fs, int list, int target) { |
| 139 | if (n > 0) | 174 | if (target == fs->lasttarget) /* same target that list `jlt'? */ |
| 140 | luaK_code1(fs, OP_POP, n); | 175 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ |
| 141 | else | 176 | else |
| 142 | luaK_code1(fs, OP_PUSHNIL, -n); | 177 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); |
| 143 | } | 178 | } |
| 144 | 179 | ||
| 145 | 180 | ||
| 146 | int luaK_lastisopen (FuncState *fs) { | 181 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
| 147 | /* check whether last instruction is an open function call */ | 182 | if (*l1 == NO_JUMP) |
| 148 | Instruction i = previous_instruction(fs); | 183 | *l1 = l2; |
| 149 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) | 184 | else { |
| 150 | return 1; | 185 | int list = *l1; |
| 151 | else return 0; | 186 | int next; |
| 187 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | ||
| 188 | list = next; | ||
| 189 | luaK_fixjump(fs, list, l2); | ||
| 190 | } | ||
| 152 | } | 191 | } |
| 153 | 192 | ||
| 154 | 193 | ||
| 155 | void luaK_setcallreturns (FuncState *fs, int nresults) { | 194 | void luaK_reserveregs (FuncState *fs, int n) { |
| 156 | if (luaK_lastisopen(fs)) { /* expression is an open function call? */ | 195 | fs->freereg += n; |
| 157 | SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ | 196 | if (fs->freereg > fs->f->maxstacksize) { |
| 158 | luaK_deltastack(fs, nresults); /* push results */ | 197 | if (fs->freereg >= MAXSTACK) |
| 198 | luaK_error(fs->ls, l_s("function or expression too complex")); | ||
| 199 | fs->f->maxstacksize = (short)fs->freereg; | ||
| 159 | } | 200 | } |
| 160 | } | 201 | } |
| 161 | 202 | ||
| 162 | 203 | ||
| 163 | static int discharge (FuncState *fs, expdesc *var) { | 204 | static void freereg (FuncState *fs, int reg) { |
| 164 | switch (var->k) { | 205 | if (reg >= fs->nactloc && reg < MAXSTACK) { |
| 165 | case VLOCAL: | 206 | fs->freereg--; |
| 166 | luaK_code1(fs, OP_GETLOCAL, var->u.index); | 207 | lua_assert(reg == fs->freereg); |
| 167 | break; | ||
| 168 | case VGLOBAL: | ||
| 169 | luaK_code1(fs, OP_GETGLOBAL, var->u.index); | ||
| 170 | break; | ||
| 171 | case VINDEXED: | ||
| 172 | luaK_code0(fs, OP_GETTABLE); | ||
| 173 | break; | ||
| 174 | case VEXP: | ||
| 175 | return 0; /* nothing to do */ | ||
| 176 | } | 208 | } |
| 177 | var->k = VEXP; | ||
| 178 | var->u.l.t = var->u.l.f = NO_JUMP; | ||
| 179 | return 1; | ||
| 180 | } | 209 | } |
| 181 | 210 | ||
| 182 | 211 | ||
| 183 | static void discharge1 (FuncState *fs, expdesc *var) { | 212 | static void freeexp (FuncState *fs, expdesc *e) { |
| 184 | discharge(fs, var); | 213 | if (e->k == VNONRELOC) |
| 185 | /* if it has jumps then it is already discharged */ | 214 | freereg(fs, e->u.i.info); |
| 186 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | ||
| 187 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
| 188 | } | 215 | } |
| 189 | 216 | ||
| 190 | 217 | ||
| 191 | void luaK_storevar (LexState *ls, const expdesc *var) { | 218 | static int addk (FuncState *fs, TObject *k) { |
| 192 | FuncState *fs = ls->fs; | 219 | Proto *f = fs->f; |
| 193 | switch (var->k) { | 220 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
| 194 | case VLOCAL: | 221 | MAXARG_Bc, l_s("constant table overflow")); |
| 195 | luaK_code1(fs, OP_SETLOCAL, var->u.index); | 222 | setobj(&f->k[fs->nk], k); |
| 196 | break; | 223 | return fs->nk++; |
| 197 | case VGLOBAL: | 224 | } |
| 198 | luaK_code1(fs, OP_SETGLOBAL, var->u.index); | 225 | |
| 199 | break; | 226 | |
| 200 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | 227 | int luaK_stringk (FuncState *fs, TString *s) { |
| 201 | luaK_code2(fs, OP_SETTABLE, 3, 3); | 228 | Proto *f = fs->f; |
| 202 | break; | 229 | int c = s->u.s.constindex; |
| 203 | default: | 230 | if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) { |
| 204 | lua_assert(0); /* invalid var kind to store */ | 231 | TObject o; |
| 232 | setsvalue(&o, s); | ||
| 233 | c = addk(fs, &o); | ||
| 234 | s->u.s.constindex = c; /* hint for next time */ | ||
| 205 | } | 235 | } |
| 236 | return c; | ||
| 206 | } | 237 | } |
| 207 | 238 | ||
| 208 | 239 | ||
| 209 | static OpCode invertjump (OpCode op) { | 240 | static int number_constant (FuncState *fs, lua_Number r) { |
| 210 | switch (op) { | 241 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ |
| 211 | case OP_JMPNE: return OP_JMPEQ; | 242 | TObject o; |
| 212 | case OP_JMPEQ: return OP_JMPNE; | 243 | Proto *f = fs->f; |
| 213 | case OP_JMPLT: return OP_JMPGE; | 244 | int c = fs->nk; |
| 214 | case OP_JMPLE: return OP_JMPGT; | 245 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; |
| 215 | case OP_JMPGT: return OP_JMPLE; | 246 | while (--c >= lim) { |
| 216 | case OP_JMPGE: return OP_JMPLT; | 247 | if (ttype(&f->k[c]) == LUA_TNUMBER && nvalue(&f->k[c]) == r) |
| 217 | case OP_JMPT: case OP_JMPONT: return OP_JMPF; | 248 | return c; |
| 218 | case OP_JMPF: case OP_JMPONF: return OP_JMPT; | ||
| 219 | default: | ||
| 220 | lua_assert(0); /* invalid jump instruction */ | ||
| 221 | return OP_JMP; /* to avoid warnings */ | ||
| 222 | } | 249 | } |
| 250 | /* not found; create a new entry */ | ||
| 251 | setnvalue(&o, r); | ||
| 252 | return addk(fs, &o); | ||
| 223 | } | 253 | } |
| 224 | 254 | ||
| 225 | 255 | ||
| 226 | static void luaK_patchlistaux (FuncState *fs, int list, int target, | 256 | void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { |
| 227 | OpCode special, int special_target) { | 257 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 228 | Instruction *code = fs->f->code; | 258 | SETARG_C(getcode(fs, e), nresults); /* set number of results */ |
| 229 | while (list != NO_JUMP) { | 259 | if (nresults == 1) { /* `regular' expression? */ |
| 230 | int next = luaK_getjump(fs, list); | 260 | e->k = VNONRELOC; |
| 231 | Instruction *i = &code[list]; | 261 | e->u.i.info = GETARG_A(getcode(fs, e)); |
| 232 | OpCode op = GET_OPCODE(*i); | ||
| 233 | if (op == special) /* this `op' already has a value */ | ||
| 234 | luaK_fixjump(fs, list, special_target); | ||
| 235 | else { | ||
| 236 | luaK_fixjump(fs, list, target); /* do the patch */ | ||
| 237 | if (op == OP_JMPONT) /* remove eventual values */ | ||
| 238 | SET_OPCODE(*i, OP_JMPT); | ||
| 239 | else if (op == OP_JMPONF) | ||
| 240 | SET_OPCODE(*i, OP_JMPF); | ||
| 241 | } | 262 | } |
| 242 | list = next; | ||
| 243 | } | 263 | } |
| 244 | } | 264 | } |
| 245 | 265 | ||
| 246 | 266 | ||
| 247 | void luaK_patchlist (FuncState *fs, int list, int target) { | 267 | static void dischargevars (FuncState *fs, expdesc *e) { |
| 248 | if (target == fs->lasttarget) /* same target that list `jlt'? */ | 268 | switch (e->k) { |
| 249 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | 269 | case VLOCAL: { |
| 250 | else | 270 | e->k = VNONRELOC; |
| 251 | luaK_patchlistaux(fs, list, target, OP_ADD, 0); | 271 | break; |
| 272 | } | ||
| 273 | case VGLOBAL: { | ||
| 274 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); | ||
| 275 | e->k = VRELOCABLE; | ||
| 276 | break; | ||
| 277 | } | ||
| 278 | case VINDEXED: { | ||
| 279 | freereg(fs, e->u.i.aux); | ||
| 280 | freereg(fs, e->u.i.info); | ||
| 281 | e->u.i.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.i.info, e->u.i.aux); | ||
| 282 | e->k = VRELOCABLE; | ||
| 283 | break; | ||
| 284 | } | ||
| 285 | case VCALL: { | ||
| 286 | luaK_setcallreturns(fs, e, 1); | ||
| 287 | break; | ||
| 288 | } | ||
| 289 | default: break; /* there is one value available (somewhere) */ | ||
| 290 | } | ||
| 252 | } | 291 | } |
| 253 | 292 | ||
| 254 | 293 | ||
| 255 | static int need_value (FuncState *fs, int list, OpCode hasvalue) { | 294 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { |
| 256 | /* check whether list has a jump without a value */ | 295 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
| 257 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) | 296 | return luaK_codeAsBc(fs, op, A, sBc); |
| 258 | if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; | ||
| 259 | return 0; /* not found */ | ||
| 260 | } | 297 | } |
| 261 | 298 | ||
| 262 | 299 | ||
| 263 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 300 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { |
| 264 | if (*l1 == NO_JUMP) | 301 | if (hasjumps(e)) { |
| 265 | *l1 = l2; | 302 | int final; /* position after whole expression */ |
| 266 | else { | 303 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ |
| 267 | int list = *l1; | 304 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ |
| 268 | int next; | 305 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { |
| 269 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | 306 | /* expression needs values */ |
| 270 | list = next; | 307 | if (e->k != VJMP) |
| 271 | luaK_fixjump(fs, list, l2); | 308 | code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
| 309 | p_nil = code_label(fs, OP_NILJMP, reg, 0); | ||
| 310 | p_1 = code_label(fs, OP_LOADINT, reg, 1); | ||
| 311 | } | ||
| 312 | final = luaK_getlabel(fs); | ||
| 313 | luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); | ||
| 314 | luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); | ||
| 272 | } | 315 | } |
| 316 | e->f = e->t = NO_JUMP; | ||
| 273 | } | 317 | } |
| 274 | 318 | ||
| 275 | 319 | ||
| 276 | static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | 320 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
| 277 | int prevpos; /* position of last instruction */ | 321 | dischargevars(fs, e); |
| 278 | Instruction *previous; | 322 | switch (e->k) { |
| 279 | int *golist, *exitlist; | 323 | case VNIL: { |
| 280 | if (!invert) { | 324 | luaK_nil(fs, reg, 1); |
| 281 | golist = &v->u.l.f; /* go if false */ | 325 | break; |
| 282 | exitlist = &v->u.l.t; /* exit if true */ | 326 | } |
| 283 | } | 327 | case VNUMBER: { |
| 284 | else { | 328 | lua_Number f = e->u.n; |
| 285 | golist = &v->u.l.t; /* go if true */ | 329 | int i = (int)f; |
| 286 | exitlist = &v->u.l.f; /* exit if false */ | 330 | if ((lua_Number)i == f && -MAXARG_sBc <= i && i <= MAXARG_sBc) |
| 331 | luaK_codeAsBc(fs, OP_LOADINT, reg, i); /* f has a small int value */ | ||
| 332 | else | ||
| 333 | luaK_codeABc(fs, OP_LOADK, reg, number_constant(fs, f)); | ||
| 334 | break; | ||
| 335 | } | ||
| 336 | case VK: { | ||
| 337 | luaK_codeABc(fs, OP_LOADK, reg, e->u.i.info); | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | case VRELOCABLE: { | ||
| 341 | Instruction *pc = &getcode(fs, e); | ||
| 342 | SETARG_A(*pc, reg); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | default: return; | ||
| 287 | } | 346 | } |
| 288 | discharge1(fs, v); | 347 | e->u.i.info = reg; |
| 289 | prevpos = fs->pc-1; | 348 | e->k = VNONRELOC; |
| 290 | previous = &fs->f->code[prevpos]; | 349 | } |
| 291 | lua_assert(*previous==previous_instruction(fs)); /* no jump allowed here */ | 350 | |
| 292 | if (!ISJUMP(GET_OPCODE(*previous))) | 351 | |
| 293 | prevpos = luaK_code1(fs, jump, NO_JUMP); | 352 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
| 294 | else { /* last instruction is already a jump */ | 353 | if (e->k != VNONRELOC) { |
| 295 | if (invert) | 354 | luaK_reserveregs(fs, 1); |
| 296 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 355 | discharge2reg(fs, e, fs->freereg-1); |
| 297 | } | 356 | } |
| 298 | luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ | ||
| 299 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | ||
| 300 | *golist = NO_JUMP; | ||
| 301 | } | 357 | } |
| 302 | 358 | ||
| 303 | 359 | ||
| 304 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { | 360 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 305 | luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); | 361 | discharge2reg(fs, e, reg); |
| 362 | switch (e->k) { | ||
| 363 | case VVOID: { | ||
| 364 | return; /* nothing to do... */ | ||
| 365 | } | ||
| 366 | case VNONRELOC: { | ||
| 367 | if (reg != e->u.i.info) | ||
| 368 | luaK_codeABC(fs, OP_MOVE, reg, e->u.i.info, 0); | ||
| 369 | break; | ||
| 370 | } | ||
| 371 | case VJMP: { | ||
| 372 | luaK_concat(fs, &e->t, e->u.i.info); /* put this jump in `t' list */ | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | default: { | ||
| 376 | lua_assert(0); /* cannot happen */ | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | dischargejumps(fs, e, reg); | ||
| 381 | e->u.i.info = reg; | ||
| 382 | e->k = VNONRELOC; | ||
| 306 | } | 383 | } |
| 307 | 384 | ||
| 308 | 385 | ||
| 309 | static void luaK_goiffalse (FuncState *fs, expdesc *v) { | 386 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
| 310 | luaK_testgo(fs, v, 0, OP_JMPONT); | 387 | int reg; |
| 388 | dischargevars(fs, e); | ||
| 389 | freeexp(fs, e); | ||
| 390 | reg = fs->freereg; | ||
| 391 | luaK_reserveregs(fs, 1); | ||
| 392 | luaK_exp2reg(fs, e, reg); | ||
| 311 | } | 393 | } |
| 312 | 394 | ||
| 313 | 395 | ||
| 314 | static int code_label (FuncState *fs, OpCode op, int arg) { | 396 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
| 315 | luaK_getlabel(fs); /* those instructions may be jump targets */ | 397 | dischargevars(fs, e); |
| 316 | return luaK_code1(fs, op, arg); | 398 | if (e->k == VNONRELOC) { |
| 317 | } | 399 | if (!hasjumps(e)) return e->u.i.info; /* exp is already in a register */ |
| 318 | 400 | if (e->u.i.info >= fs->nactloc) { /* reg. is not a local? */ | |
| 319 | 401 | dischargejumps(fs, e, e->u.i.info); /* put value on it */ | |
| 320 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | 402 | return e->u.i.info; |
| 321 | FuncState *fs = ls->fs; | ||
| 322 | if (!discharge(fs, v)) { /* `v' is an expression? */ | ||
| 323 | OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); | ||
| 324 | if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { | ||
| 325 | /* expression has no jumps */ | ||
| 326 | if (onlyone) | ||
| 327 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
| 328 | } | ||
| 329 | else { /* expression has jumps */ | ||
| 330 | int final; /* position after whole expression */ | ||
| 331 | int j = NO_JUMP; /* eventual jump over values */ | ||
| 332 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | ||
| 333 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | ||
| 334 | if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) | ||
| 335 | || need_value(fs, v->u.l.t, OP_JMPONT)) { | ||
| 336 | /* expression needs values */ | ||
| 337 | if (ISJUMP(previous)) | ||
| 338 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ | ||
| 339 | else { | ||
| 340 | j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ | ||
| 341 | /* correct stack for compiler and symbolic execution */ | ||
| 342 | luaK_adjuststack(fs, 1); | ||
| 343 | } | ||
| 344 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
| 345 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
| 346 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
| 347 | } | ||
| 348 | final = luaK_getlabel(fs); | ||
| 349 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
| 350 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
| 351 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
| 352 | } | 403 | } |
| 353 | } | 404 | } |
| 405 | luaK_exp2nextreg(fs, e); /* default */ | ||
| 406 | return e->u.i.info; | ||
| 354 | } | 407 | } |
| 355 | 408 | ||
| 356 | 409 | ||
| 357 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { | 410 | void luaK_exp2val (FuncState *fs, expdesc *e) { |
| 358 | FuncState *fs = ls->fs; | 411 | if (hasjumps(e)) |
| 359 | if (op == OPR_MINUS) { | 412 | luaK_exp2anyreg(fs, e); |
| 360 | luaK_tostack(ls, v, 1); | 413 | else |
| 361 | luaK_code0(fs, OP_MINUS); | 414 | dischargevars(fs, e); |
| 362 | } | ||
| 363 | else { /* op == NOT */ | ||
| 364 | Instruction *previous; | ||
| 365 | discharge1(fs, v); | ||
| 366 | previous = &fs->f->code[fs->pc-1]; | ||
| 367 | if (ISJUMP(GET_OPCODE(*previous))) | ||
| 368 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
| 369 | else | ||
| 370 | luaK_code0(fs, OP_NOT); | ||
| 371 | /* interchange true and false lists */ | ||
| 372 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | ||
| 373 | } | ||
| 374 | } | 415 | } |
| 375 | 416 | ||
| 376 | 417 | ||
| 377 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { | 418 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 378 | FuncState *fs = ls->fs; | 419 | luaK_exp2val(fs, e); |
| 379 | switch (op) { | 420 | if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { |
| 380 | case OPR_AND: | 421 | e->u.i.info = number_constant(fs, e->u.n); |
| 381 | luaK_goiftrue(fs, v, 1); | 422 | e->k = VK; |
| 382 | break; | ||
| 383 | case OPR_OR: | ||
| 384 | luaK_goiffalse(fs, v); | ||
| 385 | break; | ||
| 386 | default: | ||
| 387 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | ||
| 388 | } | 423 | } |
| 424 | else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) | ||
| 425 | luaK_exp2anyreg(fs, e); /* not a constant in the right range */ | ||
| 426 | return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; | ||
| 389 | } | 427 | } |
| 390 | 428 | ||
| 391 | 429 | ||
| 392 | 430 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |
| 393 | static const struct { | 431 | switch (var->k) { |
| 394 | OpCode opcode; /* opcode for each binary operator */ | 432 | case VLOCAL: { |
| 395 | int arg; /* default argument for the opcode */ | 433 | freeexp(fs, exp); |
| 396 | } codes[] = { /* ORDER OPR */ | 434 | luaK_exp2reg(fs, exp, var->u.i.info); |
| 397 | {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, | ||
| 398 | {OP_POW, 0}, {OP_CONCAT, 2}, | ||
| 399 | {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, | ||
| 400 | {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, | ||
| 401 | {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} | ||
| 402 | }; | ||
| 403 | |||
| 404 | |||
| 405 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { | ||
| 406 | FuncState *fs = ls->fs; | ||
| 407 | switch (op) { | ||
| 408 | case OPR_AND: { | ||
| 409 | lua_assert(v1->u.l.t == NO_JUMP); /* list must be closed */ | ||
| 410 | discharge1(fs, v2); | ||
| 411 | v1->u.l.t = v2->u.l.t; | ||
| 412 | luaK_concat(fs, &v1->u.l.f, v2->u.l.f); | ||
| 413 | break; | 435 | break; |
| 414 | } | 436 | } |
| 415 | case OPR_OR: { | 437 | case VGLOBAL: { |
| 416 | lua_assert(v1->u.l.f == NO_JUMP); /* list must be closed */ | 438 | int e = luaK_exp2anyreg(fs, exp); |
| 417 | discharge1(fs, v2); | 439 | freereg(fs, e); |
| 418 | v1->u.l.f = v2->u.l.f; | 440 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->u.i.info); |
| 419 | luaK_concat(fs, &v1->u.l.t, v2->u.l.t); | 441 | break; |
| 442 | } | ||
| 443 | case VINDEXED: { | ||
| 444 | int e = luaK_exp2anyreg(fs, exp); | ||
| 445 | freereg(fs, e); | ||
| 446 | luaK_codeABC(fs, OP_SETTABLE, e, var->u.i.info, var->u.i.aux); | ||
| 420 | break; | 447 | break; |
| 421 | } | 448 | } |
| 422 | default: { | 449 | default: { |
| 423 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | 450 | lua_assert(0); /* invalid var kind to store */ |
| 424 | luaK_code1(fs, codes[op].opcode, codes[op].arg); | 451 | break; |
| 425 | } | 452 | } |
| 426 | } | 453 | } |
| 427 | } | 454 | } |
| 428 | 455 | ||
| 429 | 456 | ||
| 430 | static void codelineinfo (FuncState *fs) { | 457 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
| 431 | Proto *f = fs->f; | 458 | luaK_exp2anyreg(fs, e); |
| 432 | LexState *ls = fs->ls; | 459 | freeexp(fs, e); |
| 433 | if (ls->lastline > fs->lastline) { | 460 | luaK_reserveregs(fs, 2); |
| 434 | if (ls->lastline > fs->lastline+1) { | 461 | luaK_codeABC(fs, OP_SELF, fs->freereg-2, e->u.i.info, luaK_exp2RK(fs, key)); |
| 435 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 462 | e->u.i.info = fs->freereg-2; |
| 436 | MAX_INT, l_s("line info overflow")); | 463 | e->k = VNONRELOC; |
| 437 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | 464 | } |
| 438 | } | 465 | |
| 439 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 466 | |
| 440 | MAX_INT, l_s("line info overflow")); | 467 | static OpCode invertoperator (OpCode op) { |
| 441 | f->lineinfo[fs->nlineinfo++] = fs->pc; | 468 | switch (op) { |
| 442 | fs->lastline = ls->lastline; | 469 | case OP_TESTNE: return OP_TESTEQ; |
| 470 | case OP_TESTEQ: return OP_TESTNE; | ||
| 471 | case OP_TESTLT: return OP_TESTGE; | ||
| 472 | case OP_TESTLE: return OP_TESTGT; | ||
| 473 | case OP_TESTGT: return OP_TESTLE; | ||
| 474 | case OP_TESTGE: return OP_TESTLT; | ||
| 475 | case OP_TESTT: return OP_TESTF; | ||
| 476 | case OP_TESTF: return OP_TESTT; | ||
| 477 | default: lua_assert(0); return op; /* invalid jump instruction */ | ||
| 443 | } | 478 | } |
| 444 | } | 479 | } |
| 445 | 480 | ||
| 446 | 481 | ||
| 447 | int luaK_code0 (FuncState *fs, OpCode o) { | 482 | static void invertjump (FuncState *fs, expdesc *e) { |
| 448 | return luaK_code2(fs, o, 0, 0); | 483 | Instruction *pc = getjumpcontrol(fs, e->u.i.info); |
| 484 | *pc = SET_OPCODE(*pc, invertoperator(GET_OPCODE(*pc))); | ||
| 449 | } | 485 | } |
| 450 | 486 | ||
| 451 | 487 | ||
| 452 | int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | 488 | static int jumponcond (FuncState *fs, expdesc *e, OpCode op) { |
| 453 | return luaK_code2(fs, o, arg1, 0); | 489 | if (e->k == VRELOCABLE) { |
| 490 | Instruction ie = getcode(fs, e); | ||
| 491 | if (GET_OPCODE(ie) == OP_NOT) { | ||
| 492 | op = invertoperator(op); | ||
| 493 | fs->pc--; /* remove previous OP_NOT */ | ||
| 494 | return luaK_condjump(fs, op, GETARG_B(ie), 0); | ||
| 495 | } | ||
| 496 | /* else go through */ | ||
| 497 | } | ||
| 498 | discharge2anyreg(fs, e); | ||
| 499 | freeexp(fs, e); | ||
| 500 | return luaK_condjump(fs, op, e->u.i.info, 0); | ||
| 454 | } | 501 | } |
| 455 | 502 | ||
| 456 | 503 | ||
| 457 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | 504 | void luaK_goiftrue (FuncState *fs, expdesc *e) { |
| 458 | Proto *f; | 505 | int pc; /* pc of last jump */ |
| 459 | Instruction i = previous_instruction(fs); | 506 | dischargevars(fs, e); |
| 460 | int push = (int)luaK_opproperties[o].push; | 507 | switch (e->k) { |
| 461 | int pop = (int)luaK_opproperties[o].pop; | 508 | case VK: case VNUMBER: { |
| 462 | int optm = 0; /* 1 when there is an optimization */ | 509 | pc = NO_JUMP; /* always true; do nothing */ |
| 463 | switch (o) { | ||
| 464 | case OP_CLOSURE: { | ||
| 465 | pop = arg2; | ||
| 466 | break; | 510 | break; |
| 467 | } | 511 | } |
| 468 | case OP_SETTABLE: { | 512 | case VNIL: { |
| 469 | pop = arg2; | 513 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
| 470 | break; | 514 | break; |
| 471 | } | 515 | } |
| 472 | case OP_SETLIST: { | 516 | case VJMP: { |
| 473 | pop = fs->stacklevel - 1 - arg2; | 517 | invertjump(fs, e); |
| 518 | pc = e->u.i.info; | ||
| 474 | break; | 519 | break; |
| 475 | } | 520 | } |
| 476 | case OP_SETMAP: { | 521 | case VRELOCABLE: |
| 477 | pop = fs->stacklevel - 1 - arg1; | 522 | case VNONRELOC: { |
| 523 | pc = jumponcond(fs, e, OP_TESTF); | ||
| 478 | break; | 524 | break; |
| 479 | } | 525 | } |
| 480 | case OP_PUSHNIL: { | 526 | default: { |
| 481 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 527 | pc = 0; /* to avoid warnings */ |
| 482 | push = arg1; | 528 | lua_assert(0); /* cannot happen */ |
| 483 | switch(GET_OPCODE(i)) { | ||
| 484 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | ||
| 485 | default: break; | ||
| 486 | } | ||
| 487 | break; | 529 | break; |
| 488 | } | 530 | } |
| 489 | case OP_POP: { | 531 | } |
| 490 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 532 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
| 491 | pop = arg1; | 533 | luaK_patchlist(fs, e->t, luaK_getlabel(fs)); |
| 492 | switch(GET_OPCODE(i)) { | 534 | e->t = NO_JUMP; |
| 493 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | 535 | } |
| 494 | default: break; | 536 | |
| 495 | } | 537 | |
| 538 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | ||
| 539 | int pc; /* pc of last jump */ | ||
| 540 | dischargevars(fs, e); | ||
| 541 | switch (e->k) { | ||
| 542 | case VNIL: { | ||
| 543 | pc = NO_JUMP; /* always false; do nothing */ | ||
| 496 | break; | 544 | break; |
| 497 | } | 545 | } |
| 498 | case OP_GETTABLE: { | 546 | case VJMP: { |
| 499 | switch(GET_OPCODE(i)) { | 547 | pc = e->u.i.info; |
| 500 | case OP_PUSHSTRING: /* `t.x' */ | ||
| 501 | SET_OPCODE(i, OP_GETDOTTED); | ||
| 502 | optm = 1; | ||
| 503 | break; | ||
| 504 | case OP_GETLOCAL: /* `t[i]' */ | ||
| 505 | SET_OPCODE(i, OP_GETINDEXED); | ||
| 506 | optm = 1; | ||
| 507 | break; | ||
| 508 | default: break; | ||
| 509 | } | ||
| 510 | break; | 548 | break; |
| 511 | } | 549 | } |
| 512 | case OP_ADD: { | 550 | case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ |
| 513 | switch(GET_OPCODE(i)) { | 551 | case VRELOCABLE: |
| 514 | case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ | 552 | case VNONRELOC: { |
| 515 | default: break; | 553 | pc = jumponcond(fs, e, OP_TESTT); |
| 516 | } | ||
| 517 | break; | 554 | break; |
| 518 | } | 555 | } |
| 519 | case OP_SUB: { | 556 | default: { |
| 520 | switch(GET_OPCODE(i)) { | 557 | pc = 0; /* to avoid warnings */ |
| 521 | case OP_PUSHINT: /* `a-k' */ | 558 | lua_assert(0); /* cannot happen */ |
| 522 | i = CREATE_S(OP_ADDI, -GETARG_S(i)); | ||
| 523 | optm = 1; | ||
| 524 | break; | ||
| 525 | default: break; | ||
| 526 | } | ||
| 527 | break; | 559 | break; |
| 528 | } | 560 | } |
| 529 | case OP_CONCAT: { | 561 | } |
| 530 | pop = arg1; | 562 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
| 531 | switch(GET_OPCODE(i)) { | 563 | luaK_patchlist(fs, e->f, luaK_getlabel(fs)); |
| 532 | case OP_CONCAT: /* `a..b..c' */ | 564 | e->f = NO_JUMP; |
| 533 | SETARG_U(i, GETARG_U(i)+1); | 565 | } |
| 534 | optm = 1; | 566 | |
| 535 | break; | 567 | |
| 536 | default: break; | 568 | static void codenot (FuncState *fs, expdesc *e) { |
| 537 | } | 569 | dischargevars(fs, e); |
| 570 | switch (e->k) { | ||
| 571 | case VNIL: { | ||
| 572 | e->u.n = 1; | ||
| 573 | e->k = VNUMBER; | ||
| 538 | break; | 574 | break; |
| 539 | } | 575 | } |
| 540 | case OP_MINUS: { | 576 | case VK: case VNUMBER: { |
| 541 | switch(GET_OPCODE(i)) { | 577 | e->k = VNIL; |
| 542 | case OP_PUSHINT: /* `-k' */ | ||
| 543 | SETARG_S(i, -GETARG_S(i)); | ||
| 544 | optm = 1; | ||
| 545 | break; | ||
| 546 | case OP_PUSHNUM: /* `-k' */ | ||
| 547 | SET_OPCODE(i, OP_PUSHNEGNUM); | ||
| 548 | optm = 1; | ||
| 549 | break; | ||
| 550 | default: break; | ||
| 551 | } | ||
| 552 | break; | 578 | break; |
| 553 | } | 579 | } |
| 554 | case OP_JMPNE: { | 580 | case VJMP: { |
| 555 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ | 581 | invertjump(fs, e); |
| 556 | i = CREATE_S(OP_JMPT, NO_JUMP); | ||
| 557 | optm = 1; | ||
| 558 | } | ||
| 559 | break; | 582 | break; |
| 560 | } | 583 | } |
| 561 | case OP_JMPEQ: { | 584 | case VRELOCABLE: |
| 562 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | 585 | case VNONRELOC: { |
| 563 | i = CREATE_0(OP_NOT); | 586 | discharge2anyreg(fs, e); |
| 564 | pop = 1; /* just undo effect of previous PUSHNIL */ | 587 | freeexp(fs, e); |
| 565 | optm = 1; | 588 | e->u.i.info = luaK_codeABC(fs, OP_NOT, 0, e->u.i.info, 0); |
| 566 | } | 589 | e->k = VRELOCABLE; |
| 567 | break; | 590 | break; |
| 568 | } | 591 | } |
| 569 | case OP_JMPT: | 592 | default: { |
| 570 | case OP_JMPONT: { | 593 | lua_assert(0); /* cannot happen */ |
| 571 | switch (GET_OPCODE(i)) { | ||
| 572 | case OP_NOT: { | ||
| 573 | i = CREATE_S(OP_JMPF, NO_JUMP); | ||
| 574 | optm = 1; | ||
| 575 | break; | ||
| 576 | } | ||
| 577 | case OP_PUSHINT: { | ||
| 578 | if (o == OP_JMPT) { /* JMPONT must keep original integer value */ | ||
| 579 | i = CREATE_S(OP_JMP, NO_JUMP); | ||
| 580 | optm = 1; | ||
| 581 | } | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | case OP_PUSHNIL: { | ||
| 585 | if (GETARG_U(i) == 1) { | ||
| 586 | fs->pc--; /* erase previous instruction */ | ||
| 587 | luaK_deltastack(fs, -1); /* correct stack */ | ||
| 588 | return NO_JUMP; | ||
| 589 | } | ||
| 590 | break; | ||
| 591 | } | ||
| 592 | default: break; | ||
| 593 | } | ||
| 594 | break; | 594 | break; |
| 595 | } | 595 | } |
| 596 | case OP_JMPF: | 596 | } |
| 597 | case OP_JMPONF: { | 597 | /* interchange true and false lists */ |
| 598 | switch (GET_OPCODE(i)) { | 598 | { int temp = e->f; e->f = e->t; e->t = temp; } |
| 599 | case OP_NOT: { | 599 | } |
| 600 | i = CREATE_S(OP_JMPT, NO_JUMP); | 600 | |
| 601 | optm = 1; | 601 | |
| 602 | break; | 602 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
| 603 | } | 603 | t->u.i.aux = luaK_exp2RK(fs, k); |
| 604 | case OP_PUSHINT: { /* `while 1 do ...' */ | 604 | t->k = VINDEXED; |
| 605 | fs->pc--; /* erase previous instruction */ | 605 | } |
| 606 | luaK_deltastack(fs, -1); /* correct stack */ | 606 | |
| 607 | return NO_JUMP; | 607 | |
| 608 | } | 608 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
| 609 | case OP_PUSHNIL: { /* `repeat ... until nil' */ | 609 | if (op == OPR_MINUS) { |
| 610 | if (GETARG_U(i) == 1) { | 610 | luaK_exp2val(fs, e); |
| 611 | i = CREATE_S(OP_JMP, NO_JUMP); | 611 | if (e->k == VNUMBER) |
| 612 | optm = 1; | 612 | e->u.n = -e->u.n; |
| 613 | } | 613 | else { |
| 614 | break; | 614 | luaK_exp2anyreg(fs, e); |
| 615 | } | 615 | freeexp(fs, e); |
| 616 | default: break; | 616 | e->u.i.info = luaK_codeABC(fs, OP_UNM, 0, e->u.i.info, 0); |
| 617 | } | 617 | e->k = VRELOCABLE; |
| 618 | } | ||
| 619 | } | ||
| 620 | else /* op == NOT */ | ||
| 621 | codenot(fs, e); | ||
| 622 | } | ||
| 623 | |||
| 624 | |||
| 625 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | ||
| 626 | switch (op) { | ||
| 627 | case OPR_AND: { | ||
| 628 | luaK_goiftrue(fs, v); | ||
| 629 | break; | ||
| 630 | } | ||
| 631 | case OPR_OR: { | ||
| 632 | luaK_goiffalse(fs, v); | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | case OPR_CONCAT: { | ||
| 636 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | ||
| 618 | break; | 637 | break; |
| 619 | } | 638 | } |
| 620 | case OP_GETDOTTED: | 639 | case OPR_SUB: case OPR_DIV: case OPR_POW: { |
| 621 | case OP_GETINDEXED: | 640 | /* non-comutative operators */ |
| 622 | case OP_ADDI: { | 641 | luaK_exp2anyreg(fs, v); /* first operand must be a register */ |
| 623 | lua_assert(0); /* instruction used only for optimizations */ | ||
| 624 | break; | 642 | break; |
| 625 | } | 643 | } |
| 626 | default: { | 644 | default: { |
| 645 | luaK_exp2RK(fs, v); | ||
| 627 | break; | 646 | break; |
| 628 | } | 647 | } |
| 629 | } | 648 | } |
| 630 | f = fs->f; | 649 | } |
| 631 | lua_assert(push != VD); | 650 | |
| 632 | lua_assert(pop != VD); | 651 | |
| 633 | luaK_deltastack(fs, push); | 652 | |
| 634 | luaK_deltastack(fs, -pop); | 653 | /* opcode for each binary operator */ |
| 635 | if (optm) { /* optimize: put instruction in place of last one */ | 654 | static const OpCode codes[] = { /* ORDER OPR */ |
| 636 | f->code[fs->pc-1] = i; /* change previous instruction */ | 655 | OP_ADD, OP_SUB, OP_MUL, OP_DIV, |
| 637 | return fs->pc-1; /* do not generate new instruction */ | 656 | OP_POW, OP_CONCAT, |
| 657 | OP_TESTNE, OP_TESTEQ, | ||
| 658 | OP_TESTLT, OP_TESTLE, OP_TESTGT, OP_TESTGE | ||
| 659 | }; | ||
| 660 | |||
| 661 | |||
| 662 | /* `inverted' opcode for each binary operator */ | ||
| 663 | /* ( -1 means operator has no inverse) */ | ||
| 664 | static const OpCode invcodes[] = { /* ORDER OPR */ | ||
| 665 | OP_ADD, (OpCode)-1, OP_MUL, (OpCode)-1, | ||
| 666 | (OpCode)-1, (OpCode)-1, | ||
| 667 | OP_TESTNE, OP_TESTEQ, | ||
| 668 | OP_TESTGT, OP_TESTGE, OP_TESTLT, OP_TESTLE | ||
| 669 | }; | ||
| 670 | |||
| 671 | |||
| 672 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | ||
| 673 | switch (op) { | ||
| 674 | case OPR_AND: { | ||
| 675 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | ||
| 676 | dischargevars(fs, e2); | ||
| 677 | luaK_concat(fs, &e1->f, e2->f); | ||
| 678 | e1->k = e2->k; e1->u = e2->u; e1->t = e2->t; | ||
| 679 | break; | ||
| 680 | } | ||
| 681 | case OPR_OR: { | ||
| 682 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | ||
| 683 | dischargevars(fs, e2); | ||
| 684 | luaK_concat(fs, &e1->t, e2->t); | ||
| 685 | e1->k = e2->k; e1->u = e2->u; e1->f = e2->f; | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | case OPR_CONCAT: { | ||
| 689 | luaK_exp2val(fs, e2); | ||
| 690 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | ||
| 691 | lua_assert(e1->u.i.info == GETARG_B(getcode(fs, e2))-1); | ||
| 692 | freeexp(fs, e1); | ||
| 693 | SETARG_B(getcode(fs, e2), e1->u.i.info); | ||
| 694 | e1->k = e2->k; e1->u.i.info = e2->u.i.info; | ||
| 695 | } | ||
| 696 | else { | ||
| 697 | luaK_exp2nextreg(fs, e2); | ||
| 698 | freeexp(fs, e2); | ||
| 699 | freeexp(fs, e1); | ||
| 700 | e1->u.i.info = luaK_codeABC(fs, codes[op], 0, e1->u.i.info, | ||
| 701 | e2->u.i.info); | ||
| 702 | e1->k = VRELOCABLE; | ||
| 703 | } | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | case OPR_EQ: case OPR_NE: { | ||
| 707 | luaK_exp2val(fs, e2); | ||
| 708 | if (e2->k == VNIL) { /* exp x= nil ? */ | ||
| 709 | if (e1->k == VK) { /* constant x= nil ? */ | ||
| 710 | if (op == OPR_EQ) /* constant == nil ? */ | ||
| 711 | e1->k = VNIL; /* always false */ | ||
| 712 | /* else always true (leave the constant itself) */ | ||
| 713 | } | ||
| 714 | else { | ||
| 715 | OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; | ||
| 716 | e1->u.i.info = jumponcond(fs, e1, opc); | ||
| 717 | e1->k = VJMP; | ||
| 718 | } | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | /* else go through */ | ||
| 722 | } | ||
| 723 | default: { | ||
| 724 | int o1, o2; | ||
| 725 | OpCode opc; | ||
| 726 | if (e1->k != VK) { /* not a constant operator? */ | ||
| 727 | o1 = e1->u.i.info; | ||
| 728 | o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */ | ||
| 729 | opc = codes[op]; | ||
| 730 | } | ||
| 731 | else { /* invert operands */ | ||
| 732 | o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */ | ||
| 733 | o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */ | ||
| 734 | opc = invcodes[op]; /* use inverted operator */ | ||
| 735 | } | ||
| 736 | freeexp(fs, e2); | ||
| 737 | freeexp(fs, e1); | ||
| 738 | if (op < OPR_NE) { /* ORDER OPR */ | ||
| 739 | e1->u.i.info = luaK_codeABC(fs, opc, 0, o1, o2); | ||
| 740 | e1->k = VRELOCABLE; | ||
| 741 | } | ||
| 742 | else { /* jump */ | ||
| 743 | e1->u.i.info = luaK_condjump(fs, opc, o1, o2); | ||
| 744 | e1->k = VJMP; | ||
| 745 | } | ||
| 746 | } | ||
| 638 | } | 747 | } |
| 639 | /* else build new instruction */ | 748 | } |
| 640 | switch ((enum Mode)luaK_opproperties[o].mode) { | 749 | |
| 641 | case iO: i = CREATE_0(o); break; | 750 | |
| 642 | case iU: i = CREATE_U(o, arg1); break; | 751 | static void codelineinfo (FuncState *fs) { |
| 643 | case iS: i = CREATE_S(o, arg1); break; | 752 | Proto *f = fs->f; |
| 644 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | 753 | LexState *ls = fs->ls; |
| 754 | if (ls->lastline > fs->lastline) { | ||
| 755 | if (ls->lastline > fs->lastline+1) { | ||
| 756 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
| 757 | MAX_INT, l_s("line info overflow")); | ||
| 758 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | ||
| 759 | } | ||
| 760 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
| 761 | MAX_INT, l_s("line info overflow")); | ||
| 762 | f->lineinfo[fs->nlineinfo++] = fs->pc; | ||
| 763 | fs->lastline = ls->lastline; | ||
| 645 | } | 764 | } |
| 765 | } | ||
| 766 | |||
| 767 | |||
| 768 | static int luaK_code (FuncState *fs, Instruction i) { | ||
| 769 | Proto *f; | ||
| 646 | codelineinfo(fs); | 770 | codelineinfo(fs); |
| 771 | f = fs->f; | ||
| 647 | /* put new instruction in code array */ | 772 | /* put new instruction in code array */ |
| 648 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | 773 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, |
| 649 | MAX_INT, l_s("code size overflow")); | 774 | MAX_INT, l_s("code size overflow")); |
| 650 | f->code[fs->pc] = i; | 775 | f->code[fs->pc] = i; |
| 776 | /*printf("free: %d ", fs->freereg); printopcode(f, fs->pc);*/ | ||
| 651 | return fs->pc++; | 777 | return fs->pc++; |
| 652 | } | 778 | } |
| 653 | 779 | ||
| 654 | 780 | ||
| 655 | const OpProperties luaK_opproperties[] = { | 781 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { |
| 656 | {iU, 0, 0}, /* OP_RETURN */ | 782 | lua_assert(getOpMode(o) == iABC); |
| 657 | {iAB, 0, 0}, /* OP_CALL */ | 783 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); |
| 658 | {iU, VD, 0}, /* OP_PUSHNIL */ | 784 | } |
| 659 | {iU, 0, VD}, /* OP_POP */ | 785 | |
| 660 | {iS, 1, 0}, /* OP_PUSHINT */ | 786 | |
| 661 | {iU, 1, 0}, /* OP_PUSHSTRING */ | 787 | int luaK_codeABc (FuncState *fs, OpCode o, int a, int bc) { |
| 662 | {iU, 1, 0}, /* OP_PUSHNUM */ | 788 | lua_assert(getOpMode(o) == iABc || getOpMode(o) == iAsBc); |
| 663 | {iU, 1, 0}, /* OP_PUSHNEGNUM */ | 789 | return luaK_code(fs, CREATE_ABc(o, a, bc)); |
| 664 | {iU, 1, 0}, /* OP_PUSHUPVALUE */ | 790 | } |
| 665 | {iU, 1, 0}, /* OP_GETLOCAL */ | ||
| 666 | {iU, 1, 0}, /* OP_GETGLOBAL */ | ||
| 667 | {iO, 1, 2}, /* OP_GETTABLE */ | ||
| 668 | {iU, 1, 1}, /* OP_GETDOTTED */ | ||
| 669 | {iU, 1, 1}, /* OP_GETINDEXED */ | ||
| 670 | {iU, 2, 1}, /* OP_PUSHSELF */ | ||
| 671 | {iU, 1, 0}, /* OP_CREATETABLE */ | ||
| 672 | {iU, 0, 1}, /* OP_SETLOCAL */ | ||
| 673 | {iU, 0, 1}, /* OP_SETGLOBAL */ | ||
| 674 | {iAB, 0, VD}, /* OP_SETTABLE */ | ||
| 675 | {iAB, 0, VD}, /* OP_SETLIST */ | ||
| 676 | {iU, 0, VD}, /* OP_SETMAP */ | ||
| 677 | {iO, 1, 2}, /* OP_ADD */ | ||
| 678 | {iS, 1, 1}, /* OP_ADDI */ | ||
| 679 | {iO, 1, 2}, /* OP_SUB */ | ||
| 680 | {iO, 1, 2}, /* OP_MULT */ | ||
| 681 | {iO, 1, 2}, /* OP_DIV */ | ||
| 682 | {iO, 1, 2}, /* OP_POW */ | ||
| 683 | {iU, 1, VD}, /* OP_CONCAT */ | ||
| 684 | {iO, 1, 1}, /* OP_MINUS */ | ||
| 685 | {iO, 1, 1}, /* OP_NOT */ | ||
| 686 | {iS, 0, 2}, /* OP_JMPNE */ | ||
| 687 | {iS, 0, 2}, /* OP_JMPEQ */ | ||
| 688 | {iS, 0, 2}, /* OP_JMPLT */ | ||
| 689 | {iS, 0, 2}, /* OP_JMPLE */ | ||
| 690 | {iS, 0, 2}, /* OP_JMPGT */ | ||
| 691 | {iS, 0, 2}, /* OP_JMPGE */ | ||
| 692 | {iS, 0, 1}, /* OP_JMPT */ | ||
| 693 | {iS, 0, 1}, /* OP_JMPF */ | ||
| 694 | {iS, 0, 1}, /* OP_JMPONT */ | ||
| 695 | {iS, 0, 1}, /* OP_JMPONF */ | ||
| 696 | {iS, 0, 0}, /* OP_JMP */ | ||
| 697 | {iO, 0, 0}, /* OP_PUSHNILJMP */ | ||
| 698 | {iS, 0, 0}, /* OP_FORPREP */ | ||
| 699 | {iS, 0, 3}, /* OP_FORLOOP */ | ||
| 700 | {iS, 3, 0}, /* OP_LFORPREP */ | ||
| 701 | {iS, 0, 4}, /* OP_LFORLOOP */ | ||
| 702 | {iAB, 1, VD} /* OP_CLOSURE */ | ||
| 703 | }; | ||
| 704 | 791 | ||
