1 /*
2 ** $Id: lcode.c,v 1.2 2002/04/02 23:17:42 sfuerst Exp $
3 ** Code generator for Lua
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include "stdlib.h"
9 
10 #include "lua.h"
11 
12 #include "lcode.h"
13 #include "ldo.h"
14 #include "llex.h"
15 #include "lmem.h"
16 #include "lobject.h"
17 #include "lopcodes.h"
18 #include "lparser.h"
19 
20 
luaK_error(LexState * ls,const char * msg)21 void luaK_error (LexState *ls, const char *msg) {
22   luaX_error(ls, msg, ls->t.token);
23 }
24 
25 
26 /*
27 ** Returns the the previous instruction, for optimizations.
28 ** If there is a jump target between this and the current instruction,
29 ** returns a dummy instruction to avoid wrong optimizations.
30 */
previous_instruction(FuncState * fs)31 static Instruction previous_instruction (FuncState *fs) {
32   if (fs->pc > fs->lasttarget)  /* no jumps to current position? */
33     return fs->f->code[fs->pc-1];  /* returns previous instruction */
34   else
35     return CREATE_0(OP_END);  /* no optimizations after an `END' */
36 }
37 
38 
luaK_jump(FuncState * fs)39 int luaK_jump (FuncState *fs) {
40   int j = luaK_code1(fs, OP_JMP, NO_JUMP);
41   if (j == fs->lasttarget) {  /* possible jumps to this jump? */
42     luaK_concat(fs, &j, fs->jlt);  /* keep them on hold */
43     fs->jlt = NO_JUMP;
44   }
45   return j;
46 }
47 
48 
luaK_fixjump(FuncState * fs,int pc,int dest)49 static void luaK_fixjump (FuncState *fs, int pc, int dest) {
50   Instruction *jmp = &fs->f->code[pc];
51   if (dest == NO_JUMP)
52     SETARG_S(*jmp, NO_JUMP);  /* point to itself to represent end of list */
53   else {  /* jump is relative to position following jump instruction */
54     int offset = dest-(pc+1);
55     if (abs(offset) > MAXARG_S)
56       luaK_error(fs->ls, "control structure too long");
57     SETARG_S(*jmp, offset);
58   }
59 }
60 
61 
luaK_getjump(FuncState * fs,int pc)62 static int luaK_getjump (FuncState *fs, int pc) {
63   int offset = GETARG_S(fs->f->code[pc]);
64   if (offset == NO_JUMP)  /* point to itself represents end of list */
65     return NO_JUMP;  /* end of list */
66   else
67     return (pc+1)+offset;  /* turn offset into absolute position */
68 }
69 
70 
71 /*
72 ** returns current `pc' and marks it as a jump target (to avoid wrong
73 ** optimizations with consecutive instructions not in the same basic block).
74 ** discharge list of jumps to last target.
75 */
luaK_getlabel(FuncState * fs)76 int luaK_getlabel (FuncState *fs) {
77   if (fs->pc != fs->lasttarget) {
78     int lasttarget = fs->lasttarget;
79     fs->lasttarget = fs->pc;
80     luaK_patchlist(fs, fs->jlt, lasttarget);  /* discharge old list `jlt' */
81     fs->jlt = NO_JUMP;  /* nobody jumps to this new label (yet) */
82   }
83   return fs->pc;
84 }
85 
86 
luaK_deltastack(FuncState * fs,int delta)87 void luaK_deltastack (FuncState *fs, int delta) {
88   fs->stacklevel += delta;
89   if (fs->stacklevel > fs->f->maxstacksize) {
90     if (fs->stacklevel > MAXSTACK)
91       luaK_error(fs->ls, "function or expression too complex");
92     fs->f->maxstacksize = fs->stacklevel;
93   }
94 }
95 
96 
luaK_kstr(LexState * ls,int c)97 void luaK_kstr (LexState *ls, int c) {
98   luaK_code1(ls->fs, OP_PUSHSTRING, c);
99 }
100 
101 
number_constant(FuncState * fs,Number r)102 static int number_constant (FuncState *fs, Number r) {
103   /* check whether `r' has appeared within the last LOOKBACKNUMS entries */
104   Proto *f = fs->f;
105   int c = f->nknum;
106   int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS;
107   while (--c >= lim)
108     if (f->knum[c] == r) return c;
109   /* not found; create a new entry */
110   luaM_growvector(fs->L, f->knum, f->nknum, 1, Number,
111                   "constant table overflow", MAXARG_U);
112   c = f->nknum++;
113   f->knum[c] = r;
114   return c;
115 }
116 
117 
luaK_number(FuncState * fs,Number f)118 void luaK_number (FuncState *fs, Number f) {
119   if (f <= (Number)MAXARG_S && (Number)(int)f == f)
120     luaK_code1(fs, OP_PUSHINT, (int)f);  /* f has a short integer value */
121   else
122     luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f));
123 }
124 
125 
luaK_adjuststack(FuncState * fs,int n)126 void luaK_adjuststack (FuncState *fs, int n) {
127   if (n > 0)
128     luaK_code1(fs, OP_POP, n);
129   else
130     luaK_code1(fs, OP_PUSHNIL, -n);
131 }
132 
133 
luaK_lastisopen(FuncState * fs)134 int luaK_lastisopen (FuncState *fs) {
135   /* check whether last instruction is an open function call */
136   Instruction i = previous_instruction(fs);
137   if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET)
138     return 1;
139   else return 0;
140 }
141 
142 
luaK_setcallreturns(FuncState * fs,int nresults)143 void luaK_setcallreturns (FuncState *fs, int nresults) {
144   if (luaK_lastisopen(fs)) {  /* expression is an open function call? */
145     SETARG_B(fs->f->code[fs->pc-1], nresults);  /* set number of results */
146     luaK_deltastack(fs, nresults);  /* push results */
147   }
148 }
149 
150 
discharge(FuncState * fs,expdesc * var)151 static int discharge (FuncState *fs, expdesc *var) {
152   switch (var->k) {
153     case VLOCAL:
154       luaK_code1(fs, OP_GETLOCAL, var->u.index);
155       break;
156     case VGLOBAL:
157       luaK_code1(fs, OP_GETGLOBAL, var->u.index);
158       break;
159     case VINDEXED:
160       luaK_code0(fs, OP_GETTABLE);
161       break;
162     case VEXP:
163       return 0;  /* nothing to do */
164   }
165   var->k = VEXP;
166   var->u.l.t = var->u.l.f = NO_JUMP;
167   return 1;
168 }
169 
170 
discharge1(FuncState * fs,expdesc * var)171 static void discharge1 (FuncState *fs, expdesc *var) {
172   discharge(fs, var);
173  /* if it has jumps then it is already discharged */
174   if (var->u.l.t == NO_JUMP && var->u.l.f  == NO_JUMP)
175     luaK_setcallreturns(fs, 1);  /* call must return 1 value */
176 }
177 
178 
luaK_storevar(LexState * ls,const expdesc * var)179 void luaK_storevar (LexState *ls, const expdesc *var) {
180   FuncState *fs = ls->fs;
181   switch (var->k) {
182     case VLOCAL:
183       luaK_code1(fs, OP_SETLOCAL, var->u.index);
184       break;
185     case VGLOBAL:
186       luaK_code1(fs, OP_SETGLOBAL, var->u.index);
187       break;
188     case VINDEXED:  /* table is at top-3; pop 3 elements after operation */
189       luaK_code2(fs, OP_SETTABLE, 3, 3);
190       break;
191     default:
192       LUA_INTERNALERROR("invalid var kind to store");
193   }
194 }
195 
196 
invertjump(OpCode op)197 static OpCode invertjump (OpCode op) {
198   switch (op) {
199     case OP_JMPNE: return OP_JMPEQ;
200     case OP_JMPEQ: return OP_JMPNE;
201     case OP_JMPLT: return OP_JMPGE;
202     case OP_JMPLE: return OP_JMPGT;
203     case OP_JMPGT: return OP_JMPLE;
204     case OP_JMPGE: return OP_JMPLT;
205     case OP_JMPT: case OP_JMPONT:  return OP_JMPF;
206     case OP_JMPF: case OP_JMPONF:  return OP_JMPT;
207     default:
208       LUA_INTERNALERROR("invalid jump instruction");
209       return OP_END;  /* to avoid warnings */
210   }
211 }
212 
213 
luaK_patchlistaux(FuncState * fs,int list,int target,OpCode special,int special_target)214 static void luaK_patchlistaux (FuncState *fs, int list, int target,
215                                OpCode special, int special_target) {
216   Instruction *code = fs->f->code;
217   while (list != NO_JUMP) {
218     int next = luaK_getjump(fs, list);
219     Instruction *i = &code[list];
220     OpCode op = GET_OPCODE(*i);
221     if (op == special)  /* this `op' already has a value */
222       luaK_fixjump(fs, list, special_target);
223     else {
224       luaK_fixjump(fs, list, target);  /* do the patch */
225       if (op == OP_JMPONT)  /* remove eventual values */
226         SET_OPCODE(*i, OP_JMPT);
227       else if (op == OP_JMPONF)
228         SET_OPCODE(*i, OP_JMPF);
229     }
230     list = next;
231   }
232 }
233 
234 
luaK_patchlist(FuncState * fs,int list,int target)235 void luaK_patchlist (FuncState *fs, int list, int target) {
236   if (target == fs->lasttarget)  /* same target that list `jlt'? */
237     luaK_concat(fs, &fs->jlt, list);  /* delay fixing */
238   else
239     luaK_patchlistaux(fs, list, target, OP_END, 0);
240 }
241 
242 
need_value(FuncState * fs,int list,OpCode hasvalue)243 static int need_value (FuncState *fs, int list, OpCode hasvalue) {
244   /* check whether list has a jump without a value */
245   for (; list != NO_JUMP; list = luaK_getjump(fs, list))
246     if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1;
247   return 0;  /* not found */
248 }
249 
250 
luaK_concat(FuncState * fs,int * l1,int l2)251 void luaK_concat (FuncState *fs, int *l1, int l2) {
252   if (*l1 == NO_JUMP)
253     *l1 = l2;
254   else {
255     int list = *l1;
256     for (;;) {  /* traverse `l1' */
257       int next = luaK_getjump(fs, list);
258       if (next == NO_JUMP) {  /* end of list? */
259         luaK_fixjump(fs, list, l2);
260         return;
261       }
262       list = next;
263     }
264   }
265 }
266 
267 
luaK_testgo(FuncState * fs,expdesc * v,int invert,OpCode jump)268 static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) {
269   int prevpos;  /* position of last instruction */
270   Instruction *previous;
271   int *golist, *exitlist;
272   if (!invert) {
273     golist = &v->u.l.f;    /* go if false */
274     exitlist = &v->u.l.t;  /* exit if true */
275   }
276   else {
277     golist = &v->u.l.t;    /* go if true */
278     exitlist = &v->u.l.f;  /* exit if false */
279   }
280   discharge1(fs, v);
281   prevpos = fs->pc-1;
282   previous = &fs->f->code[prevpos];
283   LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here");
284   if (!ISJUMP(GET_OPCODE(*previous)))
285     prevpos = luaK_code1(fs, jump, NO_JUMP);
286   else {  /* last instruction is already a jump */
287     if (invert)
288       SET_OPCODE(*previous, (OpCode)invertjump(GET_OPCODE(*previous)));
289   }
290   luaK_concat(fs, exitlist, prevpos);  /* insert last jump in `exitlist' */
291   luaK_patchlist(fs, *golist, luaK_getlabel(fs));
292   *golist = NO_JUMP;
293 }
294 
295 
luaK_goiftrue(FuncState * fs,expdesc * v,int keepvalue)296 void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) {
297   luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF);
298 }
299 
300 
luaK_goiffalse(FuncState * fs,expdesc * v,int keepvalue)301 static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) {
302   luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT);
303 }
304 
305 
code_label(FuncState * fs,OpCode op,int arg)306 static int code_label (FuncState *fs, OpCode op, int arg) {
307   luaK_getlabel(fs);  /* those instructions may be jump targets */
308   return luaK_code1(fs, op, arg);
309 }
310 
311 
luaK_tostack(LexState * ls,expdesc * v,int onlyone)312 void luaK_tostack (LexState *ls, expdesc *v, int onlyone) {
313   FuncState *fs = ls->fs;
314   if (!discharge(fs, v)) {  /* `v' is an expression? */
315     OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]);
316     if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) {
317       /* expression has no jumps */
318       if (onlyone)
319         luaK_setcallreturns(fs, 1);  /* call must return 1 value */
320     }
321     else {  /* expression has jumps */
322       int final;  /* position after whole expression */
323       int j = NO_JUMP;  /*  eventual  jump over values */
324       int p_nil = NO_JUMP;  /* position of an eventual PUSHNIL */
325       int p_1 = NO_JUMP;  /* position of an eventual PUSHINT */
326       if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF)
327                            || need_value(fs, v->u.l.t, OP_JMPONT)) {
328         /* expression needs values */
329         if (ISJUMP(previous))
330           luaK_concat(fs, &v->u.l.t, fs->pc-1);  /* put `previous' in t. list */
331         else {
332           j = code_label(fs, OP_JMP, NO_JUMP);  /* to jump over both pushes */
333           /* correct stack for compiler and symbolic execution */
334           luaK_adjuststack(fs, 1);
335         }
336         p_nil = code_label(fs, OP_PUSHNILJMP, 0);
337         p_1 = code_label(fs, OP_PUSHINT, 1);
338         luaK_patchlist(fs, j, luaK_getlabel(fs));
339       }
340       final = luaK_getlabel(fs);
341       luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final);
342       luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final);
343       v->u.l.f = v->u.l.t = NO_JUMP;
344     }
345   }
346 }
347 
348 
luaK_prefix(LexState * ls,UnOpr op,expdesc * v)349 void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) {
350   FuncState *fs = ls->fs;
351   if (op == OPR_MINUS) {
352     luaK_tostack(ls, v, 1);
353     luaK_code0(fs, OP_MINUS);
354   }
355   else {  /* op == NOT */
356     Instruction *previous;
357     discharge1(fs, v);
358     previous = &fs->f->code[fs->pc-1];
359     if (ISJUMP(GET_OPCODE(*previous)))
360       SET_OPCODE(*previous, (OpCode)invertjump(GET_OPCODE(*previous)));
361     else
362       luaK_code0(fs, OP_NOT);
363     /* interchange true and false lists */
364     { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; }
365   }
366 }
367 
368 
luaK_infix(LexState * ls,BinOpr op,expdesc * v)369 void luaK_infix (LexState *ls, BinOpr op, expdesc *v) {
370   FuncState *fs = ls->fs;
371   switch (op) {
372     case OPR_AND:
373       luaK_goiftrue(fs, v, 1);
374       break;
375     case OPR_OR:
376       luaK_goiffalse(fs, v, 1);
377       break;
378     default:
379       luaK_tostack(ls, v, 1);  /* all other binary operators need a value */
380   }
381 }
382 
383 
384 
385 static const struct {
386   OpCode opcode;  /* opcode for each binary operator */
387   int arg;        /* default argument for the opcode */
388 } codes[] = {  /* ORDER OPR */
389       {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0},
390       {OP_POW, 0}, {OP_CONCAT, 2},
391       {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP},
392       {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP},
393       {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP}
394 };
395 
396 
luaK_posfix(LexState * ls,BinOpr op,expdesc * v1,expdesc * v2)397 void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) {
398   FuncState *fs = ls->fs;
399   switch (op) {
400     case OPR_AND: {
401       LUA_ASSERT(v1->u.l.t == NO_JUMP, "list must be closed");
402       discharge1(fs, v2);
403       v1->u.l.t = v2->u.l.t;
404       luaK_concat(fs, &v1->u.l.f, v2->u.l.f);
405       break;
406     }
407     case OPR_OR: {
408       LUA_ASSERT(v1->u.l.f == NO_JUMP, "list must be closed");
409       discharge1(fs, v2);
410       v1->u.l.f = v2->u.l.f;
411       luaK_concat(fs, &v1->u.l.t, v2->u.l.t);
412       break;
413     }
414     default: {
415       luaK_tostack(ls, v2, 1);  /* `v2' must be a value */
416       luaK_code1(fs, codes[op].opcode, codes[op].arg);
417     }
418   }
419 }
420 
421 
codelineinfo(FuncState * fs)422 static void codelineinfo (FuncState *fs) {
423   Proto *f = fs->f;
424   LexState *ls = fs->ls;
425   if (ls->lastline > fs->lastline) {
426     luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int,
427                     "line info overflow", MAX_INT);
428     if (ls->lastline > fs->lastline+1)
429       f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1));
430     f->lineinfo[f->nlineinfo++] = fs->pc;
431     fs->lastline = ls->lastline;
432   }
433 }
434 
435 
luaK_code0(FuncState * fs,OpCode o)436 int luaK_code0 (FuncState *fs, OpCode o) {
437   return luaK_code2(fs, o, 0, 0);
438 }
439 
440 
luaK_code1(FuncState * fs,OpCode o,int arg1)441 int luaK_code1 (FuncState *fs, OpCode o, int arg1) {
442   return luaK_code2(fs, o, arg1, 0);
443 }
444 
445 
luaK_code2(FuncState * fs,OpCode o,int arg1,int arg2)446 int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
447   Instruction i = previous_instruction(fs);
448   int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop;
449   int optm = 0;  /* 1 when there is an optimization */
450   switch (o) {
451     case OP_CLOSURE: {
452       delta = -arg2+1;
453       break;
454     }
455     case OP_SETTABLE: {
456       delta = -arg2;
457       break;
458     }
459     case OP_SETLIST: {
460       if (arg2 == 0) return NO_JUMP;  /* nothing to do */
461       delta = -arg2;
462       break;
463     }
464     case OP_SETMAP: {
465       if (arg1 == 0) return NO_JUMP;  /* nothing to do */
466       delta = -2*arg1;
467       break;
468     }
469     case OP_RETURN: {
470       if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) {
471         SET_OPCODE(i, OP_TAILCALL);
472         SETARG_B(i, arg1);
473         optm = 1;
474       }
475       break;
476     }
477     case OP_PUSHNIL: {
478       if (arg1 == 0) return NO_JUMP;  /* nothing to do */
479       delta = arg1;
480       switch(GET_OPCODE(i)) {
481         case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break;
482         default: break;
483       }
484       break;
485     }
486     case OP_POP: {
487       if (arg1 == 0) return NO_JUMP;  /* nothing to do */
488       delta = -arg1;
489       switch(GET_OPCODE(i)) {
490         case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break;
491         default: break;
492       }
493       break;
494     }
495     case OP_GETTABLE: {
496       switch(GET_OPCODE(i)) {
497         case OP_PUSHSTRING:  /* `t.x' */
498           SET_OPCODE(i, OP_GETDOTTED);
499           optm = 1;
500           break;
501         case OP_GETLOCAL:  /* `t[i]' */
502           SET_OPCODE(i, OP_GETINDEXED);
503           optm = 1;
504           break;
505         default: break;
506       }
507       break;
508     }
509     case OP_ADD: {
510       switch(GET_OPCODE(i)) {
511         case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break;  /* `a+k' */
512         default: break;
513       }
514       break;
515     }
516     case OP_SUB: {
517       switch(GET_OPCODE(i)) {
518         case OP_PUSHINT:  /* `a-k' */
519           i = CREATE_S(OP_ADDI, -GETARG_S(i));
520           optm = 1;
521           break;
522         default: break;
523       }
524       break;
525     }
526     case OP_CONCAT: {
527       delta = -arg1+1;
528       switch(GET_OPCODE(i)) {
529         case OP_CONCAT:  /* `a..b..c' */
530           SETARG_U(i, GETARG_U(i)+1);
531           optm = 1;
532           break;
533         default: break;
534       }
535       break;
536     }
537     case OP_MINUS: {
538       switch(GET_OPCODE(i)) {
539         case OP_PUSHINT:  /* `-k' */
540           SETARG_S(i, -GETARG_S(i));
541           optm = 1;
542           break;
543         case OP_PUSHNUM:  /* `-k' */
544           SET_OPCODE(i, OP_PUSHNEGNUM);
545           optm = 1;
546           break;
547         default: break;
548       }
549       break;
550     }
551     case OP_JMPNE: {
552       if (i == CREATE_U(OP_PUSHNIL, 1)) {  /* `a~=nil' */
553         i = CREATE_S(OP_JMPT, NO_JUMP);
554         optm = 1;
555       }
556       break;
557     }
558     case OP_JMPEQ: {
559       if (i == CREATE_U(OP_PUSHNIL, 1)) {  /* `a==nil' */
560         i = CREATE_0(OP_NOT);
561         delta = -1;  /* just undo effect of previous PUSHNIL */
562         optm = 1;
563       }
564       break;
565     }
566     case OP_JMPT:
567     case OP_JMPONT: {
568       switch (GET_OPCODE(i)) {
569         case OP_NOT: {
570           i = CREATE_S(OP_JMPF, NO_JUMP);
571           optm = 1;
572           break;
573         }
574         case OP_PUSHINT: {
575           if (o == OP_JMPT) {  /* JMPONT must keep original integer value */
576             i = CREATE_S(OP_JMP, NO_JUMP);
577             optm = 1;
578           }
579           break;
580         }
581         case OP_PUSHNIL: {
582           if (GETARG_U(i) == 1) {
583             fs->pc--;  /* erase previous instruction */
584             luaK_deltastack(fs, -1);  /* correct stack */
585             return NO_JUMP;
586           }
587           break;
588         }
589         default: break;
590       }
591       break;
592     }
593     case OP_JMPF:
594     case OP_JMPONF: {
595       switch (GET_OPCODE(i)) {
596         case OP_NOT: {
597           i = CREATE_S(OP_JMPT, NO_JUMP);
598           optm = 1;
599           break;
600         }
601         case OP_PUSHINT: {  /* `while 1 do ...' */
602           fs->pc--;  /* erase previous instruction */
603           luaK_deltastack(fs, -1);  /* correct stack */
604           return NO_JUMP;
605         }
606         case OP_PUSHNIL: {  /* `repeat ... until nil' */
607           if (GETARG_U(i) == 1) {
608             i = CREATE_S(OP_JMP, NO_JUMP);
609             optm = 1;
610           }
611           break;
612         }
613         default: break;
614       }
615       break;
616     }
617     case OP_GETDOTTED:
618     case OP_GETINDEXED:
619     case OP_TAILCALL:
620     case OP_ADDI: {
621       LUA_INTERNALERROR("instruction used only for optimizations");
622       break;
623     }
624     default: {
625       LUA_ASSERT(delta != VD, "invalid delta");
626       break;
627     }
628   }
629   luaK_deltastack(fs, delta);
630   if (optm) {  /* optimize: put instruction in place of last one */
631       fs->f->code[fs->pc-1] = i;  /* change previous instruction */
632       return fs->pc-1;  /* do not generate new instruction */
633   }
634   /* else build new instruction */
635   switch ((enum Mode)luaK_opproperties[o].mode) {
636     case iO: i = CREATE_0(o); break;
637     case iU: i = CREATE_U(o, arg1); break;
638     case iS: i = CREATE_S(o, arg1); break;
639     case iAB: i = CREATE_AB(o, arg1, arg2); break;
640   }
641   codelineinfo(fs);
642   /* put new instruction in code array */
643   luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction,
644                   "code size overflow", MAX_INT);
645   fs->f->code[fs->pc] = i;
646   return fs->pc++;
647 }
648 
649 
650 const struct OpProperties luaK_opproperties[NUM_OPCODES] = {
651   {iO, 0, 0},	/* OP_END */
652   {iU, 0, 0},	/* OP_RETURN */
653   {iAB, 0, 0},	/* OP_CALL */
654   {iAB, 0, 0},	/* OP_TAILCALL */
655   {iU, VD, 0},	/* OP_PUSHNIL */
656   {iU, VD, 0},	/* OP_POP */
657   {iS, 1, 0},	/* OP_PUSHINT */
658   {iU, 1, 0},	/* OP_PUSHSTRING */
659   {iU, 1, 0},	/* OP_PUSHNUM */
660   {iU, 1, 0},	/* OP_PUSHNEGNUM */
661   {iU, 1, 0},	/* OP_PUSHUPVALUE */
662   {iU, 1, 0},	/* OP_GETLOCAL */
663   {iU, 1, 0},	/* OP_GETGLOBAL */
664   {iO, 1, 2},	/* OP_GETTABLE */
665   {iU, 1, 1},	/* OP_GETDOTTED */
666   {iU, 1, 1},	/* OP_GETINDEXED */
667   {iU, 2, 1},	/* OP_PUSHSELF */
668   {iU, 1, 0},	/* OP_CREATETABLE */
669   {iU, 0, 1},	/* OP_SETLOCAL */
670   {iU, 0, 1},	/* OP_SETGLOBAL */
671   {iAB, VD, 0},	/* OP_SETTABLE */
672   {iAB, VD, 0},	/* OP_SETLIST */
673   {iU, VD, 0},	/* OP_SETMAP */
674   {iO, 1, 2},	/* OP_ADD */
675   {iS, 1, 1},	/* OP_ADDI */
676   {iO, 1, 2},	/* OP_SUB */
677   {iO, 1, 2},	/* OP_MULT */
678   {iO, 1, 2},	/* OP_DIV */
679   {iO, 1, 2},	/* OP_POW */
680   {iU, VD, 0},	/* OP_CONCAT */
681   {iO, 1, 1},	/* OP_MINUS */
682   {iO, 1, 1},	/* OP_NOT */
683   {iS, 0, 2},	/* OP_JMPNE */
684   {iS, 0, 2},	/* OP_JMPEQ */
685   {iS, 0, 2},	/* OP_JMPLT */
686   {iS, 0, 2},	/* OP_JMPLE */
687   {iS, 0, 2},	/* OP_JMPGT */
688   {iS, 0, 2},	/* OP_JMPGE */
689   {iS, 0, 1},	/* OP_JMPT */
690   {iS, 0, 1},	/* OP_JMPF */
691   {iS, 0, 1},	/* OP_JMPONT */
692   {iS, 0, 1},	/* OP_JMPONF */
693   {iS, 0, 0},	/* OP_JMP */
694   {iO, 0, 0},	/* OP_PUSHNILJMP */
695   {iS, 0, 0},	/* OP_FORPREP */
696   {iS, 0, 3},	/* OP_FORLOOP */
697   {iS, 2, 0},	/* OP_LFORPREP */
698   {iS, 0, 3},	/* OP_LFORLOOP */
699   {iAB, VD, 0}	/* OP_CLOSURE */
700 };
701 
702