The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/lua/lcode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 7da107e2ddd3203613c96bc3d58ee98f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.