LCOV - code coverage report
Current view: top level - ugbase/bindings/lua/externals/lua - lcode.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 426 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 47 0

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

Generated by: LCOV version 2.0-1