summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c133
1 files changed, 92 insertions, 41 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 9b064b867..23e036d49 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -93,6 +93,7 @@ codegen_error(codegen_scope *s, const char *message)
if (!s) return;
while (s->prev) {
codegen_scope *tmp = s->prev;
+ mrb_free(s->mrb, s->iseq);
mrb_pool_close(s->mpool);
s = tmp;
}
@@ -387,6 +388,9 @@ dispatch(codegen_scope *s, int pc)
scope_error(s);
break;
}
+ if (diff > MAXARG_sBx) {
+ codegen_error(s, "too distant jump address");
+ }
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -500,7 +504,12 @@ new_lit(codegen_scope *s, mrb_value val)
return i;
}
-static inline int
+/* method symbols should be fit in 9 bits */
+#define MAXMSYMLEN 512
+/* maximum symbol numbers */
+#define MAXSYMLEN 65536
+
+static int
new_msym(codegen_scope *s, mrb_sym sym)
{
size_t i, len;
@@ -508,20 +517,20 @@ new_msym(codegen_scope *s, mrb_sym sym)
mrb_assert(s->irep);
len = s->irep->slen;
- if (len > 256) len = 256;
+ if (len > MAXMSYMLEN) len = MAXMSYMLEN;
for (i=0; i<len; i++) {
if (s->irep->syms[i] == sym) return i;
if (s->irep->syms[i] == 0) break;
}
- if (i == 256) {
- codegen_error(s, "too many symbols (max 256)");
+ if (i == MAXMSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
}
s->irep->syms[i] = sym;
if (i == s->irep->slen) s->irep->slen++;
return i;
}
-static inline int
+static int
new_sym(codegen_scope *s, mrb_sym sym)
{
size_t i;
@@ -529,13 +538,18 @@ new_sym(codegen_scope *s, mrb_sym sym)
for (i=0; i<s->irep->slen; i++) {
if (s->irep->syms[i] == sym) return i;
}
- if (s->irep->slen > 125 && s->irep->slen < 256) {
- s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536);
- for (i = 0; i < 256 - s->irep->slen; i++) {
+ if (s->irep->slen == MAXSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
+ }
+
+ if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
+ s->scapa = MAXSYMLEN;
+ s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
+ for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
static const mrb_sym mrb_sym_zero = { 0 };
- s->irep->syms[i + s->irep->slen] = mrb_sym_zero;
+ s->irep->syms[i] = mrb_sym_zero;
}
- s->irep->slen = 256;
+ s->irep->slen = MAXMSYMLEN;
}
s->irep->syms[s->irep->slen] = sym;
return s->irep->slen++;
@@ -588,9 +602,6 @@ for_body(codegen_scope *s, node *tree)
push(); /* push for a block parameter */
- lp = loop_push(s, LOOP_FOR);
- lp->pc1 = new_label(s);
-
/* generate loop variable */
n2 = tree->car;
genop(s, MKOP_Ax(OP_ENTER, 0x40000));
@@ -600,6 +611,11 @@ for_body(codegen_scope *s, node *tree)
else {
gen_vmassignment(s, n2, 1, VAL);
}
+ /* construct loop */
+ lp = loop_push(s, LOOP_FOR);
+ lp->pc2 = new_label(s);
+
+ /* loop body */
codegen(s, tree->cdr->cdr->car, VAL);
pop();
if (s->pc > 0) {
@@ -650,6 +666,9 @@ lambda_body(codegen_scope *s, node *tree, int blk)
ka = kd = 0;
ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
+ if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
+ codegen_error(s, "too many formal arguments");
+ }
a = ((mrb_aspec)(ma & 0x1f) << 18)
| ((mrb_aspec)(oa & 0x1f) << 13)
| ((ra & 1) << 12)
@@ -770,6 +789,8 @@ attrsym(codegen_scope *s, mrb_sym a)
return mrb_intern(s->mrb, name2, len+1);
}
+#define CALL_MAXARGS 127
+
static int
gen_values(codegen_scope *s, node *t, int val)
{
@@ -778,7 +799,9 @@ gen_values(codegen_scope *s, node *t, int val)
while (t) {
is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
- if (n >= 127 || is_splat) {
+ if (
+ n >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
+ || is_splat) {
if (val) {
if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
codegen(s, t->car->cdr, VAL);
@@ -812,8 +835,6 @@ gen_values(codegen_scope *s, node *t, int val)
}
}
else {
- codegen(s, t->car->cdr, NOVAL);
- t = t->cdr;
while (t) {
codegen(s, t->car, NOVAL);
t = t->cdr;
@@ -829,8 +850,6 @@ gen_values(codegen_scope *s, node *t, int val)
return n;
}
-#define CALL_MAXARGS 127
-
static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
{
@@ -1057,7 +1076,9 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
n++;
}
}
- push();
+ if (!val) {
+ push();
+ }
}
}
@@ -1360,6 +1381,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos1, pos2;
node *e = tree->cdr->cdr->car;
+ if (!tree->car) {
+ codegen(s, e, val);
+ return;
+ }
switch ((intptr_t)tree->car->car) {
case NODE_TRUE:
case NODE_INT:
@@ -1510,7 +1535,9 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
if (pos3) dispatch_linked(s, pos3);
if (head) pop();
- genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ if (cursp() != pos) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ }
push();
}
else {
@@ -1655,7 +1682,6 @@ codegen(codegen_scope *s, node *tree, int val)
}
tree = tree->car;
if (tree->car) { /* pre */
- int first = TRUE;
t = tree->car;
n = 0;
while (t) {
@@ -1664,10 +1690,7 @@ codegen(codegen_scope *s, node *tree, int val)
n++;
}
else {
- if (first) {
- genop(s, MKOP_A(OP_LOADNIL, rhs+n));
- first = FALSE;
- }
+ genop(s, MKOP_A(OP_LOADNIL, rhs+n));
gen_assignment(s, t->car, rhs+n, NOVAL);
}
t = t->cdr;
@@ -1746,6 +1769,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_RESCUE, exc));
genop(s, MKOP_A(OP_LOADF, exc));
dispatch(s, noexc);
+ loop_pop(s, NOVAL);
}
else if ((intptr_t)tree->car->car == NODE_CALL) {
node *n = tree->car->cdr;
@@ -1795,8 +1819,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
pop();
- if (val && vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ if (val) {
+ if (vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
}
else {
@@ -2012,7 +2038,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_REDO:
- if (!s->loop) {
+ if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
raise_error(s, "unexpected redo");
}
else {
@@ -2021,6 +2047,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
}
+ if (val) push();
break;
case NODE_RETRY:
@@ -2055,6 +2082,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
}
}
+ if (val) push();
}
break;
@@ -2194,7 +2222,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_FLOAT:
if (val) {
char *p = (char*)tree;
- mrb_float f = str_to_mrb_float(p);
+ mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, f));
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
@@ -2208,9 +2236,9 @@ codegen(codegen_scope *s, node *tree, int val)
tree = tree->cdr;
switch (nt) {
case NODE_FLOAT:
- {
+ if (val) {
char *p = (char*)tree;
- mrb_float f = str_to_mrb_float(p);
+ mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
@@ -2219,7 +2247,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_INT:
- {
+ if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
mrb_int i;
@@ -2248,7 +2276,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
default:
- {
+ if (val) {
int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
@@ -2257,6 +2285,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop(); pop();
genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
}
+ else {
+ codegen(s, tree, NOVAL);
+ }
break;
}
}
@@ -2282,7 +2313,11 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
node *n = tree;
- if (!n) break;
+ if (!n) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ break;
+ }
codegen(s, n->car, VAL);
n = n->cdr;
while (n) {
@@ -2539,13 +2574,31 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
while (t) {
- int symbol = new_msym(s, sym(t->car));
+ int symbol;
+ if (num >= CALL_MAXARGS - 1) {
+ pop_n(num);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
+ while (t) {
+ symbol = new_msym(s, sym(t->car));
+ push();
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ t = t->cdr;
+ }
+ num = CALL_MAXARGS;
+ break;
+ }
+ symbol = new_msym(s, sym(t->car));
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
push();
t = t->cdr;
num++;
}
- pop_n(num + 1);
+ pop();
+ if (num < CALL_MAXARGS) {
+ pop_n(num);
+ }
genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
if (val) {
push();
@@ -2713,13 +2766,13 @@ 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->irep->iseq = NULL;
p->pcapa = 32;
p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
p->irep->plen = 0;
- p->scapa = 256;
+ p->scapa = MAXMSYMLEN;
p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
p->irep->slen = 0;
@@ -2797,6 +2850,7 @@ scope_finish(codegen_scope *s)
memcpy(fname, s->filename, fname_len);
fname[fname_len] = '\0';
irep->filename = fname;
+ irep->own_filename = TRUE;
}
irep->nlocals = s->nlocals;
@@ -2904,9 +2958,6 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
return proc;
}
MRB_CATCH(&scope->jmp) {
- if (scope->filename == scope->irep->filename) {
- scope->irep->filename = NULL;
- }
mrb_irep_decref(mrb, scope->irep);
mrb_pool_close(scope->mpool);
return NULL;