Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / ktap / userspace / code.c
1 /*
2  * code.c - Code generator for ktap
3  *
4  * This file is part of ktap by Jovi Zhangwei.
5  *
6  * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
7  *
8  * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
9  *  - The part of code in this file is copied from lua initially.
10  *  - lua's MIT license is compatible with GPL.
11  *
12  * ktap is free software; you can redistribute it and/or modify it
13  * under the terms and conditions of the GNU General Public License,
14  * version 2, as published by the Free Software Foundation.
15  *
16  * ktap is distributed in the hope it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19  * more details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "../include/ktap_types.h"
31 #include "../include/ktap_opcodes.h"
32 #include "ktapc.h"
33 #include "../runtime/kp_obj.h"
34
35
36 #define hasjumps(e)     ((e)->t != (e)->f)
37
38 void codegen_patchtohere (ktap_funcstate *fs, int list);
39
40 static int isnumeral(ktap_expdesc *e)
41 {
42         return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
43 }
44
45 void codegen_nil(ktap_funcstate *fs, int from, int n)
46 {
47         ktap_instruction *previous;
48         int l = from + n - 1;  /* last register to set nil */
49
50         if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
51                 previous = &fs->f->code[fs->pc-1];
52                 if (GET_OPCODE(*previous) == OP_LOADNIL) {
53                         int pfrom = GETARG_A(*previous);
54                         int pl = pfrom + GETARG_B(*previous);
55
56                         if ((pfrom <= from && from <= pl + 1) ||
57                                 (from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
58                                 if (pfrom < from)
59                                         from = pfrom;  /* from = min(from, pfrom) */
60                                 if (pl > l)
61                                         l = pl;  /* l = max(l, pl) */
62                                 SETARG_A(*previous, from);
63                                 SETARG_B(*previous, l - from);
64                                 return;
65                         }
66                 }  /* else go through */
67         }
68         codegen_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
69 }
70
71 int codegen_jump(ktap_funcstate *fs)
72 {
73         int jpc = fs->jpc;  /* save list of jumps to here */
74         int j;
75
76         fs->jpc = NO_JUMP;
77         j = codegen_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
78         codegen_concat(fs, &j, jpc);  /* keep them on hold */
79         return j;
80 }
81
82 void codegen_ret(ktap_funcstate *fs, int first, int nret)
83 {
84         codegen_codeABC(fs, OP_RETURN, first, nret+1, 0);
85 }
86
87 static int condjump(ktap_funcstate *fs, OpCode op, int A, int B, int C)
88 {
89         codegen_codeABC(fs, op, A, B, C);
90         return codegen_jump(fs);
91 }
92
93 static void fixjump(ktap_funcstate *fs, int pc, int dest)
94 {
95         ktap_instruction *jmp = &fs->f->code[pc];
96         int offset = dest-(pc+1);
97
98         ktap_assert(dest != NO_JUMP);
99         if (abs(offset) > MAXARG_sBx)
100                 lex_syntaxerror(fs->ls, "control structure too long");
101         SETARG_sBx(*jmp, offset);
102 }
103
104 /*
105  * returns current `pc' and marks it as a jump target (to avoid wrong
106  * optimizations with consecutive instructions not in the same basic block).
107  */
108 int codegen_getlabel(ktap_funcstate *fs)
109 {
110         fs->lasttarget = fs->pc;
111         return fs->pc;
112 }
113
114 static int getjump(ktap_funcstate *fs, int pc)
115 {
116         int offset = GETARG_sBx(fs->f->code[pc]);
117
118         if (offset == NO_JUMP)  /* point to itself represents end of list */
119                 return NO_JUMP;  /* end of list */
120         else
121                 return (pc+1)+offset;  /* turn offset into absolute position */
122 }
123
124 static ktap_instruction *getjumpcontrol(ktap_funcstate *fs, int pc)
125 {
126         ktap_instruction *pi = &fs->f->code[pc];
127         if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
128                 return pi-1;
129         else
130                 return pi;
131 }
132
133 /*
134  * check whether list has any jump that do not produce a value
135  * (or produce an inverted value)
136  */
137 static int need_value(ktap_funcstate *fs, int list)
138 {
139         for (; list != NO_JUMP; list = getjump(fs, list)) {
140                 ktap_instruction i = *getjumpcontrol(fs, list);
141                 if (GET_OPCODE(i) != OP_TESTSET)
142                         return 1;
143         }
144         return 0;  /* not found */
145 }
146
147 static int patchtestreg(ktap_funcstate *fs, int node, int reg)
148 {
149         ktap_instruction *i = getjumpcontrol(fs, node);
150         if (GET_OPCODE(*i) != OP_TESTSET)
151                 return 0;  /* cannot patch other instructions */
152         if (reg != NO_REG && reg != GETARG_B(*i))
153                 SETARG_A(*i, reg);
154         else  /* no register to put value or register already has the value */
155                 *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
156
157         return 1;
158 }
159
160 static void removevalues(ktap_funcstate *fs, int list)
161 {
162         for (; list != NO_JUMP; list = getjump(fs, list))
163                 patchtestreg(fs, list, NO_REG);
164 }
165
166 static void patchlistaux(ktap_funcstate *fs, int list, int vtarget, int reg,
167                          int dtarget)
168 {
169         while (list != NO_JUMP) {
170                 int next = getjump(fs, list);
171                 if (patchtestreg(fs, list, reg))
172                         fixjump(fs, list, vtarget);
173                 else
174                         fixjump(fs, list, dtarget);  /* jump to default target */
175                 list = next;
176         }
177 }
178
179 static void dischargejpc(ktap_funcstate *fs)
180 {
181         patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
182         fs->jpc = NO_JUMP;
183 }
184
185 void codegen_patchlist(ktap_funcstate *fs, int list, int target)
186 {
187         if (target == fs->pc)
188                 codegen_patchtohere(fs, list);
189         else {
190                 ktap_assert(target < fs->pc);
191                 patchlistaux(fs, list, target, NO_REG, target);
192         }
193 }
194
195 void codegen_patchclose(ktap_funcstate *fs, int list, int level)
196 {
197         level++;  /* argument is +1 to reserve 0 as non-op */
198         while (list != NO_JUMP) {
199                 int next = getjump(fs, list);
200                 ktap_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
201                            (GETARG_A(fs->f->code[list]) == 0 ||
202                             GETARG_A(fs->f->code[list]) >= level));
203                 SETARG_A(fs->f->code[list], level);
204                 list = next;
205         }
206 }
207
208 void codegen_patchtohere(ktap_funcstate *fs, int list)
209 {
210         codegen_getlabel(fs);
211         codegen_concat(fs, &fs->jpc, list);
212 }
213
214 void codegen_concat(ktap_funcstate *fs, int *l1, int l2)
215 {
216         if (l2 == NO_JUMP)
217                 return;
218         else if (*l1 == NO_JUMP)
219                 *l1 = l2;
220         else {
221                 int list = *l1;
222                 int next;
223                 while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
224                         list = next;
225                 fixjump(fs, list, l2);
226         }
227 }
228
229 static int codegen_code(ktap_funcstate *fs, ktap_instruction i)
230 {
231         ktap_proto *f = fs->f;
232
233         dischargejpc(fs);  /* `pc' will change */
234
235         /* put new instruction in code array */
236         ktapc_growvector(f->code, fs->pc, f->sizecode, ktap_instruction,
237                          MAX_INT, "opcodes");
238         f->code[fs->pc] = i;
239
240         /* save corresponding line information */
241         ktapc_growvector(f->lineinfo, fs->pc, f->sizelineinfo, int,
242                          MAX_INT, "opcodes");
243         f->lineinfo[fs->pc] = fs->ls->lastline;
244         return fs->pc++;
245 }
246
247 int codegen_codeABC(ktap_funcstate *fs, OpCode o, int a, int b, int c)
248 {
249         ktap_assert(getOpMode(o) == iABC);
250         //ktap_assert(getBMode(o) != OpArgN || b == 0);
251         //ktap_assert(getCMode(o) != OpArgN || c == 0);
252         //ktap_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
253         return codegen_code(fs, CREATE_ABC(o, a, b, c));
254 }
255
256 int codegen_codeABx(ktap_funcstate *fs, OpCode o, int a, unsigned int bc)
257 {
258         ktap_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
259         ktap_assert(getCMode(o) == OpArgN);
260         ktap_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
261         return codegen_code(fs, CREATE_ABx(o, a, bc));
262 }
263
264 static int codeextraarg(ktap_funcstate *fs, int a)
265 {
266         ktap_assert(a <= MAXARG_Ax);
267         return codegen_code(fs, CREATE_Ax(OP_EXTRAARG, a));
268 }
269
270 int codegen_codek(ktap_funcstate *fs, int reg, int k)
271 {
272         if (k <= MAXARG_Bx)
273                 return codegen_codeABx(fs, OP_LOADK, reg, k);
274         else {
275                 int p = codegen_codeABx(fs, OP_LOADKX, reg, 0);
276                 codeextraarg(fs, k);
277                 return p;
278         }
279 }
280
281 void codegen_checkstack(ktap_funcstate *fs, int n)
282 {
283         int newstack = fs->freereg + n;
284
285         if (newstack > fs->f->maxstacksize) {
286                 if (newstack >= MAXSTACK)
287                         lex_syntaxerror(fs->ls, "function or expression too complex");
288                 fs->f->maxstacksize = (u8)(newstack);
289         }
290 }
291
292 void codegen_reserveregs(ktap_funcstate *fs, int n)
293 {
294         codegen_checkstack(fs, n);
295         fs->freereg += n;
296 }
297
298 static void freereg(ktap_funcstate *fs, int reg)
299 {
300         if (!ISK(reg) && reg >= fs->nactvar) {
301                 fs->freereg--;
302                 ktap_assert(reg == fs->freereg);
303         }
304 }
305
306 static void freeexp(ktap_funcstate *fs, ktap_expdesc *e)
307 {
308         if (e->k == VNONRELOC)
309                 freereg(fs, e->u.info);
310 }
311
312 static int addk(ktap_funcstate *fs, ktap_value *key, ktap_value *v)
313 {
314         const ktap_value *idx = ktapc_table_get(fs->h, key);
315         ktap_proto *f = fs->f;
316         ktap_value kn;
317         int k, oldsize;
318
319         if (is_number(idx)) {
320                 ktap_number n = nvalue(idx);
321                 kp_number2int(k, n);
322                 if (ktapc_equalobj(&f->k[k], v))
323                         return k;
324                 /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
325                         go through and create a new entry for this value */
326         }
327         /* constant not found; create a new entry */
328         oldsize = f->sizek;
329         k = fs->nk;
330
331         /* numerical value does not need GC barrier;
332            table has no metatable, so it does not need to invalidate cache */
333         set_number(&kn, (ktap_number)k);
334         ktapc_table_setvalue(fs->h, key, &kn);
335         ktapc_growvector(f->k, k, f->sizek, ktap_value, MAXARG_Ax, "constants");
336         while (oldsize < f->sizek)
337                 set_nil(&f->k[oldsize++]);
338         set_obj(&f->k[k], v);
339         fs->nk++;
340         return k;
341 }
342
343 int codegen_stringK(ktap_funcstate *fs, ktap_string *s)
344 {
345         ktap_value o;
346
347         set_string(&o, s);
348         return addk(fs, &o, &o);
349 }
350
351 int codegen_numberK(ktap_funcstate *fs, ktap_number r)
352 {
353         int n;
354         ktap_value o, s;
355
356         set_number(&o, r);
357         if (r == 0 || ktap_numisnan(NULL, r)) {  /* handle -0 and NaN */
358                 /* use raw representation as key to avoid numeric problems */
359                 set_string(&s, ktapc_ts_newlstr((char *)&r, sizeof(r)));
360                 //   incr_top(L);
361                 n = addk(fs, &s, &o);
362                 //   L->top--;
363         } else
364                 n = addk(fs, &o, &o);  /* regular case */
365         return n;
366 }
367
368 static int boolK(ktap_funcstate *fs, int b)
369 {
370         ktap_value o;
371         set_boolean(&o, b);
372         return addk(fs, &o, &o);
373 }
374
375 static int nilK(ktap_funcstate *fs)
376 {
377         ktap_value k, v;
378         set_nil(&v);
379         /* cannot use nil as key; instead use table itself to represent nil */
380         set_table(&k, fs->h);
381         return addk(fs, &k, &v);
382 }
383
384 void codegen_setreturns(ktap_funcstate *fs, ktap_expdesc *e, int nresults)
385 {
386         if (e->k == VCALL) {  /* expression is an open function call? */
387                 SETARG_C(getcode(fs, e), nresults+1);
388         }
389         else if (e->k == VVARARG) {
390                 SETARG_B(getcode(fs, e), nresults+1);
391                 SETARG_A(getcode(fs, e), fs->freereg);
392                 codegen_reserveregs(fs, 1);
393         }
394 }
395
396 void codegen_setoneret(ktap_funcstate *fs, ktap_expdesc *e)
397 {
398         if (e->k == VCALL) {  /* expression is an open function call? */
399                 e->k = VNONRELOC;
400                 e->u.info = GETARG_A(getcode(fs, e));
401         } else if (e->k == VVARARG) {
402                 SETARG_B(getcode(fs, e), 2);
403                 e->k = VRELOCABLE;  /* can relocate its simple result */
404         }
405 }
406
407 void codegen_dischargevars(ktap_funcstate *fs, ktap_expdesc *e)
408 {
409         switch (e->k) {
410         case VLOCAL: {
411                 e->k = VNONRELOC;
412                 break;
413         }
414         case VUPVAL: {
415                 e->u.info = codegen_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
416                 e->k = VRELOCABLE;
417                 break;
418         }
419         case VINDEXED: {
420                 OpCode op = OP_GETTABUP;  /* assume 't' is in an upvalue */
421                 freereg(fs, e->u.ind.idx);
422                 if (e->u.ind.vt == VLOCAL) {  /* 't' is in a register? */
423                         freereg(fs, e->u.ind.t);
424                         op = OP_GETTABLE;
425                 }
426                 e->u.info = codegen_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
427                 e->k = VRELOCABLE;
428                 break;
429         }
430         case VVARARG:
431         case VCALL: {
432                 codegen_setoneret(fs, e);
433                 break;
434         }
435         default:
436                 break;  /* there is one value available (somewhere) */
437         }
438 }
439
440 static int code_label(ktap_funcstate *fs, int A, int b, int jump)
441 {
442         codegen_getlabel(fs);  /* those instructions may be jump targets */
443         return codegen_codeABC(fs, OP_LOADBOOL, A, b, jump);
444 }
445
446 static void discharge2reg(ktap_funcstate *fs, ktap_expdesc *e, int reg)
447 {
448         codegen_dischargevars(fs, e);
449         switch (e->k) {
450         case VNIL: {
451                 codegen_nil(fs, reg, 1);
452                 break;
453         }
454         case VFALSE:  case VTRUE: {
455                 codegen_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
456                 break;
457         }
458         case VEVENT:
459                 codegen_codeABC(fs, OP_EVENT, reg, 0, 0);
460                 break;
461         case VEVENTNAME:
462                 codegen_codeABC(fs, OP_EVENTNAME, reg, 0, 0);
463                 break;
464         case VEVENTARG:
465                 codegen_codeABC(fs, OP_EVENTARG, reg, e->u.info, 0);
466                 break;
467         case VK: {
468                 codegen_codek(fs, reg, e->u.info);
469                 break;
470         }
471         case VKNUM: {
472                 codegen_codek(fs, reg, codegen_numberK(fs, e->u.nval));
473                 break;
474         }
475         case VRELOCABLE: {
476                 ktap_instruction *pc = &getcode(fs, e);
477                 SETARG_A(*pc, reg);
478                 break;
479         }
480         case VNONRELOC: {
481                 if (reg != e->u.info)
482                         codegen_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
483                 break;
484         }
485         default:
486                 ktap_assert(e->k == VVOID || e->k == VJMP);
487                 return;  /* nothing to do... */
488         }
489
490         e->u.info = reg;
491         e->k = VNONRELOC;
492 }
493
494 static void discharge2anyreg(ktap_funcstate *fs, ktap_expdesc *e)
495 {
496         if (e->k != VNONRELOC) {
497                 codegen_reserveregs(fs, 1);
498                 discharge2reg(fs, e, fs->freereg-1);
499         }
500 }
501
502 static void exp2reg(ktap_funcstate *fs, ktap_expdesc *e, int reg)
503 {
504         discharge2reg(fs, e, reg);
505         if (e->k == VJMP)
506                 codegen_concat(fs, &e->t, e->u.info);  /* put this jump in `t' list */
507         if (hasjumps(e)) {
508                 int final;  /* position after whole expression */
509                 int p_f = NO_JUMP;  /* position of an eventual LOAD false */
510                 int p_t = NO_JUMP;  /* position of an eventual LOAD true */
511
512                 if (need_value(fs, e->t) || need_value(fs, e->f)) {
513                         int fj = (e->k == VJMP) ? NO_JUMP : codegen_jump(fs);
514
515                         p_f = code_label(fs, reg, 0, 1);
516                         p_t = code_label(fs, reg, 1, 0);
517                         codegen_patchtohere(fs, fj);
518                 }
519                 final = codegen_getlabel(fs);
520                 patchlistaux(fs, e->f, final, reg, p_f);
521                 patchlistaux(fs, e->t, final, reg, p_t);
522         }
523         e->f = e->t = NO_JUMP;
524         e->u.info = reg;
525         e->k = VNONRELOC;
526 }
527
528 void codegen_exp2nextreg(ktap_funcstate *fs, ktap_expdesc *e)
529 {
530         codegen_dischargevars(fs, e);
531         freeexp(fs, e);
532         codegen_reserveregs(fs, 1);
533         exp2reg(fs, e, fs->freereg - 1);
534 }
535
536 int codegen_exp2anyreg(ktap_funcstate *fs, ktap_expdesc *e)
537 {
538         codegen_dischargevars(fs, e);
539         if (e->k == VNONRELOC) {
540                 if (!hasjumps(e))
541                         return e->u.info;  /* exp is already in a register */
542                 if (e->u.info >= fs->nactvar) {  /* reg. is not a local? */
543                         exp2reg(fs, e, e->u.info);  /* put value on it */
544                         return e->u.info;
545                 }
546         }
547         codegen_exp2nextreg(fs, e);  /* default */
548         return e->u.info;
549 }
550
551 void codegen_exp2anyregup(ktap_funcstate *fs, ktap_expdesc *e)
552 {
553         if (e->k != VUPVAL || hasjumps(e))
554                 codegen_exp2anyreg(fs, e);
555 }
556
557 void codegen_exp2val(ktap_funcstate *fs, ktap_expdesc *e)
558 {
559         if (hasjumps(e))
560                 codegen_exp2anyreg(fs, e);
561         else
562                 codegen_dischargevars(fs, e);
563 }
564
565 int codegen_exp2RK(ktap_funcstate *fs, ktap_expdesc *e)
566 {
567         codegen_exp2val(fs, e);
568         switch (e->k) {
569         case VTRUE:
570         case VFALSE:
571         case VNIL: {
572                 if (fs->nk <= MAXINDEXRK) {  /* constant fits in RK operand? */
573                         e->u.info = (e->k == VNIL) ? nilK(fs) :
574                                                      boolK(fs, (e->k == VTRUE));
575                         e->k = VK;
576                         return RKASK(e->u.info);
577                 }
578                 else
579                         break;
580         }
581         case VKNUM: {
582                 e->u.info = codegen_numberK(fs, e->u.nval);
583                 e->k = VK;
584                 /* go through */
585         }
586         case VK: {
587                 if (e->u.info <= MAXINDEXRK)  /* constant fits in argC? */
588                         return RKASK(e->u.info);
589                 else
590                         break;
591         }
592         default:
593                 break;
594         }
595         /* not a constant in the right range: put it in a register */
596         return codegen_exp2anyreg(fs, e);
597 }
598
599 void codegen_storevar(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex)
600 {
601         switch (var->k) {
602         case VLOCAL: {
603                 freeexp(fs, ex);
604                 exp2reg(fs, ex, var->u.info);
605                 return;
606         }
607         case VUPVAL: {
608                 int e = codegen_exp2anyreg(fs, ex);
609                 codegen_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
610                 break;
611         }
612         case VINDEXED: {
613                 OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
614                 int e = codegen_exp2RK(fs, ex);
615                 codegen_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
616                 break;
617         }
618         default:
619                 ktap_assert(0);  /* invalid var kind to store */
620                 break;
621         }
622
623         freeexp(fs, ex);
624 }
625
626 void codegen_storeincr(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex)
627 {
628         switch (var->k) {
629 #if 0 /*current not supported */
630         case VLOCAL: {
631                 freeexp(fs, ex);
632                 exp2reg(fs, ex, var->u.info);
633                 return;
634         }
635         case VUPVAL: {
636                 int e = codegen_exp2anyreg(fs, ex);
637                 codegen_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
638                 break;
639         }
640 #endif
641         case VINDEXED: {
642                 OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE_INCR :
643                                 OP_SETTABUP_INCR;
644                 int e = codegen_exp2RK(fs, ex);
645                 codegen_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
646                 break;
647         }
648         default:
649                 ktap_assert(0);  /* invalid var kind to store */
650                 break;
651         }
652
653         freeexp(fs, ex);
654 }
655
656 void codegen_store_aggr(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex)
657 {
658         switch (var->k) {
659 #if 0 /*current not supported */
660         case VLOCAL: {
661                 freeexp(fs, ex);
662                 exp2reg(fs, ex, var->u.info);
663                 return;
664         }
665         case VUPVAL: {
666                 int e = codegen_exp2anyreg(fs, ex);
667                 codegen_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
668                 break;
669         }
670 #endif
671         case VINDEXED: {
672                 OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE_AGGR :
673                                 OP_SETTABUP_AGGR;
674                 int e = codegen_exp2RK(fs, ex);
675                 codegen_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
676                 break;
677         }
678         default:
679                 ktap_assert(0);  /* invalid var kind to store */
680                 break;
681         }
682
683         freeexp(fs, ex);
684 }
685
686 void codegen_self(ktap_funcstate *fs, ktap_expdesc *e, ktap_expdesc *key)
687 {
688         int ereg;
689
690         codegen_exp2anyreg(fs, e);
691         ereg = e->u.info;  /* register where 'e' was placed */
692         freeexp(fs, e);
693         e->u.info = fs->freereg;  /* base register for op_self */
694         e->k = VNONRELOC;
695         codegen_reserveregs(fs, 2);  /* function and 'self' produced by op_self */
696         codegen_codeABC(fs, OP_SELF, e->u.info, ereg, codegen_exp2RK(fs, key));
697         freeexp(fs, key);
698 }
699
700 static void invertjump(ktap_funcstate *fs, ktap_expdesc *e)
701 {
702         ktap_instruction *pc = getjumpcontrol(fs, e->u.info);
703         ktap_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
704                         GET_OPCODE(*pc) != OP_TEST);
705         SETARG_A(*pc, !(GETARG_A(*pc)));
706 }
707
708 static int jumponcond(ktap_funcstate *fs, ktap_expdesc *e, int cond)
709 {
710         if (e->k == VRELOCABLE) {
711                 ktap_instruction ie = getcode(fs, e);
712                 if (GET_OPCODE(ie) == OP_NOT) {
713                         fs->pc--;  /* remove previous OP_NOT */
714                         return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
715                 }
716                 /* else go through */
717         }
718         discharge2anyreg(fs, e);
719         freeexp(fs, e);
720         return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
721 }
722
723 void codegen_goiftrue(ktap_funcstate *fs, ktap_expdesc *e)
724 {
725         int pc;  /* pc of last jump */
726
727         codegen_dischargevars(fs, e);
728         switch (e->k) {
729         case VJMP: {
730                 invertjump(fs, e);
731                 pc = e->u.info;
732                 break;
733         }
734         case VK: case VKNUM: case VTRUE: {
735                 pc = NO_JUMP;  /* always true; do nothing */
736                 break;
737         }
738         default:
739                 pc = jumponcond(fs, e, 0);
740                 break;
741         }
742
743         codegen_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
744         codegen_patchtohere(fs, e->t);
745         e->t = NO_JUMP;
746 }
747
748 void codegen_goiffalse(ktap_funcstate *fs, ktap_expdesc *e)
749 {
750         int pc;  /* pc of last jump */
751         codegen_dischargevars(fs, e);
752
753         switch (e->k) {
754         case VJMP: {
755                 pc = e->u.info;
756                 break;
757         }
758         case VNIL: case VFALSE: {
759                 pc = NO_JUMP;  /* always false; do nothing */
760                 break;
761         }
762         default:
763                 pc = jumponcond(fs, e, 1);
764                 break;
765         }
766         codegen_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
767         codegen_patchtohere(fs, e->f);
768         e->f = NO_JUMP;
769 }
770
771 static void codenot(ktap_funcstate *fs, ktap_expdesc *e)
772 {
773         codegen_dischargevars(fs, e);
774         switch (e->k) {
775         case VNIL: case VFALSE: {
776                 e->k = VTRUE;
777                 break;
778         }
779         case VK: case VKNUM: case VTRUE: {
780                 e->k = VFALSE;
781                 break;
782         }
783         case VJMP: {
784                 invertjump(fs, e);
785                 break;
786         }
787         case VRELOCABLE:
788         case VNONRELOC: {
789                 discharge2anyreg(fs, e);
790                 freeexp(fs, e);
791                 e->u.info = codegen_codeABC(fs, OP_NOT, 0, e->u.info, 0);
792                 e->k = VRELOCABLE;
793                 break;
794         }
795         default:
796                 ktap_assert(0);  /* cannot happen */
797                 break;
798         }
799
800         /* interchange true and false lists */
801         { int temp = e->f; e->f = e->t; e->t = temp; }
802         removevalues(fs, e->f);
803         removevalues(fs, e->t);
804 }
805
806 void codegen_indexed(ktap_funcstate *fs, ktap_expdesc *t, ktap_expdesc *k)
807 {
808         ktap_assert(!hasjumps(t));
809         t->u.ind.t = t->u.info;
810         t->u.ind.idx = codegen_exp2RK(fs, k);
811         t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
812                         : check_exp(vkisinreg(t->k), VLOCAL);
813         t->k = VINDEXED;
814 }
815
816 static int constfolding(OpCode op, ktap_expdesc *e1, ktap_expdesc *e2)
817 {
818         ktap_number r;
819
820         if (!isnumeral(e1) || !isnumeral(e2))
821                 return 0;
822
823         if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
824                 return 0;  /* do not attempt to divide by 0 */
825
826         if (op == OP_POW)
827                 return 0; /* ktap current do not suppor pow arith */
828
829         r = ktapc_arith(op - OP_ADD + KTAP_OPADD, e1->u.nval, e2->u.nval);
830         e1->u.nval = r;
831         return 1;
832 }
833
834 static void codearith(ktap_funcstate *fs, OpCode op,
835                       ktap_expdesc *e1, ktap_expdesc *e2, int line)
836 {
837         if (constfolding(op, e1, e2))
838                 return;
839         else {
840                 int o2 = (op != OP_UNM && op != OP_LEN) ? codegen_exp2RK(fs, e2) : 0;
841                 int o1 = codegen_exp2RK(fs, e1);
842
843                 if (o1 > o2) {
844                         freeexp(fs, e1);
845                         freeexp(fs, e2);
846                 } else {
847                         freeexp(fs, e2);
848                         freeexp(fs, e1);
849                 }
850                 e1->u.info = codegen_codeABC(fs, op, 0, o1, o2);
851                 e1->k = VRELOCABLE;
852                 codegen_fixline(fs, line);
853         }
854 }
855
856 static void codecomp(ktap_funcstate *fs, OpCode op, int cond, ktap_expdesc *e1,
857                      ktap_expdesc *e2)
858 {
859         int o1 = codegen_exp2RK(fs, e1);
860         int o2 = codegen_exp2RK(fs, e2);
861
862         freeexp(fs, e2);
863         freeexp(fs, e1);
864         if (cond == 0 && op != OP_EQ) {
865                 int temp;  /* exchange args to replace by `<' or `<=' */
866                 temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
867                 cond = 1;
868         }
869         e1->u.info = condjump(fs, op, cond, o1, o2);
870         e1->k = VJMP;
871 }
872
873 void codegen_prefix(ktap_funcstate *fs, UnOpr op, ktap_expdesc *e, int line)
874 {
875         ktap_expdesc e2;
876
877         e2.t = e2.f = NO_JUMP;
878         e2.k = VKNUM;
879         e2.u.nval = 0;
880
881         switch (op) {
882         case OPR_MINUS: {
883                 if (isnumeral(e))  /* minus constant? */
884                         e->u.nval = ktap_numunm(e->u.nval);  /* fold it */
885                 else {
886                         codegen_exp2anyreg(fs, e);
887                         codearith(fs, OP_UNM, e, &e2, line);
888                 }
889                 break;
890         }
891         case OPR_NOT:
892                 codenot(fs, e);
893                 break;
894         case OPR_LEN: {
895                 codegen_exp2anyreg(fs, e);  /* cannot operate on constants */
896                 codearith(fs, OP_LEN, e, &e2, line);
897                 break;
898         }
899         default:
900                 ktap_assert(0);
901         }
902 }
903
904 void codegen_infix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *v)
905 {
906         switch (op) {
907         case OPR_AND: {
908                 codegen_goiftrue(fs, v);
909                 break;
910         }
911         case OPR_OR: {
912                 codegen_goiffalse(fs, v);
913                 break;
914         }
915         case OPR_CONCAT: {
916                 codegen_exp2nextreg(fs, v);  /* operand must be on the `stack' */
917                 break;
918         }
919         case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
920         case OPR_MOD: case OPR_POW: {
921                 if (!isnumeral(v)) codegen_exp2RK(fs, v);
922                         break;
923         }
924         default:
925                 codegen_exp2RK(fs, v);
926                 break;
927         }
928 }
929
930 void codegen_posfix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *e1, ktap_expdesc *e2, int line)
931 {
932         switch (op) {
933         case OPR_AND: {
934                 ktap_assert(e1->t == NO_JUMP);  /* list must be closed */
935                 codegen_dischargevars(fs, e2);
936                 codegen_concat(fs, &e2->f, e1->f);
937                 *e1 = *e2;
938                 break;
939         }
940         case OPR_OR: {
941                 ktap_assert(e1->f == NO_JUMP);  /* list must be closed */
942                 codegen_dischargevars(fs, e2);
943                 codegen_concat(fs, &e2->t, e1->t);
944                 *e1 = *e2;
945                 break;
946         }
947         case OPR_CONCAT: {
948                 codegen_exp2val(fs, e2);
949                 if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
950                         ktap_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
951                         freeexp(fs, e1);
952                         SETARG_B(getcode(fs, e2), e1->u.info);
953                         e1->k = VRELOCABLE; e1->u.info = e2->u.info;
954                 } else {
955                         codegen_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
956                         codearith(fs, OP_CONCAT, e1, e2, line);
957                 }
958                 break;
959         }
960         case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
961         case OPR_MOD: case OPR_POW: {
962                 codearith(fs, (OpCode)(op - OPR_ADD + OP_ADD), e1, e2, line);
963                 break;
964         }
965         case OPR_EQ: case OPR_LT: case OPR_LE: {
966                 codecomp(fs, (OpCode)(op - OPR_EQ + OP_EQ), 1, e1, e2);
967                 break;
968         }
969         case OPR_NE: case OPR_GT: case OPR_GE: {
970                 codecomp(fs, (OpCode)(op - OPR_NE + OP_EQ), 0, e1, e2);
971                 break;
972         }
973         default:
974                 ktap_assert(0);
975         }
976 }
977
978 void codegen_fixline(ktap_funcstate *fs, int line)
979 {
980         fs->f->lineinfo[fs->pc - 1] = line;
981 }
982
983 void codegen_setlist(ktap_funcstate *fs, int base, int nelems, int tostore)
984 {
985         int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
986         int b = (tostore == KTAP_MULTRET) ? 0 : tostore;
987
988         ktap_assert(tostore != 0);
989         if (c <= MAXARG_C)
990                 codegen_codeABC(fs, OP_SETLIST, base, b, c);
991         else if (c <= MAXARG_Ax) {
992                 codegen_codeABC(fs, OP_SETLIST, base, b, 0);
993                 codeextraarg(fs, c);
994         } else
995                 lex_syntaxerror(fs->ls, "constructor too long");
996         fs->freereg = base + 1;  /* free registers with list values */
997 }
998