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