5 * File name: ir/ana/ecg.c
6 * Purpose: Extended Call Graph
11 * Copyright: (c) 1999-2004 Universität Karlsruhe
12 * Licence: This file is protected by the GPL - GNU GENERAL PUBLIC LICENSE.
20 Erweiterter Aufrufgraph.
25 /* #include "eset.h" */
35 # endif /* not defined TRUE */
37 # define BUF_SIZE 1024
40 # include "typalise.h"
43 # define HERE(msg) fprintf (stdout, "%s:%i %s\n", __FUNCTION__, __LINE__, msg)
48 /* static int verbose = 0; */
49 static int do_typalise = 0;
55 /* Ids for the ctxs */
56 static int ctx_id = 0;
57 ctx_info_t *main_ctx = NULL;
59 /* mapping from method graphs (callR) to method graphs (lset_ts of callEds) */
60 /* static pmap *calls; */
61 static pmap *graph_infos;
63 /* linked list of all graph_infos: */
64 static graph_info_t *graph_infos_list = NULL;
66 /* Counters for ecg_ecg and friends */
67 static long _graphs = 0;
68 static long _calls = 0;
69 static long _allocs = 0;
71 static int _depth = 0;
72 static int _max_depth = 0;
74 static int _max_callEds = 0;
75 static entity* _max_callEds_callR = NULL;
78 void set_main_ctx (ctx_info_t*);
80 /* ====================
82 ==================== */
83 static void append_alloc (graph_info_t *ginfo, ir_node *alloc, type *tp)
85 alloc_info_t *ainfo = (alloc_info_t*) xmalloc (sizeof (alloc_info_t));
87 ainfo->graph = ginfo->graph;
91 ainfo->prev = ginfo->allocs;
92 ginfo->allocs = ainfo;
96 /* ====================
98 ==================== */
100 Append the given callEd to the given callEd info.
102 static callEd_info_t *append_callEd_info (callEd_info_t *ced, ir_graph *callEd)
104 callEd_info_t *nced = (callEd_info_t*) xmalloc (sizeof (sizeof (callEd_info_t)));
106 nced->callEd = callEd;
113 Append all callEd methods of the given (call) node to the given graph_info.
115 static void append_calls (graph_info_t *info, ir_node *call, lset_t *callEds)
117 call_info_t *cinfo = (call_info_t*) xmalloc (sizeof (call_info_t));
121 cinfo->prev = info->calls;
123 cinfo->callEds = NULL;
126 ir_graph *callEd = lset_first (callEds);
128 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
130 callEd = lset_next (callEds);
135 Append the (single) callEd to the given (call) node of the given graph_info.
137 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
139 call_info_t *cinfo = (call_info_t*) xmalloc (sizeof (call_info_t));
142 cinfo->prev = info->calls;
145 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
149 Given a method, find the firm graph that implements that method.
150 Return NULL for abstract and native methods.
152 static ir_graph *_get_implementing_graph (entity *method)
154 ir_graph *graph = NULL;
156 /* What's up with the fenced out stuff in rta? */
157 if (peculiarity_existent == get_entity_peculiarity (method)) {
158 if (visibility_external_allocated == get_entity_visibility (method)) {
159 /* Todo: native implementation */
163 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
164 assert (graph && "no graph");
168 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
169 /* abstract --- can't find an implementation */
170 graph = get_entity_irg (method);
171 assert (!graph && "graph in abstract method");
174 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
175 (peculiarity_inherited == get_entity_peculiarity (method))) {
178 int n_over = get_entity_n_overwrites (method);
182 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
183 entity *over = get_entity_overwrites (method, i);
185 graph = _get_implementing_graph (over);
188 assert (0 && "invalid peculiarity");
196 Collect all graphs of 'method' in the given set.
198 static void _collect_implementing_graphs (entity *method, lset_t *set)
200 /* search DOWN-wards in clazz hierarchy */
202 int n_over = get_entity_n_overwrittenby (method);
203 ir_graph *graph = get_entity_irg (method);
206 graph = _get_implementing_graph (method);
210 lset_insert (set, graph);
213 for (i = 0; i < n_over; i ++) {
214 entity *over = get_entity_overwrittenby (method, i);
216 _collect_implementing_graphs (over, set);
222 Collect all graphs that could possibly be executed when 'method' is called.
224 static lset_t *get_implementing_graphs (entity *method, ir_node *select)
226 lset_t *set = lset_create ();
228 ir_graph *impl = _get_implementing_graph (method);
231 lset_insert (set, impl);
233 /* actually, abstract OR native */
237 _collect_implementing_graphs (method, set);
239 if (lset_empty (set)) {
240 /* then it's a method which is only implemented natively, and we
241 don' bother to analyse anything */
245 /* void *tmp = lset_first (set); */
246 int n_graphs = lset_n_entries (set);
248 /* typalise select_in */
250 ir_node *select_in = get_Sel_ptr (select);
251 typalise_t *ta = typalise (select_in);
252 assert (ta && "typalise failed (go figure)");
254 /* const char *res = ta_name (ta); */
256 /* fprintf (stdout, "typalyse res = %s\n", res); */
259 set = filter_for_ta (set, ta);
261 int n_filtered_graphs = lset_n_entries (set);
264 fprintf (stdout, "%s: %02d %02d\n",
268 n_graphs - n_filtered_graphs);
270 n_graphs = n_filtered_graphs;
274 if (n_graphs > _max_callEds) {
275 _max_callEds = n_graphs;
276 _max_callEds_callR = method;
280 if (visibility_external_allocated != get_entity_visibility (method)) {
282 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
283 assert (n_graphs && "no graphs for method");
291 Action for the graph.
293 static void ecg_calls_act (ir_node *node, void *env)
295 opcode op = get_irn_opcode (node);
296 graph_info_t *graph_info = (graph_info_t*) env;
298 if (iro_Call == op) { /* CALL */
300 ir_node *ptr = get_Call_ptr (node);
303 if (iro_Sel == get_irn_opcode (ptr)) {
304 ent = get_Sel_entity (ptr);
305 lset_t *graphs = get_implementing_graphs (ent, ptr);
307 append_calls (graph_info, node, graphs);
308 } else if (iro_SymConst == get_irn_opcode (ptr)) {
309 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
310 ent = get_SymConst_entity (ptr);
311 ir_graph *graph = get_entity_irg (ent);
314 append_call (graph_info, node, graph);
316 /* it's an externally allocated thingy */
318 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
319 /* If this SymConst refers to a method the method is external_visible
320 and therefore must be considered live anyways. */
321 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
322 assert (ent && "couldn't determine entity of call to symConst");
325 /* other symconst. */
326 assert (0 && "This SymConst can not be an address for a method call.");
329 /* STRANGE, no less ... */
332 assert (0 && "Unexpected address expression");
334 } else if (iro_Alloc == op) {
335 type *tp = get_Alloc_type (node);
336 /* const char *name = get_type_name (tp); */
338 append_alloc (graph_info, node, tp);
340 /* fprintf (stdout, "NEW \"%s\"\n", name); */
345 Collect called graphs for the given graph.
347 static void ecg_fill_graph_calls (ir_graph *graph)
349 graph_info_t *ginfo = (graph_info_t*) xmalloc (sizeof (graph_info_t));
351 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
352 assert (ginfo != graph_infos_list);
354 ginfo->graph = graph;
361 /* link up into global list */
362 ginfo->prev = graph_infos_list;
363 graph_infos_list = ginfo;
365 assert (ginfo != ginfo->prev);
367 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
369 pmap_insert (graph_infos, graph, ginfo);
373 For each graph, collect called graphs, and enter them into calls.
375 static void ecg_fill_calls (void)
379 for (i = 0; i < get_irp_n_irgs (); i++) {
380 ir_graph *graph = get_irp_irg (i);
382 ecg_fill_graph_calls (graph);
387 Allocate a new ctx for the given graph and the given enclosing ctx.
389 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
391 ctx_info_t *res = xmalloc (sizeof (ctx_info_t));
403 Fill in the ctxs parts of the graph_infos
405 static void ecg_fill_ctxs_count (ir_graph *graph)
407 graph_info_t *ginfo = ecg_get_info (graph);
409 /* count how many ctxs we have per graph */
410 if (0 == ginfo->ecg_seen) {
413 call_info_t *cinfo = ginfo->calls;
415 while (NULL != cinfo) {
416 callEd_info_t *ced = cinfo->callEds;
418 while (NULL != ced) {
419 ir_graph *callEd_graph = ced->callEd;
421 /* first step: we have a new ctx */
422 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
423 callEd_info->n_ctxs ++;
425 /* Calling graph -> callEd_graph */
426 ecg_fill_ctxs_count (callEd_graph);
429 } /* end forall callEds (call) */
432 } /* end forall (calls(graph)) */
438 static void ecg_fill_ctxs_alloc (void)
440 /* allocate the memory needed for the ctxts: */
441 graph_info_t *ginfo = graph_infos_list;
443 while (NULL != ginfo) {
444 ginfo->ctxs = (ctx_info_t **) xmalloc (ginfo->n_ctxs * sizeof (ctx_info_t*));
447 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
448 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
452 assert (ginfo != ginfo->prev);
458 Fill in the ctxs parts of the graph_infos
460 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
462 graph_info_t *ginfo = ecg_get_info (graph);
464 /* enter a new ctx for all callEds along the call edges of this graph */
465 if (0 == ginfo->ecg_seen) {
467 call_info_t *cinfo = ginfo->calls;
469 while (NULL != cinfo) {
470 callEd_info_t *ced = cinfo->callEds;
472 while (NULL != ced) {
473 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
475 ir_graph *callEd_graph = ced->callEd;
477 /* write the ctx of this call into the callEd graph */
478 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
480 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
481 callEd_info->n_ctxs ++;
483 /* Calling graph -> callEd_graph */
484 ecg_fill_ctxs_write (callEd_graph, ctx);
487 } /* end forall callEds (call) */
490 } /* end forall (calls(graph)) */
497 Fill in the ctxs parts of the graph_infos
499 static void ecg_fill_ctxs (void)
501 ecg_fill_ctxs_count (get_irp_main_irg ());
502 ecg_fill_ctxs_alloc ();
504 ctx_info_t *main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
505 ir_graph *main_irg = get_irp_main_irg ();
507 set_main_ctx (main_ctx);
509 /* Grrr, have to add this ctx manually to main.ginfo ... */
510 graph_info_t *ginfo = ecg_get_info (main_irg);
512 ginfo->ctxs = (ctx_info_t **) xmalloc (1 * sizeof (ctx_info_t*));
513 ginfo->ctxs [0] = main_ctx;
515 ecg_fill_ctxs_write (main_irg, main_ctx);
518 /* ====================
520 ==================== */
522 Nicely print a ctx_info_t to the given output stream
524 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
526 entity *ent = get_irg_ent (ctx->graph);
527 ir_node *call = ctx->call;
528 const char *ent_name = (char*) get_entity_name (ent);
529 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
531 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
532 ctx->id, own_name, ent_name,
533 get_op_name (get_irn_op (call)),
534 get_irn_node_nr (call));
536 if (NULL != ctx->enc) {
537 fprintf (stream, "->%i", ctx->enc->id);
540 fprintf (stream, "\n");
544 Get a ctx of the given graph info
546 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
548 assert (ginfo->n_ctxs > ctx_idx);
550 return (ginfo->ctxs [ctx_idx]);
554 Get the pseudo-ctx of 'main'
556 ctx_info_t *get_main_ctx ()
562 Set the pseudo-ctx of 'main'
564 void set_main_ctx (ctx_info_t *ctx)
570 /* ====================
572 ==================== */
574 /* ====================
576 ==================== */
578 Iterate over all graphs
580 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
582 graph_info_t *ginfo = graph_infos_list;
584 while (NULL != ginfo) {
585 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
587 if (0 != ginfo->n_ctxs) {
597 Iterate of all allocs of a given graph info
599 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
601 alloc_info_t *ainfo = ginfo->allocs;
603 while (NULL != ainfo) {
612 Iterate over all calls of the given graph info
614 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
616 call_info_t *cinfo = ginfo->calls;
618 while (NULL != cinfo) {
627 Iterate over all callEds of the given call info
629 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
631 callEd_info_t *ced = cinfo->callEds;
633 while (NULL != ced) {
642 get the call infos for the given graph
644 graph_info_t *ecg_get_info (ir_graph *graph)
646 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
648 assert (ginfo && "no info for graph");
654 Get the Alloc Infos for the given graph
656 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
658 graph_info_t *ginfo = ecg_get_info (graph);
660 return (ginfo->allocs);
664 Get the Call Info for the given call
666 callEd_info_t *ecg_get_callEd_info (ir_node *call)
668 ir_graph *graph = get_irn_irg (call);
669 graph_info_t *ginfo = ecg_get_info (graph);
671 call_info_t *call_info = ginfo->calls;
673 while (NULL != call_info) {
674 if (call == call_info->call) {
675 return (call_info->callEds);
678 call_info = call_info->prev;
686 Dump the given graph and it's calls and it's calls callEds to the given file.
688 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
690 const char *name = get_irg_entity (graph) ?
691 get_entity_name (get_irg_entity (graph)) : "noEntity";
693 (get_entity_stickyness
694 (get_irg_entity (graph)) == stickyness_sticky) ?
695 "red" : "lightyellow";
697 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
698 graph_info_t *ginfo = ecg_get_info (graph);
700 if (0 != ginfo->ecg_seen) {
701 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
702 name, (int) ginfo->ecg_seen);
704 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
707 return (ginfo->ecg_seen);
710 assert (0L <= _graphs);
712 const int graph_no = _graphs ++;
713 ginfo->ecg_seen = graph_no;
715 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
716 get_type_name (get_entity_owner (get_irg_entity (graph))),
718 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
720 get_type_name (get_entity_owner (get_irg_entity (graph))),
726 if (visibility_external_allocated ==
727 get_entity_visibility (get_irg_entity (graph))) {
728 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
733 call_info_t *cinfo = ginfo->calls;
734 while (NULL != cinfo) {
735 ir_node *call = cinfo->call;
736 callEd_info_t *ced = cinfo->callEds;
737 const int call_no = _calls ++;
738 const char *call_color = (NULL == ced->prev) ? "lightblue" : "blue3";
740 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
741 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
742 call_no, get_irn_node_nr (call), call_color);
743 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
745 while (NULL != ced) {
746 ir_graph *callEd_graph = ced->callEd;
747 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
748 const char *callEd_name = get_irg_entity (callEd_graph) ?
749 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
750 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
751 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
753 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
756 /* Check for recursive calls */
757 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
758 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
759 call_no, callEd_no, callEd_color, direction);
764 } /* done all calEds (call) */
767 } /* done all calls (graph) */
770 alloc_info_t *ainfo = ecg_get_alloc_info (graph);
772 fprintf (dot, "\t/* now the allocs */\n");
774 fprintf (dot, "\t/* no allocs */\n");
777 while (NULL != ainfo) {
778 ir_node *alloc = ainfo->alloc;
779 const char *name = get_type_name (ainfo->tp);
780 const char *color = "red1";
783 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
784 (int) alloc, graph_no, name, color);
786 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
787 graph_no, (int) alloc, graph_no);
792 if (0 == ginfo->allocs_seen) {
793 ginfo->allocs_seen = 1;
796 /* write table of ctxs */
798 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
801 const int max_ctxs = 30;
802 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
804 assert (ginfo->ctxs && "no ctx");
805 for (i = 0; i < n_ctxs; i ++) {
806 ctx_info_t *ctx_info = ginfo->ctxs [i];
808 if (NULL != ctx_info->enc) {
809 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
814 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
823 if (0 < ginfo->n_ctxs - max_ctxs) {
824 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
827 fprintf (dot, "\", color=\"green3\"];\n");
830 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
834 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
843 Count how many nodes the ECG will have
845 static char spaces [BUF_SIZE];
847 static void ecg_ecg_count (ir_graph *graph)
849 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
851 if (0 != ginfo->ecg_seen) {
856 if (_depth > _max_depth) {
860 fprintf (stdout, "_max_depth = %i\n", _max_depth);
861 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
865 assert (0L <= _graphs);
868 if (0 == (_graphs % 1000000)) {
869 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
870 fprintf (stdout, "_depth = %i\n", _depth);
874 const int graph_no = _graphs ++;
875 ginfo->ecg_seen = graph_no;
877 fprintf (stdout, "%sMethod \"%s.%s\"\n",
878 spaces + BUF_SIZE - _depth,
879 get_type_name (get_entity_owner (get_irg_entity (graph))),
880 get_entity_name (get_irg_entity (graph)));
882 call_info_t *cinfo = ginfo->calls;
883 while (NULL != cinfo) {
885 callEd_info_t *ced = cinfo->callEds;
887 fprintf (stdout, "%sCall \"0x%08x\"\n",
888 spaces + BUF_SIZE - _depth,
891 while (NULL != ced) {
892 ir_graph *callEd_graph = ced->callEd;
894 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
895 spaces + BUF_SIZE - _depth,
896 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
897 get_entity_name (get_irg_entity (callEd_graph)));
899 ecg_ecg_count (callEd_graph);
902 } /* done all calEds (call) */
904 } /* done all calls (graph) */
910 /* ====================
912 ==================== */
915 Initialise our data structures.
917 void ecg_init (int typalise)
919 do_typalise = typalise;
921 graph_infos = pmap_create ();
937 for (i = 0; i < get_irp_n_irgs (); i++) {
938 ir_graph *graph = get_irp_irg (i);
940 graph_info_t *info = pmap_get (graph_infos, graph);
941 call_info_t *cinfo = info->calls;
943 while (NULL != cinfo) {
946 callEd_info_t *ced = cinfo->callEds;
948 while (NULL != ced) {
949 callEd_info_t *nced = ced->prev;
956 cinfo->callEds = NULL;
963 pmap_insert (graph_infos, graph, NULL);
967 pmap_destroy (graph_infos);
974 Show what we have found.
980 FILE *dot = fopen ("calls.dot", "w");
982 fprintf (dot, "digraph \"calls\" {\n");
983 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\"];\n");
984 fprintf (dot, "\tnode [shape = \"record\", style = \"filled\"];\n");
985 fprintf (dot, "\tedge [color = \"black\"];\n");
987 fprintf (dot, "\tsize = \"11, 7\";\n");
988 fprintf (dot, "\trotate = \"90\";\n");
989 fprintf (dot, "\tratio = \"fill\";\n");
992 for (i = 0; i < get_irp_n_irgs (); i++) {
993 ir_graph *graph = get_irp_irg (i);
994 graph_info_t *info = (graph_info_t*) pmap_get (graph_infos, graph);
996 const char *name = get_irg_entity (graph) ?
997 get_entity_name (get_irg_entity (graph)) : "noEntity";
999 const char *oname = get_type_name
1000 (get_entity_owner (get_irg_entity (graph)));
1003 (get_entity_stickyness
1004 (get_irg_entity (graph)) == stickyness_sticky) ?
1005 "red3" : "lightyellow";
1007 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1009 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1010 (int) graph, oname, name, color);
1011 fprintf (dot, "\n");
1013 call_info_t *cinfo = info->calls;
1015 fprintf (dot, "\t/* now the calls */\n");
1017 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1020 while (NULL != cinfo) {
1021 ir_node *call = cinfo->call;
1023 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1024 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\\l0x%08x\"];\n",
1025 (int) call, get_irn_node_nr (call), (int) call);
1026 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1027 (int) graph, (int) call);
1029 callEd_info_t *ced = cinfo->callEds;
1030 while (NULL != ced) {
1031 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1032 (int) call, (int) ced->callEd);
1035 fprintf (dot, "\n");
1037 cinfo = cinfo->prev;
1039 fprintf (dot, "\n");
1041 alloc_info_t *ainfo = info->allocs;
1043 fprintf (dot, "\t/* now the allocs */\n");
1045 fprintf (dot, "\t/* no allocs */\n");
1049 while (NULL != ainfo) {
1050 ir_node *alloc = ainfo->alloc;
1051 const char *name = get_type_name (ainfo->tp);
1052 const char *color = "green3";
1054 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1055 (int) alloc, name, color);
1056 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1057 (int) graph, (int) alloc);
1059 ainfo = ainfo->prev;
1062 fprintf (dot, "}\n");
1065 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1066 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1067 get_entity_name (_max_callEds_callR));
1073 Experimental: Print the ecg
1080 ir_graph *main_graph = get_irp_main_irg ();
1083 memset (spaces, '.', BUF_SIZE);
1084 spaces [BUF_SIZE-1] = '\0';
1086 ecg_ecg_count (main_graph);
1087 fprintf (stdout, "n_graphs: %i\n", _graphs);
1088 fprintf (stdout, "max_depth = %i\n", _max_depth);
1096 FILE *dot = fopen ("ecg.dot", "w");
1098 fprintf (dot, "digraph \"ecg\" {\n");
1099 fprintf (dot, "\tnode [shape = \"record\", style = \"filled\"];\n");
1100 fprintf (dot, "\tedge [color = \"black\"];\n");
1101 fprintf (dot, "\n");
1102 fprintf (dot, "\tsize = \"11, 7\";\n");
1103 fprintf (dot, "\trotate = \"90\";\n");
1104 fprintf (dot, "\tratio = \"fill\";\n");
1105 fprintf (dot, "\trankdir = \"LR\";\n");
1106 fprintf (dot, "\n");
1108 /* ir_graph *main_graph = get_irp_main_irg (); */
1109 ecg_ecg_graph (dot, main_graph);
1111 fprintf (dot, "\t/* Grand Total: */\n");
1112 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1113 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1114 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1115 fprintf (dot, "\t/* (sales tax not included) */\n");
1117 fprintf (dot, "}\n");
1126 Revision 1.8 2004/11/30 14:45:44 liekweg
1127 fix graph dumping, remove 'HERE's
1129 Revision 1.7 2004/11/26 16:01:56 liekweg
1130 debugging annotations
1132 Revision 1.6 2004/11/24 14:53:55 liekweg
1135 Revision 1.5 2004/11/20 21:20:29 liekweg
1136 Added iterator functions
1138 Revision 1.4 2004/11/18 16:36:37 liekweg
1139 Added unique ids for debugging, added access functions
1141 Revision 1.3 2004/11/04 14:54:44 liekweg
1144 Revision 1.2 2004/10/21 11:09:37 liekweg
1145 Moved memwalk stuf into irmemwalk
1146 Moved lset stuff into lset
1147 Moved typalise stuff into typalise
1149 Revision 1.1 2004/10/20 14:59:41 liekweg
1150 Added ana2, added ecg and pto
1152 Revision 1.6 2004/10/18 12:47:19 liekweg
1155 Revision 1.5 2004/10/14 11:31:28 liekweg
1158 Revision 1.4 2004/10/12 11:02:01 liekweg