Correctly casting node for accessing nd_recv, nd_mid and nd_args in compile.c

This commit is contained in:
yui-knk 2023-10-01 12:51:25 +09:00 committed by Yuichiro Kaneko
parent fdc329ea6f
commit b1131851e0

125
compile.c
View File

@ -721,6 +721,73 @@ validate_labels(rb_iseq_t *iseq, st_table *labels_table)
st_free_table(labels_table); st_free_table(labels_table);
} }
static NODE *
get_nd_recv(const NODE *node)
{
switch (nd_type(node)) {
case NODE_CALL:
return RNODE_CALL(node)->nd_recv;
case NODE_OPCALL:
return RNODE_OPCALL(node)->nd_recv;
case NODE_FCALL:
return 0;
case NODE_QCALL:
return RNODE_QCALL(node)->nd_recv;
case NODE_VCALL:
return 0;
case NODE_ATTRASGN:
return RNODE_ATTRASGN(node)->nd_recv;
case NODE_OP_ASGN1:
return RNODE_OP_ASGN1(node)->nd_recv;
case NODE_OP_ASGN2:
return RNODE_OP_ASGN2(node)->nd_recv;
default:
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
}
}
static ID
get_nd_mid(const NODE *node)
{
switch (nd_type(node)) {
case NODE_CALL:
return RNODE_CALL(node)->nd_mid;
case NODE_OPCALL:
return RNODE_OPCALL(node)->nd_mid;
case NODE_FCALL:
return RNODE_FCALL(node)->nd_mid;
case NODE_QCALL:
return RNODE_QCALL(node)->nd_mid;
case NODE_VCALL:
return RNODE_VCALL(node)->nd_mid;
case NODE_ATTRASGN:
return RNODE_ATTRASGN(node)->nd_mid;
default:
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
}
}
static NODE *
get_nd_args(const NODE *node)
{
switch (nd_type(node)) {
case NODE_CALL:
return RNODE_CALL(node)->nd_args;
case NODE_OPCALL:
return RNODE_OPCALL(node)->nd_args;
case NODE_FCALL:
return RNODE_FCALL(node)->nd_args;
case NODE_QCALL:
return RNODE_QCALL(node)->nd_args;
case NODE_VCALL:
return 0;
case NODE_ATTRASGN:
return RNODE_ATTRASGN(node)->nd_args;
default:
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
}
}
VALUE VALUE
rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func * ifunc) rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func * ifunc)
{ {
@ -5353,8 +5420,8 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath)
static inline int static inline int
private_recv_p(const NODE *node) private_recv_p(const NODE *node)
{ {
if (nd_type_p(RNODE_CALL(node)->nd_recv, NODE_SELF)) { if (nd_type_p(get_nd_recv(node), NODE_SELF)) {
NODE *self = RNODE_CALL(node)->nd_recv; NODE *self = get_nd_recv(node);
return RNODE_SELF(self)->nd_state != 0; return RNODE_SELF(self)->nd_state != 0;
} }
return 0; return 0;
@ -5477,7 +5544,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
(type == NODE_CALL || type == NODE_OPCALL || (type == NODE_CALL || type == NODE_OPCALL ||
(type == NODE_ATTRASGN && !private_recv_p(node))); (type == NODE_ATTRASGN && !private_recv_p(node)));
if (RNODE_CALL(node)->nd_args || explicit_receiver) { if (get_nd_args(node) || explicit_receiver) {
if (!lfinish[1]) { if (!lfinish[1]) {
lfinish[1] = NEW_LABEL(line); lfinish[1] = NEW_LABEL(line);
} }
@ -5485,31 +5552,31 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
lfinish[2] = NEW_LABEL(line); lfinish[2] = NEW_LABEL(line);
} }
} }
if (RNODE_CALL(node)->nd_args) { if (get_nd_args(node)) {
defined_expr0(iseq, ret, RNODE_CALL(node)->nd_args, lfinish, Qfalse, false); defined_expr0(iseq, ret, get_nd_args(node), lfinish, Qfalse, false);
ADD_INSNL(ret, line_node, branchunless, lfinish[1]); ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
} }
if (explicit_receiver) { if (explicit_receiver) {
defined_expr0(iseq, ret, RNODE_CALL(node)->nd_recv, lfinish, Qfalse, true); defined_expr0(iseq, ret, get_nd_recv(node), lfinish, Qfalse, true);
switch (nd_type(RNODE_CALL(node)->nd_recv)) { switch (nd_type(get_nd_recv(node))) {
case NODE_CALL: case NODE_CALL:
case NODE_OPCALL: case NODE_OPCALL:
case NODE_VCALL: case NODE_VCALL:
case NODE_FCALL: case NODE_FCALL:
case NODE_ATTRASGN: case NODE_ATTRASGN:
ADD_INSNL(ret, line_node, branchunless, lfinish[2]); ADD_INSNL(ret, line_node, branchunless, lfinish[2]);
compile_call(iseq, ret, RNODE_CALL(node)->nd_recv, nd_type(RNODE_CALL(node)->nd_recv), line_node, 0, true); compile_call(iseq, ret, get_nd_recv(node), nd_type(get_nd_recv(node)), line_node, 0, true);
break; break;
default: default:
ADD_INSNL(ret, line_node, branchunless, lfinish[1]); ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
NO_CHECK(COMPILE(ret, "defined/recv", RNODE_CALL(node)->nd_recv)); NO_CHECK(COMPILE(ret, "defined/recv", get_nd_recv(node)));
break; break;
} }
if (keep_result) { if (keep_result) {
ADD_INSN(ret, line_node, dup); ADD_INSN(ret, line_node, dup);
} }
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD), ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD),
ID2SYM(RNODE_CALL(node)->nd_mid), PUSH_VAL(DEFINED_METHOD)); ID2SYM(get_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
} }
else { else {
ADD_INSN(ret, line_node, putself); ADD_INSN(ret, line_node, putself);
@ -5517,7 +5584,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
ADD_INSN(ret, line_node, dup); ADD_INSN(ret, line_node, dup);
} }
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC), ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC),
ID2SYM(RNODE_CALL(node)->nd_mid), PUSH_VAL(DEFINED_METHOD)); ID2SYM(get_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
} }
return; return;
} }
@ -8018,13 +8085,13 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
/* optimization shortcut /* optimization shortcut
* "literal".freeze -> opt_str_freeze("literal") * "literal".freeze -> opt_str_freeze("literal")
*/ */
if (RNODE_CALL(node)->nd_recv && nd_type_p(RNODE_CALL(node)->nd_recv, NODE_STR) && if (get_nd_recv(node) && nd_type_p(get_nd_recv(node), NODE_STR) &&
(RNODE_CALL(node)->nd_mid == idFreeze || RNODE_CALL(node)->nd_mid == idUMinus) && (get_nd_mid(node) == idFreeze || get_nd_mid(node) == idUMinus) &&
RNODE_CALL(node)->nd_args == NULL && get_nd_args(node) == NULL &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL && ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
VALUE str = rb_fstring(RNODE_STR(RNODE_CALL(node)->nd_recv)->nd_lit); VALUE str = rb_fstring(RNODE_STR(get_nd_recv(node))->nd_lit);
if (RNODE_CALL(node)->nd_mid == idUMinus) { if (get_nd_mid(node) == idUMinus) {
ADD_INSN2(ret, line_node, opt_str_uminus, str, ADD_INSN2(ret, line_node, opt_str_uminus, str,
new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE)); new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
} }
@ -8041,14 +8108,14 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
/* optimization shortcut /* optimization shortcut
* obj["literal"] -> opt_aref_with(obj, "literal") * obj["literal"] -> opt_aref_with(obj, "literal")
*/ */
if (RNODE_CALL(node)->nd_mid == idAREF && !private_recv_p(node) && RNODE_CALL(node)->nd_args && if (get_nd_mid(node) == idAREF && !private_recv_p(node) && get_nd_args(node) &&
nd_type_p(RNODE_CALL(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_CALL(node)->nd_args)->as.nd_alen == 1 && nd_type_p(get_nd_args(node), NODE_LIST) && RNODE_LIST(get_nd_args(node))->as.nd_alen == 1 &&
nd_type_p(RNODE_LIST(RNODE_CALL(node)->nd_args)->nd_head, NODE_STR) && nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL && ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal && !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(RNODE_CALL(node)->nd_args)->nd_head)->nd_lit); VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(get_nd_args(node))->nd_head)->nd_lit);
CHECK(COMPILE(ret, "recv", RNODE_CALL(node)->nd_recv)); CHECK(COMPILE(ret, "recv", get_nd_recv(node)));
ADD_INSN2(ret, line_node, opt_aref_with, str, ADD_INSN2(ret, line_node, opt_aref_with, str,
new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE)); new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
RB_OBJ_WRITTEN(iseq, Qundef, str); RB_OBJ_WRITTEN(iseq, Qundef, str);
@ -8319,7 +8386,7 @@ static int
compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped, compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped,
const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func) const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func)
{ {
NODE *args_node = RNODE_QCALL(node)->nd_args; NODE *args_node = get_nd_args(node);
if (parent_block != NULL) { if (parent_block != NULL) {
COMPILE_ERROR(ERROR_ARGS_AT(line_node) "should not call builtins here."); COMPILE_ERROR(ERROR_ARGS_AT(line_node) "should not call builtins here.");
@ -8422,7 +8489,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
*/ */
DECL_ANCHOR(recv); DECL_ANCHOR(recv);
DECL_ANCHOR(args); DECL_ANCHOR(args);
ID mid = RNODE_CALL(node)->nd_mid; ID mid = get_nd_mid(node);
VALUE argc; VALUE argc;
unsigned int flag = 0; unsigned int flag = 0;
struct rb_callinfo_kwarg *keywords = NULL; struct rb_callinfo_kwarg *keywords = NULL;
@ -8501,7 +8568,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
const char *builtin_func; const char *builtin_func;
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
(builtin_func = iseq_builtin_function_name(type, RNODE_CALL(node)->nd_recv, mid)) != NULL) { (builtin_func = iseq_builtin_function_name(type, get_nd_recv(node), mid)) != NULL) {
return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func); return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func);
} }
@ -8511,16 +8578,16 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
int idx, level; int idx, level;
if (mid == idCall && if (mid == idCall &&
nd_type_p(RNODE_CALL(node)->nd_recv, NODE_LVAR) && nd_type_p(get_nd_recv(node), NODE_LVAR) &&
iseq_block_param_id_p(iseq, RNODE_LVAR(RNODE_CALL(node)->nd_recv)->nd_vid, &idx, &level)) { iseq_block_param_id_p(iseq, RNODE_LVAR(get_nd_recv(node))->nd_vid, &idx, &level)) {
ADD_INSN2(recv, RNODE_CALL(node)->nd_recv, getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); ADD_INSN2(recv, get_nd_recv(node), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
} }
else if (private_recv_p(node)) { else if (private_recv_p(node)) {
ADD_INSN(recv, node, putself); ADD_INSN(recv, node, putself);
flag |= VM_CALL_FCALL; flag |= VM_CALL_FCALL;
} }
else { else {
CHECK(COMPILE(recv, "recv", RNODE_CALL(node)->nd_recv)); CHECK(COMPILE(recv, "recv", get_nd_recv(node)));
} }
if (type == NODE_QCALL) { if (type == NODE_QCALL) {
@ -8534,7 +8601,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
/* args */ /* args */
if (type != NODE_VCALL) { if (type != NODE_VCALL) {
argc = setup_args(iseq, args, RNODE_CALL(node)->nd_args, &flag, &keywords); argc = setup_args(iseq, args, get_nd_args(node), &flag, &keywords);
CHECK(!NIL_P(argc)); CHECK(!NIL_P(argc));
} }
else { else {