1 /*
2 ** codegen.c - mruby code generator
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include <ctype.h>
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include <mruby.h>
13 #include <mruby/compile.h>
14 #include <mruby/proc.h>
15 #include <mruby/numeric.h>
16 #include <mruby/string.h>
17 #include <mruby/debug.h>
18 #include "node.h"
19 #include <mruby/opcode.h>
20 #include <mruby/re.h>
21 #include <mruby/throw.h>
22 
23 #ifndef MRB_CODEGEN_LEVEL_MAX
24 #define MRB_CODEGEN_LEVEL_MAX 1024
25 #endif
26 
27 #define MAXARG_S (1<<16)
28 
29 typedef mrb_ast_node node;
30 typedef struct mrb_parser_state parser_state;
31 
32 enum looptype {
33   LOOP_NORMAL,
34   LOOP_BLOCK,
35   LOOP_FOR,
36   LOOP_BEGIN,
37   LOOP_RESCUE,
38 };
39 
40 struct loopinfo {
41   enum looptype type;
42   int pc0, pc1, pc2, pc3, acc;
43   int ensure_level;
44   struct loopinfo *prev;
45 };
46 
47 typedef struct scope {
48   mrb_state *mrb;
49   mrb_pool *mpool;
50   struct mrb_jmpbuf jmp;
51 
52   struct scope *prev;
53 
54   node *lv;
55 
56   uint16_t sp;
57   uint16_t pc;
58   uint16_t lastpc;
59   uint16_t lastlabel;
60   int ainfo:15;
61   mrb_bool mscope:1;
62 
63   struct loopinfo *loop;
64   int ensure_level;
65   mrb_sym filename_sym;
66   uint16_t lineno;
67 
68   mrb_code *iseq;
69   uint16_t *lines;
70   uint32_t icapa;
71 
72   mrb_irep *irep;
73   uint32_t pcapa, scapa, rcapa;
74 
75   uint16_t nlocals;
76   uint16_t nregs;
77   int ai;
78 
79   int debug_start_pos;
80   uint16_t filename_index;
81   parser_state* parser;
82 
83   int rlev;                     /* recursion levels */
84 } codegen_scope;
85 
86 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
87 static void scope_finish(codegen_scope *s);
88 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
89 static void loop_break(codegen_scope *s, node *tree);
90 static void loop_pop(codegen_scope *s, int val);
91 
92 static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
93 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
94 
95 static void codegen(codegen_scope *s, node *tree, int val);
96 static void raise_error(codegen_scope *s, const char *msg);
97 
98 static void
codegen_error(codegen_scope * s,const char * message)99 codegen_error(codegen_scope *s, const char *message)
100 {
101   if (!s) return;
102   while (s->prev) {
103     codegen_scope *tmp = s->prev;
104     mrb_free(s->mrb, s->iseq);
105     mrb_free(s->mrb, s->lines);
106     mrb_pool_close(s->mpool);
107     s = tmp;
108   }
109 #ifndef MRB_DISABLE_STDIO
110   if (s->filename_sym && s->lineno) {
111     const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
112     fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
113   }
114   else {
115     fprintf(stderr, "codegen error: %s\n", message);
116   }
117 #endif
118   MRB_THROW(&s->jmp);
119 }
120 
121 static void*
codegen_palloc(codegen_scope * s,size_t len)122 codegen_palloc(codegen_scope *s, size_t len)
123 {
124   void *p = mrb_pool_alloc(s->mpool, len);
125 
126   if (!p) codegen_error(s, "pool memory allocation");
127   return p;
128 }
129 
130 static void*
codegen_realloc(codegen_scope * s,void * p,size_t len)131 codegen_realloc(codegen_scope *s, void *p, size_t len)
132 {
133   p = mrb_realloc_simple(s->mrb, p, len);
134 
135   if (!p && len > 0) codegen_error(s, "mrb_realloc");
136   return p;
137 }
138 
139 static int
new_label(codegen_scope * s)140 new_label(codegen_scope *s)
141 {
142   return s->lastlabel = s->pc;
143 }
144 
145 static void
emit_B(codegen_scope * s,uint32_t pc,uint8_t i)146 emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
147 {
148   if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
149     codegen_error(s, "too big code block");
150   }
151   if (pc >= s->icapa) {
152     s->icapa *= 2;
153     if (s->icapa > MAXARG_S) {
154       s->icapa = MAXARG_S;
155     }
156     s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
157     if (s->lines) {
158       s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
159     }
160   }
161   if (s->lines) {
162     if (s->lineno > 0 || pc == 0)
163       s->lines[pc] = s->lineno;
164     else
165       s->lines[pc] = s->lines[pc-1];
166   }
167   s->iseq[pc] = i;
168 }
169 
170 static void
emit_S(codegen_scope * s,int pc,uint16_t i)171 emit_S(codegen_scope *s, int pc, uint16_t i)
172 {
173   uint8_t hi = i>>8;
174   uint8_t lo = i&0xff;
175 
176   emit_B(s, pc,   hi);
177   emit_B(s, pc+1, lo);
178 }
179 
180 static void
gen_B(codegen_scope * s,uint8_t i)181 gen_B(codegen_scope *s, uint8_t i)
182 {
183   emit_B(s, s->pc, i);
184   s->pc++;
185 }
186 
187 static void
gen_S(codegen_scope * s,uint16_t i)188 gen_S(codegen_scope *s, uint16_t i)
189 {
190   emit_S(s, s->pc, i);
191   s->pc += 2;
192 }
193 
194 static void
genop_0(codegen_scope * s,mrb_code i)195 genop_0(codegen_scope *s, mrb_code i)
196 {
197   s->lastpc = s->pc;
198   gen_B(s, i);
199 }
200 
201 static void
genop_1(codegen_scope * s,mrb_code i,uint16_t a)202 genop_1(codegen_scope *s, mrb_code i, uint16_t a)
203 {
204   s->lastpc = s->pc;
205   if (a > 0xff) {
206     gen_B(s, OP_EXT1);
207     gen_B(s, i);
208     gen_S(s, a);
209   }
210   else {
211     gen_B(s, i);
212     gen_B(s, (uint8_t)a);
213   }
214 }
215 
216 static void
genop_2(codegen_scope * s,mrb_code i,uint16_t a,uint16_t b)217 genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
218 {
219   s->lastpc = s->pc;
220   if (a > 0xff && b > 0xff) {
221     gen_B(s, OP_EXT3);
222     gen_B(s, i);
223     gen_S(s, a);
224     gen_S(s, b);
225   }
226   else if (b > 0xff) {
227     gen_B(s, OP_EXT2);
228     gen_B(s, i);
229     gen_B(s, (uint8_t)a);
230     gen_S(s, b);
231   }
232   else if (a > 0xff) {
233     gen_B(s, OP_EXT1);
234     gen_B(s, i);
235     gen_S(s, a);
236     gen_B(s, (uint8_t)b);
237   }
238   else {
239     gen_B(s, i);
240     gen_B(s, (uint8_t)a);
241     gen_B(s, (uint8_t)b);
242   }
243 }
244 
245 static void
genop_3(codegen_scope * s,mrb_code i,uint16_t a,uint16_t b,uint8_t c)246 genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
247 {
248   genop_2(s, i, a, b);
249   gen_B(s, c);
250 }
251 
252 static void
genop_2S(codegen_scope * s,mrb_code i,uint16_t a,uint16_t b)253 genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
254 {
255   genop_1(s, i, a);
256   gen_S(s, b);
257 }
258 
259 static void
genop_W(codegen_scope * s,mrb_code i,uint32_t a)260 genop_W(codegen_scope *s, mrb_code i, uint32_t a)
261 {
262   uint8_t a1 = (a>>16) & 0xff;
263   uint8_t a2 = (a>>8) & 0xff;
264   uint8_t a3 = a & 0xff;
265 
266   s->lastpc = s->pc;
267   gen_B(s, i);
268   gen_B(s, a1);
269   gen_B(s, a2);
270   gen_B(s, a3);
271 }
272 
273 #define NOVAL  0
274 #define VAL    1
275 
276 static mrb_bool
no_optimize(codegen_scope * s)277 no_optimize(codegen_scope *s)
278 {
279   if (s && s->parser && s->parser->no_optimize)
280     return TRUE;
281   return FALSE;
282 }
283 
284 struct mrb_insn_data
mrb_decode_insn(const mrb_code * pc)285 mrb_decode_insn(const mrb_code *pc)
286 {
287   struct mrb_insn_data data = { 0 };
288   mrb_code insn = READ_B();
289   uint16_t a = 0;
290   uint16_t b = 0;
291   uint8_t  c = 0;
292 
293   switch (insn) {
294 #define FETCH_Z() /* empty */
295 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
296 #include "mruby/ops.h"
297 #undef OPCODE
298   }
299   switch (insn) {
300   case OP_EXT1:
301     insn = READ_B();
302     switch (insn) {
303 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
304 #include "mruby/ops.h"
305 #undef OPCODE
306     }
307     break;
308   case OP_EXT2:
309     insn = READ_B();
310     switch (insn) {
311 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
312 #include "mruby/ops.h"
313 #undef OPCODE
314     }
315     break;
316   case OP_EXT3:
317     insn = READ_B();
318     switch (insn) {
319 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
320 #include "mruby/ops.h"
321 #undef OPCODE
322     }
323     break;
324   default:
325     break;
326   }
327   data.insn = insn;
328   data.a = a;
329   data.b = b;
330   data.c = c;
331   return data;
332 }
333 
334 static struct mrb_insn_data
mrb_last_insn(codegen_scope * s)335 mrb_last_insn(codegen_scope *s)
336 {
337   if (s->pc == s->lastpc) {
338     struct mrb_insn_data data;
339 
340     data.insn = OP_NOP;
341     return data;
342   }
343   return mrb_decode_insn(&s->iseq[s->lastpc]);
344 }
345 
346 static mrb_bool
no_peephole(codegen_scope * s)347 no_peephole(codegen_scope *s)
348 {
349   return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
350 }
351 
352 static uint16_t
genjmp(codegen_scope * s,mrb_code i,uint16_t pc)353 genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
354 {
355   uint16_t pos;
356 
357   s->lastpc = s->pc;
358   gen_B(s, i);
359   pos = s->pc;
360   gen_S(s, pc);
361   return pos;
362 }
363 
364 static uint16_t
genjmp2(codegen_scope * s,mrb_code i,uint16_t a,int pc,int val)365 genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
366 {
367   uint16_t pos;
368 
369   if (!no_peephole(s) && !val) {
370     struct mrb_insn_data data = mrb_last_insn(s);
371 
372     if (data.insn == OP_MOVE && data.a == a) {
373       s->pc = s->lastpc;
374       a = data.b;
375     }
376   }
377 
378   s->lastpc = s->pc;
379   if (a > 0xff) {
380     gen_B(s, OP_EXT1);
381     gen_B(s, i);
382     gen_S(s, a);
383     pos = s->pc;
384     gen_S(s, pc);
385   }
386   else {
387     gen_B(s, i);
388     gen_B(s, (uint8_t)a);
389     pos = s->pc;
390     gen_S(s, pc);
391   }
392   return pos;
393 }
394 
395 static void
gen_move(codegen_scope * s,uint16_t dst,uint16_t src,int nopeep)396 gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
397 {
398   if (no_peephole(s)) {
399   normal:
400     genop_2(s, OP_MOVE, dst, src);
401     return;
402   }
403   else {
404     struct mrb_insn_data data = mrb_last_insn(s);
405 
406     switch (data.insn) {
407     case OP_MOVE:
408       if (dst == src) return;             /* remove useless MOVE */
409       if (data.b == dst && data.a == src) /* skip swapping MOVE */
410         return;
411       goto normal;
412     case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
413     case OP_LOADI__1:
414     case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
415     case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
416       if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
417       s->pc = s->lastpc;
418       genop_1(s, data.insn, dst);
419       break;
420     case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM:
421     case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
422     case OP_GETCONST: case OP_STRING:
423     case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
424       if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
425       s->pc = s->lastpc;
426       genop_2(s, data.insn, dst, data.b);
427       break;
428     default:
429       goto normal;
430     }
431   }
432 }
433 
434 static void
gen_return(codegen_scope * s,uint8_t op,uint16_t src)435 gen_return(codegen_scope *s, uint8_t op, uint16_t src)
436 {
437   if (no_peephole(s)) {
438     genop_1(s, op, src);
439   }
440   else {
441     struct mrb_insn_data data = mrb_last_insn(s);
442 
443     if (data.insn == OP_MOVE && src == data.a) {
444       s->pc = s->lastpc;
445       genop_1(s, op, data.b);
446     }
447     else if (data.insn != OP_RETURN) {
448       genop_1(s, op, src);
449     }
450   }
451 }
452 
453 static void
gen_addsub(codegen_scope * s,uint8_t op,uint16_t dst)454 gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
455 {
456   if (no_peephole(s)) {
457   normal:
458     genop_1(s, op, dst);
459     return;
460   }
461   else {
462     struct mrb_insn_data data = mrb_last_insn(s);
463 
464     switch (data.insn) {
465     case OP_LOADI__1:
466       if (op == OP_ADD) op = OP_SUB;
467       else op = OP_ADD;
468       data.b = 1;
469       goto replace;
470     case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
471     case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
472       data.b = data.insn - OP_LOADI_0;
473       /* fall through */
474     case OP_LOADI:
475     replace:
476       if (data.b >= 128) goto normal;
477       s->pc = s->lastpc;
478       if (op == OP_ADD) {
479         genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
480       }
481       else {
482         genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
483       }
484       break;
485     default:
486       goto normal;
487     }
488   }
489 }
490 
491 static int
dispatch(codegen_scope * s,uint16_t pos0)492 dispatch(codegen_scope *s, uint16_t pos0)
493 {
494   uint16_t newpos;
495 
496   s->lastlabel = s->pc;
497   newpos = PEEK_S(s->iseq+pos0);
498   emit_S(s, pos0, s->pc);
499   return newpos;
500 }
501 
502 static void
dispatch_linked(codegen_scope * s,uint16_t pos)503 dispatch_linked(codegen_scope *s, uint16_t pos)
504 {
505   if (pos==0) return;
506   for (;;) {
507     pos = dispatch(s, pos);
508     if (pos==0) break;
509   }
510 }
511 
512 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
513 static void
push_n_(codegen_scope * s,int n)514 push_n_(codegen_scope *s, int n)
515 {
516   if (s->sp+n >= 0xffff) {
517     codegen_error(s, "too complex expression");
518   }
519   s->sp+=n;
520   nregs_update;
521 }
522 
523 static void
pop_n_(codegen_scope * s,int n)524 pop_n_(codegen_scope *s, int n)
525 {
526   if ((int)s->sp-n < 0) {
527     codegen_error(s, "stack pointer underflow");
528   }
529   s->sp-=n;
530 }
531 
532 #define push() push_n_(s,1)
533 #define push_n(n) push_n_(s,n)
534 #define pop() pop_n_(s,1)
535 #define pop_n(n) pop_n_(s,n)
536 #define cursp() (s->sp)
537 
538 static inline int
new_lit(codegen_scope * s,mrb_value val)539 new_lit(codegen_scope *s, mrb_value val)
540 {
541   int i;
542   mrb_value *pv;
543 
544   switch (mrb_type(val)) {
545   case MRB_TT_STRING:
546     for (i=0; i<s->irep->plen; i++) {
547       mrb_int len;
548       pv = &s->irep->pool[i];
549 
550       if (!mrb_string_p(*pv)) continue;
551       if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
552       if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
553         return i;
554     }
555     break;
556 #ifndef MRB_WITHOUT_FLOAT
557   case MRB_TT_FLOAT:
558     for (i=0; i<s->irep->plen; i++) {
559       mrb_float f1, f2;
560       pv = &s->irep->pool[i];
561       if (!mrb_float_p(*pv)) continue;
562       f1 = mrb_float(*pv);
563       f2 = mrb_float(val);
564       if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
565     }
566     break;
567 #endif
568   case MRB_TT_FIXNUM:
569     for (i=0; i<s->irep->plen; i++) {
570       pv = &s->irep->pool[i];
571       if (!mrb_fixnum_p(*pv)) continue;
572       if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
573     }
574     break;
575   default:
576     /* should not happen */
577     return 0;
578   }
579 
580   if (s->irep->plen == s->pcapa) {
581     s->pcapa *= 2;
582     s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
583   }
584 
585   pv = &s->irep->pool[s->irep->plen];
586   i = s->irep->plen++;
587 
588   switch (mrb_type(val)) {
589   case MRB_TT_STRING:
590     *pv = mrb_str_pool(s->mrb, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(val)));
591     break;
592 
593 #ifndef MRB_WITHOUT_FLOAT
594   case MRB_TT_FLOAT:
595 #ifdef MRB_WORD_BOXING
596     *pv = mrb_float_pool(s->mrb, mrb_float(val));
597     break;
598 #endif
599 #endif
600   case MRB_TT_FIXNUM:
601     *pv = val;
602     break;
603 
604   default:
605     /* should not happen */
606     break;
607   }
608   return i;
609 }
610 
611 /* maximum symbol numbers */
612 #define MAXSYMLEN 0x10000
613 
614 static int
new_sym(codegen_scope * s,mrb_sym sym)615 new_sym(codegen_scope *s, mrb_sym sym)
616 {
617   int i, len;
618 
619   mrb_assert(s->irep);
620 
621   len = s->irep->slen;
622   for (i=0; i<len; i++) {
623     if (s->irep->syms[i] == sym) return i;
624   }
625   if (s->irep->slen >= s->scapa) {
626     s->scapa *= 2;
627     s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
628   }
629   s->irep->syms[s->irep->slen] = sym;
630   return s->irep->slen++;
631 }
632 
633 static int
node_len(node * tree)634 node_len(node *tree)
635 {
636   int n = 0;
637 
638   while (tree) {
639     n++;
640     tree = tree->cdr;
641   }
642   return n;
643 }
644 
645 #define nint(x) ((int)(intptr_t)(x))
646 #define nchar(x) ((char)(intptr_t)(x))
647 #define nsym(x) ((mrb_sym)(intptr_t)(x))
648 
649 #define lv_name(lv) nsym((lv)->car)
650 
651 static int
lv_idx(codegen_scope * s,mrb_sym id)652 lv_idx(codegen_scope *s, mrb_sym id)
653 {
654   node *lv = s->lv;
655   int n = 1;
656 
657   while (lv) {
658     if (lv_name(lv) == id) return n;
659     n++;
660     lv = lv->cdr;
661   }
662   return 0;
663 }
664 
665 static int
search_upvar(codegen_scope * s,mrb_sym id,int * idx)666 search_upvar(codegen_scope *s, mrb_sym id, int *idx)
667 {
668   struct RProc *u;
669   int lv = 0;
670   codegen_scope *up = s->prev;
671 
672   while (up) {
673     *idx = lv_idx(up, id);
674     if (*idx > 0) {
675       return lv;
676     }
677     lv ++;
678     up = up->prev;
679   }
680 
681   if (lv < 1) lv = 1;
682   u = s->parser->upper;
683   while (u && !MRB_PROC_CFUNC_P(u)) {
684     struct mrb_irep *ir = u->body.irep;
685     uint_fast16_t n = ir->nlocals;
686     const struct mrb_locals *v = ir->lv;
687     for (; n > 1; n --, v ++) {
688       if (v->name == id) {
689         *idx = v->r;
690         return lv - 1;
691       }
692     }
693     if (MRB_PROC_SCOPE_P(u)) break;
694     u = u->upper;
695     lv ++;
696   }
697 
698   codegen_error(s, "Can't found local variables");
699   return -1; /* not reached */
700 }
701 
702 static void
for_body(codegen_scope * s,node * tree)703 for_body(codegen_scope *s, node *tree)
704 {
705   codegen_scope *prev = s;
706   int idx;
707   struct loopinfo *lp;
708   node *n2;
709 
710   /* generate receiver */
711   codegen(s, tree->cdr->car, VAL);
712   /* generate loop-block */
713   s = scope_new(s->mrb, s, NULL);
714 
715   push();                       /* push for a block parameter */
716 
717   /* generate loop variable */
718   n2 = tree->car;
719   genop_W(s, OP_ENTER, 0x40000);
720   if (n2->car && !n2->car->cdr && !n2->cdr) {
721     gen_assignment(s, n2->car->car, 1, NOVAL);
722   }
723   else {
724     gen_vmassignment(s, n2, 1, VAL);
725   }
726   /* construct loop */
727   lp = loop_push(s, LOOP_FOR);
728   lp->pc2 = new_label(s);
729 
730   /* loop body */
731   codegen(s, tree->cdr->cdr->car, VAL);
732   pop();
733   gen_return(s, OP_RETURN, cursp());
734   loop_pop(s, NOVAL);
735   scope_finish(s);
736   s = prev;
737   genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
738   push();pop(); /* space for a block */
739   pop();
740   idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
741   genop_3(s, OP_SENDB, cursp(), idx, 0);
742 }
743 
744 static int
lambda_body(codegen_scope * s,node * tree,int blk)745 lambda_body(codegen_scope *s, node *tree, int blk)
746 {
747   codegen_scope *parent = s;
748   s = scope_new(s->mrb, s, tree->car);
749 
750   s->mscope = !blk;
751 
752   if (blk) {
753     struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
754     lp->pc0 = new_label(s);
755   }
756   tree = tree->cdr;
757   if (tree->car == NULL) {
758     genop_W(s, OP_ENTER, 0);
759   }
760   else {
761     mrb_aspec a;
762     int ma, oa, ra, pa, ka, kd, ba;
763     int pos, i;
764     node *opt;
765     node *margs, *pargs;
766     node *tail;
767 
768     /* mandatory arguments */
769     ma = node_len(tree->car->car);
770     margs = tree->car->car;
771     tail = tree->car->cdr->cdr->cdr->cdr;
772 
773     /* optional arguments */
774     oa = node_len(tree->car->cdr->car);
775     /* rest argument? */
776     ra = tree->car->cdr->cdr->car ? 1 : 0;
777     /* mandatory arugments after rest argument */
778     pa = node_len(tree->car->cdr->cdr->cdr->car);
779     pargs = tree->car->cdr->cdr->cdr->car;
780     /* keyword arguments */
781     ka = tail? node_len(tail->cdr->car) : 0;
782     /* keyword dictionary? */
783     kd = tail && tail->cdr->cdr->car? 1 : 0;
784     /* block argument? */
785     ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
786 
787     if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
788       codegen_error(s, "too many formal arguments");
789     }
790     a = MRB_ARGS_REQ(ma)
791       | MRB_ARGS_OPT(oa)
792       | (ra? MRB_ARGS_REST() : 0)
793       | MRB_ARGS_POST(pa)
794       | MRB_ARGS_KEY(ka, kd)
795       | (ba? MRB_ARGS_BLOCK() : 0);
796     s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
797       | ((ra & 0x1) << 6)
798       | ((pa & 0x1f) << 1)
799       | ((ka | kd) != 0 ? 0x01 : 0x00);
800     genop_W(s, OP_ENTER, a);
801     /* generate jump table for optional arguments initializer */
802     pos = new_label(s);
803     for (i=0; i<oa; i++) {
804       new_label(s);
805       genjmp(s, OP_JMP, 0);
806     }
807     if (oa > 0) {
808       genjmp(s, OP_JMP, 0);
809     }
810     opt = tree->car->cdr->car;
811     i = 0;
812     while (opt) {
813       int idx;
814       mrb_sym id = nsym(opt->car->car);
815 
816       dispatch(s, pos+i*3+1);
817       codegen(s, opt->car->cdr, VAL);
818       pop();
819       idx = lv_idx(s, id);
820       if (idx > 0) {
821         gen_move(s, idx, cursp(), 0);
822       }
823       else {
824         int lv = search_upvar(s, id, &idx);
825         genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
826       }
827       i++;
828       opt = opt->cdr;
829     }
830     if (oa > 0) {
831       dispatch(s, pos+i*3+1);
832     }
833 
834     /* keyword arguments */
835     if (tail) {
836       node *kwds = tail->cdr->car;
837       int kwrest = 0;
838 
839       if (tail->cdr->cdr->car) {
840         kwrest = 1;
841       }
842       mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
843       mrb_assert(node_len(tail) == 4);
844 
845       while (kwds) {
846         int jmpif_key_p, jmp_def_set = -1;
847         node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
848         mrb_sym kwd_sym = nsym(kwd->cdr->car);
849 
850         mrb_assert(nint(kwd->car) == NODE_KW_ARG);
851 
852         if (def_arg) {
853           int idx;
854           genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
855           jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
856           codegen(s, def_arg, VAL);
857           pop();
858           idx = lv_idx(s, kwd_sym);
859           if (idx > 0) {
860             gen_move(s, idx, cursp(), 0);
861           }
862           else {
863             int lv = search_upvar(s, kwd_sym, &idx);
864             genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
865           }
866           jmp_def_set = genjmp(s, OP_JMP, 0);
867           dispatch(s, jmpif_key_p);
868         }
869         genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
870         if (jmp_def_set != -1) {
871           dispatch(s, jmp_def_set);
872         }
873         i++;
874 
875         kwds = kwds->cdr;
876       }
877       if (tail->cdr->car && !kwrest) {
878         genop_0(s, OP_KEYEND);
879       }
880     }
881 
882     /* argument destructuring */
883     if (margs) {
884       node *n = margs;
885 
886       pos = 1;
887       while (n) {
888         if (nint(n->car->car) == NODE_MASGN) {
889           gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
890         }
891         pos++;
892         n = n->cdr;
893       }
894     }
895     if (pargs) {
896       node *n = margs;
897 
898       pos = ma+oa+ra+1;
899       while (n) {
900         if (nint(n->car->car) == NODE_MASGN) {
901           gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
902         }
903         pos++;
904         n = n->cdr;
905       }
906     }
907   }
908 
909   codegen(s, tree->cdr->car, VAL);
910   pop();
911   if (s->pc > 0) {
912     gen_return(s, OP_RETURN, cursp());
913   }
914   if (blk) {
915     loop_pop(s, NOVAL);
916   }
917   scope_finish(s);
918   return parent->irep->rlen - 1;
919 }
920 
921 static int
scope_body(codegen_scope * s,node * tree,int val)922 scope_body(codegen_scope *s, node *tree, int val)
923 {
924   codegen_scope *scope = scope_new(s->mrb, s, tree->car);
925 
926   codegen(scope, tree->cdr, VAL);
927   gen_return(scope, OP_RETURN, scope->sp-1);
928   if (!s->iseq) {
929     genop_0(scope, OP_STOP);
930   }
931   scope_finish(scope);
932   if (!s->irep) {
933     /* should not happen */
934     return 0;
935   }
936   return s->irep->rlen - 1;
937 }
938 
939 static mrb_bool
nosplat(node * t)940 nosplat(node *t)
941 {
942   while (t) {
943     if (nint(t->car->car) == NODE_SPLAT) return FALSE;
944     t = t->cdr;
945   }
946   return TRUE;
947 }
948 
949 static mrb_sym
attrsym(codegen_scope * s,mrb_sym a)950 attrsym(codegen_scope *s, mrb_sym a)
951 {
952   const char *name;
953   mrb_int len;
954   char *name2;
955 
956   name = mrb_sym_name_len(s->mrb, a, &len);
957   name2 = (char *)codegen_palloc(s,
958                                  (size_t)len
959                                  + 1 /* '=' */
960                                  + 1 /* '\0' */
961                                  );
962   mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
963   memcpy(name2, name, (size_t)len);
964   name2[len] = '=';
965   name2[len+1] = '\0';
966 
967   return mrb_intern(s->mrb, name2, len+1);
968 }
969 
970 #define CALL_MAXARGS 127
971 
972 static int
gen_values(codegen_scope * s,node * t,int val,int extra)973 gen_values(codegen_scope *s, node *t, int val, int extra)
974 {
975   int n = 0;
976   int is_splat;
977 
978   while (t) {
979     is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
980     if (
981       n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
982       || is_splat) {
983       if (val) {
984         if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
985           codegen(s, t->car->cdr, VAL);
986           pop();
987         }
988         else {
989           pop_n(n);
990           if (n == 0 && is_splat) {
991             genop_1(s, OP_LOADNIL, cursp());
992           }
993           else {
994             genop_2(s, OP_ARRAY, cursp(), n);
995           }
996           push();
997           codegen(s, t->car, VAL);
998           pop(); pop();
999           if (is_splat) {
1000             genop_1(s, OP_ARYCAT, cursp());
1001           }
1002           else {
1003             genop_1(s, OP_ARYPUSH, cursp());
1004           }
1005         }
1006         t = t->cdr;
1007         while (t) {
1008           push();
1009           codegen(s, t->car, VAL);
1010           pop(); pop();
1011           if (nint(t->car->car) == NODE_SPLAT) {
1012             genop_1(s, OP_ARYCAT, cursp());
1013           }
1014           else {
1015             genop_1(s, OP_ARYPUSH, cursp());
1016           }
1017           t = t->cdr;
1018         }
1019       }
1020       else {
1021         while (t) {
1022           codegen(s, t->car, NOVAL);
1023           t = t->cdr;
1024         }
1025       }
1026       return -1;
1027     }
1028     /* normal (no splat) mode */
1029     codegen(s, t->car, val);
1030     n++;
1031     t = t->cdr;
1032   }
1033   return n;
1034 }
1035 
1036 static void
gen_call(codegen_scope * s,node * tree,mrb_sym name,int sp,int val,int safe)1037 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
1038 {
1039   mrb_sym sym = name ? name : nsym(tree->cdr->car);
1040   int skip = 0;
1041   int n = 0, noop = 0, sendv = 0, blk = 0;
1042 
1043   codegen(s, tree->car, VAL); /* receiver */
1044   if (safe) {
1045     int recv = cursp()-1;
1046     gen_move(s, cursp(), recv, 1);
1047     skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1048   }
1049   tree = tree->cdr->cdr->car;
1050   if (tree) {
1051     n = gen_values(s, tree->car, VAL, sp?1:0);
1052     if (n < 0) {
1053       n = noop = sendv = 1;
1054       push();
1055     }
1056   }
1057   if (sp) {                     /* last argument pushed (attr=) */
1058     if (sendv) {
1059       gen_move(s, cursp(), sp, 0);
1060       pop();
1061       genop_1(s, OP_ARYPUSH, cursp());
1062       push();
1063     }
1064     else {
1065       gen_move(s, cursp(), sp, 0);
1066       push();
1067       n++;
1068     }
1069   }
1070   if (tree && tree->cdr) {
1071     noop = 1;
1072     codegen(s, tree->cdr, VAL);
1073     pop();
1074     blk = 1;
1075   }
1076   push();pop();
1077   pop_n(n+1);
1078   {
1079     mrb_int symlen;
1080     const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
1081 
1082     if (!noop && symlen == 1 && symname[0] == '+' && n == 1)  {
1083       gen_addsub(s, OP_ADD, cursp());
1084     }
1085     else if (!noop && symlen == 1 && symname[0] == '-' && n == 1)  {
1086       gen_addsub(s, OP_SUB, cursp());
1087     }
1088     else if (!noop && symlen == 1 && symname[0] == '*' && n == 1)  {
1089       genop_1(s, OP_MUL, cursp());
1090     }
1091     else if (!noop && symlen == 1 && symname[0] == '/' && n == 1)  {
1092       genop_1(s, OP_DIV, cursp());
1093     }
1094     else if (!noop && symlen == 1 && symname[0] == '<' && n == 1)  {
1095       genop_1(s, OP_LT, cursp());
1096     }
1097     else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1)  {
1098       genop_1(s, OP_LE, cursp());
1099     }
1100     else if (!noop && symlen == 1 && symname[0] == '>' && n == 1)  {
1101       genop_1(s, OP_GT, cursp());
1102     }
1103     else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1)  {
1104       genop_1(s, OP_GE, cursp());
1105     }
1106     else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1)  {
1107       genop_1(s, OP_EQ, cursp());
1108     }
1109     else {
1110       int idx = new_sym(s, sym);
1111 
1112       if (sendv) {
1113         genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
1114       }
1115       else {
1116         genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
1117       }
1118     }
1119   }
1120   if (safe) {
1121     dispatch(s, skip);
1122   }
1123   if (val) {
1124     push();
1125   }
1126 }
1127 
1128 static void
gen_assignment(codegen_scope * s,node * tree,int sp,int val)1129 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
1130 {
1131   int idx;
1132   int type = nint(tree->car);
1133 
1134   tree = tree->cdr;
1135   switch (type) {
1136   case NODE_GVAR:
1137     idx = new_sym(s, nsym(tree));
1138     genop_2(s, OP_SETGV, sp, idx);
1139     break;
1140   case NODE_ARG:
1141   case NODE_LVAR:
1142     idx = lv_idx(s, nsym(tree));
1143     if (idx > 0) {
1144       if (idx != sp) {
1145         gen_move(s, idx, sp, val);
1146       }
1147       break;
1148     }
1149     else {                      /* upvar */
1150       int lv = search_upvar(s, nsym(tree), &idx);
1151       genop_3(s, OP_SETUPVAR, sp, idx, lv);
1152     }
1153     break;
1154   case NODE_NVAR:
1155     idx = nint(tree);
1156     codegen_error(s, "Can't assign to numbered parameter");
1157     break;
1158   case NODE_IVAR:
1159     idx = new_sym(s, nsym(tree));
1160     genop_2(s, OP_SETIV, sp, idx);
1161     break;
1162   case NODE_CVAR:
1163     idx = new_sym(s, nsym(tree));
1164     genop_2(s, OP_SETCV, sp, idx);
1165     break;
1166   case NODE_CONST:
1167     idx = new_sym(s, nsym(tree));
1168     genop_2(s, OP_SETCONST, sp, idx);
1169     break;
1170   case NODE_COLON2:
1171     gen_move(s, cursp(), sp, 0);
1172     push();
1173     codegen(s, tree->car, VAL);
1174     pop_n(2);
1175     idx = new_sym(s, nsym(tree->cdr));
1176     genop_2(s, OP_SETMCNST, sp, idx);
1177     break;
1178 
1179   case NODE_CALL:
1180   case NODE_SCALL:
1181     push();
1182     gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1183              type == NODE_SCALL);
1184     pop();
1185     if (val) {
1186       gen_move(s, cursp(), sp, 0);
1187     }
1188     break;
1189 
1190   case NODE_MASGN:
1191     gen_vmassignment(s, tree->car, sp, val);
1192     break;
1193 
1194   /* splat without assignment */
1195   case NODE_NIL:
1196     break;
1197 
1198   default:
1199 #ifndef MRB_DISABLE_STDIO
1200     fprintf(stderr, "unknown lhs %d\n", type);
1201 #endif
1202     break;
1203   }
1204   if (val) push();
1205 }
1206 
1207 static void
gen_vmassignment(codegen_scope * s,node * tree,int rhs,int val)1208 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1209 {
1210   int n = 0, post = 0;
1211   node *t, *p;
1212 
1213   if (tree->car) {              /* pre */
1214     t = tree->car;
1215     n = 0;
1216     while (t) {
1217       int sp = cursp();
1218 
1219       genop_3(s, OP_AREF, sp, rhs, n);
1220       push();
1221       gen_assignment(s, t->car, sp, NOVAL);
1222       pop();
1223       n++;
1224       t = t->cdr;
1225     }
1226   }
1227   t = tree->cdr;
1228   if (t) {
1229     if (t->cdr) {               /* post count */
1230       p = t->cdr->car;
1231       while (p) {
1232         post++;
1233         p = p->cdr;
1234       }
1235     }
1236     gen_move(s, cursp(), rhs, val);
1237     push_n(post+1);
1238     pop_n(post+1);
1239     genop_3(s, OP_APOST, cursp(), n, post);
1240     n = 1;
1241     if (t->car && t->car != (node*)-1) { /* rest */
1242       gen_assignment(s, t->car, cursp(), NOVAL);
1243     }
1244     if (t->cdr && t->cdr->car) {
1245       t = t->cdr->car;
1246       while (t) {
1247         gen_assignment(s, t->car, cursp()+n, NOVAL);
1248         t = t->cdr;
1249         n++;
1250       }
1251     }
1252     if (val) {
1253       gen_move(s, cursp(), rhs, 0);
1254     }
1255   }
1256 }
1257 
1258 static void
gen_intern(codegen_scope * s)1259 gen_intern(codegen_scope *s)
1260 {
1261   pop();
1262   genop_1(s, OP_INTERN, cursp());
1263   push();
1264 }
1265 
1266 static void
gen_literal_array(codegen_scope * s,node * tree,mrb_bool sym,int val)1267 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1268 {
1269   if (val) {
1270     int i = 0, j = 0;
1271 
1272     while (tree) {
1273       switch (nint(tree->car->car)) {
1274       case NODE_STR:
1275         if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1276           break;
1277         /* fall through */
1278       case NODE_BEGIN:
1279         codegen(s, tree->car, VAL);
1280         ++j;
1281         break;
1282 
1283       case NODE_LITERAL_DELIM:
1284         if (j > 0) {
1285           j = 0;
1286           ++i;
1287           if (sym)
1288             gen_intern(s);
1289         }
1290         break;
1291       }
1292       while (j >= 2) {
1293         pop(); pop();
1294         genop_1(s, OP_STRCAT, cursp());
1295         push();
1296         j--;
1297       }
1298       tree = tree->cdr;
1299     }
1300     if (j > 0) {
1301       ++i;
1302       if (sym)
1303         gen_intern(s);
1304     }
1305     pop_n(i);
1306     genop_2(s, OP_ARRAY, cursp(), i);
1307     push();
1308   }
1309   else {
1310     while (tree) {
1311       switch (nint(tree->car->car)) {
1312       case NODE_BEGIN: case NODE_BLOCK:
1313         codegen(s, tree->car, NOVAL);
1314       }
1315       tree = tree->cdr;
1316     }
1317   }
1318 }
1319 
1320 static void
raise_error(codegen_scope * s,const char * msg)1321 raise_error(codegen_scope *s, const char *msg)
1322 {
1323   int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1324 
1325   genop_1(s, OP_ERR, idx);
1326 }
1327 
1328 #ifndef MRB_WITHOUT_FLOAT
1329 static double
readint_float(codegen_scope * s,const char * p,int base)1330 readint_float(codegen_scope *s, const char *p, int base)
1331 {
1332   const char *e = p + strlen(p);
1333   double f = 0;
1334   int n;
1335 
1336   if (*p == '+') p++;
1337   while (p < e) {
1338     char c = *p;
1339     c = tolower((unsigned char)c);
1340     for (n=0; n<base; n++) {
1341       if (mrb_digitmap[n] == c) {
1342         f *= base;
1343         f += n;
1344         break;
1345       }
1346     }
1347     if (n == base) {
1348       codegen_error(s, "malformed readint input");
1349     }
1350     p++;
1351   }
1352   return f;
1353 }
1354 #endif
1355 
1356 static mrb_int
readint_mrb_int(codegen_scope * s,const char * p,int base,mrb_bool neg,mrb_bool * overflow)1357 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1358 {
1359   const char *e = p + strlen(p);
1360   mrb_int result = 0;
1361   int n;
1362 
1363   mrb_assert(base >= 2 && base <= 36);
1364   if (*p == '+') p++;
1365   while (p < e) {
1366     char c = *p;
1367     c = tolower((unsigned char)c);
1368     for (n=0; n<base; n++) {
1369       if (mrb_digitmap[n] == c) {
1370         break;
1371       }
1372     }
1373     if (n == base) {
1374       codegen_error(s, "malformed readint input");
1375     }
1376 
1377     if (neg) {
1378       if ((MRB_INT_MIN + n)/base > result) {
1379         *overflow = TRUE;
1380         return 0;
1381       }
1382       result *= base;
1383       result -= n;
1384     }
1385     else {
1386       if ((MRB_INT_MAX - n)/base < result) {
1387         *overflow = TRUE;
1388         return 0;
1389       }
1390       result *= base;
1391       result += n;
1392     }
1393     p++;
1394   }
1395   *overflow = FALSE;
1396   return result;
1397 }
1398 
1399 static void
gen_retval(codegen_scope * s,node * tree)1400 gen_retval(codegen_scope *s, node *tree)
1401 {
1402   if (nint(tree->car) == NODE_SPLAT) {
1403     codegen(s, tree, VAL);
1404     pop();
1405     genop_1(s, OP_ARYDUP, cursp());
1406   }
1407   else {
1408     codegen(s, tree, VAL);
1409     pop();
1410   }
1411 }
1412 
1413 static void
codegen(codegen_scope * s,node * tree,int val)1414 codegen(codegen_scope *s, node *tree, int val)
1415 {
1416   int nt;
1417   int rlev = s->rlev;
1418 
1419   if (!tree) {
1420     if (val) {
1421       genop_1(s, OP_LOADNIL, cursp());
1422       push();
1423     }
1424     return;
1425   }
1426 
1427   s->rlev++;
1428   if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1429     codegen_error(s, "too complex expression");
1430   }
1431   if (s->irep && s->filename_index != tree->filename_index) {
1432     mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
1433     const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
1434 
1435     mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
1436                                filename, s->lines, s->debug_start_pos, s->pc);
1437     s->debug_start_pos = s->pc;
1438     s->filename_index = tree->filename_index;
1439     s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
1440   }
1441 
1442   nt = nint(tree->car);
1443   s->lineno = tree->lineno;
1444   tree = tree->cdr;
1445   switch (nt) {
1446   case NODE_BEGIN:
1447     if (val && !tree) {
1448       genop_1(s, OP_LOADNIL, cursp());
1449       push();
1450     }
1451     while (tree) {
1452       codegen(s, tree->car, tree->cdr ? NOVAL : val);
1453       tree = tree->cdr;
1454     }
1455     break;
1456 
1457   case NODE_RESCUE:
1458     {
1459       int noexc, exend, pos1, pos2, tmp;
1460       struct loopinfo *lp;
1461 
1462       if (tree->car == NULL) goto exit;
1463       lp = loop_push(s, LOOP_BEGIN);
1464       lp->pc0 = new_label(s);
1465       lp->pc1 = genjmp(s, OP_ONERR, 0);
1466       codegen(s, tree->car, VAL);
1467       pop();
1468       lp->type = LOOP_RESCUE;
1469       noexc = genjmp(s, OP_JMP, 0);
1470       dispatch(s, lp->pc1);
1471       tree = tree->cdr;
1472       exend = 0;
1473       pos1 = 0;
1474       if (tree->car) {
1475         node *n2 = tree->car;
1476         int exc = cursp();
1477 
1478         genop_1(s, OP_EXCEPT, exc);
1479         push();
1480         while (n2) {
1481           node *n3 = n2->car;
1482           node *n4 = n3->car;
1483 
1484           if (pos1) dispatch(s, pos1);
1485           pos2 = 0;
1486           do {
1487             if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
1488               codegen(s, n4->car, VAL);
1489               gen_move(s, cursp(), exc, 0);
1490               push_n(2); pop_n(2); /* space for one arg and a block */
1491               pop();
1492               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1493             }
1494             else {
1495               if (n4) {
1496                 codegen(s, n4->car, VAL);
1497               }
1498               else {
1499                 genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
1500                 push();
1501               }
1502               pop();
1503               genop_2(s, OP_RESCUE, exc, cursp());
1504             }
1505             tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
1506             pos2 = tmp;
1507             if (n4) {
1508               n4 = n4->cdr;
1509             }
1510           } while (n4);
1511           pos1 = genjmp(s, OP_JMP, 0);
1512           dispatch_linked(s, pos2);
1513 
1514           pop();
1515           if (n3->cdr->car) {
1516             gen_assignment(s, n3->cdr->car, exc, NOVAL);
1517           }
1518           if (n3->cdr->cdr->car) {
1519             codegen(s, n3->cdr->cdr->car, val);
1520             if (val) pop();
1521           }
1522           tmp = genjmp(s, OP_JMP, exend);
1523           exend = tmp;
1524           n2 = n2->cdr;
1525           push();
1526         }
1527         if (pos1) {
1528           dispatch(s, pos1);
1529           genop_1(s, OP_RAISE, exc);
1530         }
1531       }
1532       pop();
1533       tree = tree->cdr;
1534       dispatch(s, noexc);
1535       genop_1(s, OP_POPERR, 1);
1536       if (tree->car) {
1537         codegen(s, tree->car, val);
1538       }
1539       else if (val) {
1540         push();
1541       }
1542       dispatch_linked(s, exend);
1543       loop_pop(s, NOVAL);
1544     }
1545     break;
1546 
1547   case NODE_ENSURE:
1548     if (!tree->cdr || !tree->cdr->cdr ||
1549         (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1550          tree->cdr->cdr->cdr)) {
1551       int idx;
1552 
1553       s->ensure_level++;
1554       idx = scope_body(s, tree->cdr, NOVAL);
1555       genop_1(s, OP_EPUSH, idx);
1556       codegen(s, tree->car, val);
1557       s->ensure_level--;
1558       genop_1(s, OP_EPOP, 1);
1559     }
1560     else {                      /* empty ensure ignored */
1561       codegen(s, tree->car, val);
1562     }
1563     break;
1564 
1565   case NODE_LAMBDA:
1566     if (val) {
1567       int idx = lambda_body(s, tree, 1);
1568 
1569       genop_2(s, OP_LAMBDA, cursp(), idx);
1570       push();
1571     }
1572     break;
1573 
1574   case NODE_BLOCK:
1575     if (val) {
1576       int idx = lambda_body(s, tree, 1);
1577 
1578       genop_2(s, OP_BLOCK, cursp(), idx);
1579       push();
1580     }
1581     break;
1582 
1583   case NODE_IF:
1584     {
1585       int pos1, pos2, nil_p = FALSE;
1586       node *elsepart = tree->cdr->cdr->car;
1587 
1588       if (!tree->car) {
1589         codegen(s, elsepart, val);
1590         goto exit;
1591       }
1592       switch (nint(tree->car->car)) {
1593       case NODE_TRUE:
1594       case NODE_INT:
1595       case NODE_STR:
1596         codegen(s, tree->cdr->car, val);
1597         goto exit;
1598       case NODE_FALSE:
1599       case NODE_NIL:
1600         codegen(s, elsepart, val);
1601         goto exit;
1602       case NODE_CALL:
1603         {
1604           node *n = tree->car->cdr;
1605           mrb_sym mid = nsym(n->cdr->car);
1606           mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
1607           if (mid == mnil && n->cdr->cdr->car == NULL) {
1608             nil_p = TRUE;
1609             codegen(s, n->car, VAL);
1610           }
1611         }
1612         break;
1613       }
1614       if (!nil_p) {
1615         codegen(s, tree->car, VAL);
1616       }
1617       pop();
1618       if (val || tree->cdr->car) {
1619         if (nil_p) {
1620           pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1621           pos1 = genjmp(s, OP_JMP, 0);
1622           dispatch(s, pos2);
1623         }
1624         else {
1625           pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1626         }
1627         codegen(s, tree->cdr->car, val);
1628         if (val) pop();
1629         if (elsepart || val) {
1630           pos2 = genjmp(s, OP_JMP, 0);
1631           dispatch(s, pos1);
1632           codegen(s, elsepart, val);
1633           dispatch(s, pos2);
1634         }
1635         else {
1636           dispatch(s, pos1);
1637         }
1638       }
1639       else {                    /* empty then-part */
1640         if (elsepart) {
1641           if (nil_p) {
1642             pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1643           }
1644           else {
1645             pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1646           }
1647           codegen(s, elsepart, val);
1648           dispatch(s, pos1);
1649         }
1650         else if (val && !nil_p) {
1651           genop_1(s, OP_LOADNIL, cursp());
1652           push();
1653         }
1654       }
1655     }
1656     break;
1657 
1658   case NODE_AND:
1659     {
1660       int pos;
1661 
1662       codegen(s, tree->car, VAL);
1663       pop();
1664       pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1665       codegen(s, tree->cdr, val);
1666       dispatch(s, pos);
1667     }
1668     break;
1669 
1670   case NODE_OR:
1671     {
1672       int pos;
1673 
1674       codegen(s, tree->car, VAL);
1675       pop();
1676       pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1677       codegen(s, tree->cdr, val);
1678       dispatch(s, pos);
1679     }
1680     break;
1681 
1682   case NODE_WHILE:
1683     {
1684       struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1685 
1686       lp->pc0 = new_label(s);
1687       lp->pc1 = genjmp(s, OP_JMP, 0);
1688       lp->pc2 = new_label(s);
1689       codegen(s, tree->cdr, NOVAL);
1690       dispatch(s, lp->pc1);
1691       codegen(s, tree->car, VAL);
1692       pop();
1693       genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
1694 
1695       loop_pop(s, val);
1696     }
1697     break;
1698 
1699   case NODE_UNTIL:
1700     {
1701       struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1702 
1703       lp->pc0 = new_label(s);
1704       lp->pc1 = genjmp(s, OP_JMP, 0);
1705       lp->pc2 = new_label(s);
1706       codegen(s, tree->cdr, NOVAL);
1707       dispatch(s, lp->pc1);
1708       codegen(s, tree->car, VAL);
1709       pop();
1710       genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
1711 
1712       loop_pop(s, val);
1713     }
1714     break;
1715 
1716   case NODE_FOR:
1717     for_body(s, tree);
1718     if (val) push();
1719     break;
1720 
1721   case NODE_CASE:
1722     {
1723       int head = 0;
1724       int pos1, pos2, pos3, tmp;
1725       node *n;
1726 
1727       pos3 = 0;
1728       if (tree->car) {
1729         head = cursp();
1730         codegen(s, tree->car, VAL);
1731       }
1732       tree = tree->cdr;
1733       while (tree) {
1734         n = tree->car->car;
1735         pos1 = pos2 = 0;
1736         while (n) {
1737           codegen(s, n->car, VAL);
1738           if (head) {
1739             gen_move(s, cursp(), head, 0);
1740             push(); push(); pop(); pop(); pop();
1741             if (nint(n->car->car) == NODE_SPLAT) {
1742               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1743             }
1744             else {
1745               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
1746             }
1747           }
1748           else {
1749             pop();
1750           }
1751           tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
1752           pos2 = tmp;
1753           n = n->cdr;
1754         }
1755         if (tree->car->car) {
1756           pos1 = genjmp(s, OP_JMP, 0);
1757           dispatch_linked(s, pos2);
1758         }
1759         codegen(s, tree->car->cdr, val);
1760         if (val) pop();
1761         tmp = genjmp(s, OP_JMP, pos3);
1762         pos3 = tmp;
1763         if (pos1) dispatch(s, pos1);
1764         tree = tree->cdr;
1765       }
1766       if (val) {
1767         int pos = cursp();
1768         genop_1(s, OP_LOADNIL, cursp());
1769         if (pos3) dispatch_linked(s, pos3);
1770         if (head) pop();
1771         if (cursp() != pos) {
1772           gen_move(s, cursp(), pos, 0);
1773         }
1774         push();
1775       }
1776       else {
1777         if (pos3) {
1778           dispatch_linked(s, pos3);
1779         }
1780         if (head) {
1781           pop();
1782         }
1783       }
1784     }
1785     break;
1786 
1787   case NODE_SCOPE:
1788     scope_body(s, tree, NOVAL);
1789     break;
1790 
1791   case NODE_FCALL:
1792   case NODE_CALL:
1793     gen_call(s, tree, 0, 0, val, 0);
1794     break;
1795   case NODE_SCALL:
1796     gen_call(s, tree, 0, 0, val, 1);
1797     break;
1798 
1799   case NODE_DOT2:
1800     codegen(s, tree->car, val);
1801     codegen(s, tree->cdr, val);
1802     if (val) {
1803       pop(); pop();
1804       genop_1(s, OP_RANGE_INC, cursp());
1805       push();
1806     }
1807     break;
1808 
1809   case NODE_DOT3:
1810     codegen(s, tree->car, val);
1811     codegen(s, tree->cdr, val);
1812     if (val) {
1813       pop(); pop();
1814       genop_1(s, OP_RANGE_EXC, cursp());
1815       push();
1816     }
1817     break;
1818 
1819   case NODE_COLON2:
1820     {
1821       int sym = new_sym(s, nsym(tree->cdr));
1822 
1823       codegen(s, tree->car, VAL);
1824       pop();
1825       genop_2(s, OP_GETMCNST, cursp(), sym);
1826       if (val) push();
1827     }
1828     break;
1829 
1830   case NODE_COLON3:
1831     {
1832       int sym = new_sym(s, nsym(tree));
1833 
1834       genop_1(s, OP_OCLASS, cursp());
1835       genop_2(s, OP_GETMCNST, cursp(), sym);
1836       if (val) push();
1837     }
1838     break;
1839 
1840   case NODE_ARRAY:
1841     {
1842       int n;
1843 
1844       n = gen_values(s, tree, val, 0);
1845       if (n >= 0) {
1846         if (val) {
1847           pop_n(n);
1848           genop_2(s, OP_ARRAY, cursp(), n);
1849           push();
1850         }
1851       }
1852       else if (val) {
1853         push();
1854       }
1855     }
1856     break;
1857 
1858   case NODE_HASH:
1859   case NODE_KW_HASH:
1860     {
1861       int len = 0;
1862       mrb_bool update = FALSE;
1863 
1864       while (tree) {
1865         if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1866           if (len > 0) {
1867             pop_n(len*2);
1868             if (!update) {
1869               genop_2(s, OP_HASH, cursp(), len);
1870             }
1871             else {
1872               pop();
1873               genop_2(s, OP_HASHADD, cursp(), len);
1874             }
1875             push();
1876           }
1877           codegen(s, tree->car->cdr, VAL);
1878           if (len > 0 || update) {
1879             pop(); pop();
1880             genop_1(s, OP_HASHCAT, cursp());
1881             push();
1882           }
1883           update = TRUE;
1884           len = 0;
1885         }
1886         else {
1887           codegen(s, tree->car->car, val);
1888           codegen(s, tree->car->cdr, val);
1889           len++;
1890         }
1891         tree = tree->cdr;
1892         if (val && cursp() > 127) {
1893           pop_n(len*2);
1894           if (!update) {
1895             genop_2(s, OP_HASH, cursp(), len);
1896           }
1897           else {
1898             pop();
1899             genop_2(s, OP_HASHADD, cursp(), len);
1900           }
1901           push();
1902           update = TRUE;
1903           len = 0;
1904         }
1905       }
1906       if (val) {
1907         pop_n(len*2);
1908         if (!update) {
1909           genop_2(s, OP_HASH, cursp(), len);
1910         }
1911         else {
1912           pop();
1913           if (len > 0) {
1914             genop_2(s, OP_HASHADD, cursp(), len);
1915           }
1916         }
1917         push();
1918       }
1919     }
1920     break;
1921 
1922   case NODE_SPLAT:
1923     codegen(s, tree, val);
1924     break;
1925 
1926   case NODE_ASGN:
1927     codegen(s, tree->cdr, VAL);
1928     pop();
1929     gen_assignment(s, tree->car, cursp(), val);
1930     break;
1931 
1932   case NODE_MASGN:
1933     {
1934       int len = 0, n = 0, post = 0;
1935       node *t = tree->cdr, *p;
1936       int rhs = cursp();
1937 
1938       if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1939         /* fixed rhs */
1940         t = t->cdr;
1941         while (t) {
1942           codegen(s, t->car, VAL);
1943           len++;
1944           t = t->cdr;
1945         }
1946         tree = tree->car;
1947         if (tree->car) {                /* pre */
1948           t = tree->car;
1949           n = 0;
1950           while (t) {
1951             if (n < len) {
1952               gen_assignment(s, t->car, rhs+n, NOVAL);
1953               n++;
1954             }
1955             else {
1956               genop_1(s, OP_LOADNIL, rhs+n);
1957               gen_assignment(s, t->car, rhs+n, NOVAL);
1958             }
1959             t = t->cdr;
1960           }
1961         }
1962         t = tree->cdr;
1963         if (t) {
1964           if (t->cdr) {         /* post count */
1965             p = t->cdr->car;
1966             while (p) {
1967               post++;
1968               p = p->cdr;
1969             }
1970           }
1971           if (t->car) {         /* rest (len - pre - post) */
1972             int rn;
1973 
1974             if (len < post + n) {
1975               rn = 0;
1976             }
1977             else {
1978               rn = len - post - n;
1979             }
1980             genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
1981             gen_assignment(s, t->car, cursp(), NOVAL);
1982             n += rn;
1983           }
1984           if (t->cdr && t->cdr->car) {
1985             t = t->cdr->car;
1986             while (n<len) {
1987               gen_assignment(s, t->car, rhs+n, NOVAL);
1988               t = t->cdr;
1989               n++;
1990             }
1991           }
1992         }
1993         pop_n(len);
1994         if (val) {
1995           genop_2(s, OP_ARRAY, rhs, len);
1996           push();
1997         }
1998       }
1999       else {
2000         /* variable rhs */
2001         codegen(s, t, VAL);
2002         gen_vmassignment(s, tree->car, rhs, val);
2003         if (!val) {
2004           pop();
2005         }
2006       }
2007     }
2008     break;
2009 
2010   case NODE_OP_ASGN:
2011     {
2012       mrb_sym sym = nsym(tree->cdr->car);
2013       mrb_int len;
2014       const char *name = mrb_sym_name_len(s->mrb, sym, &len);
2015       int idx, callargs = -1, vsp = -1;
2016 
2017       if ((len == 2 && name[0] == '|' && name[1] == '|') &&
2018           (nint(tree->car->car) == NODE_CONST ||
2019            nint(tree->car->car) == NODE_CVAR)) {
2020         int onerr, noexc, exc;
2021         struct loopinfo *lp;
2022 
2023         onerr = genjmp(s, OP_ONERR, 0);
2024         lp = loop_push(s, LOOP_BEGIN);
2025         lp->pc1 = onerr;
2026         exc = cursp();
2027         codegen(s, tree->car, VAL);
2028         lp->type = LOOP_RESCUE;
2029         genop_1(s, OP_POPERR, 1);
2030         noexc = genjmp(s, OP_JMP, 0);
2031         dispatch(s, onerr);
2032         genop_1(s, OP_EXCEPT, exc);
2033         genop_1(s, OP_LOADF, exc);
2034         dispatch(s, noexc);
2035         loop_pop(s, NOVAL);
2036       }
2037       else if (nint(tree->car->car) == NODE_CALL) {
2038         node *n = tree->car->cdr;
2039         int base, i, nargs = 0;
2040         callargs = 0;
2041 
2042         if (val) {
2043           vsp = cursp();
2044           push();
2045         }
2046         codegen(s, n->car, VAL);   /* receiver */
2047         idx = new_sym(s, nsym(n->cdr->car));
2048         base = cursp()-1;
2049         if (n->cdr->cdr->car) {
2050           nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
2051           if (nargs >= 0) {
2052             callargs = nargs;
2053           }
2054           else { /* varargs */
2055             push();
2056             nargs = 1;
2057             callargs = CALL_MAXARGS;
2058           }
2059         }
2060         /* copy receiver and arguments */
2061         gen_move(s, cursp(), base, 1);
2062         for (i=0; i<nargs; i++) {
2063           gen_move(s, cursp()+i+1, base+i+1, 1);
2064         }
2065         push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
2066         genop_3(s, OP_SEND, cursp(), idx, callargs);
2067         push();
2068       }
2069       else {
2070         codegen(s, tree->car, VAL);
2071       }
2072       if (len == 2 &&
2073           ((name[0] == '|' && name[1] == '|') ||
2074            (name[0] == '&' && name[1] == '&'))) {
2075         int pos;
2076 
2077         pop();
2078         if (val) {
2079           if (vsp >= 0) {
2080             gen_move(s, vsp, cursp(), 1);
2081           }
2082           pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2083         }
2084         else {
2085           pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2086         }
2087         codegen(s, tree->cdr->cdr->car, VAL);
2088         pop();
2089         if (val && vsp >= 0) {
2090           gen_move(s, vsp, cursp(), 1);
2091         }
2092         if (nint(tree->car->car) == NODE_CALL) {
2093           if (callargs == CALL_MAXARGS) {
2094             pop();
2095             genop_1(s, OP_ARYPUSH, cursp());
2096           }
2097           else {
2098             pop_n(callargs);
2099             callargs++;
2100           }
2101           pop();
2102           idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2103           genop_3(s, OP_SEND, cursp(), idx, callargs);
2104         }
2105         else {
2106           gen_assignment(s, tree->car, cursp(), val);
2107         }
2108         dispatch(s, pos);
2109         goto exit;
2110       }
2111       codegen(s, tree->cdr->cdr->car, VAL);
2112       push(); pop();
2113       pop(); pop();
2114 
2115       if (len == 1 && name[0] == '+')  {
2116         gen_addsub(s, OP_ADD, cursp());
2117       }
2118       else if (len == 1 && name[0] == '-')  {
2119         gen_addsub(s, OP_SUB, cursp());
2120       }
2121       else if (len == 1 && name[0] == '*')  {
2122         genop_1(s, OP_MUL, cursp());
2123       }
2124       else if (len == 1 && name[0] == '/')  {
2125         genop_1(s, OP_DIV, cursp());
2126       }
2127       else if (len == 1 && name[0] == '<')  {
2128         genop_1(s, OP_LT, cursp());
2129       }
2130       else if (len == 2 && name[0] == '<' && name[1] == '=')  {
2131         genop_1(s, OP_LE, cursp());
2132       }
2133       else if (len == 1 && name[0] == '>')  {
2134         genop_1(s, OP_GT, cursp());
2135       }
2136       else if (len == 2 && name[0] == '>' && name[1] == '=')  {
2137         genop_1(s, OP_GE, cursp());
2138       }
2139       else {
2140         idx = new_sym(s, sym);
2141         genop_3(s, OP_SEND, cursp(), idx, 1);
2142       }
2143       if (callargs < 0) {
2144         gen_assignment(s, tree->car, cursp(), val);
2145       }
2146       else {
2147         if (val && vsp >= 0) {
2148           gen_move(s, vsp, cursp(), 0);
2149         }
2150         if (callargs == CALL_MAXARGS) {
2151           pop();
2152           genop_1(s, OP_ARYPUSH, cursp());
2153         }
2154         else {
2155           pop_n(callargs);
2156           callargs++;
2157         }
2158         pop();
2159         idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2160         genop_3(s, OP_SEND, cursp(), idx, callargs);
2161       }
2162     }
2163     break;
2164 
2165   case NODE_SUPER:
2166     {
2167       codegen_scope *s2 = s;
2168       int lv = 0;
2169       int n = 0, noop = 0, sendv = 0;
2170 
2171       push();        /* room for receiver */
2172       while (!s2->mscope) {
2173         lv++;
2174         s2 = s2->prev;
2175         if (!s2) break;
2176       }
2177       genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
2178       push(); push();         /* ARGARY pushes two values */
2179       pop(); pop();
2180       if (tree) {
2181         node *args = tree->car;
2182         if (args) {
2183           n = gen_values(s, args, VAL, 0);
2184           if (n < 0) {
2185             n = noop = sendv = 1;
2186             push();
2187           }
2188         }
2189       }
2190       if (tree && tree->cdr) {
2191         codegen(s, tree->cdr, VAL);
2192         pop();
2193       }
2194       else {
2195         genop_1(s, OP_LOADNIL, cursp());
2196         push(); pop();
2197       }
2198       pop_n(n+1);
2199       if (sendv) n = CALL_MAXARGS;
2200       genop_2(s, OP_SUPER, cursp(), n);
2201       if (val) push();
2202     }
2203     break;
2204 
2205   case NODE_ZSUPER:
2206     {
2207       codegen_scope *s2 = s;
2208       int lv = 0, ainfo = 0;
2209 
2210       push();        /* room for receiver */
2211       while (!s2->mscope) {
2212         lv++;
2213         s2 = s2->prev;
2214         if (!s2) break;
2215       }
2216       if (s2) ainfo = s2->ainfo;
2217       genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
2218       push(); push(); pop();    /* ARGARY pushes two values */
2219       if (tree && tree->cdr) {
2220         codegen(s, tree->cdr, VAL);
2221         pop();
2222       }
2223       pop(); pop();
2224       genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
2225       if (val) push();
2226     }
2227     break;
2228 
2229   case NODE_RETURN:
2230     if (tree) {
2231       gen_retval(s, tree);
2232     }
2233     else {
2234       genop_1(s, OP_LOADNIL, cursp());
2235     }
2236     if (s->loop) {
2237       gen_return(s, OP_RETURN_BLK, cursp());
2238     }
2239     else {
2240       gen_return(s, OP_RETURN, cursp());
2241     }
2242     if (val) push();
2243     break;
2244 
2245   case NODE_YIELD:
2246     {
2247       codegen_scope *s2 = s;
2248       int lv = 0, ainfo = 0;
2249       int n = 0, sendv = 0;
2250 
2251       while (!s2->mscope) {
2252         lv++;
2253         s2 = s2->prev;
2254         if (!s2) break;
2255       }
2256       if (s2) ainfo = s2->ainfo;
2257       push();
2258       if (tree) {
2259         n = gen_values(s, tree, VAL, 0);
2260         if (n < 0) {
2261           n = sendv = 1;
2262           push();
2263         }
2264       }
2265       push();pop(); /* space for a block */
2266       pop_n(n+1);
2267       genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
2268       if (sendv) n = CALL_MAXARGS;
2269       genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
2270       if (val) push();
2271     }
2272     break;
2273 
2274   case NODE_BREAK:
2275     loop_break(s, tree);
2276     if (val) push();
2277     break;
2278 
2279   case NODE_NEXT:
2280     if (!s->loop) {
2281       raise_error(s, "unexpected next");
2282     }
2283     else if (s->loop->type == LOOP_NORMAL) {
2284       if (s->ensure_level > s->loop->ensure_level) {
2285         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2286       }
2287       codegen(s, tree, NOVAL);
2288       genjmp(s, OP_JMP, s->loop->pc0);
2289     }
2290     else {
2291       if (tree) {
2292         codegen(s, tree, VAL);
2293         pop();
2294       }
2295       else {
2296         genop_1(s, OP_LOADNIL, cursp());
2297       }
2298       gen_return(s, OP_RETURN, cursp());
2299     }
2300     if (val) push();
2301     break;
2302 
2303   case NODE_REDO:
2304     if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2305       raise_error(s, "unexpected redo");
2306     }
2307     else {
2308       if (s->ensure_level > s->loop->ensure_level) {
2309         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2310       }
2311       genjmp(s, OP_JMP, s->loop->pc2);
2312     }
2313     if (val) push();
2314     break;
2315 
2316   case NODE_RETRY:
2317     {
2318       const char *msg = "unexpected retry";
2319 
2320       if (!s->loop) {
2321         raise_error(s, msg);
2322       }
2323       else {
2324         struct loopinfo *lp = s->loop;
2325         int n = 0;
2326 
2327         while (lp && lp->type != LOOP_RESCUE) {
2328           if (lp->type == LOOP_BEGIN) {
2329             n++;
2330           }
2331           lp = lp->prev;
2332         }
2333         if (!lp) {
2334           raise_error(s, msg);
2335         }
2336         else {
2337           if (n > 0) {
2338             genop_1(s, OP_POPERR, n);
2339           }
2340           if (s->ensure_level > lp->ensure_level) {
2341             genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
2342           }
2343           genjmp(s, OP_JMP, lp->pc0);
2344         }
2345       }
2346       if (val) push();
2347     }
2348     break;
2349 
2350   case NODE_LVAR:
2351     if (val) {
2352       int idx = lv_idx(s, nsym(tree));
2353 
2354       if (idx > 0) {
2355         gen_move(s, cursp(), idx, val);
2356       }
2357       else {
2358         int lv = search_upvar(s, nsym(tree), &idx);
2359         genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
2360       }
2361       push();
2362     }
2363     break;
2364 
2365   case NODE_NVAR:
2366     if (val) {
2367       int idx = nint(tree);
2368 
2369       gen_move(s, cursp(), idx, val);
2370 
2371       push();
2372     }
2373     break;
2374 
2375   case NODE_GVAR:
2376     {
2377       int sym = new_sym(s, nsym(tree));
2378 
2379       genop_2(s, OP_GETGV, cursp(), sym);
2380       if (val) push();
2381     }
2382     break;
2383 
2384   case NODE_IVAR:
2385     {
2386       int sym = new_sym(s, nsym(tree));
2387 
2388       genop_2(s, OP_GETIV, cursp(), sym);
2389       if (val) push();
2390     }
2391     break;
2392 
2393   case NODE_CVAR:
2394     {
2395       int sym = new_sym(s, nsym(tree));
2396 
2397       genop_2(s, OP_GETCV, cursp(), sym);
2398       if (val) push();
2399     }
2400     break;
2401 
2402   case NODE_CONST:
2403     {
2404       int sym = new_sym(s, nsym(tree));
2405 
2406       genop_2(s, OP_GETCONST, cursp(), sym);
2407       if (val) push();
2408     }
2409     break;
2410 
2411   case NODE_BACK_REF:
2412     if (val) {
2413       char buf[] = {'$', nchar(tree)};
2414       int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
2415 
2416       genop_2(s, OP_GETGV, cursp(), sym);
2417       push();
2418     }
2419     break;
2420 
2421   case NODE_NTH_REF:
2422     if (val) {
2423       mrb_state *mrb = s->mrb;
2424       mrb_value str;
2425       int sym;
2426 
2427       str = mrb_format(mrb, "$%d", nint(tree));
2428       sym = new_sym(s, mrb_intern_str(mrb, str));
2429       genop_2(s, OP_GETGV, cursp(), sym);
2430       push();
2431     }
2432     break;
2433 
2434   case NODE_ARG:
2435     /* should not happen */
2436     break;
2437 
2438   case NODE_BLOCK_ARG:
2439     codegen(s, tree, val);
2440     break;
2441 
2442   case NODE_INT:
2443     if (val) {
2444       char *p = (char*)tree->car;
2445       int base = nint(tree->cdr->car);
2446       mrb_int i;
2447       mrb_bool overflow;
2448 
2449       i = readint_mrb_int(s, p, base, FALSE, &overflow);
2450 #ifndef MRB_WITHOUT_FLOAT
2451       if (overflow) {
2452         double f = readint_float(s, p, base);
2453         int off = new_lit(s, mrb_float_value(s->mrb, f));
2454 
2455         genop_2(s, OP_LOADL, cursp(), off);
2456       }
2457       else
2458 #endif
2459       {
2460         if (i < 0) {
2461           if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2462           else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2463           else if (i >= -0x8000) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
2464           else goto lit_int;
2465         }
2466         else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
2467         else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
2468         else if (i <= 0x7fff) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
2469         else {
2470           int off;
2471 
2472         lit_int:
2473           off = new_lit(s, mrb_fixnum_value(i));
2474           genop_2(s, OP_LOADL, cursp(), off);
2475         }
2476       }
2477       push();
2478     }
2479     break;
2480 
2481 #ifndef MRB_WITHOUT_FLOAT
2482   case NODE_FLOAT:
2483     if (val) {
2484       char *p = (char*)tree;
2485       mrb_float f = mrb_float_read(p, NULL);
2486       int off = new_lit(s, mrb_float_value(s->mrb, f));
2487 
2488       genop_2(s, OP_LOADL, cursp(), off);
2489       push();
2490     }
2491     break;
2492 #endif
2493 
2494   case NODE_NEGATE:
2495     {
2496       nt = nint(tree->car);
2497       switch (nt) {
2498 #ifndef MRB_WITHOUT_FLOAT
2499       case NODE_FLOAT:
2500         if (val) {
2501           char *p = (char*)tree->cdr;
2502           mrb_float f = mrb_float_read(p, NULL);
2503           int off = new_lit(s, mrb_float_value(s->mrb, -f));
2504 
2505           genop_2(s, OP_LOADL, cursp(), off);
2506           push();
2507         }
2508         break;
2509 #endif
2510 
2511       case NODE_INT:
2512         if (val) {
2513           char *p = (char*)tree->cdr->car;
2514           int base = nint(tree->cdr->cdr->car);
2515           mrb_int i;
2516           mrb_bool overflow;
2517 
2518           i = readint_mrb_int(s, p, base, TRUE, &overflow);
2519 #ifndef MRB_WITHOUT_FLOAT
2520           if (overflow) {
2521             double f = readint_float(s, p, base);
2522             int off = new_lit(s, mrb_float_value(s->mrb, -f));
2523 
2524             genop_2(s, OP_LOADL, cursp(), off);
2525           }
2526           else {
2527 #endif
2528             if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2529             else if (i >= -0xff) {
2530               genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2531             }
2532             else if (i >= -0x8000) {
2533               genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
2534             }
2535             else {
2536               int off = new_lit(s, mrb_fixnum_value(i));
2537               genop_2(s, OP_LOADL, cursp(), off);
2538             }
2539 #ifndef MRB_WITHOUT_FLOAT
2540           }
2541 #endif
2542           push();
2543         }
2544         break;
2545 
2546       default:
2547         if (val) {
2548           int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
2549           codegen(s, tree, VAL);
2550           pop();
2551           genop_3(s, OP_SEND, cursp(), sym, 0);
2552           push();
2553         }
2554         else {
2555           codegen(s, tree, NOVAL);
2556         }
2557         break;
2558       }
2559     }
2560     break;
2561 
2562   case NODE_STR:
2563     if (val) {
2564       char *p = (char*)tree->car;
2565       size_t len = (intptr_t)tree->cdr;
2566       int ai = mrb_gc_arena_save(s->mrb);
2567       int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2568 
2569       mrb_gc_arena_restore(s->mrb, ai);
2570       genop_2(s, OP_STRING, cursp(), off);
2571       push();
2572     }
2573     break;
2574 
2575   case NODE_HEREDOC:
2576     tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2577     /* fall through */
2578   case NODE_DSTR:
2579     if (val) {
2580       node *n = tree;
2581 
2582       if (!n) {
2583         genop_1(s, OP_LOADNIL, cursp());
2584         push();
2585         break;
2586       }
2587       codegen(s, n->car, VAL);
2588       n = n->cdr;
2589       while (n) {
2590         codegen(s, n->car, VAL);
2591         pop(); pop();
2592         genop_1(s, OP_STRCAT, cursp());
2593         push();
2594         n = n->cdr;
2595       }
2596     }
2597     else {
2598       node *n = tree;
2599 
2600       while (n) {
2601         if (nint(n->car->car) != NODE_STR) {
2602           codegen(s, n->car, NOVAL);
2603         }
2604         n = n->cdr;
2605       }
2606     }
2607     break;
2608 
2609   case NODE_WORDS:
2610     gen_literal_array(s, tree, FALSE, val);
2611     break;
2612 
2613   case NODE_SYMBOLS:
2614     gen_literal_array(s, tree, TRUE, val);
2615     break;
2616 
2617   case NODE_DXSTR:
2618     {
2619       node *n;
2620       int ai = mrb_gc_arena_save(s->mrb);
2621       int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2622 
2623       genop_1(s, OP_LOADSELF, cursp());
2624       push();
2625       codegen(s, tree->car, VAL);
2626       n = tree->cdr;
2627       while (n) {
2628         if (nint(n->car->car) == NODE_XSTR) {
2629           n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2630           mrb_assert(!n->cdr); /* must be the end */
2631         }
2632         codegen(s, n->car, VAL);
2633         pop(); pop();
2634         genop_1(s, OP_STRCAT, cursp());
2635         push();
2636         n = n->cdr;
2637       }
2638       push();                   /* for block */
2639       pop_n(3);
2640       sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2641       genop_3(s, OP_SEND, cursp(), sym, 1);
2642       if (val) push();
2643       mrb_gc_arena_restore(s->mrb, ai);
2644     }
2645     break;
2646 
2647   case NODE_XSTR:
2648     {
2649       char *p = (char*)tree->car;
2650       size_t len = (intptr_t)tree->cdr;
2651       int ai = mrb_gc_arena_save(s->mrb);
2652       int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2653       int sym;
2654 
2655       genop_1(s, OP_LOADSELF, cursp());
2656       push();
2657       genop_2(s, OP_STRING, cursp(), off);
2658       push(); push();
2659       pop_n(3);
2660       sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2661       genop_3(s, OP_SEND, cursp(), sym, 1);
2662       if (val) push();
2663       mrb_gc_arena_restore(s->mrb, ai);
2664     }
2665     break;
2666 
2667   case NODE_REGX:
2668     if (val) {
2669       char *p1 = (char*)tree->car;
2670       char *p2 = (char*)tree->cdr->car;
2671       char *p3 = (char*)tree->cdr->cdr;
2672       int ai = mrb_gc_arena_save(s->mrb);
2673       int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2674       int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2675       int argc = 1;
2676 
2677       genop_1(s, OP_OCLASS, cursp());
2678       genop_2(s, OP_GETMCNST, cursp(), sym);
2679       push();
2680       genop_2(s, OP_STRING, cursp(), off);
2681       push();
2682       if (p2 || p3) {
2683         if (p2) { /* opt */
2684           off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2685           genop_2(s, OP_STRING, cursp(), off);
2686         }
2687         else {
2688           genop_1(s, OP_LOADNIL, cursp());
2689         }
2690         push();
2691         argc++;
2692         if (p3) { /* enc */
2693           off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2694           genop_2(s, OP_STRING, cursp(), off);
2695           push();
2696           argc++;
2697         }
2698       }
2699       push(); /* space for a block */
2700       pop_n(argc+2);
2701       sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2702       genop_3(s, OP_SEND, cursp(), sym, argc);
2703       mrb_gc_arena_restore(s->mrb, ai);
2704       push();
2705     }
2706     break;
2707 
2708   case NODE_DREGX:
2709     if (val) {
2710       node *n = tree->car;
2711       int ai = mrb_gc_arena_save(s->mrb);
2712       int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2713       int argc = 1;
2714       int off;
2715       char *p;
2716 
2717       genop_1(s, OP_OCLASS, cursp());
2718       genop_2(s, OP_GETMCNST, cursp(), sym);
2719       push();
2720       codegen(s, n->car, VAL);
2721       n = n->cdr;
2722       while (n) {
2723         codegen(s, n->car, VAL);
2724         pop(); pop();
2725         genop_1(s, OP_STRCAT, cursp());
2726         push();
2727         n = n->cdr;
2728       }
2729       n = tree->cdr->cdr;
2730       if (n->car) { /* tail */
2731         p = (char*)n->car;
2732         off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2733         codegen(s, tree->car, VAL);
2734         genop_2(s, OP_STRING, cursp(), off);
2735         pop();
2736         genop_1(s, OP_STRCAT, cursp());
2737         push();
2738       }
2739       if (n->cdr->car) { /* opt */
2740         char *p2 = (char*)n->cdr->car;
2741         off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2742         genop_2(s, OP_STRING, cursp(), off);
2743         push();
2744         argc++;
2745       }
2746       if (n->cdr->cdr) { /* enc */
2747         char *p2 = (char*)n->cdr->cdr;
2748         off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2749         genop_2(s, OP_STRING, cursp(), off);
2750         push();
2751         argc++;
2752       }
2753       push(); /* space for a block */
2754       pop_n(argc+2);
2755       sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2756       genop_3(s, OP_SEND, cursp(), sym, argc);
2757       mrb_gc_arena_restore(s->mrb, ai);
2758       push();
2759     }
2760     else {
2761       node *n = tree->car;
2762 
2763       while (n) {
2764         if (nint(n->car->car) != NODE_STR) {
2765           codegen(s, n->car, NOVAL);
2766         }
2767         n = n->cdr;
2768       }
2769     }
2770     break;
2771 
2772   case NODE_SYM:
2773     if (val) {
2774       int sym = new_sym(s, nsym(tree));
2775 
2776       genop_2(s, OP_LOADSYM, cursp(), sym);
2777       push();
2778     }
2779     break;
2780 
2781   case NODE_DSYM:
2782     codegen(s, tree, val);
2783     if (val) {
2784       gen_intern(s);
2785     }
2786     break;
2787 
2788   case NODE_SELF:
2789     if (val) {
2790       genop_1(s, OP_LOADSELF, cursp());
2791       push();
2792     }
2793     break;
2794 
2795   case NODE_NIL:
2796     if (val) {
2797       genop_1(s, OP_LOADNIL, cursp());
2798       push();
2799     }
2800     break;
2801 
2802   case NODE_TRUE:
2803     if (val) {
2804       genop_1(s, OP_LOADT, cursp());
2805       push();
2806     }
2807     break;
2808 
2809   case NODE_FALSE:
2810     if (val) {
2811       genop_1(s, OP_LOADF, cursp());
2812       push();
2813     }
2814     break;
2815 
2816   case NODE_ALIAS:
2817     {
2818       int a = new_sym(s, nsym(tree->car));
2819       int b = new_sym(s, nsym(tree->cdr));
2820 
2821       genop_2(s, OP_ALIAS, a, b);
2822       if (val) {
2823         genop_1(s, OP_LOADNIL, cursp());
2824         push();
2825       }
2826     }
2827    break;
2828 
2829   case NODE_UNDEF:
2830     {
2831       node *t = tree;
2832 
2833       while (t) {
2834         int symbol = new_sym(s, nsym(t->car));
2835         genop_1(s, OP_UNDEF, symbol);
2836         t = t->cdr;
2837       }
2838       if (val) {
2839         genop_1(s, OP_LOADNIL, cursp());
2840         push();
2841       }
2842     }
2843     break;
2844 
2845   case NODE_CLASS:
2846     {
2847       int idx;
2848       node *body;
2849 
2850       if (tree->car->car == (node*)0) {
2851         genop_1(s, OP_LOADNIL, cursp());
2852         push();
2853       }
2854       else if (tree->car->car == (node*)1) {
2855         genop_1(s, OP_OCLASS, cursp());
2856         push();
2857       }
2858       else {
2859         codegen(s, tree->car->car, VAL);
2860       }
2861       if (tree->cdr->car) {
2862         codegen(s, tree->cdr->car, VAL);
2863       }
2864       else {
2865         genop_1(s, OP_LOADNIL, cursp());
2866         push();
2867       }
2868       pop(); pop();
2869       idx = new_sym(s, nsym(tree->car->cdr));
2870       genop_2(s, OP_CLASS, cursp(), idx);
2871       body = tree->cdr->cdr->car;
2872       if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
2873         genop_1(s, OP_LOADNIL, cursp());
2874       }
2875       else {
2876         idx = scope_body(s, body, val);
2877         genop_2(s, OP_EXEC, cursp(), idx);
2878       }
2879       if (val) {
2880         push();
2881       }
2882     }
2883     break;
2884 
2885   case NODE_MODULE:
2886     {
2887       int idx;
2888 
2889       if (tree->car->car == (node*)0) {
2890         genop_1(s, OP_LOADNIL, cursp());
2891         push();
2892       }
2893       else if (tree->car->car == (node*)1) {
2894         genop_1(s, OP_OCLASS, cursp());
2895         push();
2896       }
2897       else {
2898         codegen(s, tree->car->car, VAL);
2899       }
2900       pop();
2901       idx = new_sym(s, nsym(tree->car->cdr));
2902       genop_2(s, OP_MODULE, cursp(), idx);
2903       if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2904           tree->cdr->car->cdr->cdr == NULL) {
2905         genop_1(s, OP_LOADNIL, cursp());
2906       }
2907       else {
2908         idx = scope_body(s, tree->cdr->car, val);
2909         genop_2(s, OP_EXEC, cursp(), idx);
2910       }
2911       if (val) {
2912         push();
2913       }
2914     }
2915     break;
2916 
2917   case NODE_SCLASS:
2918     {
2919       int idx;
2920 
2921       codegen(s, tree->car, VAL);
2922       pop();
2923       genop_1(s, OP_SCLASS, cursp());
2924       if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2925           tree->cdr->car->cdr->cdr == NULL) {
2926         genop_1(s, OP_LOADNIL, cursp());
2927       }
2928       else {
2929         idx = scope_body(s, tree->cdr->car, val);
2930         genop_2(s, OP_EXEC, cursp(), idx);
2931       }
2932       if (val) {
2933         push();
2934       }
2935     }
2936     break;
2937 
2938   case NODE_DEF:
2939     {
2940       int sym = new_sym(s, nsym(tree->car));
2941       int idx = lambda_body(s, tree->cdr, 0);
2942 
2943       genop_1(s, OP_TCLASS, cursp());
2944       push();
2945       genop_2(s, OP_METHOD, cursp(), idx);
2946       push(); pop();
2947       pop();
2948       genop_2(s, OP_DEF, cursp(), sym);
2949       if (val) {
2950         genop_2(s, OP_LOADSYM, cursp(), sym);
2951         push();
2952       }
2953     }
2954     break;
2955 
2956   case NODE_SDEF:
2957     {
2958       node *recv = tree->car;
2959       int sym = new_sym(s, nsym(tree->cdr->car));
2960       int idx = lambda_body(s, tree->cdr->cdr, 0);
2961 
2962       codegen(s, recv, VAL);
2963       pop();
2964       genop_1(s, OP_SCLASS, cursp());
2965       push();
2966       genop_2(s, OP_METHOD, cursp(), idx);
2967       pop();
2968       genop_2(s, OP_DEF, cursp(), sym);
2969       if (val) {
2970         genop_2(s, OP_LOADSYM, cursp(), sym);
2971         push();
2972       }
2973     }
2974     break;
2975 
2976   case NODE_POSTEXE:
2977     codegen(s, tree, NOVAL);
2978     break;
2979 
2980   default:
2981     break;
2982   }
2983  exit:
2984   s->rlev = rlev;
2985 }
2986 
2987 static void
scope_add_irep(codegen_scope * s,mrb_irep * irep)2988 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2989 {
2990   if (s->irep == NULL) {
2991     s->irep = irep;
2992     return;
2993   }
2994   if (s->irep->rlen == s->rcapa) {
2995     s->rcapa *= 2;
2996     s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2997   }
2998   s->irep->reps[s->irep->rlen] = irep;
2999   s->irep->rlen++;
3000 }
3001 
3002 static codegen_scope*
scope_new(mrb_state * mrb,codegen_scope * prev,node * lv)3003 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
3004 {
3005   static const codegen_scope codegen_scope_zero = { 0 };
3006   mrb_pool *pool = mrb_pool_open(mrb);
3007   codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
3008 
3009   if (!p) {
3010     if (prev)
3011       codegen_error(prev, "unexpected scope");
3012     return NULL;
3013   }
3014   *p = codegen_scope_zero;
3015   p->mrb = mrb;
3016   p->mpool = pool;
3017   if (!prev) return p;
3018   p->prev = prev;
3019   p->ainfo = -1;
3020   p->mscope = 0;
3021 
3022   p->irep = mrb_add_irep(mrb);
3023   scope_add_irep(prev, p->irep);
3024 
3025   p->rcapa = 8;
3026   p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
3027 
3028   p->icapa = 1024;
3029   p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
3030   p->irep->iseq = NULL;
3031 
3032   p->pcapa = 32;
3033   p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
3034   p->irep->plen = 0;
3035 
3036   p->scapa = 256;
3037   p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
3038   p->irep->slen = 0;
3039 
3040   p->lv = lv;
3041   p->sp += node_len(lv)+1;        /* add self */
3042   p->nlocals = p->sp;
3043   if (lv) {
3044     node *n = lv;
3045     size_t i = 0;
3046 
3047     p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
3048     for (i=0, n=lv; n; i++,n=n->cdr) {
3049       p->irep->lv[i].name = lv_name(n);
3050       if (lv_name(n)) {
3051         p->irep->lv[i].r = lv_idx(p, lv_name(n));
3052       }
3053       else {
3054         p->irep->lv[i].r = 0;
3055       }
3056     }
3057     mrb_assert(i + 1 == p->nlocals);
3058   }
3059   p->ai = mrb_gc_arena_save(mrb);
3060 
3061   p->filename_sym = prev->filename_sym;
3062   if (p->filename_sym) {
3063     p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
3064   }
3065   p->lineno = prev->lineno;
3066 
3067   /* debug setting */
3068   p->debug_start_pos = 0;
3069   if (p->filename_sym) {
3070     mrb_debug_info_alloc(mrb, p->irep);
3071   }
3072   else {
3073     p->irep->debug_info = NULL;
3074   }
3075   p->parser = prev->parser;
3076   p->filename_index = prev->filename_index;
3077 
3078   p->rlev = prev->rlev+1;
3079 
3080   return p;
3081 }
3082 
3083 static void
scope_finish(codegen_scope * s)3084 scope_finish(codegen_scope *s)
3085 {
3086   mrb_state *mrb = s->mrb;
3087   mrb_irep *irep = s->irep;
3088 
3089   if (s->nlocals >= 0x3ff) {
3090     codegen_error(s, "too many local variables");
3091   }
3092   irep->flags = 0;
3093   if (s->iseq) {
3094     irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
3095     irep->ilen = s->pc;
3096   }
3097   irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
3098   irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
3099   irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
3100   if (s->filename_sym) {
3101     mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
3102     const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
3103 
3104     mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3105                                filename, s->lines, s->debug_start_pos, s->pc);
3106   }
3107   mrb_free(s->mrb, s->lines);
3108 
3109   irep->nlocals = s->nlocals;
3110   irep->nregs = s->nregs;
3111 
3112   mrb_gc_arena_restore(mrb, s->ai);
3113   mrb_pool_close(s->mpool);
3114 }
3115 
3116 static struct loopinfo*
loop_push(codegen_scope * s,enum looptype t)3117 loop_push(codegen_scope *s, enum looptype t)
3118 {
3119   struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
3120 
3121   p->type = t;
3122   p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
3123   p->prev = s->loop;
3124   p->ensure_level = s->ensure_level;
3125   p->acc = cursp();
3126   s->loop = p;
3127 
3128   return p;
3129 }
3130 
3131 static void
loop_break(codegen_scope * s,node * tree)3132 loop_break(codegen_scope *s, node *tree)
3133 {
3134   if (!s->loop) {
3135     codegen(s, tree, NOVAL);
3136     raise_error(s, "unexpected break");
3137   }
3138   else {
3139     struct loopinfo *loop;
3140     int n = 0;
3141 
3142     if (tree) {
3143       gen_retval(s, tree);
3144     }
3145 
3146     loop = s->loop;
3147     while (loop) {
3148       if (loop->type == LOOP_BEGIN) {
3149         n++;
3150         loop = loop->prev;
3151       }
3152       else if (loop->type == LOOP_RESCUE) {
3153         loop = loop->prev;
3154       }
3155       else{
3156         break;
3157       }
3158     }
3159     if (!loop) {
3160       raise_error(s, "unexpected break");
3161       return;
3162     }
3163     if (n > 0) {
3164       genop_1(s, OP_POPERR, n);
3165     }
3166 
3167     if (loop->type == LOOP_NORMAL) {
3168       int tmp;
3169 
3170       if (s->ensure_level > s->loop->ensure_level) {
3171         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
3172       }
3173       if (tree) {
3174         gen_move(s, loop->acc, cursp(), 0);
3175       }
3176       tmp = genjmp(s, OP_JMP, loop->pc3);
3177       loop->pc3 = tmp;
3178     }
3179     else {
3180       if (!tree) {
3181         genop_1(s, OP_LOADNIL, cursp());
3182       }
3183       gen_return(s, OP_BREAK, cursp());
3184     }
3185   }
3186 }
3187 
3188 static void
loop_pop(codegen_scope * s,int val)3189 loop_pop(codegen_scope *s, int val)
3190 {
3191   if (val) {
3192     genop_1(s, OP_LOADNIL, cursp());
3193   }
3194   dispatch_linked(s, s->loop->pc3);
3195   s->loop = s->loop->prev;
3196   if (val) push();
3197 }
3198 
3199 static struct RProc*
generate_code(mrb_state * mrb,parser_state * p,int val)3200 generate_code(mrb_state *mrb, parser_state *p, int val)
3201 {
3202   codegen_scope *scope = scope_new(mrb, 0, 0);
3203   struct RProc *proc;
3204   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3205 
3206   scope->mrb = mrb;
3207   scope->parser = p;
3208   scope->filename_sym = p->filename_sym;
3209   scope->filename_index = p->current_filename_index;
3210 
3211   MRB_TRY(&scope->jmp) {
3212     mrb->jmp = &scope->jmp;
3213     /* prepare irep */
3214     codegen(scope, p->tree, val);
3215     proc = mrb_proc_new(mrb, scope->irep);
3216     mrb_irep_decref(mrb, scope->irep);
3217     mrb_pool_close(scope->mpool);
3218     proc->c = NULL;
3219     if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
3220       proc->upper = NULL;
3221     }
3222     mrb->jmp = prev_jmp;
3223     return proc;
3224   }
3225   MRB_CATCH(&scope->jmp) {
3226     mrb_irep_decref(mrb, scope->irep);
3227     mrb_pool_close(scope->mpool);
3228     mrb->jmp = prev_jmp;
3229     return NULL;
3230   }
3231   MRB_END_EXC(&scope->jmp);
3232 }
3233 
3234 MRB_API struct RProc*
mrb_generate_code(mrb_state * mrb,parser_state * p)3235 mrb_generate_code(mrb_state *mrb, parser_state *p)
3236 {
3237   return generate_code(mrb, p, VAL);
3238 }
3239 
3240 void
mrb_irep_remove_lv(mrb_state * mrb,mrb_irep * irep)3241 mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
3242 {
3243   int i;
3244 
3245   if (irep->lv) {
3246     mrb_free(mrb, irep->lv);
3247     irep->lv = NULL;
3248   }
3249 
3250   for (i = 0; i < irep->rlen; ++i) {
3251     mrb_irep_remove_lv(mrb, irep->reps[i]);
3252   }
3253 }
3254 
3255 #undef OPCODE
3256 #define Z 1
3257 #define S 3
3258 #define W 4
3259 /* instruction sizes */
3260 uint8_t mrb_insn_size[] = {
3261 #define B 2
3262 #define BB 3
3263 #define BBB 4
3264 #define BS 4
3265 #define SB 4
3266 #define OPCODE(_,x) x,
3267 #include "mruby/ops.h"
3268 #undef OPCODE
3269 #undef B
3270 #undef BB
3271 #undef BS
3272 #undef SB
3273 #undef BBB
3274 };
3275 /* EXT1 instruction sizes */
3276 uint8_t mrb_insn_size1[] = {
3277 #define B 3
3278 #define BB 4
3279 #define BBB 5
3280 #define BS 5
3281 #define SB 5
3282 #define OPCODE(_,x) x,
3283 #include "mruby/ops.h"
3284 #undef OPCODE
3285 #undef B
3286 };
3287 /* EXT2 instruction sizes */
3288 uint8_t mrb_insn_size2[] = {
3289 #define B 2
3290 #define OPCODE(_,x) x,
3291 #include "mruby/ops.h"
3292 #undef OPCODE
3293 #undef BB
3294 #undef BBB
3295 #undef BS
3296 #undef SB
3297 };
3298 /* EXT3 instruction sizes */
3299 #define BB 5
3300 #define BBB 6
3301 #define BS 4
3302 #define SB 5
3303 uint8_t mrb_insn_size3[] = {
3304 #define OPCODE(_,x) x,
3305 #include "mruby/ops.h"
3306 };
3307