summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/codegen.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2016-05-16 01:46:37 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2016-05-16 01:49:24 +0900
commit29d3a40418dd41dfb0e10f92d08ce313bb439eca (patch)
tree055ea997bd675f56c4e6f3ed2f91e864a9888918 /mrbgems/mruby-compiler/core/codegen.c
parent2e81fee7316d9604d96bb6e0966f2817520bb98d (diff)
downloadmruby-29d3a40418dd41dfb0e10f92d08ce313bb439eca.tar.gz
mruby-29d3a40418dd41dfb0e10f92d08ce313bb439eca.zip
stack adjustment after NODE_OP_ASGN with NODE_CALL was wrong; fix #3159
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c55
1 files changed, 44 insertions, 11 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 4b45beab8..37a7cbd0d 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -1747,21 +1747,32 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n->car, VAL); /* receiver */
idx = new_msym(s, sym(n->cdr->car));
if (n->cdr->cdr->car) {
- int i = gen_values(s, n->cdr->cdr->car->car, VAL);
- if (i >= 0) {
- pop_n(i);
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
+ int base = cursp()-1;
+ int nargs = gen_values(s, n->cdr->cdr->car->car, VAL);
+
+ /* copy receiver and arguments */
+ if (nargs >= 0) {
+ int i;
+
+ genop(s, MKOP_AB(OP_MOVE, cursp(), base));
+ for (i=0; i<nargs; i++) {
+ genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
+ }
+ callargs = nargs;
}
- genop(s, MKOP_AB(OP_MOVE, cursp()+1, cursp()-1));
- genop(s, MKOP_AB(OP_MOVE, cursp()+2, cursp()));
- push();
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, CALL_MAXARGS));
- callargs = CALL_MAXARGS;
+ else {
+ /* varargs */
+ push();
+ genop(s, MKOP_AB(OP_MOVE, cursp(), base));
+ genop(s, MKOP_AB(OP_MOVE, cursp()+1, base+1));
+ callargs = CALL_MAXARGS;
+ }
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
}
else {
genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
- callargs = 1;
+ callargs = 0;
}
push();
}
@@ -1775,6 +1786,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
if (val) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
}
else {
@@ -1782,7 +1794,28 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, tree->cdr->cdr->car, VAL);
pop();
- gen_assignment(s, tree->car, cursp(), val);
+ if (val) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
+ if ((intptr_t)tree->car->car == NODE_CALL) {
+ mrb_sym m = sym(tree->car->cdr->cdr->car);
+ mrb_sym m2 = attrsym(s, m);
+
+ idx = new_msym(s, m2);
+ pop();
+ if (callargs == CALL_MAXARGS) {
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ }
+ else {
+ pop_n(callargs);
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs+1));
+ }
+ }
+ else {
+ gen_assignment(s, tree->car, cursp(), val);
+ }
dispatch(s, pos);
return;
}