1*0a6a1f1dSLionel Sambuc /* $NetBSD: lcode.c,v 1.4 2015/10/08 13:21:00 mbalmer Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*
4*0a6a1f1dSLionel Sambuc ** Id: lcode.c,v 2.101 2015/04/29 18:24:11 roberto Exp
511be35a1SLionel Sambuc ** Code generator for Lua
611be35a1SLionel Sambuc ** See Copyright Notice in lua.h
711be35a1SLionel Sambuc */
811be35a1SLionel Sambuc
911be35a1SLionel Sambuc #define lcode_c
1011be35a1SLionel Sambuc #define LUA_CORE
1111be35a1SLionel Sambuc
12*0a6a1f1dSLionel Sambuc #include "lprefix.h"
13*0a6a1f1dSLionel Sambuc
14*0a6a1f1dSLionel Sambuc
15*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
16*0a6a1f1dSLionel Sambuc #include <math.h>
17*0a6a1f1dSLionel Sambuc #include <stdlib.h>
18*0a6a1f1dSLionel Sambuc #endif
19*0a6a1f1dSLionel Sambuc
2011be35a1SLionel Sambuc #include "lua.h"
2111be35a1SLionel Sambuc
2211be35a1SLionel Sambuc #include "lcode.h"
2311be35a1SLionel Sambuc #include "ldebug.h"
2411be35a1SLionel Sambuc #include "ldo.h"
2511be35a1SLionel Sambuc #include "lgc.h"
2611be35a1SLionel Sambuc #include "llex.h"
2711be35a1SLionel Sambuc #include "lmem.h"
2811be35a1SLionel Sambuc #include "lobject.h"
2911be35a1SLionel Sambuc #include "lopcodes.h"
3011be35a1SLionel Sambuc #include "lparser.h"
31*0a6a1f1dSLionel Sambuc #include "lstring.h"
3211be35a1SLionel Sambuc #include "ltable.h"
33*0a6a1f1dSLionel Sambuc #include "lvm.h"
34*0a6a1f1dSLionel Sambuc
35*0a6a1f1dSLionel Sambuc
36*0a6a1f1dSLionel Sambuc /* Maximum number of registers in a Lua function (must fit in 8 bits) */
37*0a6a1f1dSLionel Sambuc #define MAXREGS 255
3811be35a1SLionel Sambuc
3911be35a1SLionel Sambuc
4011be35a1SLionel Sambuc #define hasjumps(e) ((e)->t != (e)->f)
4111be35a1SLionel Sambuc
4211be35a1SLionel Sambuc
tonumeral(expdesc * e,TValue * v)43*0a6a1f1dSLionel Sambuc static int tonumeral(expdesc *e, TValue *v) {
44*0a6a1f1dSLionel Sambuc if (e->t != NO_JUMP || e->f != NO_JUMP)
45*0a6a1f1dSLionel Sambuc return 0; /* not a numeral */
46*0a6a1f1dSLionel Sambuc switch (e->k) {
47*0a6a1f1dSLionel Sambuc case VKINT:
48*0a6a1f1dSLionel Sambuc if (v) setivalue(v, e->u.ival);
49*0a6a1f1dSLionel Sambuc return 1;
50*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
51*0a6a1f1dSLionel Sambuc case VKFLT:
52*0a6a1f1dSLionel Sambuc if (v) setfltvalue(v, e->u.nval);
53*0a6a1f1dSLionel Sambuc return 1;
54*0a6a1f1dSLionel Sambuc #endif
55*0a6a1f1dSLionel Sambuc default: return 0;
56*0a6a1f1dSLionel Sambuc }
5711be35a1SLionel Sambuc }
5811be35a1SLionel Sambuc
5911be35a1SLionel Sambuc
luaK_nil(FuncState * fs,int from,int n)6011be35a1SLionel Sambuc void luaK_nil (FuncState *fs, int from, int n) {
6111be35a1SLionel Sambuc Instruction *previous;
62*0a6a1f1dSLionel Sambuc int l = from + n - 1; /* last register to set nil */
6311be35a1SLionel Sambuc if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
6411be35a1SLionel Sambuc previous = &fs->f->code[fs->pc-1];
6511be35a1SLionel Sambuc if (GET_OPCODE(*previous) == OP_LOADNIL) {
6611be35a1SLionel Sambuc int pfrom = GETARG_A(*previous);
67*0a6a1f1dSLionel Sambuc int pl = pfrom + GETARG_B(*previous);
68*0a6a1f1dSLionel Sambuc if ((pfrom <= from && from <= pl + 1) ||
69*0a6a1f1dSLionel Sambuc (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */
70*0a6a1f1dSLionel Sambuc if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */
71*0a6a1f1dSLionel Sambuc if (pl > l) l = pl; /* l = max(l, pl) */
72*0a6a1f1dSLionel Sambuc SETARG_A(*previous, from);
73*0a6a1f1dSLionel Sambuc SETARG_B(*previous, l - from);
7411be35a1SLionel Sambuc return;
7511be35a1SLionel Sambuc }
76*0a6a1f1dSLionel Sambuc } /* else go through */
7711be35a1SLionel Sambuc }
78*0a6a1f1dSLionel Sambuc luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */
7911be35a1SLionel Sambuc }
8011be35a1SLionel Sambuc
8111be35a1SLionel Sambuc
luaK_jump(FuncState * fs)8211be35a1SLionel Sambuc int luaK_jump (FuncState *fs) {
8311be35a1SLionel Sambuc int jpc = fs->jpc; /* save list of jumps to here */
8411be35a1SLionel Sambuc int j;
8511be35a1SLionel Sambuc fs->jpc = NO_JUMP;
8611be35a1SLionel Sambuc j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
8711be35a1SLionel Sambuc luaK_concat(fs, &j, jpc); /* keep them on hold */
8811be35a1SLionel Sambuc return j;
8911be35a1SLionel Sambuc }
9011be35a1SLionel Sambuc
9111be35a1SLionel Sambuc
luaK_ret(FuncState * fs,int first,int nret)9211be35a1SLionel Sambuc void luaK_ret (FuncState *fs, int first, int nret) {
9311be35a1SLionel Sambuc luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
9411be35a1SLionel Sambuc }
9511be35a1SLionel Sambuc
9611be35a1SLionel Sambuc
condjump(FuncState * fs,OpCode op,int A,int B,int C)9711be35a1SLionel Sambuc static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
9811be35a1SLionel Sambuc luaK_codeABC(fs, op, A, B, C);
9911be35a1SLionel Sambuc return luaK_jump(fs);
10011be35a1SLionel Sambuc }
10111be35a1SLionel Sambuc
10211be35a1SLionel Sambuc
fixjump(FuncState * fs,int pc,int dest)10311be35a1SLionel Sambuc static void fixjump (FuncState *fs, int pc, int dest) {
10411be35a1SLionel Sambuc Instruction *jmp = &fs->f->code[pc];
10511be35a1SLionel Sambuc int offset = dest-(pc+1);
10611be35a1SLionel Sambuc lua_assert(dest != NO_JUMP);
10711be35a1SLionel Sambuc if (abs(offset) > MAXARG_sBx)
10811be35a1SLionel Sambuc luaX_syntaxerror(fs->ls, "control structure too long");
10911be35a1SLionel Sambuc SETARG_sBx(*jmp, offset);
11011be35a1SLionel Sambuc }
11111be35a1SLionel Sambuc
11211be35a1SLionel Sambuc
11311be35a1SLionel Sambuc /*
114*0a6a1f1dSLionel Sambuc ** returns current 'pc' and marks it as a jump target (to avoid wrong
11511be35a1SLionel Sambuc ** optimizations with consecutive instructions not in the same basic block).
11611be35a1SLionel Sambuc */
luaK_getlabel(FuncState * fs)11711be35a1SLionel Sambuc int luaK_getlabel (FuncState *fs) {
11811be35a1SLionel Sambuc fs->lasttarget = fs->pc;
11911be35a1SLionel Sambuc return fs->pc;
12011be35a1SLionel Sambuc }
12111be35a1SLionel Sambuc
12211be35a1SLionel Sambuc
getjump(FuncState * fs,int pc)12311be35a1SLionel Sambuc static int getjump (FuncState *fs, int pc) {
12411be35a1SLionel Sambuc int offset = GETARG_sBx(fs->f->code[pc]);
12511be35a1SLionel Sambuc if (offset == NO_JUMP) /* point to itself represents end of list */
12611be35a1SLionel Sambuc return NO_JUMP; /* end of list */
12711be35a1SLionel Sambuc else
12811be35a1SLionel Sambuc return (pc+1)+offset; /* turn offset into absolute position */
12911be35a1SLionel Sambuc }
13011be35a1SLionel Sambuc
13111be35a1SLionel Sambuc
getjumpcontrol(FuncState * fs,int pc)13211be35a1SLionel Sambuc static Instruction *getjumpcontrol (FuncState *fs, int pc) {
13311be35a1SLionel Sambuc Instruction *pi = &fs->f->code[pc];
13411be35a1SLionel Sambuc if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
13511be35a1SLionel Sambuc return pi-1;
13611be35a1SLionel Sambuc else
13711be35a1SLionel Sambuc return pi;
13811be35a1SLionel Sambuc }
13911be35a1SLionel Sambuc
14011be35a1SLionel Sambuc
14111be35a1SLionel Sambuc /*
14211be35a1SLionel Sambuc ** check whether list has any jump that do not produce a value
14311be35a1SLionel Sambuc ** (or produce an inverted value)
14411be35a1SLionel Sambuc */
need_value(FuncState * fs,int list)14511be35a1SLionel Sambuc static int need_value (FuncState *fs, int list) {
14611be35a1SLionel Sambuc for (; list != NO_JUMP; list = getjump(fs, list)) {
14711be35a1SLionel Sambuc Instruction i = *getjumpcontrol(fs, list);
14811be35a1SLionel Sambuc if (GET_OPCODE(i) != OP_TESTSET) return 1;
14911be35a1SLionel Sambuc }
15011be35a1SLionel Sambuc return 0; /* not found */
15111be35a1SLionel Sambuc }
15211be35a1SLionel Sambuc
15311be35a1SLionel Sambuc
patchtestreg(FuncState * fs,int node,int reg)15411be35a1SLionel Sambuc static int patchtestreg (FuncState *fs, int node, int reg) {
15511be35a1SLionel Sambuc Instruction *i = getjumpcontrol(fs, node);
15611be35a1SLionel Sambuc if (GET_OPCODE(*i) != OP_TESTSET)
15711be35a1SLionel Sambuc return 0; /* cannot patch other instructions */
15811be35a1SLionel Sambuc if (reg != NO_REG && reg != GETARG_B(*i))
15911be35a1SLionel Sambuc SETARG_A(*i, reg);
16011be35a1SLionel Sambuc else /* no register to put value or register already has the value */
16111be35a1SLionel Sambuc *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
16211be35a1SLionel Sambuc
16311be35a1SLionel Sambuc return 1;
16411be35a1SLionel Sambuc }
16511be35a1SLionel Sambuc
16611be35a1SLionel Sambuc
removevalues(FuncState * fs,int list)16711be35a1SLionel Sambuc static void removevalues (FuncState *fs, int list) {
16811be35a1SLionel Sambuc for (; list != NO_JUMP; list = getjump(fs, list))
16911be35a1SLionel Sambuc patchtestreg(fs, list, NO_REG);
17011be35a1SLionel Sambuc }
17111be35a1SLionel Sambuc
17211be35a1SLionel Sambuc
patchlistaux(FuncState * fs,int list,int vtarget,int reg,int dtarget)17311be35a1SLionel Sambuc static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
17411be35a1SLionel Sambuc int dtarget) {
17511be35a1SLionel Sambuc while (list != NO_JUMP) {
17611be35a1SLionel Sambuc int next = getjump(fs, list);
17711be35a1SLionel Sambuc if (patchtestreg(fs, list, reg))
17811be35a1SLionel Sambuc fixjump(fs, list, vtarget);
17911be35a1SLionel Sambuc else
18011be35a1SLionel Sambuc fixjump(fs, list, dtarget); /* jump to default target */
18111be35a1SLionel Sambuc list = next;
18211be35a1SLionel Sambuc }
18311be35a1SLionel Sambuc }
18411be35a1SLionel Sambuc
18511be35a1SLionel Sambuc
dischargejpc(FuncState * fs)18611be35a1SLionel Sambuc static void dischargejpc (FuncState *fs) {
18711be35a1SLionel Sambuc patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
18811be35a1SLionel Sambuc fs->jpc = NO_JUMP;
18911be35a1SLionel Sambuc }
19011be35a1SLionel Sambuc
19111be35a1SLionel Sambuc
luaK_patchlist(FuncState * fs,int list,int target)19211be35a1SLionel Sambuc void luaK_patchlist (FuncState *fs, int list, int target) {
19311be35a1SLionel Sambuc if (target == fs->pc)
19411be35a1SLionel Sambuc luaK_patchtohere(fs, list);
19511be35a1SLionel Sambuc else {
19611be35a1SLionel Sambuc lua_assert(target < fs->pc);
19711be35a1SLionel Sambuc patchlistaux(fs, list, target, NO_REG, target);
19811be35a1SLionel Sambuc }
19911be35a1SLionel Sambuc }
20011be35a1SLionel Sambuc
20111be35a1SLionel Sambuc
luaK_patchclose(FuncState * fs,int list,int level)202*0a6a1f1dSLionel Sambuc void luaK_patchclose (FuncState *fs, int list, int level) {
203*0a6a1f1dSLionel Sambuc level++; /* argument is +1 to reserve 0 as non-op */
204*0a6a1f1dSLionel Sambuc while (list != NO_JUMP) {
205*0a6a1f1dSLionel Sambuc int next = getjump(fs, list);
206*0a6a1f1dSLionel Sambuc lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
207*0a6a1f1dSLionel Sambuc (GETARG_A(fs->f->code[list]) == 0 ||
208*0a6a1f1dSLionel Sambuc GETARG_A(fs->f->code[list]) >= level));
209*0a6a1f1dSLionel Sambuc SETARG_A(fs->f->code[list], level);
210*0a6a1f1dSLionel Sambuc list = next;
211*0a6a1f1dSLionel Sambuc }
212*0a6a1f1dSLionel Sambuc }
213*0a6a1f1dSLionel Sambuc
214*0a6a1f1dSLionel Sambuc
luaK_patchtohere(FuncState * fs,int list)21511be35a1SLionel Sambuc void luaK_patchtohere (FuncState *fs, int list) {
21611be35a1SLionel Sambuc luaK_getlabel(fs);
21711be35a1SLionel Sambuc luaK_concat(fs, &fs->jpc, list);
21811be35a1SLionel Sambuc }
21911be35a1SLionel Sambuc
22011be35a1SLionel Sambuc
luaK_concat(FuncState * fs,int * l1,int l2)22111be35a1SLionel Sambuc void luaK_concat (FuncState *fs, int *l1, int l2) {
22211be35a1SLionel Sambuc if (l2 == NO_JUMP) return;
22311be35a1SLionel Sambuc else if (*l1 == NO_JUMP)
22411be35a1SLionel Sambuc *l1 = l2;
22511be35a1SLionel Sambuc else {
22611be35a1SLionel Sambuc int list = *l1;
22711be35a1SLionel Sambuc int next;
22811be35a1SLionel Sambuc while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
22911be35a1SLionel Sambuc list = next;
23011be35a1SLionel Sambuc fixjump(fs, list, l2);
23111be35a1SLionel Sambuc }
23211be35a1SLionel Sambuc }
23311be35a1SLionel Sambuc
23411be35a1SLionel Sambuc
luaK_code(FuncState * fs,Instruction i)235*0a6a1f1dSLionel Sambuc static int luaK_code (FuncState *fs, Instruction i) {
236*0a6a1f1dSLionel Sambuc Proto *f = fs->f;
237*0a6a1f1dSLionel Sambuc dischargejpc(fs); /* 'pc' will change */
238*0a6a1f1dSLionel Sambuc /* put new instruction in code array */
239*0a6a1f1dSLionel Sambuc luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
240*0a6a1f1dSLionel Sambuc MAX_INT, "opcodes");
241*0a6a1f1dSLionel Sambuc f->code[fs->pc] = i;
242*0a6a1f1dSLionel Sambuc /* save corresponding line information */
243*0a6a1f1dSLionel Sambuc luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
244*0a6a1f1dSLionel Sambuc MAX_INT, "opcodes");
245*0a6a1f1dSLionel Sambuc f->lineinfo[fs->pc] = fs->ls->lastline;
246*0a6a1f1dSLionel Sambuc return fs->pc++;
247*0a6a1f1dSLionel Sambuc }
248*0a6a1f1dSLionel Sambuc
249*0a6a1f1dSLionel Sambuc
luaK_codeABC(FuncState * fs,OpCode o,int a,int b,int c)250*0a6a1f1dSLionel Sambuc int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
251*0a6a1f1dSLionel Sambuc lua_assert(getOpMode(o) == iABC);
252*0a6a1f1dSLionel Sambuc lua_assert(getBMode(o) != OpArgN || b == 0);
253*0a6a1f1dSLionel Sambuc lua_assert(getCMode(o) != OpArgN || c == 0);
254*0a6a1f1dSLionel Sambuc lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
255*0a6a1f1dSLionel Sambuc return luaK_code(fs, CREATE_ABC(o, a, b, c));
256*0a6a1f1dSLionel Sambuc }
257*0a6a1f1dSLionel Sambuc
258*0a6a1f1dSLionel Sambuc
luaK_codeABx(FuncState * fs,OpCode o,int a,unsigned int bc)259*0a6a1f1dSLionel Sambuc int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
260*0a6a1f1dSLionel Sambuc lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
261*0a6a1f1dSLionel Sambuc lua_assert(getCMode(o) == OpArgN);
262*0a6a1f1dSLionel Sambuc lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
263*0a6a1f1dSLionel Sambuc return luaK_code(fs, CREATE_ABx(o, a, bc));
264*0a6a1f1dSLionel Sambuc }
265*0a6a1f1dSLionel Sambuc
266*0a6a1f1dSLionel Sambuc
codeextraarg(FuncState * fs,int a)267*0a6a1f1dSLionel Sambuc static int codeextraarg (FuncState *fs, int a) {
268*0a6a1f1dSLionel Sambuc lua_assert(a <= MAXARG_Ax);
269*0a6a1f1dSLionel Sambuc return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc
272*0a6a1f1dSLionel Sambuc
luaK_codek(FuncState * fs,int reg,int k)273*0a6a1f1dSLionel Sambuc int luaK_codek (FuncState *fs, int reg, int k) {
274*0a6a1f1dSLionel Sambuc if (k <= MAXARG_Bx)
275*0a6a1f1dSLionel Sambuc return luaK_codeABx(fs, OP_LOADK, reg, k);
276*0a6a1f1dSLionel Sambuc else {
277*0a6a1f1dSLionel Sambuc int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
278*0a6a1f1dSLionel Sambuc codeextraarg(fs, k);
279*0a6a1f1dSLionel Sambuc return p;
280*0a6a1f1dSLionel Sambuc }
281*0a6a1f1dSLionel Sambuc }
282*0a6a1f1dSLionel Sambuc
283*0a6a1f1dSLionel Sambuc
luaK_checkstack(FuncState * fs,int n)28411be35a1SLionel Sambuc void luaK_checkstack (FuncState *fs, int n) {
28511be35a1SLionel Sambuc int newstack = fs->freereg + n;
28611be35a1SLionel Sambuc if (newstack > fs->f->maxstacksize) {
287*0a6a1f1dSLionel Sambuc if (newstack >= MAXREGS)
288*0a6a1f1dSLionel Sambuc luaX_syntaxerror(fs->ls,
289*0a6a1f1dSLionel Sambuc "function or expression needs too many registers");
29011be35a1SLionel Sambuc fs->f->maxstacksize = cast_byte(newstack);
29111be35a1SLionel Sambuc }
29211be35a1SLionel Sambuc }
29311be35a1SLionel Sambuc
29411be35a1SLionel Sambuc
luaK_reserveregs(FuncState * fs,int n)29511be35a1SLionel Sambuc void luaK_reserveregs (FuncState *fs, int n) {
29611be35a1SLionel Sambuc luaK_checkstack(fs, n);
29711be35a1SLionel Sambuc fs->freereg += n;
29811be35a1SLionel Sambuc }
29911be35a1SLionel Sambuc
30011be35a1SLionel Sambuc
freereg(FuncState * fs,int reg)30111be35a1SLionel Sambuc static void freereg (FuncState *fs, int reg) {
30211be35a1SLionel Sambuc if (!ISK(reg) && reg >= fs->nactvar) {
30311be35a1SLionel Sambuc fs->freereg--;
30411be35a1SLionel Sambuc lua_assert(reg == fs->freereg);
30511be35a1SLionel Sambuc }
30611be35a1SLionel Sambuc }
30711be35a1SLionel Sambuc
30811be35a1SLionel Sambuc
freeexp(FuncState * fs,expdesc * e)30911be35a1SLionel Sambuc static void freeexp (FuncState *fs, expdesc *e) {
31011be35a1SLionel Sambuc if (e->k == VNONRELOC)
311*0a6a1f1dSLionel Sambuc freereg(fs, e->u.info);
31211be35a1SLionel Sambuc }
31311be35a1SLionel Sambuc
31411be35a1SLionel Sambuc
315*0a6a1f1dSLionel Sambuc /*
316*0a6a1f1dSLionel Sambuc ** Use scanner's table to cache position of constants in constant list
317*0a6a1f1dSLionel Sambuc ** and try to reuse constants
318*0a6a1f1dSLionel Sambuc */
addk(FuncState * fs,TValue * key,TValue * v)319*0a6a1f1dSLionel Sambuc static int addk (FuncState *fs, TValue *key, TValue *v) {
320*0a6a1f1dSLionel Sambuc lua_State *L = fs->ls->L;
32111be35a1SLionel Sambuc Proto *f = fs->f;
322*0a6a1f1dSLionel Sambuc TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */
323*0a6a1f1dSLionel Sambuc int k, oldsize;
324*0a6a1f1dSLionel Sambuc if (ttisinteger(idx)) { /* is there an index there? */
325*0a6a1f1dSLionel Sambuc k = cast_int(ivalue(idx));
326*0a6a1f1dSLionel Sambuc /* correct value? (warning: must distinguish floats from integers!) */
327*0a6a1f1dSLionel Sambuc if (k < fs->nk && ttype(&f->k[k]) == ttype(v) &&
328*0a6a1f1dSLionel Sambuc luaV_rawequalobj(&f->k[k], v))
329*0a6a1f1dSLionel Sambuc return k; /* reuse index */
33011be35a1SLionel Sambuc }
331*0a6a1f1dSLionel Sambuc /* constant not found; create a new entry */
332*0a6a1f1dSLionel Sambuc oldsize = f->sizek;
333*0a6a1f1dSLionel Sambuc k = fs->nk;
334*0a6a1f1dSLionel Sambuc /* numerical value does not need GC barrier;
335*0a6a1f1dSLionel Sambuc table has no metatable, so it does not need to invalidate cache */
336*0a6a1f1dSLionel Sambuc setivalue(idx, k);
337*0a6a1f1dSLionel Sambuc luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
33811be35a1SLionel Sambuc while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
339*0a6a1f1dSLionel Sambuc setobj(L, &f->k[k], v);
340*0a6a1f1dSLionel Sambuc fs->nk++;
34111be35a1SLionel Sambuc luaC_barrier(L, f, v);
342*0a6a1f1dSLionel Sambuc return k;
34311be35a1SLionel Sambuc }
34411be35a1SLionel Sambuc
34511be35a1SLionel Sambuc
luaK_stringK(FuncState * fs,TString * s)34611be35a1SLionel Sambuc int luaK_stringK (FuncState *fs, TString *s) {
34711be35a1SLionel Sambuc TValue o;
348*0a6a1f1dSLionel Sambuc setsvalue(fs->ls->L, &o, s);
34911be35a1SLionel Sambuc return addk(fs, &o, &o);
35011be35a1SLionel Sambuc }
35111be35a1SLionel Sambuc
35211be35a1SLionel Sambuc
353*0a6a1f1dSLionel Sambuc /*
354*0a6a1f1dSLionel Sambuc ** Integers use userdata as keys to avoid collision with floats with same
355*0a6a1f1dSLionel Sambuc ** value; conversion to 'void*' used only for hashing, no "precision"
356*0a6a1f1dSLionel Sambuc ** problems
357*0a6a1f1dSLionel Sambuc */
luaK_intK(FuncState * fs,lua_Integer n)358*0a6a1f1dSLionel Sambuc int luaK_intK (FuncState *fs, lua_Integer n) {
359*0a6a1f1dSLionel Sambuc TValue k, o;
360*0a6a1f1dSLionel Sambuc setpvalue(&k, cast(void*, cast(size_t, n)));
361*0a6a1f1dSLionel Sambuc setivalue(&o, n);
362*0a6a1f1dSLionel Sambuc return addk(fs, &k, &o);
363*0a6a1f1dSLionel Sambuc }
364*0a6a1f1dSLionel Sambuc
365*0a6a1f1dSLionel Sambuc
366*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
luaK_numberK(FuncState * fs,lua_Number r)367*0a6a1f1dSLionel Sambuc static int luaK_numberK (FuncState *fs, lua_Number r) {
36811be35a1SLionel Sambuc TValue o;
369*0a6a1f1dSLionel Sambuc setfltvalue(&o, r);
37011be35a1SLionel Sambuc return addk(fs, &o, &o);
37111be35a1SLionel Sambuc }
372*0a6a1f1dSLionel Sambuc #endif
37311be35a1SLionel Sambuc
37411be35a1SLionel Sambuc
boolK(FuncState * fs,int b)37511be35a1SLionel Sambuc static int boolK (FuncState *fs, int b) {
37611be35a1SLionel Sambuc TValue o;
37711be35a1SLionel Sambuc setbvalue(&o, b);
37811be35a1SLionel Sambuc return addk(fs, &o, &o);
37911be35a1SLionel Sambuc }
38011be35a1SLionel Sambuc
38111be35a1SLionel Sambuc
nilK(FuncState * fs)38211be35a1SLionel Sambuc static int nilK (FuncState *fs) {
38311be35a1SLionel Sambuc TValue k, v;
38411be35a1SLionel Sambuc setnilvalue(&v);
38511be35a1SLionel Sambuc /* cannot use nil as key; instead use table itself to represent nil */
386*0a6a1f1dSLionel Sambuc sethvalue(fs->ls->L, &k, fs->ls->h);
38711be35a1SLionel Sambuc return addk(fs, &k, &v);
38811be35a1SLionel Sambuc }
38911be35a1SLionel Sambuc
39011be35a1SLionel Sambuc
luaK_setreturns(FuncState * fs,expdesc * e,int nresults)39111be35a1SLionel Sambuc void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
39211be35a1SLionel Sambuc if (e->k == VCALL) { /* expression is an open function call? */
39311be35a1SLionel Sambuc SETARG_C(getcode(fs, e), nresults+1);
39411be35a1SLionel Sambuc }
39511be35a1SLionel Sambuc else if (e->k == VVARARG) {
39611be35a1SLionel Sambuc SETARG_B(getcode(fs, e), nresults+1);
39711be35a1SLionel Sambuc SETARG_A(getcode(fs, e), fs->freereg);
39811be35a1SLionel Sambuc luaK_reserveregs(fs, 1);
39911be35a1SLionel Sambuc }
40011be35a1SLionel Sambuc }
40111be35a1SLionel Sambuc
40211be35a1SLionel Sambuc
luaK_setoneret(FuncState * fs,expdesc * e)40311be35a1SLionel Sambuc void luaK_setoneret (FuncState *fs, expdesc *e) {
40411be35a1SLionel Sambuc if (e->k == VCALL) { /* expression is an open function call? */
40511be35a1SLionel Sambuc e->k = VNONRELOC;
406*0a6a1f1dSLionel Sambuc e->u.info = GETARG_A(getcode(fs, e));
40711be35a1SLionel Sambuc }
40811be35a1SLionel Sambuc else if (e->k == VVARARG) {
40911be35a1SLionel Sambuc SETARG_B(getcode(fs, e), 2);
41011be35a1SLionel Sambuc e->k = VRELOCABLE; /* can relocate its simple result */
41111be35a1SLionel Sambuc }
41211be35a1SLionel Sambuc }
41311be35a1SLionel Sambuc
41411be35a1SLionel Sambuc
luaK_dischargevars(FuncState * fs,expdesc * e)41511be35a1SLionel Sambuc void luaK_dischargevars (FuncState *fs, expdesc *e) {
41611be35a1SLionel Sambuc switch (e->k) {
41711be35a1SLionel Sambuc case VLOCAL: {
41811be35a1SLionel Sambuc e->k = VNONRELOC;
41911be35a1SLionel Sambuc break;
42011be35a1SLionel Sambuc }
42111be35a1SLionel Sambuc case VUPVAL: {
422*0a6a1f1dSLionel Sambuc e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
42311be35a1SLionel Sambuc e->k = VRELOCABLE;
42411be35a1SLionel Sambuc break;
42511be35a1SLionel Sambuc }
42611be35a1SLionel Sambuc case VINDEXED: {
427*0a6a1f1dSLionel Sambuc OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */
428*0a6a1f1dSLionel Sambuc freereg(fs, e->u.ind.idx);
429*0a6a1f1dSLionel Sambuc if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */
430*0a6a1f1dSLionel Sambuc freereg(fs, e->u.ind.t);
431*0a6a1f1dSLionel Sambuc op = OP_GETTABLE;
432*0a6a1f1dSLionel Sambuc }
433*0a6a1f1dSLionel Sambuc e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
43411be35a1SLionel Sambuc e->k = VRELOCABLE;
43511be35a1SLionel Sambuc break;
43611be35a1SLionel Sambuc }
43711be35a1SLionel Sambuc case VVARARG:
43811be35a1SLionel Sambuc case VCALL: {
43911be35a1SLionel Sambuc luaK_setoneret(fs, e);
44011be35a1SLionel Sambuc break;
44111be35a1SLionel Sambuc }
44211be35a1SLionel Sambuc default: break; /* there is one value available (somewhere) */
44311be35a1SLionel Sambuc }
44411be35a1SLionel Sambuc }
44511be35a1SLionel Sambuc
44611be35a1SLionel Sambuc
code_label(FuncState * fs,int A,int b,int jump)44711be35a1SLionel Sambuc static int code_label (FuncState *fs, int A, int b, int jump) {
44811be35a1SLionel Sambuc luaK_getlabel(fs); /* those instructions may be jump targets */
44911be35a1SLionel Sambuc return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
45011be35a1SLionel Sambuc }
45111be35a1SLionel Sambuc
45211be35a1SLionel Sambuc
discharge2reg(FuncState * fs,expdesc * e,int reg)45311be35a1SLionel Sambuc static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
45411be35a1SLionel Sambuc luaK_dischargevars(fs, e);
45511be35a1SLionel Sambuc switch (e->k) {
45611be35a1SLionel Sambuc case VNIL: {
45711be35a1SLionel Sambuc luaK_nil(fs, reg, 1);
45811be35a1SLionel Sambuc break;
45911be35a1SLionel Sambuc }
46011be35a1SLionel Sambuc case VFALSE: case VTRUE: {
46111be35a1SLionel Sambuc luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
46211be35a1SLionel Sambuc break;
46311be35a1SLionel Sambuc }
46411be35a1SLionel Sambuc case VK: {
465*0a6a1f1dSLionel Sambuc luaK_codek(fs, reg, e->u.info);
46611be35a1SLionel Sambuc break;
46711be35a1SLionel Sambuc }
468*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
469*0a6a1f1dSLionel Sambuc case VKFLT: {
470*0a6a1f1dSLionel Sambuc luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
471*0a6a1f1dSLionel Sambuc break;
472*0a6a1f1dSLionel Sambuc }
473*0a6a1f1dSLionel Sambuc #endif
474*0a6a1f1dSLionel Sambuc case VKINT: {
475*0a6a1f1dSLionel Sambuc luaK_codek(fs, reg, luaK_intK(fs, e->u.ival));
47611be35a1SLionel Sambuc break;
47711be35a1SLionel Sambuc }
47811be35a1SLionel Sambuc case VRELOCABLE: {
47911be35a1SLionel Sambuc Instruction *pc = &getcode(fs, e);
48011be35a1SLionel Sambuc SETARG_A(*pc, reg);
48111be35a1SLionel Sambuc break;
48211be35a1SLionel Sambuc }
48311be35a1SLionel Sambuc case VNONRELOC: {
484*0a6a1f1dSLionel Sambuc if (reg != e->u.info)
485*0a6a1f1dSLionel Sambuc luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
48611be35a1SLionel Sambuc break;
48711be35a1SLionel Sambuc }
48811be35a1SLionel Sambuc default: {
48911be35a1SLionel Sambuc lua_assert(e->k == VVOID || e->k == VJMP);
49011be35a1SLionel Sambuc return; /* nothing to do... */
49111be35a1SLionel Sambuc }
49211be35a1SLionel Sambuc }
493*0a6a1f1dSLionel Sambuc e->u.info = reg;
49411be35a1SLionel Sambuc e->k = VNONRELOC;
49511be35a1SLionel Sambuc }
49611be35a1SLionel Sambuc
49711be35a1SLionel Sambuc
discharge2anyreg(FuncState * fs,expdesc * e)49811be35a1SLionel Sambuc static void discharge2anyreg (FuncState *fs, expdesc *e) {
49911be35a1SLionel Sambuc if (e->k != VNONRELOC) {
50011be35a1SLionel Sambuc luaK_reserveregs(fs, 1);
50111be35a1SLionel Sambuc discharge2reg(fs, e, fs->freereg-1);
50211be35a1SLionel Sambuc }
50311be35a1SLionel Sambuc }
50411be35a1SLionel Sambuc
50511be35a1SLionel Sambuc
exp2reg(FuncState * fs,expdesc * e,int reg)50611be35a1SLionel Sambuc static void exp2reg (FuncState *fs, expdesc *e, int reg) {
50711be35a1SLionel Sambuc discharge2reg(fs, e, reg);
50811be35a1SLionel Sambuc if (e->k == VJMP)
509*0a6a1f1dSLionel Sambuc luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */
51011be35a1SLionel Sambuc if (hasjumps(e)) {
51111be35a1SLionel Sambuc int final; /* position after whole expression */
51211be35a1SLionel Sambuc int p_f = NO_JUMP; /* position of an eventual LOAD false */
51311be35a1SLionel Sambuc int p_t = NO_JUMP; /* position of an eventual LOAD true */
51411be35a1SLionel Sambuc if (need_value(fs, e->t) || need_value(fs, e->f)) {
51511be35a1SLionel Sambuc int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
51611be35a1SLionel Sambuc p_f = code_label(fs, reg, 0, 1);
51711be35a1SLionel Sambuc p_t = code_label(fs, reg, 1, 0);
51811be35a1SLionel Sambuc luaK_patchtohere(fs, fj);
51911be35a1SLionel Sambuc }
52011be35a1SLionel Sambuc final = luaK_getlabel(fs);
52111be35a1SLionel Sambuc patchlistaux(fs, e->f, final, reg, p_f);
52211be35a1SLionel Sambuc patchlistaux(fs, e->t, final, reg, p_t);
52311be35a1SLionel Sambuc }
52411be35a1SLionel Sambuc e->f = e->t = NO_JUMP;
525*0a6a1f1dSLionel Sambuc e->u.info = reg;
52611be35a1SLionel Sambuc e->k = VNONRELOC;
52711be35a1SLionel Sambuc }
52811be35a1SLionel Sambuc
52911be35a1SLionel Sambuc
luaK_exp2nextreg(FuncState * fs,expdesc * e)53011be35a1SLionel Sambuc void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
53111be35a1SLionel Sambuc luaK_dischargevars(fs, e);
53211be35a1SLionel Sambuc freeexp(fs, e);
53311be35a1SLionel Sambuc luaK_reserveregs(fs, 1);
53411be35a1SLionel Sambuc exp2reg(fs, e, fs->freereg - 1);
53511be35a1SLionel Sambuc }
53611be35a1SLionel Sambuc
53711be35a1SLionel Sambuc
luaK_exp2anyreg(FuncState * fs,expdesc * e)53811be35a1SLionel Sambuc int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
53911be35a1SLionel Sambuc luaK_dischargevars(fs, e);
54011be35a1SLionel Sambuc if (e->k == VNONRELOC) {
541*0a6a1f1dSLionel Sambuc if (!hasjumps(e)) return e->u.info; /* exp is already in a register */
542*0a6a1f1dSLionel Sambuc if (e->u.info >= fs->nactvar) { /* reg. is not a local? */
543*0a6a1f1dSLionel Sambuc exp2reg(fs, e, e->u.info); /* put value on it */
544*0a6a1f1dSLionel Sambuc return e->u.info;
54511be35a1SLionel Sambuc }
54611be35a1SLionel Sambuc }
54711be35a1SLionel Sambuc luaK_exp2nextreg(fs, e); /* default */
548*0a6a1f1dSLionel Sambuc return e->u.info;
549*0a6a1f1dSLionel Sambuc }
550*0a6a1f1dSLionel Sambuc
551*0a6a1f1dSLionel Sambuc
luaK_exp2anyregup(FuncState * fs,expdesc * e)552*0a6a1f1dSLionel Sambuc void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
553*0a6a1f1dSLionel Sambuc if (e->k != VUPVAL || hasjumps(e))
554*0a6a1f1dSLionel Sambuc luaK_exp2anyreg(fs, e);
55511be35a1SLionel Sambuc }
55611be35a1SLionel Sambuc
55711be35a1SLionel Sambuc
luaK_exp2val(FuncState * fs,expdesc * e)55811be35a1SLionel Sambuc void luaK_exp2val (FuncState *fs, expdesc *e) {
55911be35a1SLionel Sambuc if (hasjumps(e))
56011be35a1SLionel Sambuc luaK_exp2anyreg(fs, e);
56111be35a1SLionel Sambuc else
56211be35a1SLionel Sambuc luaK_dischargevars(fs, e);
56311be35a1SLionel Sambuc }
56411be35a1SLionel Sambuc
56511be35a1SLionel Sambuc
luaK_exp2RK(FuncState * fs,expdesc * e)56611be35a1SLionel Sambuc int luaK_exp2RK (FuncState *fs, expdesc *e) {
56711be35a1SLionel Sambuc luaK_exp2val(fs, e);
56811be35a1SLionel Sambuc switch (e->k) {
56911be35a1SLionel Sambuc case VTRUE:
57011be35a1SLionel Sambuc case VFALSE:
57111be35a1SLionel Sambuc case VNIL: {
572*0a6a1f1dSLionel Sambuc if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */
573*0a6a1f1dSLionel Sambuc e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE));
57411be35a1SLionel Sambuc e->k = VK;
575*0a6a1f1dSLionel Sambuc return RKASK(e->u.info);
57611be35a1SLionel Sambuc }
57711be35a1SLionel Sambuc else break;
57811be35a1SLionel Sambuc }
579*0a6a1f1dSLionel Sambuc case VKINT: {
580*0a6a1f1dSLionel Sambuc e->u.info = luaK_intK(fs, e->u.ival);
581*0a6a1f1dSLionel Sambuc e->k = VK;
582*0a6a1f1dSLionel Sambuc goto vk;
583*0a6a1f1dSLionel Sambuc }
584*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
585*0a6a1f1dSLionel Sambuc case VKFLT: {
586*0a6a1f1dSLionel Sambuc e->u.info = luaK_numberK(fs, e->u.nval);
587*0a6a1f1dSLionel Sambuc e->k = VK;
588*0a6a1f1dSLionel Sambuc }
589*0a6a1f1dSLionel Sambuc #endif
590*0a6a1f1dSLionel Sambuc /* FALLTHROUGH */
59111be35a1SLionel Sambuc case VK: {
592*0a6a1f1dSLionel Sambuc vk:
593*0a6a1f1dSLionel Sambuc if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
594*0a6a1f1dSLionel Sambuc return RKASK(e->u.info);
59511be35a1SLionel Sambuc else break;
59611be35a1SLionel Sambuc }
59711be35a1SLionel Sambuc default: break;
59811be35a1SLionel Sambuc }
59911be35a1SLionel Sambuc /* not a constant in the right range: put it in a register */
60011be35a1SLionel Sambuc return luaK_exp2anyreg(fs, e);
60111be35a1SLionel Sambuc }
60211be35a1SLionel Sambuc
60311be35a1SLionel Sambuc
luaK_storevar(FuncState * fs,expdesc * var,expdesc * ex)60411be35a1SLionel Sambuc void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
60511be35a1SLionel Sambuc switch (var->k) {
60611be35a1SLionel Sambuc case VLOCAL: {
60711be35a1SLionel Sambuc freeexp(fs, ex);
608*0a6a1f1dSLionel Sambuc exp2reg(fs, ex, var->u.info);
60911be35a1SLionel Sambuc return;
61011be35a1SLionel Sambuc }
61111be35a1SLionel Sambuc case VUPVAL: {
61211be35a1SLionel Sambuc int e = luaK_exp2anyreg(fs, ex);
613*0a6a1f1dSLionel Sambuc luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
61411be35a1SLionel Sambuc break;
61511be35a1SLionel Sambuc }
61611be35a1SLionel Sambuc case VINDEXED: {
617*0a6a1f1dSLionel Sambuc OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
61811be35a1SLionel Sambuc int e = luaK_exp2RK(fs, ex);
619*0a6a1f1dSLionel Sambuc luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
62011be35a1SLionel Sambuc break;
62111be35a1SLionel Sambuc }
62211be35a1SLionel Sambuc default: {
62311be35a1SLionel Sambuc lua_assert(0); /* invalid var kind to store */
62411be35a1SLionel Sambuc break;
62511be35a1SLionel Sambuc }
62611be35a1SLionel Sambuc }
62711be35a1SLionel Sambuc freeexp(fs, ex);
62811be35a1SLionel Sambuc }
62911be35a1SLionel Sambuc
63011be35a1SLionel Sambuc
luaK_self(FuncState * fs,expdesc * e,expdesc * key)63111be35a1SLionel Sambuc void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
632*0a6a1f1dSLionel Sambuc int ereg;
63311be35a1SLionel Sambuc luaK_exp2anyreg(fs, e);
634*0a6a1f1dSLionel Sambuc ereg = e->u.info; /* register where 'e' was placed */
63511be35a1SLionel Sambuc freeexp(fs, e);
636*0a6a1f1dSLionel Sambuc e->u.info = fs->freereg; /* base register for op_self */
63711be35a1SLionel Sambuc e->k = VNONRELOC;
638*0a6a1f1dSLionel Sambuc luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
639*0a6a1f1dSLionel Sambuc luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
640*0a6a1f1dSLionel Sambuc freeexp(fs, key);
64111be35a1SLionel Sambuc }
64211be35a1SLionel Sambuc
64311be35a1SLionel Sambuc
invertjump(FuncState * fs,expdesc * e)64411be35a1SLionel Sambuc static void invertjump (FuncState *fs, expdesc *e) {
645*0a6a1f1dSLionel Sambuc Instruction *pc = getjumpcontrol(fs, e->u.info);
64611be35a1SLionel Sambuc lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
64711be35a1SLionel Sambuc GET_OPCODE(*pc) != OP_TEST);
64811be35a1SLionel Sambuc SETARG_A(*pc, !(GETARG_A(*pc)));
64911be35a1SLionel Sambuc }
65011be35a1SLionel Sambuc
65111be35a1SLionel Sambuc
jumponcond(FuncState * fs,expdesc * e,int cond)65211be35a1SLionel Sambuc static int jumponcond (FuncState *fs, expdesc *e, int cond) {
65311be35a1SLionel Sambuc if (e->k == VRELOCABLE) {
65411be35a1SLionel Sambuc Instruction ie = getcode(fs, e);
65511be35a1SLionel Sambuc if (GET_OPCODE(ie) == OP_NOT) {
65611be35a1SLionel Sambuc fs->pc--; /* remove previous OP_NOT */
65711be35a1SLionel Sambuc return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
65811be35a1SLionel Sambuc }
65911be35a1SLionel Sambuc /* else go through */
66011be35a1SLionel Sambuc }
66111be35a1SLionel Sambuc discharge2anyreg(fs, e);
66211be35a1SLionel Sambuc freeexp(fs, e);
663*0a6a1f1dSLionel Sambuc return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
66411be35a1SLionel Sambuc }
66511be35a1SLionel Sambuc
66611be35a1SLionel Sambuc
luaK_goiftrue(FuncState * fs,expdesc * e)66711be35a1SLionel Sambuc void luaK_goiftrue (FuncState *fs, expdesc *e) {
66811be35a1SLionel Sambuc int pc; /* pc of last jump */
66911be35a1SLionel Sambuc luaK_dischargevars(fs, e);
67011be35a1SLionel Sambuc switch (e->k) {
67111be35a1SLionel Sambuc case VJMP: {
67211be35a1SLionel Sambuc invertjump(fs, e);
673*0a6a1f1dSLionel Sambuc pc = e->u.info;
674*0a6a1f1dSLionel Sambuc break;
675*0a6a1f1dSLionel Sambuc }
676*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
677*0a6a1f1dSLionel Sambuc case VK: case VKFLT: case VKINT: case VTRUE: {
678*0a6a1f1dSLionel Sambuc #else
679*0a6a1f1dSLionel Sambuc case VK: case VKINT: case VTRUE: {
680*0a6a1f1dSLionel Sambuc #endif
681*0a6a1f1dSLionel Sambuc pc = NO_JUMP; /* always true; do nothing */
68211be35a1SLionel Sambuc break;
68311be35a1SLionel Sambuc }
68411be35a1SLionel Sambuc default: {
68511be35a1SLionel Sambuc pc = jumponcond(fs, e, 0);
68611be35a1SLionel Sambuc break;
68711be35a1SLionel Sambuc }
68811be35a1SLionel Sambuc }
689*0a6a1f1dSLionel Sambuc luaK_concat(fs, &e->f, pc); /* insert last jump in 'f' list */
69011be35a1SLionel Sambuc luaK_patchtohere(fs, e->t);
69111be35a1SLionel Sambuc e->t = NO_JUMP;
69211be35a1SLionel Sambuc }
69311be35a1SLionel Sambuc
69411be35a1SLionel Sambuc
695*0a6a1f1dSLionel Sambuc void luaK_goiffalse (FuncState *fs, expdesc *e) {
69611be35a1SLionel Sambuc int pc; /* pc of last jump */
69711be35a1SLionel Sambuc luaK_dischargevars(fs, e);
69811be35a1SLionel Sambuc switch (e->k) {
699*0a6a1f1dSLionel Sambuc case VJMP: {
700*0a6a1f1dSLionel Sambuc pc = e->u.info;
70111be35a1SLionel Sambuc break;
70211be35a1SLionel Sambuc }
703*0a6a1f1dSLionel Sambuc case VNIL: case VFALSE: {
704*0a6a1f1dSLionel Sambuc pc = NO_JUMP; /* always false; do nothing */
70511be35a1SLionel Sambuc break;
70611be35a1SLionel Sambuc }
70711be35a1SLionel Sambuc default: {
70811be35a1SLionel Sambuc pc = jumponcond(fs, e, 1);
70911be35a1SLionel Sambuc break;
71011be35a1SLionel Sambuc }
71111be35a1SLionel Sambuc }
712*0a6a1f1dSLionel Sambuc luaK_concat(fs, &e->t, pc); /* insert last jump in 't' list */
71311be35a1SLionel Sambuc luaK_patchtohere(fs, e->f);
71411be35a1SLionel Sambuc e->f = NO_JUMP;
71511be35a1SLionel Sambuc }
71611be35a1SLionel Sambuc
71711be35a1SLionel Sambuc
71811be35a1SLionel Sambuc static void codenot (FuncState *fs, expdesc *e) {
71911be35a1SLionel Sambuc luaK_dischargevars(fs, e);
72011be35a1SLionel Sambuc switch (e->k) {
72111be35a1SLionel Sambuc case VNIL: case VFALSE: {
72211be35a1SLionel Sambuc e->k = VTRUE;
72311be35a1SLionel Sambuc break;
72411be35a1SLionel Sambuc }
725*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
726*0a6a1f1dSLionel Sambuc case VK: case VKFLT: case VKINT: case VTRUE: {
727*0a6a1f1dSLionel Sambuc #else
728*0a6a1f1dSLionel Sambuc case VK: case VKINT: case VTRUE: {
729*0a6a1f1dSLionel Sambuc #endif
73011be35a1SLionel Sambuc e->k = VFALSE;
73111be35a1SLionel Sambuc break;
73211be35a1SLionel Sambuc }
73311be35a1SLionel Sambuc case VJMP: {
73411be35a1SLionel Sambuc invertjump(fs, e);
73511be35a1SLionel Sambuc break;
73611be35a1SLionel Sambuc }
73711be35a1SLionel Sambuc case VRELOCABLE:
73811be35a1SLionel Sambuc case VNONRELOC: {
73911be35a1SLionel Sambuc discharge2anyreg(fs, e);
74011be35a1SLionel Sambuc freeexp(fs, e);
741*0a6a1f1dSLionel Sambuc e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
74211be35a1SLionel Sambuc e->k = VRELOCABLE;
74311be35a1SLionel Sambuc break;
74411be35a1SLionel Sambuc }
74511be35a1SLionel Sambuc default: {
74611be35a1SLionel Sambuc lua_assert(0); /* cannot happen */
74711be35a1SLionel Sambuc break;
74811be35a1SLionel Sambuc }
74911be35a1SLionel Sambuc }
75011be35a1SLionel Sambuc /* interchange true and false lists */
75111be35a1SLionel Sambuc { int temp = e->f; e->f = e->t; e->t = temp; }
75211be35a1SLionel Sambuc removevalues(fs, e->f);
75311be35a1SLionel Sambuc removevalues(fs, e->t);
75411be35a1SLionel Sambuc }
75511be35a1SLionel Sambuc
75611be35a1SLionel Sambuc
75711be35a1SLionel Sambuc void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
758*0a6a1f1dSLionel Sambuc lua_assert(!hasjumps(t));
759*0a6a1f1dSLionel Sambuc t->u.ind.t = t->u.info;
760*0a6a1f1dSLionel Sambuc t->u.ind.idx = luaK_exp2RK(fs, k);
761*0a6a1f1dSLionel Sambuc t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
762*0a6a1f1dSLionel Sambuc : check_exp(vkisinreg(t->k), VLOCAL);
76311be35a1SLionel Sambuc t->k = VINDEXED;
76411be35a1SLionel Sambuc }
76511be35a1SLionel Sambuc
76611be35a1SLionel Sambuc
767*0a6a1f1dSLionel Sambuc /*
768*0a6a1f1dSLionel Sambuc ** return false if folding can raise an error
769*0a6a1f1dSLionel Sambuc */
770*0a6a1f1dSLionel Sambuc static int validop (int op, TValue *v1, TValue *v2) {
77111be35a1SLionel Sambuc switch (op) {
772*0a6a1f1dSLionel Sambuc case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
773*0a6a1f1dSLionel Sambuc case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */
774*0a6a1f1dSLionel Sambuc lua_Integer i;
775*0a6a1f1dSLionel Sambuc return (tointeger(v1, &i) && tointeger(v2, &i));
77611be35a1SLionel Sambuc }
777*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
778*0a6a1f1dSLionel Sambuc case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */
779*0a6a1f1dSLionel Sambuc #else /* _KERNEL */
780*0a6a1f1dSLionel Sambuc case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */
781*0a6a1f1dSLionel Sambuc #endif
782*0a6a1f1dSLionel Sambuc return (nvalue(v2) != 0);
783*0a6a1f1dSLionel Sambuc default: return 1; /* everything else is valid */
784*0a6a1f1dSLionel Sambuc }
785*0a6a1f1dSLionel Sambuc }
786*0a6a1f1dSLionel Sambuc
787*0a6a1f1dSLionel Sambuc
788*0a6a1f1dSLionel Sambuc /*
789*0a6a1f1dSLionel Sambuc ** Try to "constant-fold" an operation; return 1 iff successful
790*0a6a1f1dSLionel Sambuc */
791*0a6a1f1dSLionel Sambuc static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
792*0a6a1f1dSLionel Sambuc TValue v1, v2, res;
793*0a6a1f1dSLionel Sambuc if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2))
794*0a6a1f1dSLionel Sambuc return 0; /* non-numeric operands or not safe to fold */
795*0a6a1f1dSLionel Sambuc luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */
796*0a6a1f1dSLionel Sambuc if (ttisinteger(&res)) {
797*0a6a1f1dSLionel Sambuc e1->k = VKINT;
798*0a6a1f1dSLionel Sambuc e1->u.ival = ivalue(&res);
799*0a6a1f1dSLionel Sambuc }
800*0a6a1f1dSLionel Sambuc else { /* folds neither NaN nor 0.0 (to avoid collapsing with -0.0) */
801*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
802*0a6a1f1dSLionel Sambuc lua_Number n = fltvalue(&res);
803*0a6a1f1dSLionel Sambuc if (luai_numisnan(n) || n == 0)
804*0a6a1f1dSLionel Sambuc return 0;
805*0a6a1f1dSLionel Sambuc e1->k = VKFLT;
806*0a6a1f1dSLionel Sambuc e1->u.nval = n;
807*0a6a1f1dSLionel Sambuc #else /* _KERNEL */
808*0a6a1f1dSLionel Sambuc return 0; /* if it is not integer, we must fail */
809*0a6a1f1dSLionel Sambuc #endif
810*0a6a1f1dSLionel Sambuc }
81111be35a1SLionel Sambuc return 1;
81211be35a1SLionel Sambuc }
81311be35a1SLionel Sambuc
81411be35a1SLionel Sambuc
815*0a6a1f1dSLionel Sambuc /*
816*0a6a1f1dSLionel Sambuc ** Code for binary and unary expressions that "produce values"
817*0a6a1f1dSLionel Sambuc ** (arithmetic operations, bitwise operations, concat, length). First
818*0a6a1f1dSLionel Sambuc ** try to do constant folding (only for numeric [arithmetic and
819*0a6a1f1dSLionel Sambuc ** bitwise] operations, which is what 'lua_arith' accepts).
820*0a6a1f1dSLionel Sambuc ** Expression to produce final result will be encoded in 'e1'.
821*0a6a1f1dSLionel Sambuc */
822*0a6a1f1dSLionel Sambuc static void codeexpval (FuncState *fs, OpCode op,
823*0a6a1f1dSLionel Sambuc expdesc *e1, expdesc *e2, int line) {
824*0a6a1f1dSLionel Sambuc lua_assert(op >= OP_ADD);
825*0a6a1f1dSLionel Sambuc if (op <= OP_BNOT && constfolding(fs, (op - OP_ADD) + LUA_OPADD, e1, e2))
826*0a6a1f1dSLionel Sambuc return; /* result has been folded */
82711be35a1SLionel Sambuc else {
828*0a6a1f1dSLionel Sambuc int o1, o2;
829*0a6a1f1dSLionel Sambuc /* move operands to registers (if needed) */
830*0a6a1f1dSLionel Sambuc if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { /* unary op? */
831*0a6a1f1dSLionel Sambuc o2 = 0; /* no second expression */
832*0a6a1f1dSLionel Sambuc o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */
833*0a6a1f1dSLionel Sambuc }
834*0a6a1f1dSLionel Sambuc else { /* regular case (binary operators) */
835*0a6a1f1dSLionel Sambuc o2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
836*0a6a1f1dSLionel Sambuc o1 = luaK_exp2RK(fs, e1);
837*0a6a1f1dSLionel Sambuc }
838*0a6a1f1dSLionel Sambuc if (o1 > o2) { /* free registers in proper order */
83911be35a1SLionel Sambuc freeexp(fs, e1);
84011be35a1SLionel Sambuc freeexp(fs, e2);
84111be35a1SLionel Sambuc }
84211be35a1SLionel Sambuc else {
84311be35a1SLionel Sambuc freeexp(fs, e2);
84411be35a1SLionel Sambuc freeexp(fs, e1);
84511be35a1SLionel Sambuc }
846*0a6a1f1dSLionel Sambuc e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */
847*0a6a1f1dSLionel Sambuc e1->k = VRELOCABLE; /* all those operations are relocable */
848*0a6a1f1dSLionel Sambuc luaK_fixline(fs, line);
84911be35a1SLionel Sambuc }
85011be35a1SLionel Sambuc }
85111be35a1SLionel Sambuc
85211be35a1SLionel Sambuc
85311be35a1SLionel Sambuc static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
85411be35a1SLionel Sambuc expdesc *e2) {
85511be35a1SLionel Sambuc int o1 = luaK_exp2RK(fs, e1);
85611be35a1SLionel Sambuc int o2 = luaK_exp2RK(fs, e2);
85711be35a1SLionel Sambuc freeexp(fs, e2);
85811be35a1SLionel Sambuc freeexp(fs, e1);
85911be35a1SLionel Sambuc if (cond == 0 && op != OP_EQ) {
860*0a6a1f1dSLionel Sambuc int temp; /* exchange args to replace by '<' or '<=' */
86111be35a1SLionel Sambuc temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
86211be35a1SLionel Sambuc cond = 1;
86311be35a1SLionel Sambuc }
864*0a6a1f1dSLionel Sambuc e1->u.info = condjump(fs, op, cond, o1, o2);
86511be35a1SLionel Sambuc e1->k = VJMP;
86611be35a1SLionel Sambuc }
86711be35a1SLionel Sambuc
86811be35a1SLionel Sambuc
869*0a6a1f1dSLionel Sambuc void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
87011be35a1SLionel Sambuc expdesc e2;
871*0a6a1f1dSLionel Sambuc e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
87211be35a1SLionel Sambuc switch (op) {
873*0a6a1f1dSLionel Sambuc case OPR_MINUS: case OPR_BNOT: case OPR_LEN: {
874*0a6a1f1dSLionel Sambuc codeexpval(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line);
87511be35a1SLionel Sambuc break;
87611be35a1SLionel Sambuc }
87711be35a1SLionel Sambuc case OPR_NOT: codenot(fs, e); break;
87811be35a1SLionel Sambuc default: lua_assert(0);
87911be35a1SLionel Sambuc }
88011be35a1SLionel Sambuc }
88111be35a1SLionel Sambuc
88211be35a1SLionel Sambuc
88311be35a1SLionel Sambuc void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
88411be35a1SLionel Sambuc switch (op) {
88511be35a1SLionel Sambuc case OPR_AND: {
88611be35a1SLionel Sambuc luaK_goiftrue(fs, v);
88711be35a1SLionel Sambuc break;
88811be35a1SLionel Sambuc }
88911be35a1SLionel Sambuc case OPR_OR: {
89011be35a1SLionel Sambuc luaK_goiffalse(fs, v);
89111be35a1SLionel Sambuc break;
89211be35a1SLionel Sambuc }
89311be35a1SLionel Sambuc case OPR_CONCAT: {
894*0a6a1f1dSLionel Sambuc luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */
89511be35a1SLionel Sambuc break;
89611be35a1SLionel Sambuc }
897*0a6a1f1dSLionel Sambuc case OPR_ADD: case OPR_SUB:
898*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
899*0a6a1f1dSLionel Sambuc case OPR_MUL: case OPR_DIV: case OPR_IDIV:
900*0a6a1f1dSLionel Sambuc case OPR_MOD: case OPR_POW:
901*0a6a1f1dSLionel Sambuc #else
902*0a6a1f1dSLionel Sambuc case OPR_MUL: case OPR_IDIV:
903*0a6a1f1dSLionel Sambuc case OPR_MOD:
904*0a6a1f1dSLionel Sambuc #endif
905*0a6a1f1dSLionel Sambuc case OPR_BAND: case OPR_BOR: case OPR_BXOR:
906*0a6a1f1dSLionel Sambuc case OPR_SHL: case OPR_SHR: {
907*0a6a1f1dSLionel Sambuc if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
90811be35a1SLionel Sambuc break;
90911be35a1SLionel Sambuc }
91011be35a1SLionel Sambuc default: {
91111be35a1SLionel Sambuc luaK_exp2RK(fs, v);
91211be35a1SLionel Sambuc break;
91311be35a1SLionel Sambuc }
91411be35a1SLionel Sambuc }
91511be35a1SLionel Sambuc }
91611be35a1SLionel Sambuc
91711be35a1SLionel Sambuc
918*0a6a1f1dSLionel Sambuc void luaK_posfix (FuncState *fs, BinOpr op,
919*0a6a1f1dSLionel Sambuc expdesc *e1, expdesc *e2, int line) {
92011be35a1SLionel Sambuc switch (op) {
92111be35a1SLionel Sambuc case OPR_AND: {
92211be35a1SLionel Sambuc lua_assert(e1->t == NO_JUMP); /* list must be closed */
92311be35a1SLionel Sambuc luaK_dischargevars(fs, e2);
92411be35a1SLionel Sambuc luaK_concat(fs, &e2->f, e1->f);
92511be35a1SLionel Sambuc *e1 = *e2;
92611be35a1SLionel Sambuc break;
92711be35a1SLionel Sambuc }
92811be35a1SLionel Sambuc case OPR_OR: {
92911be35a1SLionel Sambuc lua_assert(e1->f == NO_JUMP); /* list must be closed */
93011be35a1SLionel Sambuc luaK_dischargevars(fs, e2);
93111be35a1SLionel Sambuc luaK_concat(fs, &e2->t, e1->t);
93211be35a1SLionel Sambuc *e1 = *e2;
93311be35a1SLionel Sambuc break;
93411be35a1SLionel Sambuc }
93511be35a1SLionel Sambuc case OPR_CONCAT: {
93611be35a1SLionel Sambuc luaK_exp2val(fs, e2);
93711be35a1SLionel Sambuc if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
938*0a6a1f1dSLionel Sambuc lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
93911be35a1SLionel Sambuc freeexp(fs, e1);
940*0a6a1f1dSLionel Sambuc SETARG_B(getcode(fs, e2), e1->u.info);
941*0a6a1f1dSLionel Sambuc e1->k = VRELOCABLE; e1->u.info = e2->u.info;
94211be35a1SLionel Sambuc }
94311be35a1SLionel Sambuc else {
94411be35a1SLionel Sambuc luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
945*0a6a1f1dSLionel Sambuc codeexpval(fs, OP_CONCAT, e1, e2, line);
94611be35a1SLionel Sambuc }
94711be35a1SLionel Sambuc break;
94811be35a1SLionel Sambuc }
949*0a6a1f1dSLionel Sambuc #ifndef _KERNEL
950*0a6a1f1dSLionel Sambuc case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
951*0a6a1f1dSLionel Sambuc case OPR_IDIV: case OPR_MOD: case OPR_POW:
952*0a6a1f1dSLionel Sambuc #else
953*0a6a1f1dSLionel Sambuc case OPR_ADD: case OPR_SUB: case OPR_MUL:
954*0a6a1f1dSLionel Sambuc case OPR_IDIV: case OPR_MOD:
955*0a6a1f1dSLionel Sambuc #endif
956*0a6a1f1dSLionel Sambuc case OPR_BAND: case OPR_BOR: case OPR_BXOR:
957*0a6a1f1dSLionel Sambuc case OPR_SHL: case OPR_SHR: {
958*0a6a1f1dSLionel Sambuc codeexpval(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line);
959*0a6a1f1dSLionel Sambuc break;
960*0a6a1f1dSLionel Sambuc }
961*0a6a1f1dSLionel Sambuc case OPR_EQ: case OPR_LT: case OPR_LE: {
962*0a6a1f1dSLionel Sambuc codecomp(fs, cast(OpCode, (op - OPR_EQ) + OP_EQ), 1, e1, e2);
963*0a6a1f1dSLionel Sambuc break;
964*0a6a1f1dSLionel Sambuc }
965*0a6a1f1dSLionel Sambuc case OPR_NE: case OPR_GT: case OPR_GE: {
966*0a6a1f1dSLionel Sambuc codecomp(fs, cast(OpCode, (op - OPR_NE) + OP_EQ), 0, e1, e2);
967*0a6a1f1dSLionel Sambuc break;
968*0a6a1f1dSLionel Sambuc }
96911be35a1SLionel Sambuc default: lua_assert(0);
97011be35a1SLionel Sambuc }
97111be35a1SLionel Sambuc }
97211be35a1SLionel Sambuc
97311be35a1SLionel Sambuc
97411be35a1SLionel Sambuc void luaK_fixline (FuncState *fs, int line) {
97511be35a1SLionel Sambuc fs->f->lineinfo[fs->pc - 1] = line;
97611be35a1SLionel Sambuc }
97711be35a1SLionel Sambuc
97811be35a1SLionel Sambuc
97911be35a1SLionel Sambuc void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
98011be35a1SLionel Sambuc int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
98111be35a1SLionel Sambuc int b = (tostore == LUA_MULTRET) ? 0 : tostore;
98211be35a1SLionel Sambuc lua_assert(tostore != 0);
98311be35a1SLionel Sambuc if (c <= MAXARG_C)
98411be35a1SLionel Sambuc luaK_codeABC(fs, OP_SETLIST, base, b, c);
985*0a6a1f1dSLionel Sambuc else if (c <= MAXARG_Ax) {
98611be35a1SLionel Sambuc luaK_codeABC(fs, OP_SETLIST, base, b, 0);
987*0a6a1f1dSLionel Sambuc codeextraarg(fs, c);
98811be35a1SLionel Sambuc }
989*0a6a1f1dSLionel Sambuc else
990*0a6a1f1dSLionel Sambuc luaX_syntaxerror(fs->ls, "constructor too long");
99111be35a1SLionel Sambuc fs->freereg = base + 1; /* free registers with list values */
99211be35a1SLionel Sambuc }
99311be35a1SLionel Sambuc
994