xref: /netbsd-src/external/mit/lua/dist/src/lcode.c (revision bdda0531de537df87feb2bf576711ab1be9b3675)
1*bdda0531Snikita /*	$NetBSD: lcode.c,v 1.14 2023/06/08 21:12:08 nikita Exp $	*/
2dbec5304Smbalmer 
3dbec5304Smbalmer /*
4f0dad708Snikita ** Id: lcode.c
5dbec5304Smbalmer ** Code generator for Lua
6dbec5304Smbalmer ** See Copyright Notice in lua.h
7dbec5304Smbalmer */
8dbec5304Smbalmer 
973008250Slneto #define lcode_c
1073008250Slneto #define LUA_CORE
1173008250Slneto 
1273008250Slneto #include "lprefix.h"
1373008250Slneto 
14dbec5304Smbalmer 
154ab4902eSlneto #ifndef _KERNEL
16f0dad708Snikita #include <float.h>
17f0dad708Snikita #include <limits.h>
184ab4902eSlneto #include <math.h>
19dbec5304Smbalmer #include <stdlib.h>
202d6cb6c2Slneto #endif /* _KERNEL */
21dbec5304Smbalmer 
22dbec5304Smbalmer #include "lua.h"
23dbec5304Smbalmer 
24dbec5304Smbalmer #include "lcode.h"
25dbec5304Smbalmer #include "ldebug.h"
26dbec5304Smbalmer #include "ldo.h"
27dbec5304Smbalmer #include "lgc.h"
28dbec5304Smbalmer #include "llex.h"
29dbec5304Smbalmer #include "lmem.h"
30dbec5304Smbalmer #include "lobject.h"
31dbec5304Smbalmer #include "lopcodes.h"
32dbec5304Smbalmer #include "lparser.h"
334ab4902eSlneto #include "lstring.h"
34dbec5304Smbalmer #include "ltable.h"
354ab4902eSlneto #include "lvm.h"
364ab4902eSlneto 
374ab4902eSlneto 
38bee09862Smbalmer /* Maximum number of registers in a Lua function (must fit in 8 bits) */
39bee09862Smbalmer #define MAXREGS		255
40dbec5304Smbalmer 
41dbec5304Smbalmer 
42dbec5304Smbalmer #define hasjumps(e)	((e)->t != (e)->f)
43dbec5304Smbalmer 
44dbec5304Smbalmer 
45f0dad708Snikita static int codesJ (FuncState *fs, OpCode o, int sj, int k);
46f0dad708Snikita 
47f0dad708Snikita 
48f0dad708Snikita 
49f0dad708Snikita /* semantic error */
luaK_semerror(LexState * ls,const char * msg)50f0dad708Snikita l_noret luaK_semerror (LexState *ls, const char *msg) {
51f0dad708Snikita   ls->t.token = 0;  /* remove "near <token>" from final message */
52f0dad708Snikita   luaX_syntaxerror(ls, msg);
53f0dad708Snikita }
54f0dad708Snikita 
55f0dad708Snikita 
56c7f896d7Ssalazar /*
57c7f896d7Ssalazar ** If expression is a numeric constant, fills 'v' with its value
58c7f896d7Ssalazar ** and returns 1. Otherwise, returns 0.
59c7f896d7Ssalazar */
tonumeral(const expdesc * e,TValue * v)609e2f6347Smbalmer static int tonumeral (const expdesc *e, TValue *v) {
612d6cb6c2Slneto   if (hasjumps(e))
624ab4902eSlneto     return 0;  /* not a numeral */
634ab4902eSlneto   switch (e->k) {
644ab4902eSlneto     case VKINT:
654ab4902eSlneto       if (v) setivalue(v, e->u.ival);
664ab4902eSlneto       return 1;
674ab4902eSlneto #ifndef _KERNEL
684ab4902eSlneto     case VKFLT:
694ab4902eSlneto       if (v) setfltvalue(v, e->u.nval);
704ab4902eSlneto       return 1;
712d6cb6c2Slneto #endif /* _KERNEL */
724ab4902eSlneto     default: return 0;
734ab4902eSlneto   }
74dbec5304Smbalmer }
75dbec5304Smbalmer 
76dbec5304Smbalmer 
77c7f896d7Ssalazar /*
78f0dad708Snikita ** Get the constant value from a constant expression
79f0dad708Snikita */
const2val(FuncState * fs,const expdesc * e)80f0dad708Snikita static TValue *const2val (FuncState *fs, const expdesc *e) {
81f0dad708Snikita   lua_assert(e->k == VCONST);
82f0dad708Snikita   return &fs->ls->dyd->actvar.arr[e->u.info].k;
83f0dad708Snikita }
84f0dad708Snikita 
85f0dad708Snikita 
86f0dad708Snikita /*
87f0dad708Snikita ** If expression is a constant, fills 'v' with its value
88f0dad708Snikita ** and returns 1. Otherwise, returns 0.
89f0dad708Snikita */
luaK_exp2const(FuncState * fs,const expdesc * e,TValue * v)90f0dad708Snikita int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) {
91f0dad708Snikita   if (hasjumps(e))
92f0dad708Snikita     return 0;  /* not a constant */
93f0dad708Snikita   switch (e->k) {
94f0dad708Snikita     case VFALSE:
95f0dad708Snikita       setbfvalue(v);
96f0dad708Snikita       return 1;
97f0dad708Snikita     case VTRUE:
98f0dad708Snikita       setbtvalue(v);
99f0dad708Snikita       return 1;
100f0dad708Snikita     case VNIL:
101f0dad708Snikita       setnilvalue(v);
102f0dad708Snikita       return 1;
103f0dad708Snikita     case VKSTR: {
104f0dad708Snikita       setsvalue(fs->ls->L, v, e->u.strval);
105f0dad708Snikita       return 1;
106f0dad708Snikita     }
107f0dad708Snikita     case VCONST: {
108f0dad708Snikita       setobj(fs->ls->L, v, const2val(fs, e));
109f0dad708Snikita       return 1;
110f0dad708Snikita     }
111f0dad708Snikita     default: return tonumeral(e, v);
112f0dad708Snikita   }
113f0dad708Snikita }
114f0dad708Snikita 
115f0dad708Snikita 
116f0dad708Snikita /*
117f0dad708Snikita ** Return the previous instruction of the current code. If there
118f0dad708Snikita ** may be a jump target between the current instruction and the
119f0dad708Snikita ** previous one, return an invalid instruction (to avoid wrong
120f0dad708Snikita ** optimizations).
121f0dad708Snikita */
previousinstruction(FuncState * fs)122f0dad708Snikita static Instruction *previousinstruction (FuncState *fs) {
123f0dad708Snikita   static const Instruction invalidinstruction = ~(Instruction)0;
124f0dad708Snikita   if (fs->pc > fs->lasttarget)
125f0dad708Snikita     return &fs->f->code[fs->pc - 1];  /* previous instruction */
126f0dad708Snikita   else
127f0dad708Snikita     return cast(Instruction*, &invalidinstruction);
128f0dad708Snikita }
129f0dad708Snikita 
130f0dad708Snikita 
131f0dad708Snikita /*
132c7f896d7Ssalazar ** Create a OP_LOADNIL instruction, but try to optimize: if the previous
133c7f896d7Ssalazar ** instruction is also OP_LOADNIL and ranges are compatible, adjust
134c7f896d7Ssalazar ** range of previous instruction instead of emitting a new one. (For
135c7f896d7Ssalazar ** instance, 'local a; local b' will generate a single opcode.)
136c7f896d7Ssalazar */
luaK_nil(FuncState * fs,int from,int n)137dbec5304Smbalmer void luaK_nil (FuncState *fs, int from, int n) {
1384ab4902eSlneto   int l = from + n - 1;  /* last register to set nil */
139f0dad708Snikita   Instruction *previous = previousinstruction(fs);
140c7f896d7Ssalazar   if (GET_OPCODE(*previous) == OP_LOADNIL) {  /* previous is LOADNIL? */
141c7f896d7Ssalazar     int pfrom = GETARG_A(*previous);  /* get previous range */
1424ab4902eSlneto     int pl = pfrom + GETARG_B(*previous);
1434ab4902eSlneto     if ((pfrom <= from && from <= pl + 1) ||
1444ab4902eSlneto         (from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
1454ab4902eSlneto       if (pfrom < from) from = pfrom;  /* from = min(from, pfrom) */
1464ab4902eSlneto       if (pl > l) l = pl;  /* l = max(l, pl) */
1474ab4902eSlneto       SETARG_A(*previous, from);
1484ab4902eSlneto       SETARG_B(*previous, l - from);
149dbec5304Smbalmer       return;
1504ab4902eSlneto     }  /* else go through */
151dbec5304Smbalmer   }
1524ab4902eSlneto   luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
153dbec5304Smbalmer }
154dbec5304Smbalmer 
155dbec5304Smbalmer 
156c7f896d7Ssalazar /*
157c7f896d7Ssalazar ** Gets the destination address of a jump instruction. Used to traverse
158c7f896d7Ssalazar ** a list of jumps.
159c7f896d7Ssalazar */
getjump(FuncState * fs,int pc)160c7f896d7Ssalazar static int getjump (FuncState *fs, int pc) {
161f0dad708Snikita   int offset = GETARG_sJ(fs->f->code[pc]);
162c7f896d7Ssalazar   if (offset == NO_JUMP)  /* point to itself represents end of list */
163c7f896d7Ssalazar     return NO_JUMP;  /* end of list */
164c7f896d7Ssalazar   else
165c7f896d7Ssalazar     return (pc+1)+offset;  /* turn offset into absolute position */
166dbec5304Smbalmer }
167dbec5304Smbalmer 
168dbec5304Smbalmer 
169c7f896d7Ssalazar /*
170c7f896d7Ssalazar ** Fix jump instruction at position 'pc' to jump to 'dest'.
171c7f896d7Ssalazar ** (Jump addresses are relative in Lua)
172c7f896d7Ssalazar */
fixjump(FuncState * fs,int pc,int dest)173dbec5304Smbalmer static void fixjump (FuncState *fs, int pc, int dest) {
174dbec5304Smbalmer   Instruction *jmp = &fs->f->code[pc];
175dbec5304Smbalmer   int offset = dest - (pc + 1);
176dbec5304Smbalmer   lua_assert(dest != NO_JUMP);
177f0dad708Snikita   if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ))
178dbec5304Smbalmer     luaX_syntaxerror(fs->ls, "control structure too long");
179f0dad708Snikita   lua_assert(GET_OPCODE(*jmp) == OP_JMP);
180f0dad708Snikita   SETARG_sJ(*jmp, offset);
181dbec5304Smbalmer }
182dbec5304Smbalmer 
183dbec5304Smbalmer 
184dbec5304Smbalmer /*
185c7f896d7Ssalazar ** Concatenate jump-list 'l2' into jump-list 'l1'
186c7f896d7Ssalazar */
luaK_concat(FuncState * fs,int * l1,int l2)187c7f896d7Ssalazar void luaK_concat (FuncState *fs, int *l1, int l2) {
188c7f896d7Ssalazar   if (l2 == NO_JUMP) return;  /* nothing to concatenate? */
189c7f896d7Ssalazar   else if (*l1 == NO_JUMP)  /* no original list? */
190c7f896d7Ssalazar     *l1 = l2;  /* 'l1' points to 'l2' */
191c7f896d7Ssalazar   else {
192c7f896d7Ssalazar     int list = *l1;
193c7f896d7Ssalazar     int next;
194c7f896d7Ssalazar     while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
195c7f896d7Ssalazar       list = next;
196c7f896d7Ssalazar     fixjump(fs, list, l2);  /* last element links to 'l2' */
197c7f896d7Ssalazar   }
198c7f896d7Ssalazar }
199c7f896d7Ssalazar 
200c7f896d7Ssalazar 
201c7f896d7Ssalazar /*
202c7f896d7Ssalazar ** Create a jump instruction and return its position, so its destination
203f0dad708Snikita ** can be fixed later (with 'fixjump').
204c7f896d7Ssalazar */
luaK_jump(FuncState * fs)205c7f896d7Ssalazar int luaK_jump (FuncState *fs) {
206f0dad708Snikita   return codesJ(fs, OP_JMP, NO_JUMP, 0);
207c7f896d7Ssalazar }
208c7f896d7Ssalazar 
209c7f896d7Ssalazar 
210c7f896d7Ssalazar /*
211c7f896d7Ssalazar ** Code a 'return' instruction
212c7f896d7Ssalazar */
luaK_ret(FuncState * fs,int first,int nret)213c7f896d7Ssalazar void luaK_ret (FuncState *fs, int first, int nret) {
214f0dad708Snikita   OpCode op;
215f0dad708Snikita   switch (nret) {
216f0dad708Snikita     case 0: op = OP_RETURN0; break;
217f0dad708Snikita     case 1: op = OP_RETURN1; break;
218f0dad708Snikita     default: op = OP_RETURN; break;
219f0dad708Snikita   }
220f0dad708Snikita   luaK_codeABC(fs, op, first, nret + 1, 0);
221c7f896d7Ssalazar }
222c7f896d7Ssalazar 
223c7f896d7Ssalazar 
224c7f896d7Ssalazar /*
225c7f896d7Ssalazar ** Code a "conditional jump", that is, a test or comparison opcode
226c7f896d7Ssalazar ** followed by a jump. Return jump position.
227c7f896d7Ssalazar */
condjump(FuncState * fs,OpCode op,int A,int B,int C,int k)228f0dad708Snikita static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) {
229f0dad708Snikita   luaK_codeABCk(fs, op, A, B, C, k);
230c7f896d7Ssalazar   return luaK_jump(fs);
231c7f896d7Ssalazar }
232c7f896d7Ssalazar 
233c7f896d7Ssalazar 
234c7f896d7Ssalazar /*
23573008250Slneto ** returns current 'pc' and marks it as a jump target (to avoid wrong
236dbec5304Smbalmer ** optimizations with consecutive instructions not in the same basic block).
237dbec5304Smbalmer */
luaK_getlabel(FuncState * fs)238dbec5304Smbalmer int luaK_getlabel (FuncState *fs) {
239dbec5304Smbalmer   fs->lasttarget = fs->pc;
240dbec5304Smbalmer   return fs->pc;
241dbec5304Smbalmer }
242dbec5304Smbalmer 
243dbec5304Smbalmer 
244c7f896d7Ssalazar /*
245c7f896d7Ssalazar ** Returns the position of the instruction "controlling" a given
246c7f896d7Ssalazar ** jump (that is, its condition), or the jump itself if it is
247c7f896d7Ssalazar ** unconditional.
248c7f896d7Ssalazar */
getjumpcontrol(FuncState * fs,int pc)249dbec5304Smbalmer static Instruction *getjumpcontrol (FuncState *fs, int pc) {
250dbec5304Smbalmer   Instruction *pi = &fs->f->code[pc];
251dbec5304Smbalmer   if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
252dbec5304Smbalmer     return pi-1;
253dbec5304Smbalmer   else
254dbec5304Smbalmer     return pi;
255dbec5304Smbalmer }
256dbec5304Smbalmer 
257dbec5304Smbalmer 
258dbec5304Smbalmer /*
259c7f896d7Ssalazar ** Patch destination register for a TESTSET instruction.
260c7f896d7Ssalazar ** If instruction in position 'node' is not a TESTSET, return 0 ("fails").
261c7f896d7Ssalazar ** Otherwise, if 'reg' is not 'NO_REG', set it as the destination
262c7f896d7Ssalazar ** register. Otherwise, change instruction to a simple 'TEST' (produces
263c7f896d7Ssalazar ** no register value)
264dbec5304Smbalmer */
patchtestreg(FuncState * fs,int node,int reg)265dbec5304Smbalmer static int patchtestreg (FuncState *fs, int node, int reg) {
266dbec5304Smbalmer   Instruction *i = getjumpcontrol(fs, node);
267dbec5304Smbalmer   if (GET_OPCODE(*i) != OP_TESTSET)
268dbec5304Smbalmer     return 0;  /* cannot patch other instructions */
269dbec5304Smbalmer   if (reg != NO_REG && reg != GETARG_B(*i))
270dbec5304Smbalmer     SETARG_A(*i, reg);
271c7f896d7Ssalazar   else {
272c7f896d7Ssalazar      /* no register to put value or register already has the value;
273c7f896d7Ssalazar         change instruction to simple test */
274f0dad708Snikita     *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i));
275c7f896d7Ssalazar   }
276dbec5304Smbalmer   return 1;
277dbec5304Smbalmer }
278dbec5304Smbalmer 
279dbec5304Smbalmer 
280c7f896d7Ssalazar /*
281c7f896d7Ssalazar ** Traverse a list of tests ensuring no one produces a value
282c7f896d7Ssalazar */
removevalues(FuncState * fs,int list)283dbec5304Smbalmer static void removevalues (FuncState *fs, int list) {
284dbec5304Smbalmer   for (; list != NO_JUMP; list = getjump(fs, list))
285dbec5304Smbalmer       patchtestreg(fs, list, NO_REG);
286dbec5304Smbalmer }
287dbec5304Smbalmer 
288dbec5304Smbalmer 
289c7f896d7Ssalazar /*
290c7f896d7Ssalazar ** Traverse a list of tests, patching their destination address and
291c7f896d7Ssalazar ** registers: tests producing values jump to 'vtarget' (and put their
292c7f896d7Ssalazar ** values in 'reg'), other tests jump to 'dtarget'.
293c7f896d7Ssalazar */
patchlistaux(FuncState * fs,int list,int vtarget,int reg,int dtarget)294dbec5304Smbalmer static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
295dbec5304Smbalmer                           int dtarget) {
296dbec5304Smbalmer   while (list != NO_JUMP) {
297dbec5304Smbalmer     int next = getjump(fs, list);
298dbec5304Smbalmer     if (patchtestreg(fs, list, reg))
299dbec5304Smbalmer       fixjump(fs, list, vtarget);
300dbec5304Smbalmer     else
301dbec5304Smbalmer       fixjump(fs, list, dtarget);  /* jump to default target */
302dbec5304Smbalmer     list = next;
303dbec5304Smbalmer   }
304dbec5304Smbalmer }
305dbec5304Smbalmer 
306dbec5304Smbalmer 
307c7f896d7Ssalazar /*
308c7f896d7Ssalazar ** Path all jumps in 'list' to jump to 'target'.
309c7f896d7Ssalazar ** (The assert means that we cannot fix a jump to a forward address
310c7f896d7Ssalazar ** because we only know addresses once code is generated.)
311c7f896d7Ssalazar */
luaK_patchlist(FuncState * fs,int list,int target)312dbec5304Smbalmer void luaK_patchlist (FuncState *fs, int list, int target) {
313f0dad708Snikita   lua_assert(target <= fs->pc);
314dbec5304Smbalmer   patchlistaux(fs, list, target, NO_REG, target);
315dbec5304Smbalmer }
316f0dad708Snikita 
317f0dad708Snikita 
luaK_patchtohere(FuncState * fs,int list)318f0dad708Snikita void luaK_patchtohere (FuncState *fs, int list) {
319f0dad708Snikita   int hr = luaK_getlabel(fs);  /* mark "here" as a jump target */
320f0dad708Snikita   luaK_patchlist(fs, list, hr);
321f0dad708Snikita }
322f0dad708Snikita 
323f0dad708Snikita 
324f0dad708Snikita /* limit for difference between lines in relative line info. */
325f0dad708Snikita #define LIMLINEDIFF	0x80
326f0dad708Snikita 
327f0dad708Snikita 
328f0dad708Snikita /*
329f0dad708Snikita ** Save line info for a new instruction. If difference from last line
330f0dad708Snikita ** does not fit in a byte, of after that many instructions, save a new
331f0dad708Snikita ** absolute line info; (in that case, the special value 'ABSLINEINFO'
332f0dad708Snikita ** in 'lineinfo' signals the existence of this absolute information.)
333f0dad708Snikita ** Otherwise, store the difference from last line in 'lineinfo'.
334f0dad708Snikita */
savelineinfo(FuncState * fs,Proto * f,int line)335f0dad708Snikita static void savelineinfo (FuncState *fs, Proto *f, int line) {
336f0dad708Snikita   int linedif = line - fs->previousline;
337f0dad708Snikita   int pc = fs->pc - 1;  /* last instruction coded */
338f0dad708Snikita   if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) {
339f0dad708Snikita     luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo,
340f0dad708Snikita                     f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines");
341f0dad708Snikita     f->abslineinfo[fs->nabslineinfo].pc = pc;
342f0dad708Snikita     f->abslineinfo[fs->nabslineinfo++].line = line;
343f0dad708Snikita     linedif = ABSLINEINFO;  /* signal that there is absolute information */
344f0dad708Snikita     fs->iwthabs = 1;  /* restart counter */
345f0dad708Snikita   }
346f0dad708Snikita   luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte,
347f0dad708Snikita                   MAX_INT, "opcodes");
348f0dad708Snikita   f->lineinfo[pc] = linedif;
349f0dad708Snikita   fs->previousline = line;  /* last line saved */
350f0dad708Snikita }
351f0dad708Snikita 
352f0dad708Snikita 
353f0dad708Snikita /*
354f0dad708Snikita ** Remove line information from the last instruction.
355f0dad708Snikita ** If line information for that instruction is absolute, set 'iwthabs'
356f0dad708Snikita ** above its max to force the new (replacing) instruction to have
357f0dad708Snikita ** absolute line info, too.
358f0dad708Snikita */
removelastlineinfo(FuncState * fs)359f0dad708Snikita static void removelastlineinfo (FuncState *fs) {
360f0dad708Snikita   Proto *f = fs->f;
361f0dad708Snikita   int pc = fs->pc - 1;  /* last instruction coded */
362f0dad708Snikita   if (f->lineinfo[pc] != ABSLINEINFO) {  /* relative line info? */
363f0dad708Snikita     fs->previousline -= f->lineinfo[pc];  /* correct last line saved */
364f0dad708Snikita     fs->iwthabs--;  /* undo previous increment */
365f0dad708Snikita   }
366f0dad708Snikita   else {  /* absolute line information */
367f0dad708Snikita     lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc);
368f0dad708Snikita     fs->nabslineinfo--;  /* remove it */
369f0dad708Snikita     fs->iwthabs = MAXIWTHABS + 1;  /* force next line info to be absolute */
370f0dad708Snikita   }
371dbec5304Smbalmer }
372dbec5304Smbalmer 
373dbec5304Smbalmer 
374c7f896d7Ssalazar /*
375f0dad708Snikita ** Remove the last instruction created, correcting line information
376f0dad708Snikita ** accordingly.
377c7f896d7Ssalazar */
removelastinstruction(FuncState * fs)378f0dad708Snikita static void removelastinstruction (FuncState *fs) {
379f0dad708Snikita   removelastlineinfo(fs);
380f0dad708Snikita   fs->pc--;
3814ab4902eSlneto }
3824ab4902eSlneto 
3834ab4902eSlneto 
384c7f896d7Ssalazar /*
385c7f896d7Ssalazar ** Emit instruction 'i', checking for array sizes and saving also its
386c7f896d7Ssalazar ** line information. Return 'i' position.
387c7f896d7Ssalazar */
luaK_code(FuncState * fs,Instruction i)388f0dad708Snikita int luaK_code (FuncState *fs, Instruction i) {
3894ab4902eSlneto   Proto *f = fs->f;
3904ab4902eSlneto   /* put new instruction in code array */
3914ab4902eSlneto   luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
3924ab4902eSlneto                   MAX_INT, "opcodes");
393f0dad708Snikita   f->code[fs->pc++] = i;
394f0dad708Snikita   savelineinfo(fs, f, fs->ls->lastline);
395f0dad708Snikita   return fs->pc - 1;  /* index of new instruction */
3964ab4902eSlneto }
3974ab4902eSlneto 
3984ab4902eSlneto 
399c7f896d7Ssalazar /*
400c7f896d7Ssalazar ** Format and emit an 'iABC' instruction. (Assertions check consistency
401c7f896d7Ssalazar ** of parameters versus opcode.)
402c7f896d7Ssalazar */
luaK_codeABCk(FuncState * fs,OpCode o,int a,int b,int c,int k)403f0dad708Snikita int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) {
4044ab4902eSlneto   lua_assert(getOpMode(o) == iABC);
405f0dad708Snikita   lua_assert(a <= MAXARG_A && b <= MAXARG_B &&
406f0dad708Snikita              c <= MAXARG_C && (k & ~1) == 0);
407f0dad708Snikita   return luaK_code(fs, CREATE_ABCk(o, a, b, c, k));
4084ab4902eSlneto }
4094ab4902eSlneto 
4104ab4902eSlneto 
411c7f896d7Ssalazar /*
412c7f896d7Ssalazar ** Format and emit an 'iABx' instruction.
413c7f896d7Ssalazar */
luaK_codeABx(FuncState * fs,OpCode o,int a,unsigned int bc)4144ab4902eSlneto int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
415f0dad708Snikita   lua_assert(getOpMode(o) == iABx);
4164ab4902eSlneto   lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
4174ab4902eSlneto   return luaK_code(fs, CREATE_ABx(o, a, bc));
4184ab4902eSlneto }
4194ab4902eSlneto 
4204ab4902eSlneto 
421c7f896d7Ssalazar /*
422f0dad708Snikita ** Format and emit an 'iAsBx' instruction.
423f0dad708Snikita */
luaK_codeAsBx(FuncState * fs,OpCode o,int a,int bc)424f0dad708Snikita int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
425f0dad708Snikita   unsigned int b = bc + OFFSET_sBx;
426f0dad708Snikita   lua_assert(getOpMode(o) == iAsBx);
427f0dad708Snikita   lua_assert(a <= MAXARG_A && b <= MAXARG_Bx);
428f0dad708Snikita   return luaK_code(fs, CREATE_ABx(o, a, b));
429f0dad708Snikita }
430f0dad708Snikita 
431f0dad708Snikita 
432f0dad708Snikita /*
433f0dad708Snikita ** Format and emit an 'isJ' instruction.
434f0dad708Snikita */
codesJ(FuncState * fs,OpCode o,int sj,int k)435f0dad708Snikita static int codesJ (FuncState *fs, OpCode o, int sj, int k) {
436f0dad708Snikita   unsigned int j = sj + OFFSET_sJ;
437f0dad708Snikita   lua_assert(getOpMode(o) == isJ);
438f0dad708Snikita   lua_assert(j <= MAXARG_sJ && (k & ~1) == 0);
439f0dad708Snikita   return luaK_code(fs, CREATE_sJ(o, j, k));
440f0dad708Snikita }
441f0dad708Snikita 
442f0dad708Snikita 
443f0dad708Snikita /*
444c7f896d7Ssalazar ** Emit an "extra argument" instruction (format 'iAx')
445c7f896d7Ssalazar */
codeextraarg(FuncState * fs,int a)4464ab4902eSlneto static int codeextraarg (FuncState *fs, int a) {
4474ab4902eSlneto   lua_assert(a <= MAXARG_Ax);
4484ab4902eSlneto   return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
4494ab4902eSlneto }
4504ab4902eSlneto 
4514ab4902eSlneto 
452c7f896d7Ssalazar /*
453c7f896d7Ssalazar ** Emit a "load constant" instruction, using either 'OP_LOADK'
454c7f896d7Ssalazar ** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX'
455c7f896d7Ssalazar ** instruction with "extra argument".
456c7f896d7Ssalazar */
luaK_codek(FuncState * fs,int reg,int k)457f0dad708Snikita static int luaK_codek (FuncState *fs, int reg, int k) {
4584ab4902eSlneto   if (k <= MAXARG_Bx)
4594ab4902eSlneto     return luaK_codeABx(fs, OP_LOADK, reg, k);
4604ab4902eSlneto   else {
4614ab4902eSlneto     int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
4624ab4902eSlneto     codeextraarg(fs, k);
4634ab4902eSlneto     return p;
4644ab4902eSlneto   }
4654ab4902eSlneto }
4664ab4902eSlneto 
4674ab4902eSlneto 
468c7f896d7Ssalazar /*
469c7f896d7Ssalazar ** Check register-stack level, keeping track of its maximum size
470c7f896d7Ssalazar ** in field 'maxstacksize'
471c7f896d7Ssalazar */
luaK_checkstack(FuncState * fs,int n)472dbec5304Smbalmer void luaK_checkstack (FuncState *fs, int n) {
473dbec5304Smbalmer   int newstack = fs->freereg + n;
474dbec5304Smbalmer   if (newstack > fs->f->maxstacksize) {
47573008250Slneto     if (newstack >= MAXREGS)
476bee09862Smbalmer       luaX_syntaxerror(fs->ls,
477bee09862Smbalmer         "function or expression needs too many registers");
478dbec5304Smbalmer     fs->f->maxstacksize = cast_byte(newstack);
479dbec5304Smbalmer   }
480dbec5304Smbalmer }
481dbec5304Smbalmer 
482dbec5304Smbalmer 
483c7f896d7Ssalazar /*
484c7f896d7Ssalazar ** Reserve 'n' registers in register stack
485c7f896d7Ssalazar */
luaK_reserveregs(FuncState * fs,int n)486dbec5304Smbalmer void luaK_reserveregs (FuncState *fs, int n) {
487dbec5304Smbalmer   luaK_checkstack(fs, n);
488dbec5304Smbalmer   fs->freereg += n;
489dbec5304Smbalmer }
490dbec5304Smbalmer 
491dbec5304Smbalmer 
492c7f896d7Ssalazar /*
493c7f896d7Ssalazar ** Free register 'reg', if it is neither a constant index nor
494c7f896d7Ssalazar ** a local variable.
495c7f896d7Ssalazar )
496c7f896d7Ssalazar */
freereg(FuncState * fs,int reg)497dbec5304Smbalmer static void freereg (FuncState *fs, int reg) {
498f0dad708Snikita   if (reg >= luaY_nvarstack(fs)) {
499dbec5304Smbalmer     fs->freereg--;
500dbec5304Smbalmer     lua_assert(reg == fs->freereg);
501dbec5304Smbalmer   }
502dbec5304Smbalmer }
503dbec5304Smbalmer 
504dbec5304Smbalmer 
505c7f896d7Ssalazar /*
506f0dad708Snikita ** Free two registers in proper order
507f0dad708Snikita */
freeregs(FuncState * fs,int r1,int r2)508f0dad708Snikita static void freeregs (FuncState *fs, int r1, int r2) {
509f0dad708Snikita   if (r1 > r2) {
510f0dad708Snikita     freereg(fs, r1);
511f0dad708Snikita     freereg(fs, r2);
512f0dad708Snikita   }
513f0dad708Snikita   else {
514f0dad708Snikita     freereg(fs, r2);
515f0dad708Snikita     freereg(fs, r1);
516f0dad708Snikita   }
517f0dad708Snikita }
518f0dad708Snikita 
519f0dad708Snikita 
520f0dad708Snikita /*
521c7f896d7Ssalazar ** Free register used by expression 'e' (if any)
522c7f896d7Ssalazar */
freeexp(FuncState * fs,expdesc * e)523dbec5304Smbalmer static void freeexp (FuncState *fs, expdesc *e) {
524dbec5304Smbalmer   if (e->k == VNONRELOC)
5254ab4902eSlneto     freereg(fs, e->u.info);
526dbec5304Smbalmer }
527dbec5304Smbalmer 
528dbec5304Smbalmer 
5294ab4902eSlneto /*
530c7f896d7Ssalazar ** Free registers used by expressions 'e1' and 'e2' (if any) in proper
531c7f896d7Ssalazar ** order.
532c7f896d7Ssalazar */
freeexps(FuncState * fs,expdesc * e1,expdesc * e2)533c7f896d7Ssalazar static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) {
534c7f896d7Ssalazar   int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1;
535c7f896d7Ssalazar   int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1;
536f0dad708Snikita   freeregs(fs, r1, r2);
537c7f896d7Ssalazar }
538c7f896d7Ssalazar 
539c7f896d7Ssalazar 
540c7f896d7Ssalazar /*
541c7f896d7Ssalazar ** Add constant 'v' to prototype's list of constants (field 'k').
5424ab4902eSlneto ** Use scanner's table to cache position of constants in constant list
543c7f896d7Ssalazar ** and try to reuse constants. Because some values should not be used
544c7f896d7Ssalazar ** as keys (nil cannot be a key, integer keys can collapse with float
545c7f896d7Ssalazar ** keys), the caller must provide a useful 'key' for indexing the cache.
546f0dad708Snikita ** Note that all functions share the same table, so entering or exiting
547f0dad708Snikita ** a function can make some indices wrong.
5484ab4902eSlneto */
addk(FuncState * fs,TValue * key,TValue * v)5494ab4902eSlneto static int addk (FuncState *fs, TValue *key, TValue *v) {
550f0dad708Snikita   TValue val;
5514ab4902eSlneto   lua_State *L = fs->ls->L;
552dbec5304Smbalmer   Proto *f = fs->f;
553f0dad708Snikita   const TValue *idx = luaH_get(fs->ls->h, key);  /* query scanner table */
5544ab4902eSlneto   int k, oldsize;
5554ab4902eSlneto   if (ttisinteger(idx)) {  /* is there an index there? */
5564ab4902eSlneto     k = cast_int(ivalue(idx));
5574ab4902eSlneto     /* correct value? (warning: must distinguish floats from integers!) */
558f0dad708Snikita     if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) &&
5594ab4902eSlneto                       luaV_rawequalobj(&f->k[k], v))
5604ab4902eSlneto       return k;  /* reuse index */
561dbec5304Smbalmer   }
5624ab4902eSlneto   /* constant not found; create a new entry */
5634ab4902eSlneto   oldsize = f->sizek;
5644ab4902eSlneto   k = fs->nk;
5654ab4902eSlneto   /* numerical value does not need GC barrier;
5664ab4902eSlneto      table has no metatable, so it does not need to invalidate cache */
567f0dad708Snikita   setivalue(&val, k);
568f0dad708Snikita   luaH_finishset(L, fs->ls->h, key, idx, &val);
5694ab4902eSlneto   luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
570dbec5304Smbalmer   while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
5714ab4902eSlneto   setobj(L, &f->k[k], v);
5724ab4902eSlneto   fs->nk++;
573dbec5304Smbalmer   luaC_barrier(L, f, v);
5744ab4902eSlneto   return k;
575dbec5304Smbalmer }
576dbec5304Smbalmer 
577dbec5304Smbalmer 
578c7f896d7Ssalazar /*
579c7f896d7Ssalazar ** Add a string to list of constants and return its index.
580c7f896d7Ssalazar */
stringK(FuncState * fs,TString * s)581f0dad708Snikita static int stringK (FuncState *fs, TString *s) {
582dbec5304Smbalmer   TValue o;
5834ab4902eSlneto   setsvalue(fs->ls->L, &o, s);
584c7f896d7Ssalazar   return addk(fs, &o, &o);  /* use string itself as key */
585dbec5304Smbalmer }
586dbec5304Smbalmer 
587dbec5304Smbalmer 
5884ab4902eSlneto /*
589c7f896d7Ssalazar ** Add an integer to list of constants and return its index.
5904ab4902eSlneto */
luaK_intK(FuncState * fs,lua_Integer n)591f0dad708Snikita static int luaK_intK (FuncState *fs, lua_Integer n) {
592f0dad708Snikita   TValue o;
5934ab4902eSlneto   setivalue(&o, n);
594f0dad708Snikita   return addk(fs, &o, &o);  /* use integer itself as key */
5954ab4902eSlneto }
5964ab4902eSlneto 
5974ab4902eSlneto 
5984ab4902eSlneto #ifndef _KERNEL
599c7f896d7Ssalazar /*
600f0dad708Snikita ** Add a float to list of constants and return its index. Floats
601f0dad708Snikita ** with integral values need a different key, to avoid collision
602f0dad708Snikita ** with actual integers. To that, we add to the number its smaller
603f0dad708Snikita ** power-of-two fraction that is still significant in its scale.
604f0dad708Snikita ** For doubles, that would be 1/2^52.
605f0dad708Snikita ** (This method is not bulletproof: there may be another float
606f0dad708Snikita ** with that value, and for floats larger than 2^53 the result is
607f0dad708Snikita ** still an integer. At worst, this only wastes an entry with
608f0dad708Snikita ** a duplicate.)
609c7f896d7Ssalazar */
luaK_numberK(FuncState * fs,lua_Number r)6104ab4902eSlneto static int luaK_numberK (FuncState *fs, lua_Number r) {
611dbec5304Smbalmer   TValue o;
612f0dad708Snikita   lua_Integer ik;
6134ab4902eSlneto   setfltvalue(&o, r);
614f0dad708Snikita   if (!luaV_flttointeger(r, &ik, F2Ieq))  /* not an integral value? */
615c7f896d7Ssalazar     return addk(fs, &o, &o);  /* use number itself as key */
616f0dad708Snikita   else {  /* must build an alternative key */
617f0dad708Snikita     const int nbm = l_floatatt(MANT_DIG);
618f0dad708Snikita     const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1);
619f0dad708Snikita     const lua_Number k = (ik == 0) ? q : r + r*q;  /* new key */
620f0dad708Snikita     TValue kv;
621f0dad708Snikita     setfltvalue(&kv, k);
622f0dad708Snikita     /* result is not an integral value, unless value is too large */
623f0dad708Snikita     lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) ||
624f0dad708Snikita                 l_mathop(fabs)(r) >= l_mathop(1e6));
625f0dad708Snikita     return addk(fs, &kv, &o);
626f0dad708Snikita   }
627dbec5304Smbalmer }
6282d6cb6c2Slneto #endif /* _KERNEL */
629dbec5304Smbalmer 
630dbec5304Smbalmer 
631c7f896d7Ssalazar /*
632f0dad708Snikita ** Add a false to list of constants and return its index.
633c7f896d7Ssalazar */
boolF(FuncState * fs)634f0dad708Snikita static int boolF (FuncState *fs) {
635dbec5304Smbalmer   TValue o;
636f0dad708Snikita   setbfvalue(&o);
637f0dad708Snikita   return addk(fs, &o, &o);  /* use boolean itself as key */
638f0dad708Snikita }
639f0dad708Snikita 
640f0dad708Snikita 
641f0dad708Snikita /*
642f0dad708Snikita ** Add a true to list of constants and return its index.
643f0dad708Snikita */
boolT(FuncState * fs)644f0dad708Snikita static int boolT (FuncState *fs) {
645f0dad708Snikita   TValue o;
646f0dad708Snikita   setbtvalue(&o);
647c7f896d7Ssalazar   return addk(fs, &o, &o);  /* use boolean itself as key */
648dbec5304Smbalmer }
649dbec5304Smbalmer 
650dbec5304Smbalmer 
651c7f896d7Ssalazar /*
652c7f896d7Ssalazar ** Add nil to list of constants and return its index.
653c7f896d7Ssalazar */
nilK(FuncState * fs)654dbec5304Smbalmer static int nilK (FuncState *fs) {
655dbec5304Smbalmer   TValue k, v;
656dbec5304Smbalmer   setnilvalue(&v);
657dbec5304Smbalmer   /* cannot use nil as key; instead use table itself to represent nil */
6584ab4902eSlneto   sethvalue(fs->ls->L, &k, fs->ls->h);
659dbec5304Smbalmer   return addk(fs, &k, &v);
660dbec5304Smbalmer }
661dbec5304Smbalmer 
662dbec5304Smbalmer 
663c7f896d7Ssalazar /*
664f0dad708Snikita ** Check whether 'i' can be stored in an 'sC' operand. Equivalent to
665f0dad708Snikita ** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of
666f0dad708Snikita ** overflows in the hidden addition inside 'int2sC'.
667f0dad708Snikita */
fitsC(lua_Integer i)668f0dad708Snikita static int fitsC (lua_Integer i) {
669f0dad708Snikita   return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C));
670f0dad708Snikita }
671f0dad708Snikita 
672f0dad708Snikita 
673f0dad708Snikita /*
674f0dad708Snikita ** Check whether 'i' can be stored in an 'sBx' operand.
675f0dad708Snikita */
fitsBx(lua_Integer i)676f0dad708Snikita static int fitsBx (lua_Integer i) {
677f0dad708Snikita   return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx);
678f0dad708Snikita }
679f0dad708Snikita 
680f0dad708Snikita 
luaK_int(FuncState * fs,int reg,lua_Integer i)681f0dad708Snikita void luaK_int (FuncState *fs, int reg, lua_Integer i) {
682f0dad708Snikita   if (fitsBx(i))
683f0dad708Snikita     luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i));
684f0dad708Snikita   else
685f0dad708Snikita     luaK_codek(fs, reg, luaK_intK(fs, i));
686f0dad708Snikita }
687f0dad708Snikita 
688f0dad708Snikita 
689f0dad708Snikita #ifndef _KERNEL
luaK_float(FuncState * fs,int reg,lua_Number f)690f0dad708Snikita static void luaK_float (FuncState *fs, int reg, lua_Number f) {
691f0dad708Snikita   lua_Integer fi;
692f0dad708Snikita   if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi))
693f0dad708Snikita     luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
694f0dad708Snikita   else
695f0dad708Snikita     luaK_codek(fs, reg, luaK_numberK(fs, f));
696f0dad708Snikita }
697f0dad708Snikita #endif /* _KERNEL */
698f0dad708Snikita 
699f0dad708Snikita 
700f0dad708Snikita /*
701f0dad708Snikita ** Convert a constant in 'v' into an expression description 'e'
702f0dad708Snikita */
const2exp(TValue * v,expdesc * e)703f0dad708Snikita static void const2exp (TValue *v, expdesc *e) {
704f0dad708Snikita   switch (ttypetag(v)) {
705f0dad708Snikita     case LUA_VNUMINT:
706f0dad708Snikita       e->k = VKINT; e->u.ival = ivalue(v);
707f0dad708Snikita       break;
708f0dad708Snikita #ifndef _KERNEL
709f0dad708Snikita     case LUA_VNUMFLT:
710f0dad708Snikita       e->k = VKFLT; e->u.nval = fltvalue(v);
711f0dad708Snikita       break;
712f0dad708Snikita #endif /* _KERNEL */
713f0dad708Snikita     case LUA_VFALSE:
714f0dad708Snikita       e->k = VFALSE;
715f0dad708Snikita       break;
716f0dad708Snikita     case LUA_VTRUE:
717f0dad708Snikita       e->k = VTRUE;
718f0dad708Snikita       break;
719f0dad708Snikita     case LUA_VNIL:
720f0dad708Snikita       e->k = VNIL;
721f0dad708Snikita       break;
722f0dad708Snikita     case LUA_VSHRSTR:  case LUA_VLNGSTR:
723f0dad708Snikita       e->k = VKSTR; e->u.strval = tsvalue(v);
724f0dad708Snikita       break;
725f0dad708Snikita     default: lua_assert(0);
726f0dad708Snikita   }
727f0dad708Snikita }
728f0dad708Snikita 
729f0dad708Snikita 
730f0dad708Snikita /*
731c7f896d7Ssalazar ** Fix an expression to return the number of results 'nresults'.
732f0dad708Snikita ** 'e' must be a multi-ret expression (function call or vararg).
733c7f896d7Ssalazar */
luaK_setreturns(FuncState * fs,expdesc * e,int nresults)734dbec5304Smbalmer void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
735c7f896d7Ssalazar   Instruction *pc = &getinstruction(fs, e);
736f0dad708Snikita   if (e->k == VCALL)  /* expression is an open function call? */
737f0dad708Snikita     SETARG_C(*pc, nresults + 1);
738f0dad708Snikita   else {
739f0dad708Snikita     lua_assert(e->k == VVARARG);
740f0dad708Snikita     SETARG_C(*pc, nresults + 1);
741c7f896d7Ssalazar     SETARG_A(*pc, fs->freereg);
742dbec5304Smbalmer     luaK_reserveregs(fs, 1);
743dbec5304Smbalmer   }
744f0dad708Snikita }
745f0dad708Snikita 
746f0dad708Snikita 
747f0dad708Snikita /*
748f0dad708Snikita ** Convert a VKSTR to a VK
749f0dad708Snikita */
str2K(FuncState * fs,expdesc * e)750f0dad708Snikita static void str2K (FuncState *fs, expdesc *e) {
751f0dad708Snikita   lua_assert(e->k == VKSTR);
752f0dad708Snikita   e->u.info = stringK(fs, e->u.strval);
753f0dad708Snikita   e->k = VK;
754dbec5304Smbalmer }
755dbec5304Smbalmer 
756dbec5304Smbalmer 
757c7f896d7Ssalazar /*
758c7f896d7Ssalazar ** Fix an expression to return one result.
759c7f896d7Ssalazar ** If expression is not a multi-ret expression (function call or
760c7f896d7Ssalazar ** vararg), it already returns one result, so nothing needs to be done.
761c7f896d7Ssalazar ** Function calls become VNONRELOC expressions (as its result comes
762c7f896d7Ssalazar ** fixed in the base register of the call), while vararg expressions
763f0dad708Snikita ** become VRELOC (as OP_VARARG puts its results where it wants).
764c7f896d7Ssalazar ** (Calls are created returning one result, so that does not need
765c7f896d7Ssalazar ** to be fixed.)
766c7f896d7Ssalazar */
luaK_setoneret(FuncState * fs,expdesc * e)767dbec5304Smbalmer void luaK_setoneret (FuncState *fs, expdesc *e) {
768dbec5304Smbalmer   if (e->k == VCALL) {  /* expression is an open function call? */
769c7f896d7Ssalazar     /* already returns 1 value */
770c7f896d7Ssalazar     lua_assert(GETARG_C(getinstruction(fs, e)) == 2);
771c7f896d7Ssalazar     e->k = VNONRELOC;  /* result has fixed position */
772c7f896d7Ssalazar     e->u.info = GETARG_A(getinstruction(fs, e));
773dbec5304Smbalmer   }
774dbec5304Smbalmer   else if (e->k == VVARARG) {
775f0dad708Snikita     SETARG_C(getinstruction(fs, e), 2);
776f0dad708Snikita     e->k = VRELOC;  /* can relocate its simple result */
777dbec5304Smbalmer   }
778dbec5304Smbalmer }
779dbec5304Smbalmer 
780dbec5304Smbalmer 
781c7f896d7Ssalazar /*
782f0dad708Snikita ** Ensure that expression 'e' is not a variable (nor a <const>).
783f0dad708Snikita ** (Expression still may have jump lists.)
784c7f896d7Ssalazar */
luaK_dischargevars(FuncState * fs,expdesc * e)785dbec5304Smbalmer void luaK_dischargevars (FuncState *fs, expdesc *e) {
786dbec5304Smbalmer   switch (e->k) {
787f0dad708Snikita     case VCONST: {
788f0dad708Snikita       const2exp(const2val(fs, e), e);
789f0dad708Snikita       break;
790f0dad708Snikita     }
791c7f896d7Ssalazar     case VLOCAL: {  /* already in a register */
792f0dad708Snikita       e->u.info = e->u.var.ridx;
793c7f896d7Ssalazar       e->k = VNONRELOC;  /* becomes a non-relocatable value */
794dbec5304Smbalmer       break;
795dbec5304Smbalmer     }
796c7f896d7Ssalazar     case VUPVAL: {  /* move value to some (pending) register */
7974ab4902eSlneto       e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
798f0dad708Snikita       e->k = VRELOC;
799f0dad708Snikita       break;
800f0dad708Snikita     }
801f0dad708Snikita     case VINDEXUP: {
802f0dad708Snikita       e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx);
803f0dad708Snikita       e->k = VRELOC;
804f0dad708Snikita       break;
805f0dad708Snikita     }
806f0dad708Snikita     case VINDEXI: {
807f0dad708Snikita       freereg(fs, e->u.ind.t);
808f0dad708Snikita       e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx);
809f0dad708Snikita       e->k = VRELOC;
810f0dad708Snikita       break;
811f0dad708Snikita     }
812f0dad708Snikita     case VINDEXSTR: {
813f0dad708Snikita       freereg(fs, e->u.ind.t);
814f0dad708Snikita       e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx);
815f0dad708Snikita       e->k = VRELOC;
816dbec5304Smbalmer       break;
817dbec5304Smbalmer     }
818dbec5304Smbalmer     case VINDEXED: {
819f0dad708Snikita       freeregs(fs, e->u.ind.t, e->u.ind.idx);
820f0dad708Snikita       e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx);
821f0dad708Snikita       e->k = VRELOC;
822dbec5304Smbalmer       break;
823dbec5304Smbalmer     }
824c7f896d7Ssalazar     case VVARARG: case VCALL: {
825dbec5304Smbalmer       luaK_setoneret(fs, e);
826dbec5304Smbalmer       break;
827dbec5304Smbalmer     }
828dbec5304Smbalmer     default: break;  /* there is one value available (somewhere) */
829dbec5304Smbalmer   }
830dbec5304Smbalmer }
831dbec5304Smbalmer 
832dbec5304Smbalmer 
833c7f896d7Ssalazar /*
834f0dad708Snikita ** Ensure expression value is in register 'reg', making 'e' a
835f0dad708Snikita ** non-relocatable expression.
836f0dad708Snikita ** (Expression still may have jump lists.)
837c7f896d7Ssalazar */
discharge2reg(FuncState * fs,expdesc * e,int reg)838dbec5304Smbalmer static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
839dbec5304Smbalmer   luaK_dischargevars(fs, e);
840dbec5304Smbalmer   switch (e->k) {
841dbec5304Smbalmer     case VNIL: {
842dbec5304Smbalmer       luaK_nil(fs, reg, 1);
843dbec5304Smbalmer       break;
844dbec5304Smbalmer     }
845f0dad708Snikita     case VFALSE: {
846f0dad708Snikita       luaK_codeABC(fs, OP_LOADFALSE, reg, 0, 0);
847dbec5304Smbalmer       break;
848dbec5304Smbalmer     }
849f0dad708Snikita     case VTRUE: {
850f0dad708Snikita       luaK_codeABC(fs, OP_LOADTRUE, reg, 0, 0);
851f0dad708Snikita       break;
852f0dad708Snikita     }
853f0dad708Snikita     case VKSTR: {
854f0dad708Snikita       str2K(fs, e);
855f0dad708Snikita     }  /* FALLTHROUGH */
856dbec5304Smbalmer     case VK: {
8574ab4902eSlneto       luaK_codek(fs, reg, e->u.info);
858dbec5304Smbalmer       break;
859dbec5304Smbalmer     }
8604ab4902eSlneto #ifndef _KERNEL
8614ab4902eSlneto     case VKFLT: {
862f0dad708Snikita       luaK_float(fs, reg, e->u.nval);
8634ab4902eSlneto       break;
8644ab4902eSlneto     }
8652d6cb6c2Slneto #endif /* _KERNEL */
8664ab4902eSlneto     case VKINT: {
867f0dad708Snikita       luaK_int(fs, reg, e->u.ival);
868dbec5304Smbalmer       break;
869dbec5304Smbalmer     }
870f0dad708Snikita     case VRELOC: {
871c7f896d7Ssalazar       Instruction *pc = &getinstruction(fs, e);
872c7f896d7Ssalazar       SETARG_A(*pc, reg);  /* instruction will put result in 'reg' */
873dbec5304Smbalmer       break;
874dbec5304Smbalmer     }
875dbec5304Smbalmer     case VNONRELOC: {
8764ab4902eSlneto       if (reg != e->u.info)
8774ab4902eSlneto         luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
878dbec5304Smbalmer       break;
879dbec5304Smbalmer     }
880dbec5304Smbalmer     default: {
881c7f896d7Ssalazar       lua_assert(e->k == VJMP);
882dbec5304Smbalmer       return;  /* nothing to do... */
883dbec5304Smbalmer     }
884dbec5304Smbalmer   }
8854ab4902eSlneto   e->u.info = reg;
886dbec5304Smbalmer   e->k = VNONRELOC;
887dbec5304Smbalmer }
888dbec5304Smbalmer 
889dbec5304Smbalmer 
890c7f896d7Ssalazar /*
891f0dad708Snikita ** Ensure expression value is in a register, making 'e' a
892f0dad708Snikita ** non-relocatable expression.
893f0dad708Snikita ** (Expression still may have jump lists.)
894c7f896d7Ssalazar */
discharge2anyreg(FuncState * fs,expdesc * e)895dbec5304Smbalmer static void discharge2anyreg (FuncState *fs, expdesc *e) {
896c7f896d7Ssalazar   if (e->k != VNONRELOC) {  /* no fixed register yet? */
897c7f896d7Ssalazar     luaK_reserveregs(fs, 1);  /* get a register */
898c7f896d7Ssalazar     discharge2reg(fs, e, fs->freereg-1);  /* put value there */
899dbec5304Smbalmer   }
900dbec5304Smbalmer }
901dbec5304Smbalmer 
902dbec5304Smbalmer 
code_loadbool(FuncState * fs,int A,OpCode op)903f0dad708Snikita static int code_loadbool (FuncState *fs, int A, OpCode op) {
904c7f896d7Ssalazar   luaK_getlabel(fs);  /* those instructions may be jump targets */
905f0dad708Snikita   return luaK_codeABC(fs, op, A, 0, 0);
906c7f896d7Ssalazar }
907c7f896d7Ssalazar 
908c7f896d7Ssalazar 
909c7f896d7Ssalazar /*
910c7f896d7Ssalazar ** check whether list has any jump that do not produce a value
911c7f896d7Ssalazar ** or produce an inverted value
912c7f896d7Ssalazar */
need_value(FuncState * fs,int list)913c7f896d7Ssalazar static int need_value (FuncState *fs, int list) {
914c7f896d7Ssalazar   for (; list != NO_JUMP; list = getjump(fs, list)) {
915c7f896d7Ssalazar     Instruction i = *getjumpcontrol(fs, list);
916c7f896d7Ssalazar     if (GET_OPCODE(i) != OP_TESTSET) return 1;
917c7f896d7Ssalazar   }
918c7f896d7Ssalazar   return 0;  /* not found */
919c7f896d7Ssalazar }
920c7f896d7Ssalazar 
921c7f896d7Ssalazar 
922c7f896d7Ssalazar /*
923f0dad708Snikita ** Ensures final expression result (which includes results from its
924f0dad708Snikita ** jump lists) is in register 'reg'.
925c7f896d7Ssalazar ** If expression has jumps, need to patch these jumps either to
926c7f896d7Ssalazar ** its final position or to "load" instructions (for those tests
927c7f896d7Ssalazar ** that do not produce values).
928c7f896d7Ssalazar */
exp2reg(FuncState * fs,expdesc * e,int reg)929dbec5304Smbalmer static void exp2reg (FuncState *fs, expdesc *e, int reg) {
930dbec5304Smbalmer   discharge2reg(fs, e, reg);
931c7f896d7Ssalazar   if (e->k == VJMP)  /* expression itself is a test? */
93273008250Slneto     luaK_concat(fs, &e->t, e->u.info);  /* put this jump in 't' list */
933dbec5304Smbalmer   if (hasjumps(e)) {
934dbec5304Smbalmer     int final;  /* position after whole expression */
935dbec5304Smbalmer     int p_f = NO_JUMP;  /* position of an eventual LOAD false */
936dbec5304Smbalmer     int p_t = NO_JUMP;  /* position of an eventual LOAD true */
937dbec5304Smbalmer     if (need_value(fs, e->t) || need_value(fs, e->f)) {
938dbec5304Smbalmer       int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
939f0dad708Snikita       p_f = code_loadbool(fs, reg, OP_LFALSESKIP);  /* skip next inst. */
940f0dad708Snikita       p_t = code_loadbool(fs, reg, OP_LOADTRUE);
941f0dad708Snikita       /* jump around these booleans if 'e' is not a test */
942dbec5304Smbalmer       luaK_patchtohere(fs, fj);
943dbec5304Smbalmer     }
944dbec5304Smbalmer     final = luaK_getlabel(fs);
945dbec5304Smbalmer     patchlistaux(fs, e->f, final, reg, p_f);
946dbec5304Smbalmer     patchlistaux(fs, e->t, final, reg, p_t);
947dbec5304Smbalmer   }
948dbec5304Smbalmer   e->f = e->t = NO_JUMP;
9494ab4902eSlneto   e->u.info = reg;
950dbec5304Smbalmer   e->k = VNONRELOC;
951dbec5304Smbalmer }
952dbec5304Smbalmer 
953dbec5304Smbalmer 
954c7f896d7Ssalazar /*
955f0dad708Snikita ** Ensures final expression result is in next available register.
956c7f896d7Ssalazar */
luaK_exp2nextreg(FuncState * fs,expdesc * e)957dbec5304Smbalmer void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
958dbec5304Smbalmer   luaK_dischargevars(fs, e);
959dbec5304Smbalmer   freeexp(fs, e);
960dbec5304Smbalmer   luaK_reserveregs(fs, 1);
961dbec5304Smbalmer   exp2reg(fs, e, fs->freereg - 1);
962dbec5304Smbalmer }
963dbec5304Smbalmer 
964dbec5304Smbalmer 
965c7f896d7Ssalazar /*
966f0dad708Snikita ** Ensures final expression result is in some (any) register
967f0dad708Snikita ** and return that register.
968c7f896d7Ssalazar */
luaK_exp2anyreg(FuncState * fs,expdesc * e)969dbec5304Smbalmer int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
970dbec5304Smbalmer   luaK_dischargevars(fs, e);
971c7f896d7Ssalazar   if (e->k == VNONRELOC) {  /* expression already has a register? */
972c7f896d7Ssalazar     if (!hasjumps(e))  /* no jumps? */
973c7f896d7Ssalazar       return e->u.info;  /* result is already in a register */
974f0dad708Snikita     if (e->u.info >= luaY_nvarstack(fs)) {  /* reg. is not a local? */
975c7f896d7Ssalazar       exp2reg(fs, e, e->u.info);  /* put final result in it */
9764ab4902eSlneto       return e->u.info;
977dbec5304Smbalmer     }
978f0dad708Snikita     /* else expression has jumps and cannot change its register
979f0dad708Snikita        to hold the jump values, because it is a local variable.
980f0dad708Snikita        Go through to the default case. */
981dbec5304Smbalmer   }
982f0dad708Snikita   luaK_exp2nextreg(fs, e);  /* default: use next available register */
9834ab4902eSlneto   return e->u.info;
9844ab4902eSlneto }
9854ab4902eSlneto 
9864ab4902eSlneto 
987c7f896d7Ssalazar /*
988f0dad708Snikita ** Ensures final expression result is either in a register
989f0dad708Snikita ** or in an upvalue.
990c7f896d7Ssalazar */
luaK_exp2anyregup(FuncState * fs,expdesc * e)9914ab4902eSlneto void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
9924ab4902eSlneto   if (e->k != VUPVAL || hasjumps(e))
9934ab4902eSlneto     luaK_exp2anyreg(fs, e);
994dbec5304Smbalmer }
995dbec5304Smbalmer 
996dbec5304Smbalmer 
997c7f896d7Ssalazar /*
998f0dad708Snikita ** Ensures final expression result is either in a register
999f0dad708Snikita ** or it is a constant.
1000c7f896d7Ssalazar */
luaK_exp2val(FuncState * fs,expdesc * e)1001dbec5304Smbalmer void luaK_exp2val (FuncState *fs, expdesc *e) {
1002dbec5304Smbalmer   if (hasjumps(e))
1003dbec5304Smbalmer     luaK_exp2anyreg(fs, e);
1004dbec5304Smbalmer   else
1005dbec5304Smbalmer     luaK_dischargevars(fs, e);
1006dbec5304Smbalmer }
1007dbec5304Smbalmer 
1008dbec5304Smbalmer 
1009c7f896d7Ssalazar /*
1010f0dad708Snikita ** Try to make 'e' a K expression with an index in the range of R/K
1011f0dad708Snikita ** indices. Return true iff succeeded.
1012f0dad708Snikita */
luaK_exp2K(FuncState * fs,expdesc * e)1013f0dad708Snikita static int luaK_exp2K (FuncState *fs, expdesc *e) {
1014f0dad708Snikita   if (!hasjumps(e)) {
1015f0dad708Snikita     int info;
1016f0dad708Snikita     switch (e->k) {  /* move constants to 'k' */
1017f0dad708Snikita       case VTRUE: info = boolT(fs); break;
1018f0dad708Snikita       case VFALSE: info = boolF(fs); break;
1019f0dad708Snikita       case VNIL: info = nilK(fs); break;
1020f0dad708Snikita       case VKINT: info = luaK_intK(fs, e->u.ival); break;
1021f0dad708Snikita #ifndef _KERNEL
1022f0dad708Snikita       case VKFLT: info = luaK_numberK(fs, e->u.nval); break;
1023f0dad708Snikita #endif /* _KERNEL */
1024f0dad708Snikita       case VKSTR: info = stringK(fs, e->u.strval); break;
1025f0dad708Snikita       case VK: info = e->u.info; break;
1026f0dad708Snikita       default: return 0;  /* not a constant */
1027f0dad708Snikita     }
1028f0dad708Snikita     if (info <= MAXINDEXRK) {  /* does constant fit in 'argC'? */
1029f0dad708Snikita       e->k = VK;  /* make expression a 'K' expression */
1030f0dad708Snikita       e->u.info = info;
1031f0dad708Snikita       return 1;
1032f0dad708Snikita     }
1033f0dad708Snikita   }
1034f0dad708Snikita   /* else, expression doesn't fit; leave it unchanged */
1035f0dad708Snikita   return 0;
1036f0dad708Snikita }
1037f0dad708Snikita 
1038f0dad708Snikita 
1039f0dad708Snikita /*
1040c7f896d7Ssalazar ** Ensures final expression result is in a valid R/K index
1041c7f896d7Ssalazar ** (that is, it is either in a register or in 'k' with an index
1042c7f896d7Ssalazar ** in the range of R/K indices).
1043f0dad708Snikita ** Returns 1 iff expression is K.
1044c7f896d7Ssalazar */
luaK_exp2RK(FuncState * fs,expdesc * e)1045dbec5304Smbalmer int luaK_exp2RK (FuncState *fs, expdesc *e) {
1046f0dad708Snikita   if (luaK_exp2K(fs, e))
1047f0dad708Snikita     return 1;
1048f0dad708Snikita   else {  /* not a constant in the right range: put it in a register */
1049f0dad708Snikita     luaK_exp2anyreg(fs, e);
1050f0dad708Snikita     return 0;
1051dbec5304Smbalmer   }
1052f0dad708Snikita }
1053f0dad708Snikita 
1054f0dad708Snikita 
codeABRK(FuncState * fs,OpCode o,int a,int b,expdesc * ec)1055f0dad708Snikita static void codeABRK (FuncState *fs, OpCode o, int a, int b,
1056f0dad708Snikita                       expdesc *ec) {
1057f0dad708Snikita   int k = luaK_exp2RK(fs, ec);
1058f0dad708Snikita   luaK_codeABCk(fs, o, a, b, ec->u.info, k);
1059dbec5304Smbalmer }
1060dbec5304Smbalmer 
1061dbec5304Smbalmer 
1062c7f896d7Ssalazar /*
1063c7f896d7Ssalazar ** Generate code to store result of expression 'ex' into variable 'var'.
1064c7f896d7Ssalazar */
luaK_storevar(FuncState * fs,expdesc * var,expdesc * ex)1065dbec5304Smbalmer void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
1066dbec5304Smbalmer   switch (var->k) {
1067dbec5304Smbalmer     case VLOCAL: {
1068dbec5304Smbalmer       freeexp(fs, ex);
1069f0dad708Snikita       exp2reg(fs, ex, var->u.var.ridx);  /* compute 'ex' into proper place */
1070dbec5304Smbalmer       return;
1071dbec5304Smbalmer     }
1072dbec5304Smbalmer     case VUPVAL: {
1073dbec5304Smbalmer       int e = luaK_exp2anyreg(fs, ex);
10744ab4902eSlneto       luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
1075dbec5304Smbalmer       break;
1076dbec5304Smbalmer     }
1077f0dad708Snikita     case VINDEXUP: {
1078f0dad708Snikita       codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex);
1079f0dad708Snikita       break;
1080f0dad708Snikita     }
1081f0dad708Snikita     case VINDEXI: {
1082f0dad708Snikita       codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex);
1083f0dad708Snikita       break;
1084f0dad708Snikita     }
1085f0dad708Snikita     case VINDEXSTR: {
1086f0dad708Snikita       codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex);
1087f0dad708Snikita       break;
1088f0dad708Snikita     }
1089dbec5304Smbalmer     case VINDEXED: {
1090f0dad708Snikita       codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex);
1091dbec5304Smbalmer       break;
1092dbec5304Smbalmer     }
1093c7f896d7Ssalazar     default: lua_assert(0);  /* invalid var kind to store */
1094dbec5304Smbalmer   }
1095dbec5304Smbalmer   freeexp(fs, ex);
1096dbec5304Smbalmer }
1097dbec5304Smbalmer 
1098dbec5304Smbalmer 
1099c7f896d7Ssalazar /*
1100c7f896d7Ssalazar ** Emit SELF instruction (convert expression 'e' into 'e:key(e,').
1101c7f896d7Ssalazar */
luaK_self(FuncState * fs,expdesc * e,expdesc * key)1102dbec5304Smbalmer void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
11034ab4902eSlneto   int ereg;
1104dbec5304Smbalmer   luaK_exp2anyreg(fs, e);
11054ab4902eSlneto   ereg = e->u.info;  /* register where 'e' was placed */
1106dbec5304Smbalmer   freeexp(fs, e);
11074ab4902eSlneto   e->u.info = fs->freereg;  /* base register for op_self */
1108c7f896d7Ssalazar   e->k = VNONRELOC;  /* self expression has a fixed register */
11094ab4902eSlneto   luaK_reserveregs(fs, 2);  /* function and 'self' produced by op_self */
1110f0dad708Snikita   codeABRK(fs, OP_SELF, e->u.info, ereg, key);
11114ab4902eSlneto   freeexp(fs, key);
1112dbec5304Smbalmer }
1113dbec5304Smbalmer 
1114dbec5304Smbalmer 
1115c7f896d7Ssalazar /*
1116c7f896d7Ssalazar ** Negate condition 'e' (where 'e' is a comparison).
1117c7f896d7Ssalazar */
negatecondition(FuncState * fs,expdesc * e)1118c7f896d7Ssalazar static void negatecondition (FuncState *fs, expdesc *e) {
11194ab4902eSlneto   Instruction *pc = getjumpcontrol(fs, e->u.info);
1120dbec5304Smbalmer   lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
1121dbec5304Smbalmer                                            GET_OPCODE(*pc) != OP_TEST);
1122f0dad708Snikita   SETARG_k(*pc, (GETARG_k(*pc) ^ 1));
1123dbec5304Smbalmer }
1124dbec5304Smbalmer 
1125dbec5304Smbalmer 
1126c7f896d7Ssalazar /*
1127c7f896d7Ssalazar ** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond'
1128c7f896d7Ssalazar ** is true, code will jump if 'e' is true.) Return jump position.
1129c7f896d7Ssalazar ** Optimize when 'e' is 'not' something, inverting the condition
1130c7f896d7Ssalazar ** and removing the 'not'.
1131c7f896d7Ssalazar */
jumponcond(FuncState * fs,expdesc * e,int cond)1132dbec5304Smbalmer static int jumponcond (FuncState *fs, expdesc *e, int cond) {
1133f0dad708Snikita   if (e->k == VRELOC) {
1134c7f896d7Ssalazar     Instruction ie = getinstruction(fs, e);
1135dbec5304Smbalmer     if (GET_OPCODE(ie) == OP_NOT) {
1136f0dad708Snikita       removelastinstruction(fs);  /* remove previous OP_NOT */
1137f0dad708Snikita       return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond);
1138dbec5304Smbalmer     }
1139dbec5304Smbalmer     /* else go through */
1140dbec5304Smbalmer   }
1141dbec5304Smbalmer   discharge2anyreg(fs, e);
1142dbec5304Smbalmer   freeexp(fs, e);
1143f0dad708Snikita   return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond);
1144dbec5304Smbalmer }
1145dbec5304Smbalmer 
1146dbec5304Smbalmer 
1147c7f896d7Ssalazar /*
1148c7f896d7Ssalazar ** Emit code to go through if 'e' is true, jump otherwise.
1149c7f896d7Ssalazar */
luaK_goiftrue(FuncState * fs,expdesc * e)1150dbec5304Smbalmer void luaK_goiftrue (FuncState *fs, expdesc *e) {
1151c7f896d7Ssalazar   int pc;  /* pc of new jump */
1152dbec5304Smbalmer   luaK_dischargevars(fs, e);
1153dbec5304Smbalmer   switch (e->k) {
1154c7f896d7Ssalazar     case VJMP: {  /* condition? */
1155c7f896d7Ssalazar       negatecondition(fs, e);  /* jump when it is false */
1156c7f896d7Ssalazar       pc = e->u.info;  /* save jump position */
11574ab4902eSlneto       break;
11584ab4902eSlneto     }
11594ab4902eSlneto #ifndef _KERNEL
1160f0dad708Snikita     case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
11612d6cb6c2Slneto #else /* _KERNEL */
1162f0dad708Snikita     case VK: case VKINT: case VKSTR: case VTRUE: {
11632d6cb6c2Slneto #endif /* _KERNEL */
11644ab4902eSlneto       pc = NO_JUMP;  /* always true; do nothing */
1165dbec5304Smbalmer       break;
1166dbec5304Smbalmer     }
1167dbec5304Smbalmer     default: {
1168c7f896d7Ssalazar       pc = jumponcond(fs, e, 0);  /* jump when false */
1169dbec5304Smbalmer       break;
1170dbec5304Smbalmer     }
1171dbec5304Smbalmer   }
1172c7f896d7Ssalazar   luaK_concat(fs, &e->f, pc);  /* insert new jump in false list */
1173c7f896d7Ssalazar   luaK_patchtohere(fs, e->t);  /* true list jumps to here (to go through) */
1174dbec5304Smbalmer   e->t = NO_JUMP;
1175dbec5304Smbalmer }
1176dbec5304Smbalmer 
1177dbec5304Smbalmer 
1178c7f896d7Ssalazar /*
1179c7f896d7Ssalazar ** Emit code to go through if 'e' is false, jump otherwise.
1180c7f896d7Ssalazar */
11814ab4902eSlneto void luaK_goiffalse (FuncState *fs, expdesc *e) {
1182c7f896d7Ssalazar   int pc;  /* pc of new jump */
1183dbec5304Smbalmer   luaK_dischargevars(fs, e);
1184dbec5304Smbalmer   switch (e->k) {
11854ab4902eSlneto     case VJMP: {
1186c7f896d7Ssalazar       pc = e->u.info;  /* already jump if true */
1187dbec5304Smbalmer       break;
1188dbec5304Smbalmer     }
11894ab4902eSlneto     case VNIL: case VFALSE: {
11904ab4902eSlneto       pc = NO_JUMP;  /* always false; do nothing */
1191dbec5304Smbalmer       break;
1192dbec5304Smbalmer     }
1193dbec5304Smbalmer     default: {
1194c7f896d7Ssalazar       pc = jumponcond(fs, e, 1);  /* jump if true */
1195dbec5304Smbalmer       break;
1196dbec5304Smbalmer     }
1197dbec5304Smbalmer   }
1198c7f896d7Ssalazar   luaK_concat(fs, &e->t, pc);  /* insert new jump in 't' list */
1199c7f896d7Ssalazar   luaK_patchtohere(fs, e->f);  /* false list jumps to here (to go through) */
1200dbec5304Smbalmer   e->f = NO_JUMP;
1201dbec5304Smbalmer }
1202dbec5304Smbalmer 
1203dbec5304Smbalmer 
1204c7f896d7Ssalazar /*
1205c7f896d7Ssalazar ** Code 'not e', doing constant folding.
1206c7f896d7Ssalazar */
1207dbec5304Smbalmer static void codenot (FuncState *fs, expdesc *e) {
1208dbec5304Smbalmer   switch (e->k) {
1209dbec5304Smbalmer     case VNIL: case VFALSE: {
1210c7f896d7Ssalazar       e->k = VTRUE;  /* true == not nil == not false */
1211dbec5304Smbalmer       break;
1212dbec5304Smbalmer     }
12134ab4902eSlneto #ifndef _KERNEL
1214f0dad708Snikita     case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
12152d6cb6c2Slneto #else /* _KERNEL */
1216f0dad708Snikita     case VK: case VKINT: case VKSTR: case VTRUE: {
12172d6cb6c2Slneto #endif /* _KERNEL */
1218c7f896d7Ssalazar       e->k = VFALSE;  /* false == not "x" == not 0.5 == not 1 == not true */
1219dbec5304Smbalmer       break;
1220dbec5304Smbalmer     }
1221dbec5304Smbalmer     case VJMP: {
1222c7f896d7Ssalazar       negatecondition(fs, e);
1223dbec5304Smbalmer       break;
1224dbec5304Smbalmer     }
1225f0dad708Snikita     case VRELOC:
1226dbec5304Smbalmer     case VNONRELOC: {
1227dbec5304Smbalmer       discharge2anyreg(fs, e);
1228dbec5304Smbalmer       freeexp(fs, e);
12294ab4902eSlneto       e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
1230f0dad708Snikita       e->k = VRELOC;
1231dbec5304Smbalmer       break;
1232dbec5304Smbalmer     }
1233c7f896d7Ssalazar     default: lua_assert(0);  /* cannot happen */
1234dbec5304Smbalmer   }
1235dbec5304Smbalmer   /* interchange true and false lists */
1236dbec5304Smbalmer   { int temp = e->f; e->f = e->t; e->t = temp; }
1237c7f896d7Ssalazar   removevalues(fs, e->f);  /* values are useless when negated */
1238dbec5304Smbalmer   removevalues(fs, e->t);
1239dbec5304Smbalmer }
1240dbec5304Smbalmer 
1241dbec5304Smbalmer 
1242c7f896d7Ssalazar /*
1243f0dad708Snikita ** Check whether expression 'e' is a small literal string
1244f0dad708Snikita */
1245f0dad708Snikita static int isKstr (FuncState *fs, expdesc *e) {
1246f0dad708Snikita   return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
1247f0dad708Snikita           ttisshrstring(&fs->f->k[e->u.info]));
1248f0dad708Snikita }
1249f0dad708Snikita 
1250f0dad708Snikita /*
1251f0dad708Snikita ** Check whether expression 'e' is a literal integer.
1252f0dad708Snikita */
1253f0dad708Snikita int luaK_isKint (expdesc *e) {
1254f0dad708Snikita   return (e->k == VKINT && !hasjumps(e));
1255f0dad708Snikita }
1256f0dad708Snikita 
1257f0dad708Snikita 
1258f0dad708Snikita /*
1259f0dad708Snikita ** Check whether expression 'e' is a literal integer in
1260f0dad708Snikita ** proper range to fit in register C
1261f0dad708Snikita */
1262f0dad708Snikita static int isCint (expdesc *e) {
1263f0dad708Snikita   return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
1264f0dad708Snikita }
1265f0dad708Snikita 
1266f0dad708Snikita 
1267f0dad708Snikita /*
1268f0dad708Snikita ** Check whether expression 'e' is a literal integer in
1269f0dad708Snikita ** proper range to fit in register sC
1270f0dad708Snikita */
1271f0dad708Snikita static int isSCint (expdesc *e) {
1272f0dad708Snikita   return luaK_isKint(e) && fitsC(e->u.ival);
1273f0dad708Snikita }
1274f0dad708Snikita 
1275f0dad708Snikita 
1276f0dad708Snikita /*
1277f0dad708Snikita ** Check whether expression 'e' is a literal integer or float in
1278f0dad708Snikita ** proper range to fit in a register (sB or sC).
1279f0dad708Snikita */
1280f0dad708Snikita static int isSCnumber (expdesc *e, int *pi, int *isfloat) {
1281f0dad708Snikita   lua_Integer i;
1282f0dad708Snikita   if (e->k == VKINT)
1283f0dad708Snikita     i = e->u.ival;
1284f0dad708Snikita #ifndef _KERNEL
1285f0dad708Snikita   else if (e->k == VKFLT && luaV_flttointeger(e->u.nval, &i, F2Ieq))
1286f0dad708Snikita     *isfloat = 1;
1287f0dad708Snikita #endif /* _KERNEL */
1288f0dad708Snikita   else
1289f0dad708Snikita     return 0;  /* not a number */
1290f0dad708Snikita   if (!hasjumps(e) && fitsC(i)) {
1291f0dad708Snikita     *pi = int2sC(cast_int(i));
1292f0dad708Snikita     return 1;
1293f0dad708Snikita   }
1294f0dad708Snikita   else
1295f0dad708Snikita     return 0;
1296f0dad708Snikita }
1297f0dad708Snikita 
1298f0dad708Snikita 
1299f0dad708Snikita /*
1300c7f896d7Ssalazar ** Create expression 't[k]'. 't' must have its final result already in a
1301f0dad708Snikita ** register or upvalue. Upvalues can only be indexed by literal strings.
1302f0dad708Snikita ** Keys can be literal strings in the constant table or arbitrary
1303f0dad708Snikita ** values in registers.
1304c7f896d7Ssalazar */
1305dbec5304Smbalmer void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
1306f0dad708Snikita   if (k->k == VKSTR)
1307f0dad708Snikita     str2K(fs, k);
1308f0dad708Snikita   lua_assert(!hasjumps(t) &&
1309f0dad708Snikita              (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL));
1310f0dad708Snikita   if (t->k == VUPVAL && !isKstr(fs, k))  /* upvalue indexed by non 'Kstr'? */
1311f0dad708Snikita     luaK_exp2anyreg(fs, t);  /* put it in a register */
1312f0dad708Snikita   if (t->k == VUPVAL) {
1313f0dad708Snikita     t->u.ind.t = t->u.info;  /* upvalue index */
1314f0dad708Snikita     t->u.ind.idx = k->u.info;  /* literal string */
1315f0dad708Snikita     t->k = VINDEXUP;
1316f0dad708Snikita   }
1317f0dad708Snikita   else {
1318f0dad708Snikita     /* register index of the table */
1319f0dad708Snikita     t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info;
1320f0dad708Snikita     if (isKstr(fs, k)) {
1321f0dad708Snikita       t->u.ind.idx = k->u.info;  /* literal string */
1322f0dad708Snikita       t->k = VINDEXSTR;
1323f0dad708Snikita     }
1324f0dad708Snikita     else if (isCint(k)) {
1325f0dad708Snikita       t->u.ind.idx = cast_int(k->u.ival);  /* int. constant in proper range */
1326f0dad708Snikita       t->k = VINDEXI;
1327f0dad708Snikita     }
1328f0dad708Snikita     else {
1329f0dad708Snikita       t->u.ind.idx = luaK_exp2anyreg(fs, k);  /* register */
1330dbec5304Smbalmer       t->k = VINDEXED;
1331dbec5304Smbalmer     }
1332f0dad708Snikita   }
1333f0dad708Snikita }
1334dbec5304Smbalmer 
1335dbec5304Smbalmer 
13364ab4902eSlneto /*
1337c7f896d7Ssalazar ** Return false if folding can raise an error.
1338c7f896d7Ssalazar ** Bitwise operations need operands convertible to integers; division
1339c7f896d7Ssalazar ** operations cannot have 0 as divisor.
13404ab4902eSlneto */
13414ab4902eSlneto static int validop (int op, TValue *v1, TValue *v2) {
1342dbec5304Smbalmer   switch (op) {
13434ab4902eSlneto     case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
134473008250Slneto     case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: {  /* conversion errors */
134573008250Slneto       lua_Integer i;
1346f0dad708Snikita       return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) &&
1347f0dad708Snikita               luaV_tointegerns(v2, &i, LUA_FLOORN2I));
134873008250Slneto     }
134973008250Slneto #ifndef _KERNEL
135073008250Slneto     case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD:  /* division by 0 */
135173008250Slneto #else /* _KERNEL */
135273008250Slneto     case LUA_OPIDIV: case LUA_OPMOD:  /* division by 0 */
13532d6cb6c2Slneto #endif /* _KERNEL */
135473008250Slneto       return (nvalue(v2) != 0);
13554ab4902eSlneto     default: return 1;  /* everything else is valid */
1356dbec5304Smbalmer   }
13574ab4902eSlneto }
13584ab4902eSlneto 
13594ab4902eSlneto 
13604ab4902eSlneto /*
1361c7f896d7Ssalazar ** Try to "constant-fold" an operation; return 1 iff successful.
1362c7f896d7Ssalazar ** (In this case, 'e1' has the final result.)
13634ab4902eSlneto */
13649e2f6347Smbalmer static int constfolding (FuncState *fs, int op, expdesc *e1,
13659e2f6347Smbalmer                                         const expdesc *e2) {
13664ab4902eSlneto   TValue v1, v2, res;
13674ab4902eSlneto   if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2))
13684ab4902eSlneto     return 0;  /* non-numeric operands or not safe to fold */
1369f0dad708Snikita   luaO_rawarith(fs->ls->L, op, &v1, &v2, &res);  /* does operation */
13704ab4902eSlneto   if (ttisinteger(&res)) {
13714ab4902eSlneto     e1->k = VKINT;
13724ab4902eSlneto     e1->u.ival = ivalue(&res);
13734ab4902eSlneto   }
1374c7f896d7Ssalazar   else {  /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */
13754ab4902eSlneto #ifndef _KERNEL
13764ab4902eSlneto     lua_Number n = fltvalue(&res);
137773008250Slneto     if (luai_numisnan(n) || n == 0)
137873008250Slneto       return 0;
13794ab4902eSlneto     e1->k = VKFLT;
13804ab4902eSlneto     e1->u.nval = n;
138173008250Slneto #else /* _KERNEL */
138273008250Slneto     return 0;  /* if it is not integer, we must fail */
13832d6cb6c2Slneto #endif /* _KERNEL */
13844ab4902eSlneto   }
1385dbec5304Smbalmer   return 1;
1386dbec5304Smbalmer }
1387dbec5304Smbalmer 
1388dbec5304Smbalmer 
138973008250Slneto /*
1390*bdda0531Snikita ** Convert a BinOpr to an OpCode  (ORDER OPR - ORDER OP)
1391*bdda0531Snikita */
1392*bdda0531Snikita l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) {
1393*bdda0531Snikita   lua_assert(baser <= opr &&
1394*bdda0531Snikita             ((baser == OPR_ADD && opr <= OPR_SHR) ||
1395*bdda0531Snikita              (baser == OPR_LT && opr <= OPR_LE)));
1396*bdda0531Snikita   return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base));
1397*bdda0531Snikita }
1398*bdda0531Snikita 
1399*bdda0531Snikita 
1400*bdda0531Snikita /*
1401*bdda0531Snikita ** Convert a UnOpr to an OpCode  (ORDER OPR - ORDER OP)
1402*bdda0531Snikita */
1403*bdda0531Snikita l_sinline OpCode unopr2op (UnOpr opr) {
1404*bdda0531Snikita   return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) +
1405*bdda0531Snikita                                        cast_int(OP_UNM));
1406*bdda0531Snikita }
1407*bdda0531Snikita 
1408*bdda0531Snikita 
1409*bdda0531Snikita /*
1410*bdda0531Snikita ** Convert a BinOpr to a tag method  (ORDER OPR - ORDER TM)
1411*bdda0531Snikita */
1412*bdda0531Snikita l_sinline TMS binopr2TM (BinOpr opr) {
1413*bdda0531Snikita   lua_assert(OPR_ADD <= opr && opr <= OPR_SHR);
1414*bdda0531Snikita   return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD));
1415*bdda0531Snikita }
1416*bdda0531Snikita 
1417*bdda0531Snikita 
1418*bdda0531Snikita /*
1419c7f896d7Ssalazar ** Emit code for unary expressions that "produce values"
1420c7f896d7Ssalazar ** (everything but 'not').
1421c7f896d7Ssalazar ** Expression to produce final result will be encoded in 'e'.
1422c7f896d7Ssalazar */
1423c7f896d7Ssalazar static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
1424c7f896d7Ssalazar   int r = luaK_exp2anyreg(fs, e);  /* opcodes operate only on registers */
1425c7f896d7Ssalazar   freeexp(fs, e);
1426c7f896d7Ssalazar   e->u.info = luaK_codeABC(fs, op, 0, r, 0);  /* generate opcode */
1427f0dad708Snikita   e->k = VRELOC;  /* all those operations are relocatable */
1428c7f896d7Ssalazar   luaK_fixline(fs, line);
1429c7f896d7Ssalazar }
1430c7f896d7Ssalazar 
1431c7f896d7Ssalazar 
1432c7f896d7Ssalazar /*
1433c7f896d7Ssalazar ** Emit code for binary expressions that "produce values"
1434c7f896d7Ssalazar ** (everything but logical operators 'and'/'or' and comparison
1435c7f896d7Ssalazar ** operators).
143673008250Slneto ** Expression to produce final result will be encoded in 'e1'.
143773008250Slneto */
1438f0dad708Snikita static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
1439f0dad708Snikita                              OpCode op, int v2, int flip, int line,
1440f0dad708Snikita                              OpCode mmop, TMS event) {
1441f0dad708Snikita   int v1 = luaK_exp2anyreg(fs, e1);
1442f0dad708Snikita   int pc = luaK_codeABCk(fs, op, 0, v1, v2, 0);
1443c7f896d7Ssalazar   freeexps(fs, e1, e2);
1444f0dad708Snikita   e1->u.info = pc;
1445f0dad708Snikita   e1->k = VRELOC;  /* all those operations are relocatable */
1446f0dad708Snikita   luaK_fixline(fs, line);
1447f0dad708Snikita   luaK_codeABCk(fs, mmop, v1, v2, event, flip);  /* to call metamethod */
14484ab4902eSlneto   luaK_fixline(fs, line);
1449dbec5304Smbalmer }
1450dbec5304Smbalmer 
1451dbec5304Smbalmer 
1452c7f896d7Ssalazar /*
1453f0dad708Snikita ** Emit code for binary expressions that "produce values" over
1454f0dad708Snikita ** two registers.
1455c7f896d7Ssalazar */
1456*bdda0531Snikita static void codebinexpval (FuncState *fs, BinOpr opr,
1457f0dad708Snikita                            expdesc *e1, expdesc *e2, int line) {
1458*bdda0531Snikita   OpCode op = binopr2op(opr, OPR_ADD, OP_ADD);
14598e4bc226Snikita   int v2 = luaK_exp2anyreg(fs, e2);  /* make sure 'e2' is in a register */
14608e4bc226Snikita   /* 'e1' must be already in a register or it is a constant */
14618e4bc226Snikita   lua_assert((VNIL <= e1->k && e1->k <= VKSTR) ||
14628e4bc226Snikita              e1->k == VNONRELOC || e1->k == VRELOC);
1463f0dad708Snikita   lua_assert(OP_ADD <= op && op <= OP_SHR);
1464*bdda0531Snikita   finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr));
1465f0dad708Snikita }
1466f0dad708Snikita 
1467f0dad708Snikita 
1468f0dad708Snikita /*
1469f0dad708Snikita ** Code binary operators with immediate operands.
1470f0dad708Snikita */
1471f0dad708Snikita static void codebini (FuncState *fs, OpCode op,
1472f0dad708Snikita                        expdesc *e1, expdesc *e2, int flip, int line,
1473f0dad708Snikita                        TMS event) {
1474f0dad708Snikita   int v2 = int2sC(cast_int(e2->u.ival));  /* immediate operand */
1475f0dad708Snikita   lua_assert(e2->k == VKINT);
1476f0dad708Snikita   finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event);
1477f0dad708Snikita }
1478f0dad708Snikita 
1479f0dad708Snikita 
1480*bdda0531Snikita /*
1481*bdda0531Snikita ** Code binary operators with K operand.
1482*bdda0531Snikita */
1483*bdda0531Snikita static void codebinK (FuncState *fs, BinOpr opr,
1484*bdda0531Snikita                       expdesc *e1, expdesc *e2, int flip, int line) {
1485*bdda0531Snikita   TMS event = binopr2TM(opr);
1486*bdda0531Snikita   int v2 = e2->u.info;  /* K index */
1487*bdda0531Snikita   OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK);
1488*bdda0531Snikita   finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
1489*bdda0531Snikita }
1490*bdda0531Snikita 
1491*bdda0531Snikita 
1492f0dad708Snikita /* Try to code a binary operator negating its second operand.
1493f0dad708Snikita ** For the metamethod, 2nd operand must keep its original value.
1494f0dad708Snikita */
1495f0dad708Snikita static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
1496f0dad708Snikita                              OpCode op, int line, TMS event) {
1497f0dad708Snikita   if (!luaK_isKint(e2))
1498f0dad708Snikita     return 0;  /* not an integer constant */
1499f0dad708Snikita   else {
1500f0dad708Snikita     lua_Integer i2 = e2->u.ival;
1501f0dad708Snikita     if (!(fitsC(i2) && fitsC(-i2)))
1502f0dad708Snikita       return 0;  /* not in the proper range */
1503f0dad708Snikita     else {  /* operating a small integer constant */
1504f0dad708Snikita       int v2 = cast_int(i2);
1505f0dad708Snikita       finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
1506f0dad708Snikita       /* correct metamethod argument */
1507f0dad708Snikita       SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
1508f0dad708Snikita       return 1;  /* successfully coded */
1509f0dad708Snikita     }
1510f0dad708Snikita   }
1511f0dad708Snikita }
1512f0dad708Snikita 
1513f0dad708Snikita 
1514f0dad708Snikita static void swapexps (expdesc *e1, expdesc *e2) {
1515f0dad708Snikita   expdesc temp = *e1; *e1 = *e2; *e2 = temp;  /* swap 'e1' and 'e2' */
1516f0dad708Snikita }
1517f0dad708Snikita 
1518f0dad708Snikita 
1519f0dad708Snikita /*
1520*bdda0531Snikita ** Code binary operators with no constant operand.
1521*bdda0531Snikita */
1522*bdda0531Snikita static void codebinNoK (FuncState *fs, BinOpr opr,
1523*bdda0531Snikita                         expdesc *e1, expdesc *e2, int flip, int line) {
1524*bdda0531Snikita   if (flip)
1525*bdda0531Snikita     swapexps(e1, e2);  /* back to original order */
1526*bdda0531Snikita   codebinexpval(fs, opr, e1, e2, line);  /* use standard operators */
1527*bdda0531Snikita }
1528*bdda0531Snikita 
1529*bdda0531Snikita 
1530*bdda0531Snikita /*
1531f0dad708Snikita ** Code arithmetic operators ('+', '-', ...). If second operand is a
1532f0dad708Snikita ** constant in the proper range, use variant opcodes with K operands.
1533f0dad708Snikita */
1534f0dad708Snikita static void codearith (FuncState *fs, BinOpr opr,
1535f0dad708Snikita                        expdesc *e1, expdesc *e2, int flip, int line) {
1536*bdda0531Snikita   if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2))  /* K operand? */
1537*bdda0531Snikita     codebinK(fs, opr, e1, e2, flip, line);
1538*bdda0531Snikita   else  /* 'e2' is neither an immediate nor a K operand */
1539*bdda0531Snikita     codebinNoK(fs, opr, e1, e2, flip, line);
1540f0dad708Snikita }
1541f0dad708Snikita 
1542f0dad708Snikita 
1543f0dad708Snikita /*
1544f0dad708Snikita ** Code commutative operators ('+', '*'). If first operand is a
1545f0dad708Snikita ** numeric constant, change order of operands to try to use an
1546f0dad708Snikita ** immediate or K operator.
1547f0dad708Snikita */
1548f0dad708Snikita static void codecommutative (FuncState *fs, BinOpr op,
1549f0dad708Snikita                              expdesc *e1, expdesc *e2, int line) {
1550f0dad708Snikita   int flip = 0;
1551f0dad708Snikita   if (tonumeral(e1, NULL)) {  /* is first operand a numeric constant? */
1552f0dad708Snikita     swapexps(e1, e2);  /* change order */
1553f0dad708Snikita     flip = 1;
1554f0dad708Snikita   }
1555f0dad708Snikita   if (op == OPR_ADD && isSCint(e2))  /* immediate operand? */
1556*bdda0531Snikita     codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD);
1557f0dad708Snikita   else
1558f0dad708Snikita     codearith(fs, op, e1, e2, flip, line);
1559f0dad708Snikita }
1560f0dad708Snikita 
1561f0dad708Snikita 
1562f0dad708Snikita /*
15638e4bc226Snikita ** Code bitwise operations; they are all commutative, so the function
1564f0dad708Snikita ** tries to put an integer constant as the 2nd operand (a K operand).
1565f0dad708Snikita */
1566f0dad708Snikita static void codebitwise (FuncState *fs, BinOpr opr,
1567f0dad708Snikita                          expdesc *e1, expdesc *e2, int line) {
1568f0dad708Snikita   int flip = 0;
1569*bdda0531Snikita   if (e1->k == VKINT) {
1570f0dad708Snikita     swapexps(e1, e2);  /* 'e2' will be the constant operand */
1571f0dad708Snikita     flip = 1;
1572f0dad708Snikita   }
1573*bdda0531Snikita   if (e2->k == VKINT && luaK_exp2K(fs, e2))  /* K operand? */
1574*bdda0531Snikita     codebinK(fs, opr, e1, e2, flip, line);
1575*bdda0531Snikita   else  /* no constants */
1576*bdda0531Snikita     codebinNoK(fs, opr, e1, e2, flip, line);
1577f0dad708Snikita }
1578f0dad708Snikita 
1579f0dad708Snikita 
1580f0dad708Snikita /*
1581f0dad708Snikita ** Emit code for order comparisons. When using an immediate operand,
1582f0dad708Snikita ** 'isfloat' tells whether the original value was a float.
1583f0dad708Snikita */
1584*bdda0531Snikita static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
1585f0dad708Snikita   int r1, r2;
1586f0dad708Snikita   int im;
1587f0dad708Snikita   int isfloat = 0;
1588*bdda0531Snikita   OpCode op;
1589f0dad708Snikita   if (isSCnumber(e2, &im, &isfloat)) {
1590f0dad708Snikita     /* use immediate operand */
1591f0dad708Snikita     r1 = luaK_exp2anyreg(fs, e1);
1592f0dad708Snikita     r2 = im;
1593*bdda0531Snikita     op = binopr2op(opr, OPR_LT, OP_LTI);
1594f0dad708Snikita   }
1595f0dad708Snikita   else if (isSCnumber(e1, &im, &isfloat)) {
1596f0dad708Snikita     /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */
1597f0dad708Snikita     r1 = luaK_exp2anyreg(fs, e2);
1598f0dad708Snikita     r2 = im;
1599*bdda0531Snikita     op = binopr2op(opr, OPR_LT, OP_GTI);
1600f0dad708Snikita   }
1601f0dad708Snikita   else {  /* regular case, compare two registers */
1602f0dad708Snikita     r1 = luaK_exp2anyreg(fs, e1);
1603f0dad708Snikita     r2 = luaK_exp2anyreg(fs, e2);
1604*bdda0531Snikita     op = binopr2op(opr, OPR_LT, OP_LT);
1605f0dad708Snikita   }
1606c7f896d7Ssalazar   freeexps(fs, e1, e2);
1607f0dad708Snikita   e1->u.info = condjump(fs, op, r1, r2, isfloat, 1);
1608dbec5304Smbalmer   e1->k = VJMP;
1609dbec5304Smbalmer }
1610dbec5304Smbalmer 
1611dbec5304Smbalmer 
1612c7f896d7Ssalazar /*
1613f0dad708Snikita ** Emit code for equality comparisons ('==', '~=').
1614f0dad708Snikita ** 'e1' was already put as RK by 'luaK_infix'.
1615f0dad708Snikita */
1616f0dad708Snikita static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
1617f0dad708Snikita   int r1, r2;
1618f0dad708Snikita   int im;
1619f0dad708Snikita   int isfloat = 0;  /* not needed here, but kept for symmetry */
1620f0dad708Snikita   OpCode op;
1621f0dad708Snikita   if (e1->k != VNONRELOC) {
1622f0dad708Snikita     lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT);
1623f0dad708Snikita     swapexps(e1, e2);
1624f0dad708Snikita   }
1625f0dad708Snikita   r1 = luaK_exp2anyreg(fs, e1);  /* 1st expression must be in register */
1626f0dad708Snikita   if (isSCnumber(e2, &im, &isfloat)) {
1627f0dad708Snikita     op = OP_EQI;
1628f0dad708Snikita     r2 = im;  /* immediate operand */
1629f0dad708Snikita   }
16308e4bc226Snikita   else if (luaK_exp2RK(fs, e2)) {  /* 2nd expression is constant? */
1631f0dad708Snikita     op = OP_EQK;
1632f0dad708Snikita     r2 = e2->u.info;  /* constant index */
1633f0dad708Snikita   }
1634f0dad708Snikita   else {
1635f0dad708Snikita     op = OP_EQ;  /* will compare two registers */
1636f0dad708Snikita     r2 = luaK_exp2anyreg(fs, e2);
1637f0dad708Snikita   }
1638f0dad708Snikita   freeexps(fs, e1, e2);
1639f0dad708Snikita   e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ));
1640f0dad708Snikita   e1->k = VJMP;
1641f0dad708Snikita }
1642f0dad708Snikita 
1643f0dad708Snikita 
1644f0dad708Snikita /*
1645f0dad708Snikita ** Apply prefix operation 'op' to expression 'e'.
1646c7f896d7Ssalazar */
1647*bdda0531Snikita void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) {
16489e2f6347Smbalmer   static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};
1649f0dad708Snikita   luaK_dischargevars(fs, e);
1650*bdda0531Snikita   switch (opr) {
16519e2f6347Smbalmer     case OPR_MINUS: case OPR_BNOT:  /* use 'ef' as fake 2nd operand */
1652*bdda0531Snikita       if (constfolding(fs, opr + LUA_OPUNM, e, &ef))
1653dbec5304Smbalmer         break;
1654f0dad708Snikita       /* else */ /* FALLTHROUGH */
1655c7f896d7Ssalazar     case OPR_LEN:
1656*bdda0531Snikita       codeunexpval(fs, unopr2op(opr), e, line);
1657c7f896d7Ssalazar       break;
1658dbec5304Smbalmer     case OPR_NOT: codenot(fs, e); break;
1659dbec5304Smbalmer     default: lua_assert(0);
1660dbec5304Smbalmer   }
1661dbec5304Smbalmer }
1662dbec5304Smbalmer 
1663dbec5304Smbalmer 
1664c7f896d7Ssalazar /*
1665c7f896d7Ssalazar ** Process 1st operand 'v' of binary operation 'op' before reading
1666c7f896d7Ssalazar ** 2nd operand.
1667c7f896d7Ssalazar */
1668dbec5304Smbalmer void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
1669f0dad708Snikita   luaK_dischargevars(fs, v);
1670dbec5304Smbalmer   switch (op) {
1671dbec5304Smbalmer     case OPR_AND: {
1672c7f896d7Ssalazar       luaK_goiftrue(fs, v);  /* go ahead only if 'v' is true */
1673dbec5304Smbalmer       break;
1674dbec5304Smbalmer     }
1675dbec5304Smbalmer     case OPR_OR: {
1676c7f896d7Ssalazar       luaK_goiffalse(fs, v);  /* go ahead only if 'v' is false */
1677dbec5304Smbalmer       break;
1678dbec5304Smbalmer     }
1679dbec5304Smbalmer     case OPR_CONCAT: {
1680f0dad708Snikita       luaK_exp2nextreg(fs, v);  /* operand must be on the stack */
1681dbec5304Smbalmer       break;
1682dbec5304Smbalmer     }
16834ab4902eSlneto     case OPR_ADD: case OPR_SUB:
16844ab4902eSlneto #ifndef _KERNEL
16854ab4902eSlneto     case OPR_MUL: case OPR_DIV: case OPR_IDIV:
16864ab4902eSlneto     case OPR_MOD: case OPR_POW:
16872d6cb6c2Slneto #else /* _KERNEL */
16884ab4902eSlneto     case OPR_MUL: case OPR_IDIV:
16894ab4902eSlneto     case OPR_MOD:
16902d6cb6c2Slneto #endif /* _KERNEL */
16914ab4902eSlneto     case OPR_BAND: case OPR_BOR: case OPR_BXOR:
16924ab4902eSlneto     case OPR_SHL: case OPR_SHR: {
1693c7f896d7Ssalazar       if (!tonumeral(v, NULL))
1694f0dad708Snikita         luaK_exp2anyreg(fs, v);
16958e4bc226Snikita       /* else keep numeral, which may be folded or used as an immediate
16968e4bc226Snikita          operand */
1697dbec5304Smbalmer       break;
1698dbec5304Smbalmer     }
1699f0dad708Snikita     case OPR_EQ: case OPR_NE: {
1700f0dad708Snikita       if (!tonumeral(v, NULL))
1701dbec5304Smbalmer         luaK_exp2RK(fs, v);
1702f0dad708Snikita       /* else keep numeral, which may be an immediate operand */
1703dbec5304Smbalmer       break;
1704dbec5304Smbalmer     }
1705f0dad708Snikita     case OPR_LT: case OPR_LE:
1706f0dad708Snikita     case OPR_GT: case OPR_GE: {
1707f0dad708Snikita       int dummy, dummy2;
1708f0dad708Snikita       if (!isSCnumber(v, &dummy, &dummy2))
1709f0dad708Snikita         luaK_exp2anyreg(fs, v);
1710f0dad708Snikita       /* else keep numeral, which may be an immediate operand */
1711f0dad708Snikita       break;
1712f0dad708Snikita     }
1713f0dad708Snikita     default: lua_assert(0);
1714f0dad708Snikita   }
1715f0dad708Snikita }
1716f0dad708Snikita 
1717f0dad708Snikita /*
1718f0dad708Snikita ** Create code for '(e1 .. e2)'.
1719f0dad708Snikita ** For '(e1 .. e2.1 .. e2.2)' (which is '(e1 .. (e2.1 .. e2.2))',
1720f0dad708Snikita ** because concatenation is right associative), merge both CONCATs.
1721f0dad708Snikita */
1722f0dad708Snikita static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) {
1723f0dad708Snikita   Instruction *ie2 = previousinstruction(fs);
1724f0dad708Snikita   if (GET_OPCODE(*ie2) == OP_CONCAT) {  /* is 'e2' a concatenation? */
1725f0dad708Snikita     int n = GETARG_B(*ie2);  /* # of elements concatenated in 'e2' */
1726f0dad708Snikita     lua_assert(e1->u.info + 1 == GETARG_A(*ie2));
1727f0dad708Snikita     freeexp(fs, e2);
1728f0dad708Snikita     SETARG_A(*ie2, e1->u.info);  /* correct first element ('e1') */
1729f0dad708Snikita     SETARG_B(*ie2, n + 1);  /* will concatenate one more element */
1730f0dad708Snikita   }
1731f0dad708Snikita   else {  /* 'e2' is not a concatenation */
1732f0dad708Snikita     luaK_codeABC(fs, OP_CONCAT, e1->u.info, 2, 0);  /* new concat opcode */
1733f0dad708Snikita     freeexp(fs, e2);
1734f0dad708Snikita     luaK_fixline(fs, line);
1735dbec5304Smbalmer   }
1736dbec5304Smbalmer }
1737dbec5304Smbalmer 
1738dbec5304Smbalmer 
1739c7f896d7Ssalazar /*
1740c7f896d7Ssalazar ** Finalize code for binary operation, after reading 2nd operand.
1741c7f896d7Ssalazar */
1742f0dad708Snikita void luaK_posfix (FuncState *fs, BinOpr opr,
17434ab4902eSlneto                   expdesc *e1, expdesc *e2, int line) {
1744dbec5304Smbalmer   luaK_dischargevars(fs, e2);
1745f0dad708Snikita   if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2))
1746f0dad708Snikita     return;  /* done by folding */
1747f0dad708Snikita   switch (opr) {
1748f0dad708Snikita     case OPR_AND: {
1749f0dad708Snikita       lua_assert(e1->t == NO_JUMP);  /* list closed by 'luaK_infix' */
1750dbec5304Smbalmer       luaK_concat(fs, &e2->f, e1->f);
1751dbec5304Smbalmer       *e1 = *e2;
1752dbec5304Smbalmer       break;
1753dbec5304Smbalmer     }
1754dbec5304Smbalmer     case OPR_OR: {
1755f0dad708Snikita       lua_assert(e1->f == NO_JUMP);  /* list closed by 'luaK_infix' */
1756dbec5304Smbalmer       luaK_concat(fs, &e2->t, e1->t);
1757dbec5304Smbalmer       *e1 = *e2;
1758dbec5304Smbalmer       break;
1759dbec5304Smbalmer     }
1760f0dad708Snikita     case OPR_CONCAT: {  /* e1 .. e2 */
1761f0dad708Snikita       luaK_exp2nextreg(fs, e2);
1762f0dad708Snikita       codeconcat(fs, e1, e2, line);
1763dbec5304Smbalmer       break;
1764dbec5304Smbalmer     }
1765f0dad708Snikita     case OPR_ADD: case OPR_MUL: {
1766f0dad708Snikita       codecommutative(fs, opr, e1, e2, line);
1767f0dad708Snikita       break;
1768f0dad708Snikita     }
1769f0dad708Snikita     case OPR_SUB: {
1770f0dad708Snikita       if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB))
1771f0dad708Snikita         break; /* coded as (r1 + -I) */
1772f0dad708Snikita       /* ELSE */
1773f0dad708Snikita     }  /* FALLTHROUGH */
17744ab4902eSlneto #ifndef _KERNEL
1775f0dad708Snikita     case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: {
17762d6cb6c2Slneto #else /* _KERNEL */
1777f0dad708Snikita     case OPR_IDIV: case OPR_MOD: {
1778f0dad708Snikita #endif
1779f0dad708Snikita       codearith(fs, opr, e1, e2, 0, line);
17804ab4902eSlneto       break;
17814ab4902eSlneto     }
1782f0dad708Snikita     case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
1783f0dad708Snikita       codebitwise(fs, opr, e1, e2, line);
1784f0dad708Snikita       break;
1785f0dad708Snikita     }
1786f0dad708Snikita     case OPR_SHL: {
1787f0dad708Snikita       if (isSCint(e1)) {
1788f0dad708Snikita         swapexps(e1, e2);
1789f0dad708Snikita         codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL);  /* I << r2 */
1790f0dad708Snikita       }
1791f0dad708Snikita       else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) {
1792f0dad708Snikita         /* coded as (r1 >> -I) */;
1793f0dad708Snikita       }
1794f0dad708Snikita       else  /* regular case (two registers) */
1795*bdda0531Snikita        codebinexpval(fs, opr, e1, e2, line);
1796f0dad708Snikita       break;
1797f0dad708Snikita     }
1798f0dad708Snikita     case OPR_SHR: {
1799f0dad708Snikita       if (isSCint(e2))
1800f0dad708Snikita         codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR);  /* r1 >> I */
1801f0dad708Snikita       else  /* regular case (two registers) */
1802*bdda0531Snikita         codebinexpval(fs, opr, e1, e2, line);
1803f0dad708Snikita       break;
1804f0dad708Snikita     }
1805f0dad708Snikita     case OPR_EQ: case OPR_NE: {
1806f0dad708Snikita       codeeq(fs, opr, e1, e2);
1807f0dad708Snikita       break;
1808f0dad708Snikita     }
1809f0dad708Snikita     case OPR_GT: case OPR_GE: {
1810f0dad708Snikita       /* '(a > b)' <=> '(b < a)';  '(a >= b)' <=> '(b <= a)' */
1811f0dad708Snikita       swapexps(e1, e2);
1812*bdda0531Snikita       opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT);
1813*bdda0531Snikita     }  /* FALLTHROUGH */
1814*bdda0531Snikita     case OPR_LT: case OPR_LE: {
1815*bdda0531Snikita       codeorder(fs, opr, e1, e2);
18164ab4902eSlneto       break;
18174ab4902eSlneto     }
1818dbec5304Smbalmer     default: lua_assert(0);
1819dbec5304Smbalmer   }
1820dbec5304Smbalmer }
1821dbec5304Smbalmer 
1822dbec5304Smbalmer 
1823c7f896d7Ssalazar /*
1824f0dad708Snikita ** Change line information associated with current position, by removing
1825f0dad708Snikita ** previous info and adding it again with new line.
1826c7f896d7Ssalazar */
1827dbec5304Smbalmer void luaK_fixline (FuncState *fs, int line) {
1828f0dad708Snikita   removelastlineinfo(fs);
1829f0dad708Snikita   savelineinfo(fs, fs->f, line);
1830f0dad708Snikita }
1831f0dad708Snikita 
1832f0dad708Snikita 
1833f0dad708Snikita void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) {
1834f0dad708Snikita   Instruction *inst = &fs->f->code[pc];
1835f0dad708Snikita   int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0;  /* hash size */
1836f0dad708Snikita   int extra = asize / (MAXARG_C + 1);  /* higher bits of array size */
1837f0dad708Snikita   int rc = asize % (MAXARG_C + 1);  /* lower bits of array size */
1838f0dad708Snikita   int k = (extra > 0);  /* true iff needs extra argument */
1839f0dad708Snikita   *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k);
1840f0dad708Snikita   *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra);
1841dbec5304Smbalmer }
1842dbec5304Smbalmer 
1843dbec5304Smbalmer 
1844c7f896d7Ssalazar /*
1845c7f896d7Ssalazar ** Emit a SETLIST instruction.
1846c7f896d7Ssalazar ** 'base' is register that keeps table;
1847c7f896d7Ssalazar ** 'nelems' is #table plus those to be stored now;
1848c7f896d7Ssalazar ** 'tostore' is number of values (in registers 'base + 1',...) to add to
1849c7f896d7Ssalazar ** table (or LUA_MULTRET to add up to stack top).
1850c7f896d7Ssalazar */
1851dbec5304Smbalmer void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
1852c7f896d7Ssalazar   lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH);
1853f0dad708Snikita   if (tostore == LUA_MULTRET)
1854f0dad708Snikita     tostore = 0;
1855f0dad708Snikita   if (nelems <= MAXARG_C)
1856f0dad708Snikita     luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems);
1857f0dad708Snikita   else {
1858f0dad708Snikita     int extra = nelems / (MAXARG_C + 1);
1859f0dad708Snikita     nelems %= (MAXARG_C + 1);
1860f0dad708Snikita     luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1);
1861f0dad708Snikita     codeextraarg(fs, extra);
1862dbec5304Smbalmer   }
1863dbec5304Smbalmer   fs->freereg = base + 1;  /* free registers with list values */
1864dbec5304Smbalmer }
1865dbec5304Smbalmer 
1866f0dad708Snikita 
1867f0dad708Snikita /*
1868f0dad708Snikita ** return the final target of a jump (skipping jumps to jumps)
1869f0dad708Snikita */
1870f0dad708Snikita static int finaltarget (Instruction *code, int i) {
1871f0dad708Snikita   int count;
1872f0dad708Snikita   for (count = 0; count < 100; count++) {  /* avoid infinite loops */
1873f0dad708Snikita     Instruction pc = code[i];
1874f0dad708Snikita     if (GET_OPCODE(pc) != OP_JMP)
1875f0dad708Snikita       break;
1876f0dad708Snikita      else
1877f0dad708Snikita        i += GETARG_sJ(pc) + 1;
1878f0dad708Snikita   }
1879f0dad708Snikita   return i;
1880f0dad708Snikita }
1881f0dad708Snikita 
1882f0dad708Snikita 
1883f0dad708Snikita /*
1884f0dad708Snikita ** Do a final pass over the code of a function, doing small peephole
1885f0dad708Snikita ** optimizations and adjustments.
1886f0dad708Snikita */
1887f0dad708Snikita void luaK_finish (FuncState *fs) {
1888f0dad708Snikita   int i;
1889f0dad708Snikita   Proto *p = fs->f;
1890f0dad708Snikita   for (i = 0; i < fs->pc; i++) {
1891f0dad708Snikita     Instruction *pc = &p->code[i];
1892f0dad708Snikita     lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
1893f0dad708Snikita     switch (GET_OPCODE(*pc)) {
1894f0dad708Snikita       case OP_RETURN0: case OP_RETURN1: {
1895f0dad708Snikita         if (!(fs->needclose || p->is_vararg))
1896f0dad708Snikita           break;  /* no extra work */
1897f0dad708Snikita         /* else use OP_RETURN to do the extra work */
1898f0dad708Snikita         SET_OPCODE(*pc, OP_RETURN);
1899f0dad708Snikita       }  /* FALLTHROUGH */
1900f0dad708Snikita       case OP_RETURN: case OP_TAILCALL: {
1901f0dad708Snikita         if (fs->needclose)
1902f0dad708Snikita           SETARG_k(*pc, 1);  /* signal that it needs to close */
1903f0dad708Snikita         if (p->is_vararg)
1904f0dad708Snikita           SETARG_C(*pc, p->numparams + 1);  /* signal that it is vararg */
1905f0dad708Snikita         break;
1906f0dad708Snikita       }
1907f0dad708Snikita       case OP_JMP: {
1908f0dad708Snikita         int target = finaltarget(p->code, i);
1909f0dad708Snikita         fixjump(fs, i, target);
1910f0dad708Snikita         break;
1911f0dad708Snikita       }
1912f0dad708Snikita       default: break;
1913f0dad708Snikita     }
1914f0dad708Snikita   }
1915f0dad708Snikita }
1916