From 78a73b3b45c6af2b7bb66ca7f465de992acdc35c Mon Sep 17 00:00:00 2001 From: =?utf8?q?G=C3=B6tz=20Lindenmaier?= Date: Mon, 29 Sep 2003 15:17:55 +0000 Subject: [PATCH] fixed various errors with exceptions + inlineing, dumping and interproc representation added new asserstio in vrfy [r1891] --- ir/ir/ircgcons.c | 76 +++++++++++++++++++++++++++++++++++++++++++----- ir/ir/irdump.c | 52 ++++++++++++++++++--------------- ir/ir/irgopt.c | 18 +++++++++--- ir/ir/irnode.c | 2 +- ir/ir/irnode.h | 3 +- ir/ir/irvrfy.c | 13 ++------- 6 files changed, 115 insertions(+), 49 deletions(-) diff --git a/ir/ir/ircgcons.c b/ir/ir/ircgcons.c index be6d0f892..929e5e28f 100644 --- a/ir/ir/ircgcons.c +++ b/ir/ir/ircgcons.c @@ -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 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 @@ -568,12 +594,31 @@ static void construct_call(ir_node * call) { /* 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: @@ -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 Vorgänger in den Start-Blöcken der aufgerufenen Methoden diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index 247760256..963a5bd92 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -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); } } } diff --git a/ir/ir/irgopt.c b/ir/ir/irgopt.c index 2275d0344..4cb15d2da 100644 --- a/ir/ir/irgopt.c +++ b/ir/ir/irgopt.c @@ -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; inode_nr; #else - return 0; + return (long)&node; #endif } diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index 7f8b73160..6e21f7728 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -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 diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c index 11ff7a2cc..0f852aa9c 100644 --- a/ir/ir/irvrfy.c +++ b/ir/ir/irvrfy.c @@ -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; -- 2.20.1