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