return NULL;
}
+/* Returns true if control flow operation exc is predecessor of end
+ block in irg. Works also for Return nodes, not only exceptions. */
+static bool exc_branches_to_end(ir_graph *irg, ir_node *exc) {
+ int i;
+ ir_node *end = get_irg_end_block(irg);
+ for (i = get_Block_n_cfgpreds(end) -1; i >= 0; --i)
+ if (get_Block_cfgpred(end, i) == exc) return true;
+ return false;
+}
+
+/* Returns true if only caller of irg is "Unknown". */
+static bool is_outermost_graph(ir_graph *irg) {
+ irg_data_t * data = get_entity_link(get_irg_ent(irg));
+ if (data->count) {
+ return false;
+ } else if (data->open) {
+ /* Die Methode wird nur von "der" unbekannten Aufrufstelle
+ * aufgerufen. Darstellung wird für diese Methode nicht
+ * geändert. */
+ } else {
+ /* Methode kann nicht aufgerufen werden. Die Darstellung wird
+ * für diese Methode nicht geändert. Das kann nicht vorkommen,
+ * wenn zuvor "gc_irgs()" aufgerufen wurde. */
+ }
+ return true;
+}
/* Grundblock der Call-Operation aufteilen. CallBegin- und Filter-Operationen
* einfügen. Die Steuer- und Datenflussabhängigkeiten von den aufgerufenen
/* Die interprozeduralen Steuerflussvorgänger des except_block
* bestimmen. */
if ((proj = get_except(call)) != NULL) {
- except_block = create_Block(1, &proj);
- set_nodes_Block(proj, except_block);
- exchange(proj, new_Break());
- set_irg_current_block(current_ir_graph, pre_block);
- set_irn_n(except_block, 0, new_Proj(call, mode_X, 1));
- set_irg_current_block(current_ir_graph, post_block);
+ 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
+ will generate a Break that goes to the end block. This is illegal
+ Frim. So directly branch to the end block with all exceptions. */
+ exc_to_end = true;
+ 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);
+ }
+ } else
+#endif
+ {
+ except_block = create_Block(1, &proj);
+ set_nodes_Block(proj, except_block);
+ exchange(proj, new_Break());
+ set_irg_current_block(current_ir_graph, pre_block);
+ set_irn_n(except_block, 0, new_Proj(call, mode_X, 1));
+ set_irg_current_block(current_ir_graph, post_block);
+ }
/*
* Set flag to suppress verifying placement on proper irg:
in[i] = new_Unknown();
}
}
- set_Block_cg_cfgpred_arr(except_block, n_callees, in);
- }
+ preds = n_callees;
+ if (exc_to_end) {
+ /* append all existing preds of the end block to new in array.
+ * Normal access routine guarantees that with first visit we
+ * get the normal preds, and from then on the _cg_ preds.
+ * (interporcedural view is set!)
+ * Do not add the exc pred of end we are replacing! */
+ for (i = get_Block_n_cfgpreds(except_block)-1; i >= 0; --i) {
+ ir_node *pred = get_Block_cfgpred(except_block, i);
+ if (pred != proj) {
+ ARR_APP1(ir_node *, in, pred);
+ preds++;
+ }
+ }
+ }
+ set_Block_cg_cfgpred_arr(except_block, preds, in);
+ }
set_interprocedural_view(0);
/* Diesen Vorgänger in den Start-Blöcken der aufgerufenen Methoden
#define TYPE_CLASS_NODE_ATTR "color: green"
#define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
#define ENTITY_NODE_ATTR "color: yellow"
-#define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
+#define ENT_TYPE_EDGE_ATTR "class: 3 label \"type\" color: red"
#define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
#define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
#define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
static INLINE
bool is_constlike_node(ir_node *n) {
ir_op *op = get_irn_op(n);
- return (op == op_Const || op == op_Bad || op == op_SymConst);
+ return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
}
+/* outputs the predecessors of n, that are constants, local. I.e.,
+ generates a copy of the constant for each node called with. */
static void dump_const_node_local(ir_node *n, pmap *irgmap) {
int i;
if (!get_opt_dump_const_local()) return;
/* dump edges to our inputs */
static void
-dump_ir_data_edges(ir_node *n) {
+dump_ir_data_edges(ir_node *n, pmap *irgmap) {
int i, visited = get_irn_visited(n);
if ((get_irn_op(n) == op_End) && (!dump_keepalive))
fprintf (F, "edge: {sourcename: \"");
PRINT_NODEID(n);
fprintf (F, "\" targetname: ");
- if ((get_opt_dump_const_local()) && is_constlike_node(pred))
+ if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
+ !pred_in_wrong_graph(n, i, irgmap))
{
- PRINT_CONSTID(n,pred);
+ PRINT_CONSTID(n, pred);
}
else
{fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
dump_whole_node (ir_node *n, void* env) {
dump_node(n, NULL);
if (!node_floats(n)) dump_ir_block_edge(n);
- dump_ir_data_edges(n);
+ dump_ir_data_edges(n, NULL);
}
void
if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
dump_node(n, NULL);
- dump_ir_data_edges(n);
+ dump_ir_data_edges(n, NULL);
}
if (get_irn_op(n) == op_Bad)
Bad_dumped = 1;
fprintf(F, "\" status:clustered color:%s \n",
get_Block_matured (block) ? "yellow" : "red");
/* dump the blocks edges */
- dump_ir_data_edges(block);
+ dump_ir_data_edges(block, NULL);
/* dump the nodes that go into the block */
irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
dump_blockless_nodes (ir_node *n, void *env) {
if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
dump_node(n, NULL);
- dump_ir_data_edges(n);
+ dump_ir_data_edges(n, NULL);
dump_ir_block_edge(n);
if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
return;
}
if (node_floats(n)) {
dump_node(n, NULL);
- dump_ir_data_edges(n);
+ dump_ir_data_edges(n, NULL);
if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
}
}
set_irn_link(node, NULL);
}
+
static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
assert(node); assert(map);
if (is_Block(node)
ir_node *node;
pmap *irgmap = (pmap *)env;
assert(is_Block(block));
+
fprintf(F, "graph: { title: \"");
PRINT_NODEID(block);
fprintf(F, "\" label: \"");
- fprintf (F, "%s ", get_op_name(get_irn_op(block)));
-#ifdef DEBUG_libfirm
- fprintf (F, "%ld", get_irn_node_nr(block));
-#else
- fprintf (F, "%p", (void*) block);
-#endif
+ dump_node_opcode(block);
+ fprintf (F, " %ld", get_irn_node_nr(block));
+
if (exc_normal != get_Block_exc(block)) {
fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
}
get_Block_matured(block) ? "yellow" : "red");
/* dump the blocks edges */
- dump_ir_data_edges(block);
+ dump_ir_data_edges(block, irgmap);
/* dump the nodes that go into the block */
for (node = get_irn_link(block); node; node = get_irn_link(node)) {
dump_node(node, irgmap);
- dump_ir_data_edges(node);
+ dump_ir_data_edges(node, irgmap);
}
/* Close the vcg information for the block */
- fprintf(F, "}\n\n");
+ fprintf(F, "}\n");
+ dump_const_node_local(block, irgmap);
+ fprintf(F, "\n");
}
static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
int i;
- fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
+ fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
(void*) irg, get_entity_name(get_irg_ent(irg)));
for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
ir_node * node = arr[i];
if (is_Block(node)) {
- /* Dumps the block and all the nodes in the block , which are to
+ /* Dumps the block and all the nodes in the block, which are to
be found in Block->link. */
dump_cg_ir_block(node, irgmap);
} else {
/* Nodes that are not in a Block. */
dump_node(node, NULL);
- dump_ir_data_edges(node);
+ dump_ir_data_edges(node, NULL);
}
}
/* Close the vcg information for the irg */
for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
ir_node * node = arr[i];
dump_node(node, map2);
- dump_ir_data_edges(node);
+ dump_ir_data_edges(node, NULL);
if (is_Block(node)) {
for (node = get_irn_link(node); node; node = get_irn_link(node)) {
dump_node(node, map2);
dump_ir_block_edge(node);
- dump_ir_data_edges(node);
+ dump_ir_data_edges(node, NULL);
}
}
}
}
}
+#include "irdump.h"
+
void inline_method(ir_node *call, ir_graph *called_graph) {
ir_node *pre_call;
ir_node *post_call, *post_bl;
cf_op = get_Block_cfgpred(end_bl, i);
if (get_irn_op(cf_op) == op_Proj) {
cf_op = get_Proj_pred(cf_op);
- if (get_irn_op(cf_op) == op_Tuple) {
- cf_op = get_Tuple_pred(cf_op, 1);
+ if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
+ // There are unoptimized tuples from inlineing before when no exc
+ assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
+ cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
assert(get_irn_op(cf_op) == op_Jmp);
break;
}
while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
/* We would have to run gigo if new is bad, so we
promote it directly below. */
- assert(((b == new) || get_opt_control_flow_straightening() || get_opt_control_flow_weak_simplification()) &&
+ assert(((b == new) ||
+ get_opt_control_flow_straightening() ||
+ get_opt_control_flow_weak_simplification()) &&
("strange flag setting"));
exchange (b, new);
b = new;
(get_irn_arity(n) > 1)) {
arity = get_irn_arity(n);
+ if (n == get_irg_end_block(current_ir_graph))
+ return; // No use to add a block here.
+
for (i=0; i<arity; i++) {
pre = get_irn_n(n, i);
/* Predecessor has multiple sucessors. Insert new flow edge */
- if ((NULL != pre) && (op_Proj == get_irn_op(pre)) &&
+ if ((NULL != pre) &&
+ (op_Proj == get_irn_op(pre)) &&
op_Raise != get_irn_op(skip_Proj(pre))) {
/* set predecessor array for new block */
#ifdef DEBUG_libfirm
return node->node_nr;
#else
- return 0;
+ return (long)&node;
#endif
}
INLINE void *get_irn_link (const ir_node *node);
/** Outputs a unique number for this node if libfirm is compiled for
- debugging, (configure with --enable-debug) else returns 0. */
+ debugging, (configure with --enable-debug) else returns address
+ of node cast to long. */
INLINE long get_irn_node_nr(const ir_node *node);
/** Returns the ir_graph this node belongs to. Only valid for
// End block may only have Return, Raise or fragile ops as preds.
if (n == get_irg_end_block(irg))
for (i = 0; i < get_Block_n_cfgpreds(n); ++i) {
-#if 1 // Some optimization seems to add a Jmp to the End Block??
ir_node *pred = skip_Proj(get_Block_cfgpred(n, i));
- if ((get_irn_op(pred) == op_Return) ||
- is_Bad(pred) ||
- (get_irn_op(pred) == op_Raise) ||
- is_fragile_op(pred) )
- { }
- else {
- DDMG(irg); printf(" pred %d, ", i); DDMN(n); DDMN(pred);
- }
-
+ if (is_Proj(pred) || get_irn_op(pred) == op_Tuple)
+ break; // We can not test properly. How many tuples are there?
ASSERT_AND_RET(((get_irn_op(pred) == op_Return) ||
is_Bad(pred) ||
(get_irn_op(pred) == op_Raise) ||
is_fragile_op(pred) ),
"End Block node", 0);
-#endif
}
break;