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 (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));
122 cinfo->prev = info->calls;
124 cinfo->callEds = NULL;
127 callEd = lset_first (callEds);
129 while (NULL != callEd) {
130 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
131 callEd = lset_next(callEds);
137 Append the (single) callEd to the given (call) node of the given graph_info.
139 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
141 call_info_t *cinfo = (call_info_t*) xmalloc (sizeof (call_info_t));
144 cinfo->prev = info->calls;
147 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
151 Given a method, find the firm graph that implements that method.
152 Return NULL for abstract and native methods.
154 static ir_graph *_get_implementing_graph (entity *method)
156 ir_graph *graph = NULL;
158 /* What's up with the fenced out stuff in rta? */
159 if (peculiarity_existent == get_entity_peculiarity (method)) {
160 if (visibility_external_allocated == get_entity_visibility (method)) {
161 /* Todo: native implementation */
165 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
166 assert (graph && "no graph");
170 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
171 /* abstract --- can't find an implementation */
172 graph = get_entity_irg (method);
173 assert (!graph && "graph in abstract method");
176 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
177 (peculiarity_inherited == get_entity_peculiarity (method))) {
180 int n_over = get_entity_n_overwrites (method);
184 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
185 entity *over = get_entity_overwrites (method, i);
187 graph = _get_implementing_graph (over);
190 assert (0 && "invalid peculiarity");
198 Collect all graphs of 'method' in the given set.
200 static void _collect_implementing_graphs (entity *method, lset_t *set)
202 /* search DOWN-wards in clazz hierarchy */
204 int n_over = get_entity_n_overwrittenby (method);
205 ir_graph *graph = get_entity_irg (method);
208 graph = _get_implementing_graph (method);
212 lset_insert (set, graph);
215 for (i = 0; i < n_over; i ++) {
216 entity *over = get_entity_overwrittenby (method, i);
218 _collect_implementing_graphs (over, set);
224 Collect all graphs that could possibly be executed when 'method' is called.
226 static lset_t *get_implementing_graphs (entity *method, ir_node *select)
229 lset_t *set = lset_create ();
231 ir_graph *impl = _get_implementing_graph (method);
234 lset_insert (set, impl);
236 /* actually, abstract OR native */
240 _collect_implementing_graphs (method, set);
242 if (lset_empty (set)) {
243 /* then it's a method which is only implemented natively, and we
244 don' bother to analyse anything */
248 /* void *tmp = lset_first (set); */
249 n_graphs = lset_n_entries (set);
251 /* typalise select_in */
253 ir_node *select_in = get_Sel_ptr (select);
254 typalise_t *ta = typalise (select_in);
255 assert (ta && "typalise failed (go figure)");
257 /* const char *res = ta_name (ta); */
259 /* fprintf (stdout, "typalyse res = %s\n", res); */
262 int n_filtered_graphs;
264 set = filter_for_ta (set, ta);
265 n_filtered_graphs = lset_n_entries (set);
268 fprintf (stdout, "%s: %02d %02d\n",
272 n_graphs - n_filtered_graphs);
274 n_graphs = n_filtered_graphs;
278 if (n_graphs > _max_callEds) {
279 _max_callEds = n_graphs;
280 _max_callEds_callR = method;
284 if (visibility_external_allocated != get_entity_visibility (method)) {
286 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
287 assert (n_graphs && "no graphs for method");
295 Action for the graph.
297 static void ecg_calls_act (ir_node *node, void *env)
299 ir_op *op = get_irn_op(node);
300 graph_info_t *graph_info = (graph_info_t*) env;
302 if (op_Call == op) { /* CALL */
304 ir_node *ptr = get_Call_ptr (node);
307 if (op_Sel == get_irn_op(ptr)) {
309 ent = get_Sel_entity (ptr);
310 graphs = get_implementing_graphs (ent, ptr);
312 append_calls (graph_info, node, graphs);
313 } else if (op_SymConst == get_irn_op(ptr)) {
314 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
316 ent = get_SymConst_entity (ptr);
317 graph = get_entity_irg (ent);
320 append_call (graph_info, node, graph);
322 /* it's an externally allocated thingy */
324 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
325 /* If this SymConst refers to a method the method is external_visible
326 and therefore must be considered live anyways. */
327 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
328 assert (ent && "couldn't determine entity of call to symConst");
331 /* other symconst. */
332 assert (0 && "This SymConst can not be an address for a method call.");
335 /* STRANGE, no less ... */
338 assert (0 && "Unexpected address expression");
340 } else if (op_Alloc == op) {
341 type *tp = get_Alloc_type (node);
342 /* const char *name = get_type_name (tp); */
344 append_alloc (graph_info, node, tp);
346 /* fprintf (stdout, "NEW \"%s\"\n", name); */
351 Collect called graphs for the given graph.
353 static void ecg_fill_graph_calls (ir_graph *graph)
355 graph_info_t *ginfo = (graph_info_t*) xmalloc (sizeof (graph_info_t));
357 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
358 assert (ginfo != graph_infos_list);
360 ginfo->graph = graph;
367 /* link up into global list */
368 ginfo->prev = graph_infos_list;
369 graph_infos_list = ginfo;
371 assert (ginfo != ginfo->prev);
373 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
375 pmap_insert (graph_infos, graph, ginfo);
379 For each graph, collect called graphs, and enter them into calls.
381 static void ecg_fill_calls (void)
385 for (i = 0; i < get_irp_n_irgs (); i++) {
386 ir_graph *graph = get_irp_irg (i);
388 ecg_fill_graph_calls (graph);
393 Allocate a new ctx for the given graph and the given enclosing ctx.
395 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
397 ctx_info_t *res = (ctx_info_t *) xmalloc (sizeof (ctx_info_t));
409 Fill in the ctxs parts of the graph_infos
411 static void ecg_fill_ctxs_count (ir_graph *graph)
413 graph_info_t *ginfo = ecg_get_info (graph);
415 /* count how many ctxs we have per graph */
416 if (0 == ginfo->ecg_seen) {
417 call_info_t *cinfo = ginfo->calls;
421 while (NULL != cinfo) {
422 callEd_info_t *ced = cinfo->callEds;
424 while (NULL != ced) {
425 ir_graph *callEd_graph = ced->callEd;
427 /* first step: we have a new ctx */
428 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
429 callEd_info->n_ctxs ++;
431 /* CallR graph -> CallEd_graph */
432 ecg_fill_ctxs_count (callEd_graph);
435 } /* end forall callEds (call) */
438 } /* end forall (calls(graph)) */
444 static void ecg_fill_ctxs_alloc (void)
446 /* allocate the memory needed for the ctxts: */
447 graph_info_t *ginfo = graph_infos_list;
449 while (NULL != ginfo) {
450 ginfo->ctxs = (ctx_info_t **) xcalloc (ginfo->n_ctxs, sizeof (ctx_info_t *));
453 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
454 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
458 assert (ginfo != ginfo->prev);
464 Fill in the ctxs parts of the graph_infos
466 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
468 graph_info_t *ginfo = ecg_get_info (graph);
470 /* enter a new ctx for all callEds along the call edges of this graph */
471 if (0 == ginfo->ecg_seen) {
472 call_info_t *cinfo = ginfo->calls;
475 while (NULL != cinfo) {
476 callEd_info_t *ced = cinfo->callEds;
478 while (NULL != ced) {
479 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
481 ir_graph *callEd_graph = ced->callEd;
483 /* write the ctx of this call into the callEd graph */
484 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
486 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
487 callEd_info->n_ctxs ++;
489 /* CallR graph -> callEd_graph */
490 ecg_fill_ctxs_write (callEd_graph, ctx);
493 } /* end forall callEds (call) */
496 } /* end forall (calls(graph)) */
503 Fill in the ctxs parts of the graph_infos
505 static void ecg_fill_ctxs (void)
507 ctx_info_t *main_ctx;
511 ecg_fill_ctxs_count (get_irp_main_irg ());
512 ecg_fill_ctxs_alloc ();
514 main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
515 main_irg = get_irp_main_irg ();
517 set_main_ctx (main_ctx);
519 /* Grrr, have to add this ctx manually to main.ginfo ... */
520 ginfo = ecg_get_info (main_irg);
522 ginfo->ctxs = (ctx_info_t **) xcalloc (1, sizeof (ctx_info_t *));
523 ginfo->ctxs [0] = main_ctx;
525 ecg_fill_ctxs_write (main_irg, main_ctx);
528 /* ====================
530 ==================== */
532 Nicely print a ctx_info_t to the given output stream
534 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
536 entity *ent = get_irg_entity(ctx->graph);
537 ir_node *call = ctx->call;
538 const char *ent_name = get_entity_name (ent);
539 const char *own_name = get_type_name (get_entity_owner (ent));
541 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
542 ctx->id, own_name, ent_name,
543 get_op_name (get_irn_op (call)),
544 get_irn_node_nr (call));
546 if (NULL != ctx->enc) {
547 fprintf (stream, "->%i", ctx->enc->id);
550 fprintf (stream, "\n");
554 Get a ctx of the given graph info
556 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
558 assert (ginfo->n_ctxs > ctx_idx);
560 return (ginfo->ctxs [ctx_idx]);
564 Get the pseudo-ctx of 'main'
566 ctx_info_t *get_main_ctx ()
572 Set the pseudo-ctx of 'main'
574 void set_main_ctx (ctx_info_t *ctx)
580 /* ====================
582 ==================== */
584 /* ====================
586 ==================== */
588 Iterate over all graphs
590 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
592 graph_info_t *ginfo = graph_infos_list;
594 while (NULL != ginfo) {
595 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
597 if (0 != ginfo->n_ctxs) {
607 Iterate of all allocs of a given graph info
609 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
611 alloc_info_t *ainfo = ginfo->allocs;
613 while (NULL != ainfo) {
622 Iterate over all calls of the given graph info
624 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
626 call_info_t *cinfo = ginfo->calls;
628 while (NULL != cinfo) {
637 Iterate over all callEds of the given call info
639 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
641 callEd_info_t *ced = cinfo->callEds;
643 while (NULL != ced) {
652 get the call infos for the given graph
654 graph_info_t *ecg_get_info (ir_graph *graph)
656 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
658 assert (ginfo && "no info for graph");
664 Get the Alloc Infos for the given graph
666 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
668 graph_info_t *ginfo = ecg_get_info (graph);
670 return (ginfo->allocs);
674 Get the Call Info for the given call
676 callEd_info_t *ecg_get_callEd_info (ir_node *call)
678 ir_graph *graph = get_irn_irg (call);
679 graph_info_t *ginfo = ecg_get_info (graph);
681 call_info_t *call_info = ginfo->calls;
683 while (NULL != call_info) {
684 if (call == call_info->call) {
685 return (call_info->callEds);
688 call_info = call_info->prev;
696 Dump the given graph and it's calls and it's calls callEds to the given file.
698 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
703 const char *name = get_irg_entity (graph) ?
704 get_entity_name (get_irg_entity (graph)) : "noEntity";
706 (get_entity_stickyness
707 (get_irg_entity (graph)) == stickyness_sticky) ?
708 "red" : "lightyellow";
710 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
711 graph_info_t *ginfo = ecg_get_info (graph);
713 if (0 != ginfo->ecg_seen) {
714 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
715 name, (int) ginfo->ecg_seen);
717 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
720 return (ginfo->ecg_seen);
723 assert (0L <= _graphs);
725 graph_no = _graphs ++;
726 ginfo->ecg_seen = graph_no;
728 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
729 get_type_name (get_entity_owner (get_irg_entity (graph))),
731 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
733 get_type_name (get_entity_owner (get_irg_entity (graph))),
739 if (visibility_external_allocated ==
740 get_entity_visibility (get_irg_entity (graph))) {
741 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
746 cinfo = ginfo->calls;
747 while (NULL != cinfo) {
748 ir_node *call = cinfo->call;
749 callEd_info_t *ced = cinfo->callEds;
750 const int call_no = _calls ++;
751 const char *call_color = (NULL == ced) ? "blue" :
752 (NULL == ced->prev) ? "lightblue" : "blue3";
754 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
755 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
756 call_no, get_irn_node_nr (call), call_color);
757 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
759 while (NULL != ced) {
760 ir_graph *callEd_graph = ced->callEd;
761 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
762 const char *callEd_name = get_irg_entity (callEd_graph) ?
763 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
764 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
765 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
767 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
770 /* Check for recursive calls */
771 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
772 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
773 call_no, callEd_no, callEd_color, direction);
778 } /* done all calEds (call) */
781 } /* done all calls (graph) */
784 ainfo = ecg_get_alloc_info (graph);
786 fprintf (dot, "\t/* now the allocs */\n");
788 fprintf (dot, "\t/* no allocs */\n");
791 while (NULL != ainfo) {
792 ir_node *alloc = ainfo->alloc;
793 const char *name = get_type_name (ainfo->tp);
794 const char *color = "red1";
797 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
798 (int) alloc, graph_no, name, color);
800 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
801 graph_no, (int) alloc, graph_no);
806 if (0 == ginfo->allocs_seen) {
807 ginfo->allocs_seen = 1;
810 /* write table of ctxs */
813 const int max_ctxs = 30;
814 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
816 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
818 assert (ginfo->ctxs && "no ctx");
819 for (i = 0; i < n_ctxs; i ++) {
820 ctx_info_t *ctx_info = ginfo->ctxs [i];
822 if (NULL != ctx_info->enc) {
823 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
828 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
837 if (0 < ginfo->n_ctxs - max_ctxs) {
838 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
841 fprintf (dot, "\", color=\"green3\"];\n");
844 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
848 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
857 Count how many nodes the ECG will have
859 static char spaces [BUF_SIZE];
861 static void ecg_ecg_count (ir_graph *graph)
865 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
867 if (0 != ginfo->ecg_seen) {
872 if (_depth > _max_depth) {
876 fprintf (stdout, "_max_depth = %i\n", _max_depth);
877 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
881 assert (0L <= _graphs);
884 if (0 == (_graphs % 1000000)) {
885 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
886 fprintf (stdout, "_depth = %i\n", _depth);
890 graph_no = _graphs ++;
891 ginfo->ecg_seen = graph_no;
893 fprintf (stdout, "%sMethod \"%s.%s\"\n",
894 spaces + BUF_SIZE - _depth,
895 get_type_name (get_entity_owner (get_irg_entity (graph))),
896 get_entity_name (get_irg_entity (graph)));
898 cinfo = ginfo->calls;
899 while (NULL != cinfo) {
901 callEd_info_t *ced = cinfo->callEds;
903 fprintf (stdout, "%sCall \"0x%08x\"\n",
904 spaces + BUF_SIZE - _depth,
907 while (NULL != ced) {
908 ir_graph *callEd_graph = ced->callEd;
910 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
911 spaces + BUF_SIZE - _depth,
912 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
913 get_entity_name (get_irg_entity (callEd_graph)));
915 ecg_ecg_count (callEd_graph);
918 } /* done all calEds (call) */
920 } /* done all calls (graph) */
926 /* ====================
928 ==================== */
931 Initialise our data structures.
933 void ecg_init (int typalise)
935 do_typalise = typalise;
937 graph_infos = pmap_create ();
947 void ecg_cleanup (void)
953 for (i = 0; i < get_irp_n_irgs (); i++) {
954 ir_graph *graph = get_irp_irg (i);
956 graph_info_t *info = pmap_get (graph_infos, graph);
957 call_info_t *cinfo = info->calls;
959 while (NULL != cinfo) {
960 callEd_info_t *ced = cinfo->callEds;
964 while (NULL != ced) {
965 callEd_info_t *nced = ced->prev;
972 cinfo->callEds = NULL;
979 pmap_insert (graph_infos, graph, NULL);
983 pmap_destroy (graph_infos);
990 Show what we have found.
996 FILE *dot = fopen ("calls.dot", "w");
998 fprintf (dot, "digraph \"calls\" {\n");
999 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1000 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1001 fprintf (dot, "\tedge [color=\"black\"];\n");
1002 fprintf (dot, "\n");
1004 for (i = 0; i < get_irp_n_irgs (); i++) {
1005 ir_graph *graph = get_irp_irg (i);
1006 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
1008 if (0 != ginfo->n_ctxs) {
1010 alloc_info_t *ainfo;
1012 const char *name = get_irg_entity (graph) ?
1013 get_entity_name (get_irg_entity (graph)) : "noEntity";
1015 const char *oname = get_type_name
1016 (get_entity_owner (get_irg_entity (graph)));
1019 (get_entity_stickyness
1020 (get_irg_entity (graph)) == stickyness_sticky) ?
1021 "red3" : "lightyellow";
1023 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1025 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1026 (int) graph, oname, name, color);
1027 fprintf (dot, "\n");
1029 cinfo = ginfo->calls;
1031 fprintf (dot, "\t/* now the calls */\n");
1033 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1036 while (NULL != cinfo) {
1038 ir_node *call = cinfo->call;
1040 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1041 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\", shape=\"ellipse\", color=\"lightblue\"];\n",
1042 (int) call, get_irn_node_nr (call));
1043 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1044 (int) graph, (int) call);
1046 ced = cinfo->callEds;
1047 while (NULL != ced) {
1048 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1049 (int) call, (int) ced->callEd);
1052 fprintf (dot, "\n");
1054 cinfo = cinfo->prev;
1056 fprintf (dot, "\n");
1058 ainfo = ginfo->allocs;
1060 fprintf (dot, "\t/* now the allocs */\n");
1062 fprintf (dot, "\t/* no allocs */\n");
1066 while (NULL != ainfo) {
1067 ir_node *alloc = ainfo->alloc;
1068 const char *name = get_type_name (ainfo->tp);
1069 const char *color = "red1";
1071 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1072 (int) alloc, name, color);
1073 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1074 (int) graph, (int) alloc);
1076 ainfo = ainfo->prev;
1082 const int max_ctxs = 30;
1083 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
1085 fprintf (dot, "\t/* now the ctxs */\n");
1086 fprintf (dot, "\tctx_0x%08x [label=\"<HEAD>", (int) graph);
1088 assert (ginfo->ctxs && "no ctx");
1089 for (i = 0; i < n_ctxs; i ++) {
1090 ctx_info_t *ctx_info = ginfo->ctxs [i];
1092 if (NULL != ctx_info->enc) {
1093 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
1098 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
1102 if (i+1 != n_ctxs) {
1107 if (0 < ginfo->n_ctxs - max_ctxs) {
1108 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
1111 fprintf (dot, "\", color=\"green3\"];\n");
1114 "\tgraph_0x%08x -> ctx_0x%08x:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
1115 (int) graph, (int) graph);
1118 fprintf (dot, "\t/* graph is not called */\n");
1119 } /* end all graphs */
1121 fprintf (dot, "}\n");
1124 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1125 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1126 get_entity_name (_max_callEds_callR));
1132 Experimental: Print the ecg
1137 ir_graph *main_graph = get_irp_main_irg ();
1143 memset (spaces, '.', BUF_SIZE);
1144 spaces [BUF_SIZE-1] = '\0';
1146 ecg_ecg_count (main_graph);
1147 fprintf (stdout, "n_graphs: %i\n", _graphs);
1148 fprintf (stdout, "max_depth = %i\n", _max_depth);
1156 dot = fopen ("ecg.dot", "w");
1158 fprintf (dot, "digraph \"ecg\" {\n");
1159 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1160 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1161 fprintf (dot, "\tedge [color=\"black\"];\n");
1162 fprintf (dot, "\n");
1163 fprintf (dot, "\n");
1165 /* ir_graph *main_graph = get_irp_main_irg (); */
1166 ecg_ecg_graph (dot, main_graph);
1168 fprintf (dot, "\t/* Grand Total: */\n");
1169 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1170 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1171 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1172 fprintf (dot, "\t/* (sales tax not included) */\n");
1174 fprintf (dot, "}\n");
1183 Revision 1.16 2005/01/10 17:26:34 liekweg
1184 fixup printfs, don't put environments on the stack
1186 Revision 1.15 2004/12/23 15:40:03 beck
1189 Revision 1.14 2004/12/22 14:43:14 beck
1190 made allocations C-like
1192 Revision 1.13 2004/12/21 14:21:16 beck
1193 removed C99 constructs
1195 Revision 1.12 2004/12/20 17:34:34 liekweg
1196 fix recursion handling
1198 Revision 1.11 2004/12/15 09:18:18 liekweg
1201 Revision 1.10 2004/12/06 12:55:06 liekweg
1204 Revision 1.9 2004/12/02 16:17:50 beck
1205 fixed config.h include
1207 Revision 1.8 2004/11/30 14:45:44 liekweg
1208 fix graph dumping, remove 'HERE's
1210 Revision 1.7 2004/11/26 16:01:56 liekweg
1211 debugging annotations
1213 Revision 1.6 2004/11/24 14:53:55 liekweg
1216 Revision 1.5 2004/11/20 21:20:29 liekweg
1217 Added iterator functions
1219 Revision 1.4 2004/11/18 16:36:37 liekweg
1220 Added unique ids for debugging, added access functions
1222 Revision 1.3 2004/11/04 14:54:44 liekweg
1225 Revision 1.2 2004/10/21 11:09:37 liekweg
1226 Moved memwalk stuf into irmemwalk
1227 Moved lset stuff into lset
1228 Moved typalise stuff into typalise
1230 Revision 1.1 2004/10/20 14:59:41 liekweg
1231 Added ana2, added ecg and pto
1233 Revision 1.6 2004/10/18 12:47:19 liekweg
1236 Revision 1.5 2004/10/14 11:31:28 liekweg
1239 Revision 1.4 2004/10/12 11:02:01 liekweg