Commit d3670665 authored by Michael Beck's avatar Michael Beck
Browse files

Add a tail_call attribute the Call nodes to mark possible tail calls.

No analysis for this case yet.

[r26711]
parent a4db20b9
......@@ -627,6 +627,10 @@ void set_Call_param(ir_node *node, int pos, ir_node *param);
ir_type *get_Call_type(ir_node *node);
/** Sets the type of a call. */
void set_Call_type(ir_node *node, ir_type *tp);
/** Returns non-zero if this call can be a tail-call. */
unsigned get_Call_tail_call(const ir_node *node);
/** Sets the tail call attribute. */
void set_Call_tail_call(ir_node *node, unsigned tail_call);
/**
* Returns non-zero if a Call is surely a self-recursive Call.
......
......@@ -104,9 +104,9 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
fprintf(F, " index: %u\n", get_irn_idx(n));
if (opt_dump_pointer_values_to_info)
fprintf (F, " addr: %p \n", (void *)n);
fprintf (F, " addr: %p\n", (void *)n);
fprintf (F, " mode: %s\n", get_mode_name(get_irn_mode(n)));
fprintf (F, " visited: %ld \n", get_irn_visited(n));
fprintf (F, " visited: %ld\n", get_irn_visited(n));
irg = get_irn_irg(n);
if (irg != get_const_code_irg())
fprintf (F, " irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
......@@ -121,7 +121,7 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
#ifdef INTERPROCEDURAL_VIEW
fprintf(F, " arity: %d\n", get_irn_intra_arity(n));
/* show all predecessor nodes */
fprintf(F, " pred nodes: \n");
fprintf(F, " pred nodes:\n");
if (!is_Block(n)) {
fprintf(F, " -1: ");
dump_node_opcode(F, get_irn_n(n, -1));
......@@ -135,7 +135,7 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
#else
fprintf(F, " arity: %d\n", get_irn_arity(n));
/* show all predecessor nodes */
fprintf(F, " pred nodes: \n");
fprintf(F, " pred nodes:\n");
if (!is_Block(n)) {
fprintf(F, " -1: ");
dump_node_opcode(F, get_irn_n(n, -1));
......@@ -156,7 +156,7 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
#ifdef INTERPROCEDURAL_VIEW
if ((get_irp_ip_view_state() != ip_view_no) && (is_Filter(n) || is_Block(n))) {
fprintf(F, " inter arity: %d\n", get_irn_inter_arity(n));
fprintf(F, " inter pred nodes: \n");
fprintf(F, " inter pred nodes:\n");
for (i = 0; i < get_irn_inter_arity(n); ++i) {
fprintf(F, " %d: %s ", i, is_intra_backedge(n, i) ? "be" : " ");
dump_node_opcode(F, get_irn_inter_n(n, i));
......@@ -224,9 +224,9 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
} break;
case iro_Start: {
ir_type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
fprintf(F, " start of method of type %s \n", get_type_name_ex(tp, &bad));
fprintf(F, " start of method of type %s\n", get_type_name_ex(tp, &bad));
for (i = 0; i < get_method_n_params(tp); ++i)
fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
#ifdef INTERPROCEDURAL_VIEW
if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
ir_node *sbl = get_nodes_block(n);
......@@ -247,11 +247,11 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
fprintf(F, " jump prediction: %s\n", get_cond_jmp_predicate_name(get_Cond_jmp_pred(n)));
} break;
case iro_Alloc: {
fprintf(F, " allocating entity of type: %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
fprintf(F, " allocating entity of type: %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
fprintf(F, " allocating on: the %s\n", (get_Alloc_where(n) == stack_alloc) ? "stack" : "heap");
} break;
case iro_Free: {
fprintf(F, " freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
fprintf(F, " freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
fprintf(F, " allocated on: the %s\n", (get_Free_where(n) == stack_alloc) ? "stack" : "heap");
} break;
case iro_Sel: {
......@@ -268,15 +268,17 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
} break;
case iro_Call: {
ir_type *tp = get_Call_type(n);
fprintf(F, " calling method of type %s \n", get_type_name_ex(tp, &bad));
if (get_Call_tail_call(n))
fprintf(F, " tail call\n");
fprintf(F, " calling method of type %s\n", get_type_name_ex(tp, &bad));
if(get_unknown_type() != tp) {
for (i = 0; i < get_method_n_params(tp); ++i)
fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
for (i = 0; i < get_method_n_ress(tp); ++i)
fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
}
if (Call_has_callees(n)) {
fprintf(F, " possible callees: \n");
fprintf(F, " possible callees:\n");
for (i = 0; i < get_Call_n_callees(n); i++) {
fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
}
......@@ -286,7 +288,7 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
ir_node *call = get_CallBegin_call(n);
fprintf(F, " Call: %ld\n", get_irn_node_nr(call));
if (Call_has_callees(call)) {
fprintf(F, " possible callees: \n");
fprintf(F, " possible callees:\n");
for (i = 0; i < get_Call_n_callees(call); i++) {
fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
}
......@@ -298,14 +300,14 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
case iro_Return: {
if (!get_interprocedural_view()) {
ir_type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
fprintf(F, " return in method of type %s \n", get_type_name_ex(tp, &bad));
fprintf(F, " return in method of type %s\n", get_type_name_ex(tp, &bad));
for (i = 0; i < get_method_n_ress(tp); ++i)
fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
}
} break;
case iro_Const: {
assert(get_Const_type(n) != firm_none_type);
fprintf(F, " Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
fprintf(F, " Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
} break;
case iro_SymConst: {
switch(get_SymConst_kind(n)) {
......@@ -343,7 +345,7 @@ int dump_irnode_to_file(FILE *F, ir_node *n) {
fprintf(F, " name: %s\n", get_enumeration_name(get_SymConst_enum(n)));
break;
}
fprintf(F, " type of value: %s \n", get_type_name_ex(get_SymConst_value_type(n), &bad));
fprintf(F, " type of value: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
} break;
case iro_Load:
fprintf(F, " mode of loaded value: %s\n", get_mode_name_ex(get_Load_mode(n), &bad));
......@@ -636,7 +638,7 @@ void dump_entity_to_file_prefix(FILE *F, ir_entity *ent, char *prefix, unsigned
get_type_name(get_entity_owner(ov)));
}
} else {
fprintf(F, "%s Does not overwrite other entities. \n", prefix);
fprintf(F, "%s Does not overwrite other entities.\n", prefix);
}
if (get_entity_n_overwrittenby(ent) > 0) {
fprintf(F, "%s overwritten by:\n", prefix);
......@@ -646,7 +648,7 @@ void dump_entity_to_file_prefix(FILE *F, ir_entity *ent, char *prefix, unsigned
get_type_name(get_entity_owner(ov)));
}
} else {
fprintf(F, "%s Is not overwritten by other entities. \n", prefix);
fprintf(F, "%s Is not overwritten by other entities.\n", prefix);
}
if (get_irp_inh_transitive_closure_state() != inh_transitive_closure_none) {
......@@ -1140,7 +1142,7 @@ void dump_type_to_file(FILE *F, ir_type *tp, dump_verbosity verbosity) {
case tpo_class:
if ((verbosity & dump_verbosity_methods) || (verbosity & dump_verbosity_fields)) {
fprintf(F, "\n members: \n");
fprintf(F, "\n members:\n");
}
for (i = 0; i < get_class_n_members(tp); ++i) {
ir_entity *mem = get_class_member(tp, i);
......
......@@ -518,9 +518,10 @@ symconst_attr *get_irn_symconst_attr(ir_node *node) {
return &node->attr.symc;
}
ir_type *get_irn_call_attr(ir_node *node) {
call_attr *get_irn_call_attr(ir_node *node) {
assert(is_Call(node));
return node->attr.call.type = skip_tid(node->attr.call.type);
node->attr.call.type = skip_tid(node->attr.call.type);
return &node->attr.call;
}
sel_attr *get_irn_sel_attr(ir_node *node) {
......@@ -1385,6 +1386,18 @@ set_Call_type(ir_node *node, ir_type *tp) {
node->attr.call.type = tp;
}
unsigned
get_Call_tail_call(const ir_node *node) {
assert(is_Call(node));
return node->attr.call.tail_call;
}
void
set_Call_tail_call(ir_node *node, unsigned tail_call) {
assert(is_Call(node));
node->attr.call.tail_call = tail_call != 0;
}
ir_node *
get_Builtin_mem(const ir_node *node) {
assert(is_Builtin(node));
......
......@@ -48,8 +48,7 @@ long get_irn_proj_attr (ir_node *node);
alloc_attr *get_irn_alloc_attr (ir_node *node);
free_attr *get_irn_free_attr (ir_node *node);
symconst_attr *get_irn_symconst_attr (ir_node *node);
ir_type *get_irn_call_attr (ir_node *node);
ir_type *get_irn_funccall_attr (ir_node *node);
call_attr *get_irn_call_attr (ir_node *node);
sel_attr *get_irn_sel_attr (ir_node *node);
phi_attr *get_irn_phi_attr (ir_node *node);
block_attr *get_irn_block_attr (ir_node *node);
......
......@@ -308,7 +308,7 @@ static tarval *computed_value_Eor(const ir_node *n) {
tb = value_of(b);
if ((ta != tarval_bad) && (tb != tarval_bad)) {
return tarval_eor (ta, tb);
return tarval_eor(ta, tb);
}
return tarval_bad;
} /* computed_value_Eor */
......@@ -337,7 +337,7 @@ static tarval *computed_value_Shl(const ir_node *n) {
tarval *tb = value_of(b);
if ((ta != tarval_bad) && (tb != tarval_bad)) {
return tarval_shl (ta, tb);
return tarval_shl(ta, tb);
}
return tarval_bad;
} /* computed_value_Shl */
......@@ -353,7 +353,7 @@ static tarval *computed_value_Shr(const ir_node *n) {
tarval *tb = value_of(b);
if ((ta != tarval_bad) && (tb != tarval_bad)) {
return tarval_shr (ta, tb);
return tarval_shr(ta, tb);
}
return tarval_bad;
} /* computed_value_Shr */
......@@ -369,7 +369,7 @@ static tarval *computed_value_Shrs(const ir_node *n) {
tarval *tb = value_of(b);
if ((ta != tarval_bad) && (tb != tarval_bad)) {
return tarval_shrs (ta, tb);
return tarval_shrs(ta, tb);
}
return tarval_bad;
} /* computed_value_Shrs */
......@@ -5996,7 +5996,10 @@ static int node_cmp_attr_SymConst(ir_node *a, ir_node *b) {
/** Compares the attributes of two Call nodes. */
static int node_cmp_attr_Call(ir_node *a, ir_node *b) {
return get_irn_call_attr(a) != get_irn_call_attr(b);
const call_attr *pa = get_irn_call_attr(a);
const call_attr *pb = get_irn_call_attr(b);
return (pa->type != pb->type)
|| (pa->tail_call != pb->tail_call);
} /* node_cmp_attr_Call */
/** Compares the attributes of two Sel nodes. */
......
......@@ -188,9 +188,10 @@ typedef struct {
/** Call attributes. */
typedef struct {
except_attr exc; /**< the exception attribute. MUST be the first one. */
ir_type *type; /**< type of called procedure */
ir_entity ** callee_arr; /**< result of callee analysis */
except_attr exc; /**< the exception attribute. MUST be the first one. */
ir_type *type; /**< type of called procedure */
ir_entity **callee_arr; /**< result of callee analysis */
unsigned tail_call:1; /**< if set, can be a tail call */
} call_attr;
/** Builtin attributes. */
......
......@@ -79,6 +79,9 @@ def get_io_type(type, attrname, node):
elif type == "int":
importcmd = "int %s = (int) read_long(env);" % attrname
exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
elif type == "unsigned":
importcmd = "unsigned %s = (unsigned) read_long(env);" % attrname
exportcmd = """fprintf(env->file, "%%u ", %(val)s);"""
elif type == "long":
importcmd = "long %s = read_long(env);" % attrname
exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
......
......@@ -235,6 +235,12 @@ class Call(Op):
dict(
type = "ir_type*",
name = "type"
),
dict(
type = "unsigned",
name = "tail_call",
# the tail call attribute can only be set by analysis
init = "0"
)
]
attr_struct = "call_attr"
......
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