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