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 = xmalloc (sizeof(*cinfo));
122 cinfo->prev = info->calls;
124 cinfo->callEds = NULL;
127 for (callEd = lset_first (callEds); callEd; callEd = lset_next(callEds))
128 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
132 Append the (single) callEd to the given (call) node of the given graph_info.
134 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
136 call_info_t *cinfo = xmalloc (sizeof(*cinfo));
139 cinfo->prev = info->calls;
142 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
146 Given a method, find the firm graph that implements that method.
147 Return NULL for abstract and native methods.
149 static ir_graph *_get_implementing_graph (entity *method)
151 ir_graph *graph = NULL;
153 /* What's up with the fenced out stuff in rta? */
154 if (peculiarity_existent == get_entity_peculiarity (method)) {
155 if (visibility_external_allocated == get_entity_visibility (method)) {
156 /* Todo: native implementation */
160 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
161 assert (graph && "no graph");
165 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
166 /* abstract --- can't find an implementation */
167 graph = get_entity_irg (method);
168 assert (!graph && "graph in abstract method");
171 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
172 (peculiarity_inherited == get_entity_peculiarity (method))) {
175 int n_over = get_entity_n_overwrites (method);
179 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
180 entity *over = get_entity_overwrites (method, i);
182 graph = _get_implementing_graph (over);
185 assert (0 && "invalid peculiarity");
193 Collect all graphs of 'method' in the given set.
195 static void _collect_implementing_graphs (entity *method, lset_t *set)
197 /* search DOWN-wards in clazz hierarchy */
199 int n_over = get_entity_n_overwrittenby (method);
200 ir_graph *graph = get_entity_irg (method);
203 graph = _get_implementing_graph (method);
207 lset_insert (set, graph);
210 for (i = 0; i < n_over; i ++) {
211 entity *over = get_entity_overwrittenby (method, i);
213 _collect_implementing_graphs (over, set);
219 Collect all graphs that could possibly be executed when 'method' is called.
221 static lset_t *get_implementing_graphs (entity *method, ir_node *select)
224 lset_t *set = lset_create ();
226 ir_graph *impl = _get_implementing_graph (method);
229 lset_insert (set, impl);
231 /* actually, abstract OR native */
235 _collect_implementing_graphs (method, set);
237 if (lset_empty (set)) {
238 /* then it's a method which is only implemented natively, and we
239 don' bother to analyse anything */
243 /* void *tmp = lset_first (set); */
244 n_graphs = lset_n_entries (set);
246 /* typalise select_in */
248 ir_node *select_in = get_Sel_ptr (select);
249 typalise_t *ta = typalise (select_in);
250 assert (ta && "typalise failed (go figure)");
252 /* const char *res = ta_name (ta); */
254 /* fprintf (stdout, "typalyse res = %s\n", res); */
257 int n_filtered_graphs;
259 set = filter_for_ta (set, ta);
260 n_filtered_graphs = lset_n_entries (set);
263 fprintf (stdout, "%s: %02d %02d\n",
267 n_graphs - n_filtered_graphs);
269 n_graphs = n_filtered_graphs;
273 if (n_graphs > _max_callEds) {
274 _max_callEds = n_graphs;
275 _max_callEds_callR = method;
279 if (visibility_external_allocated != get_entity_visibility (method)) {
281 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
282 assert (n_graphs && "no graphs for method");
290 Action for the graph.
292 static void ecg_calls_act (ir_node *node, void *env)
294 ir_op *op = get_irn_op(node);
295 graph_info_t *graph_info = (graph_info_t*) env;
297 if (op_Call == op) { /* CALL */
299 ir_node *ptr = get_Call_ptr (node);
302 if (op_Sel == get_irn_op(ptr)) {
304 ent = get_Sel_entity (ptr);
305 graphs = get_implementing_graphs (ent, ptr);
307 append_calls (graph_info, node, graphs);
308 } else if (op_SymConst == get_irn_op(ptr)) {
309 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
311 ent = get_SymConst_entity (ptr);
312 graph = get_entity_irg (ent);
315 append_call (graph_info, node, graph);
317 /* it's an externally allocated thingy */
319 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
320 /* If this SymConst refers to a method the method is external_visible
321 and therefore must be considered live anyways. */
322 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
323 assert (ent && "couldn't determine entity of call to symConst");
326 /* other symconst. */
327 assert (0 && "This SymConst can not be an address for a method call.");
330 /* STRANGE, no less ... */
333 assert (0 && "Unexpected address expression");
335 } else if (op_Alloc == op) {
336 type *tp = get_Alloc_type (node);
337 /* const char *name = get_type_name (tp); */
339 append_alloc (graph_info, node, tp);
341 /* fprintf (stdout, "NEW \"%s\"\n", name); */
346 Collect called graphs for the given graph.
348 static void ecg_fill_graph_calls (ir_graph *graph)
350 graph_info_t *ginfo = (graph_info_t*) xmalloc (sizeof (graph_info_t));
352 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
353 assert (ginfo != graph_infos_list);
355 ginfo->graph = graph;
362 /* link up into global list */
363 ginfo->prev = graph_infos_list;
364 graph_infos_list = ginfo;
366 assert (ginfo != ginfo->prev);
368 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
370 pmap_insert (graph_infos, graph, ginfo);
374 For each graph, collect called graphs, and enter them into calls.
376 static void ecg_fill_calls (void)
380 for (i = 0; i < get_irp_n_irgs (); i++) {
381 ir_graph *graph = get_irp_irg (i);
383 ecg_fill_graph_calls (graph);
388 Allocate a new ctx for the given graph and the given enclosing ctx.
390 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
392 ctx_info_t *res = xmalloc (sizeof (ctx_info_t));
404 Fill in the ctxs parts of the graph_infos
406 static void ecg_fill_ctxs_count (ir_graph *graph)
408 graph_info_t *ginfo = ecg_get_info (graph);
410 /* count how many ctxs we have per graph */
411 if (0 == ginfo->ecg_seen) {
412 call_info_t *cinfo = ginfo->calls;
416 while (NULL != cinfo) {
417 callEd_info_t *ced = cinfo->callEds;
419 while (NULL != ced) {
420 ir_graph *callEd_graph = ced->callEd;
422 /* first step: we have a new ctx */
423 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
424 callEd_info->n_ctxs ++;
426 /* CallR graph -> CallEd_graph */
427 ecg_fill_ctxs_count (callEd_graph);
430 } /* end forall callEds (call) */
433 } /* end forall (calls(graph)) */
439 static void ecg_fill_ctxs_alloc (void)
441 /* allocate the memory needed for the ctxts: */
442 graph_info_t *ginfo = graph_infos_list;
444 while (NULL != ginfo) {
445 ginfo->ctxs = (ctx_info_t **) xmalloc (ginfo->n_ctxs * sizeof (ctx_info_t*));
448 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
449 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
453 assert (ginfo != ginfo->prev);
459 Fill in the ctxs parts of the graph_infos
461 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
463 graph_info_t *ginfo = ecg_get_info (graph);
465 /* enter a new ctx for all callEds along the call edges of this graph */
466 if (0 == ginfo->ecg_seen) {
467 call_info_t *cinfo = ginfo->calls;
470 while (NULL != cinfo) {
471 callEd_info_t *ced = cinfo->callEds;
473 while (NULL != ced) {
474 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
476 ir_graph *callEd_graph = ced->callEd;
478 /* write the ctx of this call into the callEd graph */
479 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
481 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
482 callEd_info->n_ctxs ++;
484 /* Calling graph -> callEd_graph */
485 ecg_fill_ctxs_write (callEd_graph, ctx);
488 } /* end forall callEds (call) */
491 } /* end forall (calls(graph)) */
498 Fill in the ctxs parts of the graph_infos
500 static void ecg_fill_ctxs (void)
502 ctx_info_t *main_ctx;
506 ecg_fill_ctxs_count (get_irp_main_irg ());
507 ecg_fill_ctxs_alloc ();
509 main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
510 main_irg = get_irp_main_irg ();
512 set_main_ctx (main_ctx);
514 /* Grrr, have to add this ctx manually to main.ginfo ... */
515 ginfo = ecg_get_info (main_irg);
517 ginfo->ctxs = xmalloc (1 * sizeof (ctx_info_t*));
518 ginfo->ctxs [0] = main_ctx;
520 ecg_fill_ctxs_write (main_irg, main_ctx);
523 /* ====================
525 ==================== */
527 Nicely print a ctx_info_t to the given output stream
529 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
531 entity *ent = get_irg_entity(ctx->graph);
532 ir_node *call = ctx->call;
533 const char *ent_name = get_entity_name (ent);
534 const char *own_name = get_type_name (get_entity_owner (ent));
536 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
537 ctx->id, own_name, ent_name,
538 get_op_name (get_irn_op (call)),
539 get_irn_node_nr (call));
541 if (NULL != ctx->enc) {
542 fprintf (stream, "->%i", ctx->enc->id);
545 fprintf (stream, "\n");
549 Get a ctx of the given graph info
551 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
553 assert (ginfo->n_ctxs > ctx_idx);
555 return (ginfo->ctxs [ctx_idx]);
559 Get the pseudo-ctx of 'main'
561 ctx_info_t *get_main_ctx ()
567 Set the pseudo-ctx of 'main'
569 void set_main_ctx (ctx_info_t *ctx)
575 /* ====================
577 ==================== */
579 /* ====================
581 ==================== */
583 Iterate over all graphs
585 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
587 graph_info_t *ginfo = graph_infos_list;
589 while (NULL != ginfo) {
590 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
592 if (0 != ginfo->n_ctxs) {
602 Iterate of all allocs of a given graph info
604 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
606 alloc_info_t *ainfo = ginfo->allocs;
608 while (NULL != ainfo) {
617 Iterate over all calls of the given graph info
619 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
621 call_info_t *cinfo = ginfo->calls;
623 while (NULL != cinfo) {
632 Iterate over all callEds of the given call info
634 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
636 callEd_info_t *ced = cinfo->callEds;
638 while (NULL != ced) {
647 get the call infos for the given graph
649 graph_info_t *ecg_get_info (ir_graph *graph)
651 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
653 assert (ginfo && "no info for graph");
659 Get the Alloc Infos for the given graph
661 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
663 graph_info_t *ginfo = ecg_get_info (graph);
665 return (ginfo->allocs);
669 Get the Call Info for the given call
671 callEd_info_t *ecg_get_callEd_info (ir_node *call)
673 ir_graph *graph = get_irn_irg (call);
674 graph_info_t *ginfo = ecg_get_info (graph);
676 call_info_t *call_info = ginfo->calls;
678 while (NULL != call_info) {
679 if (call == call_info->call) {
680 return (call_info->callEds);
683 call_info = call_info->prev;
691 Dump the given graph and it's calls and it's calls callEds to the given file.
693 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
698 const char *name = get_irg_entity (graph) ?
699 get_entity_name (get_irg_entity (graph)) : "noEntity";
701 (get_entity_stickyness
702 (get_irg_entity (graph)) == stickyness_sticky) ?
703 "red" : "lightyellow";
705 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
706 graph_info_t *ginfo = ecg_get_info (graph);
708 if (0 != ginfo->ecg_seen) {
709 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
710 name, (int) ginfo->ecg_seen);
712 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
715 return (ginfo->ecg_seen);
718 assert (0L <= _graphs);
720 graph_no = _graphs ++;
721 ginfo->ecg_seen = graph_no;
723 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
724 get_type_name (get_entity_owner (get_irg_entity (graph))),
726 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
728 get_type_name (get_entity_owner (get_irg_entity (graph))),
734 if (visibility_external_allocated ==
735 get_entity_visibility (get_irg_entity (graph))) {
736 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
741 cinfo = ginfo->calls;
742 while (NULL != cinfo) {
743 ir_node *call = cinfo->call;
744 callEd_info_t *ced = cinfo->callEds;
745 const int call_no = _calls ++;
746 const char *call_color = (NULL == ced) ? "blue" :
747 (NULL == ced->prev) ? "lightblue" : "blue3";
749 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
750 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
751 call_no, get_irn_node_nr (call), call_color);
752 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
754 while (NULL != ced) {
755 ir_graph *callEd_graph = ced->callEd;
756 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
757 const char *callEd_name = get_irg_entity (callEd_graph) ?
758 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
759 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
760 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
762 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
765 /* Check for recursive calls */
766 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
767 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
768 call_no, callEd_no, callEd_color, direction);
773 } /* done all calEds (call) */
776 } /* done all calls (graph) */
779 ainfo = ecg_get_alloc_info (graph);
781 fprintf (dot, "\t/* now the allocs */\n");
783 fprintf (dot, "\t/* no allocs */\n");
786 while (NULL != ainfo) {
787 ir_node *alloc = ainfo->alloc;
788 const char *name = get_type_name (ainfo->tp);
789 const char *color = "red1";
792 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
793 (int) alloc, graph_no, name, color);
795 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
796 graph_no, (int) alloc, graph_no);
801 if (0 == ginfo->allocs_seen) {
802 ginfo->allocs_seen = 1;
805 /* write table of ctxs */
808 const int max_ctxs = 30;
809 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
811 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
813 assert (ginfo->ctxs && "no ctx");
814 for (i = 0; i < n_ctxs; i ++) {
815 ctx_info_t *ctx_info = ginfo->ctxs [i];
817 if (NULL != ctx_info->enc) {
818 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
823 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
832 if (0 < ginfo->n_ctxs - max_ctxs) {
833 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
836 fprintf (dot, "\", color=\"green3\"];\n");
839 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
843 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
852 Count how many nodes the ECG will have
854 static char spaces [BUF_SIZE];
856 static void ecg_ecg_count (ir_graph *graph)
860 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
862 if (0 != ginfo->ecg_seen) {
867 if (_depth > _max_depth) {
871 fprintf (stdout, "_max_depth = %i\n", _max_depth);
872 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
876 assert (0L <= _graphs);
879 if (0 == (_graphs % 1000000)) {
880 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
881 fprintf (stdout, "_depth = %i\n", _depth);
885 graph_no = _graphs ++;
886 ginfo->ecg_seen = graph_no;
888 fprintf (stdout, "%sMethod \"%s.%s\"\n",
889 spaces + BUF_SIZE - _depth,
890 get_type_name (get_entity_owner (get_irg_entity (graph))),
891 get_entity_name (get_irg_entity (graph)));
893 cinfo = ginfo->calls;
894 while (NULL != cinfo) {
896 callEd_info_t *ced = cinfo->callEds;
898 fprintf (stdout, "%sCall \"0x%08x\"\n",
899 spaces + BUF_SIZE - _depth,
902 while (NULL != ced) {
903 ir_graph *callEd_graph = ced->callEd;
905 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
906 spaces + BUF_SIZE - _depth,
907 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
908 get_entity_name (get_irg_entity (callEd_graph)));
910 ecg_ecg_count (callEd_graph);
913 } /* done all calEds (call) */
915 } /* done all calls (graph) */
921 /* ====================
923 ==================== */
926 Initialise our data structures.
928 void ecg_init (int typalise)
930 do_typalise = typalise;
932 graph_infos = pmap_create ();
942 void ecg_cleanup (void)
948 for (i = 0; i < get_irp_n_irgs (); i++) {
949 ir_graph *graph = get_irp_irg (i);
951 graph_info_t *info = pmap_get (graph_infos, graph);
952 call_info_t *cinfo = info->calls;
954 while (NULL != cinfo) {
955 callEd_info_t *ced = cinfo->callEds;
959 while (NULL != ced) {
960 callEd_info_t *nced = ced->prev;
967 cinfo->callEds = NULL;
974 pmap_insert (graph_infos, graph, NULL);
978 pmap_destroy (graph_infos);
985 Show what we have found.
991 FILE *dot = fopen ("calls.dot", "w");
993 fprintf (dot, "digraph \"calls\" {\n");
994 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
995 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
996 fprintf (dot, "\tedge [color=\"black\"];\n");
999 for (i = 0; i < get_irp_n_irgs (); i++) {
1000 ir_graph *graph = get_irp_irg (i);
1001 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
1003 if (0 != ginfo->n_ctxs) {
1005 alloc_info_t *ainfo;
1007 const char *name = get_irg_entity (graph) ?
1008 get_entity_name (get_irg_entity (graph)) : "noEntity";
1010 const char *oname = get_type_name
1011 (get_entity_owner (get_irg_entity (graph)));
1014 (get_entity_stickyness
1015 (get_irg_entity (graph)) == stickyness_sticky) ?
1016 "red3" : "lightyellow";
1018 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1020 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1021 (int) graph, oname, name, color);
1022 fprintf (dot, "\n");
1024 cinfo = ginfo->calls;
1026 fprintf (dot, "\t/* now the calls */\n");
1028 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1031 while (NULL != cinfo) {
1033 ir_node *call = cinfo->call;
1035 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1036 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\", shape=\"ellipse\", color=\"lightblue\"];\n",
1037 (int) call, get_irn_node_nr (call));
1038 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1039 (int) graph, (int) call);
1041 ced = cinfo->callEds;
1042 while (NULL != ced) {
1043 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1044 (int) call, (int) ced->callEd);
1047 fprintf (dot, "\n");
1049 cinfo = cinfo->prev;
1051 fprintf (dot, "\n");
1053 ainfo = ginfo->allocs;
1055 fprintf (dot, "\t/* now the allocs */\n");
1057 fprintf (dot, "\t/* no allocs */\n");
1061 while (NULL != ainfo) {
1062 ir_node *alloc = ainfo->alloc;
1063 const char *name = get_type_name (ainfo->tp);
1064 const char *color = "red1";
1066 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1067 (int) alloc, name, color);
1068 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1069 (int) graph, (int) alloc);
1071 ainfo = ainfo->prev;
1077 const int max_ctxs = 30;
1078 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
1080 fprintf (dot, "\t/* now the ctxs */\n");
1081 fprintf (dot, "\tctx_0x%08x [label=\"<HEAD>", (void*) graph);
1083 assert (ginfo->ctxs && "no ctx");
1084 for (i = 0; i < n_ctxs; i ++) {
1085 ctx_info_t *ctx_info = ginfo->ctxs [i];
1087 if (NULL != ctx_info->enc) {
1088 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
1093 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
1097 if (i+1 != n_ctxs) {
1102 if (0 < ginfo->n_ctxs - max_ctxs) {
1103 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
1106 fprintf (dot, "\", color=\"green3\"];\n");
1109 "\tgraph_0x%08x -> ctx_0x%08x:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
1110 (void*) graph, (void*) graph);
1113 fprintf (dot, "\t/* graph is not called */\n");
1114 } /* end all graphs */
1116 fprintf (dot, "}\n");
1119 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1120 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1121 get_entity_name (_max_callEds_callR));
1127 Experimental: Print the ecg
1132 ir_graph *main_graph = get_irp_main_irg ();
1138 memset (spaces, '.', BUF_SIZE);
1139 spaces [BUF_SIZE-1] = '\0';
1141 ecg_ecg_count (main_graph);
1142 fprintf (stdout, "n_graphs: %i\n", _graphs);
1143 fprintf (stdout, "max_depth = %i\n", _max_depth);
1151 dot = fopen ("ecg.dot", "w");
1153 fprintf (dot, "digraph \"ecg\" {\n");
1154 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1155 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1156 fprintf (dot, "\tedge [color=\"black\"];\n");
1157 fprintf (dot, "\n");
1158 fprintf (dot, "\n");
1160 /* ir_graph *main_graph = get_irp_main_irg (); */
1161 ecg_ecg_graph (dot, main_graph);
1163 fprintf (dot, "\t/* Grand Total: */\n");
1164 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1165 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1166 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1167 fprintf (dot, "\t/* (sales tax not included) */\n");
1169 fprintf (dot, "}\n");
1178 Revision 1.13 2004/12/21 14:21:16 beck
1179 removed C99 constructs
1181 Revision 1.12 2004/12/20 17:34:34 liekweg
1182 fix recursion handling
1184 Revision 1.11 2004/12/15 09:18:18 liekweg
1187 Revision 1.10 2004/12/06 12:55:06 liekweg
1190 Revision 1.9 2004/12/02 16:17:50 beck
1191 fixed config.h include
1193 Revision 1.8 2004/11/30 14:45:44 liekweg
1194 fix graph dumping, remove 'HERE's
1196 Revision 1.7 2004/11/26 16:01:56 liekweg
1197 debugging annotations
1199 Revision 1.6 2004/11/24 14:53:55 liekweg
1202 Revision 1.5 2004/11/20 21:20:29 liekweg
1203 Added iterator functions
1205 Revision 1.4 2004/11/18 16:36:37 liekweg
1206 Added unique ids for debugging, added access functions
1208 Revision 1.3 2004/11/04 14:54:44 liekweg
1211 Revision 1.2 2004/10/21 11:09:37 liekweg
1212 Moved memwalk stuf into irmemwalk
1213 Moved lset stuff into lset
1214 Moved typalise stuff into typalise
1216 Revision 1.1 2004/10/20 14:59:41 liekweg
1217 Added ana2, added ecg and pto
1219 Revision 1.6 2004/10/18 12:47:19 liekweg
1222 Revision 1.5 2004/10/14 11:31:28 liekweg
1225 Revision 1.4 2004/10/12 11:02:01 liekweg