From: Götz Lindenmaier Date: Thu, 22 Jul 2004 12:54:32 +0000 (+0000) Subject: dumper and datastructure for callgraph X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=599e9fd21149c903f688d4a3b1eec71dc079f8a0;p=libfirm dumper and datastructure for callgraph dumper contains dumper for callgraph looptree, but commented out as uses is questionable [r3552] --- diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index 337c091a6..3a2fcdb85 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -15,32 +15,34 @@ # include #endif -# include -# include -# include - -# include "irnode_t.h" -# include "irgraph_t.h" -# include "entity_t.h" -# include "irop_t.h" -# include "firm_common_t.h" - -# include "irdump.h" - -# include "irgwalk.h" -# include "typewalk.h" -# include "irprog.h" -# include "tv_t.h" -# include "type_or_entity.h" -# include "irouts.h" -# include "irdom.h" -# include "irloop.h" -# include "irvrfy.h" - -# include "panic.h" -# include "array.h" -# include "pmap.h" -# include "eset.h" +#include +#include +#include + +#include "irnode_t.h" +#include "irgraph_t.h" +#include "entity_t.h" +#include "irop_t.h" +#include "firm_common_t.h" + +#include "irdump.h" + +#include "irgwalk.h" +#include "typewalk.h" +#include "irprog.h" +#include "tv_t.h" +#include "type_or_entity.h" +#include "irouts.h" +#include "irdom.h" +#include "irloop.h" +#include "callgraph.h" + +#include "irvrfy.h" + +#include "panic.h" +#include "array.h" +#include "pmap.h" +#include "eset.h" #if DO_HEAPANALYSIS void dump_chi_term(FILE *FL, ir_node *n); @@ -71,24 +73,25 @@ SeqNo get_Block_seqno(ir_node *n); #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted" /* Attributes of edges in type/entity graphs. */ -#define TYPE_METH_NODE_ATTR "color: lightyellow" -#define TYPE_CLASS_NODE_ATTR "color: green" +#define TYPE_METH_NODE_ATTR "color: lightyellow" +#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_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" -#define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red" -#define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue" -#define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green" -#define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green" -#define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green" +#define ENTITY_NODE_ATTR "color: yellow" +#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" +#define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red" +#define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue" +#define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green" +#define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green" +#define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green" #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red" -#define ENT_VALUE_EDGE_ATTR "label: \"value %d\"" -#define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" " -#define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue" -#define ENUM_ITEM_NODE_ATTR "color: green" +#define ENT_VALUE_EDGE_ATTR "label: \"value %d\"" +#define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" " +#define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue" +#define ENUM_ITEM_NODE_ATTR "color: green" +#define CALLGRAPH_EDGE_ATTR "calls" #if DEBUG_libfirm && NODEID_AS_LABEL #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X)) @@ -149,12 +152,16 @@ static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, .. va_end(ap); } -static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...) +static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E); + if (backedge) + fprintf(F, "backedge: { sourcename: \""); + else + fprintf(F, "edge: { sourcename: \""); + PRINT_ENTID(E); fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\""); vfprintf(F, fmt, ap); fprintf(F, "}\n"); @@ -1382,7 +1389,7 @@ dump_type_info (type_or_ent *tore, void *env) { print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR); if(is_class_type(get_entity_owner(ent))) { for(i = 0; i < get_entity_n_overwrites(ent); i++){ - print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR); + print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR); } } /* attached subgraphs */ @@ -1401,7 +1408,7 @@ dump_type_info (type_or_ent *tore, void *env) { if (value) { print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i); dump_const_expression(value); - print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i); + print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i); /* fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" " ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent), @@ -1511,7 +1518,7 @@ dump_class_hierarchy_node (type_or_ent *tore, void *env) { print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR); for(i = 0; i < get_entity_n_overwrites(ent); i++) { - print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR); + print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, 0, ENT_OVERWRITES_EDGE_ATTR); } } } break; /* case k_entity */ @@ -1938,7 +1945,7 @@ dump_cfg (ir_graph *irg) int ddif = dump_dominator_information_flag; int ipv = interprocedural_view; - if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return; + if(strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0) return; current_ir_graph = irg; @@ -1965,6 +1972,33 @@ dump_cfg (ir_graph *irg) +void dump_callgraph(char *filesuffix) { + int i, n_irgs = get_irp_n_irgs(); + + vcg_open_name ("Callgraph", filesuffix); + dump_vcg_header("Callgraph", NULL); + + for (i = 0; i < n_irgs; ++i) { + ir_graph *irg = get_irp_irg(i); + entity *ent = get_irg_ent(irg); + int j, n_callees = get_irg_n_callees(irg); + + dump_entity_node(ent); + for (j = 0; j < n_callees; ++j) { + entity *c = get_irg_entity(get_irg_callee(irg, j)); + int be = is_irg_callee_backedge(irg, j); + char *attr; + attr = (be) ? + "label:\"recursion\" color:red" : + "label:\"calls\""; + print_ent_ent_edge(F, ent, c, be, attr); + } + } + + vcg_close(); +} + + /* Dump all irgs in interprocedural view to a single file. */ void dump_all_cg_block_graph(void) { int i; @@ -2097,7 +2131,7 @@ void dump_loops_standalone (ir_loop *loop) { dump_loop_son_edge(loop, son_number++); dump_loops_standalone(son); } - else { + else if (get_kind(son) == k_ir_node) { /* We are a loop node -> Collect firm nodes */ ir_node *n = le.node; @@ -2121,6 +2155,27 @@ void dump_loops_standalone (ir_loop *loop) { bad |= dump_node_nodeattr(n); fprintf (F, " %ld", get_irn_node_nr(n)); } +#if CALLGRAPH_LOOP_TREE + else { + assert(get_kind(son) == k_ir_graph); + /* We are a loop node -> Collect firm graphs */ + + ir_graph *n = (ir_graph *)le.node; + + if (!loop_node_started) { + /* Start a new node which contains all firm nodes of the current loop */ + fprintf (F, "node: { title: \""); + PRINT_LOOPID(loop); + fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i); + loop_node_started = 1; + first = i; + } + else + fprintf(F, "\n"); + + fprintf (F, " %s", get_irg_dump_name(n)); + } +#endif } if (loop_node_started) { @@ -2156,6 +2211,16 @@ void dump_loop_tree(ir_graph *irg, char *suffix) current_ir_graph = rem; } +#if CALLGRAPH_LOOP_TREE +/* works, but the tree is meaningless. */ +void dump_callgraph_loop_tree(ir_loop *l, char *suffix) { + vcg_open_name("callgraph_looptree", suffix); + dump_vcg_header("callgraph_looptree", "top_to_bottom"); + dump_loops_standalone(l); + vcg_close(); +} +#endif + /*******************************************************************************/ /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */ diff --git a/ir/ir/irdump.h b/ir/ir/irdump.h index 24ccd057d..b094b2fcc 100644 --- a/ir/ir/irdump.h +++ b/ir/ir/irdump.h @@ -170,6 +170,13 @@ void dump_all_ir_graphs (dump_graph_func *dump_graph); */ void dump_cfg (ir_graph *irg); + +/** Dump the call graph. + * + * Dumps the callgraph to a file "callgraph"".vcg". + */ +void dump_callgraph(char *filesuffix); + /** * Dumps all the type information needed for Calls, Sels, ... in this graph. * Does not dump the graph! diff --git a/ir/ir/irgraph.h b/ir/ir/irgraph.h index 835c7fd9d..2250edc1a 100644 --- a/ir/ir/irgraph.h +++ b/ir/ir/irgraph.h @@ -204,13 +204,22 @@ long get_irg_graph_nr(ir_graph *irg); information associated with the graph. Optimizations invalidate these states. */ -/** state: phase values: phase_building, phase_high, phase_low. - The irg is in phase_building during construction of the irgraph. It is in - phase_high after construction. All nodes are allowed. To get the irgraph - into phase_low all Sel nodes must be removed and replaced by explicit - address computations. SymConst size and typetag nodes must be removed (@@@ - really?). Initialization of memory allocated by Alloc must be explicit. - @@@ More conditions? */ +/** The states of an ir graph. + * + * state phase values: phase_building, phase_high, phase_low. + * + * The graph is in phase_building during construction of the irgraph. + * The construction is finished by a call to finalize_cons(). + * + * Finalize_cons() sets the state to phase_high. All Firm nodes are + * allowed. + * + * To get the irgraph into phase_low all Sel nodes must be removed and + * replaced by explicit address computations. SymConst size and + * typetag nodes must be removed (@@@ really?). Initialization of + * memory allocated by Alloc must be explicit. @@@ More conditions? + * + */ typedef enum { phase_building, phase_high, @@ -284,7 +293,7 @@ void set_irg_loopinfo_inconsistent(ir_graph *irg); /** state: callee_information_state * Call nodes contain a list of possible callees. This list must be - * computed by an anlyses. */ + * computed by an anlysis. */ typedef enum { irg_callee_info_none, irg_callee_info_consistent, diff --git a/ir/ir/irgraph_t.h b/ir/ir/irgraph_t.h index 8040fdf84..fb79b0e69 100644 --- a/ir/ir/irgraph_t.h +++ b/ir/ir/irgraph_t.h @@ -63,10 +63,10 @@ struct ir_graph { op_pinned pinned; /**< Flag for status of nodes */ irg_outs_state outs_state; /**< Out edges. */ irg_dom_state dom_state; /**< Dominator information */ - irg_typeinfo_state typeinfo_state; /**< Validity of type information */ + irg_typeinfo_state typeinfo_state; /**< Validity of type information */ irg_callee_info_state callee_info_state; /**< Validity of callee information */ irg_inline_property inline_property; /**< How to handle inlineing. */ - irg_loopinfo_state loopinfo_state; /**< state of loop information */ + irg_loopinfo_state loopinfo_state; /**< state of loop information */ /* -- Fields for construction -- */ #if USE_EXPLICIT_PHI_IN_STACK @@ -81,12 +81,17 @@ struct ir_graph { struct ir_node **outs; /**< Space for the out arrays. */ #ifdef DEBUG_libfirm - int n_outs; /* < Size wasted for outs */ + int n_outs; /* < Size wasted for outs */ #endif /* defined DEBUG_libfirm */ struct ir_loop *loop; /**< The outermost loop */ void *link; /**< A void* field to link any information to the node. */ + ir_graph **callers; /**< For callgraph analyses. */ + int *caller_isbe; /**< For callgraph analyses: set if backedge. */ + ir_graph **callees; /**< For callgraph analyses. */ + int *callee_isbe; /**< For callgraph analyses: set if backedge. */ + /* -- Fields for Walking the graph -- */ unsigned long visited; /**< this flag is an identifier for ir walk. it will be incremented