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) {
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
* einfgen. Die Steuer- und Datenflussabhngigkeiten von den aufgerufenen
......@@ -568,12 +594,31 @@ static void construct_call(ir_node * call) {
/* Die interprozeduralen Steuerflussvorgnger 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:
......@@ -594,9 +639,24 @@ static void construct_call(ir_node * call) {
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 Vorgnger in den Start-Blcken der aufgerufenen Methoden
......
......@@ -63,7 +63,7 @@
#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"
......@@ -352,10 +352,12 @@ static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
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;
......@@ -517,7 +519,7 @@ static void print_edge_vcgattr(ir_node *from, int to) {
/* 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))
......@@ -534,9 +536,10 @@ dump_ir_data_edges(ir_node *n) {
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, "\"");
......@@ -1074,7 +1077,7 @@ static void
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
......@@ -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)) {
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;
......@@ -1137,7 +1140,7 @@ dump_ir_block (ir_node *block, void *env) {
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);
......@@ -1153,14 +1156,14 @@ static void
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;
}
}
......@@ -1426,6 +1429,7 @@ static void clear_link(ir_node * node, void * env) {
set_irn_link(node, NULL);
}
static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
assert(node); assert(map);
if (is_Block(node)
......@@ -1458,15 +1462,13 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
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)));
}
......@@ -1475,34 +1477,36 @@ static void dump_cg_ir_block(ir_node * block, void * env) {
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 */
......@@ -1604,12 +1608,12 @@ void dump_cg_graph(ir_graph * 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);
}
}
}
......
......@@ -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) {
ir_node *pre_call;
ir_node *post_call, *post_bl;
......@@ -775,8 +777,10 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
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;
}
......@@ -1182,7 +1186,9 @@ static void merge_blocks(ir_node *n, void *env) {
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;
......@@ -1491,10 +1497,14 @@ static void walk_critical_cf_edges(ir_node *n, void *env) {
(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 */
......
......@@ -384,7 +384,7 @@ get_irn_node_nr(const ir_node *node) {
#ifdef DEBUG_libfirm
return node->node_nr;
#else
return 0;
return (long)&node;
#endif
}
......
......@@ -150,7 +150,8 @@ INLINE void set_irn_link (ir_node *node, void *link);
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
......
......@@ -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.
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;
......
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