diff options
Diffstat (limited to 'src/codegen.c')
| -rw-r--r-- | src/codegen.c | 479 |
1 files changed, 329 insertions, 150 deletions
diff --git a/src/codegen.c b/src/codegen.c index 505f0ad5b..bf6fd0b3e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -10,12 +10,13 @@ #include "mruby.h" #include "mruby/string.h" #include "mruby/irep.h" -#include "mruby/proc.h" #include "mruby/compile.h" +#include "mruby/numeric.h" #include "opcode.h" #include "node.h" #include <string.h> #include <stdlib.h> +#include <ctype.h> typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -47,7 +48,8 @@ typedef struct scope { int sp; int pc; int lastlabel; - int ainfo; + int ainfo:15; + int mscope:1; struct loopinfo *loop; int ensure_level; @@ -89,7 +91,9 @@ codegen_error(codegen_scope *s, const char *message) s = s->prev; } mrb_pool_close(s->mpool); +#ifdef ENABLE_STDIO fprintf(stderr, "codegen error: %s\n", message); +#endif longjmp(s->jmp, 1); } @@ -132,7 +136,7 @@ genop(codegen_scope *s, mrb_code i) { if (s->pc == s->icapa) { s->icapa *= 2; - s->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); + s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); } s->iseq[s->pc] = i; s->pc++; @@ -141,7 +145,7 @@ genop(codegen_scope *s, mrb_code i) static void genop_peep(codegen_scope *s, mrb_code i, int val) { - // peephole optimization + /* peephole optimization */ if (!val && s->lastlabel != s->pc && s->pc > 0) { mrb_code i0 = s->iseq[s->pc-1]; int c1 = GET_OPCODE(i); @@ -152,9 +156,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val) switch (c0) { case OP_MOVE: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) { - // skip swapping OP_MOVE + /* skip swapping OP_MOVE */ return; } + if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { + s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)); + return; + } break; case OP_LOADI: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { @@ -180,7 +188,6 @@ genop_peep(codegen_scope *s, mrb_code i, int val) case OP_GETSPECIAL: case OP_LOADL: case OP_STRING: - case OP_GETMCNST: if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); return; @@ -202,29 +209,27 @@ genop_peep(codegen_scope *s, mrb_code i, int val) return; } break; + default: + break; } break; case OP_SETIV: case OP_SETCV: case OP_SETCONST: case OP_SETMCNST: - switch (c0) { - case OP_MOVE: + if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); return; } - break; } break; case OP_SETUPVAR: - switch (c0) { - case OP_MOVE: + if (c0 == OP_MOVE) { if (GETARG_A(i) == GETARG_A(i0)) { s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); return; } - break; } break; case OP_EPOP: @@ -239,6 +244,52 @@ genop_peep(codegen_scope *s, mrb_code i, int val) return; } break; + case OP_RETURN: + switch (c0) { + case OP_MOVE: + s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); + return; + case OP_LOADI: + s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, 0, GETARG_sBx(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_ARRAY: + case OP_HASH: + case OP_RANGE: + case OP_AREF: + case OP_GETUPVAR: + s->iseq[s->pc-1] = MKOP_ABC(c0, 0, GETARG_B(i0), GETARG_C(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_LOADSYM: + case OP_GETGLOBAL: + case OP_GETIV: + case OP_GETCV: + case OP_GETCONST: + case OP_GETSPECIAL: + case OP_LOADL: + case OP_STRING: + s->iseq[s->pc-1] = MKOP_ABx(c0, 0, GETARG_Bx(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_SCLASS: + s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + case OP_LOADNIL: + case OP_LOADSELF: + case OP_LOADT: + case OP_LOADF: + case OP_OCLASS: + s->iseq[s->pc-1] = MKOP_A(c0, 0); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + return; + default: + break; + } + break; + default: + break; } } genop(s, i); @@ -265,7 +316,9 @@ dispatch(codegen_scope *s, int pc) case OP_ONERR: break; default: +#ifdef ENABLE_STDIO fprintf(stderr, "bug: dispatch on non JMP op\n"); +#endif scope_error(s); } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); @@ -297,21 +350,10 @@ push_(codegen_scope *s) s->sp++; nregs_update; } -#if 0 -static void -push_n_(codegen_scope *s, int n) -{ - if (s->sp + n > 511) { - codegen_error(s, "too complex expression"); - } - s->sp += n; - nregs_update; -} -#endif #define push() push_(s) -#define push_n(n) push_n_(s, n) -#define pop() (s->sp--) +#define pop_(s) ((s)->sp--) +#define pop() pop_(s) #define pop_n(n) (s->sp-=(n)) #define cursp() (s->sp) @@ -321,11 +363,11 @@ new_lit(codegen_scope *s, mrb_value val) int i; for (i=0; i<s->plen; i++) { - if (memcmp(&s->pool[i], &val, sizeof(mrb_value)) == 0) return i; + if (mrb_obj_equal(s->mrb, s->pool[i], val)) return i; } if (s->plen == s->pcapa) { s->pcapa *= 2; - s->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa); + s->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa); } s->pool[s->plen] = val; return s->plen++; @@ -359,7 +401,7 @@ new_sym(codegen_scope *s, mrb_sym sym) if (s->syms[i] == sym) return i; } if (s->slen > 125 && s->slen < 256) { - s->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536); + s->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536); memset(s->syms+s->slen, 0, sizeof(mrb_sym)*(256-s->slen)); s->slen = 256; } @@ -429,7 +471,7 @@ for_body(codegen_scope *s, node *tree) pop(); c = s->iseq[s->pc-1]; if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } loop_pop(s, NOVAL); scope_finish(s, idx); @@ -448,6 +490,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) s = scope_new(s->mrb, s, tree->car); idx = s->idx; + s->mscope = !blk; if (blk) { struct loopinfo *lp = loop_push(s, LOOP_BLOCK); @@ -484,10 +527,10 @@ lambda_body(codegen_scope *s, node *tree, int blk) pos = new_label(s); for (i=0; i<oa; i++) { new_label(s); - genop(s, MKOP_Ax(OP_JMP, 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); } if (oa > 0) { - genop(s, MKOP_Ax(OP_JMP, 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); } opt = tree->car->cdr->car; i = 0; @@ -510,7 +553,13 @@ lambda_body(codegen_scope *s, node *tree, int blk) pop(); c = s->iseq[s->pc-1]; if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + if (s->nregs == 0) { + genop(s, MKOP_A(OP_LOADNIL, 0)); + genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + } + else { + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); + } } if (blk) { loop_pop(s, NOVAL); @@ -526,13 +575,19 @@ scope_body(codegen_scope *s, node *tree) codegen_scope *scope = scope_new(s->mrb, s, tree->car); int idx = scope->idx; + codegen(scope, tree->cdr, VAL); if (!s->iseq) { - codegen(scope, tree->cdr, VAL); genop(scope, MKOP_A(OP_STOP, 0)); } else { - codegen(scope, tree->cdr, VAL); - genop(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL)); + pop_(scope); + if (scope->nregs == 0) { + genop(scope, MKOP_A(OP_LOADNIL, 0)); + genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + } + else { + genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL), NOVAL); + } } scope_finish(scope, idx); @@ -552,16 +607,17 @@ nosplat(node *t) static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { - const char *name = mrb_sym2name(s->mrb, a); + const char *name; + int len; char *name2; - size_t len = strlen(name); - name2 = codegen_palloc(s, len+1); - strcpy(name2, name); + name = mrb_sym2name_len(s->mrb, a, &len); + name2 = (char *)codegen_palloc(s, len+1); + memcpy(name2, name, len); name2[len] = '='; name2[len+1] = '\0'; - return mrb_intern(s->mrb, name2); + return mrb_intern2(s->mrb, name2, len+1); } static int @@ -607,7 +663,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) { mrb_sym sym = name ? name : (mrb_sym)tree->cdr->car; int idx; - int n = 0, noop = 0, sendv = 0; + int n = 0, noop = 0, sendv = 0, blk = 0; codegen(s, tree->car, VAL); /* receiver */ idx = new_msym(s, sym); @@ -637,31 +693,44 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) pop(); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + blk = cursp(); } pop_n(n+1); { - const char *name = mrb_sym2name(s->mrb, sym); + int len; + const char *name = mrb_sym2name_len(s->mrb, sym, &len); - if (!noop && name[0] == '+' && strlen(name) == 1) { + if (!noop && len == 1 && name[0] == '+') { genop(s, MKOP_ABC(OP_ADD, cursp(), idx, n)); } - else if (!noop && name[0] == '-' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '-') { genop(s, MKOP_ABC(OP_SUB, cursp(), idx, n)); } - else if (!noop && name[0] == '<' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '*') { + genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n)); + } + else if (!noop && len == 1 && name[0] == '/') { + genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n)); + } + else if (!noop && len == 1 && name[0] == '<') { genop(s, MKOP_ABC(OP_LT, cursp(), idx, n)); } - else if (!noop && name[0] == '<' && strlen(name) == 2 && name[1] == '=') { + else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') { genop(s, MKOP_ABC(OP_LE, cursp(), idx, n)); } - else if (!noop && name[0] == '>' && strlen(name) == 1) { + else if (!noop && len == 1 && name[0] == '>') { genop(s, MKOP_ABC(OP_GT, cursp(), idx, n)); } - else if (!noop && name[0] == '>' && strlen(name) == 2 && name[1] == '=') { + else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') { genop(s, MKOP_ABC(OP_GE, cursp(), idx, n)); } + else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') { + genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n)); + } else { + if (blk > 0) { /* no block */ + genop(s, MKOP_A(OP_LOADNIL, blk)); + } if (sendv) n = CALL_MAXARGS; genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n)); } @@ -735,7 +804,9 @@ gen_assignment(codegen_scope *s, node *node, int sp, int val) break; default: +#ifdef ENABLE_STDIO printf("unknown lhs %d\n", type); +#endif break; } if (val) push(); @@ -795,6 +866,32 @@ raise_error(codegen_scope *s, const char *msg) genop(s, MKOP_ABx(OP_ERR, 0, idx)); } +static double +readint_float(codegen_scope *s, const char *p, int base) +{ + const char *e = p + strlen(p); + double f = 0; + int n; + + if (*p == '+') p++; + while (p < e) { + char c = *p; + c = tolower((unsigned char)c); + for (n=0; n<base; n++) { + if (mrb_digitmap[n] == c) { + f *= base; + f += n; + break; + } + } + if (n == base) { + codegen_error(s, "malformed readint input"); + } + p++; + } + return f; +} + static void codegen(codegen_scope *s, node *tree, int val) { @@ -838,28 +935,34 @@ codegen(codegen_scope *s, node *tree, int val) push(); while (n2) { node *n3 = n2->car; + node *n4 = n3->car; if (pos1) dispatch(s, pos1); - if (n3->car) { - node *n4 = n3->car; - - pos2 = 0; - while (n4) { + pos2 = 0; + do { + if (n4) { codegen(s, n4->car, VAL); - genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); + } + else { + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError")))); push(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - pop(); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); - tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); - pos2 = tmp; + } + genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); + push(); + genop(s, MKOP_A(OP_LOADNIL, cursp())); + pop(); pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + tmp = new_label(s); + genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + pos2 = tmp; + if (n4) { n4 = n4->cdr; } - pos1 = new_label(s); - genop(s, MKOP_Bx(OP_JMP, 0)); - dispatch_linked(s, pos2); - } + } while (n4); + pos1 = new_label(s); + genop(s, MKOP_sBx(OP_JMP, 0)); + dispatch_linked(s, pos2); + pop(); if (n3->cdr->car) { gen_assignment(s, n3->cdr->car, exc, NOVAL); @@ -868,7 +971,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n3->cdr->cdr->car, val); } tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), exend)); + genop(s, MKOP_sBx(OP_JMP, exend)); exend = tmp; n2 = n2->cdr; push(); @@ -878,6 +981,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_RAISE, exc)); } } + pop(); tree = tree->cdr; dispatch(s, noexc); genop(s, MKOP_A(OP_POPERR, 1)); @@ -983,13 +1087,14 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc1 = new_label(s); - codegen(s, tree->car, VAL); - pop(); + genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); codegen(s, tree->cdr, NOVAL); - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); - dispatch(s, lp->pc2); + dispatch(s, lp->pc1); + codegen(s, tree->car, VAL); + pop(); + genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc)); + loop_pop(s, val); } break; @@ -999,13 +1104,14 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc1 = new_label(s); - codegen(s, tree->car, VAL); - pop(); + genop(s, MKOP_sBx(OP_JMP, 0)); lp->pc2 = new_label(s); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); codegen(s, tree->cdr, NOVAL); - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); - dispatch(s, lp->pc2); + dispatch(s, lp->pc1); + codegen(s, tree->car, VAL); + pop(); + genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc)); + loop_pop(s, val); } break; @@ -1046,21 +1152,23 @@ codegen(codegen_scope *s, node *tree, int val) } if (tree->car->car) { pos1 = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), 0)); + genop(s, MKOP_sBx(OP_JMP, 0)); dispatch_linked(s, pos2); } - pop(); pop(); + pop(); codegen(s, tree->car->cdr, val); + pop(); tmp = new_label(s); - genop(s, MKOP_AsBx(OP_JMP, cursp(), pos3)); + genop(s, MKOP_sBx(OP_JMP, pos3)); pos3 = tmp; if (pos1) dispatch(s, pos1); tree = tree->cdr; - push(); push(); + push(); } pop(); - if (pos3) dispatch_linked(s, pos3); + genop(s, MKOP_A(OP_LOADNIL, cursp())); if (val) push(); + if (pos3) dispatch_linked(s, pos3); } break; @@ -1227,12 +1335,14 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = (mrb_sym)tree->cdr->car; - const char *name = mrb_sym2name(s->mrb, sym); - int idx; + int len; + const char *name = mrb_sym2name_len(s->mrb, sym, &len); + int idx, blk = 0; codegen(s, tree->car, VAL); - if ((name[0] == '|' && strlen(name) == 2 && name[1] == '|') || - (name[0] == '&' && strlen(name) == 2 && name[1] == '&')) { + if (len == 2 && + ((name[0] == '|' && name[1] == '|') || + (name[0] == '&' && name[1] == '&'))) { int pos; pop(); @@ -1245,29 +1355,32 @@ codegen(codegen_scope *s, node *tree, int val) break; } codegen(s, tree->cdr->cdr->car, VAL); - genop(s, MKOP_A(OP_LOADNIL, cursp())); + blk = cursp(); pop(); pop(); idx = new_msym(s, sym); - if (name[0] == '+' && strlen(name) == 1) { + if (len == 1 && name[0] == '+') { genop(s, MKOP_ABC(OP_ADD, cursp(), idx, 1)); } - else if (name[0] == '-' && strlen(name) == 1) { + else if (len == 1 && name[0] == '-') { genop(s, MKOP_ABC(OP_SUB, cursp(), idx, 1)); } - else if (name[0] == '<' && strlen(name) == 1) { + else if (len == 1 && name[0] == '<') { genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1)); } - else if (name[0] == '<' && strlen(name) == 2 && name[1] == '=') { + else if (len == 2 && name[0] == '<' && name[1] == '=') { genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1)); } - else if (name[0] == '>' && strlen(name) == 1) { + else if (len == 1 && name[0] == '>') { genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1)); } - else if (name[0] == '>' && strlen(name) == 2 && name[1] == '=') { + else if (len == 2 && name[0] == '>' && name[1] == '=') { genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1)); } else { + if (blk > 0) { + genop(s, MKOP_A(OP_LOADNIL, blk)); + } genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); } } @@ -1276,16 +1389,18 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_SUPER: { - int n = 0; + int n = 0, noop = 0, sendv = 0; - push(); + push(); /* room for receiver */ if (tree) { node *args = tree->car; - while (args) { - codegen(s, args->car, VAL); - n++; - args = args->cdr; - } + if (args) { + n = gen_values(s, args); + if (n < 0) { + n = noop = sendv = 1; + push(); + } + } } if (tree && tree->cdr) { codegen(s, tree->cdr, VAL); @@ -1295,6 +1410,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_LOADNIL, cursp())); } pop_n(n+1); + if (sendv) n = CALL_MAXARGS; genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n)); if (val) push(); } @@ -1305,14 +1421,19 @@ codegen(codegen_scope *s, node *tree, int val) codegen_scope *s2 = s; int lv = 0, ainfo = 0; - while (s2->ainfo < 0) { + push(); /* room for receiver */ + while (!s2->mscope) { lv++; s2 = s2->prev; if (!s2) break; } if (s2) ainfo = s2->ainfo; - push(); genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf))); + if (tree && tree->cdr) { + push(); + codegen(s, tree->cdr, VAL); + pop_n(2); + } pop(); genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS)); if (val) push(); @@ -1326,7 +1447,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN)); } else { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } break; @@ -1336,7 +1457,7 @@ codegen(codegen_scope *s, node *tree, int val) int lv = 0, ainfo = 0; int n = 0, sendv = 0; - while (s2->ainfo < 0) { + while (!s2->mscope) { lv++; s2 = s2->prev; if (!s2) break; @@ -1378,7 +1499,7 @@ codegen(codegen_scope *s, node *tree, int val) else { codegen(s, tree, VAL); pop(); - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL)); + genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } if (val) push(); break; @@ -1498,10 +1619,11 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_BACK_REF: { char buf[4]; + int len; int sym; - snprintf(buf, 3, "$%c", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern(s->mrb, buf)); + len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree); + sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1510,10 +1632,11 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_NTH_REF: { char buf[4]; + int len; int sym; - snprintf(buf, 3, "$%d", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern(s->mrb, buf)); + len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree); + sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1531,17 +1654,27 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - int i = readint(p, base); + double f; + mrb_int i; mrb_code co; - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); + f = readint_float(s, p, base); + if (!FIXABLE(f)) { + int off = new_lit(s, mrb_float_value(f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); } else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); + i = (mrb_int)f; + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); } - genop(s, co); push(); } break; @@ -1577,18 +1710,27 @@ codegen(codegen_scope *s, node *tree, int val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - int i = readint(p, base); + mrb_float f; + mrb_int i; mrb_code co; - i = -i; - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } - else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); - } - genop(s, co); + f = readint_float(s, p, base); + if (!FIXABLE(f)) { + int off = new_lit(s, mrb_float_value(-f)); + + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + } + else { + i = (mrb_int)-f; + if (i < MAXARG_sBx && i > -MAXARG_sBx) { + co = MKOP_AsBx(OP_LOADI, cursp(), i); + } + else { + int off = new_lit(s, mrb_fixnum_value(i)); + co = MKOP_ABx(OP_LOADL, cursp(), off); + } + genop(s, co); + } push(); } break; @@ -1654,6 +1796,15 @@ codegen(codegen_scope *s, node *tree, int val) } break; + case NODE_DSYM: + codegen(s, tree, val); + if (val) { + pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); + push(); + } + break; + case NODE_SELF: if (val) { genop(s, MKOP_A(OP_LOADSELF, cursp())); @@ -1843,7 +1994,7 @@ static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) { mrb_pool *pool = mrb_pool_open(mrb); - codegen_scope *p = mrb_pool_alloc(pool, sizeof(codegen_scope)); + codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); if (!p) return 0; memset(p, 0, sizeof(codegen_scope)); @@ -1852,15 +2003,16 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) if (!prev) return p; p->prev = prev; p->ainfo = -1; + p->mscope = 0; p->mrb = prev->mrb; p->icapa = 1024; - p->iseq = mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); + p->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); p->pcapa = 32; - p->pool = mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); + p->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); - p->syms = mrb_malloc(mrb, sizeof(mrb_sym)*256); + p->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym)*256); p->lv = lv; p->sp += node_len(lv)+2; @@ -1879,20 +2031,20 @@ scope_finish(codegen_scope *s, int idx) mrb_irep *irep; mrb_add_irep(mrb, idx); - irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep)); + irep = mrb->irep[idx] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); irep->idx = idx; irep->flags = 0; if (s->iseq) { - irep->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); + irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); irep->ilen = s->pc; } if (s->pool) { - irep->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen); + irep->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen); irep->plen = s->plen; } if (s->syms) { - irep->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen); + irep->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen); irep->slen = s->slen; } @@ -1906,7 +2058,7 @@ scope_finish(codegen_scope *s, int idx) static struct loopinfo* loop_push(codegen_scope *s, enum looptype t) { - struct loopinfo *p = codegen_palloc(s, sizeof(struct loopinfo)); + struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); p->type = t; p->pc1 = p->pc2 = p->pc3 = 0; @@ -1971,6 +2123,7 @@ loop_pop(codegen_scope *s, int val) static void codedump(mrb_state *mrb, int n) { +#ifdef ENABLE_STDIO mrb_irep *irep = mrb->irep[n]; int i; mrb_code c; @@ -1995,7 +2148,7 @@ codedump(mrb_state *mrb, int n) printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c)); break; case OP_LOADSYM: - printf("OP_LOADSYM\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_LOADNIL: @@ -2011,20 +2164,20 @@ codedump(mrb_state *mrb, int n) printf("OP_LOADF\tR%d\n", GETARG_A(c)); break; case OP_GETGLOBAL: - printf("OP_GETGLOBAL\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_SETGLOBAL: - printf("OP_SETGLOBAL\t'%s'\tR%d\n", + printf("OP_SETGLOBAL\t:%s\tR%d\n", mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), GETARG_A(c)); break; case OP_GETCONST: - printf("OP_GETCONST\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); break; case OP_SETCONST: - printf("OP_SETCONST\t'%s'\tR%d\n", + printf("OP_SETCONST\t:%s\tR%d\n", mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), GETARG_A(c)); break; @@ -2073,7 +2226,12 @@ codedump(mrb_state *mrb, int n) printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); break; case OP_SEND: - printf("OP_SEND\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_TAILCALL: + printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; @@ -2128,37 +2286,52 @@ codedump(mrb_state *mrb, int n) printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); break; case OP_METHOD: - printf("OP_METHOD\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_ADD: - printf("OP_ADD\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_SUB: - printf("OP_SUB\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_MUL: + printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_DIV: + printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_LT: - printf("OP_LT\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_LE: - printf("OP_LE\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_GT: - printf("OP_GT\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; case OP_GE: - printf("OP_GE\tR%d\t'%s'\t%d\n", GETARG_A(c), + printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c), + mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), + GETARG_C(c)); + break; + case OP_EQ: + printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; @@ -2183,7 +2356,12 @@ codedump(mrb_state *mrb, int n) printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); break; case OP_STRING: - printf("OP_STRING\tR%d\t'%s'\n", GETARG_A(c), RSTRING_PTR(irep->pool[GETARG_Bx(c)])); + { + mrb_value s = irep->pool[GETARG_Bx(c)]; + + s = mrb_str_dump(mrb, s); + printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s)); + } break; case OP_STRCAT: printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c)); @@ -2196,11 +2374,11 @@ codedump(mrb_state *mrb, int n) printf("OP_OCLASS\tR%d\n", GETARG_A(c)); break; case OP_CLASS: - printf("OP_CLASS\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_MODULE: - printf("OP_MODULE\tR%d\t'%s'\n", GETARG_A(c), + printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_EXEC: @@ -2213,7 +2391,7 @@ codedump(mrb_state *mrb, int n) printf("OP_TCLASS\tR%d\n", GETARG_A(c)); break; case OP_ERR: - printf("OP_ERR\t:L(%d)\n", GETARG_Bx(c)); + printf("OP_ERR\tL(%d)\n", GETARG_Bx(c)); break; case OP_EPUSH: printf("OP_EPUSH\t:I(%d)\n", n+GETARG_Bx(c)); @@ -2241,6 +2419,7 @@ codedump(mrb_state *mrb, int n) } } printf("\n"); +#endif } void |
