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"
45 # define HERE(msg) fprintf (stdout, "%s:%i %s\n", __FUNCTION__, __LINE__, msg)
50 /* static int verbose = 0; */
51 static int do_typalise = 0;
57 /* Ids for the ctxs */
58 static int ctx_id = 0;
59 ctx_info_t *main_ctx = NULL;
61 /* mapping from method graphs (callR) to method graphs (lset_ts of callEds) */
62 /* static pmap *calls; */
63 static pmap *graph_infos;
65 /* linked list of all graph_infos: */
66 static graph_info_t *graph_infos_list = NULL;
68 /* Counters for ecg_ecg and friends */
69 static long _graphs = 0;
70 static long _calls = 0;
71 static long _allocs = 0;
73 static int _depth = 0;
74 static int _max_depth = 0;
76 static int _max_callEds = 0;
77 static entity* _max_callEds_callR = NULL;
80 void set_main_ctx (ctx_info_t*);
82 /* ====================
84 ==================== */
85 static void append_alloc (graph_info_t *ginfo, ir_node *alloc, type *tp)
87 alloc_info_t *ainfo = xmalloc (sizeof (alloc_info_t));
89 ainfo->graph = ginfo->graph;
93 ainfo->prev = ginfo->allocs;
94 ginfo->allocs = ainfo;
98 /* ====================
100 ==================== */
102 Create a new call info struct from the given values.
104 static call_info_t *new_call_info (ir_node *call,
105 callEd_info_t *callEds,
108 call_info_t *cinfo = xmalloc (sizeof (call_info_t));
110 cinfo->callEds = callEds;
117 Append the given callEd to the given callEd info.
119 static callEd_info_t *append_callEd_info (callEd_info_t *ced, ir_graph *callEd)
121 callEd_info_t *nced = xmalloc (sizeof (callEd_info_t));
123 assert (NULL != callEd);
125 nced->callEd = callEd;
132 Append all callEd methods of the given (call) node to the given graph_info.
134 static void append_calls (graph_info_t *info, ir_node *call, lset_t *callEds)
136 ir_graph *callEd = NULL;
137 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
142 callEd = lset_first (callEds);
144 while (NULL != callEd) {
145 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
146 callEd = lset_next(callEds);
152 Append the (single) callEd to the given (call) node of the given graph_info.
154 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
156 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
160 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
164 Given a method, find the firm graph that implements that method.
165 Return NULL for abstract and native methods.
167 static ir_graph *_get_implementing_graph (entity *method)
169 ir_graph *graph = NULL;
171 /* What's up with the fenced out stuff in rta? */
172 if (peculiarity_existent == get_entity_peculiarity (method)) {
173 if (visibility_external_allocated == get_entity_visibility (method)) {
174 /* Todo: native implementation */
178 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
179 assert (graph && "no graph");
183 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
184 /* abstract --- can't find an implementation */
185 graph = get_entity_irg (method);
186 assert (!graph && "graph in abstract method");
189 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
190 (peculiarity_inherited == get_entity_peculiarity (method))) {
193 int n_over = get_entity_n_overwrites (method);
197 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
198 entity *over = get_entity_overwrites (method, i);
200 graph = _get_implementing_graph (over);
203 assert (0 && "invalid peculiarity");
211 Collect all graphs of 'method' in the given set.
213 static void _collect_implementing_graphs (entity *method, lset_t *set)
215 /* search DOWN-wards in clazz hierarchy */
217 int n_over = get_entity_n_overwrittenby (method);
218 ir_graph *graph = get_entity_irg (method);
221 graph = _get_implementing_graph (method);
225 lset_insert (set, graph);
228 for (i = 0; i < n_over; i ++) {
229 entity *over = get_entity_overwrittenby (method, i);
231 _collect_implementing_graphs (over, set);
237 Collect all graphs that could possibly be executed when 'method' is called.
239 static lset_t *get_implementing_graphs (entity *method, ir_node *select)
241 /* const char *name = get_entity_name (method); */
242 /* fprintf (stdout, "%s (ent %s)\n", __FUNCTION__, name); */
245 lset_t *set = lset_create ();
247 ir_graph *impl = _get_implementing_graph (method);
250 lset_insert (set, impl);
252 /* actually, abstract OR native */
256 _collect_implementing_graphs (method, set);
258 if (lset_empty (set)) {
259 /* then it's a method which is only implemented natively, and we
260 don' bother to analyse anything */
264 /* void *tmp = lset_first (set); */
265 n_graphs = lset_n_entries (set);
268 if (visibility_external_allocated != get_entity_visibility (method)) {
270 ir_graph *graph = get_irn_irg (select);
272 dump_ir_block_graph (graph, "-typealise");
274 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
275 assert (n_graphs && "no graphs for method");
278 /* typalise select_in */
280 ir_node *select_in = get_Sel_ptr (select);
281 typalise_t *ta = typalise (select_in);
282 /* assert (ta && "typalise failed (go figure)"); */
285 fprintf (stdout, "typalyse res = ");
288 if (type_invalid == ta->kind) {
289 fprintf (stdout, "invalid");
290 } else if (type_exact == ta->kind) {
291 const char *name = get_type_name (ta->res.type);
293 fprintf (stdout, "exact [");
294 fprintf (stdout, "%s", name);
295 fprintf (stdout, "]\n");
296 } else if (type_types == ta->kind) {
297 fprintf (stdout, "types [");
298 fprintf (stdout, "...");
299 fprintf (stdout, "]\n");
300 } else if (type_type == ta->kind) {
301 const char *name = get_type_name (ta->res.type);
302 fprintf (stdout, "type [");
303 fprintf (stdout, "%s", name);
304 fprintf (stdout, "]\n");
307 fprintf (stdout, "(null)\n");
312 int n_filtered_graphs;
314 set = filter_for_ta (set, ta);
315 n_filtered_graphs = lset_n_entries (set);
318 fprintf (stdout, "%s: %02d %02d\n",
322 n_graphs - n_filtered_graphs);
324 n_graphs = n_filtered_graphs;
327 if (visibility_external_allocated != get_entity_visibility (method)) {
329 ir_graph *graph = get_irn_irg (select);
331 dump_ir_block_graph (graph, "-ecg");
332 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
333 assert (n_graphs && "no graphs for method");
339 if (n_graphs > _max_callEds) {
340 _max_callEds = n_graphs;
341 _max_callEds_callR = method;
349 Determine whether a call is actually a call or if it is being
350 abused for some b/d-ed reason.
352 static int call_is_call (ir_node *call, ir_node *ptr)
354 if (op_SymConst != get_irn_op (ptr)) {
356 } else if (get_SymConst_kind (ptr) != symconst_addr_name) {
364 Action for the graph.
366 static void ecg_calls_act (ir_node *node, void *env)
368 ir_op *op = get_irn_op(node);
369 graph_info_t *graph_info = (graph_info_t*) env;
371 if (op_Call == op) { /* CALL */
373 ir_node *ptr = get_Call_ptr (node);
375 if (!call_is_call (node, ptr)) {
377 fprintf (stdout, "not a call: %s[%li]\n",
378 get_op_name (get_irn_op (node)),
379 get_irn_node_nr (node)); */
384 if (op_Sel == get_irn_op (ptr)) {
386 ent = get_Sel_entity (ptr);
387 graphs = get_implementing_graphs (ent, ptr);
389 append_calls (graph_info, node, graphs);
390 } else if (op_SymConst == get_irn_op (ptr)) {
391 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
393 ent = get_SymConst_entity (ptr);
394 graph = get_entity_irg (ent);
397 append_call (graph_info, node, graph);
399 /* it's an externally allocated thingy */
401 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
402 /* If this SymConst refers to a method the method is external_visible
403 and therefore must be considered live anyways. */
404 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
405 assert (ent && "couldn't determine entity of call to symConst");
408 /* other symconst. */
409 assert (0 && "This SymConst can not be an address for a method call.");
412 /* STRANGE, no less ... */
415 assert (0 && "Unexpected address expression");
417 } else if (op_Alloc == op) {
418 type *tp = get_Alloc_type (node);
419 /* const char *name = get_type_name (tp); */
421 append_alloc (graph_info, node, tp);
423 /* fprintf (stdout, "NEW \"%s\"\n", name); */
428 Collect called graphs for the given graph.
430 static void ecg_fill_graph_calls (ir_graph *graph)
432 graph_info_t *ginfo = xmalloc (sizeof (graph_info_t));
434 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
435 assert (ginfo != graph_infos_list);
437 ginfo->graph = graph;
439 ginfo->allocs = NULL;
443 ginfo->allocs_seen = 0;
446 /* link up into global list */
447 ginfo->prev = graph_infos_list;
448 graph_infos_list = ginfo;
450 assert (ginfo != ginfo->prev);
452 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
454 pmap_insert (graph_infos, graph, ginfo);
458 For each graph, collect called graphs, and enter them into calls.
460 static void ecg_fill_calls (void)
464 for (i = 0; i < get_irp_n_irgs (); i++) {
465 ir_graph *graph = get_irp_irg (i);
467 ecg_fill_graph_calls (graph);
472 Allocate a new ctx for the given graph and the given enclosing ctx.
474 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
476 ctx_info_t *res = xmalloc (sizeof (ctx_info_t));
488 Fill in the ctxs parts of the graph_infos
490 static void ecg_fill_ctxs_count (ir_graph *graph)
492 graph_info_t *ginfo = ecg_get_info (graph);
494 /* count how many ctxs we have per graph */
495 if (0 == ginfo->ecg_seen) {
496 call_info_t *cinfo = ginfo->calls;
500 while (NULL != cinfo) {
501 callEd_info_t *ced = cinfo->callEds;
503 while (NULL != ced) {
504 ir_graph *callEd_graph = ced->callEd;
506 /* first step: we have a new ctx */
507 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
508 callEd_info->n_ctxs ++;
510 /* CallR graph -> CallEd_graph */
511 ecg_fill_ctxs_count (callEd_graph);
514 } /* end forall callEds (call) */
517 } /* end forall (calls(graph)) */
523 static void ecg_fill_ctxs_alloc (void)
525 /* allocate the memory needed for the ctxts: */
526 graph_info_t *ginfo = graph_infos_list;
528 while (NULL != ginfo) {
529 ginfo->ctxs = xcalloc (ginfo->n_ctxs, sizeof (ctx_info_t *));
532 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
533 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
537 assert (ginfo != ginfo->prev);
543 Fill in the ctxs parts of the graph_infos
545 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
547 graph_info_t *ginfo = ecg_get_info (graph);
549 /* enter a new ctx for all callEds along the call edges of this graph */
550 if (0 == ginfo->ecg_seen) {
551 call_info_t *cinfo = ginfo->calls;
554 while (NULL != cinfo) {
555 callEd_info_t *ced = cinfo->callEds;
557 while (NULL != ced) {
558 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
560 ir_graph *callEd_graph = ced->callEd;
562 /* write the ctx of this call into the callEd graph */
563 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
565 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
566 callEd_info->n_ctxs ++;
568 /* CallR graph -> callEd_graph */
569 ecg_fill_ctxs_write (callEd_graph, ctx);
572 } /* end forall callEds (call) */
575 } /* end forall (calls(graph)) */
582 Fill in the ctxs parts of the graph_infos
584 static void ecg_fill_ctxs (void)
586 ctx_info_t *main_ctx;
590 ecg_fill_ctxs_count (get_irp_main_irg ());
591 ecg_fill_ctxs_alloc ();
593 main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
594 main_irg = get_irp_main_irg ();
596 set_main_ctx (main_ctx);
598 /* Grrr, have to add this ctx manually to main.ginfo ... */
599 ginfo = ecg_get_info (main_irg);
601 ginfo->ctxs = xcalloc (1, sizeof (ctx_info_t *));
602 ginfo->ctxs [0] = main_ctx;
604 ecg_fill_ctxs_write (main_irg, main_ctx);
607 /* ====================
609 ==================== */
611 Nicely print a ctx_info_t to the given output stream
613 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
615 entity *ent = get_irg_entity(ctx->graph);
616 ir_node *call = ctx->call;
617 const char *ent_name = get_entity_name (ent);
618 const char *own_name = get_type_name (get_entity_owner (ent));
620 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
621 ctx->id, own_name, ent_name,
622 get_op_name (get_irn_op (call)),
623 get_irn_node_nr (call));
625 if (NULL != ctx->enc) {
626 fprintf (stream, "->%i", ctx->enc->id);
629 fprintf (stream, "\n");
633 Get a ctx of the given graph info
635 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
637 assert (ginfo->n_ctxs > ctx_idx);
639 return (ginfo->ctxs [ctx_idx]);
643 Get the pseudo-ctx of 'main'
645 ctx_info_t *get_main_ctx ()
651 Set the pseudo-ctx of 'main'
653 void set_main_ctx (ctx_info_t *ctx)
659 /* ====================
661 ==================== */
663 /* ====================
665 ==================== */
667 Iterate over all graphs
669 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
671 graph_info_t *ginfo = graph_infos_list;
673 while (NULL != ginfo) {
674 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
676 if (0 != ginfo->n_ctxs) {
686 Iterate of all allocs of a given graph info
688 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
690 alloc_info_t *ainfo = ginfo->allocs;
692 while (NULL != ainfo) {
701 Iterate over all calls of the given graph info
703 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
705 call_info_t *cinfo = ginfo->calls;
707 while (NULL != cinfo) {
716 Iterate over all callEds of the given call info
718 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
720 callEd_info_t *ced = cinfo->callEds;
722 while (NULL != ced) {
731 get the call infos for the given graph
733 graph_info_t *ecg_get_info (ir_graph *graph)
735 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
737 assert (ginfo && "no info for graph");
743 Get the Alloc Infos for the given graph
745 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
747 graph_info_t *ginfo = ecg_get_info (graph);
749 return (ginfo->allocs);
753 Get the Call Info for the given call
755 callEd_info_t *ecg_get_callEd_info (ir_node *call)
757 ir_graph *graph = get_irn_irg (call);
758 graph_info_t *ginfo = ecg_get_info (graph);
760 call_info_t *call_info = ginfo->calls;
762 while (NULL != call_info) {
763 if (call == call_info->call) {
764 return (call_info->callEds);
767 call_info = call_info->prev;
775 Dump the given graph and it's calls and it's calls callEds to the given file.
777 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
782 const char *name = get_irg_entity (graph) ?
783 get_entity_name (get_irg_entity (graph)) : "noEntity";
785 (get_entity_stickyness
786 (get_irg_entity (graph)) == stickyness_sticky) ?
787 "red" : "lightyellow";
789 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
790 graph_info_t *ginfo = ecg_get_info (graph);
792 if (0 != ginfo->ecg_seen) {
793 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
794 name, (int) ginfo->ecg_seen);
796 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
799 return (ginfo->ecg_seen);
802 assert (0L <= _graphs);
804 graph_no = _graphs ++;
805 ginfo->ecg_seen = graph_no;
807 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
808 get_type_name (get_entity_owner (get_irg_entity (graph))),
810 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
812 get_type_name (get_entity_owner (get_irg_entity (graph))),
818 if (visibility_external_allocated ==
819 get_entity_visibility (get_irg_entity (graph))) {
820 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
825 cinfo = ginfo->calls;
826 while (NULL != cinfo) {
827 ir_node *call = cinfo->call;
828 callEd_info_t *ced = cinfo->callEds;
829 const int call_no = _calls ++;
830 const char *call_color = (NULL == ced) ? "blue" :
831 (NULL == ced->prev) ? "lightblue" : "blue3";
833 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
834 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
835 call_no, get_irn_node_nr (call), call_color);
836 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
838 while (NULL != ced) {
839 ir_graph *callEd_graph = ced->callEd;
840 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
841 const char *callEd_name = get_irg_entity (callEd_graph) ?
842 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
843 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
844 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
846 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
849 /* Check for recursive calls */
850 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
851 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
852 call_no, callEd_no, callEd_color, direction);
857 } /* done all calEds (call) */
860 } /* done all calls (graph) */
863 ainfo = ecg_get_alloc_info (graph);
865 fprintf (dot, "\t/* now the allocs */\n");
867 fprintf (dot, "\t/* no allocs */\n");
870 while (NULL != ainfo) {
871 ir_node *alloc = ainfo->alloc;
872 const char *name = get_type_name (ainfo->tp);
873 const char *color = "red1";
876 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
877 (int) alloc, graph_no, name, color);
879 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
880 graph_no, (int) alloc, graph_no);
885 if (0 == ginfo->allocs_seen) {
886 ginfo->allocs_seen = 1;
889 /* write table of ctxs */
892 const int max_ctxs = 30;
893 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
895 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
897 assert (ginfo->ctxs && "no ctx");
898 for (i = 0; i < n_ctxs; i ++) {
899 ctx_info_t *ctx_info = ginfo->ctxs [i];
901 if (NULL != ctx_info->enc) {
902 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
907 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
916 if (0 < ginfo->n_ctxs - max_ctxs) {
917 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
920 fprintf (dot, "\", color=\"green3\"];\n");
923 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
927 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
936 Count how many nodes the ECG will have
938 static char spaces [BUF_SIZE];
940 static void ecg_ecg_count (ir_graph *graph)
944 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
946 if (0 != ginfo->ecg_seen) {
951 if (_depth > _max_depth) {
955 fprintf (stdout, "_max_depth = %i\n", _max_depth);
956 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
960 assert (0L <= _graphs);
963 if (0 == (_graphs % 1000000)) {
964 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
965 fprintf (stdout, "_depth = %i\n", _depth);
969 graph_no = _graphs ++;
970 ginfo->ecg_seen = graph_no;
972 fprintf (stdout, "%sMethod \"%s.%s\"\n",
973 spaces + BUF_SIZE - _depth,
974 get_type_name (get_entity_owner (get_irg_entity (graph))),
975 get_entity_name (get_irg_entity (graph)));
977 cinfo = ginfo->calls;
978 while (NULL != cinfo) {
980 callEd_info_t *ced = cinfo->callEds;
982 fprintf (stdout, "%sCall \"0x%08x\"\n",
983 spaces + BUF_SIZE - _depth,
986 while (NULL != ced) {
987 ir_graph *callEd_graph = ced->callEd;
989 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
990 spaces + BUF_SIZE - _depth,
991 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
992 get_entity_name (get_irg_entity (callEd_graph)));
994 ecg_ecg_count (callEd_graph);
997 } /* done all calEds (call) */
999 } /* done all calls (graph) */
1001 ginfo->ecg_seen = 0;
1005 /* ====================
1007 ==================== */
1010 Initialise our data structures.
1012 void ecg_init (int typalise)
1014 do_typalise = typalise;
1020 graph_infos = pmap_create ();
1030 void ecg_cleanup (void)
1036 for (i = 0; i < get_irp_n_irgs (); i++) {
1037 ir_graph *graph = get_irp_irg (i);
1039 graph_info_t *info = pmap_get (graph_infos, graph);
1040 call_info_t *cinfo = info->calls;
1042 while (NULL != cinfo) {
1043 callEd_info_t *ced = cinfo->callEds;
1047 while (NULL != ced) {
1048 callEd_info_t *nced = ced->prev;
1055 cinfo->callEds = NULL;
1058 cinfo = cinfo->prev;
1062 pmap_insert (graph_infos, graph, NULL);
1066 pmap_destroy (graph_infos);
1073 Show what we have found.
1079 FILE *dot = fopen ("calls.dot", "w");
1081 fprintf (dot, "digraph \"calls\" {\n");
1082 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1083 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1084 fprintf (dot, "\tedge [color=\"black\"];\n");
1085 fprintf (dot, "\n");
1087 for (i = 0; i < get_irp_n_irgs (); i++) {
1088 ir_graph *graph = get_irp_irg (i);
1089 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
1091 if (0 != ginfo->n_ctxs) {
1093 alloc_info_t *ainfo;
1095 const char *name = get_irg_entity (graph) ?
1096 get_entity_name (get_irg_entity (graph)) : "noEntity";
1098 const char *oname = get_type_name
1099 (get_entity_owner (get_irg_entity (graph)));
1102 (get_entity_stickyness
1103 (get_irg_entity (graph)) == stickyness_sticky) ?
1104 "red3" : "lightyellow";
1106 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1108 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1109 (int) graph, oname, name, color);
1110 fprintf (dot, "\n");
1112 cinfo = ginfo->calls;
1114 fprintf (dot, "\t/* now the calls */\n");
1116 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1119 while (NULL != cinfo) {
1121 ir_node *call = cinfo->call;
1123 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1124 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\", shape=\"ellipse\", color=\"lightblue\"];\n",
1125 (int) call, get_irn_node_nr (call));
1126 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1127 (int) graph, (int) call);
1129 ced = cinfo->callEds;
1130 while (NULL != ced) {
1131 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1132 (int) call, (int) ced->callEd);
1135 fprintf (dot, "\n");
1137 cinfo = cinfo->prev;
1139 fprintf (dot, "\n");
1141 ainfo = ginfo->allocs;
1143 fprintf (dot, "\t/* now the allocs */\n");
1145 fprintf (dot, "\t/* no allocs */\n");
1149 while (NULL != ainfo) {
1150 ir_node *alloc = ainfo->alloc;
1151 const char *name = get_type_name (ainfo->tp);
1152 const char *color = "red1";
1154 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1155 (int) alloc, name, color);
1156 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1157 (int) graph, (int) alloc);
1159 ainfo = ainfo->prev;
1165 const int max_ctxs = 30;
1166 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
1168 fprintf (dot, "\t/* now the ctxs */\n");
1169 fprintf (dot, "\tctx_0x%08x [label=\"<HEAD>", (int) graph);
1171 assert (ginfo->ctxs && "no ctx");
1172 for (i = 0; i < n_ctxs; i ++) {
1173 ctx_info_t *ctx_info = ginfo->ctxs [i];
1175 if (NULL != ctx_info->enc) {
1176 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
1181 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
1185 if (i+1 != n_ctxs) {
1190 if (0 < ginfo->n_ctxs - max_ctxs) {
1191 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
1194 fprintf (dot, "\", color=\"green3\"];\n");
1197 "\tgraph_0x%08x -> ctx_0x%08x:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
1198 (int) graph, (int) graph);
1201 fprintf (dot, "\t/* graph is not called */\n");
1202 } /* end all graphs */
1204 fprintf (dot, "}\n");
1207 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1208 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1209 get_entity_name (_max_callEds_callR));
1215 Experimental: Print the ecg
1220 ir_graph *main_graph = get_irp_main_irg ();
1226 memset (spaces, '.', BUF_SIZE);
1227 spaces [BUF_SIZE-1] = '\0';
1229 ecg_ecg_count (main_graph);
1230 fprintf (stdout, "n_graphs: %i\n", _graphs);
1231 fprintf (stdout, "max_depth = %i\n", _max_depth);
1239 dot = fopen ("ecg.dot", "w");
1241 fprintf (dot, "digraph \"ecg\" {\n");
1242 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1243 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1244 fprintf (dot, "\tedge [color=\"black\"];\n");
1245 fprintf (dot, "\n");
1246 fprintf (dot, "\n");
1248 /* ir_graph *main_graph = get_irp_main_irg (); */
1249 ecg_ecg_graph (dot, main_graph);
1251 fprintf (dot, "\t/* Grand Total: */\n");
1252 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1253 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1254 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1255 fprintf (dot, "\t/* (sales tax not included) */\n");
1257 fprintf (dot, "}\n");
1266 Revision 1.19 2005/03/22 13:55:51 liekweg
1267 Need to initialise typalise now
1269 Revision 1.18 2005/01/14 14:14:43 liekweg
1272 Revision 1.17 2005/01/14 13:34:25 liekweg
1273 Factor out call_info_t ctor; fix mallocs; fix initialisation
1275 Revision 1.16 2005/01/10 17:26:34 liekweg
1276 fixup printfs, don't put environments on the stack
1278 Revision 1.15 2004/12/23 15:40:03 beck
1281 Revision 1.14 2004/12/22 14:43:14 beck
1282 made allocations C-like
1284 Revision 1.13 2004/12/21 14:21:16 beck
1285 removed C99 constructs
1287 Revision 1.12 2004/12/20 17:34:34 liekweg
1288 fix recursion handling
1290 Revision 1.11 2004/12/15 09:18:18 liekweg
1293 Revision 1.10 2004/12/06 12:55:06 liekweg
1296 Revision 1.9 2004/12/02 16:17:50 beck
1297 fixed config.h include
1299 Revision 1.8 2004/11/30 14:45:44 liekweg
1300 fix graph dumping, remove 'HERE's
1302 Revision 1.7 2004/11/26 16:01:56 liekweg
1303 debugging annotations
1305 Revision 1.6 2004/11/24 14:53:55 liekweg
1308 Revision 1.5 2004/11/20 21:20:29 liekweg
1309 Added iterator functions
1311 Revision 1.4 2004/11/18 16:36:37 liekweg
1312 Added unique ids for debugging, added access functions
1314 Revision 1.3 2004/11/04 14:54:44 liekweg
1317 Revision 1.2 2004/10/21 11:09:37 liekweg
1318 Moved memwalk stuf into irmemwalk
1319 Moved lset stuff into lset
1320 Moved typalise stuff into typalise
1322 Revision 1.1 2004/10/20 14:59:41 liekweg
1323 Added ana2, added ecg and pto
1325 Revision 1.6 2004/10/18 12:47:19 liekweg
1328 Revision 1.5 2004/10/14 11:31:28 liekweg
1331 Revision 1.4 2004/10/12 11:02:01 liekweg