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_pool_close(s->mpool);
108 #ifndef MRB_DISABLE_STDIO
109 if (s->filename_sym && s->lineno) {
110 const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
111 fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
114 fprintf(stderr, "codegen error: %s\n", message);
121 codegen_palloc(codegen_scope *s, size_t len)
123 void *p = mrb_pool_alloc(s->mpool, len);
125 if (!p) codegen_error(s, "pool memory allocation");
130 codegen_realloc(codegen_scope *s, void *p, size_t len)
132 p = mrb_realloc_simple(s->mrb, p, len);
134 if (!p && len > 0) codegen_error(s, "mrb_realloc");
139 new_label(codegen_scope *s)
141 return s->lastlabel = s->pc;
145 emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
147 if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
148 codegen_error(s, "too big code block");
150 if (pc >= s->icapa) {
152 if (s->icapa > MAXARG_S) {
155 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
157 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
161 if (s->lineno > 0 || pc == 0)
162 s->lines[pc] = s->lineno;
164 s->lines[pc] = s->lines[pc-1];
170 emit_S(codegen_scope *s, int pc, uint16_t i)
180 gen_B(codegen_scope *s, uint8_t i)
187 gen_S(codegen_scope *s, uint16_t i)
194 genop_0(codegen_scope *s, mrb_code i)
201 genop_1(codegen_scope *s, mrb_code i, uint16_t a)
211 gen_B(s, (uint8_t)a);
216 genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
219 if (a > 0xff && b > 0xff) {
228 gen_B(s, (uint8_t)a);
235 gen_B(s, (uint8_t)b);
239 gen_B(s, (uint8_t)a);
240 gen_B(s, (uint8_t)b);
245 genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
252 genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
259 genop_W(codegen_scope *s, mrb_code i, uint32_t a)
261 uint8_t a1 = (a>>16) & 0xff;
262 uint8_t a2 = (a>>8) & 0xff;
263 uint8_t a3 = a & 0xff;
277 no_optimize(codegen_scope *s)
279 if (s && s->parser && s->parser->no_optimize)
286 on_eval(codegen_scope *s)
288 if (s && s->parser && s->parser->on_eval)
294 mrb_decode_insn(mrb_code *pc)
296 struct mrb_insn_data data = { 0 };
297 mrb_code insn = READ_B();
303 #define FETCH_Z() /* empty */
304 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
305 #include "mruby/ops.h"
312 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
313 #include "mruby/ops.h"
320 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
321 #include "mruby/ops.h"
328 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
329 #include "mruby/ops.h"
343 static struct mrb_insn_data
344 mrb_last_insn(codegen_scope *s)
346 if (s->pc == s->lastpc) {
347 struct mrb_insn_data data;
352 return mrb_decode_insn(&s->iseq[s->lastpc]);
356 no_peephole(codegen_scope *s)
358 return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
362 genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
374 genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
378 if (!no_peephole(s) && !val) {
379 struct mrb_insn_data data = mrb_last_insn(s);
381 if (data.insn == OP_MOVE && data.a == a) {
397 gen_B(s, (uint8_t)a);
405 gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
407 if (no_peephole(s)) {
409 genop_2(s, OP_MOVE, dst, src);
416 struct mrb_insn_data data = mrb_last_insn(s);
420 if (dst == src) return; /* remove useless MOVE */
421 if (data.b == dst && data.a == src) /* skip swapping MOVE */
424 case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
426 case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
427 case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
428 if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
430 genop_1(s, data.insn, dst);
432 case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM:
433 case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
434 case OP_GETCONST: case OP_STRING:
435 case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
436 if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
438 genop_2(s, data.insn, dst, data.b);
447 gen_return(codegen_scope *s, uint8_t op, uint16_t src)
449 if (no_peephole(s)) {
453 struct mrb_insn_data data = mrb_last_insn(s);
455 if (data.insn == OP_MOVE && src == data.a) {
457 genop_1(s, op, data.b);
459 else if (data.insn != OP_RETURN) {
466 gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
468 if (no_peephole(s)) {
474 struct mrb_insn_data data = mrb_last_insn(s);
478 if (op == OP_ADD) op = OP_SUB;
482 case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
483 case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
484 data.b = data.insn - OP_LOADI_0;
488 if (data.b >= 128) goto normal;
491 genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
494 genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
504 dispatch(codegen_scope *s, uint16_t pos0)
508 s->lastlabel = s->pc;
509 newpos = PEEK_S(s->iseq+pos0);
510 emit_S(s, pos0, s->pc);
515 dispatch_linked(codegen_scope *s, uint16_t pos)
519 pos = dispatch(s, pos);
524 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
526 push_n_(codegen_scope *s, int n)
528 if (s->sp+n >= 0xffff) {
529 codegen_error(s, "too complex expression");
536 pop_n_(codegen_scope *s, int n)
538 if ((int)s->sp-n < 0) {
539 codegen_error(s, "stack pointer underflow");
544 #define push() push_n_(s,1)
545 #define push_n(n) push_n_(s,n)
546 #define pop() pop_n_(s,1)
547 #define pop_n(n) pop_n_(s,n)
548 #define cursp() (s->sp)
551 new_lit(codegen_scope *s, mrb_value val)
556 switch (mrb_type(val)) {
558 for (i=0; i<s->irep->plen; i++) {
560 pv = &s->irep->pool[i];
562 if (mrb_type(*pv) != MRB_TT_STRING) continue;
563 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
564 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
568 #ifndef MRB_WITHOUT_FLOAT
570 for (i=0; i<s->irep->plen; i++) {
572 pv = &s->irep->pool[i];
573 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
576 if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
581 for (i=0; i<s->irep->plen; i++) {
582 pv = &s->irep->pool[i];
583 if (!mrb_fixnum_p(*pv)) continue;
584 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
588 /* should not happen */
592 if (s->irep->plen == s->pcapa) {
594 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
597 pv = &s->irep->pool[s->irep->plen];
600 switch (mrb_type(val)) {
602 *pv = mrb_str_pool(s->mrb, val);
605 #ifndef MRB_WITHOUT_FLOAT
607 #ifdef MRB_WORD_BOXING
608 *pv = mrb_float_pool(s->mrb, mrb_float(val));
617 /* should not happen */
623 /* maximum symbol numbers */
624 #define MAXSYMLEN 0x10000
627 new_sym(codegen_scope *s, mrb_sym sym)
634 for (i=0; i<len; i++) {
635 if (s->irep->syms[i] == sym) return i;
637 if (s->irep->slen >= s->scapa) {
639 s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
641 s->irep->syms[s->irep->slen] = sym;
642 return s->irep->slen++;
657 #define nint(x) ((int)(intptr_t)(x))
658 #define nchar(x) ((char)(intptr_t)(x))
659 #define nsym(x) ((mrb_sym)(intptr_t)(x))
661 #define lv_name(lv) nsym((lv)->car)
664 lv_idx(codegen_scope *s, mrb_sym id)
670 if (lv_name(lv) == id) return n;
678 for_body(codegen_scope *s, node *tree)
680 codegen_scope *prev = s;
685 /* generate receiver */
686 codegen(s, tree->cdr->car, VAL);
687 /* generate loop-block */
688 s = scope_new(s->mrb, s, NULL);
690 raise_error(prev, "unexpected scope");
693 push(); /* push for a block parameter */
695 /* generate loop variable */
697 genop_W(s, OP_ENTER, 0x40000);
698 if (n2->car && !n2->car->cdr && !n2->cdr) {
699 gen_assignment(s, n2->car->car, 1, NOVAL);
702 gen_vmassignment(s, n2, 1, VAL);
705 lp = loop_push(s, LOOP_FOR);
706 lp->pc2 = new_label(s);
709 codegen(s, tree->cdr->cdr->car, VAL);
711 gen_return(s, OP_RETURN, cursp());
715 genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
716 push();pop(); /* space for a block */
718 idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
719 genop_3(s, OP_SENDB, cursp(), idx, 0);
723 lambda_body(codegen_scope *s, node *tree, int blk)
725 codegen_scope *parent = s;
726 s = scope_new(s->mrb, s, tree->car);
728 raise_error(parent, "unexpected scope");
734 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
735 lp->pc0 = new_label(s);
738 if (tree->car == NULL) {
739 genop_W(s, OP_ENTER, 0);
743 int ma, oa, ra, pa, ka, kd, ba;
749 /* mandatory arguments */
750 ma = node_len(tree->car->car);
751 margs = tree->car->car;
752 tail = tree->car->cdr->cdr->cdr->cdr;
754 /* optional arguments */
755 oa = node_len(tree->car->cdr->car);
757 ra = tree->car->cdr->cdr->car ? 1 : 0;
758 /* mandatory arugments after rest argument */
759 pa = node_len(tree->car->cdr->cdr->cdr->car);
760 pargs = tree->car->cdr->cdr->cdr->car;
761 /* keyword arguments */
762 ka = tail? node_len(tail->cdr->car) : 0;
763 /* keyword dictionary? */
764 kd = tail && tail->cdr->cdr->car? 1 : 0;
765 /* block argument? */
766 ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
768 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
769 codegen_error(s, "too many formal arguments");
773 | (ra? MRB_ARGS_REST() : 0)
775 | MRB_ARGS_KEY(ka, kd)
776 | (ba? MRB_ARGS_BLOCK() : 0);
777 s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
781 genop_W(s, OP_ENTER, a);
782 /* generate jump table for optional arguments initializer */
784 for (i=0; i<oa; i++) {
786 genjmp(s, OP_JMP, 0);
789 genjmp(s, OP_JMP, 0);
791 opt = tree->car->cdr->car;
796 dispatch(s, pos+i*3+1);
797 codegen(s, opt->car->cdr, VAL);
799 idx = lv_idx(s, nsym(opt->car->car));
800 gen_move(s, idx, cursp(), 0);
805 dispatch(s, pos+i*3+1);
808 /* keyword arguments */
810 node *kwds = tail->cdr->car;
813 if (tail->cdr->cdr->car) {
816 mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
817 mrb_assert(node_len(tail) == 4);
820 int jmpif_key_p, jmp_def_set = -1;
821 node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
822 mrb_sym kwd_sym = nsym(kwd->cdr->car);
824 mrb_assert(nint(kwd->car) == NODE_KW_ARG);
827 genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
828 jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
829 codegen(s, def_arg, VAL);
831 gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
832 jmp_def_set = genjmp(s, OP_JMP, 0);
833 dispatch(s, jmpif_key_p);
835 genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
836 if (jmp_def_set != -1) {
837 dispatch(s, jmp_def_set);
843 if (tail->cdr->car && !kwrest) {
844 genop_0(s, OP_KEYEND);
848 /* argument destructuring */
854 if (nint(n->car->car) == NODE_MASGN) {
855 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
866 if (nint(n->car->car) == NODE_MASGN) {
867 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
875 codegen(s, tree->cdr->car, VAL);
878 gen_return(s, OP_RETURN, cursp());
884 return parent->irep->rlen - 1;
888 scope_body(codegen_scope *s, node *tree, int val)
890 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
892 codegen_error(s, "unexpected scope");
895 codegen(scope, tree->cdr, VAL);
896 gen_return(scope, OP_RETURN, scope->sp-1);
898 genop_0(scope, OP_STOP);
902 /* should not happen */
905 return s->irep->rlen - 1;
912 if (nint(t->car->car) == NODE_SPLAT) return FALSE;
919 attrsym(codegen_scope *s, mrb_sym a)
925 name = mrb_sym2name_len(s->mrb, a, &len);
926 name2 = (char *)codegen_palloc(s,
931 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
932 memcpy(name2, name, (size_t)len);
936 return mrb_intern(s->mrb, name2, len+1);
939 #define CALL_MAXARGS 127
942 gen_values(codegen_scope *s, node *t, int val, int extra)
948 is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
950 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
953 if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
954 codegen(s, t->car->cdr, VAL);
959 genop_2(s, OP_ARRAY, cursp(), n);
961 codegen(s, t->car, VAL);
964 genop_1(s, OP_ARYCAT, cursp());
967 genop_1(s, OP_ARYPUSH, cursp());
973 codegen(s, t->car, VAL);
975 if (nint(t->car->car) == NODE_SPLAT) {
976 genop_1(s, OP_ARYCAT, cursp());
979 genop_1(s, OP_ARYPUSH, cursp());
986 codegen(s, t->car, NOVAL);
992 /* normal (no splat) mode */
993 codegen(s, t->car, val);
1001 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
1003 mrb_sym sym = name ? name : nsym(tree->cdr->car);
1005 int n = 0, noop = 0, sendv = 0, blk = 0;
1007 codegen(s, tree->car, VAL); /* receiver */
1009 int recv = cursp()-1;
1010 gen_move(s, cursp(), recv, 1);
1011 skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1013 tree = tree->cdr->cdr->car;
1015 n = gen_values(s, tree->car, VAL, sp?1:0);
1017 n = noop = sendv = 1;
1021 if (sp) { /* last argument pushed (attr=) */
1023 gen_move(s, cursp(), sp, 0);
1025 genop_1(s, OP_ARYPUSH, cursp());
1029 gen_move(s, cursp(), sp, 0);
1034 if (tree && tree->cdr) {
1036 codegen(s, tree->cdr, VAL);
1044 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
1046 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
1047 gen_addsub(s, OP_ADD, cursp());
1049 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
1050 gen_addsub(s, OP_SUB, cursp());
1052 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
1053 genop_1(s, OP_MUL, cursp());
1055 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
1056 genop_1(s, OP_DIV, cursp());
1058 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
1059 genop_1(s, OP_LT, cursp());
1061 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
1062 genop_1(s, OP_LE, cursp());
1064 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
1065 genop_1(s, OP_GT, cursp());
1067 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
1068 genop_1(s, OP_GE, cursp());
1070 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
1071 genop_1(s, OP_EQ, cursp());
1074 int idx = new_sym(s, sym);
1077 genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
1080 genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
1093 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
1096 int type = nint(tree->car);
1101 idx = new_sym(s, nsym(tree));
1102 genop_2(s, OP_SETGV, sp, idx);
1106 idx = lv_idx(s, nsym(tree));
1109 gen_move(s, idx, sp, val);
1110 if (val && on_eval(s)) genop_0(s, OP_NOP);
1116 codegen_scope *up = s->prev;
1119 idx = lv_idx(up, nsym(tree));
1121 genop_3(s, OP_SETUPVAR, sp, idx, lv);
1130 idx = new_sym(s, nsym(tree));
1131 genop_2(s, OP_SETIV, sp, idx);
1134 idx = new_sym(s, nsym(tree));
1135 genop_2(s, OP_SETCV, sp, idx);
1138 idx = new_sym(s, nsym(tree));
1139 genop_2(s, OP_SETCONST, sp, idx);
1142 gen_move(s, cursp(), sp, 0);
1144 codegen(s, tree->car, VAL);
1146 idx = new_sym(s, nsym(tree->cdr));
1147 genop_2(s, OP_SETMCNST, sp, idx);
1153 gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1154 type == NODE_SCALL);
1157 gen_move(s, cursp(), sp, 0);
1162 gen_vmassignment(s, tree->car, sp, val);
1165 /* splat without assignment */
1170 #ifndef MRB_DISABLE_STDIO
1171 fprintf(stderr, "unknown lhs %d\n", type);
1179 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1181 int n = 0, post = 0;
1184 if (tree->car) { /* pre */
1190 genop_3(s, OP_AREF, sp, rhs, n);
1192 gen_assignment(s, t->car, sp, NOVAL);
1200 if (t->cdr) { /* post count */
1207 gen_move(s, cursp(), rhs, val);
1210 genop_3(s, OP_APOST, cursp(), n, post);
1212 if (t->car && t->car != (node*)-1) { /* rest */
1213 gen_assignment(s, t->car, cursp(), NOVAL);
1215 if (t->cdr && t->cdr->car) {
1218 gen_assignment(s, t->car, cursp()+n, NOVAL);
1224 gen_move(s, cursp(), rhs, 0);
1230 gen_intern(codegen_scope *s)
1233 genop_1(s, OP_INTERN, cursp());
1238 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1244 switch (nint(tree->car->car)) {
1246 if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1250 codegen(s, tree->car, VAL);
1254 case NODE_LITERAL_DELIM:
1265 genop_1(s, OP_STRCAT, cursp());
1277 genop_2(s, OP_ARRAY, cursp(), i);
1282 switch (nint(tree->car->car)) {
1283 case NODE_BEGIN: case NODE_BLOCK:
1284 codegen(s, tree->car, NOVAL);
1292 raise_error(codegen_scope *s, const char *msg)
1294 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1296 genop_1(s, OP_ERR, idx);
1299 #ifndef MRB_WITHOUT_FLOAT
1301 readint_float(codegen_scope *s, const char *p, int base)
1303 const char *e = p + strlen(p);
1310 c = tolower((unsigned char)c);
1311 for (n=0; n<base; n++) {
1312 if (mrb_digitmap[n] == c) {
1319 codegen_error(s, "malformed readint input");
1328 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1330 const char *e = p + strlen(p);
1334 mrb_assert(base >= 2 && base <= 36);
1338 c = tolower((unsigned char)c);
1339 for (n=0; n<base; n++) {
1340 if (mrb_digitmap[n] == c) {
1345 codegen_error(s, "malformed readint input");
1349 if ((MRB_INT_MIN + n)/base > result) {
1357 if ((MRB_INT_MAX - n)/base < result) {
1371 gen_retval(codegen_scope *s, node *tree)
1373 if (nint(tree->car) == NODE_SPLAT) {
1374 codegen(s, tree, VAL);
1376 genop_1(s, OP_ARYDUP, cursp());
1379 codegen(s, tree, VAL);
1385 codegen(codegen_scope *s, node *tree, int val)
1392 genop_1(s, OP_LOADNIL, cursp());
1399 if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1400 codegen_error(s, "too complex expression");
1402 if (s->irep && s->filename_index != tree->filename_index) {
1403 mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
1404 const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
1406 mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
1407 filename, s->lines, s->debug_start_pos, s->pc);
1408 s->debug_start_pos = s->pc;
1409 s->filename_index = tree->filename_index;
1410 s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
1413 nt = nint(tree->car);
1414 s->lineno = tree->lineno;
1419 genop_1(s, OP_LOADNIL, cursp());
1423 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1430 int noexc, exend, pos1, pos2, tmp;
1431 struct loopinfo *lp;
1433 if (tree->car == NULL) goto exit;
1434 lp = loop_push(s, LOOP_BEGIN);
1435 lp->pc0 = new_label(s);
1436 lp->pc1 = genjmp(s, OP_ONERR, 0);
1437 codegen(s, tree->car, VAL);
1439 lp->type = LOOP_RESCUE;
1440 noexc = genjmp(s, OP_JMP, 0);
1441 dispatch(s, lp->pc1);
1446 node *n2 = tree->car;
1449 genop_1(s, OP_EXCEPT, exc);
1455 if (pos1) dispatch(s, pos1);
1458 if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
1459 codegen(s, n4->car, VAL);
1460 gen_move(s, cursp(), exc, 0);
1461 push_n(2); pop_n(2); /* space for one arg and a block */
1463 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1467 codegen(s, n4->car, VAL);
1470 genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
1474 genop_2(s, OP_RESCUE, exc, cursp());
1476 tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
1482 pos1 = genjmp(s, OP_JMP, 0);
1483 dispatch_linked(s, pos2);
1487 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1489 if (n3->cdr->cdr->car) {
1490 codegen(s, n3->cdr->cdr->car, val);
1493 tmp = genjmp(s, OP_JMP, exend);
1500 genop_1(s, OP_RAISE, exc);
1506 genop_1(s, OP_POPERR, 1);
1508 codegen(s, tree->car, val);
1513 dispatch_linked(s, exend);
1519 if (!tree->cdr || !tree->cdr->cdr ||
1520 (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1521 tree->cdr->cdr->cdr)) {
1525 idx = scope_body(s, tree->cdr, NOVAL);
1526 genop_1(s, OP_EPUSH, idx);
1527 codegen(s, tree->car, val);
1529 genop_1(s, OP_EPOP, 1);
1531 else { /* empty ensure ignored */
1532 codegen(s, tree->car, val);
1538 int idx = lambda_body(s, tree, 1);
1540 genop_2(s, OP_LAMBDA, cursp(), idx);
1547 int idx = lambda_body(s, tree, 1);
1549 genop_2(s, OP_BLOCK, cursp(), idx);
1557 node *elsepart = tree->cdr->cdr->car;
1560 codegen(s, elsepart, val);
1563 switch (nint(tree->car->car)) {
1567 codegen(s, tree->cdr->car, val);
1571 codegen(s, elsepart, val);
1574 codegen(s, tree->car, VAL);
1576 pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1578 codegen(s, tree->cdr->car, val);
1581 pos2 = genjmp(s, OP_JMP, 0);
1583 codegen(s, elsepart, val);
1589 pos2 = genjmp(s, OP_JMP, 0);
1591 genop_1(s, OP_LOADNIL, cursp());
1606 codegen(s, tree->car, VAL);
1608 pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1609 codegen(s, tree->cdr, val);
1618 codegen(s, tree->car, VAL);
1620 pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1621 codegen(s, tree->cdr, val);
1628 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1630 lp->pc0 = new_label(s);
1631 lp->pc1 = genjmp(s, OP_JMP, 0);
1632 lp->pc2 = new_label(s);
1633 codegen(s, tree->cdr, NOVAL);
1634 dispatch(s, lp->pc1);
1635 codegen(s, tree->car, VAL);
1637 genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
1645 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1647 lp->pc0 = new_label(s);
1648 lp->pc1 = genjmp(s, OP_JMP, 0);
1649 lp->pc2 = new_label(s);
1650 codegen(s, tree->cdr, NOVAL);
1651 dispatch(s, lp->pc1);
1652 codegen(s, tree->car, VAL);
1654 genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
1668 int pos1, pos2, pos3, tmp;
1674 codegen(s, tree->car, VAL);
1681 codegen(s, n->car, VAL);
1683 gen_move(s, cursp(), head, 0);
1684 push(); push(); pop(); pop(); pop();
1685 if (nint(n->car->car) == NODE_SPLAT) {
1686 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1689 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
1695 tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
1699 if (tree->car->car) {
1700 pos1 = genjmp(s, OP_JMP, 0);
1701 dispatch_linked(s, pos2);
1703 codegen(s, tree->car->cdr, val);
1705 tmp = genjmp(s, OP_JMP, pos3);
1707 if (pos1) dispatch(s, pos1);
1712 genop_1(s, OP_LOADNIL, cursp());
1713 if (pos3) dispatch_linked(s, pos3);
1715 if (cursp() != pos) {
1716 gen_move(s, cursp(), pos, 0);
1722 dispatch_linked(s, pos3);
1732 scope_body(s, tree, NOVAL);
1737 gen_call(s, tree, 0, 0, val, 0);
1740 gen_call(s, tree, 0, 0, val, 1);
1744 codegen(s, tree->car, val);
1745 codegen(s, tree->cdr, val);
1748 genop_1(s, OP_RANGE_INC, cursp());
1754 codegen(s, tree->car, val);
1755 codegen(s, tree->cdr, val);
1758 genop_1(s, OP_RANGE_EXC, cursp());
1765 int sym = new_sym(s, nsym(tree->cdr));
1767 codegen(s, tree->car, VAL);
1769 genop_2(s, OP_GETMCNST, cursp(), sym);
1776 int sym = new_sym(s, nsym(tree));
1778 genop_1(s, OP_OCLASS, cursp());
1779 genop_2(s, OP_GETMCNST, cursp(), sym);
1788 n = gen_values(s, tree, val, 0);
1792 genop_2(s, OP_ARRAY, cursp(), n);
1806 mrb_bool update = FALSE;
1809 if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1813 genop_2(s, OP_HASH, cursp(), len);
1817 genop_2(s, OP_HASHADD, cursp(), len);
1821 codegen(s, tree->car->cdr, VAL);
1822 if (len > 0 || update) {
1824 genop_1(s, OP_HASHCAT, cursp());
1831 codegen(s, tree->car->car, val);
1832 codegen(s, tree->car->cdr, val);
1836 if (val && len == 255) {
1839 genop_2(s, OP_HASH, cursp(), len);
1843 genop_2(s, OP_HASHADD, cursp(), len);
1853 genop_2(s, OP_HASH, cursp(), len);
1858 genop_2(s, OP_HASHADD, cursp(), len);
1867 codegen(s, tree, val);
1871 codegen(s, tree->cdr, VAL);
1873 gen_assignment(s, tree->car, cursp(), val);
1878 int len = 0, n = 0, post = 0;
1879 node *t = tree->cdr, *p;
1882 if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1886 codegen(s, t->car, VAL);
1891 if (tree->car) { /* pre */
1896 gen_assignment(s, t->car, rhs+n, NOVAL);
1900 genop_1(s, OP_LOADNIL, rhs+n);
1901 gen_assignment(s, t->car, rhs+n, NOVAL);
1908 if (t->cdr) { /* post count */
1915 if (t->car) { /* rest (len - pre - post) */
1918 if (len < post + n) {
1922 rn = len - post - n;
1924 genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
1925 gen_assignment(s, t->car, cursp(), NOVAL);
1928 if (t->cdr && t->cdr->car) {
1931 gen_assignment(s, t->car, rhs+n, NOVAL);
1939 genop_2(s, OP_ARRAY, rhs, len);
1946 gen_vmassignment(s, tree->car, rhs, val);
1956 mrb_sym sym = nsym(tree->cdr->car);
1958 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1959 int idx, callargs = -1, vsp = -1;
1961 if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1962 (nint(tree->car->car) == NODE_CONST ||
1963 nint(tree->car->car) == NODE_CVAR)) {
1964 int onerr, noexc, exc;
1965 struct loopinfo *lp;
1967 onerr = genjmp(s, OP_ONERR, 0);
1968 lp = loop_push(s, LOOP_BEGIN);
1971 codegen(s, tree->car, VAL);
1972 lp->type = LOOP_RESCUE;
1973 genop_1(s, OP_POPERR, 1);
1974 noexc = genjmp(s, OP_JMP, 0);
1976 genop_1(s, OP_EXCEPT, exc);
1977 genop_1(s, OP_LOADF, exc);
1981 else if (nint(tree->car->car) == NODE_CALL) {
1982 node *n = tree->car->cdr;
1983 int base, i, nargs = 0;
1990 codegen(s, n->car, VAL); /* receiver */
1991 idx = new_sym(s, nsym(n->cdr->car));
1993 if (n->cdr->cdr->car) {
1994 nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
1998 else { /* varargs */
2001 callargs = CALL_MAXARGS;
2004 /* copy receiver and arguments */
2005 gen_move(s, cursp(), base, 1);
2006 for (i=0; i<nargs; i++) {
2007 gen_move(s, cursp()+i+1, base+i+1, 1);
2009 push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
2010 genop_3(s, OP_SEND, cursp(), idx, callargs);
2014 codegen(s, tree->car, VAL);
2017 ((name[0] == '|' && name[1] == '|') ||
2018 (name[0] == '&' && name[1] == '&'))) {
2024 gen_move(s, vsp, cursp(), 1);
2026 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2029 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2031 codegen(s, tree->cdr->cdr->car, VAL);
2033 if (val && vsp >= 0) {
2034 gen_move(s, vsp, cursp(), 1);
2036 if (nint(tree->car->car) == NODE_CALL) {
2037 if (callargs == CALL_MAXARGS) {
2039 genop_1(s, OP_ARYPUSH, cursp());
2046 idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2047 genop_3(s, OP_SEND, cursp(), idx, callargs);
2050 gen_assignment(s, tree->car, cursp(), val);
2055 codegen(s, tree->cdr->cdr->car, VAL);
2059 if (len == 1 && name[0] == '+') {
2060 gen_addsub(s, OP_ADD, cursp());
2062 else if (len == 1 && name[0] == '-') {
2063 gen_addsub(s, OP_SUB, cursp());
2065 else if (len == 1 && name[0] == '*') {
2066 genop_1(s, OP_MUL, cursp());
2068 else if (len == 1 && name[0] == '/') {
2069 genop_1(s, OP_DIV, cursp());
2071 else if (len == 1 && name[0] == '<') {
2072 genop_1(s, OP_LT, cursp());
2074 else if (len == 2 && name[0] == '<' && name[1] == '=') {
2075 genop_1(s, OP_LE, cursp());
2077 else if (len == 1 && name[0] == '>') {
2078 genop_1(s, OP_GT, cursp());
2080 else if (len == 2 && name[0] == '>' && name[1] == '=') {
2081 genop_1(s, OP_GE, cursp());
2084 idx = new_sym(s, sym);
2085 genop_3(s, OP_SEND, cursp(), idx, 1);
2088 gen_assignment(s, tree->car, cursp(), val);
2091 if (val && vsp >= 0) {
2092 gen_move(s, vsp, cursp(), 0);
2094 if (callargs == CALL_MAXARGS) {
2096 genop_1(s, OP_ARYPUSH, cursp());
2103 idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2104 genop_3(s, OP_SEND, cursp(), idx, callargs);
2111 codegen_scope *s2 = s;
2113 int n = 0, noop = 0, sendv = 0;
2115 push(); /* room for receiver */
2116 while (!s2->mscope) {
2121 genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
2122 push(); push(); /* ARGARY pushes two values */
2125 node *args = tree->car;
2127 n = gen_values(s, args, VAL, 0);
2129 n = noop = sendv = 1;
2134 if (tree && tree->cdr) {
2135 codegen(s, tree->cdr, VAL);
2139 genop_1(s, OP_LOADNIL, cursp());
2143 if (sendv) n = CALL_MAXARGS;
2144 genop_2(s, OP_SUPER, cursp(), n);
2151 codegen_scope *s2 = s;
2152 int lv = 0, ainfo = 0;
2154 push(); /* room for receiver */
2155 while (!s2->mscope) {
2160 if (s2) ainfo = s2->ainfo;
2161 genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
2162 push(); push(); pop(); /* ARGARY pushes two values */
2163 if (tree && tree->cdr) {
2164 codegen(s, tree->cdr, VAL);
2168 genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
2175 gen_retval(s, tree);
2178 genop_1(s, OP_LOADNIL, cursp());
2181 gen_return(s, OP_RETURN_BLK, cursp());
2184 gen_return(s, OP_RETURN, cursp());
2191 codegen_scope *s2 = s;
2192 int lv = 0, ainfo = 0;
2193 int n = 0, sendv = 0;
2195 while (!s2->mscope) {
2200 if (s2) ainfo = s2->ainfo;
2203 n = gen_values(s, tree, VAL, 0);
2209 push();pop(); /* space for a block */
2211 genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
2212 if (sendv) n = CALL_MAXARGS;
2213 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
2219 loop_break(s, tree);
2225 raise_error(s, "unexpected next");
2227 else if (s->loop->type == LOOP_NORMAL) {
2228 if (s->ensure_level > s->loop->ensure_level) {
2229 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2231 codegen(s, tree, NOVAL);
2232 genjmp(s, OP_JMP, s->loop->pc0);
2236 codegen(s, tree, VAL);
2240 genop_1(s, OP_LOADNIL, cursp());
2242 gen_return(s, OP_RETURN, cursp());
2248 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2249 raise_error(s, "unexpected redo");
2252 if (s->ensure_level > s->loop->ensure_level) {
2253 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2255 genjmp(s, OP_JMP, s->loop->pc2);
2262 const char *msg = "unexpected retry";
2265 raise_error(s, msg);
2268 struct loopinfo *lp = s->loop;
2271 while (lp && lp->type != LOOP_RESCUE) {
2272 if (lp->type == LOOP_BEGIN) {
2278 raise_error(s, msg);
2282 genop_1(s, OP_POPERR, n);
2284 if (s->ensure_level > lp->ensure_level) {
2285 genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
2287 genjmp(s, OP_JMP, lp->pc0);
2296 int idx = lv_idx(s, nsym(tree));
2299 gen_move(s, cursp(), idx, val);
2300 if (val && on_eval(s)) genop_0(s, OP_NOP);
2304 codegen_scope *up = s->prev;
2307 idx = lv_idx(up, nsym(tree));
2309 genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
2322 int sym = new_sym(s, nsym(tree));
2324 genop_2(s, OP_GETGV, cursp(), sym);
2331 int sym = new_sym(s, nsym(tree));
2333 genop_2(s, OP_GETIV, cursp(), sym);
2340 int sym = new_sym(s, nsym(tree));
2342 genop_2(s, OP_GETCV, cursp(), sym);
2349 int sym = new_sym(s, nsym(tree));
2351 genop_2(s, OP_GETCONST, cursp(), sym);
2357 codegen(s, tree, val);
2362 char buf[] = {'$', nchar(tree)};
2363 int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
2365 genop_2(s, OP_GETGV, cursp(), sym);
2372 mrb_state *mrb = s->mrb;
2376 str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
2377 sym = new_sym(s, mrb_intern_str(mrb, str));
2378 genop_2(s, OP_GETGV, cursp(), sym);
2384 /* should not happen */
2387 case NODE_BLOCK_ARG:
2388 codegen(s, tree, val);
2393 char *p = (char*)tree->car;
2394 int base = nint(tree->cdr->car);
2398 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2399 #ifndef MRB_WITHOUT_FLOAT
2401 double f = readint_float(s, p, base);
2402 int off = new_lit(s, mrb_float_value(s->mrb, f));
2404 genop_2(s, OP_LOADL, cursp(), off);
2409 if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2410 else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2411 else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
2412 else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
2414 int off = new_lit(s, mrb_fixnum_value(i));
2415 genop_2(s, OP_LOADL, cursp(), off);
2422 #ifndef MRB_WITHOUT_FLOAT
2425 char *p = (char*)tree;
2426 mrb_float f = mrb_float_read(p, NULL);
2427 int off = new_lit(s, mrb_float_value(s->mrb, f));
2429 genop_2(s, OP_LOADL, cursp(), off);
2437 nt = nint(tree->car);
2439 #ifndef MRB_WITHOUT_FLOAT
2442 char *p = (char*)tree->cdr;
2443 mrb_float f = mrb_float_read(p, NULL);
2444 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2446 genop_2(s, OP_LOADL, cursp(), off);
2454 char *p = (char*)tree->cdr->car;
2455 int base = nint(tree->cdr->cdr->car);
2459 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2460 #ifndef MRB_WITHOUT_FLOAT
2462 double f = readint_float(s, p, base);
2463 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2465 genop_2(s, OP_LOADL, cursp(), off);
2469 if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2470 else if (i >= -0xffff) {
2471 genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2474 int off = new_lit(s, mrb_fixnum_value(i));
2475 genop_2(s, OP_LOADL, cursp(), off);
2477 #ifndef MRB_WITHOUT_FLOAT
2486 int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
2487 codegen(s, tree, VAL);
2489 genop_3(s, OP_SEND, cursp(), sym, 0);
2493 codegen(s, tree, NOVAL);
2502 char *p = (char*)tree->car;
2503 size_t len = (intptr_t)tree->cdr;
2504 int ai = mrb_gc_arena_save(s->mrb);
2505 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2507 mrb_gc_arena_restore(s->mrb, ai);
2508 genop_2(s, OP_STRING, cursp(), off);
2514 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2521 genop_1(s, OP_LOADNIL, cursp());
2525 codegen(s, n->car, VAL);
2528 codegen(s, n->car, VAL);
2530 genop_1(s, OP_STRCAT, cursp());
2539 if (nint(n->car->car) != NODE_STR) {
2540 codegen(s, n->car, NOVAL);
2548 gen_literal_array(s, tree, FALSE, val);
2552 gen_literal_array(s, tree, TRUE, val);
2558 int ai = mrb_gc_arena_save(s->mrb);
2559 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2561 genop_1(s, OP_LOADSELF, cursp());
2563 codegen(s, tree->car, VAL);
2566 if (nint(n->car->car) == NODE_XSTR) {
2567 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2568 mrb_assert(!n->cdr); /* must be the end */
2570 codegen(s, n->car, VAL);
2572 genop_1(s, OP_STRCAT, cursp());
2576 push(); /* for block */
2578 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2579 genop_3(s, OP_SEND, cursp(), sym, 1);
2581 mrb_gc_arena_restore(s->mrb, ai);
2587 char *p = (char*)tree->car;
2588 size_t len = (intptr_t)tree->cdr;
2589 int ai = mrb_gc_arena_save(s->mrb);
2590 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2593 genop_1(s, OP_LOADSELF, cursp());
2595 genop_2(s, OP_STRING, cursp(), off);
2598 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2599 genop_3(s, OP_SEND, cursp(), sym, 1);
2601 mrb_gc_arena_restore(s->mrb, ai);
2607 char *p1 = (char*)tree->car;
2608 char *p2 = (char*)tree->cdr->car;
2609 char *p3 = (char*)tree->cdr->cdr;
2610 int ai = mrb_gc_arena_save(s->mrb);
2611 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2612 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2615 genop_1(s, OP_OCLASS, cursp());
2616 genop_2(s, OP_GETMCNST, cursp(), sym);
2618 genop_2(s, OP_STRING, cursp(), off);
2622 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2623 genop_2(s, OP_STRING, cursp(), off);
2626 genop_1(s, OP_LOADNIL, cursp());
2631 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2632 genop_2(s, OP_STRING, cursp(), off);
2637 push(); /* space for a block */
2639 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2640 genop_3(s, OP_SEND, cursp(), sym, argc);
2641 mrb_gc_arena_restore(s->mrb, ai);
2648 node *n = tree->car;
2649 int ai = mrb_gc_arena_save(s->mrb);
2650 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2655 genop_1(s, OP_OCLASS, cursp());
2656 genop_2(s, OP_GETMCNST, cursp(), sym);
2658 codegen(s, n->car, VAL);
2661 codegen(s, n->car, VAL);
2663 genop_1(s, OP_STRCAT, cursp());
2668 if (n->car) { /* tail */
2670 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2671 codegen(s, tree->car, VAL);
2672 genop_2(s, OP_STRING, cursp(), off);
2674 genop_1(s, OP_STRCAT, cursp());
2677 if (n->cdr->car) { /* opt */
2678 char *p2 = (char*)n->cdr->car;
2679 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2680 genop_2(s, OP_STRING, cursp(), off);
2684 if (n->cdr->cdr) { /* enc */
2685 char *p2 = (char*)n->cdr->cdr;
2686 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2687 genop_2(s, OP_STRING, cursp(), off);
2691 push(); /* space for a block */
2693 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2694 genop_3(s, OP_SEND, cursp(), sym, argc);
2695 mrb_gc_arena_restore(s->mrb, ai);
2699 node *n = tree->car;
2702 if (nint(n->car->car) != NODE_STR) {
2703 codegen(s, n->car, NOVAL);
2712 int sym = new_sym(s, nsym(tree));
2714 genop_2(s, OP_LOADSYM, cursp(), sym);
2720 codegen(s, tree, val);
2728 genop_1(s, OP_LOADSELF, cursp());
2735 genop_1(s, OP_LOADNIL, cursp());
2742 genop_1(s, OP_LOADT, cursp());
2749 genop_1(s, OP_LOADF, cursp());
2756 int a = new_sym(s, nsym(tree->car));
2757 int b = new_sym(s, nsym(tree->cdr));
2759 genop_2(s, OP_ALIAS, a, b);
2761 genop_1(s, OP_LOADNIL, cursp());
2772 int symbol = new_sym(s, nsym(t->car));
2773 genop_1(s, OP_UNDEF, symbol);
2777 genop_1(s, OP_LOADNIL, cursp());
2788 if (tree->car->car == (node*)0) {
2789 genop_1(s, OP_LOADNIL, cursp());
2792 else if (tree->car->car == (node*)1) {
2793 genop_1(s, OP_OCLASS, cursp());
2797 codegen(s, tree->car->car, VAL);
2799 if (tree->cdr->car) {
2800 codegen(s, tree->cdr->car, VAL);
2803 genop_1(s, OP_LOADNIL, cursp());
2807 idx = new_sym(s, nsym(tree->car->cdr));
2808 genop_2(s, OP_CLASS, cursp(), idx);
2809 body = tree->cdr->cdr->car;
2810 if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
2811 genop_1(s, OP_LOADNIL, cursp());
2814 idx = scope_body(s, body, val);
2815 genop_2(s, OP_EXEC, cursp(), idx);
2827 if (tree->car->car == (node*)0) {
2828 genop_1(s, OP_LOADNIL, cursp());
2831 else if (tree->car->car == (node*)1) {
2832 genop_1(s, OP_OCLASS, cursp());
2836 codegen(s, tree->car->car, VAL);
2839 idx = new_sym(s, nsym(tree->car->cdr));
2840 genop_2(s, OP_MODULE, cursp(), idx);
2841 if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2842 tree->cdr->car->cdr->cdr == NULL) {
2843 genop_1(s, OP_LOADNIL, cursp());
2846 idx = scope_body(s, tree->cdr->car, val);
2847 genop_2(s, OP_EXEC, cursp(), idx);
2859 codegen(s, tree->car, VAL);
2861 genop_1(s, OP_SCLASS, cursp());
2862 if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2863 tree->cdr->car->cdr->cdr == NULL) {
2864 genop_1(s, OP_LOADNIL, cursp());
2867 idx = scope_body(s, tree->cdr->car, val);
2868 genop_2(s, OP_EXEC, cursp(), idx);
2878 int sym = new_sym(s, nsym(tree->car));
2879 int idx = lambda_body(s, tree->cdr, 0);
2881 genop_1(s, OP_TCLASS, cursp());
2883 genop_2(s, OP_METHOD, cursp(), idx);
2886 genop_2(s, OP_DEF, cursp(), sym);
2888 genop_2(s, OP_LOADSYM, cursp(), sym);
2896 node *recv = tree->car;
2897 int sym = new_sym(s, nsym(tree->cdr->car));
2898 int idx = lambda_body(s, tree->cdr->cdr, 0);
2900 codegen(s, recv, VAL);
2902 genop_1(s, OP_SCLASS, cursp());
2904 genop_2(s, OP_METHOD, cursp(), idx);
2906 genop_2(s, OP_DEF, cursp(), sym);
2908 genop_2(s, OP_LOADSYM, cursp(), sym);
2915 codegen(s, tree, NOVAL);
2926 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2928 if (s->irep == NULL) {
2932 if (s->irep->rlen == s->rcapa) {
2934 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2936 s->irep->reps[s->irep->rlen] = irep;
2940 static codegen_scope*
2941 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2943 static const codegen_scope codegen_scope_zero = { 0 };
2944 mrb_pool *pool = mrb_pool_open(mrb);
2945 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2947 if (!p) return NULL;
2948 *p = codegen_scope_zero;
2951 if (!prev) return p;
2956 p->irep = mrb_add_irep(mrb);
2957 scope_add_irep(prev, p->irep);
2960 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2963 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2964 p->irep->iseq = NULL;
2967 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2971 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2975 p->sp += node_len(lv)+1; /* add self */
2981 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2982 for (i=0, n=lv; n; i++,n=n->cdr) {
2983 p->irep->lv[i].name = lv_name(n);
2985 p->irep->lv[i].r = lv_idx(p, lv_name(n));
2988 p->irep->lv[i].r = 0;
2991 mrb_assert(i + 1 == p->nlocals);
2993 p->ai = mrb_gc_arena_save(mrb);
2995 p->filename_sym = prev->filename_sym;
2996 if (p->filename_sym) {
2997 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2999 p->lineno = prev->lineno;
3002 p->debug_start_pos = 0;
3003 if (p->filename_sym) {
3004 mrb_debug_info_alloc(mrb, p->irep);
3007 p->irep->debug_info = NULL;
3009 p->parser = prev->parser;
3010 p->filename_index = prev->filename_index;
3012 p->rlev = prev->rlev+1;
3018 scope_finish(codegen_scope *s)
3020 mrb_state *mrb = s->mrb;
3021 mrb_irep *irep = s->irep;
3025 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
3028 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
3029 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
3030 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
3031 if (s->filename_sym) {
3032 mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
3033 const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
3035 mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3036 filename, s->lines, s->debug_start_pos, s->pc);
3038 mrb_free(s->mrb, s->lines);
3040 irep->nlocals = s->nlocals;
3041 irep->nregs = s->nregs;
3043 mrb_gc_arena_restore(mrb, s->ai);
3044 mrb_pool_close(s->mpool);
3047 static struct loopinfo*
3048 loop_push(codegen_scope *s, enum looptype t)
3050 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
3053 p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
3055 p->ensure_level = s->ensure_level;
3063 loop_break(codegen_scope *s, node *tree)
3066 codegen(s, tree, NOVAL);
3067 raise_error(s, "unexpected break");
3070 struct loopinfo *loop;
3074 gen_retval(s, tree);
3079 if (loop->type == LOOP_BEGIN) {
3083 else if (loop->type == LOOP_RESCUE) {
3091 raise_error(s, "unexpected break");
3095 genop_1(s, OP_POPERR, n);
3098 if (loop->type == LOOP_NORMAL) {
3101 if (s->ensure_level > s->loop->ensure_level) {
3102 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
3105 gen_move(s, loop->acc, cursp(), 0);
3107 tmp = genjmp(s, OP_JMP, loop->pc3);
3112 genop_1(s, OP_LOADNIL, cursp());
3114 gen_return(s, OP_BREAK, cursp());
3120 loop_pop(codegen_scope *s, int val)
3123 genop_1(s, OP_LOADNIL, cursp());
3125 dispatch_linked(s, s->loop->pc3);
3126 s->loop = s->loop->prev;
3130 static struct RProc*
3131 generate_code(mrb_state *mrb, parser_state *p, int val)
3133 codegen_scope *scope = scope_new(mrb, 0, 0);
3135 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3142 scope->filename_sym = p->filename_sym;
3143 scope->filename_index = p->current_filename_index;
3145 MRB_TRY(&scope->jmp) {
3146 mrb->jmp = &scope->jmp;
3148 codegen(scope, p->tree, val);
3149 proc = mrb_proc_new(mrb, scope->irep);
3150 mrb_irep_decref(mrb, scope->irep);
3151 mrb_pool_close(scope->mpool);
3153 if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
3156 mrb->jmp = prev_jmp;
3159 MRB_CATCH(&scope->jmp) {
3160 mrb_irep_decref(mrb, scope->irep);
3161 mrb_pool_close(scope->mpool);
3162 mrb->jmp = prev_jmp;
3165 MRB_END_EXC(&scope->jmp);
3168 MRB_API struct RProc*
3169 mrb_generate_code(mrb_state *mrb, parser_state *p)
3171 return generate_code(mrb, p, VAL);
3175 mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
3180 mrb_free(mrb, irep->lv);
3184 for (i = 0; i < irep->rlen; ++i) {
3185 mrb_irep_remove_lv(mrb, irep->reps[i]);
3193 /* instruction sizes */
3194 uint8_t mrb_insn_size[] = {
3200 #define OPCODE(_,x) x,
3201 #include "mruby/ops.h"
3209 /* EXT1 instruction sizes */
3210 uint8_t mrb_insn_size1[] = {
3216 #define OPCODE(_,x) x,
3217 #include "mruby/ops.h"
3221 /* EXT2 instruction sizes */
3222 uint8_t mrb_insn_size2[] = {
3224 #define OPCODE(_,x) x,
3225 #include "mruby/ops.h"
3232 /* EXT3 instruction sizes */
3237 uint8_t mrb_insn_size3[] = {
3238 #define OPCODE(_,x) x,
3239 #include "mruby/ops.h"