/* Datenstruktur für jede Methode */
typedef struct {
- int count;
+ int count; /* GL: anzahl aufrufer */
bool open; /* offene Methode (mit unbekanntem Aufrufer) */
ir_node * reg, * mem, ** res; /* EndReg, Mem und Rückgabewerte */
ir_node * except, * except_mem; /* EndExcept und Mem für Ausnahmeabbruch */
} irg_data_t;
-
static irg_data_t * irg_data_create(void) {
irg_data_t * data = xmalloc(sizeof(irg_data_t));
memset(data, 0, sizeof(irg_data_t)); /* init */
return data;
}
-
/* Die Anzahl der Aufrufer jeder Methode zählen (irg_data_t->count), und die
* offenen Methoden (mit unbekannten Vorgänger) markieren. */
static void caller_init(int arr_length, entity ** free_methods) {
ir_node * filter;
assert(get_irn_op(proj) == op_Proj);
filter = new_Filter(get_Proj_pred(proj), get_irn_mode(proj), get_Proj_proj(proj));
- assert(get_Proj_proj(proj) == get_Filter_proj(filter)); /* XXX:SID */
/* Die Proj- (Id-) Operation sollte im gleichen Grundblock stehen, wie die
* Filter-Operation. */
set_nodes_Block(proj, get_nodes_Block(filter));
/* Künstlicher Steuerzusammenfluss EndReg einfügen. */
static void prepare_irg_end(ir_graph * irg, irg_data_t * data) {
- ir_node * end_block = get_irg_end_block(irg);
- ir_node * end = get_irg_end(irg);
- ir_node ** ret_arr = NULL;
+ ir_node * end_block = get_irg_end_block(irg);
+ ir_node * end = get_irg_end(irg);
+ ir_node **ret_arr = NULL;
+ ir_node **cfgpred_arr = get_Block_cfgpred_arr(end_block);
int i, j;
int n_ret = 0;
- ir_node ** cfgpred_arr = get_Block_cfgpred_arr(end_block);
+
for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
if (get_irn_op(cfgpred_arr[i]) == op_Return) {
if (ret_arr) {
++n_ret;
}
}
+
if (n_ret > 0) {
int n_res = get_method_n_ress(get_entity_type(get_irg_ent(irg)));
ir_node ** in = NEW_ARR_F(ir_node *, n_ret);
+
/* block */
for (i = n_ret - 1; i >= 0; --i) {
set_irg_current_block(irg, get_nodes_Block(ret_arr[i]));
in[i] = new_Jmp();
}
create_Block(n_ret, in);
+
/* end */
data->reg = new_EndReg();
+
/* mem */
for (i = n_ret - 1; i >= 0; --i) {
in[i] = get_Return_mem(ret_arr[i]);
}
data->mem = new_Phi(n_ret, in, mode_M);
- /* This Phi is a merge, therefor needs not be kept alive.
+ /* This Phi is a merge, therefore needs not be kept alive.
It might be optimized away, though. */
if (get_End_keepalive(end, get_End_n_keepalives(end)-1 ) == data->mem)
set_End_keepalive(end, get_End_n_keepalives(end)-1, new_Bad());
+
/* res */
data->res = NEW_ARR_F(ir_node *, n_res);
for (j = n_res - 1; j >= 0; --j) {
else /* All preds are Bad */
data->res[j] = new_Bad();
}
+
DEL_ARR_F(in);
}
+
if (ret_arr) DEL_ARR_F(ret_arr);
}
/* Rekursiv die Operation "node" und alle ihre Vorgänger aus dem Block
- * "from_block" nach "to_block" verschieben. */
+ * "from_block" nach "to_block" verschieben.
+ * Verschiebe ebenfalls die Projs aus diesen Operationen. */
static void move_nodes(ir_node * from_block, ir_node * to_block, ir_node * node) {
int i;
for (i = get_irn_arity(node) - 1; i >= 0; --i) {
}
}
set_nodes_Block(node, to_block);
+
+ /* Move projs of this node. */
+ ir_node *proj = get_irn_link(node);
+ for (; proj; proj = skip_Id(get_irn_link(proj))) {
+ if (get_irn_op(proj) != op_Proj && get_irn_op(proj) != op_Filter) continue;
+ if ((get_nodes_Block(proj) == from_block) && (skip_Proj(get_irn_n(proj, 0)) == node))
+ set_nodes_Block(proj, to_block);
+ }
}
* Start-Block auf den Aufrufer hinzufügen. */
static void construct_start(entity * caller, entity * callee,
ir_node * call, ir_node * exec) {
- irg_data_t * data = get_entity_link(callee);
- ir_graph * irg = get_entity_irg(callee);
- ir_node * start = get_irg_start(irg), * filter;
+ irg_data_t *data = get_entity_link(callee);
+ ir_graph *irg = get_entity_irg(callee);
+ ir_node *start = get_irg_start(irg);
+ ir_node *filter;
assert(irg);
assert(get_entity_peculiarity(callee) == peculiarity_existent); /* Else data is not initalized. */
assert((0 <= data->count) &&
(data->count < get_Block_cg_n_cfgpreds(get_nodes_Block(start))));
+
set_Block_cg_cfgpred(get_nodes_Block(start), data->count, exec);
for (filter = get_irn_link(start); filter; filter = get_irn_link(filter)) {
if (get_irn_op(filter) != op_Filter) continue;
/* Operationen verschieben */
move_phis(post_block, pre_block);
move_nodes(post_block, pre_block, call);
- /* @@@ GL Wer setzt die Laenge des PostBlock cgfpred array auf 1?
- GL: na, dieser Befehl... generiert neuen array. */
set_irn_in(post_block, 1, &jmp);
/* Wiederverwendete Daten initialisieren. */
if ((proj = get_except(call)) != NULL) {
int preds = 0;
bool exc_to_end = false;
-#if 1
if (exc_branches_to_end(current_ir_graph, proj)) {
/* The Call aborts the procedure if it returns with an exception.
If this is an outermost procedure, the normal handling of exceptions
if (is_outermost_graph(current_ir_graph)) {
except_block = get_irg_end_block(current_ir_graph);
} else {
- irg_data_t * data = get_entity_link(get_irg_ent(current_ir_graph));
- except_block = get_nodes_block(data->except);
+ irg_data_t * tmp_data = get_entity_link(get_irg_ent(current_ir_graph));
+ except_block = get_nodes_block(tmp_data->except);
}
} else
-#endif
{
except_block = create_Block(1, &proj);
set_nodes_Block(proj, except_block);
/* Proj-Operationen in Filter-Operationen umwandeln und
* interprozedurale Vorgänger einfügen. */
set_irg_current_block(current_ir_graph, post_block);
- for (proj = get_irn_link(call); proj && get_irn_op(proj) == op_Proj; proj = get_irn_link(proj)) {
+ for (proj = get_irn_link(call); proj; proj = get_irn_link(proj)) {
+ if (get_irn_op(proj) != op_Proj) continue;
+ if (skip_Proj(get_Proj_pred(proj)) != call) continue;
if (get_Proj_pred(proj) == call) {
if (get_Proj_proj(proj) == 0) { /* memory */
- /* memory */
+ set_nodes_Block(proj, post_block);
ir_node * filter = exchange_proj(proj);
/* filter in die Liste der Phis aufnehmen */
if (get_irn_link(filter) == NULL) { /* note CSE */
} else if (get_Proj_proj(proj) == 1) { /* except */
/* nothing: siehe oben */
} else if (get_Proj_proj(proj) == 2) { /* results */
- set_nodes_Block(proj, pre_block);
+ /* nothing */
} else if (get_Proj_proj(proj) == 3) { /* except_mem */
- /* except_mem */
+ set_nodes_Block(proj, post_block);
ir_node * filter;
assert(except_block);
set_irg_current_block(current_ir_graph, except_block);
} else {
assert(0 && "not reached");
}
- } else {
- /* result */
+ } else { /* result */
+ assert(is_Proj(get_Proj_pred(proj)) && get_Proj_pred(get_Proj_pred(proj)) == call);
+ set_nodes_Block(proj, post_block);
ir_node * filter = exchange_proj(proj);
/* filter in die Liste der Phis aufnehmen */
- if (get_irn_link(filter) == NULL) { /* note CSE */
+ if (get_irn_link(filter) == NULL) { /* not CSE */
set_irn_link(filter, get_irn_link(post_block));
set_irn_link(post_block, filter);
}
static INLINE void
dump_node_info (ir_node *n) {
int i;
+ ir_graph *irg;
fprintf (F, " info1: \"");
if (opt_dump_pointer_values_to_info)
- fprintf (F, "addr: %p \n", (void *)n);
+ fprintf (F, "addr: %p \n", (void *)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_entity_name(get_irg_entity(irg)));
/* Source types */
- switch(get_irn_opcode(n)) {
+ switch (get_irn_opcode(n)) {
case iro_Start: {
type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
fprintf(F, "start of method of type %s \n", get_type_name(tp));
assert(tp != none_type);
fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
} break;
+ case iro_Filter: {
+ int i;
+ if (interprocedural_view) {
+ fprintf(F, "intra predecessor nodes:\n");
+ for (i = 0; i < get_irn_intra_arity(n); i++) {
+ ir_node *pred = get_irn_intra_n(n, i);
+ fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
+ }
+ } else {
+ fprintf(F, "inter predecessor nodes:\n");
+ for (i = 0; i < get_irn_inter_arity(n); i++) {
+ ir_node *pred = get_irn_inter_n(n, i);
+ fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
+ get_irn_node_nr(pred), get_entity_name(get_irg_entity(get_irn_irg(pred))));
+ }
+ }
+ } break;
default: ;
}
+
if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
if (get_irn_type(n) != none_type)
fprintf (F, "\"");
}
-/* Returns true if n and pred pos are in different graphs. */
-static bool pred_in_wrong_graph(ir_node *n, int pos) {
- ir_node *pred = get_irn_n(n, pos);
-
- if (get_irn_irg(n) != get_irn_irg(pred)) return true;
- return false;
-}
-
static INLINE
bool is_constlike_node(ir_node *n) {
/* outputs the predecessors of n, that are constants, local. I.e.,
- generates a copy of the constant for each node called with. */
+ generates a copy of the constant predecessors for each node called with. */
static void dump_const_node_local(ir_node *n) {
int i;
if (!get_opt_dump_const_local()) return;
+
/* Use visited flag to avoid outputting nodes twice.
initialize it first. */
for (i = 0; i < get_irn_arity(n); i++) {
ir_node *con = get_irn_n(n, i);
if (is_constlike_node(con)) {
- if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
}
}
+
for (i = 0; i < get_irn_arity(n); i++) {
ir_node *con = get_irn_n(n, i);
if (is_constlike_node(con) && irn_not_visited(con)) {
- if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
mark_irn_visited(con);
/* Generate a new name for the node by appending the names of
n and const. */
- fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
+ fprintf (F, "node: {title: "); PRINT_CONSTID(n, con);
fprintf(F, " label: \"");
dump_node_opcode(con);
dump_node_mode (con);
dump_node_typeinfo(con);
fprintf (F, " ");
dump_node_nodeattr(con);
-#ifdef DEBUG_libfirm
fprintf (F, " %ld", get_irn_node_nr(con));
-#endif
fprintf (F, "\" ");
dump_node_vcgattr(con);
dump_node_info(con);
static void
dump_node (ir_node *n) {
if (get_opt_dump_const_local() && is_constlike_node(n)) return;
-
/* dump this node */
fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
dump_node_typeinfo(n);
fprintf (F, " ");
dump_node_nodeattr(n);
-#ifdef DEBUG_libfirm
fprintf (F, " %ld", get_irn_node_nr(n));
-#endif
fprintf (F, "\" ");
dump_node_vcgattr(n);
dump_node_info(n);
for (i = 0; i < get_irn_arity(n); i++) {
ir_node * pred = get_irn_n(n, i);
assert(pred);
+
if ((interprocedural_view && get_irn_visited(pred) < visited))
continue; /* pred not dumped */
+
if (dump_backedge_information_flag && is_backedge(n, i))
fprintf (F, "backedge: {sourcename: \"");
else
fprintf (F, "edge: {sourcename: \"");
PRINT_NODEID(n);
fprintf (F, "\" targetname: ");
- if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
- !pred_in_wrong_graph(n, i)) {
+ if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
PRINT_CONSTID(n, pred);
} else {
fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
int i;
char *suffix;
- construct_block_lists(irg);
-
if (interprocedural_view) suffix = "-ip";
else suffix = "";
vcg_open (irg, suffix);
+ construct_block_lists(irg);
+
for (i = 0; i < get_irp_n_irgs(); i++) {
ir_node **arr = ird_get_irg_link(get_irp_irg(i));
if (arr) {
/* dump all graphs */
for (i = 0; i < get_irp_n_irgs(); i++) {
current_ir_graph = get_irp_irg(i);
+ assert(ird_get_irg_link(current_ir_graph));
dump_graph(current_ir_graph);
DEL_ARR_F(ird_get_irg_link(current_ir_graph));
}
void set_interprocedural_view(bool state);
/** Create a new ir graph to built ir for a procedure.
- ent is the entity representing this procedure, i.e., the type of the
- entity must be of a method type. The constructor automatically sets the
- field irg of the entity as well as current_ir_graph to the new ir graph.
- n_loc is the number of local variables in this procedure including
- the procedure parameters.
- The state of the ir graph is: phase_building, pinned, no_outs. */
+ *
+ * ent is the entity representing this procedure, i.e., the type of the
+ * entity must be of a method type. The constructor automatically sets the
+ * field irg of the entity as well as current_ir_graph to the new ir graph.
+ * n_loc is the number of local variables in this procedure including
+ * the procedure parameters.
+ * The constructor adds the new irgraph to the list in ir_prog.
+ * The state of the ir graph is: phase_building, pinned, no_outs. */
ir_graph *new_ir_graph (entity *ent, int n_loc);
/** Frees the passed irgraph.
ir_graph * rem = current_ir_graph;
ir_node * pred;
- assert(node && node->kind==k_ir_node);
+ assert(node && node->kind == k_ir_node);
if (get_irn_visited(node) >= visited) return;
set_irn_visited(node, visited);
irg_walk(node, (irg_walk_func *) collect_irgs, NULL, irg_set);
interprocedural_view = true;
visited = get_max_irg_visited() + 1;
- irg_walk_cg(node, visited, irg_set, pre, post, env);
for (irg = eset_first(irg_set); irg; irg = eset_next(irg_set)) {
set_irg_visited(irg, visited);
}
+ irg_walk_cg(node, visited, irg_set, pre, post, env);
eset_destroy(irg_set);
} else {
inc_irg_visited(current_ir_graph);
current_ir_graph = get_irp_irg(i);
sb = get_irg_start_block(current_ir_graph);
+
if ((get_Block_n_cfgpreds(sb) > 1) ||
(get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
cg_walk_2(get_irg_end(current_ir_graph), pre, post, env);
}
+ /* Check whether we walked all procedures: there could be procedures
+ with cyclic calls but no call from the outside. */
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ ir_node *eb;
+ current_ir_graph = get_irp_irg(i);
+
+ eb = get_irg_start_block(current_ir_graph);
+ if (get_irn_visited(eb) < get_irg_visited(current_ir_graph)) {
+ cg_walk_2(get_irg_end(current_ir_graph), pre, post, env);
+ }
+ }
+
interprocedural_view = rem_view;
current_ir_graph = rem;
}
/* returns the number of predecessors without the block predecessor. */
INLINE int
-get_irn_arity (const ir_node *node) {
+get_irn_intra_arity (const ir_node *node) {
assert(node);
- if (interprocedural_view) { /* handle Filter and Block specially */
- if (get_irn_opcode(node) == iro_Filter) {
- assert(node->attr.filter.in_cg);
- return ARR_LEN(node->attr.filter.in_cg) - 1;
- } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
- return ARR_LEN(node->attr.block.in_cg) - 1;
- }
- /* else fall through */
- }
return ARR_LEN(node->in) - 1;
}
+/* returns the number of predecessors without the block predecessor. */
+INLINE int
+get_irn_inter_arity (const ir_node *node) {
+ assert(node);
+ if (get_irn_opcode(node) == iro_Filter) {
+ assert(node->attr.filter.in_cg);
+ return ARR_LEN(node->attr.filter.in_cg) - 1;
+ } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
+ return ARR_LEN(node->attr.block.in_cg) - 1;
+ }
+ return get_irn_intra_arity(node);
+}
+
+/* returns the number of predecessors without the block predecessor. */
+INLINE int
+get_irn_arity (const ir_node *node) {
+ assert(node);
+ if (interprocedural_view) return get_irn_inter_arity(node);
+ return get_irn_intra_arity(node);
+}
+
/* Returns the array with ins. This array is shifted with respect to the
array accessed by get_irn_n: The block operand is at position 0 not -1.
(@@@ This should be changed.)
memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
}
+INLINE ir_node *
+get_irn_intra_n (ir_node *node, int n) {
+ return (node->in[n + 1] = skip_nop(node->in[n + 1]));
+}
+
+INLINE ir_node*
+get_irn_inter_n (ir_node *node, int n) {
+ /* handle Filter and Block specially */
+ if (get_irn_opcode(node) == iro_Filter) {
+ assert(node->attr.filter.in_cg);
+ return (node->attr.filter.in_cg[n + 1] = skip_nop(node->attr.filter.in_cg[n + 1]));
+ } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
+ return (node->attr.block.in_cg[n + 1] = skip_nop(node->attr.block.in_cg[n + 1]));
+ }
+
+ return get_irn_intra_n (node, n);
+}
+
/* to iterate through the predecessors without touching the array */
/* To iterate over the operands iterate from 0 to i < get_irn_arity(),
to iterate includind the Block predecessor iterate from i = -1 to
If it is a block, the entry -1 is NULL. */
INLINE ir_node *
get_irn_n (ir_node *node, int n) {
- /* debug @@@
+ /* debug @@@ */
if (-1 > n || get_irn_arity(node) <= n) {
printf("pos: %d, arity: %d ", n, get_irn_arity(node));
DDMN(node);
- } */
+ } /**/
assert(node); assert(-1 <= n && n < get_irn_arity(node));
- if (interprocedural_view) { /* handle Filter and Block specially */
- if (get_irn_opcode(node) == iro_Filter) {
- assert(node->attr.filter.in_cg);
- return (node->attr.filter.in_cg[n + 1] = skip_nop(node->attr.filter.in_cg[n + 1]));
- } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
- return (node->attr.block.in_cg[n + 1] = skip_nop(node->attr.block.in_cg[n + 1]));
- }
- /* else fall through */
- }
- return (node->in[n + 1] = skip_nop(node->in[n + 1]));
+ if (interprocedural_view) return get_irn_inter_n (node, n);
+ return get_irn_intra_n (node, n);
}
+
INLINE void
set_irn_n (ir_node *node, int n, ir_node *in) {
assert(node && -1 <= n && n < get_irn_arity(node));
return node->mode->code;
}
+/** Gets the string representation of the mode .*/
+INLINE const char *
+get_irn_modename (const ir_node *node)
+{
+ assert(node);
+ return get_mode_name(node->mode);
+}
INLINE ident *
get_irn_modeident (const ir_node *node)
/** returns the number of predecessors without the block predecessor: */
int get_irn_arity (const ir_node *node);
+INLINE int get_irn_intra_arity (const ir_node *node);
+INLINE int get_irn_inter_arity (const ir_node *node);
/** Replaces the old in array by a new one that will contain the ins given in
the parameters. Conserves the block predecessor. It copies the array passed.
/* Access predecessor n */
/* get_irn_n removes Id predecessors. */
INLINE ir_node *get_irn_n (ir_node *node, int n);
+INLINE ir_node *get_irn_intra_n (ir_node *node, int n);
+INLINE ir_node *get_irn_inter_n (ir_node *node, int n);
INLINE void set_irn_n (ir_node *node, int n, ir_node *in);
/** Sets the mode struct of node */
INLINE void set_irn_mode (ir_node *node, ir_mode *mode);
INLINE modecode get_irn_modecode (const ir_node *node);
/** Gets the ident for a string representation of the mode .*/
INLINE ident *get_irn_modeident (const ir_node *node);
+/** Gets the string representation of the mode .*/
+INLINE const char *get_irn_modename (const ir_node *node);
/** Gets the opcode struct of the node */
INLINE ir_op *get_irn_op (const ir_node *node);
/** Sets the opcode struct of the node. */