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