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