Lua 5.1.4: lcode.c


L0001    /*
L0002    ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
L0003    ** Code generator for Lua
L0004    ** See Copyright Notice in lua.h
L0005    */
L0006    
L0007    
L0008    #include <stdlib.h>
L0009    
L0010    #define lcode_c
L0011    #define LUA_CORE
L0012    
L0013    #include "lua.h"
L0014    
L0015    #include "lcode.h"
L0016    #include "ldebug.h"
L0017    #include "ldo.h"
L0018    #include "lgc.h"
L0019    #include "llex.h"
L0020    #include "lmem.h"
L0021    #include "lobject.h"
L0022    #include "lopcodes.h"
L0023    #include "lparser.h"
L0024    #include "ltable.h"
L0025    
L0026    
L0027    #define hasjumps(e)	((e)->t != (e)->f)
L0028    
L0029    
L0030    static int isnumeral(expdesc *e) {
L0031      return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
L0032    }
L0033    
L0034    
L0035    void luaK_nil (FuncState *fs, int from, int n) {
L0036      Instruction *previous;
L0037      if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
L0038        if (fs->pc == 0) {  /* function start? */
L0039          if (from >= fs->nactvar)
L0040            return;  /* positions are already clean */
L0041        }
L0042        else {
L0043          previous = &fs->f->code[fs->pc-1];
L0044          if (GET_OPCODE(*previous) == OP_LOADNIL) {
L0045            int pfrom = GETARG_A(*previous);
L0046            int pto = GETARG_B(*previous);
L0047            if (pfrom <= from && from <= pto+1) {  /* can connect both? */
L0048              if (from+n-1 > pto)
L0049                SETARG_B(*previous, from+n-1);
L0050              return;
L0051            }
L0052          }
L0053        }
L0054      }
L0055      luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
L0056    }
L0057    
L0058    
L0059    int luaK_jump (FuncState *fs) {
L0060      int jpc = fs->jpc;  /* save list of jumps to here */
L0061      int j;
L0062      fs->jpc = NO_JUMP;
L0063      j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
L0064      luaK_concat(fs, &j, jpc);  /* keep them on hold */
L0065      return j;
L0066    }
L0067    
L0068    
L0069    void luaK_ret (FuncState *fs, int first, int nret) {
Encode opcode for "return" (OP_RETURN). Note: (first,nret)=(0,0) means return no values. nret == LUA_MULTRET means return all values starting at first (useful for vararg expressions).
L0070 luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); L0071 } L0072 L0073 L0074 static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { L0075 luaK_codeABC(fs, op, A, B, C); L0076 return luaK_jump(fs); L0077 } L0078 L0079 L0080 static void fixjump (FuncState *fs, int pc, int dest) { L0081 Instruction *jmp = &fs->f->code[pc]; L0082 int offset = dest-(pc+1); L0083 lua_assert(dest != NO_JUMP); L0084 if (abs(offset) > MAXARG_sBx) L0085 luaX_syntaxerror(fs->ls, "control structure too long"); L0086 SETARG_sBx(*jmp, offset); L0087 } L0088 L0089 L0090 /* L0091 ** returns current `pc' and marks it as a jump target (to avoid wrong L0092 ** optimizations with consecutive instructions not in the same basic block). L0093 */ L0094 int luaK_getlabel (FuncState *fs) { L0095 fs->lasttarget = fs->pc; L0096 return fs->pc; L0097 } L0098 L0099 L0100 static int getjump (FuncState *fs, int pc) { L0101 int offset = GETARG_sBx(fs->f->code[pc]); L0102 if (offset == NO_JUMP) /* point to itself represents end of list */ L0103 return NO_JUMP; /* end of list */ L0104 else L0105 return (pc+1)+offset; /* turn offset into absolute position */ L0106 } L0107 L0108 L0109 static Instruction *getjumpcontrol (FuncState *fs, int pc) { L0110 Instruction *pi = &fs->f->code[pc]; L0111 if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) L0112 return pi-1; L0113 else L0114 return pi; L0115 } L0116 L0117 L0118 /* L0119 ** check whether list has any jump that do not produce a value L0120 ** (or produce an inverted value) L0121 */ L0122 static int need_value (FuncState *fs, int list) { L0123 for (; list != NO_JUMP; list = getjump(fs, list)) { L0124 Instruction i = *getjumpcontrol(fs, list); L0125 if (GET_OPCODE(i) != OP_TESTSET) return 1; L0126 } L0127 return 0; /* not found */ L0128 } L0129 L0130 L0131 static int patchtestreg (FuncState *fs, int node, int reg) { L0132 Instruction *i = getjumpcontrol(fs, node); L0133 if (GET_OPCODE(*i) != OP_TESTSET) L0134 return 0; /* cannot patch other instructions */ L0135 if (reg != NO_REG && reg != GETARG_B(*i)) L0136 SETARG_A(*i, reg); L0137 else /* no register to put value or register already has the value */ L0138 *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); L0139 L0140 return 1; L0141 } L0142 L0143 L0144 static void removevalues (FuncState *fs, int list) { L0145 for (; list != NO_JUMP; list = getjump(fs, list)) L0146 patchtestreg(fs, list, NO_REG); L0147 } L0148 L0149 L0150 static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, L0151 int dtarget) { L0152 while (list != NO_JUMP) { L0153 int next = getjump(fs, list); L0154 if (patchtestreg(fs, list, reg)) L0155 fixjump(fs, list, vtarget); L0156 else L0157 fixjump(fs, list, dtarget); /* jump to default target */ L0158 list = next; L0159 } L0160 } L0161 L0162 L0163 static void dischargejpc (FuncState *fs) { L0164 patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); L0165 fs->jpc = NO_JUMP; L0166 } L0167 L0168 L0169 void luaK_patchlist (FuncState *fs, int list, int target) { L0170 if (target == fs->pc) L0171 luaK_patchtohere(fs, list); L0172 else { L0173 lua_assert(target < fs->pc); L0174 patchlistaux(fs, list, target, NO_REG, target); L0175 } L0176 } L0177 L0178 L0179 void luaK_patchtohere (FuncState *fs, int list) { L0180 luaK_getlabel(fs); L0181 luaK_concat(fs, &fs->jpc, list); L0182 } L0183 L0184 L0185 void luaK_concat (FuncState *fs, int *l1, int l2) { L0186 if (l2 == NO_JUMP) return; L0187 else if (*l1 == NO_JUMP) L0188 *l1 = l2; L0189 else { L0190 int list = *l1; L0191 int next; L0192 while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ L0193 list = next; L0194 fixjump(fs, list, l2); L0195 } L0196 } L0197 L0198 L0199 void luaK_checkstack (FuncState *fs, int n) {
Updates function state's maximum needed stack size (maxstacksize) given that n additional registers will be needed. Raises syntax error if above limit (MAXSTACK).
L0200 int newstack = fs->freereg + n; L0201 if (newstack > fs->f->maxstacksize) { L0202 if (newstack >= MAXSTACK) L0203 luaX_syntaxerror(fs->ls, "function or expression too complex"); L0204 fs->f->maxstacksize = cast_byte(newstack); L0205 } L0206 } L0207 L0208 L0209 void luaK_reserveregs (FuncState *fs, int n) {
Like luaK_checkstack but also reserves those n additional registers.
L0210 luaK_checkstack(fs, n); L0211 fs->freereg += n; L0212 } L0213 L0214 L0215 static void freereg (FuncState *fs, int reg) {
This complements luaK_reserveregs. It frees the top-most reserved register. But it only does this if reg is actually a register (not an index in the constant table) and it's not used for storage of a local variable (the lowest nactvar values on the stack).
L0216 if (!ISK(reg) && reg >= fs->nactvar) { L0217 fs->freereg--; L0218 lua_assert(reg == fs->freereg); L0219 } L0220 } L0221 L0222 L0223 static void freeexp (FuncState *fs, expdesc *e) { L0224 if (e->k == VNONRELOC) L0225 freereg(fs, e->u.s.info); L0226 } L0227 L0228 L0229 static int addk (FuncState *fs, TValue *k, TValue *v) {
Adds a constant with name `key` and value v to the function state's constant table (i.e. array k of size sizek where first nk values are used). Duplicates are detected and avoided via the helper table 'h', which maps each existing value in the constant table to an integer index in the constant table. The constant table allocated size may need to be grown (and new empty space filled with nil's) prior to inserting the constant. (TODO-comment on luaC_barrier?) Returns 0-based index of the new constant in the constant table.
L0230 lua_State *L = fs->L; L0231 TValue *idx = luaH_set(L, fs->h, k); L0232 Proto *f = fs->f; L0233 int oldsize = f->sizek; L0234 if (ttisnumber(idx)) { L0235 lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); L0236 return cast_int(nvalue(idx)); L0237 } L0238 else { /* constant not found; create a new entry */ L0239 setnvalue(idx, cast_num(fs->nk)); L0240 luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, L0241 MAXARG_Bx, "constant table overflow"); L0242 while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); L0243 setobj(L, &f->k[fs->nk], v); L0244 luaC_barrier(L, f, v); L0245 return fs->nk++; L0246 } L0247 } L0248 L0249 L0250 int luaK_stringK (FuncState *fs, TString *s) {
Adds a string to the constant table (addk). Note: stores in TValue first.
L0251 TValue o; L0252 setsvalue(fs->L, &o, s); L0253 return addk(fs, &o, &o); L0254 } L0255 L0256 L0257 int luaK_numberK (FuncState *fs, lua_Number r) {
Adds a number to the constant table (addk). (TODO: comment on "numeric problems")
L0258 TValue o; L0259 setnvalue(&o, r); L0260 return addk(fs, &o, &o); L0261 } L0262 L0263 L0264 static int boolK (FuncState *fs, int b) {
Adds a boolean (0 or 1) to the constant table (addk).
L0265 TValue o; L0266 setbvalue(&o, b); L0267 return addk(fs, &o, &o); L0268 } L0269 L0270 L0271 static int nilK (FuncState *fs) {
Adds a nil to the constant table (addk). Note: the helper table 'h' (see addk) normally maps constant values to indicies in the constant table, but the constant value is nil here, which Lua tables don't allow. So, following a design pattern in http://lua-users.org/wiki/StoringNilsInTables, we use another unique value instead as its placeholder, which here is convenient to use the h table itself, which is never used outside of the compiler internal and therefore has no chance of misinterpretation. h is a Table, which we wrap in a TValue before doing addk.
L0272 TValue k, v; L0273 setnilvalue(&v); L0274 /* cannot use nil as key; instead use table itself to represent nil */ L0275 sethvalue(fs->L, &k, fs->h); L0276 return addk(fs, &k, &v); L0277 } L0278 L0279 L0280 void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { L0281 if (e->k == VCALL) { /* expression is an open function call? */ L0282 SETARG_C(getcode(fs, e), nresults+1); L0283 } L0284 else if (e->k == VVARARG) { L0285 SETARG_B(getcode(fs, e), nresults+1); L0286 SETARG_A(getcode(fs, e), fs->freereg); L0287 luaK_reserveregs(fs, 1); L0288 } L0289 } L0290 L0291 L0292 void luaK_setoneret (FuncState *fs, expdesc *e) { L0293 if (e->k == VCALL) { /* expression is an open function call? */ L0294 e->k = VNONRELOC; L0295 e->u.s.info = GETARG_A(getcode(fs, e)); L0296 } L0297 else if (e->k == VVARARG) { L0298 SETARG_B(getcode(fs, e), 2); L0299 e->k = VRELOCABLE; /* can relocate its simple result */ L0300 } L0301 } L0302 L0303 L0304 void luaK_dischargevars (FuncState *fs, expdesc *e) { L0305 switch (e->k) { L0306 case VLOCAL: { L0307 e->k = VNONRELOC; L0308 break; L0309 } L0310 case VUPVAL: { L0311 e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); L0312 e->k = VRELOCABLE; L0313 break; L0314 } L0315 case VGLOBAL: { L0316 e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); L0317 e->k = VRELOCABLE; L0318 break; L0319 } L0320 case VINDEXED: { L0321 freereg(fs, e->u.s.aux); L0322 freereg(fs, e->u.s.info); L0323 e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); L0324 e->k = VRELOCABLE; L0325 break; L0326 } L0327 case VVARARG: L0328 case VCALL: { L0329 luaK_setoneret(fs, e); L0330 break; L0331 } L0332 default: break; /* there is one value available (somewhere) */ L0333 } L0334 } L0335 L0336 L0337 static int code_label (FuncState *fs, int A, int b, int jump) { L0338 luaK_getlabel(fs); /* those instructions may be jump targets */ L0339 return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); L0340 } L0341 L0342 L0343 static void discharge2reg (FuncState *fs, expdesc *e, int reg) { L0344 luaK_dischargevars(fs, e); L0345 switch (e->k) { L0346 case VNIL: { L0347 luaK_nil(fs, reg, 1); L0348 break; L0349 } L0350 case VFALSE: case VTRUE: { L0351 luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); L0352 break; L0353 } L0354 case VK: { L0355 luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); L0356 break; L0357 } L0358 case VKNUM: { L0359 luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); L0360 break; L0361 } L0362 case VRELOCABLE: { L0363 Instruction *pc = &getcode(fs, e); L0364 SETARG_A(*pc, reg); L0365 break; L0366 } L0367 case VNONRELOC: { L0368 if (reg != e->u.s.info) L0369 luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); L0370 break; L0371 } L0372 default: { L0373 lua_assert(e->k == VVOID || e->k == VJMP); L0374 return; /* nothing to do... */ L0375 } L0376 } L0377 e->u.s.info = reg; L0378 e->k = VNONRELOC; L0379 } L0380 L0381 L0382 static void discharge2anyreg (FuncState *fs, expdesc *e) { L0383 if (e->k != VNONRELOC) { L0384 luaK_reserveregs(fs, 1); L0385 discharge2reg(fs, e, fs->freereg-1); L0386 } L0387 } L0388 L0389 L0390 static void exp2reg (FuncState *fs, expdesc *e, int reg) { L0391 discharge2reg(fs, e, reg); L0392 if (e->k == VJMP) L0393 luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ L0394 if (hasjumps(e)) { L0395 int final; /* position after whole expression */ L0396 int p_f = NO_JUMP; /* position of an eventual LOAD false */ L0397 int p_t = NO_JUMP; /* position of an eventual LOAD true */ L0398 if (need_value(fs, e->t) || need_value(fs, e->f)) { L0399 int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); L0400 p_f = code_label(fs, reg, 0, 1); L0401 p_t = code_label(fs, reg, 1, 0); L0402 luaK_patchtohere(fs, fj); L0403 } L0404 final = luaK_getlabel(fs); L0405 patchlistaux(fs, e->f, final, reg, p_f); L0406 patchlistaux(fs, e->t, final, reg, p_t); L0407 } L0408 e->f = e->t = NO_JUMP; L0409 e->u.s.info = reg; L0410 e->k = VNONRELOC; L0411 } L0412 L0413 L0414 void luaK_exp2nextreg (FuncState *fs, expdesc *e) { L0415 luaK_dischargevars(fs, e); L0416 freeexp(fs, e); L0417 luaK_reserveregs(fs, 1); L0418 exp2reg(fs, e, fs->freereg - 1); L0419 } L0420 L0421 L0422 int luaK_exp2anyreg (FuncState *fs, expdesc *e) { L0423 luaK_dischargevars(fs, e); L0424 if (e->k == VNONRELOC) { L0425 if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ L0426 if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ L0427 exp2reg(fs, e, e->u.s.info); /* put value on it */ L0428 return e->u.s.info; L0429 } L0430 } L0431 luaK_exp2nextreg(fs, e); /* default */ L0432 return e->u.s.info; L0433 } L0434 L0435 L0436 void luaK_exp2val (FuncState *fs, expdesc *e) { L0437 if (hasjumps(e)) L0438 luaK_exp2anyreg(fs, e); L0439 else L0440 luaK_dischargevars(fs, e); L0441 } L0442 L0443 L0444 int luaK_exp2RK (FuncState *fs, expdesc *e) { L0445 luaK_exp2val(fs, e); L0446 switch (e->k) { L0447 case VKNUM: L0448 case VTRUE: L0449 case VFALSE: L0450 case VNIL: { L0451 if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ L0452 e->u.s.info = (e->k == VNIL) ? nilK(fs) : L0453 (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : L0454 boolK(fs, (e->k == VTRUE)); L0455 e->k = VK; L0456 return RKASK(e->u.s.info); L0457 } L0458 else break; L0459 } L0460 case VK: { L0461 if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ L0462 return RKASK(e->u.s.info); L0463 else break; L0464 } L0465 default: break; L0466 } L0467 /* not a constant in the right range: put it in a register */ L0468 return luaK_exp2anyreg(fs, e); L0469 } L0470 L0471 L0472 void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { L0473 switch (var->k) { L0474 case VLOCAL: { L0475 freeexp(fs, ex); L0476 exp2reg(fs, ex, var->u.s.info); L0477 return; L0478 } L0479 case VUPVAL: { L0480 int e = luaK_exp2anyreg(fs, ex); L0481 luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); L0482 break; L0483 } L0484 case VGLOBAL: { L0485 int e = luaK_exp2anyreg(fs, ex); L0486 luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); L0487 break; L0488 } L0489 case VINDEXED: { L0490 int e = luaK_exp2RK(fs, ex); L0491 luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); L0492 break; L0493 } L0494 default: { L0495 lua_assert(0); /* invalid var kind to store */ L0496 break; L0497 } L0498 } L0499 freeexp(fs, ex); L0500 } L0501 L0502 L0503 void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { L0504 int func; L0505 luaK_exp2anyreg(fs, e); L0506 freeexp(fs, e); L0507 func = fs->freereg; L0508 luaK_reserveregs(fs, 2); L0509 luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); L0510 freeexp(fs, key); L0511 e->u.s.info = func; L0512 e->k = VNONRELOC; L0513 } L0514 L0515 L0516 static void invertjump (FuncState *fs, expdesc *e) { L0517 Instruction *pc = getjumpcontrol(fs, e->u.s.info); L0518 lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && L0519 GET_OPCODE(*pc) != OP_TEST); L0520 SETARG_A(*pc, !(GETARG_A(*pc))); L0521 } L0522 L0523 L0524 static int jumponcond (FuncState *fs, expdesc *e, int cond) { L0525 if (e->k == VRELOCABLE) { L0526 Instruction ie = getcode(fs, e); L0527 if (GET_OPCODE(ie) == OP_NOT) { L0528 fs->pc--; /* remove previous OP_NOT */ L0529 return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); L0530 } L0531 /* else go through */ L0532 } L0533 discharge2anyreg(fs, e); L0534 freeexp(fs, e); L0535 return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); L0536 } L0537 L0538 L0539 void luaK_goiftrue (FuncState *fs, expdesc *e) { L0540 int pc; /* pc of last jump */ L0541 luaK_dischargevars(fs, e); L0542 switch (e->k) { L0543 case VK: case VKNUM: case VTRUE: { L0544 pc = NO_JUMP; /* always true; do nothing */ L0545 break; L0546 } L0547 case VFALSE: { L0548 pc = luaK_jump(fs); /* always jump */ L0549 break; L0550 } L0551 case VJMP: { L0552 invertjump(fs, e); L0553 pc = e->u.s.info; L0554 break; L0555 } L0556 default: { L0557 pc = jumponcond(fs, e, 0); L0558 break; L0559 } L0560 } L0561 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ L0562 luaK_patchtohere(fs, e->t); L0563 e->t = NO_JUMP; L0564 } L0565 L0566 L0567 static void luaK_goiffalse (FuncState *fs, expdesc *e) { L0568 int pc; /* pc of last jump */ L0569 luaK_dischargevars(fs, e); L0570 switch (e->k) { L0571 case VNIL: case VFALSE: { L0572 pc = NO_JUMP; /* always false; do nothing */ L0573 break; L0574 } L0575 case VTRUE: { L0576 pc = luaK_jump(fs); /* always jump */ L0577 break; L0578 } L0579 case VJMP: { L0580 pc = e->u.s.info; L0581 break; L0582 } L0583 default: { L0584 pc = jumponcond(fs, e, 1); L0585 break; L0586 } L0587 } L0588 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ L0589 luaK_patchtohere(fs, e->f); L0590 e->f = NO_JUMP; L0591 } L0592 L0593 L0594 static void codenot (FuncState *fs, expdesc *e) { L0595 luaK_dischargevars(fs, e); L0596 switch (e->k) { L0597 case VNIL: case VFALSE: { L0598 e->k = VTRUE; L0599 break; L0600 } L0601 case VK: case VKNUM: case VTRUE: { L0602 e->k = VFALSE; L0603 break; L0604 } L0605 case VJMP: { L0606 invertjump(fs, e); L0607 break; L0608 } L0609 case VRELOCABLE: L0610 case VNONRELOC: { L0611 discharge2anyreg(fs, e); L0612 freeexp(fs, e); L0613 e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); L0614 e->k = VRELOCABLE; L0615 break; L0616 } L0617 default: { L0618 lua_assert(0); /* cannot happen */ L0619 break; L0620 } L0621 } L0622 /* interchange true and false lists */ L0623 { int temp = e->f; e->f = e->t; e->t = temp; } L0624 removevalues(fs, e->f); L0625 removevalues(fs, e->t); L0626 } L0627 L0628 L0629 void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { L0630 t->u.s.aux = luaK_exp2RK(fs, k); L0631 t->k = VINDEXED; L0632 } L0633 L0634 L0635 static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
Attempts to constant fold (i.e. evaluate at compile time as an optimization) the given operation on the two expressions. Folding is attempted only on operations on numbers that are known constants (e.g. `local x = 1+1` -> `local x = 2`). Moreover, constant folding is skipped on division (or modulo) by zero (resulting in not-a-number, NaN), which Lua 5.1 folded but it caused problems so this folding was eliminated in Lua 5.2. Returns 1 (not 0) if folding was possible. --see http://lua-users.org/lists/lua-l/2007-02/msg00207.html.
L0636 lua_Number v1, v2, r; L0637 if (!isnumeral(e1) || !isnumeral(e2)) return 0; L0638 v1 = e1->u.nval; L0639 v2 = e2->u.nval; L0640 switch (op) { L0641 case OP_ADD: r = luai_numadd(v1, v2); break; L0642 case OP_SUB: r = luai_numsub(v1, v2); break; L0643 case OP_MUL: r = luai_nummul(v1, v2); break; L0644 case OP_DIV: L0645 if (v2 == 0) return 0; /* do not attempt to divide by 0 */ L0646 r = luai_numdiv(v1, v2); break; L0647 case OP_MOD: L0648 if (v2 == 0) return 0; /* do not attempt to divide by 0 */ L0649 r = luai_nummod(v1, v2); break; L0650 case OP_POW: r = luai_numpow(v1, v2); break; L0651 case OP_UNM: r = luai_numunm(v1); break; L0652 case OP_LEN: return 0; /* no constant folding for 'len' */ L0653 default: lua_assert(0); r = 0; break; L0654 } L0655 if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ L0656 e1->u.nval = r; L0657 return 1; L0658 } L0659 L0660 L0661 static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { L0662 if (constfolding(op, e1, e2)) L0663 return; L0664 else { L0665 int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; L0666 int o1 = luaK_exp2RK(fs, e1); L0667 if (o1 > o2) { L0668 freeexp(fs, e1); L0669 freeexp(fs, e2); L0670 } L0671 else { L0672 freeexp(fs, e2); L0673 freeexp(fs, e1); L0674 } L0675 e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); L0676 e1->k = VRELOCABLE; L0677 } L0678 } L0679 L0680 L0681 static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, L0682 expdesc *e2) { L0683 int o1 = luaK_exp2RK(fs, e1); L0684 int o2 = luaK_exp2RK(fs, e2); L0685 freeexp(fs, e2); L0686 freeexp(fs, e1); L0687 if (cond == 0 && op != OP_EQ) { L0688 int temp; /* exchange args to replace by `<' or `<=' */ L0689 temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ L0690 cond = 1; L0691 } L0692 e1->u.s.info = condjump(fs, op, cond, o1, o2); L0693 e1->k = VJMP; L0694 } L0695 L0696 L0697 void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { L0698 expdesc e2; L0699 e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; L0700 switch (op) { L0701 case OPR_MINUS: { L0702 if (!isnumeral(e)) L0703 luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ L0704 codearith(fs, OP_UNM, e, &e2); L0705 break; L0706 } L0707 case OPR_NOT: codenot(fs, e); break; L0708 case OPR_LEN: { L0709 luaK_exp2anyreg(fs, e); /* cannot operate on constants */ L0710 codearith(fs, OP_LEN, e, &e2); L0711 break; L0712 } L0713 default: lua_assert(0); L0714 } L0715 } L0716 L0717 L0718 void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { L0719 switch (op) { L0720 case OPR_AND: { L0721 luaK_goiftrue(fs, v); L0722 break; L0723 } L0724 case OPR_OR: { L0725 luaK_goiffalse(fs, v); L0726 break; L0727 } L0728 case OPR_CONCAT: { L0729 luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ L0730 break; L0731 } L0732 case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: L0733 case OPR_MOD: case OPR_POW: { L0734 if (!isnumeral(v)) luaK_exp2RK(fs, v); L0735 break; L0736 } L0737 default: { L0738 luaK_exp2RK(fs, v); L0739 break; L0740 } L0741 } L0742 } L0743 L0744 L0745 void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { L0746 switch (op) { L0747 case OPR_AND: { L0748 lua_assert(e1->t == NO_JUMP); /* list must be closed */ L0749 luaK_dischargevars(fs, e2); L0750 luaK_concat(fs, &e2->f, e1->f); L0751 *e1 = *e2; L0752 break; L0753 } L0754 case OPR_OR: { L0755 lua_assert(e1->f == NO_JUMP); /* list must be closed */ L0756 luaK_dischargevars(fs, e2); L0757 luaK_concat(fs, &e2->t, e1->t); L0758 *e1 = *e2; L0759 break; L0760 } L0761 case OPR_CONCAT: { L0762 luaK_exp2val(fs, e2); L0763 if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { L0764 lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); L0765 freeexp(fs, e1); L0766 SETARG_B(getcode(fs, e2), e1->u.s.info); L0767 e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; L0768 } L0769 else { L0770 luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ L0771 codearith(fs, OP_CONCAT, e1, e2); L0772 } L0773 break; L0774 } L0775 case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; L0776 case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; L0777 case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; L0778 case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; L0779 case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; L0780 case OPR_POW: codearith(fs, OP_POW, e1, e2); break; L0781 case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; L0782 case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; L0783 case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; L0784 case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; L0785 case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; L0786 case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; L0787 default: lua_assert(0); L0788 } L0789 } L0790 L0791 L0792 void luaK_fixline (FuncState *fs, int line) { L0793 fs->f->lineinfo[fs->pc - 1] = line; L0794 } L0795 L0796 L0797 static int luaK_code (FuncState *fs, Instruction i, int line) { L0798 Proto *f = fs->f; L0799 dischargejpc(fs); /* `pc' will change */ L0800 /* put new instruction in code array */ L0801 luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, L0802 MAX_INT, "code size overflow"); L0803 f->code[fs->pc] = i; L0804 /* save corresponding line information */ L0805 luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, L0806 MAX_INT, "code size overflow"); L0807 f->lineinfo[fs->pc] = line; L0808 return fs->pc++; L0809 } L0810 L0811 L0812 int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { L0813 lua_assert(getOpMode(o) == iABC); L0814 lua_assert(getBMode(o) != OpArgN || b == 0); L0815 lua_assert(getCMode(o) != OpArgN || c == 0); L0816 return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); L0817 } L0818 L0819 L0820 int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { L0821 lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); L0822 lua_assert(getCMode(o) == OpArgN); L0823 return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); L0824 } L0825 L0826 L0827 void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { L0828 int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; L0829 int b = (tostore == LUA_MULTRET) ? 0 : tostore; L0830 lua_assert(tostore != 0); L0831 if (c <= MAXARG_C) L0832 luaK_codeABC(fs, OP_SETLIST, base, b, c); L0833 else { L0834 luaK_codeABC(fs, OP_SETLIST, base, b, 0); L0835 luaK_code(fs, cast(Instruction, c), fs->ls->lastline); L0836 } L0837 fs->freereg = base + 1; /* free registers with list values */ L0838 } L0839

Generated by pretty.lua