2 ** codegen.c - mruby code generator
4 ** See Copyright Notice in 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>
19 #include <mruby/opcode.h>
21 #include <mruby/throw.h>
23 #ifndef MRB_CODEGEN_LEVEL_MAX
24 #define MRB_CODEGEN_LEVEL_MAX 1024
27 #define MAXARG_S (1<<16)
29 typedef mrb_ast_node node;
30 typedef struct mrb_parser_state parser_state;
42 int pc0, pc1, pc2, pc3, acc;
44 struct loopinfo *prev;
47 typedef struct scope {
50 struct mrb_jmpbuf jmp;
63 struct loopinfo *loop;
73 uint32_t pcapa, scapa, rcapa;
80 uint16_t filename_index;
83 int rlev; /* recursion levels */
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);
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);
95 static void codegen(codegen_scope *s, node *tree, int val);
96 static void raise_error(codegen_scope *s, const char *msg);
99 codegen_error(codegen_scope *s, const char *message)
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);
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);
115 fprintf(stderr, "codegen error: %s\n", message);
122 codegen_palloc(codegen_scope *s, size_t len)
124 void *p = mrb_pool_alloc(s->mpool, len);
126 if (!p) codegen_error(s, "pool memory allocation");
131 codegen_realloc(codegen_scope *s, void *p, size_t len)
133 p = mrb_realloc_simple(s->mrb, p, len);
135 if (!p && len > 0) codegen_error(s, "mrb_realloc");
140 new_label(codegen_scope *s)
142 return s->lastlabel = s->pc;
146 emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
148 if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
149 codegen_error(s, "too big code block");
151 if (pc >= s->icapa) {
153 if (s->icapa > MAXARG_S) {
156 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
158 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
162 if (s->lineno > 0 || pc == 0)
163 s->lines[pc] = s->lineno;
165 s->lines[pc] = s->lines[pc-1];
171 emit_S(codegen_scope *s, int pc, uint16_t i)
181 gen_B(codegen_scope *s, uint8_t i)
188 gen_S(codegen_scope *s, uint16_t i)
195 genop_0(codegen_scope *s, mrb_code i)
202 genop_1(codegen_scope *s, mrb_code i, uint16_t a)
212 gen_B(s, (uint8_t)a);
217 genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
220 if (a > 0xff && b > 0xff) {
229 gen_B(s, (uint8_t)a);
236 gen_B(s, (uint8_t)b);
240 gen_B(s, (uint8_t)a);
241 gen_B(s, (uint8_t)b);
246 genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
253 genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
260 genop_W(codegen_scope *s, mrb_code i, uint32_t a)
262 uint8_t a1 = (a>>16) & 0xff;
263 uint8_t a2 = (a>>8) & 0xff;
264 uint8_t a3 = a & 0xff;
277 no_optimize(codegen_scope *s)
279 if (s && s->parser && s->parser->no_optimize)
285 mrb_decode_insn(const mrb_code *pc)
287 struct mrb_insn_data data = { 0 };
288 mrb_code insn = READ_B();
294 #define FETCH_Z() /* empty */
295 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
296 #include "mruby/ops.h"
303 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
304 #include "mruby/ops.h"
311 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
312 #include "mruby/ops.h"
319 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
320 #include "mruby/ops.h"
334 static struct mrb_insn_data
335 mrb_last_insn(codegen_scope *s)
337 if (s->pc == s->lastpc) {
338 struct mrb_insn_data data;
343 return mrb_decode_insn(&s->iseq[s->lastpc]);
347 no_peephole(codegen_scope *s)
349 return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
353 genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
365 genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
369 if (!no_peephole(s) && !val) {
370 struct mrb_insn_data data = mrb_last_insn(s);
372 if (data.insn == OP_MOVE && data.a == a) {
388 gen_B(s, (uint8_t)a);
396 gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
398 if (no_peephole(s)) {
400 genop_2(s, OP_MOVE, dst, src);
404 struct mrb_insn_data data = mrb_last_insn(s);
408 if (dst == src) return; /* remove useless MOVE */
409 if (data.b == dst && data.a == src) /* skip swapping MOVE */
412 case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
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;
418 genop_1(s, data.insn, dst);
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;
426 genop_2(s, data.insn, dst, data.b);
435 gen_return(codegen_scope *s, uint8_t op, uint16_t src)
437 if (no_peephole(s)) {
441 struct mrb_insn_data data = mrb_last_insn(s);
443 if (data.insn == OP_MOVE && src == data.a) {
445 genop_1(s, op, data.b);
447 else if (data.insn != OP_RETURN) {
454 gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
456 if (no_peephole(s)) {
462 struct mrb_insn_data data = mrb_last_insn(s);
466 if (op == OP_ADD) op = OP_SUB;
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;
476 if (data.b >= 128) goto normal;
479 genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
482 genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
492 dispatch(codegen_scope *s, uint16_t pos0)
496 s->lastlabel = s->pc;
497 newpos = PEEK_S(s->iseq+pos0);
498 emit_S(s, pos0, s->pc);
503 dispatch_linked(codegen_scope *s, uint16_t pos)
507 pos = dispatch(s, pos);
512 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
514 push_n_(codegen_scope *s, int n)
516 if (s->sp+n >= 0xffff) {
517 codegen_error(s, "too complex expression");
524 pop_n_(codegen_scope *s, int n)
526 if ((int)s->sp-n < 0) {
527 codegen_error(s, "stack pointer underflow");
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)
539 new_lit(codegen_scope *s, mrb_value val)
544 switch (mrb_type(val)) {
546 for (i=0; i<s->irep->plen; i++) {
548 pv = &s->irep->pool[i];
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)
556 #ifndef MRB_WITHOUT_FLOAT
558 for (i=0; i<s->irep->plen; i++) {
560 pv = &s->irep->pool[i];
561 if (!mrb_float_p(*pv)) continue;
564 if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
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;
576 /* should not happen */
580 if (s->irep->plen == s->pcapa) {
582 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
585 pv = &s->irep->pool[s->irep->plen];
588 switch (mrb_type(val)) {
590 *pv = mrb_str_pool(s->mrb, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(val)));
593 #ifndef MRB_WITHOUT_FLOAT
595 #ifdef MRB_WORD_BOXING
596 *pv = mrb_float_pool(s->mrb, mrb_float(val));
605 /* should not happen */
611 /* maximum symbol numbers */
612 #define MAXSYMLEN 0x10000
615 new_sym(codegen_scope *s, mrb_sym sym)
622 for (i=0; i<len; i++) {
623 if (s->irep->syms[i] == sym) return i;
625 if (s->irep->slen >= s->scapa) {
627 s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
629 s->irep->syms[s->irep->slen] = sym;
630 return s->irep->slen++;
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))
649 #define lv_name(lv) nsym((lv)->car)
652 lv_idx(codegen_scope *s, mrb_sym id)
658 if (lv_name(lv) == id) return n;
666 search_upvar(codegen_scope *s, mrb_sym id, int *idx)
670 codegen_scope *up = s->prev;
673 *idx = lv_idx(up, id);
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 ++) {
693 if (MRB_PROC_SCOPE_P(u)) break;
698 codegen_error(s, "Can't found local variables");
699 return -1; /* not reached */
703 for_body(codegen_scope *s, node *tree)
705 codegen_scope *prev = s;
710 /* generate receiver */
711 codegen(s, tree->cdr->car, VAL);
712 /* generate loop-block */
713 s = scope_new(s->mrb, s, NULL);
715 push(); /* push for a block parameter */
717 /* generate loop variable */
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);
724 gen_vmassignment(s, n2, 1, VAL);
727 lp = loop_push(s, LOOP_FOR);
728 lp->pc2 = new_label(s);
731 codegen(s, tree->cdr->cdr->car, VAL);
733 gen_return(s, OP_RETURN, cursp());
737 genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
738 push();pop(); /* space for a block */
740 idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
741 genop_3(s, OP_SENDB, cursp(), idx, 0);
745 lambda_body(codegen_scope *s, node *tree, int blk)
747 codegen_scope *parent = s;
748 s = scope_new(s->mrb, s, tree->car);
753 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
754 lp->pc0 = new_label(s);
757 if (tree->car == NULL) {
758 genop_W(s, OP_ENTER, 0);
762 int ma, oa, ra, pa, ka, kd, ba;
768 /* mandatory arguments */
769 ma = node_len(tree->car->car);
770 margs = tree->car->car;
771 tail = tree->car->cdr->cdr->cdr->cdr;
773 /* optional arguments */
774 oa = node_len(tree->car->cdr->car);
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;
787 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
788 codegen_error(s, "too many formal arguments");
792 | (ra? MRB_ARGS_REST() : 0)
794 | MRB_ARGS_KEY(ka, kd)
795 | (ba? MRB_ARGS_BLOCK() : 0);
796 s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
799 | ((ka | kd) != 0 ? 0x01 : 0x00);
800 genop_W(s, OP_ENTER, a);
801 /* generate jump table for optional arguments initializer */
803 for (i=0; i<oa; i++) {
805 genjmp(s, OP_JMP, 0);
808 genjmp(s, OP_JMP, 0);
810 opt = tree->car->cdr->car;
814 mrb_sym id = nsym(opt->car->car);
816 dispatch(s, pos+i*3+1);
817 codegen(s, opt->car->cdr, VAL);
821 gen_move(s, idx, cursp(), 0);
824 int lv = search_upvar(s, id, &idx);
825 genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
831 dispatch(s, pos+i*3+1);
834 /* keyword arguments */
836 node *kwds = tail->cdr->car;
839 if (tail->cdr->cdr->car) {
842 mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
843 mrb_assert(node_len(tail) == 4);
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);
850 mrb_assert(nint(kwd->car) == NODE_KW_ARG);
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);
858 idx = lv_idx(s, kwd_sym);
860 gen_move(s, idx, cursp(), 0);
863 int lv = search_upvar(s, kwd_sym, &idx);
864 genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
866 jmp_def_set = genjmp(s, OP_JMP, 0);
867 dispatch(s, jmpif_key_p);
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);
877 if (tail->cdr->car && !kwrest) {
878 genop_0(s, OP_KEYEND);
882 /* argument destructuring */
888 if (nint(n->car->car) == NODE_MASGN) {
889 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
900 if (nint(n->car->car) == NODE_MASGN) {
901 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
909 codegen(s, tree->cdr->car, VAL);
912 gen_return(s, OP_RETURN, cursp());
918 return parent->irep->rlen - 1;
922 scope_body(codegen_scope *s, node *tree, int val)
924 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
926 codegen(scope, tree->cdr, VAL);
927 gen_return(scope, OP_RETURN, scope->sp-1);
929 genop_0(scope, OP_STOP);
933 /* should not happen */
936 return s->irep->rlen - 1;
943 if (nint(t->car->car) == NODE_SPLAT) return FALSE;
950 attrsym(codegen_scope *s, mrb_sym a)
956 name = mrb_sym_name_len(s->mrb, a, &len);
957 name2 = (char *)codegen_palloc(s,
962 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
963 memcpy(name2, name, (size_t)len);
967 return mrb_intern(s->mrb, name2, len+1);
970 #define CALL_MAXARGS 127
973 gen_values(codegen_scope *s, node *t, int val, int extra)
979 is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
981 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
984 if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
985 codegen(s, t->car->cdr, VAL);
990 if (n == 0 && is_splat) {
991 genop_1(s, OP_LOADNIL, cursp());
994 genop_2(s, OP_ARRAY, cursp(), n);
997 codegen(s, t->car, VAL);
1000 genop_1(s, OP_ARYCAT, cursp());
1003 genop_1(s, OP_ARYPUSH, cursp());
1009 codegen(s, t->car, VAL);
1011 if (nint(t->car->car) == NODE_SPLAT) {
1012 genop_1(s, OP_ARYCAT, cursp());
1015 genop_1(s, OP_ARYPUSH, cursp());
1022 codegen(s, t->car, NOVAL);
1028 /* normal (no splat) mode */
1029 codegen(s, t->car, val);
1037 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
1039 mrb_sym sym = name ? name : nsym(tree->cdr->car);
1041 int n = 0, noop = 0, sendv = 0, blk = 0;
1043 codegen(s, tree->car, VAL); /* receiver */
1045 int recv = cursp()-1;
1046 gen_move(s, cursp(), recv, 1);
1047 skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1049 tree = tree->cdr->cdr->car;
1051 n = gen_values(s, tree->car, VAL, sp?1:0);
1053 n = noop = sendv = 1;
1057 if (sp) { /* last argument pushed (attr=) */
1059 gen_move(s, cursp(), sp, 0);
1061 genop_1(s, OP_ARYPUSH, cursp());
1065 gen_move(s, cursp(), sp, 0);
1070 if (tree && tree->cdr) {
1072 codegen(s, tree->cdr, VAL);
1080 const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
1082 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
1083 gen_addsub(s, OP_ADD, cursp());
1085 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
1086 gen_addsub(s, OP_SUB, cursp());
1088 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
1089 genop_1(s, OP_MUL, cursp());
1091 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
1092 genop_1(s, OP_DIV, cursp());
1094 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
1095 genop_1(s, OP_LT, cursp());
1097 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
1098 genop_1(s, OP_LE, cursp());
1100 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
1101 genop_1(s, OP_GT, cursp());
1103 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
1104 genop_1(s, OP_GE, cursp());
1106 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
1107 genop_1(s, OP_EQ, cursp());
1110 int idx = new_sym(s, sym);
1113 genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
1116 genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
1129 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
1132 int type = nint(tree->car);
1137 idx = new_sym(s, nsym(tree));
1138 genop_2(s, OP_SETGV, sp, idx);
1142 idx = lv_idx(s, nsym(tree));
1145 gen_move(s, idx, sp, val);
1150 int lv = search_upvar(s, nsym(tree), &idx);
1151 genop_3(s, OP_SETUPVAR, sp, idx, lv);
1156 codegen_error(s, "Can't assign to numbered parameter");
1159 idx = new_sym(s, nsym(tree));
1160 genop_2(s, OP_SETIV, sp, idx);
1163 idx = new_sym(s, nsym(tree));
1164 genop_2(s, OP_SETCV, sp, idx);
1167 idx = new_sym(s, nsym(tree));
1168 genop_2(s, OP_SETCONST, sp, idx);
1171 gen_move(s, cursp(), sp, 0);
1173 codegen(s, tree->car, VAL);
1175 idx = new_sym(s, nsym(tree->cdr));
1176 genop_2(s, OP_SETMCNST, sp, idx);
1182 gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1183 type == NODE_SCALL);
1186 gen_move(s, cursp(), sp, 0);
1191 gen_vmassignment(s, tree->car, sp, val);
1194 /* splat without assignment */
1199 #ifndef MRB_DISABLE_STDIO
1200 fprintf(stderr, "unknown lhs %d\n", type);
1208 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1210 int n = 0, post = 0;
1213 if (tree->car) { /* pre */
1219 genop_3(s, OP_AREF, sp, rhs, n);
1221 gen_assignment(s, t->car, sp, NOVAL);
1229 if (t->cdr) { /* post count */
1236 gen_move(s, cursp(), rhs, val);
1239 genop_3(s, OP_APOST, cursp(), n, post);
1241 if (t->car && t->car != (node*)-1) { /* rest */
1242 gen_assignment(s, t->car, cursp(), NOVAL);
1244 if (t->cdr && t->cdr->car) {
1247 gen_assignment(s, t->car, cursp()+n, NOVAL);
1253 gen_move(s, cursp(), rhs, 0);
1259 gen_intern(codegen_scope *s)
1262 genop_1(s, OP_INTERN, cursp());
1267 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1273 switch (nint(tree->car->car)) {
1275 if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1279 codegen(s, tree->car, VAL);
1283 case NODE_LITERAL_DELIM:
1294 genop_1(s, OP_STRCAT, cursp());
1306 genop_2(s, OP_ARRAY, cursp(), i);
1311 switch (nint(tree->car->car)) {
1312 case NODE_BEGIN: case NODE_BLOCK:
1313 codegen(s, tree->car, NOVAL);
1321 raise_error(codegen_scope *s, const char *msg)
1323 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1325 genop_1(s, OP_ERR, idx);
1328 #ifndef MRB_WITHOUT_FLOAT
1330 readint_float(codegen_scope *s, const char *p, int base)
1332 const char *e = p + strlen(p);
1339 c = tolower((unsigned char)c);
1340 for (n=0; n<base; n++) {
1341 if (mrb_digitmap[n] == c) {
1348 codegen_error(s, "malformed readint input");
1357 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1359 const char *e = p + strlen(p);
1363 mrb_assert(base >= 2 && base <= 36);
1367 c = tolower((unsigned char)c);
1368 for (n=0; n<base; n++) {
1369 if (mrb_digitmap[n] == c) {
1374 codegen_error(s, "malformed readint input");
1378 if ((MRB_INT_MIN + n)/base > result) {
1386 if ((MRB_INT_MAX - n)/base < result) {
1400 gen_retval(codegen_scope *s, node *tree)
1402 if (nint(tree->car) == NODE_SPLAT) {
1403 codegen(s, tree, VAL);
1405 genop_1(s, OP_ARYDUP, cursp());
1408 codegen(s, tree, VAL);
1414 codegen(codegen_scope *s, node *tree, int val)
1421 genop_1(s, OP_LOADNIL, cursp());
1428 if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1429 codegen_error(s, "too complex expression");
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);
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);
1442 nt = nint(tree->car);
1443 s->lineno = tree->lineno;
1448 genop_1(s, OP_LOADNIL, cursp());
1452 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1459 int noexc, exend, pos1, pos2, tmp;
1460 struct loopinfo *lp;
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);
1468 lp->type = LOOP_RESCUE;
1469 noexc = genjmp(s, OP_JMP, 0);
1470 dispatch(s, lp->pc1);
1475 node *n2 = tree->car;
1478 genop_1(s, OP_EXCEPT, exc);
1484 if (pos1) dispatch(s, pos1);
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 */
1492 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1496 codegen(s, n4->car, VAL);
1499 genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
1503 genop_2(s, OP_RESCUE, exc, cursp());
1505 tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
1511 pos1 = genjmp(s, OP_JMP, 0);
1512 dispatch_linked(s, pos2);
1516 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1518 if (n3->cdr->cdr->car) {
1519 codegen(s, n3->cdr->cdr->car, val);
1522 tmp = genjmp(s, OP_JMP, exend);
1529 genop_1(s, OP_RAISE, exc);
1535 genop_1(s, OP_POPERR, 1);
1537 codegen(s, tree->car, val);
1542 dispatch_linked(s, exend);
1548 if (!tree->cdr || !tree->cdr->cdr ||
1549 (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1550 tree->cdr->cdr->cdr)) {
1554 idx = scope_body(s, tree->cdr, NOVAL);
1555 genop_1(s, OP_EPUSH, idx);
1556 codegen(s, tree->car, val);
1558 genop_1(s, OP_EPOP, 1);
1560 else { /* empty ensure ignored */
1561 codegen(s, tree->car, val);
1567 int idx = lambda_body(s, tree, 1);
1569 genop_2(s, OP_LAMBDA, cursp(), idx);
1576 int idx = lambda_body(s, tree, 1);
1578 genop_2(s, OP_BLOCK, cursp(), idx);
1585 int pos1, pos2, nil_p = FALSE;
1586 node *elsepart = tree->cdr->cdr->car;
1589 codegen(s, elsepart, val);
1592 switch (nint(tree->car->car)) {
1596 codegen(s, tree->cdr->car, val);
1600 codegen(s, elsepart, val);
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) {
1609 codegen(s, n->car, VAL);
1615 codegen(s, tree->car, VAL);
1618 if (val || tree->cdr->car) {
1620 pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1621 pos1 = genjmp(s, OP_JMP, 0);
1625 pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1627 codegen(s, tree->cdr->car, val);
1629 if (elsepart || val) {
1630 pos2 = genjmp(s, OP_JMP, 0);
1632 codegen(s, elsepart, val);
1639 else { /* empty then-part */
1642 pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1645 pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1647 codegen(s, elsepart, val);
1650 else if (val && !nil_p) {
1651 genop_1(s, OP_LOADNIL, cursp());
1662 codegen(s, tree->car, VAL);
1664 pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1665 codegen(s, tree->cdr, val);
1674 codegen(s, tree->car, VAL);
1676 pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1677 codegen(s, tree->cdr, val);
1684 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
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);
1693 genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
1701 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
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);
1710 genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
1724 int pos1, pos2, pos3, tmp;
1730 codegen(s, tree->car, VAL);
1737 codegen(s, n->car, VAL);
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);
1745 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
1751 tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
1755 if (tree->car->car) {
1756 pos1 = genjmp(s, OP_JMP, 0);
1757 dispatch_linked(s, pos2);
1759 codegen(s, tree->car->cdr, val);
1761 tmp = genjmp(s, OP_JMP, pos3);
1763 if (pos1) dispatch(s, pos1);
1768 genop_1(s, OP_LOADNIL, cursp());
1769 if (pos3) dispatch_linked(s, pos3);
1771 if (cursp() != pos) {
1772 gen_move(s, cursp(), pos, 0);
1778 dispatch_linked(s, pos3);
1788 scope_body(s, tree, NOVAL);
1793 gen_call(s, tree, 0, 0, val, 0);
1796 gen_call(s, tree, 0, 0, val, 1);
1800 codegen(s, tree->car, val);
1801 codegen(s, tree->cdr, val);
1804 genop_1(s, OP_RANGE_INC, cursp());
1810 codegen(s, tree->car, val);
1811 codegen(s, tree->cdr, val);
1814 genop_1(s, OP_RANGE_EXC, cursp());
1821 int sym = new_sym(s, nsym(tree->cdr));
1823 codegen(s, tree->car, VAL);
1825 genop_2(s, OP_GETMCNST, cursp(), sym);
1832 int sym = new_sym(s, nsym(tree));
1834 genop_1(s, OP_OCLASS, cursp());
1835 genop_2(s, OP_GETMCNST, cursp(), sym);
1844 n = gen_values(s, tree, val, 0);
1848 genop_2(s, OP_ARRAY, cursp(), n);
1862 mrb_bool update = FALSE;
1865 if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1869 genop_2(s, OP_HASH, cursp(), len);
1873 genop_2(s, OP_HASHADD, cursp(), len);
1877 codegen(s, tree->car->cdr, VAL);
1878 if (len > 0 || update) {
1880 genop_1(s, OP_HASHCAT, cursp());
1887 codegen(s, tree->car->car, val);
1888 codegen(s, tree->car->cdr, val);
1892 if (val && cursp() > 127) {
1895 genop_2(s, OP_HASH, cursp(), len);
1899 genop_2(s, OP_HASHADD, cursp(), len);
1909 genop_2(s, OP_HASH, cursp(), len);
1914 genop_2(s, OP_HASHADD, cursp(), len);
1923 codegen(s, tree, val);
1927 codegen(s, tree->cdr, VAL);
1929 gen_assignment(s, tree->car, cursp(), val);
1934 int len = 0, n = 0, post = 0;
1935 node *t = tree->cdr, *p;
1938 if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1942 codegen(s, t->car, VAL);
1947 if (tree->car) { /* pre */
1952 gen_assignment(s, t->car, rhs+n, NOVAL);
1956 genop_1(s, OP_LOADNIL, rhs+n);
1957 gen_assignment(s, t->car, rhs+n, NOVAL);
1964 if (t->cdr) { /* post count */
1971 if (t->car) { /* rest (len - pre - post) */
1974 if (len < post + n) {
1978 rn = len - post - n;
1980 genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
1981 gen_assignment(s, t->car, cursp(), NOVAL);
1984 if (t->cdr && t->cdr->car) {
1987 gen_assignment(s, t->car, rhs+n, NOVAL);
1995 genop_2(s, OP_ARRAY, rhs, len);
2002 gen_vmassignment(s, tree->car, rhs, val);
2012 mrb_sym sym = nsym(tree->cdr->car);
2014 const char *name = mrb_sym_name_len(s->mrb, sym, &len);
2015 int idx, callargs = -1, vsp = -1;
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;
2023 onerr = genjmp(s, OP_ONERR, 0);
2024 lp = loop_push(s, LOOP_BEGIN);
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);
2032 genop_1(s, OP_EXCEPT, exc);
2033 genop_1(s, OP_LOADF, exc);
2037 else if (nint(tree->car->car) == NODE_CALL) {
2038 node *n = tree->car->cdr;
2039 int base, i, nargs = 0;
2046 codegen(s, n->car, VAL); /* receiver */
2047 idx = new_sym(s, nsym(n->cdr->car));
2049 if (n->cdr->cdr->car) {
2050 nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
2054 else { /* varargs */
2057 callargs = CALL_MAXARGS;
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);
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);
2070 codegen(s, tree->car, VAL);
2073 ((name[0] == '|' && name[1] == '|') ||
2074 (name[0] == '&' && name[1] == '&'))) {
2080 gen_move(s, vsp, cursp(), 1);
2082 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2085 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2087 codegen(s, tree->cdr->cdr->car, VAL);
2089 if (val && vsp >= 0) {
2090 gen_move(s, vsp, cursp(), 1);
2092 if (nint(tree->car->car) == NODE_CALL) {
2093 if (callargs == CALL_MAXARGS) {
2095 genop_1(s, OP_ARYPUSH, cursp());
2102 idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2103 genop_3(s, OP_SEND, cursp(), idx, callargs);
2106 gen_assignment(s, tree->car, cursp(), val);
2111 codegen(s, tree->cdr->cdr->car, VAL);
2115 if (len == 1 && name[0] == '+') {
2116 gen_addsub(s, OP_ADD, cursp());
2118 else if (len == 1 && name[0] == '-') {
2119 gen_addsub(s, OP_SUB, cursp());
2121 else if (len == 1 && name[0] == '*') {
2122 genop_1(s, OP_MUL, cursp());
2124 else if (len == 1 && name[0] == '/') {
2125 genop_1(s, OP_DIV, cursp());
2127 else if (len == 1 && name[0] == '<') {
2128 genop_1(s, OP_LT, cursp());
2130 else if (len == 2 && name[0] == '<' && name[1] == '=') {
2131 genop_1(s, OP_LE, cursp());
2133 else if (len == 1 && name[0] == '>') {
2134 genop_1(s, OP_GT, cursp());
2136 else if (len == 2 && name[0] == '>' && name[1] == '=') {
2137 genop_1(s, OP_GE, cursp());
2140 idx = new_sym(s, sym);
2141 genop_3(s, OP_SEND, cursp(), idx, 1);
2144 gen_assignment(s, tree->car, cursp(), val);
2147 if (val && vsp >= 0) {
2148 gen_move(s, vsp, cursp(), 0);
2150 if (callargs == CALL_MAXARGS) {
2152 genop_1(s, OP_ARYPUSH, cursp());
2159 idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2160 genop_3(s, OP_SEND, cursp(), idx, callargs);
2167 codegen_scope *s2 = s;
2169 int n = 0, noop = 0, sendv = 0;
2171 push(); /* room for receiver */
2172 while (!s2->mscope) {
2177 genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
2178 push(); push(); /* ARGARY pushes two values */
2181 node *args = tree->car;
2183 n = gen_values(s, args, VAL, 0);
2185 n = noop = sendv = 1;
2190 if (tree && tree->cdr) {
2191 codegen(s, tree->cdr, VAL);
2195 genop_1(s, OP_LOADNIL, cursp());
2199 if (sendv) n = CALL_MAXARGS;
2200 genop_2(s, OP_SUPER, cursp(), n);
2207 codegen_scope *s2 = s;
2208 int lv = 0, ainfo = 0;
2210 push(); /* room for receiver */
2211 while (!s2->mscope) {
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);
2224 genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
2231 gen_retval(s, tree);
2234 genop_1(s, OP_LOADNIL, cursp());
2237 gen_return(s, OP_RETURN_BLK, cursp());
2240 gen_return(s, OP_RETURN, cursp());
2247 codegen_scope *s2 = s;
2248 int lv = 0, ainfo = 0;
2249 int n = 0, sendv = 0;
2251 while (!s2->mscope) {
2256 if (s2) ainfo = s2->ainfo;
2259 n = gen_values(s, tree, VAL, 0);
2265 push();pop(); /* space for a block */
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);
2275 loop_break(s, tree);
2281 raise_error(s, "unexpected next");
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);
2287 codegen(s, tree, NOVAL);
2288 genjmp(s, OP_JMP, s->loop->pc0);
2292 codegen(s, tree, VAL);
2296 genop_1(s, OP_LOADNIL, cursp());
2298 gen_return(s, OP_RETURN, cursp());
2304 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2305 raise_error(s, "unexpected redo");
2308 if (s->ensure_level > s->loop->ensure_level) {
2309 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2311 genjmp(s, OP_JMP, s->loop->pc2);
2318 const char *msg = "unexpected retry";
2321 raise_error(s, msg);
2324 struct loopinfo *lp = s->loop;
2327 while (lp && lp->type != LOOP_RESCUE) {
2328 if (lp->type == LOOP_BEGIN) {
2334 raise_error(s, msg);
2338 genop_1(s, OP_POPERR, n);
2340 if (s->ensure_level > lp->ensure_level) {
2341 genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
2343 genjmp(s, OP_JMP, lp->pc0);
2352 int idx = lv_idx(s, nsym(tree));
2355 gen_move(s, cursp(), idx, val);
2358 int lv = search_upvar(s, nsym(tree), &idx);
2359 genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
2367 int idx = nint(tree);
2369 gen_move(s, cursp(), idx, val);
2377 int sym = new_sym(s, nsym(tree));
2379 genop_2(s, OP_GETGV, cursp(), sym);
2386 int sym = new_sym(s, nsym(tree));
2388 genop_2(s, OP_GETIV, cursp(), sym);
2395 int sym = new_sym(s, nsym(tree));
2397 genop_2(s, OP_GETCV, cursp(), sym);
2404 int sym = new_sym(s, nsym(tree));
2406 genop_2(s, OP_GETCONST, cursp(), sym);
2413 char buf[] = {'$', nchar(tree)};
2414 int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
2416 genop_2(s, OP_GETGV, cursp(), sym);
2423 mrb_state *mrb = s->mrb;
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);
2435 /* should not happen */
2438 case NODE_BLOCK_ARG:
2439 codegen(s, tree, val);
2444 char *p = (char*)tree->car;
2445 int base = nint(tree->cdr->car);
2449 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2450 #ifndef MRB_WITHOUT_FLOAT
2452 double f = readint_float(s, p, base);
2453 int off = new_lit(s, mrb_float_value(s->mrb, f));
2455 genop_2(s, OP_LOADL, cursp(), off);
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);
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);
2473 off = new_lit(s, mrb_fixnum_value(i));
2474 genop_2(s, OP_LOADL, cursp(), off);
2481 #ifndef MRB_WITHOUT_FLOAT
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));
2488 genop_2(s, OP_LOADL, cursp(), off);
2496 nt = nint(tree->car);
2498 #ifndef MRB_WITHOUT_FLOAT
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));
2505 genop_2(s, OP_LOADL, cursp(), off);
2513 char *p = (char*)tree->cdr->car;
2514 int base = nint(tree->cdr->cdr->car);
2518 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2519 #ifndef MRB_WITHOUT_FLOAT
2521 double f = readint_float(s, p, base);
2522 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2524 genop_2(s, OP_LOADL, cursp(), off);
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);
2532 else if (i >= -0x8000) {
2533 genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
2536 int off = new_lit(s, mrb_fixnum_value(i));
2537 genop_2(s, OP_LOADL, cursp(), off);
2539 #ifndef MRB_WITHOUT_FLOAT
2548 int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
2549 codegen(s, tree, VAL);
2551 genop_3(s, OP_SEND, cursp(), sym, 0);
2555 codegen(s, tree, NOVAL);
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));
2569 mrb_gc_arena_restore(s->mrb, ai);
2570 genop_2(s, OP_STRING, cursp(), off);
2576 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2583 genop_1(s, OP_LOADNIL, cursp());
2587 codegen(s, n->car, VAL);
2590 codegen(s, n->car, VAL);
2592 genop_1(s, OP_STRCAT, cursp());
2601 if (nint(n->car->car) != NODE_STR) {
2602 codegen(s, n->car, NOVAL);
2610 gen_literal_array(s, tree, FALSE, val);
2614 gen_literal_array(s, tree, TRUE, val);
2620 int ai = mrb_gc_arena_save(s->mrb);
2621 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2623 genop_1(s, OP_LOADSELF, cursp());
2625 codegen(s, tree->car, VAL);
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 */
2632 codegen(s, n->car, VAL);
2634 genop_1(s, OP_STRCAT, cursp());
2638 push(); /* for block */
2640 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2641 genop_3(s, OP_SEND, cursp(), sym, 1);
2643 mrb_gc_arena_restore(s->mrb, ai);
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));
2655 genop_1(s, OP_LOADSELF, cursp());
2657 genop_2(s, OP_STRING, cursp(), off);
2660 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2661 genop_3(s, OP_SEND, cursp(), sym, 1);
2663 mrb_gc_arena_restore(s->mrb, ai);
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));
2677 genop_1(s, OP_OCLASS, cursp());
2678 genop_2(s, OP_GETMCNST, cursp(), sym);
2680 genop_2(s, OP_STRING, cursp(), off);
2684 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2685 genop_2(s, OP_STRING, cursp(), off);
2688 genop_1(s, OP_LOADNIL, cursp());
2693 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2694 genop_2(s, OP_STRING, cursp(), off);
2699 push(); /* space for a block */
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);
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));
2717 genop_1(s, OP_OCLASS, cursp());
2718 genop_2(s, OP_GETMCNST, cursp(), sym);
2720 codegen(s, n->car, VAL);
2723 codegen(s, n->car, VAL);
2725 genop_1(s, OP_STRCAT, cursp());
2730 if (n->car) { /* tail */
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);
2736 genop_1(s, OP_STRCAT, cursp());
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);
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);
2753 push(); /* space for a block */
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);
2761 node *n = tree->car;
2764 if (nint(n->car->car) != NODE_STR) {
2765 codegen(s, n->car, NOVAL);
2774 int sym = new_sym(s, nsym(tree));
2776 genop_2(s, OP_LOADSYM, cursp(), sym);
2782 codegen(s, tree, val);
2790 genop_1(s, OP_LOADSELF, cursp());
2797 genop_1(s, OP_LOADNIL, cursp());
2804 genop_1(s, OP_LOADT, cursp());
2811 genop_1(s, OP_LOADF, cursp());
2818 int a = new_sym(s, nsym(tree->car));
2819 int b = new_sym(s, nsym(tree->cdr));
2821 genop_2(s, OP_ALIAS, a, b);
2823 genop_1(s, OP_LOADNIL, cursp());
2834 int symbol = new_sym(s, nsym(t->car));
2835 genop_1(s, OP_UNDEF, symbol);
2839 genop_1(s, OP_LOADNIL, cursp());
2850 if (tree->car->car == (node*)0) {
2851 genop_1(s, OP_LOADNIL, cursp());
2854 else if (tree->car->car == (node*)1) {
2855 genop_1(s, OP_OCLASS, cursp());
2859 codegen(s, tree->car->car, VAL);
2861 if (tree->cdr->car) {
2862 codegen(s, tree->cdr->car, VAL);
2865 genop_1(s, OP_LOADNIL, cursp());
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());
2876 idx = scope_body(s, body, val);
2877 genop_2(s, OP_EXEC, cursp(), idx);
2889 if (tree->car->car == (node*)0) {
2890 genop_1(s, OP_LOADNIL, cursp());
2893 else if (tree->car->car == (node*)1) {
2894 genop_1(s, OP_OCLASS, cursp());
2898 codegen(s, tree->car->car, VAL);
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());
2908 idx = scope_body(s, tree->cdr->car, val);
2909 genop_2(s, OP_EXEC, cursp(), idx);
2921 codegen(s, tree->car, VAL);
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());
2929 idx = scope_body(s, tree->cdr->car, val);
2930 genop_2(s, OP_EXEC, cursp(), idx);
2940 int sym = new_sym(s, nsym(tree->car));
2941 int idx = lambda_body(s, tree->cdr, 0);
2943 genop_1(s, OP_TCLASS, cursp());
2945 genop_2(s, OP_METHOD, cursp(), idx);
2948 genop_2(s, OP_DEF, cursp(), sym);
2950 genop_2(s, OP_LOADSYM, cursp(), sym);
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);
2962 codegen(s, recv, VAL);
2964 genop_1(s, OP_SCLASS, cursp());
2966 genop_2(s, OP_METHOD, cursp(), idx);
2968 genop_2(s, OP_DEF, cursp(), sym);
2970 genop_2(s, OP_LOADSYM, cursp(), sym);
2977 codegen(s, tree, NOVAL);
2988 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2990 if (s->irep == NULL) {
2994 if (s->irep->rlen == s->rcapa) {
2996 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2998 s->irep->reps[s->irep->rlen] = irep;
3002 static codegen_scope*
3003 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
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));
3011 codegen_error(prev, "unexpected scope");
3014 *p = codegen_scope_zero;
3017 if (!prev) return p;
3022 p->irep = mrb_add_irep(mrb);
3023 scope_add_irep(prev, p->irep);
3026 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
3029 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
3030 p->irep->iseq = NULL;
3033 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
3037 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
3041 p->sp += node_len(lv)+1; /* add self */
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);
3051 p->irep->lv[i].r = lv_idx(p, lv_name(n));
3054 p->irep->lv[i].r = 0;
3057 mrb_assert(i + 1 == p->nlocals);
3059 p->ai = mrb_gc_arena_save(mrb);
3061 p->filename_sym = prev->filename_sym;
3062 if (p->filename_sym) {
3063 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
3065 p->lineno = prev->lineno;
3068 p->debug_start_pos = 0;
3069 if (p->filename_sym) {
3070 mrb_debug_info_alloc(mrb, p->irep);
3073 p->irep->debug_info = NULL;
3075 p->parser = prev->parser;
3076 p->filename_index = prev->filename_index;
3078 p->rlev = prev->rlev+1;
3084 scope_finish(codegen_scope *s)
3086 mrb_state *mrb = s->mrb;
3087 mrb_irep *irep = s->irep;
3089 if (s->nlocals >= 0x3ff) {
3090 codegen_error(s, "too many local variables");
3094 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
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);
3104 mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3105 filename, s->lines, s->debug_start_pos, s->pc);
3107 mrb_free(s->mrb, s->lines);
3109 irep->nlocals = s->nlocals;
3110 irep->nregs = s->nregs;
3112 mrb_gc_arena_restore(mrb, s->ai);
3113 mrb_pool_close(s->mpool);
3116 static struct loopinfo*
3117 loop_push(codegen_scope *s, enum looptype t)
3119 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
3122 p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
3124 p->ensure_level = s->ensure_level;
3132 loop_break(codegen_scope *s, node *tree)
3135 codegen(s, tree, NOVAL);
3136 raise_error(s, "unexpected break");
3139 struct loopinfo *loop;
3143 gen_retval(s, tree);
3148 if (loop->type == LOOP_BEGIN) {
3152 else if (loop->type == LOOP_RESCUE) {
3160 raise_error(s, "unexpected break");
3164 genop_1(s, OP_POPERR, n);
3167 if (loop->type == LOOP_NORMAL) {
3170 if (s->ensure_level > s->loop->ensure_level) {
3171 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
3174 gen_move(s, loop->acc, cursp(), 0);
3176 tmp = genjmp(s, OP_JMP, loop->pc3);
3181 genop_1(s, OP_LOADNIL, cursp());
3183 gen_return(s, OP_BREAK, cursp());
3189 loop_pop(codegen_scope *s, int val)
3192 genop_1(s, OP_LOADNIL, cursp());
3194 dispatch_linked(s, s->loop->pc3);
3195 s->loop = s->loop->prev;
3199 static struct RProc*
3200 generate_code(mrb_state *mrb, parser_state *p, int val)
3202 codegen_scope *scope = scope_new(mrb, 0, 0);
3204 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3208 scope->filename_sym = p->filename_sym;
3209 scope->filename_index = p->current_filename_index;
3211 MRB_TRY(&scope->jmp) {
3212 mrb->jmp = &scope->jmp;
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);
3219 if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
3222 mrb->jmp = prev_jmp;
3225 MRB_CATCH(&scope->jmp) {
3226 mrb_irep_decref(mrb, scope->irep);
3227 mrb_pool_close(scope->mpool);
3228 mrb->jmp = prev_jmp;
3231 MRB_END_EXC(&scope->jmp);
3234 MRB_API struct RProc*
3235 mrb_generate_code(mrb_state *mrb, parser_state *p)
3237 return generate_code(mrb, p, VAL);
3241 mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
3246 mrb_free(mrb, irep->lv);
3250 for (i = 0; i < irep->rlen; ++i) {
3251 mrb_irep_remove_lv(mrb, irep->reps[i]);
3259 /* instruction sizes */
3260 uint8_t mrb_insn_size[] = {
3266 #define OPCODE(_,x) x,
3267 #include "mruby/ops.h"
3275 /* EXT1 instruction sizes */
3276 uint8_t mrb_insn_size1[] = {
3282 #define OPCODE(_,x) x,
3283 #include "mruby/ops.h"
3287 /* EXT2 instruction sizes */
3288 uint8_t mrb_insn_size2[] = {
3290 #define OPCODE(_,x) x,
3291 #include "mruby/ops.h"
3298 /* EXT3 instruction sizes */
3303 uint8_t mrb_insn_size3[] = {
3304 #define OPCODE(_,x) x,
3305 #include "mruby/ops.h"