codegen.c: fix evaluation order of constant initialization.

`a::B = c` should evaluate `a` then `c`. It used to be `c` then `a`. The
`OP_SETMCNST` instruction operands are designed for older order in mind.
Should we changed the operand order?
parent b68ba2df
...@@ -101,8 +101,8 @@ static void loop_pop(codegen_scope *s, int val); ...@@ -101,8 +101,8 @@ static void loop_pop(codegen_scope *s, int val);
static int catch_handler_new(codegen_scope *s); static int catch_handler_new(codegen_scope *s);
static void catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target); static void catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target);
static void gen_assignment(codegen_scope *s, node *tree, int sp, int val); static void gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val);
static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val); static void gen_vmassignment(codegen_scope *s, node *tree, int sp, int val);
static void codegen(codegen_scope *s, node *tree, int val); static void codegen(codegen_scope *s, node *tree, int val);
static void raise_error(codegen_scope *s, const char *msg); static void raise_error(codegen_scope *s, const char *msg);
...@@ -1275,7 +1275,7 @@ for_body(codegen_scope *s, node *tree) ...@@ -1275,7 +1275,7 @@ for_body(codegen_scope *s, node *tree)
n2 = tree->car; n2 = tree->car;
genop_W(s, OP_ENTER, 0x40000); genop_W(s, OP_ENTER, 0x40000);
if (n2->car && !n2->car->cdr && !n2->cdr) { if (n2->car && !n2->car->cdr && !n2->cdr) {
gen_assignment(s, n2->car->car, 1, NOVAL); gen_assignment(s, n2->car->car, NULL, 1, NOVAL);
} }
else { else {
gen_vmassignment(s, n2, 1, VAL); gen_vmassignment(s, n2, 1, VAL);
...@@ -1774,11 +1774,42 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) ...@@ -1774,11 +1774,42 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
} }
static void static void
gen_assignment(codegen_scope *s, node *tree, int sp, int val) gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
{ {
int idx; int idx;
int type = nint(tree->car); int type = nint(tree->car);
switch (type) {
case NODE_GVAR:
case NODE_ARG:
case NODE_LVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_NIL:
case NODE_MASGN:
case NODE_SCALL:
case NODE_CALL:
if (rhs) {
codegen(s, rhs, VAL);
pop();
sp = cursp();
}
break;
case NODE_COLON2:
/* keep evaluation order */
break;
case NODE_NVAR:
codegen_error(s, "Can't assign to numbered parameter");
break;
default:
codegen_error(s, "unknown lhs");
break;
}
tree = tree->cdr; tree = tree->cdr;
switch (type) { switch (type) {
case NODE_GVAR: case NODE_GVAR:
...@@ -1797,10 +1828,6 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) ...@@ -1797,10 +1828,6 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_setupvar(s, sp, nsym(tree)); gen_setupvar(s, sp, nsym(tree));
} }
break; break;
case NODE_NVAR:
idx = nint(tree);
codegen_error(s, "Can't assign to numbered parameter");
break;
case NODE_IVAR: case NODE_IVAR:
gen_setxv(s, OP_SETIV, sp, nsym(tree), val); gen_setxv(s, OP_SETIV, sp, nsym(tree), val);
break; break;
...@@ -1811,9 +1838,16 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) ...@@ -1811,9 +1838,16 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_setxv(s, OP_SETCONST, sp, nsym(tree), val); gen_setxv(s, OP_SETCONST, sp, nsym(tree), val);
break; break;
case NODE_COLON2: case NODE_COLON2:
gen_move(s, cursp(), sp, 0); if (sp) {
gen_move(s, cursp(), sp, 0);
}
sp = cursp();
push(); push();
codegen(s, tree->car, VAL); codegen(s, tree->car, VAL);
if (rhs) {
codegen(s, rhs, VAL); pop();
gen_move(s, sp, cursp(), 0);
}
pop_n(2); pop_n(2);
idx = new_sym(s, nsym(tree->cdr)); idx = new_sym(s, nsym(tree->cdr));
genop_2(s, OP_SETMCNST, sp, idx); genop_2(s, OP_SETMCNST, sp, idx);
...@@ -1822,8 +1856,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) ...@@ -1822,8 +1856,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
case NODE_CALL: case NODE_CALL:
case NODE_SCALL: case NODE_SCALL:
push(); push();
gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL, gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL, type == NODE_SCALL);
type == NODE_SCALL);
pop(); pop();
if (val && cursp() != sp) { if (val && cursp() != sp) {
gen_move(s, cursp(), sp, 0); gen_move(s, cursp(), sp, 0);
...@@ -1859,7 +1892,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) ...@@ -1859,7 +1892,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
genop_3(s, OP_AREF, sp, rhs, n); genop_3(s, OP_AREF, sp, rhs, n);
push(); push();
gen_assignment(s, t->car, sp, NOVAL); gen_assignment(s, t->car, NULL, sp, NOVAL);
pop(); pop();
n++; n++;
t = t->cdr; t = t->cdr;
...@@ -1880,12 +1913,12 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) ...@@ -1880,12 +1913,12 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
genop_3(s, OP_APOST, cursp(), n, post); genop_3(s, OP_APOST, cursp(), n, post);
n = 1; n = 1;
if (t->car && t->car != (node*)-1) { /* rest */ if (t->car && t->car != (node*)-1) { /* rest */
gen_assignment(s, t->car, cursp(), NOVAL); gen_assignment(s, t->car, NULL, cursp(), NOVAL);
} }
if (t->cdr && t->cdr->car) { if (t->cdr && t->cdr->car) {
t = t->cdr->car; t = t->cdr->car;
while (t) { while (t) {
gen_assignment(s, t->car, cursp()+n, NOVAL); gen_assignment(s, t->car, NULL, cursp()+n, NOVAL);
t = t->cdr; t = t->cdr;
n++; n++;
} }
...@@ -2205,7 +2238,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2205,7 +2238,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop(); pop();
if (n3->cdr->car) { if (n3->cdr->car) {
gen_assignment(s, n3->cdr->car, exc, NOVAL); gen_assignment(s, n3->cdr->car, NULL, exc, NOVAL);
} }
if (n3->cdr->cdr->car) { if (n3->cdr->cdr->car) {
codegen(s, n3->cdr->cdr->car, val); codegen(s, n3->cdr->cdr->car, val);
...@@ -2589,9 +2622,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2589,9 +2622,7 @@ codegen(codegen_scope *s, node *tree, int val)
break; break;
case NODE_ASGN: case NODE_ASGN:
codegen(s, tree->cdr, VAL); gen_assignment(s, tree->car, tree->cdr, 0, val);
pop();
gen_assignment(s, tree->car, cursp(), val);
break; break;
case NODE_MASGN: case NODE_MASGN:
...@@ -2614,12 +2645,12 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2614,12 +2645,12 @@ codegen(codegen_scope *s, node *tree, int val)
n = 0; n = 0;
while (t) { while (t) {
if (n < len) { if (n < len) {
gen_assignment(s, t->car, rhs+n, NOVAL); gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
n++; n++;
} }
else { else {
genop_1(s, OP_LOADNIL, rhs+n); genop_1(s, OP_LOADNIL, rhs+n);
gen_assignment(s, t->car, rhs+n, NOVAL); gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
} }
t = t->cdr; t = t->cdr;
} }
...@@ -2643,13 +2674,13 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2643,13 +2674,13 @@ codegen(codegen_scope *s, node *tree, int val)
rn = len - post - n; rn = len - post - n;
} }
genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn); genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
gen_assignment(s, t->car, cursp(), NOVAL); gen_assignment(s, t->car, NULL, cursp(), NOVAL);
n += rn; n += rn;
} }
if (t->cdr && t->cdr->car) { if (t->cdr && t->cdr->car) {
t = t->cdr->car; t = t->cdr->car;
while (n<len) { while (n<len) {
gen_assignment(s, t->car, rhs+n, NOVAL); gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
t = t->cdr; t = t->cdr;
n++; n++;
} }
...@@ -2770,7 +2801,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2770,7 +2801,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_3(s, OP_SEND, cursp(), idx, callargs); genop_3(s, OP_SEND, cursp(), idx, callargs);
} }
else { else {
gen_assignment(s, tree->car, cursp(), val); gen_assignment(s, tree->car, NULL, cursp(), val);
} }
dispatch(s, pos); dispatch(s, pos);
goto exit; goto exit;
...@@ -2808,7 +2839,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -2808,7 +2839,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_3(s, OP_SEND, cursp(), idx, 1); genop_3(s, OP_SEND, cursp(), idx, 1);
} }
if (callargs < 0) { if (callargs < 0) {
gen_assignment(s, tree->car, cursp(), val); gen_assignment(s, tree->car, NULL, cursp(), val);
} }
else { else {
if (val && vsp >= 0) { if (val && vsp >= 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment