Commit 78a73b3b authored by Götz Lindenmaier's avatar Götz Lindenmaier
Browse files

fixed various errors with exceptions + inlineing, dumping and interproc representation

added new asserstio in vrfy

[r1891]
parent 65fc134f
...@@ -498,6 +498,32 @@ static ir_node * get_except(ir_node * call) { ...@@ -498,6 +498,32 @@ static ir_node * get_except(ir_node * call) {
return NULL; 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 fr diese Methode nicht
* gendert. */
} else {
/* Methode kann nicht aufgerufen werden. Die Darstellung wird
* fr diese Methode nicht gendert. Das kann nicht vorkommen,
* wenn zuvor "gc_irgs()" aufgerufen wurde. */
}
return true;
}
/* Grundblock der Call-Operation aufteilen. CallBegin- und Filter-Operationen /* Grundblock der Call-Operation aufteilen. CallBegin- und Filter-Operationen
* einfgen. Die Steuer- und Datenflussabhngigkeiten von den aufgerufenen * einfgen. Die Steuer- und Datenflussabhngigkeiten von den aufgerufenen
...@@ -568,12 +594,31 @@ static void construct_call(ir_node * call) { ...@@ -568,12 +594,31 @@ static void construct_call(ir_node * call) {
/* Die interprozeduralen Steuerflussvorgnger des except_block /* Die interprozeduralen Steuerflussvorgnger des except_block
* bestimmen. */ * bestimmen. */
if ((proj = get_except(call)) != NULL) { if ((proj = get_except(call)) != NULL) {
except_block = create_Block(1, &proj); int preds = 0;
set_nodes_Block(proj, except_block); bool exc_to_end = false;
exchange(proj, new_Break()); #if 1
set_irg_current_block(current_ir_graph, pre_block); if (exc_branches_to_end(current_ir_graph, proj)) {
set_irn_n(except_block, 0, new_Proj(call, mode_X, 1)); /* The Call aborts the procedure if it returns with an exception.
set_irg_current_block(current_ir_graph, post_block); 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: * Set flag to suppress verifying placement on proper irg:
...@@ -594,9 +639,24 @@ static void construct_call(ir_node * call) { ...@@ -594,9 +639,24 @@ static void construct_call(ir_node * call) {
in[i] = new_Unknown(); 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); set_interprocedural_view(0);
/* Diesen Vorgnger in den Start-Blcken der aufgerufenen Methoden /* Diesen Vorgnger in den Start-Blcken der aufgerufenen Methoden
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
#define TYPE_CLASS_NODE_ATTR "color: green" #define TYPE_CLASS_NODE_ATTR "color: green"
#define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen" #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
#define ENTITY_NODE_ATTR "color: yellow" #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 ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
#define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green" #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
#define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green" #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
...@@ -352,10 +352,12 @@ static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) { ...@@ -352,10 +352,12 @@ static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
static INLINE static INLINE
bool is_constlike_node(ir_node *n) { bool is_constlike_node(ir_node *n) {
ir_op *op = get_irn_op(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) { static void dump_const_node_local(ir_node *n, pmap *irgmap) {
int i; int i;
if (!get_opt_dump_const_local()) return; if (!get_opt_dump_const_local()) return;
...@@ -517,7 +519,7 @@ static void print_edge_vcgattr(ir_node *from, int to) { ...@@ -517,7 +519,7 @@ static void print_edge_vcgattr(ir_node *from, int to) {
/* dump edges to our inputs */ /* dump edges to our inputs */
static void 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); int i, visited = get_irn_visited(n);
if ((get_irn_op(n) == op_End) && (!dump_keepalive)) if ((get_irn_op(n) == op_End) && (!dump_keepalive))
...@@ -534,9 +536,10 @@ dump_ir_data_edges(ir_node *n) { ...@@ -534,9 +536,10 @@ dump_ir_data_edges(ir_node *n) {
fprintf (F, "edge: {sourcename: \""); fprintf (F, "edge: {sourcename: \"");
PRINT_NODEID(n); PRINT_NODEID(n);
fprintf (F, "\" targetname: "); 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 else
{fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\""); {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
...@@ -1074,7 +1077,7 @@ static void ...@@ -1074,7 +1077,7 @@ static void
dump_whole_node (ir_node *n, void* env) { dump_whole_node (ir_node *n, void* env) {
dump_node(n, NULL); dump_node(n, NULL);
if (!node_floats(n)) dump_ir_block_edge(n); if (!node_floats(n)) dump_ir_block_edge(n);
dump_ir_data_edges(n); dump_ir_data_edges(n, NULL);
} }
void void
...@@ -1110,7 +1113,7 @@ dump_ir_blocks_nodes (ir_node *n, void *env) { ...@@ -1110,7 +1113,7 @@ dump_ir_blocks_nodes (ir_node *n, void *env) {
if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) { if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
dump_node(n, NULL); dump_node(n, NULL);
dump_ir_data_edges(n); dump_ir_data_edges(n, NULL);
} }
if (get_irn_op(n) == op_Bad) if (get_irn_op(n) == op_Bad)
Bad_dumped = 1; Bad_dumped = 1;
...@@ -1137,7 +1140,7 @@ dump_ir_block (ir_node *block, void *env) { ...@@ -1137,7 +1140,7 @@ dump_ir_block (ir_node *block, void *env) {
fprintf(F, "\" status:clustered color:%s \n", fprintf(F, "\" status:clustered color:%s \n",
get_Block_matured (block) ? "yellow" : "red"); get_Block_matured (block) ? "yellow" : "red");
/* dump the blocks edges */ /* dump the blocks edges */
dump_ir_data_edges(block); dump_ir_data_edges(block, NULL);
/* dump the nodes that go into the block */ /* dump the nodes that go into the block */
irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block); irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
...@@ -1153,14 +1156,14 @@ static void ...@@ -1153,14 +1156,14 @@ static void
dump_blockless_nodes (ir_node *n, void *env) { dump_blockless_nodes (ir_node *n, void *env) {
if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) { if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
dump_node(n, NULL); dump_node(n, NULL);
dump_ir_data_edges(n); dump_ir_data_edges(n, NULL);
dump_ir_block_edge(n); dump_ir_block_edge(n);
if (get_irn_op(n) == op_Bad) Bad_dumped = 1; if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
return; return;
} }
if (node_floats(n)) { if (node_floats(n)) {
dump_node(n, NULL); 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; if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
} }
} }
...@@ -1426,6 +1429,7 @@ static void clear_link(ir_node * node, void * env) { ...@@ -1426,6 +1429,7 @@ static void clear_link(ir_node * node, void * env) {
set_irn_link(node, NULL); set_irn_link(node, NULL);
} }
static void collect_blocks_floats_cg(ir_node * node, pmap * map) { static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
assert(node); assert(map); assert(node); assert(map);
if (is_Block(node) if (is_Block(node)
...@@ -1458,15 +1462,13 @@ static void dump_cg_ir_block(ir_node * block, void * env) { ...@@ -1458,15 +1462,13 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
ir_node *node; ir_node *node;
pmap *irgmap = (pmap *)env; pmap *irgmap = (pmap *)env;
assert(is_Block(block)); assert(is_Block(block));
fprintf(F, "graph: { title: \""); fprintf(F, "graph: { title: \"");
PRINT_NODEID(block); PRINT_NODEID(block);
fprintf(F, "\" label: \""); fprintf(F, "\" label: \"");
fprintf (F, "%s ", get_op_name(get_irn_op(block))); dump_node_opcode(block);
#ifdef DEBUG_libfirm fprintf (F, " %ld", get_irn_node_nr(block));
fprintf (F, "%ld", get_irn_node_nr(block));
#else
fprintf (F, "%p", (void*) block);
#endif
if (exc_normal != get_Block_exc(block)) { if (exc_normal != get_Block_exc(block)) {
fprintf (F, " (%s)", exc_to_string (get_Block_exc(block))); fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
} }
...@@ -1475,34 +1477,36 @@ static void dump_cg_ir_block(ir_node * block, void * env) { ...@@ -1475,34 +1477,36 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
get_Block_matured(block) ? "yellow" : "red"); get_Block_matured(block) ? "yellow" : "red");
/* dump the blocks edges */ /* dump the blocks edges */
dump_ir_data_edges(block); dump_ir_data_edges(block, irgmap);
/* dump the nodes that go into the block */ /* dump the nodes that go into the block */
for (node = get_irn_link(block); node; node = get_irn_link(node)) { for (node = get_irn_link(block); node; node = get_irn_link(node)) {
dump_node(node, irgmap); dump_node(node, irgmap);
dump_ir_data_edges(node); dump_ir_data_edges(node, irgmap);
} }
/* Close the vcg information for the block */ /* 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) { static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
int i; 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))); (void*) irg, get_entity_name(get_irg_ent(irg)));
for (i = ARR_LEN(arr) - 1; i >= 0; --i) { for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
ir_node * node = arr[i]; ir_node * node = arr[i];
if (is_Block(node)) { 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. */ be found in Block->link. */
dump_cg_ir_block(node, irgmap); dump_cg_ir_block(node, irgmap);
} else { } else {
/* Nodes that are not in a Block. */ /* Nodes that are not in a Block. */
dump_node(node, NULL); dump_node(node, NULL);
dump_ir_data_edges(node); dump_ir_data_edges(node, NULL);
} }
} }
/* Close the vcg information for the irg */ /* Close the vcg information for the irg */
...@@ -1604,12 +1608,12 @@ void dump_cg_graph(ir_graph * irg) { ...@@ -1604,12 +1608,12 @@ void dump_cg_graph(ir_graph * irg) {
for (i = ARR_LEN(arr) - 1; i >= 0; --i) { for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
ir_node * node = arr[i]; ir_node * node = arr[i];
dump_node(node, map2); dump_node(node, map2);
dump_ir_data_edges(node); dump_ir_data_edges(node, NULL);
if (is_Block(node)) { if (is_Block(node)) {
for (node = get_irn_link(node); node; node = get_irn_link(node)) { for (node = get_irn_link(node); node; node = get_irn_link(node)) {
dump_node(node, map2); dump_node(node, map2);
dump_ir_block_edge(node); dump_ir_block_edge(node);
dump_ir_data_edges(node); dump_ir_data_edges(node, NULL);
} }
} }
} }
......
...@@ -529,6 +529,8 @@ copy_node_inline (ir_node *n, void *env) { ...@@ -529,6 +529,8 @@ copy_node_inline (ir_node *n, void *env) {
} }
} }
#include "irdump.h"
void inline_method(ir_node *call, ir_graph *called_graph) { void inline_method(ir_node *call, ir_graph *called_graph) {
ir_node *pre_call; ir_node *pre_call;
ir_node *post_call, *post_bl; ir_node *post_call, *post_bl;
...@@ -775,8 +777,10 @@ void inline_method(ir_node *call, ir_graph *called_graph) { ...@@ -775,8 +777,10 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
cf_op = get_Block_cfgpred(end_bl, i); cf_op = get_Block_cfgpred(end_bl, i);
if (get_irn_op(cf_op) == op_Proj) { if (get_irn_op(cf_op) == op_Proj) {
cf_op = get_Proj_pred(cf_op); cf_op = get_Proj_pred(cf_op);
if (get_irn_op(cf_op) == op_Tuple) { if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
cf_op = get_Tuple_pred(cf_op, 1); // 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); assert(get_irn_op(cf_op) == op_Jmp);
break; break;
} }
...@@ -1182,7 +1186,9 @@ static void merge_blocks(ir_node *n, void *env) { ...@@ -1182,7 +1186,9 @@ static void merge_blocks(ir_node *n, void *env) {
while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) { while (irn_not_visited(b) && (!is_Bad(new)) && (new != b)) {
/* We would have to run gigo if new is bad, so we /* We would have to run gigo if new is bad, so we
promote it directly below. */ 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")); ("strange flag setting"));
exchange (b, new); exchange (b, new);
b = new; b = new;
...@@ -1491,10 +1497,14 @@ static void walk_critical_cf_edges(ir_node *n, void *env) { ...@@ -1491,10 +1497,14 @@ static void walk_critical_cf_edges(ir_node *n, void *env) {
(get_irn_arity(n) > 1)) { (get_irn_arity(n) > 1)) {
arity = get_irn_arity(n); 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++) { for (i=0; i<arity; i++) {
pre = get_irn_n(n, i); pre = get_irn_n(n, i);
/* Predecessor has multiple sucessors. Insert new flow edge */ /* 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))) { op_Raise != get_irn_op(skip_Proj(pre))) {
/* set predecessor array for new block */ /* set predecessor array for new block */
......
...@@ -384,7 +384,7 @@ get_irn_node_nr(const ir_node *node) { ...@@ -384,7 +384,7 @@ get_irn_node_nr(const ir_node *node) {
#ifdef DEBUG_libfirm #ifdef DEBUG_libfirm
return node->node_nr; return node->node_nr;
#else #else
return 0; return (long)&node;
#endif #endif
} }
......
...@@ -150,7 +150,8 @@ INLINE void set_irn_link (ir_node *node, void *link); ...@@ -150,7 +150,8 @@ INLINE void set_irn_link (ir_node *node, void *link);
INLINE void *get_irn_link (const ir_node *node); INLINE void *get_irn_link (const ir_node *node);
/** Outputs a unique number for this node if libfirm is compiled for /** 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); INLINE long get_irn_node_nr(const ir_node *node);
/** Returns the ir_graph this node belongs to. Only valid for /** Returns the ir_graph this node belongs to. Only valid for
......
...@@ -263,23 +263,14 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) ...@@ -263,23 +263,14 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg)
// End block may only have Return, Raise or fragile ops as preds. // End block may only have Return, Raise or fragile ops as preds.
if (n == get_irg_end_block(irg)) if (n == get_irg_end_block(irg))
for (i = 0; i < get_Block_n_cfgpreds(n); ++i) { 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)); ir_node *pred = skip_Proj(get_Block_cfgpred(n, i));
if ((get_irn_op(pred) == op_Return) || if (is_Proj(pred) || get_irn_op(pred) == op_Tuple)
is_Bad(pred) || break; // We can not test properly. How many tuples are there?
(get_irn_op(pred) == op_Raise) ||
is_fragile_op(pred) )
{ }
else {
DDMG(irg); printf(" pred %d, ", i); DDMN(n); DDMN(pred);
}
ASSERT_AND_RET(((get_irn_op(pred) == op_Return) || ASSERT_AND_RET(((get_irn_op(pred) == op_Return) ||
is_Bad(pred) || is_Bad(pred) ||
(get_irn_op(pred) == op_Raise) || (get_irn_op(pred) == op_Raise) ||
is_fragile_op(pred) ), is_fragile_op(pred) ),
"End Block node", 0); "End Block node", 0);
#endif
} }
break; break;
......
Supports Markdown
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