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 = xmalloc (sizeof (alloc_info_t));
87 ainfo->graph = ginfo->graph;
91 ainfo->prev = ginfo->allocs;
92 ginfo->allocs = ainfo;
96 /* ====================
98 ==================== */
100 Create a new call info struct from the given values.
102 static call_info_t *new_call_info (ir_node *call,
103 callEd_info_t *callEds,
106 call_info_t *cinfo = xmalloc (sizeof (call_info_t));
108 cinfo->callEds = callEds;
115 Append the given callEd to the given callEd info.
117 static callEd_info_t *append_callEd_info (callEd_info_t *ced, ir_graph *callEd)
119 callEd_info_t *nced = xmalloc (sizeof (callEd_info_t));
121 assert (NULL != callEd);
123 nced->callEd = callEd;
130 Append all callEd methods of the given (call) node to the given graph_info.
132 static void append_calls (graph_info_t *info, ir_node *call, lset_t *callEds)
134 ir_graph *callEd = NULL;
135 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
140 callEd = lset_first (callEds);
142 while (NULL != callEd) {
143 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
144 callEd = lset_next(callEds);
150 Append the (single) callEd to the given (call) node of the given graph_info.
152 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
154 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
158 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
162 Given a method, find the firm graph that implements that method.
163 Return NULL for abstract and native methods.
165 static ir_graph *_get_implementing_graph (entity *method)
167 ir_graph *graph = NULL;
169 /* What's up with the fenced out stuff in rta? */
170 if (peculiarity_existent == get_entity_peculiarity (method)) {
171 if (visibility_external_allocated == get_entity_visibility (method)) {
172 /* Todo: native implementation */
176 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
177 assert (graph && "no graph");
181 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
182 /* abstract --- can't find an implementation */
183 graph = get_entity_irg (method);
184 assert (!graph && "graph in abstract method");
187 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
188 (peculiarity_inherited == get_entity_peculiarity (method))) {
191 int n_over = get_entity_n_overwrites (method);
195 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
196 entity *over = get_entity_overwrites (method, i);
198 graph = _get_implementing_graph (over);
201 assert (0 && "invalid peculiarity");
209 Collect all graphs of 'method' in the given set.
211 static void _collect_implementing_graphs (entity *method, lset_t *set)
213 /* search DOWN-wards in clazz hierarchy */
215 int n_over = get_entity_n_overwrittenby (method);
216 ir_graph *graph = get_entity_irg (method);
219 graph = _get_implementing_graph (method);
223 lset_insert (set, graph);
226 for (i = 0; i < n_over; i ++) {
227 entity *over = get_entity_overwrittenby (method, i);
229 _collect_implementing_graphs (over, set);
235 Collect all graphs that could possibly be executed when 'method' is called.
237 static lset_t *get_implementing_graphs (entity *method, ir_node *select)
240 lset_t *set = lset_create ();
242 ir_graph *impl = _get_implementing_graph (method);
245 lset_insert (set, impl);
247 /* actually, abstract OR native */
251 _collect_implementing_graphs (method, set);
253 if (lset_empty (set)) {
254 /* then it's a method which is only implemented natively, and we
255 don' bother to analyse anything */
259 /* void *tmp = lset_first (set); */
260 n_graphs = lset_n_entries (set);
262 /* typalise select_in */
264 ir_node *select_in = get_Sel_ptr (select);
265 typalise_t *ta = typalise (select_in);
266 assert (ta && "typalise failed (go figure)");
268 /* const char *res = ta_name (ta); */
270 /* fprintf (stdout, "typalyse res = %s\n", res); */
273 int n_filtered_graphs;
275 set = filter_for_ta (set, ta);
276 n_filtered_graphs = lset_n_entries (set);
279 fprintf (stdout, "%s: %02d %02d\n",
283 n_graphs - n_filtered_graphs);
285 n_graphs = n_filtered_graphs;
289 if (n_graphs > _max_callEds) {
290 _max_callEds = n_graphs;
291 _max_callEds_callR = method;
295 if (visibility_external_allocated != get_entity_visibility (method)) {
297 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
298 assert (n_graphs && "no graphs for method");
306 Action for the graph.
308 static void ecg_calls_act (ir_node *node, void *env)
310 ir_op *op = get_irn_op(node);
311 graph_info_t *graph_info = (graph_info_t*) env;
313 if (op_Call == op) { /* CALL */
315 ir_node *ptr = get_Call_ptr (node);
318 if (op_Sel == get_irn_op(ptr)) {
320 ent = get_Sel_entity (ptr);
321 graphs = get_implementing_graphs (ent, ptr);
323 append_calls (graph_info, node, graphs);
324 } else if (op_SymConst == get_irn_op(ptr)) {
325 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
327 ent = get_SymConst_entity (ptr);
328 graph = get_entity_irg (ent);
331 append_call (graph_info, node, graph);
333 /* it's an externally allocated thingy */
335 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
336 /* If this SymConst refers to a method the method is external_visible
337 and therefore must be considered live anyways. */
338 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
339 assert (ent && "couldn't determine entity of call to symConst");
342 /* other symconst. */
343 assert (0 && "This SymConst can not be an address for a method call.");
346 /* STRANGE, no less ... */
349 assert (0 && "Unexpected address expression");
351 } else if (op_Alloc == op) {
352 type *tp = get_Alloc_type (node);
353 /* const char *name = get_type_name (tp); */
355 append_alloc (graph_info, node, tp);
357 /* fprintf (stdout, "NEW \"%s\"\n", name); */
362 Collect called graphs for the given graph.
364 static void ecg_fill_graph_calls (ir_graph *graph)
366 graph_info_t *ginfo = xmalloc (sizeof (graph_info_t));
368 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
369 assert (ginfo != graph_infos_list);
371 ginfo->graph = graph;
373 ginfo->allocs = NULL;
377 ginfo->allocs_seen = 0;
380 /* link up into global list */
381 ginfo->prev = graph_infos_list;
382 graph_infos_list = ginfo;
384 assert (ginfo != ginfo->prev);
386 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
388 pmap_insert (graph_infos, graph, ginfo);
392 For each graph, collect called graphs, and enter them into calls.
394 static void ecg_fill_calls (void)
398 for (i = 0; i < get_irp_n_irgs (); i++) {
399 ir_graph *graph = get_irp_irg (i);
401 ecg_fill_graph_calls (graph);
406 Allocate a new ctx for the given graph and the given enclosing ctx.
408 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
410 ctx_info_t *res = xmalloc (sizeof (ctx_info_t));
422 Fill in the ctxs parts of the graph_infos
424 static void ecg_fill_ctxs_count (ir_graph *graph)
426 graph_info_t *ginfo = ecg_get_info (graph);
428 /* count how many ctxs we have per graph */
429 if (0 == ginfo->ecg_seen) {
430 call_info_t *cinfo = ginfo->calls;
434 while (NULL != cinfo) {
435 callEd_info_t *ced = cinfo->callEds;
437 while (NULL != ced) {
438 ir_graph *callEd_graph = ced->callEd;
440 /* first step: we have a new ctx */
441 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
442 callEd_info->n_ctxs ++;
444 /* CallR graph -> CallEd_graph */
445 ecg_fill_ctxs_count (callEd_graph);
448 } /* end forall callEds (call) */
451 } /* end forall (calls(graph)) */
457 static void ecg_fill_ctxs_alloc (void)
459 /* allocate the memory needed for the ctxts: */
460 graph_info_t *ginfo = graph_infos_list;
462 while (NULL != ginfo) {
463 ginfo->ctxs = xcalloc (ginfo->n_ctxs, sizeof (ctx_info_t *));
466 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
467 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
471 assert (ginfo != ginfo->prev);
477 Fill in the ctxs parts of the graph_infos
479 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
481 graph_info_t *ginfo = ecg_get_info (graph);
483 /* enter a new ctx for all callEds along the call edges of this graph */
484 if (0 == ginfo->ecg_seen) {
485 call_info_t *cinfo = ginfo->calls;
488 while (NULL != cinfo) {
489 callEd_info_t *ced = cinfo->callEds;
491 while (NULL != ced) {
492 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
494 ir_graph *callEd_graph = ced->callEd;
496 /* write the ctx of this call into the callEd graph */
497 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
499 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
500 callEd_info->n_ctxs ++;
502 /* CallR graph -> callEd_graph */
503 ecg_fill_ctxs_write (callEd_graph, ctx);
506 } /* end forall callEds (call) */
509 } /* end forall (calls(graph)) */
516 Fill in the ctxs parts of the graph_infos
518 static void ecg_fill_ctxs (void)
520 ctx_info_t *main_ctx;
524 ecg_fill_ctxs_count (get_irp_main_irg ());
525 ecg_fill_ctxs_alloc ();
527 main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
528 main_irg = get_irp_main_irg ();
530 set_main_ctx (main_ctx);
532 /* Grrr, have to add this ctx manually to main.ginfo ... */
533 ginfo = ecg_get_info (main_irg);
535 ginfo->ctxs = xcalloc (1, sizeof (ctx_info_t *));
536 ginfo->ctxs [0] = main_ctx;
538 ecg_fill_ctxs_write (main_irg, main_ctx);
541 /* ====================
543 ==================== */
545 Nicely print a ctx_info_t to the given output stream
547 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
549 entity *ent = get_irg_entity(ctx->graph);
550 ir_node *call = ctx->call;
551 const char *ent_name = get_entity_name (ent);
552 const char *own_name = get_type_name (get_entity_owner (ent));
554 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
555 ctx->id, own_name, ent_name,
556 get_op_name (get_irn_op (call)),
557 get_irn_node_nr (call));
559 if (NULL != ctx->enc) {
560 fprintf (stream, "->%i", ctx->enc->id);
563 fprintf (stream, "\n");
567 Get a ctx of the given graph info
569 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
571 assert (ginfo->n_ctxs > ctx_idx);
573 return (ginfo->ctxs [ctx_idx]);
577 Get the pseudo-ctx of 'main'
579 ctx_info_t *get_main_ctx ()
585 Set the pseudo-ctx of 'main'
587 void set_main_ctx (ctx_info_t *ctx)
593 /* ====================
595 ==================== */
597 /* ====================
599 ==================== */
601 Iterate over all graphs
603 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
605 graph_info_t *ginfo = graph_infos_list;
607 while (NULL != ginfo) {
608 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
610 if (0 != ginfo->n_ctxs) {
620 Iterate of all allocs of a given graph info
622 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
624 alloc_info_t *ainfo = ginfo->allocs;
626 while (NULL != ainfo) {
635 Iterate over all calls of the given graph info
637 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
639 call_info_t *cinfo = ginfo->calls;
641 while (NULL != cinfo) {
650 Iterate over all callEds of the given call info
652 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
654 callEd_info_t *ced = cinfo->callEds;
656 while (NULL != ced) {
665 get the call infos for the given graph
667 graph_info_t *ecg_get_info (ir_graph *graph)
669 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
671 assert (ginfo && "no info for graph");
677 Get the Alloc Infos for the given graph
679 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
681 graph_info_t *ginfo = ecg_get_info (graph);
683 return (ginfo->allocs);
687 Get the Call Info for the given call
689 callEd_info_t *ecg_get_callEd_info (ir_node *call)
691 ir_graph *graph = get_irn_irg (call);
692 graph_info_t *ginfo = ecg_get_info (graph);
694 call_info_t *call_info = ginfo->calls;
696 while (NULL != call_info) {
697 if (call == call_info->call) {
698 return (call_info->callEds);
701 call_info = call_info->prev;
709 Dump the given graph and it's calls and it's calls callEds to the given file.
711 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
716 const char *name = get_irg_entity (graph) ?
717 get_entity_name (get_irg_entity (graph)) : "noEntity";
719 (get_entity_stickyness
720 (get_irg_entity (graph)) == stickyness_sticky) ?
721 "red" : "lightyellow";
723 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
724 graph_info_t *ginfo = ecg_get_info (graph);
726 if (0 != ginfo->ecg_seen) {
727 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
728 name, (int) ginfo->ecg_seen);
730 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
733 return (ginfo->ecg_seen);
736 assert (0L <= _graphs);
738 graph_no = _graphs ++;
739 ginfo->ecg_seen = graph_no;
741 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
742 get_type_name (get_entity_owner (get_irg_entity (graph))),
744 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
746 get_type_name (get_entity_owner (get_irg_entity (graph))),
752 if (visibility_external_allocated ==
753 get_entity_visibility (get_irg_entity (graph))) {
754 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
759 cinfo = ginfo->calls;
760 while (NULL != cinfo) {
761 ir_node *call = cinfo->call;
762 callEd_info_t *ced = cinfo->callEds;
763 const int call_no = _calls ++;
764 const char *call_color = (NULL == ced) ? "blue" :
765 (NULL == ced->prev) ? "lightblue" : "blue3";
767 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
768 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
769 call_no, get_irn_node_nr (call), call_color);
770 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
772 while (NULL != ced) {
773 ir_graph *callEd_graph = ced->callEd;
774 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
775 const char *callEd_name = get_irg_entity (callEd_graph) ?
776 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
777 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
778 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
780 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
783 /* Check for recursive calls */
784 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
785 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
786 call_no, callEd_no, callEd_color, direction);
791 } /* done all calEds (call) */
794 } /* done all calls (graph) */
797 ainfo = ecg_get_alloc_info (graph);
799 fprintf (dot, "\t/* now the allocs */\n");
801 fprintf (dot, "\t/* no allocs */\n");
804 while (NULL != ainfo) {
805 ir_node *alloc = ainfo->alloc;
806 const char *name = get_type_name (ainfo->tp);
807 const char *color = "red1";
810 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
811 (int) alloc, graph_no, name, color);
813 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
814 graph_no, (int) alloc, graph_no);
819 if (0 == ginfo->allocs_seen) {
820 ginfo->allocs_seen = 1;
823 /* write table of ctxs */
826 const int max_ctxs = 30;
827 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
829 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
831 assert (ginfo->ctxs && "no ctx");
832 for (i = 0; i < n_ctxs; i ++) {
833 ctx_info_t *ctx_info = ginfo->ctxs [i];
835 if (NULL != ctx_info->enc) {
836 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
841 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
850 if (0 < ginfo->n_ctxs - max_ctxs) {
851 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
854 fprintf (dot, "\", color=\"green3\"];\n");
857 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
861 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
870 Count how many nodes the ECG will have
872 static char spaces [BUF_SIZE];
874 static void ecg_ecg_count (ir_graph *graph)
878 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
880 if (0 != ginfo->ecg_seen) {
885 if (_depth > _max_depth) {
889 fprintf (stdout, "_max_depth = %i\n", _max_depth);
890 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
894 assert (0L <= _graphs);
897 if (0 == (_graphs % 1000000)) {
898 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
899 fprintf (stdout, "_depth = %i\n", _depth);
903 graph_no = _graphs ++;
904 ginfo->ecg_seen = graph_no;
906 fprintf (stdout, "%sMethod \"%s.%s\"\n",
907 spaces + BUF_SIZE - _depth,
908 get_type_name (get_entity_owner (get_irg_entity (graph))),
909 get_entity_name (get_irg_entity (graph)));
911 cinfo = ginfo->calls;
912 while (NULL != cinfo) {
914 callEd_info_t *ced = cinfo->callEds;
916 fprintf (stdout, "%sCall \"0x%08x\"\n",
917 spaces + BUF_SIZE - _depth,
920 while (NULL != ced) {
921 ir_graph *callEd_graph = ced->callEd;
923 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
924 spaces + BUF_SIZE - _depth,
925 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
926 get_entity_name (get_irg_entity (callEd_graph)));
928 ecg_ecg_count (callEd_graph);
931 } /* done all calEds (call) */
933 } /* done all calls (graph) */
939 /* ====================
941 ==================== */
944 Initialise our data structures.
946 void ecg_init (int typalise)
948 do_typalise = typalise;
950 graph_infos = pmap_create ();
960 void ecg_cleanup (void)
966 for (i = 0; i < get_irp_n_irgs (); i++) {
967 ir_graph *graph = get_irp_irg (i);
969 graph_info_t *info = pmap_get (graph_infos, graph);
970 call_info_t *cinfo = info->calls;
972 while (NULL != cinfo) {
973 callEd_info_t *ced = cinfo->callEds;
977 while (NULL != ced) {
978 callEd_info_t *nced = ced->prev;
985 cinfo->callEds = NULL;
992 pmap_insert (graph_infos, graph, NULL);
996 pmap_destroy (graph_infos);
1003 Show what we have found.
1009 FILE *dot = fopen ("calls.dot", "w");
1011 fprintf (dot, "digraph \"calls\" {\n");
1012 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1013 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1014 fprintf (dot, "\tedge [color=\"black\"];\n");
1015 fprintf (dot, "\n");
1017 for (i = 0; i < get_irp_n_irgs (); i++) {
1018 ir_graph *graph = get_irp_irg (i);
1019 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
1021 if (0 != ginfo->n_ctxs) {
1023 alloc_info_t *ainfo;
1025 const char *name = get_irg_entity (graph) ?
1026 get_entity_name (get_irg_entity (graph)) : "noEntity";
1028 const char *oname = get_type_name
1029 (get_entity_owner (get_irg_entity (graph)));
1032 (get_entity_stickyness
1033 (get_irg_entity (graph)) == stickyness_sticky) ?
1034 "red3" : "lightyellow";
1036 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1038 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1039 (int) graph, oname, name, color);
1040 fprintf (dot, "\n");
1042 cinfo = ginfo->calls;
1044 fprintf (dot, "\t/* now the calls */\n");
1046 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1049 while (NULL != cinfo) {
1051 ir_node *call = cinfo->call;
1053 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1054 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\", shape=\"ellipse\", color=\"lightblue\"];\n",
1055 (int) call, get_irn_node_nr (call));
1056 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1057 (int) graph, (int) call);
1059 ced = cinfo->callEds;
1060 while (NULL != ced) {
1061 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1062 (int) call, (int) ced->callEd);
1065 fprintf (dot, "\n");
1067 cinfo = cinfo->prev;
1069 fprintf (dot, "\n");
1071 ainfo = ginfo->allocs;
1073 fprintf (dot, "\t/* now the allocs */\n");
1075 fprintf (dot, "\t/* no allocs */\n");
1079 while (NULL != ainfo) {
1080 ir_node *alloc = ainfo->alloc;
1081 const char *name = get_type_name (ainfo->tp);
1082 const char *color = "red1";
1084 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1085 (int) alloc, name, color);
1086 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1087 (int) graph, (int) alloc);
1089 ainfo = ainfo->prev;
1095 const int max_ctxs = 30;
1096 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
1098 fprintf (dot, "\t/* now the ctxs */\n");
1099 fprintf (dot, "\tctx_0x%08x [label=\"<HEAD>", (int) graph);
1101 assert (ginfo->ctxs && "no ctx");
1102 for (i = 0; i < n_ctxs; i ++) {
1103 ctx_info_t *ctx_info = ginfo->ctxs [i];
1105 if (NULL != ctx_info->enc) {
1106 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
1111 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
1115 if (i+1 != n_ctxs) {
1120 if (0 < ginfo->n_ctxs - max_ctxs) {
1121 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
1124 fprintf (dot, "\", color=\"green3\"];\n");
1127 "\tgraph_0x%08x -> ctx_0x%08x:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
1128 (int) graph, (int) graph);
1131 fprintf (dot, "\t/* graph is not called */\n");
1132 } /* end all graphs */
1134 fprintf (dot, "}\n");
1137 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1138 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1139 get_entity_name (_max_callEds_callR));
1145 Experimental: Print the ecg
1150 ir_graph *main_graph = get_irp_main_irg ();
1156 memset (spaces, '.', BUF_SIZE);
1157 spaces [BUF_SIZE-1] = '\0';
1159 ecg_ecg_count (main_graph);
1160 fprintf (stdout, "n_graphs: %i\n", _graphs);
1161 fprintf (stdout, "max_depth = %i\n", _max_depth);
1169 dot = fopen ("ecg.dot", "w");
1171 fprintf (dot, "digraph \"ecg\" {\n");
1172 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1173 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1174 fprintf (dot, "\tedge [color=\"black\"];\n");
1175 fprintf (dot, "\n");
1176 fprintf (dot, "\n");
1178 /* ir_graph *main_graph = get_irp_main_irg (); */
1179 ecg_ecg_graph (dot, main_graph);
1181 fprintf (dot, "\t/* Grand Total: */\n");
1182 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1183 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1184 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1185 fprintf (dot, "\t/* (sales tax not included) */\n");
1187 fprintf (dot, "}\n");
1196 Revision 1.17 2005/01/14 13:34:25 liekweg
1197 Factor out call_info_t ctor; fix mallocs; fix initialisation
1199 Revision 1.16 2005/01/10 17:26:34 liekweg
1200 fixup printfs, don't put environments on the stack
1202 Revision 1.15 2004/12/23 15:40:03 beck
1205 Revision 1.14 2004/12/22 14:43:14 beck
1206 made allocations C-like
1208 Revision 1.13 2004/12/21 14:21:16 beck
1209 removed C99 constructs
1211 Revision 1.12 2004/12/20 17:34:34 liekweg
1212 fix recursion handling
1214 Revision 1.11 2004/12/15 09:18:18 liekweg
1217 Revision 1.10 2004/12/06 12:55:06 liekweg
1220 Revision 1.9 2004/12/02 16:17:50 beck
1221 fixed config.h include
1223 Revision 1.8 2004/11/30 14:45:44 liekweg
1224 fix graph dumping, remove 'HERE's
1226 Revision 1.7 2004/11/26 16:01:56 liekweg
1227 debugging annotations
1229 Revision 1.6 2004/11/24 14:53:55 liekweg
1232 Revision 1.5 2004/11/20 21:20:29 liekweg
1233 Added iterator functions
1235 Revision 1.4 2004/11/18 16:36:37 liekweg
1236 Added unique ids for debugging, added access functions
1238 Revision 1.3 2004/11/04 14:54:44 liekweg
1241 Revision 1.2 2004/10/21 11:09:37 liekweg
1242 Moved memwalk stuf into irmemwalk
1243 Moved lset stuff into lset
1244 Moved typalise stuff into typalise
1246 Revision 1.1 2004/10/20 14:59:41 liekweg
1247 Added ana2, added ecg and pto
1249 Revision 1.6 2004/10/18 12:47:19 liekweg
1252 Revision 1.5 2004/10/14 11:31:28 liekweg
1255 Revision 1.4 2004/10/12 11:02:01 liekweg