diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2016-05-16 01:46:37 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2016-05-16 01:49:24 +0900 |
| commit | 29d3a40418dd41dfb0e10f92d08ce313bb439eca (patch) | |
| tree | 055ea997bd675f56c4e6f3ed2f91e864a9888918 /mrbgems | |
| parent | 2e81fee7316d9604d96bb6e0966f2817520bb98d (diff) | |
| download | mruby-29d3a40418dd41dfb0e10f92d08ce313bb439eca.tar.gz mruby-29d3a40418dd41dfb0e10f92d08ce313bb439eca.zip | |
stack adjustment after NODE_OP_ASGN with NODE_CALL was wrong; fix #3159
Diffstat (limited to 'mrbgems')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 55 |
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; } |
