compile.c: check compile

* compile.c (iseq_compile_each): check if sub nodes succeeded.
  [ruby-core:76531] [Bug #12613]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57300 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-01-10 15:28:11 +00:00
parent a3fb17f3a0
commit 52b02ad22a
2 changed files with 146 additions and 120 deletions

249
compile.c
View File

@ -400,6 +400,8 @@ do { \
#define COMPILE_OK 1 #define COMPILE_OK 1
#define COMPILE_NG 0 #define COMPILE_NG 0
#define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
#define BEFORE_RETURN
/* leave name uninitialized so that compiler warn if INIT_ANCHOR is /* leave name uninitialized so that compiler warn if INIT_ANCHOR is
* missing */ * missing */
@ -594,7 +596,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_B_CALL); ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_B_CALL);
ADD_LABEL(ret, start); ADD_LABEL(ret, start);
COMPILE(ret, "block body", node->nd_body); CHECK(COMPILE(ret, "block body", node->nd_body));
ADD_LABEL(ret, end); ADD_LABEL(ret, end);
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_B_RETURN); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_B_RETURN);
@ -606,19 +608,19 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
case ISEQ_TYPE_CLASS: case ISEQ_TYPE_CLASS:
{ {
ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CLASS); ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CLASS);
COMPILE(ret, "scoped node", node->nd_body); CHECK(COMPILE(ret, "scoped node", node->nd_body));
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
break; break;
} }
case ISEQ_TYPE_METHOD: case ISEQ_TYPE_METHOD:
{ {
ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CALL); ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CALL);
COMPILE(ret, "scoped node", node->nd_body); CHECK(COMPILE(ret, "scoped node", node->nd_body));
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
break; break;
} }
default: { default: {
COMPILE(ret, "scoped node", node->nd_body); CHECK(COMPILE(ret, "scoped node", node->nd_body));
break; break;
} }
} }
@ -641,15 +643,15 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
return COMPILE_NG; return COMPILE_NG;
case ISEQ_TYPE_RESCUE: case ISEQ_TYPE_RESCUE:
iseq_set_exception_local_table(iseq); iseq_set_exception_local_table(iseq);
COMPILE(ret, "rescue", node); CHECK(COMPILE(ret, "rescue", node));
break; break;
case ISEQ_TYPE_ENSURE: case ISEQ_TYPE_ENSURE:
iseq_set_exception_local_table(iseq); iseq_set_exception_local_table(iseq);
COMPILE_POPPED(ret, "ensure", node); CHECK(COMPILE_POPPED(ret, "ensure", node));
break; break;
case ISEQ_TYPE_DEFINED_GUARD: case ISEQ_TYPE_DEFINED_GUARD:
iseq_set_exception_local_table(iseq); iseq_set_exception_local_table(iseq);
COMPILE(ret, "defined guard", node); CHECK(COMPILE(ret, "defined guard", node));
break; break;
default: default:
compile_bug(ERROR_ARGS "unknown scope"); compile_bug(ERROR_ARGS "unknown scope");
@ -2779,7 +2781,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int
lit = Qnil; lit = Qnil;
} }
else { else {
COMPILE(ret, "each string", node); CHECK(COMPILE(ret, "each string", node));
} }
cnt++; cnt++;
list = list->nd_next; list = list->nd_next;
@ -2797,7 +2799,7 @@ static int
compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node) compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
{ {
int cnt; int cnt;
compile_dstr_fragments(iseq, ret, node, &cnt); CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt)); ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
return COMPILE_OK; return COMPILE_OK;
} }
@ -2806,7 +2808,7 @@ static int
compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node) compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
{ {
int cnt; int cnt;
compile_dstr_fragments(iseq, ret, node, &cnt); CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt)); ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt));
return COMPILE_OK; return COMPILE_OK;
} }
@ -2825,7 +2827,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int again
ADD_INSNL(ret, line, branchif, lend); ADD_INSNL(ret, line, branchif, lend);
/* *flip == 0 */ /* *flip == 0 */
COMPILE(ret, "flip2 beg", node->nd_beg); CHECK(COMPILE(ret, "flip2 beg", node->nd_beg));
ADD_INSNL(ret, line, branchunless, else_label); ADD_INSNL(ret, line, branchunless, else_label);
ADD_INSN1(ret, line, putobject, Qtrue); ADD_INSN1(ret, line, putobject, Qtrue);
ADD_INSN1(ret, line, setspecial, key); ADD_INSN1(ret, line, setspecial, key);
@ -2835,7 +2837,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int again
/* *flip == 1 */ /* *flip == 1 */
ADD_LABEL(ret, lend); ADD_LABEL(ret, lend);
COMPILE(ret, "flip2 end", node->nd_end); CHECK(COMPILE(ret, "flip2 end", node->nd_end));
ADD_INSNL(ret, line, branchunless, then_label); ADD_INSNL(ret, line, branchunless, then_label);
ADD_INSN1(ret, line, putobject, Qfalse); ADD_INSN1(ret, line, putobject, Qfalse);
ADD_INSN1(ret, line, setspecial, key); ADD_INSN1(ret, line, setspecial, key);
@ -2852,18 +2854,18 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *cond,
case NODE_AND: case NODE_AND:
{ {
LABEL *label = NEW_LABEL(nd_line(cond)); LABEL *label = NEW_LABEL(nd_line(cond));
compile_branch_condition(iseq, ret, cond->nd_1st, label, CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
else_label); else_label));
ADD_LABEL(ret, label); ADD_LABEL(ret, label);
compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, CHECK(compile_branch_condition(iseq, ret, cond->nd_2nd, then_label,
else_label); else_label));
break; break;
} }
case NODE_OR: case NODE_OR:
{ {
LABEL *label = NEW_LABEL(nd_line(cond)); LABEL *label = NEW_LABEL(nd_line(cond));
compile_branch_condition(iseq, ret, cond->nd_1st, then_label, CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
label); label));
ADD_LABEL(ret, label); ADD_LABEL(ret, label);
compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, compile_branch_condition(iseq, ret, cond->nd_2nd, then_label,
else_label); else_label);
@ -2893,13 +2895,13 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *cond,
ADD_INSNL(ret, nd_line(cond), jump, else_label); ADD_INSNL(ret, nd_line(cond), jump, else_label);
break; break;
case NODE_FLIP2: case NODE_FLIP2:
compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label); CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
break; break;
case NODE_FLIP3: case NODE_FLIP3:
compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label); CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
break; break;
default: default:
COMPILE(ret, "branch condition", cond); CHECK(COMPILE(ret, "branch condition", cond));
ADD_INSNL(ret, nd_line(cond), branchunless, else_label); ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
ADD_INSNL(ret, nd_line(cond), jump, then_label); ADD_INSNL(ret, nd_line(cond), jump, then_label);
break; break;
@ -3238,7 +3240,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
VALUE dupidx; VALUE dupidx;
int line = nd_line(node); int line = nd_line(node);
COMPILE_POPPED(ret, "masgn lhs (NODE_ATTRASGN)", node); CHECK(COMPILE_POPPED(ret, "masgn lhs (NODE_ATTRASGN)", node));
iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */ iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */
ci = (struct rb_call_info *)iobj->operands[0]; ci = (struct rb_call_info *)iobj->operands[0];
@ -3257,7 +3259,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
case NODE_MASGN: { case NODE_MASGN: {
DECL_ANCHOR(anchor); DECL_ANCHOR(anchor);
INIT_ANCHOR(anchor); INIT_ANCHOR(anchor);
COMPILE_POPPED(anchor, "nest masgn lhs", node); CHECK(COMPILE_POPPED(anchor, "nest masgn lhs", node));
REMOVE_ELEM(FIRST_ELEMENT(anchor)); REMOVE_ELEM(FIRST_ELEMENT(anchor));
ADD_SEQ(ret, anchor); ADD_SEQ(ret, anchor);
break; break;
@ -3265,7 +3267,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
default: { default: {
DECL_ANCHOR(anchor); DECL_ANCHOR(anchor);
INIT_ANCHOR(anchor); INIT_ANCHOR(anchor);
COMPILE_POPPED(anchor, "masgn lhs", node); CHECK(COMPILE_POPPED(anchor, "masgn lhs", node));
REMOVE_ELEM(FIRST_ELEMENT(anchor)); REMOVE_ELEM(FIRST_ELEMENT(anchor));
ADD_SEQ(ret, anchor); ADD_SEQ(ret, anchor);
} }
@ -3274,13 +3276,14 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
return COMPILE_OK; return COMPILE_OK;
} }
static void static int
compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *lhsn) compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *lhsn)
{ {
if (lhsn) { if (lhsn) {
compile_massign_opt_lhs(iseq, ret, lhsn->nd_next); CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
compile_massign_lhs(iseq, ret, lhsn->nd_head); CHECK(compile_massign_lhs(iseq, ret, lhsn->nd_head));
} }
return COMPILE_OK;
} }
static int static int
@ -3375,7 +3378,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
INIT_ANCHOR(lhsseq); INIT_ANCHOR(lhsseq);
while (lhsn) { while (lhsn) {
compile_massign_lhs(iseq, lhsseq, lhsn->nd_head); CHECK(compile_massign_lhs(iseq, lhsseq, lhsn->nd_head));
llen += 1; llen += 1;
lhsn = lhsn->nd_next; lhsn = lhsn->nd_next;
} }
@ -3428,16 +3431,16 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
INT2FIX(num), INT2FIX(flag)); INT2FIX(num), INT2FIX(flag));
if ((VALUE)restn != (VALUE)-1) { if ((VALUE)restn != (VALUE)-1) {
compile_massign_lhs(iseq, ret, restn); CHECK(compile_massign_lhs(iseq, ret, restn));
} }
while (postn) { while (postn) {
compile_massign_lhs(iseq, ret, postn->nd_head); CHECK(compile_massign_lhs(iseq, ret, postn->nd_head));
postn = postn->nd_next; postn = postn->nd_next;
} }
} }
else { else {
/* a, b, *r */ /* a, b, *r */
compile_massign_lhs(iseq, ret, splatn); CHECK(compile_massign_lhs(iseq, ret, splatn));
} }
} }
} }
@ -3465,7 +3468,7 @@ compile_colon2(rb_iseq_t *iseq, NODE *node,
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
break; break;
default: default:
COMPILE(pref, "const colon2 prefix", node); CHECK(COMPILE(pref, "const colon2 prefix", node));
break; break;
} }
return COMPILE_OK; return COMPILE_OK;
@ -3982,18 +3985,20 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
debug_node_start(node); debug_node_start(node);
#undef BEFORE_RETURN
#define BEFORE_RETURN debug_node_end()
type = nd_type(node); type = nd_type(node);
switch (type) { switch (type) {
case NODE_BLOCK:{ case NODE_BLOCK:{
while (node && nd_type(node) == NODE_BLOCK) { while (node && nd_type(node) == NODE_BLOCK) {
COMPILE_(ret, "BLOCK body", node->nd_head, CHECK(COMPILE_(ret, "BLOCK body", node->nd_head,
(node->nd_next == 0 && popped == 0) ? 0 : 1); (node->nd_next ? 1 : popped)));
node = node->nd_next; node = node->nd_next;
} }
if (node) { if (node) {
COMPILE_(ret, "BLOCK next", node->nd_next, popped); CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped));
} }
break; break;
} }
@ -4012,8 +4017,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
compile_branch_condition(iseq, cond_seq, node->nd_cond, compile_branch_condition(iseq, cond_seq, node->nd_cond,
then_label, else_label); then_label, else_label);
COMPILE_(then_seq, "then", node->nd_body, popped); CHECK(COMPILE_(then_seq, "then", node->nd_body, popped));
COMPILE_(else_seq, "else", node->nd_else, popped); CHECK(COMPILE_(else_seq, "else", node->nd_else, popped));
ADD_SEQ(ret, cond_seq); ADD_SEQ(ret, cond_seq);
@ -4045,10 +4050,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
rb_hash_tbl_raw(literals)->type = &cdhash_type; rb_hash_tbl_raw(literals)->type = &cdhash_type;
if (node->nd_head == 0) { if (node->nd_head == 0) {
COMPILE_(ret, "when", node->nd_body, popped); CHECK(COMPILE_(ret, "when", node->nd_body, popped));
break; break;
} }
COMPILE(head, "case base", node->nd_head); CHECK(COMPILE(head, "case base", node->nd_head));
node = node->nd_body; node = node->nd_body;
type = nd_type(node); type = nd_type(node);
@ -4056,6 +4061,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
if (type != NODE_WHEN) { if (type != NODE_WHEN) {
COMPILE_ERROR(ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type)); COMPILE_ERROR(ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type));
ng:
debug_node_end(); debug_node_end();
return COMPILE_NG; return COMPILE_NG;
} }
@ -4071,7 +4077,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
l1 = NEW_LABEL(line); l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1); ADD_LABEL(body_seq, l1);
ADD_INSN(body_seq, line, pop); ADD_INSN(body_seq, line, pop);
COMPILE_(body_seq, "when body", node->nd_body, popped); CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
ADD_INSNL(body_seq, line, jump, endlabel); ADD_INSNL(body_seq, line, jump, endlabel);
vals = node->nd_head; vals = node->nd_head;
@ -4085,7 +4091,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ARGSPUSH: case NODE_ARGSPUSH:
only_special_literals = 0; only_special_literals = 0;
ADD_INSN (cond_seq, nd_line(vals), dup); ADD_INSN (cond_seq, nd_line(vals), dup);
COMPILE(cond_seq, "when/cond splat", vals); CHECK(COMPILE(cond_seq, "when/cond splat", vals));
ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
ADD_INSNL(cond_seq, nd_line(vals), branchif, l1); ADD_INSNL(cond_seq, nd_line(vals), branchif, l1);
break; break;
@ -4108,7 +4114,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
if (node) { if (node) {
ADD_LABEL(cond_seq, elselabel); ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, line, pop); ADD_INSN(cond_seq, line, pop);
COMPILE_(cond_seq, "else", node, popped); CHECK(COMPILE_(cond_seq, "else", node, popped));
ADD_INSNL(cond_seq, line, jump, endlabel); ADD_INSNL(cond_seq, line, jump, endlabel);
} }
else { else {
@ -4147,7 +4153,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
while (node && nd_type(node) == NODE_WHEN) { while (node && nd_type(node) == NODE_WHEN) {
LABEL *l1 = NEW_LABEL(line = nd_line(node)); LABEL *l1 = NEW_LABEL(line = nd_line(node));
ADD_LABEL(body_seq, l1); ADD_LABEL(body_seq, l1);
COMPILE_(body_seq, "when", node->nd_body, popped); CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
ADD_INSNL(body_seq, line, jump, endlabel); ADD_INSNL(body_seq, line, jump, endlabel);
vals = node->nd_head; vals = node->nd_head;
@ -4158,7 +4164,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ARRAY: case NODE_ARRAY:
while (vals) { while (vals) {
val = vals->nd_head; val = vals->nd_head;
COMPILE(ret, "when2", val); CHECK(COMPILE(ret, "when2", val));
ADD_INSNL(ret, nd_line(val), branchif, l1); ADD_INSNL(ret, nd_line(val), branchif, l1);
vals = vals->nd_next; vals = vals->nd_next;
} }
@ -4167,7 +4173,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ARGSCAT: case NODE_ARGSCAT:
case NODE_ARGSPUSH: case NODE_ARGSPUSH:
ADD_INSN(ret, nd_line(vals), putnil); ADD_INSN(ret, nd_line(vals), putnil);
COMPILE(ret, "when2/cond splat", vals); CHECK(COMPILE(ret, "when2/cond splat", vals));
ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
ADD_INSNL(ret, nd_line(vals), branchif, l1); ADD_INSNL(ret, nd_line(vals), branchif, l1);
break; break;
@ -4177,7 +4183,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
node = node->nd_next; node = node->nd_next;
} }
/* else */ /* else */
COMPILE_(ret, "else", node, popped); CHECK(COMPILE_(ret, "else", node, popped));
ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
ADD_SEQ(ret, body_seq); ADD_SEQ(ret, body_seq);
@ -4222,7 +4228,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
if (tmp_label) ADD_LABEL(ret, tmp_label); if (tmp_label) ADD_LABEL(ret, tmp_label);
ADD_LABEL(ret, redo_label); ADD_LABEL(ret, redo_label);
COMPILE_POPPED(ret, "while body", node->nd_body); CHECK(COMPILE_POPPED(ret, "while body", node->nd_body));
ADD_LABEL(ret, next_label); /* next */ ADD_LABEL(ret, next_label); /* next */
if (type == NODE_WHILE) { if (type == NODE_WHILE) {
@ -4280,7 +4286,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
NODE *var = node->nd_var; NODE *var = node->nd_var;
LABEL *not_single = NEW_LABEL(nd_line(var)); LABEL *not_single = NEW_LABEL(nd_line(var));
LABEL *not_ary = NEW_LABEL(nd_line(var)); LABEL *not_ary = NEW_LABEL(nd_line(var));
COMPILE(ret, "for var", var); CHECK(COMPILE(ret, "for var", var));
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
ADD_CALL(ret, line, idLength, INT2FIX(0)); ADD_CALL(ret, line, idLength, INT2FIX(0));
ADD_INSN1(ret, line, putobject, INT2FIX(1)); ADD_INSN1(ret, line, putobject, INT2FIX(1));
@ -4306,7 +4312,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_LABEL(ret, retry_label); ADD_LABEL(ret, retry_label);
if (nd_type(node) == NODE_FOR) { if (nd_type(node) == NODE_FOR) {
COMPILE(ret, "iter caller (for)", node->nd_iter); CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
ISEQ_COMPILE_DATA(iseq)->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_COMPILE_DATA(iseq)->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
ISEQ_TYPE_BLOCK, line); ISEQ_TYPE_BLOCK, line);
@ -4315,7 +4321,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else { else {
ISEQ_COMPILE_DATA(iseq)->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_COMPILE_DATA(iseq)->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
ISEQ_TYPE_BLOCK, line); ISEQ_TYPE_BLOCK, line);
COMPILE(ret, "iter caller", node->nd_iter); CHECK(COMPILE(ret, "iter caller", node->nd_iter));
} }
ADD_LABEL(ret, retry_end_l); ADD_LABEL(ret, retry_end_l);
@ -4337,7 +4343,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
LABEL *splabel = NEW_LABEL(0); LABEL *splabel = NEW_LABEL(0);
ADD_LABEL(ret, splabel); ADD_LABEL(ret, splabel);
ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label); ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
COMPILE_(ret, "break val (while/until)", node->nd_stts, ISEQ_COMPILE_DATA(iseq)->loopval_popped); CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
ISEQ_COMPILE_DATA(iseq)->loopval_popped));
add_ensure_iseq(ret, iseq, 0); add_ensure_iseq(ret, iseq, 0);
ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label); ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
ADD_ADJUST_RESTORE(ret, splabel); ADD_ADJUST_RESTORE(ret, splabel);
@ -4349,7 +4356,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else if (iseq->body->type == ISEQ_TYPE_BLOCK) { else if (iseq->body->type == ISEQ_TYPE_BLOCK) {
break_by_insn: break_by_insn:
/* escape from block */ /* escape from block */
COMPILE(ret, "break val (block)", node->nd_stts); CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_BREAK)); ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_BREAK));
if (popped) { if (popped) {
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
@ -4358,8 +4365,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else if (iseq->body->type == ISEQ_TYPE_EVAL) { else if (iseq->body->type == ISEQ_TYPE_EVAL) {
break_in_eval: break_in_eval:
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break"); COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
debug_node_end(); goto ng;
return COMPILE_NG;
} }
else { else {
const rb_iseq_t *ip = iseq->body->parent_iseq; const rb_iseq_t *ip = iseq->body->parent_iseq;
@ -4386,8 +4392,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ip = ip->body->parent_iseq; ip = ip->body->parent_iseq;
} }
COMPILE_ERROR(ERROR_ARGS "Invalid break"); COMPILE_ERROR(ERROR_ARGS "Invalid break");
debug_node_end(); goto ng;
return COMPILE_NG;
} }
break; break;
} }
@ -4398,7 +4403,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
LABEL *splabel = NEW_LABEL(0); LABEL *splabel = NEW_LABEL(0);
debugs("next in while loop\n"); debugs("next in while loop\n");
ADD_LABEL(ret, splabel); ADD_LABEL(ret, splabel);
COMPILE(ret, "next val/valid syntax?", node->nd_stts); CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
add_ensure_iseq(ret, iseq, 0); add_ensure_iseq(ret, iseq, 0);
ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label); ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label); ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
@ -4412,7 +4417,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
debugs("next in block\n"); debugs("next in block\n");
ADD_LABEL(ret, splabel); ADD_LABEL(ret, splabel);
ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label); ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
COMPILE(ret, "next val", node->nd_stts); CHECK(COMPILE(ret, "next val", node->nd_stts));
add_ensure_iseq(ret, iseq, 0); add_ensure_iseq(ret, iseq, 0);
ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label); ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
ADD_ADJUST_RESTORE(ret, splabel); ADD_ADJUST_RESTORE(ret, splabel);
@ -4424,6 +4429,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else if (iseq->body->type == ISEQ_TYPE_EVAL) { else if (iseq->body->type == ISEQ_TYPE_EVAL) {
next_in_eval: next_in_eval:
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next"); COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
goto ng;
} }
else { else {
const rb_iseq_t *ip = iseq; const rb_iseq_t *ip = iseq;
@ -4449,7 +4455,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ip = ip->body->parent_iseq; ip = ip->body->parent_iseq;
} }
if (ip != 0) { if (ip != 0) {
COMPILE(ret, "next val", node->nd_stts); CHECK(COMPILE(ret, "next val", node->nd_stts));
ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_NEXT)); ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_NEXT));
if (popped) { if (popped) {
@ -4458,6 +4464,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
else { else {
COMPILE_ERROR(ERROR_ARGS "Invalid next"); COMPILE_ERROR(ERROR_ARGS "Invalid next");
goto ng;
} }
} }
break; break;
@ -4478,6 +4485,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else if (iseq->body->type == ISEQ_TYPE_EVAL) { else if (iseq->body->type == ISEQ_TYPE_EVAL) {
redo_in_eval: redo_in_eval:
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo"); COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo");
goto ng;
} }
else if (ISEQ_COMPILE_DATA(iseq)->start_label) { else if (ISEQ_COMPILE_DATA(iseq)->start_label) {
LABEL *splabel = NEW_LABEL(0); LABEL *splabel = NEW_LABEL(0);
@ -4525,6 +4533,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
else { else {
COMPILE_ERROR(ERROR_ARGS "Invalid redo"); COMPILE_ERROR(ERROR_ARGS "Invalid redo");
goto ng;
} }
} }
break; break;
@ -4540,11 +4549,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
else { else {
COMPILE_ERROR(ERROR_ARGS "Invalid retry"); COMPILE_ERROR(ERROR_ARGS "Invalid retry");
goto ng;
} }
break; break;
} }
case NODE_BEGIN:{ case NODE_BEGIN:{
COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped); CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped));
break; break;
} }
case NODE_RESCUE:{ case NODE_RESCUE:{
@ -4558,11 +4568,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
lstart->rescued = LABEL_RESCUE_BEG; lstart->rescued = LABEL_RESCUE_BEG;
lend->rescued = LABEL_RESCUE_END; lend->rescued = LABEL_RESCUE_END;
ADD_LABEL(ret, lstart); ADD_LABEL(ret, lstart);
COMPILE(ret, "rescue head", node->nd_head); CHECK(COMPILE(ret, "rescue head", node->nd_head));
ADD_LABEL(ret, lend); ADD_LABEL(ret, lend);
if (node->nd_else) { if (node->nd_else) {
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
COMPILE(ret, "rescue else", node->nd_else); CHECK(COMPILE(ret, "rescue else", node->nd_else));
} }
ADD_INSN(ret, line, nop); ADD_INSN(ret, line, nop);
ADD_LABEL(ret, lcont); ADD_LABEL(ret, lcont);
@ -4591,7 +4601,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ARRAY: case NODE_ARRAY:
while (narg) { while (narg) {
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
COMPILE(ret, "rescue arg", narg->nd_head); CHECK(COMPILE(ret, "rescue arg", narg->nd_head));
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
ADD_INSNL(ret, line, branchif, label_hit); ADD_INSNL(ret, line, branchif, label_hit);
narg = narg->nd_next; narg = narg->nd_next;
@ -4601,7 +4611,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ARGSCAT: case NODE_ARGSCAT:
case NODE_ARGSPUSH: case NODE_ARGSPUSH:
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0); ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
COMPILE(ret, "rescue/cond splat", narg); CHECK(COMPILE(ret, "rescue/cond splat", narg));
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY)); ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
ADD_INSNL(ret, line, branchif, label_hit); ADD_INSNL(ret, line, branchif, label_hit);
break; break;
@ -4617,7 +4627,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
ADD_INSNL(ret, line, jump, label_miss); ADD_INSNL(ret, line, jump, label_miss);
ADD_LABEL(ret, label_hit); ADD_LABEL(ret, label_hit);
COMPILE(ret, "resbody body", resq->nd_body); CHECK(COMPILE(ret, "resbody body", resq->nd_body));
if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) { if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
ADD_INSN(ret, line, nop); ADD_INSN(ret, line, nop);
} }
@ -4642,7 +4652,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
struct ensure_range *erange; struct ensure_range *erange;
INIT_ANCHOR(ensr); INIT_ANCHOR(ensr);
COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr); CHECK(COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr));
last = ensr->last; last = ensr->last;
last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave); last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
if (!popped && last_leave) if (!popped && last_leave)
@ -4654,7 +4664,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
push_ensure_entry(iseq, &enl, &er, node->nd_ensr); push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
ADD_LABEL(ret, lstart); ADD_LABEL(ret, lstart);
COMPILE_(ret, "ensure head", node->nd_head, popped); CHECK(COMPILE_(ret, "ensure head", node->nd_head, popped));
ADD_LABEL(ret, lend); ADD_LABEL(ret, lend);
if (ensr->anchor.next == 0) { if (ensr->anchor.next == 0) {
ADD_INSN(ret, line, nop); ADD_INSN(ret, line, nop);
@ -4681,7 +4691,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_AND: case NODE_AND:
case NODE_OR:{ case NODE_OR:{
LABEL *end_label = NEW_LABEL(line); LABEL *end_label = NEW_LABEL(line);
COMPILE(ret, "nd_1st", node->nd_1st); CHECK(COMPILE(ret, "nd_1st", node->nd_1st));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
} }
@ -4694,7 +4704,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
if (!popped) { if (!popped) {
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
} }
COMPILE_(ret, "nd_2nd", node->nd_2nd, popped); CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped));
ADD_LABEL(ret, end_label); ADD_LABEL(ret, end_label);
break; break;
} }
@ -4709,7 +4719,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id); int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
debugs("lvar: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx); debugs("lvar: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx);
COMPILE(ret, "rvalue", node->nd_value); CHECK(COMPILE(ret, "rvalue", node->nd_value));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
@ -4720,7 +4730,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_DASGN: case NODE_DASGN:
case NODE_DASGN_CURR:{ case NODE_DASGN_CURR:{
int idx, lv, ls; int idx, lv, ls;
COMPILE(ret, "dvalue", node->nd_value); CHECK(COMPILE(ret, "dvalue", node->nd_value));
debugi("dassn id", rb_id2str(node->nd_vid) ? node->nd_vid : '*'); debugi("dassn id", rb_id2str(node->nd_vid) ? node->nd_vid : '*');
if (!popped) { if (!popped) {
@ -4737,7 +4747,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
break; break;
} }
case NODE_GASGN:{ case NODE_GASGN:{
COMPILE(ret, "lvalue", node->nd_value); CHECK(COMPILE(ret, "lvalue", node->nd_value));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
@ -4748,7 +4758,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
case NODE_IASGN: case NODE_IASGN:
case NODE_IASGN2:{ case NODE_IASGN2:{
COMPILE(ret, "lvalue", node->nd_value); CHECK(COMPILE(ret, "lvalue", node->nd_value));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
} }
@ -4758,7 +4768,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
break; break;
} }
case NODE_CDECL:{ case NODE_CDECL:{
COMPILE(ret, "lvalue", node->nd_value); CHECK(COMPILE(ret, "lvalue", node->nd_value));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
@ -4776,7 +4786,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
break; break;
} }
case NODE_CVASGN:{ case NODE_CVASGN:{
COMPILE(ret, "cvasgn val", node->nd_value); CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
} }
@ -4858,7 +4868,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
if (!popped) { if (!popped) {
ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
} }
@ -4892,7 +4902,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_LABEL(ret, lfin); ADD_LABEL(ret, lfin);
} }
else { else {
COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
ADD_SEND(ret, line, id, INT2FIX(1)); ADD_SEND(ret, line, id, INT2FIX(1));
if (!popped) { if (!popped) {
ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff)); ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
@ -4989,7 +4999,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_INSNL(ret, line, branchunless, lcfin); ADD_INSNL(ret, line, branchunless, lcfin);
} }
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
ADD_INSN(ret, line, swap); ADD_INSN(ret, line, swap);
ADD_INSN1(ret, line, topn, INT2FIX(1)); ADD_INSN1(ret, line, topn, INT2FIX(1));
ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag)); ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag));
@ -5009,7 +5019,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
} }
else { else {
COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
ADD_SEND(ret, line, atype, INT2FIX(1)); ADD_SEND(ret, line, atype, INT2FIX(1));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, swap); ADD_INSN(ret, line, swap);
@ -5033,13 +5043,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_INSN1(ret, line, putobject, rb_cObject); ADD_INSN1(ret, line, putobject, rb_cObject);
break; break;
case NODE_COLON2: case NODE_COLON2:
COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head); CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
break; break;
default: default:
COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL", COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
ruby_node_name(nd_type(node->nd_head))); ruby_node_name(nd_type(node->nd_head)));
debug_node_end(); goto ng;
return COMPILE_NG;
} }
mid = node->nd_head->nd_mid; mid = node->nd_head->nd_mid;
/* cref */ /* cref */
@ -5063,7 +5072,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
/* cref [obj] */ /* cref [obj] */
if (!popped) ADD_INSN(ret, line, pop); /* cref */ if (!popped) ADD_INSN(ret, line, pop); /* cref */
if (lassign) ADD_LABEL(ret, lassign); if (lassign) ADD_LABEL(ret, lassign);
COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value); CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
/* cref value */ /* cref value */
if (popped) if (popped)
ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */ ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */
@ -5077,7 +5086,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_INSN(ret, line, pop); /* [value] */ ADD_INSN(ret, line, pop); /* [value] */
} }
else { else {
COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value); CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
/* cref obj value */ /* cref obj value */
ADD_CALL(ret, line, node->nd_aid, INT2FIX(1)); ADD_CALL(ret, line, node->nd_aid, INT2FIX(1));
/* cref value */ /* cref value */
@ -5110,7 +5119,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
lassign = NEW_LABEL(line); lassign = NEW_LABEL(line);
} }
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head); CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
if (nd_type(node) == NODE_OP_ASGN_AND) { if (nd_type(node) == NODE_OP_ASGN_AND) {
@ -5122,7 +5131,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
ADD_LABEL(ret, lassign); ADD_LABEL(ret, lassign);
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value); CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
ADD_LABEL(ret, lfin); ADD_LABEL(ret, lfin);
if (popped) { if (popped) {
@ -5157,7 +5166,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
node->nd_args->nd_head->nd_lit = str; node->nd_args->nd_head->nd_lit = str;
COMPILE(ret, "recv", node->nd_recv); CHECK(COMPILE(ret, "recv", node->nd_recv));
ADD_INSN3(ret, line, opt_aref_with, ADD_INSN3(ret, line, opt_aref_with,
new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE), new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE),
NULL/* CALL_CACHE */, str); NULL/* CALL_CACHE */, str);
@ -5237,6 +5246,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
else { else {
COMPILE_ERROR(ERROR_ARGS "invalid goto/label format"); COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
goto ng;
} }
@ -5252,7 +5262,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
#endif #endif
/* receiver */ /* receiver */
if (type == NODE_CALL || type == NODE_QCALL) { if (type == NODE_CALL || type == NODE_QCALL) {
COMPILE(recv, "recv", node->nd_recv); CHECK(COMPILE(recv, "recv", node->nd_recv));
if (type == NODE_QCALL) { if (type == NODE_QCALL) {
lskip = NEW_LABEL(line); lskip = NEW_LABEL(line);
ADD_INSN(recv, line, dup); ADD_INSN(recv, line, dup);
@ -5434,7 +5444,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_VALUES:{ case NODE_VALUES:{
NODE *n = node; NODE *n = node;
while (n) { while (n) {
COMPILE(ret, "values item", n->nd_head); CHECK(COMPILE(ret, "values item", n->nd_head));
n = n->nd_next; n = n->nd_next;
} }
ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen)); ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen));
@ -5491,7 +5501,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_ADJUST(ret, line, 0); ADD_ADJUST(ret, line, 0);
} }
COMPILE(ret, "return nd_stts (return val)", node->nd_stts); CHECK(COMPILE(ret, "return nd_stts (return val)", node->nd_stts));
if (type == ISEQ_TYPE_METHOD) { if (type == ISEQ_TYPE_METHOD) {
add_ensure_iseq(ret, iseq, 1); add_ensure_iseq(ret, iseq, 1);
@ -5522,8 +5532,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
INIT_ANCHOR(args); INIT_ANCHOR(args);
if (iseq->body->type == ISEQ_TYPE_TOP) { if (iseq->body->type == ISEQ_TYPE_TOP) {
COMPILE_ERROR(ERROR_ARGS "Invalid yield"); COMPILE_ERROR(ERROR_ARGS "Invalid yield");
debug_node_end(); goto ng;
return COMPILE_NG;
} }
if (node->nd_head) { if (node->nd_head) {
@ -5643,12 +5652,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
INT2FIX(0)); INT2FIX(0));
break; break;
case NODE_MATCH2: case NODE_MATCH2:
COMPILE(recv, "receiver", node->nd_recv); CHECK(COMPILE(recv, "receiver", node->nd_recv));
COMPILE(val, "value", node->nd_value); CHECK(COMPILE(val, "value", node->nd_value));
break; break;
case NODE_MATCH3: case NODE_MATCH3:
COMPILE(recv, "receiver", node->nd_value); CHECK(COMPILE(recv, "receiver", node->nd_value));
COMPILE(val, "value", node->nd_recv); CHECK(COMPILE(val, "value", node->nd_recv));
break; break;
} }
@ -5751,7 +5760,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
break; break;
} }
case NODE_EVSTR:{ case NODE_EVSTR:{
COMPILE(ret, "nd_body", node->nd_body); CHECK(COMPILE(ret, "nd_body", node->nd_body));
if (popped) { if (popped) {
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
@ -5784,37 +5793,37 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
case NODE_ARGSCAT:{ case NODE_ARGSCAT:{
if (popped) { if (popped) {
COMPILE(ret, "argscat head", node->nd_head); CHECK(COMPILE(ret, "argscat head", node->nd_head));
ADD_INSN1(ret, line, splatarray, Qfalse); ADD_INSN1(ret, line, splatarray, Qfalse);
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
COMPILE(ret, "argscat body", node->nd_body); CHECK(COMPILE(ret, "argscat body", node->nd_body));
ADD_INSN1(ret, line, splatarray, Qfalse); ADD_INSN1(ret, line, splatarray, Qfalse);
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
} }
else { else {
COMPILE(ret, "argscat head", node->nd_head); CHECK(COMPILE(ret, "argscat head", node->nd_head));
COMPILE(ret, "argscat body", node->nd_body); CHECK(COMPILE(ret, "argscat body", node->nd_body));
ADD_INSN(ret, line, concatarray); ADD_INSN(ret, line, concatarray);
} }
break; break;
} }
case NODE_ARGSPUSH:{ case NODE_ARGSPUSH:{
if (popped) { if (popped) {
COMPILE(ret, "arsgpush head", node->nd_head); CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
ADD_INSN1(ret, line, splatarray, Qfalse); ADD_INSN1(ret, line, splatarray, Qfalse);
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
COMPILE_(ret, "argspush body", node->nd_body, popped); CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
} }
else { else {
COMPILE(ret, "arsgpush head", node->nd_head); CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
COMPILE_(ret, "argspush body", node->nd_body, popped); CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
ADD_INSN1(ret, line, newarray, INT2FIX(1)); ADD_INSN1(ret, line, newarray, INT2FIX(1));
ADD_INSN(ret, line, concatarray); ADD_INSN(ret, line, concatarray);
} }
break; break;
} }
case NODE_SPLAT:{ case NODE_SPLAT:{
COMPILE(ret, "splat", node->nd_head); CHECK(COMPILE(ret, "splat", node->nd_head));
ADD_INSN1(ret, line, splatarray, Qtrue); ADD_INSN1(ret, line, splatarray, Qtrue);
if (popped) { if (popped) {
@ -5848,7 +5857,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
debugp_param("defs/iseq", rb_iseqw_new(singleton_method)); debugp_param("defs/iseq", rb_iseqw_new(singleton_method));
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
COMPILE(ret, "defs: recv", node->nd_recv); CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid)); ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
ADD_INSN1(ret, line, putiseq, singleton_method); ADD_INSN1(ret, line, putiseq, singleton_method);
ADD_SEND (ret, line, id_core_define_singleton_method, INT2FIX(3)); ADD_SEND (ret, line, id_core_define_singleton_method, INT2FIX(3));
@ -5861,8 +5870,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_ALIAS:{ case NODE_ALIAS:{
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
COMPILE(ret, "alias arg1", node->u1.node); CHECK(COMPILE(ret, "alias arg1", node->u1.node));
COMPILE(ret, "alias arg2", node->u2.node); CHECK(COMPILE(ret, "alias arg2", node->u2.node));
ADD_SEND(ret, line, id_core_set_method_alias, INT2FIX(3)); ADD_SEND(ret, line, id_core_set_method_alias, INT2FIX(3));
if (popped) { if (popped) {
@ -5884,7 +5893,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
case NODE_UNDEF:{ case NODE_UNDEF:{
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
COMPILE(ret, "undef arg", node->u2.node); CHECK(COMPILE(ret, "undef arg", node->u2.node));
ADD_SEND(ret, line, id_core_undef_method, INT2FIX(2)); ADD_SEND(ret, line, id_core_undef_method, INT2FIX(2));
if (popped) { if (popped) {
@ -5901,7 +5910,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED; if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED;
if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS; if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS;
COMPILE(ret, "super", node->nd_super); CHECK(COMPILE(ret, "super", node->nd_super));
ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags)); ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags));
if (popped) { if (popped) {
@ -5930,7 +5939,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_str_new2("singleton class"), const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_str_new2("singleton class"),
ISEQ_TYPE_CLASS, line); ISEQ_TYPE_CLASS, line);
COMPILE(ret, "sclass#recv", node->nd_recv); CHECK(COMPILE(ret, "sclass#recv", node->nd_recv));
ADD_INSN (ret, line, putnil); ADD_INSN (ret, line, putnil);
CONST_ID(singletonclass, "singletonclass"); CONST_ID(singletonclass, "singletonclass");
ADD_INSN3(ret, line, defineclass, ADD_INSN3(ret, line, defineclass,
@ -5977,7 +5986,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
else { else {
/* function call */ /* function call */
ADD_CALL_RECEIVER(ret, line); ADD_CALL_RECEIVER(ret, line);
COMPILE(ret, "colon2#nd_head", node->nd_head); CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head));
ADD_CALL(ret, line, node->nd_mid, INT2FIX(1)); ADD_CALL(ret, line, node->nd_mid, INT2FIX(1));
} }
if (popped) { if (popped) {
@ -6024,8 +6033,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
} }
break; break;
} }
COMPILE(ret, "min", (NODE *) node->nd_beg); CHECK(COMPILE(ret, "min", (NODE *) node->nd_beg));
COMPILE(ret, "max", (NODE *) node->nd_end); CHECK(COMPILE(ret, "max", (NODE *) node->nd_end));
if (popped) { if (popped) {
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
@ -6161,7 +6170,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx)); ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
ADD_INSNL(ret, line, branchif, end_label); ADD_INSNL(ret, line, branchif, end_label);
COMPILE_POPPED(ret, "keyword default argument", node->nd_body); CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body));
ADD_LABEL(ret, end_label); ADD_LABEL(ret, end_label);
} }
@ -6197,8 +6206,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
node->nd_args->nd_head->nd_lit = str; node->nd_args->nd_head->nd_lit = str;
iseq_add_mark_object(iseq, str); iseq_add_mark_object(iseq, str);
COMPILE(ret, "recv", node->nd_recv); CHECK(COMPILE(ret, "recv", node->nd_recv));
COMPILE(ret, "value", node->nd_args->nd_next->nd_head); CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head));
if (!popped) { if (!popped) {
ADD_INSN(ret, line, swap); ADD_INSN(ret, line, swap);
ADD_INSN1(ret, line, topn, INT2FIX(1)); ADD_INSN1(ret, line, topn, INT2FIX(1));
@ -6268,8 +6277,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe
rb_iseq_make_compile_option(&new_opt, node->nd_orig); rb_iseq_make_compile_option(&new_opt, node->nd_orig);
ISEQ_COMPILE_DATA(iseq)->option = &new_opt; ISEQ_COMPILE_DATA(iseq)->option = &new_opt;
} }
COMPILE_POPPED(ret, "prelude", node->nd_head); CHECK(COMPILE_POPPED(ret, "prelude", node->nd_head));
COMPILE_(ret, "body", node->nd_body, popped); CHECK(COMPILE_(ret, "body", node->nd_body, popped));
ISEQ_COMPILE_DATA(iseq)->option = orig_opt; ISEQ_COMPILE_DATA(iseq)->option = orig_opt;
break; break;
} }

View File

@ -958,6 +958,23 @@ eom
end end
end end
def test_syntax_error_in_rescue
bug12613 = '[ruby-core:76531] [Bug #12613]'
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
begin;
while true
begin
p
rescue
retry
else
retry
end
break
end
end;
end
private private
def not_label(x) @result = x; @not_label ||= nil end def not_label(x) @result = x; @not_label ||= nil end