summaryrefslogtreecommitdiffhomepage
path: root/src/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c159
1 files changed, 90 insertions, 69 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 2072d278a..11273bf7e 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -26,7 +26,7 @@ enum looptype {
LOOP_FOR,
LOOP_BEGIN,
LOOP_RESCUE,
-} type;
+};
struct loopinfo {
enum looptype type;
@@ -61,8 +61,8 @@ typedef struct scope {
mrb_irep *irep;
size_t pcapa;
- int scapa;
- int rcapa;
+ size_t scapa;
+ size_t rcapa;
int nlocals;
int nregs;
@@ -89,10 +89,10 @@ codegen_error(codegen_scope *s, const char *message)
{
if (!s) return;
while (s->prev) {
+ codegen_scope *tmp = s->prev;
mrb_pool_close(s->mpool);
- s = s->prev;
+ s = tmp;
}
- mrb_pool_close(s->mpool);
#ifdef ENABLE_STDIO
if (s->filename && s->lineno) {
fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
@@ -113,19 +113,19 @@ codegen_palloc(codegen_scope *s, size_t len)
return p;
}
-void*
+static void*
codegen_malloc(codegen_scope *s, size_t len)
{
- void *p = mrb_malloc(s->mrb, len);
+ void *p = mrb_malloc_simple(s->mrb, len);
if (!p) codegen_error(s, "mrb_malloc");
return p;
}
-void*
+static void*
codegen_realloc(codegen_scope *s, void *p, size_t len)
{
- p = mrb_realloc(s->mrb, p, len);
+ p = mrb_realloc_simple(s->mrb, p, len);
if (!p && len > 0) codegen_error(s, "mrb_realloc");
return p;
@@ -316,8 +316,8 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
if (c0 == OP_STRING) {
int i = GETARG_Bx(i0);
- if (s->irep->pool[i].type == IREP_TT_STRING &&
- s->irep->pool[i].value.s->len == 0) {
+ if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
+ RSTRING_LEN(s->irep->pool[i]) == 0) {
s->pc--;
return;
}
@@ -397,7 +397,7 @@ static inline int
new_lit(codegen_scope *s, mrb_value val)
{
size_t i;
- struct irep_pool *pv;
+ mrb_value *pv;
switch (mrb_type(val)) {
case MRB_TT_STRING:
@@ -405,24 +405,24 @@ new_lit(codegen_scope *s, mrb_value val)
mrb_int len;
pv = &s->irep->pool[i];
- if (pv->type != IREP_TT_STRING) continue;
- if ((len = pv->value.s->len) != RSTRING_LEN(val)) continue;
- if (memcmp(pv->value.s->buf, RSTRING_PTR(val), len) == 0)
+ if (mrb_type(*pv) != MRB_TT_STRING) continue;
+ if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
+ if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
return i;
}
break;
case MRB_TT_FLOAT:
for (i=0; i<s->irep->plen; i++) {
pv = &s->irep->pool[i];
- if (pv->type != IREP_TT_FLOAT) continue;
- if (pv->value.f == mrb_float(val)) return i;
+ if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
+ if (mrb_float(*pv) == mrb_float(val)) return i;
}
break;
case MRB_TT_FIXNUM:
for (i=0; i<s->irep->plen; i++) {
pv = &s->irep->pool[i];
- if (pv->type != IREP_TT_FIXNUM) continue;
- if (pv->value.i == mrb_fixnum(val)) return i;
+ if (!mrb_fixnum_p(*pv)) continue;
+ if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
}
break;
default:
@@ -432,7 +432,7 @@ new_lit(codegen_scope *s, mrb_value val)
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
- s->irep->pool = (struct irep_pool*)codegen_realloc(s, s->irep->pool, sizeof(struct irep_pool)*s->pcapa);
+ s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
}
pv = &s->irep->pool[s->irep->plen];
@@ -440,19 +440,18 @@ new_lit(codegen_scope *s, mrb_value val)
switch (mrb_type(val)) {
case MRB_TT_STRING:
- pv->type = IREP_TT_STRING;
- pv->value.s = (struct irep_pool_string*)codegen_malloc(s, sizeof(struct irep_pool_string) + RSTRING_LEN(val));
- pv->value.s->len = RSTRING_LEN(val);
- memcpy(pv->value.s->buf, RSTRING_PTR(val), RSTRING_LEN(val));
+ *pv = mrb_str_pool(s->mrb, val);
break;
+
case MRB_TT_FLOAT:
- pv->type = IREP_TT_FLOAT;
- pv->value.f = mrb_float(val);
+#ifdef MRB_WORD_BOXING
+ *pv = mrb_float_pool(s->mrb, mrb_float(val));
break;
+#endif
case MRB_TT_FIXNUM:
- pv->type = IREP_TT_FIXNUM;
- pv->value.i = mrb_fixnum(val);
+ *pv = val;
break;
+
default:
/* should not happen */
break;
@@ -566,7 +565,7 @@ for_body(codegen_scope *s, node *tree)
s = prev;
genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
pop();
- idx = new_msym(s, mrb_intern2(s->mrb, "each", 4));
+ idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
}
@@ -658,7 +657,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
}
static int
-scope_body(codegen_scope *s, node *tree)
+scope_body(codegen_scope *s, node *tree, int val)
{
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
@@ -666,15 +665,16 @@ scope_body(codegen_scope *s, node *tree)
if (!s->iseq) {
genop(scope, MKOP_A(OP_STOP, 0));
}
+ else if (!val) {
+ genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
else {
if (scope->nregs == 0) {
genop(scope, MKOP_A(OP_LOADNIL, 0));
genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
}
else {
- pop();
- genop_peep(scope, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
- push();
+ genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
}
}
scope_finish(scope);
@@ -708,7 +708,7 @@ attrsym(codegen_scope *s, mrb_sym a)
name2[len] = '=';
name2[len+1] = '\0';
- return mrb_intern2(s->mrb, name2, len+1);
+ return mrb_intern(s->mrb, name2, len+1);
}
static int
@@ -977,11 +977,11 @@ static void
gen_send_intern(codegen_scope *s)
{
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
push();
}
static void
-gen_literal_array(codegen_scope *s, node *tree, int sym, int val)
+gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
{
if (val) {
int i = 0, j = 0;
@@ -1069,7 +1069,7 @@ readint_float(codegen_scope *s, const char *p, int base)
}
static mrb_int
-readint_mrb_int(codegen_scope *s, const char *p, int base, int neg, int *overflow)
+readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
{
const char *e = p + strlen(p);
mrb_int result = 0;
@@ -1177,12 +1177,12 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n4->car, VAL);
}
else {
- genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13))));
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
push();
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
tmp = new_label(s);
genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
@@ -1236,7 +1236,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_Bx(OP_EPUSH, 0));
s->ensure_level++;
codegen(s, tree->car, val);
- idx = scope_body(s, tree->cdr);
+ idx = scope_body(s, tree->cdr, NOVAL);
s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
s->ensure_level--;
genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
@@ -1386,7 +1386,12 @@ codegen(codegen_scope *s, node *tree, int val)
if (head) {
genop(s, MKOP_AB(OP_MOVE, cursp(), head));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1));
+ if ((intptr_t)n->car->car == NODE_SPLAT) {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
+ }
+ else {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
+ }
}
else {
pop();
@@ -1410,15 +1415,21 @@ codegen(codegen_scope *s, node *tree, int val)
tree = tree->cdr;
}
if (val) {
+ int pos = cursp();
genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ if (pos3) dispatch_linked(s, pos3);
+ pop();
+ genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
push();
}
- if (pos3) dispatch_linked(s, pos3);
+ else if (pos3) {
+ dispatch_linked(s, pos3);
+ }
}
break;
case NODE_SCOPE:
- scope_body(s, tree);
+ scope_body(s, tree, NOVAL);
break;
case NODE_FCALL:
@@ -1726,7 +1737,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
pop_n(n+1);
if (sendv) n = CALL_MAXARGS;
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
if (val) push();
}
break;
@@ -1915,7 +1926,7 @@ codegen(codegen_scope *s, node *tree, int val)
int base = (intptr_t)tree->cdr->car;
mrb_int i;
mrb_code co;
- int overflow;
+ mrb_bool overflow;
i = readint_mrb_int(s, p, base, FALSE, &overflow);
if (overflow) {
@@ -1971,7 +1982,7 @@ codegen(codegen_scope *s, node *tree, int val)
int base = (intptr_t)tree->cdr->car;
mrb_int i;
mrb_code co;
- int overflow;
+ mrb_bool overflow;
i = readint_mrb_int(s, p, base, TRUE, &overflow);
if (overflow) {
@@ -1996,7 +2007,7 @@ codegen(codegen_scope *s, node *tree, int val)
default:
{
- int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1));
+ int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
push();
@@ -2064,7 +2075,7 @@ codegen(codegen_scope *s, node *tree, int val)
char *p = (char*)tree->car;
size_t len = (intptr_t)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
- int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6));
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
genop(s, MKOP_A(OP_OCLASS, cursp()));
@@ -2072,7 +2083,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
pop();
- sym = new_sym(s, mrb_intern2(s->mrb, "`", 1));
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
mrb_gc_arena_restore(s->mrb, ai);
push();
@@ -2084,7 +2095,7 @@ codegen(codegen_scope *s, node *tree, int val)
char *p1 = (char*)tree->car;
char *p2 = (char*)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
- int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN));
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1)));
int argc = 1;
@@ -2100,7 +2111,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
mrb_gc_arena_restore(s->mrb, ai);
push();
@@ -2111,7 +2122,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
node *n = tree->car;
int ai = mrb_gc_arena_save(s->mrb);
- int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN));
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
int argc = 1;
int off;
char *p;
@@ -2148,7 +2159,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
pop();
- sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7));
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
mrb_gc_arena_restore(s->mrb, ai);
push();
@@ -2213,7 +2224,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
int a = new_msym(s, sym(tree->car));
int b = new_msym(s, sym(tree->cdr));
- int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12));
+ int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method"));
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
@@ -2232,7 +2243,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_UNDEF:
{
- int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12));
+ int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
int num = 0;
node *t = tree;
@@ -2278,7 +2289,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop(); pop();
idx = new_msym(s, sym(tree->car->cdr));
genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
- idx = scope_body(s, tree->cdr->cdr->car);
+ idx = scope_body(s, tree->cdr->cdr->car, val);
genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
if (val) {
push();
@@ -2304,7 +2315,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
idx = new_msym(s, sym(tree->car->cdr));
genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
- idx = scope_body(s, tree->cdr->car);
+ idx = scope_body(s, tree->cdr->car, val);
genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
if (val) {
push();
@@ -2319,7 +2330,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
- idx = scope_body(s, tree->cdr->car);
+ idx = scope_body(s, tree->cdr->car, val);
genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
if (val) {
push();
@@ -2412,13 +2423,14 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
p->icapa = 1024;
p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
+ p->irep->iseq = p->iseq;
p->pcapa = 32;
- p->irep->pool = (struct irep_pool*)mrb_malloc(mrb, sizeof(struct irep_pool)*p->pcapa);
+ p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
p->irep->plen = 0;
p->scapa = 256;
- p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*256);
+ p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
p->irep->slen = 0;
p->lv = lv;
@@ -2467,7 +2479,7 @@ scope_finish(codegen_scope *s)
irep->lines = 0;
}
}
- irep->pool = (struct irep_pool*)codegen_realloc(s, irep->pool, sizeof(struct irep_pool)*irep->plen);
+ irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
if (s->filename) {
@@ -2722,7 +2734,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
break;
case OP_LAMBDA:
- printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c), GETARG_c(c));
+ printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c));
break;
case OP_RANGE:
printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
@@ -2809,8 +2821,8 @@ codedump(mrb_state *mrb, mrb_irep *irep)
break;
case OP_STRING:
{
- struct irep_pool *pv = &irep->pool[GETARG_Bx(c)];
- mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, pv->value.s->buf, pv->value.s->len));
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s));
}
break;
@@ -2833,7 +2845,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_EXEC:
- printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c));
+ printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)+1);
break;
case OP_SCLASS:
printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
@@ -2842,10 +2854,14 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf("OP_TCLASS\tR%d\n", GETARG_A(c));
break;
case OP_ERR:
- printf("OP_ERR\tL(%d)\n", GETARG_Bx(c));
+ {
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
+ printf("OP_ERR\t%s\n", RSTRING_PTR(s));
+ }
break;
case OP_EPUSH:
- printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c));
+ printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
break;
case OP_ONERR:
printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
@@ -2886,9 +2902,9 @@ codedump_recur(mrb_state *mrb, mrb_irep *irep)
}
void
-codedump_all(mrb_state *mrb, struct RProc *proc)
+mrb_codedump_all(mrb_state *mrb, struct RProc *proc)
{
- return codedump_recur(mrb, proc->body.irep);
+ codedump_recur(mrb, proc->body.irep);
}
struct RProc*
@@ -2913,6 +2929,11 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
return proc;
}
else {
+ if (scope->filename == scope->irep->filename) {
+ scope->irep->filename = NULL;
+ }
+ mrb_irep_decref(mrb, scope->irep);
+ mrb_pool_close(scope->mpool);
return NULL;
}
}