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