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