LCOV - code coverage report
Current view: directory - src - lcode.c Found Hit Coverage
Test: Lua 5.1.4 Lines: 458 442 96.5 %
Date: 2009-09-13
Colors: not hit hit

       1                 : /*
       2                 : ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
       3                 : ** Code generator for Lua
       4                 : ** See Copyright Notice in lua.h
       5                 : */
       6                 : 
       7                 : 
       8                 : #include <stdlib.h>
       9                 : 
      10                 : #define lcode_c
      11                 : #define LUA_CORE
      12                 : 
      13                 : #include "lua.h"
      14                 : 
      15                 : #include "lcode.h"
      16                 : #include "ldebug.h"
      17                 : #include "ldo.h"
      18                 : #include "lgc.h"
      19                 : #include "llex.h"
      20                 : #include "lmem.h"
      21                 : #include "lobject.h"
      22                 : #include "lopcodes.h"
      23                 : #include "lparser.h"
      24                 : #include "ltable.h"
      25                 : 
      26                 : 
      27                 : #define hasjumps(e)     ((e)->t != (e)->f)
      28                 : 
      29                 : 
      30            1915 : static int isnumeral(expdesc *e) {
      31            1915 :   return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
      32                 : }
      33                 : 
      34                 : 
      35             182 : void luaK_nil (FuncState *fs, int from, int n) {
      36                 :   Instruction *previous;
      37             182 :   if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
      38             175 :     if (fs->pc == 0) {  /* function start? */
      39              33 :       if (from >= fs->nactvar)
      40              33 :         return;  /* positions are already clean */
      41                 :     }
      42                 :     else {
      43             142 :       previous = &fs->f->code[fs->pc-1];
      44             142 :       if (GET_OPCODE(*previous) == OP_LOADNIL) {
      45               2 :         int pfrom = GETARG_A(*previous);
      46               2 :         int pto = GETARG_B(*previous);
      47               2 :         if (pfrom <= from && from <= pto+1) {  /* can connect both? */
      48               2 :           if (from+n-1 > pto)
      49               2 :             SETARG_B(*previous, from+n-1);
      50               2 :           return;
      51                 :         }
      52                 :       }
      53                 :     }
      54                 :   }
      55             147 :   luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
      56                 : }
      57                 : 
      58                 : 
      59            2120 : int luaK_jump (FuncState *fs) {
      60            2120 :   int jpc = fs->jpc;  /* save list of jumps to here */
      61                 :   int j;
      62            2120 :   fs->jpc = NO_JUMP;
      63            2120 :   j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
      64            2120 :   luaK_concat(fs, &j, jpc);  /* keep them on hold */
      65            2120 :   return j;
      66                 : }
      67                 : 
      68                 : 
      69            2626 : void luaK_ret (FuncState *fs, int first, int nret) {
      70            2626 :   luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
      71            2626 : }
      72                 : 
      73                 : 
      74            1454 : static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
      75            1454 :   luaK_codeABC(fs, op, A, B, C);
      76            1454 :   return luaK_jump(fs);
      77                 : }
      78                 : 
      79                 : 
      80            2473 : static void fixjump (FuncState *fs, int pc, int dest) {
      81            2473 :   Instruction *jmp = &fs->f->code[pc];
      82            2473 :   int offset = dest-(pc+1);
      83                 :   lua_assert(dest != NO_JUMP);
      84            2473 :   if (abs(offset) > MAXARG_sBx)
      85               0 :     luaX_syntaxerror(fs->ls, "control structure too long");
      86            2473 :   SETARG_sBx(*jmp, offset);
      87            2473 : }
      88                 : 
      89                 : 
      90                 : /*
      91                 : ** returns current `pc' and marks it as a jump target (to avoid wrong
      92                 : ** optimizations with consecutive instructions not in the same basic block).
      93                 : */
      94            6030 : int luaK_getlabel (FuncState *fs) {
      95            6030 :   fs->lasttarget = fs->pc;
      96            6030 :   return fs->pc;
      97                 : }
      98                 : 
      99                 : 
     100            2675 : static int getjump (FuncState *fs, int pc) {
     101            2675 :   int offset = GETARG_sBx(fs->f->code[pc]);
     102            2675 :   if (offset == NO_JUMP)  /* point to itself represents end of list */
     103            2349 :     return NO_JUMP;  /* end of list */
     104                 :   else
     105             326 :     return (pc+1)+offset;  /* turn offset into absolute position */
     106                 : }
     107                 : 
     108                 : 
     109            3298 : static Instruction *getjumpcontrol (FuncState *fs, int pc) {
     110            3298 :   Instruction *pi = &fs->f->code[pc];
     111            3298 :   if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
     112            2674 :     return pi-1;
     113                 :   else
     114             624 :     return pi;
     115                 : }
     116                 : 
     117                 : 
     118                 : /*
     119                 : ** check whether list has any jump that do not produce a value
     120                 : ** (or produce an inverted value)
     121                 : */
     122             623 : static int need_value (FuncState *fs, int list) {
     123             752 :   for (; list != NO_JUMP; list = getjump(fs, list)) {
     124             491 :     Instruction i = *getjumpcontrol(fs, list);
     125             491 :     if (GET_OPCODE(i) != OP_TESTSET) return 1;
     126                 :   }
     127             261 :   return 0;  /* not found */
     128                 : }
     129                 : 
     130                 : 
     131            2220 : static int patchtestreg (FuncState *fs, int node, int reg) {
     132            2220 :   Instruction *i = getjumpcontrol(fs, node);
     133            2220 :   if (GET_OPCODE(*i) != OP_TESTSET)
     134            1995 :     return 0;  /* cannot patch other instructions */
     135             227 :   if (reg != NO_REG && reg != GETARG_B(*i))
     136               2 :     SETARG_A(*i, reg);
     137                 :   else  /* no register to put value or register already has the value */
     138             223 :     *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
     139                 : 
     140             225 :   return 1;
     141                 : }
     142                 : 
     143                 : 
     144             708 : static void removevalues (FuncState *fs, int list) {
     145             708 :   for (; list != NO_JUMP; list = getjump(fs, list))
     146               0 :       patchtestreg(fs, list, NO_REG);
     147             708 : }
     148                 : 
     149                 : 
     150                 : static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
     151           40060 :                           int dtarget) {
     152           82340 :   while (list != NO_JUMP) {
     153            2220 :     int next = getjump(fs, list);
     154            2220 :     if (patchtestreg(fs, list, reg))
     155             225 :       fixjump(fs, list, vtarget);
     156                 :     else
     157            1995 :       fixjump(fs, list, dtarget);  /* jump to default target */
     158            2220 :     list = next;
     159                 :   }
     160           40060 : }
     161                 : 
     162                 : 
     163           38868 : static void dischargejpc (FuncState *fs) {
     164           38868 :   patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
     165           38868 :   fs->jpc = NO_JUMP;
     166           38868 : }
     167                 : 
     168                 : 
     169             210 : void luaK_patchlist (FuncState *fs, int list, int target) {
     170             210 :   if (target == fs->pc)
     171               0 :     luaK_patchtohere(fs, list);
     172                 :   else {
     173                 :     lua_assert(target < fs->pc);
     174             210 :     patchlistaux(fs, list, target, NO_REG, target);
     175                 :   }
     176             210 : }
     177                 : 
     178                 : 
     179            4800 : void luaK_patchtohere (FuncState *fs, int list) {
     180            4800 :   luaK_getlabel(fs);
     181            4800 :   luaK_concat(fs, &fs->jpc, list);
     182            4800 : }
     183                 : 
     184                 : 
     185            9486 : void luaK_concat (FuncState *fs, int *l1, int l2) {
     186            9486 :   if (l2 == NO_JUMP) return;
     187            4054 :   else if (*l1 == NO_JUMP)
     188            3801 :     *l1 = l2;
     189                 :   else {
     190             253 :     int list = *l1;
     191                 :     int next;
     192             579 :     while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
     193              73 :       list = next;
     194             253 :     fixjump(fs, list, l2);
     195                 :   }
     196                 : }
     197                 : 
     198                 : 
     199           25072 : void luaK_checkstack (FuncState *fs, int n) {
     200           25072 :   int newstack = fs->freereg + n;
     201           25072 :   if (newstack > fs->f->maxstacksize) {
     202            5859 :     if (newstack >= MAXSTACK)
     203               0 :       luaX_syntaxerror(fs->ls, "function or expression too complex");
     204            5859 :     fs->f->maxstacksize = cast_byte(newstack);
     205                 :   }
     206           25072 : }
     207                 : 
     208                 : 
     209           24927 : void luaK_reserveregs (FuncState *fs, int n) {
     210           24927 :   luaK_checkstack(fs, n);
     211           24927 :   fs->freereg += n;
     212           24927 : }
     213                 : 
     214                 : 
     215           16265 : static void freereg (FuncState *fs, int reg) {
     216           16265 :   if (!ISK(reg) && reg >= fs->nactvar) {
     217            8542 :     fs->freereg--;
     218                 :     lua_assert(reg == fs->freereg);
     219                 :   }
     220           16265 : }
     221                 : 
     222                 : 
     223           31149 : static void freeexp (FuncState *fs, expdesc *e) {
     224           31149 :   if (e->k == VNONRELOC)
     225           11533 :     freereg(fs, e->u.s.info);
     226           31149 : }
     227                 : 
     228                 : 
     229           14387 : static int addk (FuncState *fs, TValue *k, TValue *v) {
     230           14387 :   lua_State *L = fs->L;
     231           14387 :   TValue *idx = luaH_set(L, fs->h, k);
     232           14387 :   Proto *f = fs->f;
     233           14387 :   int oldsize = f->sizek;
     234           14387 :   if (ttisnumber(idx)) {
     235                 :     lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
     236            5415 :     return cast_int(nvalue(idx));
     237                 :   }
     238                 :   else {  /* constant not found; create a new entry */
     239            8972 :     setnvalue(idx, cast_num(fs->nk));
     240            8972 :     luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
     241                 :                     MAXARG_Bx, "constant table overflow");
     242            8972 :     while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
     243            8972 :     setobj(L, &f->k[fs->nk], v);
     244            8972 :     luaC_barrier(L, f, v);
     245            8972 :     return fs->nk++;
     246                 :   }
     247                 : }
     248                 : 
     249                 : 
     250           12234 : int luaK_stringK (FuncState *fs, TString *s) {
     251                 :   TValue o;
     252           12234 :   setsvalue(fs->L, &o, s);
     253           12234 :   return addk(fs, &o, &o);
     254                 : }
     255                 : 
     256                 : 
     257            2052 : int luaK_numberK (FuncState *fs, lua_Number r) {
     258                 :   TValue o;
     259            2052 :   setnvalue(&o, r);
     260            2052 :   return addk(fs, &o, &o);
     261                 : }
     262                 : 
     263                 : 
     264              38 : static int boolK (FuncState *fs, int b) {
     265                 :   TValue o;
     266              38 :   setbvalue(&o, b);
     267              38 :   return addk(fs, &o, &o);
     268                 : }
     269                 : 
     270                 : 
     271              63 : static int nilK (FuncState *fs) {
     272                 :   TValue k, v;
     273              63 :   setnilvalue(&v);
     274                 :   /* cannot use nil as key; instead use table itself to represent nil */
     275              63 :   sethvalue(fs->L, &k, fs->h);
     276              63 :   return addk(fs, &k, &v);
     277                 : }
     278                 : 
     279                 : 
     280            5606 : void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
     281            5606 :   if (e->k == VCALL) {  /* expression is an open function call? */
     282             828 :     SETARG_C(getcode(fs, e), nresults+1);
     283                 :   }
     284            4778 :   else if (e->k == VVARARG) {
     285              12 :     SETARG_B(getcode(fs, e), nresults+1);
     286              12 :     SETARG_A(getcode(fs, e), fs->freereg);
     287              12 :     luaK_reserveregs(fs, 1);
     288                 :   }
     289            5606 : }
     290                 : 
     291                 : 
     292            2456 : void luaK_setoneret (FuncState *fs, expdesc *e) {
     293            2456 :   if (e->k == VCALL) {  /* expression is an open function call? */
     294            1363 :     e->k = VNONRELOC;
     295            1363 :     e->u.s.info = GETARG_A(getcode(fs, e));
     296                 :   }
     297            1093 :   else if (e->k == VVARARG) {
     298               1 :     SETARG_B(getcode(fs, e), 2);
     299               1 :     e->k = VRELOCABLE;  /* can relocate its simple result */
     300                 :   }
     301            2456 : }
     302                 : 
     303                 : 
     304           68729 : void luaK_dischargevars (FuncState *fs, expdesc *e) {
     305           68729 :   switch (e->k) {
     306                 :     case VLOCAL: {
     307            5681 :       e->k = VNONRELOC;
     308            5681 :       break;
     309                 :     }
     310                 :     case VUPVAL: {
     311            2617 :       e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
     312            2617 :       e->k = VRELOCABLE;
     313            2617 :       break;
     314                 :     }
     315                 :     case VGLOBAL: {
     316            3851 :       e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
     317            3851 :       e->k = VRELOCABLE;
     318            3851 :       break;
     319                 :     }
     320                 :     case VINDEXED: {
     321            2366 :       freereg(fs, e->u.s.aux);
     322            2366 :       freereg(fs, e->u.s.info);
     323            2366 :       e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
     324            2366 :       e->k = VRELOCABLE;
     325            2366 :       break;
     326                 :     }
     327                 :     case VVARARG:
     328                 :     case VCALL: {
     329            1135 :       luaK_setoneret(fs, e);
     330                 :       break;
     331                 :     }
     332                 :     default: break;  /* there is one value available (somewhere) */
     333                 :   }
     334           68729 : }
     335                 : 
     336                 : 
     337             724 : static int code_label (FuncState *fs, int A, int b, int jump) {
     338             724 :   luaK_getlabel(fs);  /* those instructions may be jump targets */
     339             724 :   return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
     340                 : }
     341                 : 
     342                 : 
     343           23090 : static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
     344           23090 :   luaK_dischargevars(fs, e);
     345           23090 :   switch (e->k) {
     346                 :     case VNIL: {
     347             117 :       luaK_nil(fs, reg, 1);
     348             117 :       break;
     349                 :     }
     350                 :     case VFALSE:  case VTRUE: {
     351             534 :       luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
     352             534 :       break;
     353                 :     }
     354                 :     case VK: {
     355            3829 :       luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
     356            3829 :       break;
     357                 :     }
     358                 :     case VKNUM: {
     359            1316 :       luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
     360            1316 :       break;
     361                 :     }
     362                 :     case VRELOCABLE: {
     363           12143 :       Instruction *pc = &getcode(fs, e);
     364           12143 :       SETARG_A(*pc, reg);
     365           12143 :       break;
     366                 :     }
     367                 :     case VNONRELOC: {
     368            4792 :       if (reg != e->u.s.info)
     369            3574 :         luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
     370            4792 :       break;
     371                 :     }
     372                 :     default: {
     373                 :       lua_assert(e->k == VVOID || e->k == VJMP);
     374             359 :       return;  /* nothing to do... */
     375                 :     }
     376                 :   }
     377           22731 :   e->u.s.info = reg;
     378           22731 :   e->k = VNONRELOC;
     379                 : }
     380                 : 
     381                 : 
     382             568 : static void discharge2anyreg (FuncState *fs, expdesc *e) {
     383             568 :   if (e->k != VNONRELOC) {
     384              50 :     luaK_reserveregs(fs, 1);
     385              50 :     discharge2reg(fs, e, fs->freereg-1);
     386                 :   }
     387             568 : }
     388                 : 
     389                 : 
     390           23040 : static void exp2reg (FuncState *fs, expdesc *e, int reg) {
     391           23040 :   discharge2reg(fs, e, reg);
     392           23040 :   if (e->k == VJMP)
     393             359 :     luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */
     394           23040 :   if (hasjumps(e)) {
     395                 :     int final;  /* position after whole expression */
     396             491 :     int p_f = NO_JUMP;  /* position of an eventual LOAD false */
     397             491 :     int p_t = NO_JUMP;  /* position of an eventual LOAD true */
     398             491 :     if (need_value(fs, e->t) || need_value(fs, e->f)) {
     399             362 :       int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
     400             362 :       p_f = code_label(fs, reg, 0, 1);
     401             362 :       p_t = code_label(fs, reg, 1, 0);
     402             362 :       luaK_patchtohere(fs, fj);
     403                 :     }
     404             491 :     final = luaK_getlabel(fs);
     405             491 :     patchlistaux(fs, e->f, final, reg, p_f);
     406             491 :     patchlistaux(fs, e->t, final, reg, p_t);
     407                 :   }
     408           23040 :   e->f = e->t = NO_JUMP;
     409           23040 :   e->u.s.info = reg;
     410           23040 :   e->k = VNONRELOC;
     411           23040 : }
     412                 : 
     413                 : 
     414           22554 : void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
     415           22554 :   luaK_dischargevars(fs, e);
     416           22554 :   freeexp(fs, e);
     417           22554 :   luaK_reserveregs(fs, 1);
     418           22554 :   exp2reg(fs, e, fs->freereg - 1);
     419           22554 : }
     420                 : 
     421                 : 
     422           10420 : int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
     423           10420 :   luaK_dischargevars(fs, e);
     424           10420 :   if (e->k == VNONRELOC) {
     425            5031 :     if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */
     426               2 :     if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */
     427               1 :       exp2reg(fs, e, e->u.s.info);  /* put value on it */
     428               1 :       return e->u.s.info;
     429                 :     }
     430                 :   }
     431            5390 :   luaK_exp2nextreg(fs, e);  /* default */
     432            5390 :   return e->u.s.info;
     433                 : }
     434                 : 
     435                 : 
     436           10997 : void luaK_exp2val (FuncState *fs, expdesc *e) {
     437           10997 :   if (hasjumps(e))
     438               0 :     luaK_exp2anyreg(fs, e);
     439                 :   else
     440           10997 :     luaK_dischargevars(fs, e);
     441           10997 : }
     442                 : 
     443                 : 
     444            9046 : int luaK_exp2RK (FuncState *fs, expdesc *e) {
     445            9046 :   luaK_exp2val(fs, e);
     446            9046 :   switch (e->k) {
     447                 :     case VKNUM:
     448                 :     case VTRUE:
     449                 :     case VFALSE:
     450                 :     case VNIL: {
     451             797 :       if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
     452             797 :         e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
     453                 :                       (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
     454                 :                                         boolK(fs, (e->k == VTRUE));
     455             797 :         e->k = VK;
     456             797 :         return RKASK(e->u.s.info);
     457                 :       }
     458               0 :       else break;
     459                 :     }
     460                 :     case VK: {
     461            3225 :       if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */
     462            3225 :         return RKASK(e->u.s.info);
     463               0 :       else break;
     464                 :     }
     465                 :     default: break;
     466                 :   }
     467                 :   /* not a constant in the right range: put it in a register */
     468            5024 :   return luaK_exp2anyreg(fs, e);
     469                 : }
     470                 : 
     471                 : 
     472            2402 : void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
     473            2402 :   switch (var->k) {
     474                 :     case VLOCAL: {
     475             485 :       freeexp(fs, ex);
     476             485 :       exp2reg(fs, ex, var->u.s.info);
     477             485 :       return;
     478                 :     }
     479                 :     case VUPVAL: {
     480             317 :       int e = luaK_exp2anyreg(fs, ex);
     481             317 :       luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
     482             317 :       break;
     483                 :     }
     484                 :     case VGLOBAL: {
     485            1432 :       int e = luaK_exp2anyreg(fs, ex);
     486            1432 :       luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
     487            1432 :       break;
     488                 :     }
     489                 :     case VINDEXED: {
     490             168 :       int e = luaK_exp2RK(fs, ex);
     491             168 :       luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
     492                 :       break;
     493                 :     }
     494                 :     default: {
     495                 :       lua_assert(0);  /* invalid var kind to store */
     496                 :       break;
     497                 :     }
     498                 :   }
     499            1917 :   freeexp(fs, ex);
     500                 : }
     501                 : 
     502                 : 
     503             183 : void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
     504                 :   int func;
     505             183 :   luaK_exp2anyreg(fs, e);
     506             183 :   freeexp(fs, e);
     507             183 :   func = fs->freereg;
     508             183 :   luaK_reserveregs(fs, 2);
     509             183 :   luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
     510             183 :   freeexp(fs, key);
     511             183 :   e->u.s.info = func;
     512             183 :   e->k = VNONRELOC;
     513             183 : }
     514                 : 
     515                 : 
     516             587 : static void invertjump (FuncState *fs, expdesc *e) {
     517             587 :   Instruction *pc = getjumpcontrol(fs, e->u.s.info);
     518                 :   lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
     519                 :                                            GET_OPCODE(*pc) != OP_TEST);
     520             587 :   SETARG_A(*pc, !(GETARG_A(*pc)));
     521             587 : }
     522                 : 
     523                 : 
     524             507 : static int jumponcond (FuncState *fs, expdesc *e, int cond) {
     525             507 :   if (e->k == VRELOCABLE) {
     526             320 :     Instruction ie = getcode(fs, e);
     527             320 :     if (GET_OPCODE(ie) == OP_NOT) {
     528             282 :       fs->pc--;  /* remove previous OP_NOT */
     529             282 :       return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
     530                 :     }
     531                 :     /* else go through */
     532                 :   }
     533             225 :   discharge2anyreg(fs, e);
     534             225 :   freeexp(fs, e);
     535             225 :   return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
     536                 : }
     537                 : 
     538                 : 
     539             975 : void luaK_goiftrue (FuncState *fs, expdesc *e) {
     540                 :   int pc;  /* pc of last jump */
     541             975 :   luaK_dischargevars(fs, e);
     542             975 :   switch (e->k) {
     543                 :     case VK: case VKNUM: case VTRUE: {
     544               4 :       pc = NO_JUMP;  /* always true; do nothing */
     545               4 :       break;
     546                 :     }
     547                 :     case VFALSE: {
     548               4 :       pc = luaK_jump(fs);  /* always jump */
     549               4 :       break;
     550                 :     }
     551                 :     case VJMP: {
     552             587 :       invertjump(fs, e);
     553             587 :       pc = e->u.s.info;
     554             587 :       break;
     555                 :     }
     556                 :     default: {
     557             380 :       pc = jumponcond(fs, e, 0);
     558                 :       break;
     559                 :     }
     560                 :   }
     561             975 :   luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
     562             975 :   luaK_patchtohere(fs, e->t);
     563             975 :   e->t = NO_JUMP;
     564             975 : }
     565                 : 
     566                 : 
     567             132 : static void luaK_goiffalse (FuncState *fs, expdesc *e) {
     568                 :   int pc;  /* pc of last jump */
     569             132 :   luaK_dischargevars(fs, e);
     570             132 :   switch (e->k) {
     571                 :     case VNIL: case VFALSE: {
     572               4 :       pc = NO_JUMP;  /* always false; do nothing */
     573               4 :       break;
     574                 :     }
     575                 :     case VTRUE: {
     576               0 :       pc = luaK_jump(fs);  /* always jump */
     577               0 :       break;
     578                 :     }
     579                 :     case VJMP: {
     580               1 :       pc = e->u.s.info;
     581               1 :       break;
     582                 :     }
     583                 :     default: {
     584             127 :       pc = jumponcond(fs, e, 1);
     585                 :       break;
     586                 :     }
     587                 :   }
     588             132 :   luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
     589             132 :   luaK_patchtohere(fs, e->f);
     590             132 :   e->f = NO_JUMP;
     591             132 : }
     592                 : 
     593                 : 
     594             354 : static void codenot (FuncState *fs, expdesc *e) {
     595             354 :   luaK_dischargevars(fs, e);
     596             354 :   switch (e->k) {
     597                 :     case VNIL: case VFALSE: {
     598               5 :       e->k = VTRUE;
     599               5 :       break;
     600                 :     }
     601                 :     case VK: case VKNUM: case VTRUE: {
     602               6 :       e->k = VFALSE;
     603               6 :       break;
     604                 :     }
     605                 :     case VJMP: {
     606               0 :       invertjump(fs, e);
     607               0 :       break;
     608                 :     }
     609                 :     case VRELOCABLE:
     610                 :     case VNONRELOC: {
     611             343 :       discharge2anyreg(fs, e);
     612             343 :       freeexp(fs, e);
     613             343 :       e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
     614             343 :       e->k = VRELOCABLE;
     615                 :       break;
     616                 :     }
     617                 :     default: {
     618                 :       lua_assert(0);  /* cannot happen */
     619                 :       break;
     620                 :     }
     621                 :   }
     622                 :   /* interchange true and false lists */
     623             354 :   { int temp = e->f; e->f = e->t; e->t = temp; }
     624             354 :   removevalues(fs, e->f);
     625             354 :   removevalues(fs, e->t);
     626             354 : }
     627                 : 
     628                 : 
     629            2534 : void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
     630            2534 :   t->u.s.aux = luaK_exp2RK(fs, k);
     631            2534 :   t->k = VINDEXED;
     632            2534 : }
     633                 : 
     634                 : 
     635            1325 : static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
     636                 :   lua_Number v1, v2, r;
     637            1325 :   if (!isnumeral(e1) || !isnumeral(e2)) return 0;
     638              72 :   v1 = e1->u.nval;
     639              72 :   v2 = e2->u.nval;
     640              72 :   switch (op) {
     641               2 :     case OP_ADD: r = luai_numadd(v1, v2); break;
     642               1 :     case OP_SUB: r = luai_numsub(v1, v2); break;
     643               2 :     case OP_MUL: r = luai_nummul(v1, v2); break;
     644                 :     case OP_DIV:
     645               3 :       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
     646               1 :       r = luai_numdiv(v1, v2); break;
     647                 :     case OP_MOD:
     648               3 :       if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
     649               1 :       r = luai_nummod(v1, v2); break;
     650               0 :     case OP_POW: r = luai_numpow(v1, v2); break;
     651              61 :     case OP_UNM: r = luai_numunm(v1); break;
     652               0 :     case OP_LEN: return 0;  /* no constant folding for 'len' */
     653               0 :     default: lua_assert(0); r = 0; break;
     654                 :   }
     655              68 :   if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
     656              68 :   e1->u.nval = r;
     657              68 :   return 1;
     658                 : }
     659                 : 
     660                 : 
     661            1325 : static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
     662            1325 :   if (constfolding(op, e1, e2))
     663              68 :     return;
     664                 :   else {
     665            1257 :     int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
     666            1257 :     int o1 = luaK_exp2RK(fs, e1);
     667            1257 :     if (o1 > o2) {
     668             147 :       freeexp(fs, e1);
     669             147 :       freeexp(fs, e2);
     670                 :     }
     671                 :     else {
     672            1110 :       freeexp(fs, e2);
     673            1110 :       freeexp(fs, e1);
     674                 :     }
     675            1257 :     e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
     676            1257 :     e1->k = VRELOCABLE;
     677                 :   }
     678                 : }
     679                 : 
     680                 : 
     681                 : static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
     682             947 :                                                           expdesc *e2) {
     683             947 :   int o1 = luaK_exp2RK(fs, e1);
     684             947 :   int o2 = luaK_exp2RK(fs, e2);
     685             947 :   freeexp(fs, e2);
     686             947 :   freeexp(fs, e1);
     687             947 :   if (cond == 0 && op != OP_EQ) {
     688                 :     int temp;  /* exchange args to replace by `<' or `<=' */
     689             128 :     temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
     690             128 :     cond = 1;
     691                 :   }
     692             947 :   e1->u.s.info = condjump(fs, op, cond, o1, o2);
     693             947 :   e1->k = VJMP;
     694             947 : }
     695                 : 
     696                 : 
     697             661 : void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
     698                 :   expdesc e2;
     699             661 :   e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
     700             661 :   switch (op) {
     701                 :     case OPR_MINUS: {
     702              75 :       if (!isnumeral(e))
     703              14 :         luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */
     704              75 :       codearith(fs, OP_UNM, e, &e2);
     705              75 :       break;
     706                 :     }
     707             354 :     case OPR_NOT: codenot(fs, e); break;
     708                 :     case OPR_LEN: {
     709             232 :       luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
     710             232 :       codearith(fs, OP_LEN, e, &e2);
     711                 :       break;
     712                 :     }
     713                 :     default: lua_assert(0);
     714                 :   }
     715             661 : }
     716                 : 
     717                 : 
     718            2991 : void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
     719            2991 :   switch (op) {
     720                 :     case OPR_AND: {
     721              43 :       luaK_goiftrue(fs, v);
     722              43 :       break;
     723                 :     }
     724                 :     case OPR_OR: {
     725             132 :       luaK_goiffalse(fs, v);
     726             132 :       break;
     727                 :     }
     728                 :     case OPR_CONCAT: {
     729            1460 :       luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
     730            1460 :       break;
     731                 :     }
     732                 :     case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
     733                 :     case OPR_MOD: case OPR_POW: {
     734             409 :       if (!isnumeral(v)) luaK_exp2RK(fs, v);
     735             409 :       break;
     736                 :     }
     737                 :     default: {
     738             947 :       luaK_exp2RK(fs, v);
     739                 :       break;
     740                 :     }
     741                 :   }
     742            2991 : }
     743                 : 
     744                 : 
     745            2991 : void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
     746            2991 :   switch (op) {
     747                 :     case OPR_AND: {
     748                 :       lua_assert(e1->t == NO_JUMP);  /* list must be closed */
     749              43 :       luaK_dischargevars(fs, e2);
     750              43 :       luaK_concat(fs, &e2->f, e1->f);
     751              43 :       *e1 = *e2;
     752              43 :       break;
     753                 :     }
     754                 :     case OPR_OR: {
     755                 :       lua_assert(e1->f == NO_JUMP);  /* list must be closed */
     756             132 :       luaK_dischargevars(fs, e2);
     757             132 :       luaK_concat(fs, &e2->t, e1->t);
     758             132 :       *e1 = *e2;
     759             132 :       break;
     760                 :     }
     761                 :     case OPR_CONCAT: {
     762            1460 :       luaK_exp2val(fs, e2);
     763            2311 :       if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
     764                 :         lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
     765             851 :         freeexp(fs, e1);
     766             851 :         SETARG_B(getcode(fs, e2), e1->u.s.info);
     767             851 :         e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
     768                 :       }
     769                 :       else {
     770             609 :         luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
     771             609 :         codearith(fs, OP_CONCAT, e1, e2);
     772                 :       }
     773            1460 :       break;
     774                 :     }
     775             201 :     case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
     776              82 :     case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
     777              55 :     case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
     778              34 :     case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
     779              17 :     case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
     780              20 :     case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
     781             455 :     case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
     782             217 :     case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
     783              89 :     case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
     784              58 :     case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
     785              59 :     case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
     786              69 :     case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
     787                 :     default: lua_assert(0);
     788                 :   }
     789            2991 : }
     790                 : 
     791                 : 
     792            6165 : void luaK_fixline (FuncState *fs, int line) {
     793            6165 :   fs->f->lineinfo[fs->pc - 1] = line;
     794            6165 : }
     795                 : 
     796                 : 
     797           38868 : static int luaK_code (FuncState *fs, Instruction i, int line) {
     798           38868 :   Proto *f = fs->f;
     799           38868 :   dischargejpc(fs);  /* `pc' will change */
     800                 :   /* put new instruction in code array */
     801           38868 :   luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
     802                 :                   MAX_INT, "code size overflow");
     803           38868 :   f->code[fs->pc] = i;
     804                 :   /* save corresponding line information */
     805           38868 :   luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
     806                 :                   MAX_INT, "code size overflow");
     807           38868 :   f->lineinfo[fs->pc] = line;
     808           38868 :   return fs->pc++;
     809                 : }
     810                 : 
     811                 : 
     812           24736 : int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
     813                 :   lua_assert(getOpMode(o) == iABC);
     814                 :   lua_assert(getBMode(o) != OpArgN || b == 0);
     815                 :   lua_assert(getCMode(o) != OpArgN || c == 0);
     816           24736 :   return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
     817                 : }
     818                 : 
     819                 : 
     820           14132 : int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
     821                 :   lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
     822                 :   lua_assert(getCMode(o) == OpArgN);
     823           14132 :   return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
     824                 : }
     825                 : 
     826                 : 
     827             324 : void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
     828             324 :   int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
     829             324 :   int b = (tostore == LUA_MULTRET) ? 0 : tostore;
     830                 :   lua_assert(tostore != 0);
     831             324 :   if (c <= MAXARG_C)
     832             324 :     luaK_codeABC(fs, OP_SETLIST, base, b, c);
     833                 :   else {
     834               0 :     luaK_codeABC(fs, OP_SETLIST, base, b, 0);
     835               0 :     luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
     836                 :   }
     837             324 :   fs->freereg = base + 1;  /* free registers with list values */
     838             324 : }
     839                 : 

Generated by: LCOV version 1.7