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