4 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
6 * This file is part of libFirm.
8 * This file may be distributed and/or modified under the terms of the
9 * GNU General Public License version 2 as published by the Free Software
10 * Foundation and appearing in the file LICENSE.GPL included in the
11 * packaging of this file.
13 * Licensees holding valid libFirm Professional Edition licenses may use
14 * this file in accordance with the libFirm Commercial License.
15 * Agreement provided with the Software.
17 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * @brief Extended Call Graph
36 Erweiterter Aufrufgraph.
41 /* #include "eset.h" */
53 # endif /* not defined TRUE */
55 # define BUF_SIZE 1024
58 # include "typalise.h"
63 # define HERE(msg) fprintf (stdout, "%s:%i %s\n", __FUNCTION__, __LINE__, msg)
68 /* static int verbose = 0; */
69 static int do_typalise = 0;
75 /* Ids for the ctxs */
76 static int ctx_id = 0;
77 ctx_info_t *main_ctx = NULL;
79 /* mapping from method graphs (callR) to method graphs (lset_ts of callEds) */
80 /* static pmap *calls; */
81 static pmap *graph_infos;
83 /* linked list of all graph_infos: */
84 static graph_info_t *graph_infos_list = NULL;
86 /* Counters for ecg_ecg and friends */
87 static long _graphs = 0;
88 static long _calls = 0;
89 static long _allocs = 0;
91 static int _depth = 0;
92 static int _max_depth = 0;
94 static int _max_callEds = 0;
95 static ir_entity* _max_callEds_callR = NULL;
98 void set_main_ctx (ctx_info_t*);
100 /* ====================
102 ==================== */
103 static void append_alloc (graph_info_t *ginfo, ir_node *alloc, ir_type *tp)
105 alloc_info_t *ainfo = xmalloc (sizeof (alloc_info_t));
107 ainfo->graph = ginfo->graph;
108 ainfo->alloc = alloc;
111 ainfo->prev = ginfo->allocs;
112 ginfo->allocs = ainfo;
116 /* ====================
118 ==================== */
120 Create a new call info struct from the given values.
122 static call_info_t *new_call_info (ir_node *call,
123 callEd_info_t *callEds,
126 call_info_t *cinfo = xmalloc (sizeof (call_info_t));
128 cinfo->callEds = callEds;
135 Append the given callEd to the given callEd info.
137 static callEd_info_t *append_callEd_info (callEd_info_t *ced, ir_graph *callEd)
139 callEd_info_t *nced = xmalloc (sizeof (callEd_info_t));
141 assert (NULL != callEd);
143 nced->callEd = callEd;
150 Append all callEd methods of the given (call) node to the given graph_info.
152 static void append_calls (graph_info_t *info, ir_node *call, lset_t *callEds)
154 ir_graph *callEd = NULL;
155 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
160 callEd = lset_first (callEds);
162 while (NULL != callEd) {
163 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
164 callEd = lset_next(callEds);
170 Append the (single) callEd to the given (call) node of the given graph_info.
172 static void append_call (graph_info_t *info, ir_node *call, ir_graph *callEd)
174 call_info_t *cinfo = new_call_info (call, NULL, info->calls);
178 cinfo->callEds = append_callEd_info (cinfo->callEds, callEd);
182 Given a method, find the firm graph that implements that method.
183 Return NULL for abstract and native methods.
185 static ir_graph *_get_implementing_graph (ir_entity *method)
187 ir_graph *graph = NULL;
189 /* What's up with the fenced out stuff in rta? */
190 if (peculiarity_existent == get_entity_peculiarity (method)) {
191 if (visibility_external_allocated == get_entity_visibility (method)) {
192 /* Todo: native implementation */
196 graph = get_entity_irg (get_SymConst_entity (get_atomic_ent_value (method)));
197 assert (graph && "no graph");
201 } else if (0 && (peculiarity_description == get_entity_peculiarity (method))) {
202 /* abstract --- can't find an implementation */
203 graph = get_entity_irg (method);
204 assert (!graph && "graph in abstract method");
207 } else if ((peculiarity_description == get_entity_peculiarity (method)) ||
208 (peculiarity_inherited == get_entity_peculiarity (method))) {
211 int n_over = get_entity_n_overwrites (method);
215 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
216 ir_entity *over = get_entity_overwrites (method, i);
218 graph = _get_implementing_graph (over);
221 assert (0 && "invalid peculiarity");
229 Collect all graphs of 'method' in the given set.
231 static void _collect_implementing_graphs (ir_entity *method, lset_t *set)
233 /* search DOWN-wards in clazz hierarchy */
235 int n_over = get_entity_n_overwrittenby (method);
236 ir_graph *graph = get_entity_irg (method);
239 graph = _get_implementing_graph (method);
243 lset_insert (set, graph);
246 for (i = 0; i < n_over; i ++) {
247 ir_entity *over = get_entity_overwrittenby (method, i);
249 _collect_implementing_graphs (over, set);
255 Collect all graphs that could possibly be executed when 'method' is called.
257 static lset_t *get_implementing_graphs (ir_entity *method, ir_node *select)
259 /* const char *name = get_entity_name (method); */
260 /* fprintf (stdout, "%s (ent %s)\n", __FUNCTION__, name); */
263 lset_t *set = lset_create ();
265 ir_graph *impl = _get_implementing_graph (method);
268 lset_insert (set, impl);
270 /* actually, abstract OR native */
274 _collect_implementing_graphs (method, set);
276 if (lset_empty (set)) {
277 /* then it's a method which is only implemented natively, and we
278 don' bother to analyse anything */
282 /* void *tmp = lset_first (set); */
283 n_graphs = lset_n_entries (set);
286 if (visibility_external_allocated != get_entity_visibility (method)) {
288 ir_graph *graph = get_irn_irg (select);
290 dump_ir_block_graph (graph, "-typealise");
292 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
293 assert (n_graphs && "no graphs for method");
296 /* typalise select_in */
298 ir_node *select_in = get_Sel_ptr (select);
299 typalise_t *ta = typalise (select_in);
300 /* assert (ta && "typalise failed (go figure)"); */
303 fprintf (stdout, "typalyse res = ");
306 if (type_invalid == ta->kind) {
307 fprintf (stdout, "invalid");
308 } else if (type_exact == ta->kind) {
309 const char *name = get_type_name (ta->res.type);
311 fprintf (stdout, "exact [");
312 fprintf (stdout, "%s", name);
313 fprintf (stdout, "]\n");
314 } else if (type_types == ta->kind) {
315 fprintf (stdout, "types [");
316 fprintf (stdout, "...");
317 fprintf (stdout, "]\n");
318 } else if (type_type == ta->kind) {
319 const char *name = get_type_name (ta->res.type);
320 fprintf (stdout, "type [");
321 fprintf (stdout, "%s", name);
322 fprintf (stdout, "]\n");
325 fprintf (stdout, "(null)\n");
330 int n_filtered_graphs;
332 set = filter_for_ta (set, ta);
333 n_filtered_graphs = lset_n_entries (set);
336 fprintf (stdout, "%s: %02d %02d\n",
340 n_graphs - n_filtered_graphs);
342 n_graphs = n_filtered_graphs;
345 if (visibility_external_allocated != get_entity_visibility (method)) {
347 ir_graph *graph = get_irn_irg (select);
349 dump_ir_block_graph (graph, "-ecg");
350 /* fprintf (stdout, "no graphs for method %s\n", get_entity_name (method)); */
351 assert (n_graphs && "no graphs for method");
357 if (n_graphs > _max_callEds) {
358 _max_callEds = n_graphs;
359 _max_callEds_callR = method;
367 Determine whether a call is actually a call or if it is being
368 abused for some b/d-ed reason.
370 static int call_is_call (ir_node *call, ir_node *ptr)
372 if (op_SymConst != get_irn_op (ptr)) {
374 } else if (get_SymConst_kind (ptr) != symconst_addr_name) {
382 Action for the graph.
384 static void ecg_calls_act (ir_node *node, void *env)
386 ir_op *op = get_irn_op(node);
387 graph_info_t *graph_info = (graph_info_t*) env;
389 if (op_Call == op) { /* CALL */
390 ir_entity *ent = NULL;
391 ir_node *ptr = get_Call_ptr (node);
393 if (!call_is_call (node, ptr)) {
395 fprintf (stdout, "not a call: %s[%li]\n",
396 get_op_name (get_irn_op (node)),
397 get_irn_node_nr (node)); */
402 if (op_Sel == get_irn_op (ptr)) {
404 ent = get_Sel_entity (ptr);
405 graphs = get_implementing_graphs (ent, ptr);
407 append_calls (graph_info, node, graphs);
408 } else if (op_SymConst == get_irn_op (ptr)) {
409 if (get_SymConst_kind (ptr) == symconst_addr_ent) {
411 ent = get_SymConst_entity (ptr);
412 graph = get_entity_irg (ent);
415 append_call (graph_info, node, graph);
417 /* it's an externally allocated thingy */
419 } else if (get_SymConst_kind (ptr) == symconst_addr_name) {
420 /* If this SymConst refers to a method the method is external_visible
421 and therefore must be considered live anyways. */
422 if (get_SymConst_name (ptr) != new_id_from_str ("iro_Catch")) {
423 assert (ent && "couldn't determine entity of call to symConst");
426 /* other symconst. */
427 assert (0 && "This SymConst can not be an address for a method call.");
430 /* STRANGE, no less ... */
433 assert (0 && "Unexpected address expression");
435 } else if (op_Alloc == op) {
436 ir_type *tp = get_Alloc_type (node);
437 /* const char *name = get_type_name (tp); */
439 append_alloc (graph_info, node, tp);
441 /* fprintf (stdout, "NEW \"%s\"\n", name); */
446 Collect called graphs for the given graph.
448 static void ecg_fill_graph_calls (ir_graph *graph)
450 graph_info_t *ginfo = xmalloc (sizeof (graph_info_t));
452 /* memset (ginfo, 0x00, sizeof (graph_info_t)); */
453 assert (ginfo != graph_infos_list);
455 ginfo->graph = graph;
457 ginfo->allocs = NULL;
461 ginfo->allocs_seen = 0;
464 /* link up into global list */
465 ginfo->prev = graph_infos_list;
466 graph_infos_list = ginfo;
468 assert (ginfo != ginfo->prev);
470 irg_walk_graph (graph, ecg_calls_act, NULL, ginfo);
472 pmap_insert (graph_infos, graph, ginfo);
476 For each graph, collect called graphs, and enter them into calls.
478 static void ecg_fill_calls (void)
482 for (i = 0; i < get_irp_n_irgs (); i++) {
483 ir_graph *graph = get_irp_irg (i);
485 ecg_fill_graph_calls (graph);
490 Allocate a new ctx for the given graph and the given enclosing ctx.
492 static ctx_info_t *new_ctx (ir_graph *graph, ir_node *call, ctx_info_t *enc)
494 ctx_info_t *res = xmalloc (sizeof (ctx_info_t));
506 Fill in the ctxs parts of the graph_infos
508 static void ecg_fill_ctxs_count (ir_graph *graph)
510 graph_info_t *ginfo = ecg_get_info (graph);
512 /* count how many ctxs we have per graph */
513 if (0 == ginfo->ecg_seen) {
514 call_info_t *cinfo = ginfo->calls;
518 while (NULL != cinfo) {
519 callEd_info_t *ced = cinfo->callEds;
521 while (NULL != ced) {
522 ir_graph *callEd_graph = ced->callEd;
524 /* first step: we have a new ctx */
525 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
526 callEd_info->n_ctxs ++;
528 /* CallR graph -> CallEd_graph */
529 ecg_fill_ctxs_count (callEd_graph);
532 } /* end forall callEds (call) */
535 } /* end forall (calls(graph)) */
541 static void ecg_fill_ctxs_alloc (void)
543 /* allocate the memory needed for the ctxts: */
544 graph_info_t *ginfo = graph_infos_list;
546 while (NULL != ginfo) {
547 ginfo->ctxs = xcalloc (ginfo->n_ctxs, sizeof (ctx_info_t *));
550 fprintf (stdout, "graph of \"%s\": n_ctxs = %i\n",
551 get_entity_name (get_irg_entity (ginfo->graph)), ginfo->n_ctxs);
555 assert (ginfo != ginfo->prev);
561 Fill in the ctxs parts of the graph_infos
563 static void ecg_fill_ctxs_write (ir_graph *graph, ctx_info_t *enc_ctx)
565 graph_info_t *ginfo = ecg_get_info (graph);
567 /* enter a new ctx for all callEds along the call edges of this graph */
568 if (0 == ginfo->ecg_seen) {
569 call_info_t *cinfo = ginfo->calls;
572 while (NULL != cinfo) {
573 callEd_info_t *ced = cinfo->callEds;
575 while (NULL != ced) {
576 ctx_info_t *ctx = new_ctx (graph, cinfo->call, enc_ctx);
578 ir_graph *callEd_graph = ced->callEd;
580 /* write the ctx of this call into the callEd graph */
581 graph_info_t *callEd_info = ecg_get_info (callEd_graph);
583 callEd_info->ctxs [callEd_info->n_ctxs] = ctx;
584 callEd_info->n_ctxs ++;
586 /* CallR graph -> callEd_graph */
587 ecg_fill_ctxs_write (callEd_graph, ctx);
590 } /* end forall callEds (call) */
593 } /* end forall (calls(graph)) */
600 Fill in the ctxs parts of the graph_infos
602 static void ecg_fill_ctxs (void)
604 ctx_info_t *main_ctx;
608 ecg_fill_ctxs_count (get_irp_main_irg ());
609 ecg_fill_ctxs_alloc ();
611 main_ctx = new_ctx (get_irp_main_irg (), NULL, NULL);
612 main_irg = get_irp_main_irg ();
614 set_main_ctx (main_ctx);
616 /* Grrr, have to add this ctx manually to main.ginfo ... */
617 ginfo = ecg_get_info (main_irg);
619 ginfo->ctxs = xcalloc (1, sizeof (ctx_info_t *));
620 ginfo->ctxs [0] = main_ctx;
622 ecg_fill_ctxs_write (main_irg, main_ctx);
625 /* ====================
627 ==================== */
629 Nicely print a ctx_info_t to the given output stream
631 void ecg_print_ctx (ctx_info_t *ctx, FILE *stream)
633 ir_entity *ent = get_irg_entity(ctx->graph);
634 ir_node *call = ctx->call;
635 const char *ent_name = get_entity_name (ent);
636 const char *own_name = get_type_name (get_entity_owner (ent));
638 fprintf (stream, "CTX[%i](%s.%s->%s[%li])",
639 ctx->id, own_name, ent_name,
640 get_op_name (get_irn_op (call)),
641 get_irn_node_nr (call));
643 if (NULL != ctx->enc) {
644 fprintf (stream, "->%i", ctx->enc->id);
647 fprintf (stream, "\n");
651 Get a ctx of the given graph info
653 ctx_info_t *get_ctx (graph_info_t *ginfo, int ctx_idx)
655 assert (ginfo->n_ctxs > ctx_idx);
657 return (ginfo->ctxs [ctx_idx]);
661 Get the pseudo-ctx of 'main'
663 ctx_info_t *get_main_ctx ()
669 Set the pseudo-ctx of 'main'
671 void set_main_ctx (ctx_info_t *ctx)
677 /* ====================
679 ==================== */
681 /* ====================
683 ==================== */
685 Iterate over all graphs
687 void ecg_iterate_graphs (graph_hnd_t *hnd, void *env)
689 graph_info_t *ginfo = graph_infos_list;
691 while (NULL != ginfo) {
692 /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
694 if (0 != ginfo->n_ctxs) {
704 Iterate of all allocs of a given graph info
706 void ecg_iterate_allocs (graph_info_t *ginfo, alloc_hnd_t *hnd, void *env)
708 alloc_info_t *ainfo = ginfo->allocs;
710 while (NULL != ainfo) {
719 Iterate over all calls of the given graph info
721 void ecg_iterate_calls (graph_info_t *ginfo, call_hnd_t *hnd, void *env)
723 call_info_t *cinfo = ginfo->calls;
725 while (NULL != cinfo) {
734 Iterate over all callEds of the given call info
736 void ecg_iterate_callEds (call_info_t *cinfo, callEd_hnd_t *hnd, void *env)
738 callEd_info_t *ced = cinfo->callEds;
740 while (NULL != ced) {
749 get the call infos for the given graph
751 graph_info_t *ecg_get_info (ir_graph *graph)
753 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
755 assert (ginfo && "no info for graph");
761 Get the Alloc Infos for the given graph
763 alloc_info_t *ecg_get_alloc_info (ir_graph *graph)
765 graph_info_t *ginfo = ecg_get_info (graph);
767 return (ginfo->allocs);
771 Get the Call Info for the given call
773 callEd_info_t *ecg_get_callEd_info (ir_node *call)
775 ir_graph *graph = get_irn_irg (call);
776 graph_info_t *ginfo = ecg_get_info (graph);
778 call_info_t *call_info = ginfo->calls;
780 while (NULL != call_info) {
781 if (call == call_info->call) {
782 return (call_info->callEds);
785 call_info = call_info->prev;
793 Dump the given graph and it's calls and it's calls callEds to the given file.
795 static int ecg_ecg_graph (FILE *dot, ir_graph *graph)
800 const char *name = get_irg_entity (graph) ?
801 get_entity_name (get_irg_entity (graph)) : "noEntity";
803 (get_entity_stickyness
804 (get_irg_entity (graph)) == stickyness_sticky) ?
805 "red" : "lightyellow";
807 /* graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph); */
808 graph_info_t *ginfo = ecg_get_info (graph);
810 if (0 != ginfo->ecg_seen) {
811 fprintf (dot, "\t/* recursive call to \"%s\" (%d) */\n",
812 name, (int) ginfo->ecg_seen);
814 fprintf (dot, "\t/* recursive call to \"%s\" (0x%08x) */\n",
817 return (ginfo->ecg_seen);
820 assert (0L <= _graphs);
822 graph_no = _graphs ++;
823 ginfo->ecg_seen = graph_no;
825 fprintf (dot, "\t/* Graph of \"%s.%s\" */\n",
826 get_type_name (get_entity_owner (get_irg_entity (graph))),
828 fprintf (dot, "\tgraph_%i [label=\"<HEAD>%s\\l%s\\l|<CTX>n_ctx = %i\\l\", color=\"%s\"];\n",
830 get_type_name (get_entity_owner (get_irg_entity (graph))),
836 if (visibility_external_allocated ==
837 get_entity_visibility (get_irg_entity (graph))) {
838 fprintf (dot, "\t/* graph \"%s\" is external */\n", name);
843 cinfo = ginfo->calls;
844 while (NULL != cinfo) {
845 ir_node *call = cinfo->call;
846 callEd_info_t *ced = cinfo->callEds;
847 const int call_no = _calls ++;
848 const char *call_color = (NULL == ced) ? "blue" :
849 (NULL == ced->prev) ? "lightblue" : "blue3";
851 fprintf (dot, "\t/* Call %li */\n", get_irn_node_nr (call));
852 fprintf (dot, "\tcall_%i [label=\"call\\[%li\\]\", color=\"%s\", shape=\"ellipse\"];\n",
853 call_no, get_irn_node_nr (call), call_color);
854 fprintf (dot, "\tgraph_%i -> call_%i [color=\"black\"];\n", graph_no, call_no);
856 while (NULL != ced) {
857 ir_graph *callEd_graph = ced->callEd;
858 const int callEd_no = ecg_ecg_graph (dot, callEd_graph);
859 const char *callEd_name = get_irg_entity (callEd_graph) ?
860 get_entity_name (get_irg_entity (callEd_graph)) : "noEntity";
861 const char *direction = (callEd_no <= graph_no) ? "forward" : "forward";
862 const char *callEd_color = (callEd_no <= graph_no) ? "red" : "black";
864 fprintf (dot, "\t/* Call from graph \"%s\" to graph \"%s\" */\n",
867 /* Check for recursive calls */
868 /* if (callEd_no > graph_no) */ { /* do recursive calls (for now) */
869 fprintf (dot, "\tcall_%i -> graph_%i:HEAD [color=\"%s\", dir=\"%s\"];\n",
870 call_no, callEd_no, callEd_color, direction);
875 } /* done all calEds (call) */
878 } /* done all calls (graph) */
881 ainfo = ecg_get_alloc_info (graph);
883 fprintf (dot, "\t/* now the allocs */\n");
885 fprintf (dot, "\t/* no allocs */\n");
888 while (NULL != ainfo) {
889 ir_node *alloc = ainfo->alloc;
890 const char *name = get_type_name (ainfo->tp);
891 const char *color = "red1";
894 fprintf (dot, "\talloc_0x%08x_%i [label=\"%s\", color=\"%s\"];\n",
895 (int) alloc, graph_no, name, color);
897 fprintf (dot, "\tgraph_%i -> alloc_0x%08x_%i;\n",
898 graph_no, (int) alloc, graph_no);
903 if (0 == ginfo->allocs_seen) {
904 ginfo->allocs_seen = 1;
907 /* write table of ctxs */
910 const int max_ctxs = 30;
911 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
913 fprintf (dot, "\tctx_%i [label=\"<HEAD>", graph_no);
915 assert (ginfo->ctxs && "no ctx");
916 for (i = 0; i < n_ctxs; i ++) {
917 ctx_info_t *ctx_info = ginfo->ctxs [i];
919 if (NULL != ctx_info->enc) {
920 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
925 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
934 if (0 < ginfo->n_ctxs - max_ctxs) {
935 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
938 fprintf (dot, "\", color=\"green3\"];\n");
941 "\tgraph_%i:CTX -> ctx_%i:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
945 fprintf (dot, "\t/* done with graph of \"%s\" */\n\n", name);
954 Count how many nodes the ECG will have
956 static char spaces [BUF_SIZE];
958 static void ecg_ecg_count (ir_graph *graph)
962 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
964 if (0 != ginfo->ecg_seen) {
969 if (_depth > _max_depth) {
973 fprintf (stdout, "_max_depth = %i\n", _max_depth);
974 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
978 assert (0L <= _graphs);
981 if (0 == (_graphs % 1000000)) {
982 fprintf (stdout, "\tn_graphs: %i\n", _graphs);
983 fprintf (stdout, "_depth = %i\n", _depth);
987 graph_no = _graphs ++;
988 ginfo->ecg_seen = graph_no;
990 fprintf (stdout, "%sMethod \"%s.%s\"\n",
991 spaces + BUF_SIZE - _depth,
992 get_type_name (get_entity_owner (get_irg_entity (graph))),
993 get_entity_name (get_irg_entity (graph)));
995 cinfo = ginfo->calls;
996 while (NULL != cinfo) {
998 callEd_info_t *ced = cinfo->callEds;
1000 fprintf (stdout, "%sCall \"0x%08x\"\n",
1001 spaces + BUF_SIZE - _depth,
1004 while (NULL != ced) {
1005 ir_graph *callEd_graph = ced->callEd;
1007 fprintf (stdout, "%sCall Target \"%s.%s\"\n",
1008 spaces + BUF_SIZE - _depth,
1009 get_type_name (get_entity_owner (get_irg_entity (callEd_graph))),
1010 get_entity_name (get_irg_entity (callEd_graph)));
1012 ecg_ecg_count (callEd_graph);
1015 } /* done all calEds (call) */
1016 cinfo = cinfo->prev;
1017 } /* done all calls (graph) */
1019 ginfo->ecg_seen = 0;
1023 /* ====================
1025 ==================== */
1028 Initialise our data structures.
1030 void ecg_init (int typalise)
1032 do_typalise = typalise;
1038 graph_infos = pmap_create ();
1048 void ecg_cleanup (void)
1054 for (i = 0; i < get_irp_n_irgs (); i++) {
1055 ir_graph *graph = get_irp_irg (i);
1057 graph_info_t *info = pmap_get (graph_infos, graph);
1058 call_info_t *cinfo = info->calls;
1060 while (NULL != cinfo) {
1061 callEd_info_t *ced = cinfo->callEds;
1065 while (NULL != ced) {
1066 callEd_info_t *nced = ced->prev;
1073 cinfo->callEds = NULL;
1076 cinfo = cinfo->prev;
1080 pmap_insert (graph_infos, graph, NULL);
1084 pmap_destroy (graph_infos);
1091 Show what we have found.
1097 FILE *dot = fopen ("calls.dot", "w");
1099 fprintf (dot, "digraph \"calls\" {\n");
1100 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1101 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1102 fprintf (dot, "\tedge [color=\"black\"];\n");
1103 fprintf (dot, "\n");
1105 for (i = 0; i < get_irp_n_irgs (); i++) {
1106 ir_graph *graph = get_irp_irg (i);
1107 graph_info_t *ginfo = (graph_info_t*) pmap_get (graph_infos, graph);
1109 if (0 != ginfo->n_ctxs) {
1111 alloc_info_t *ainfo;
1113 const char *name = get_irg_entity (graph) ?
1114 get_entity_name (get_irg_entity (graph)) : "noEntity";
1116 const char *oname = get_type_name
1117 (get_entity_owner (get_irg_entity (graph)));
1120 (get_entity_stickyness
1121 (get_irg_entity (graph)) == stickyness_sticky) ?
1122 "red3" : "lightyellow";
1124 fprintf (dot, "\t/* graph_0x%08x (\"%s\") */\n", (int) graph, name);
1126 "\tgraph_0x%08x [label=\"%s\\l%s\", color=\"%s\"];\n",
1127 (int) graph, oname, name, color);
1128 fprintf (dot, "\n");
1130 cinfo = ginfo->calls;
1132 fprintf (dot, "\t/* now the calls */\n");
1134 fprintf (dot, "\t/* no calls, nothing to see, move along! */\n");
1137 while (NULL != cinfo) {
1139 ir_node *call = cinfo->call;
1141 fprintf (dot, "\t/* call_0x%08x */\n", (int) call);
1142 fprintf (dot, "\tcall_0x%08x [label=\"call\\[%li\\]\", shape=\"ellipse\", color=\"lightblue\"];\n",
1143 (int) call, get_irn_node_nr (call));
1144 fprintf (dot, "\tgraph_0x%08x -> call_0x%08x;\n",
1145 (int) graph, (int) call);
1147 ced = cinfo->callEds;
1148 while (NULL != ced) {
1149 fprintf (dot, "\tcall_0x%08x -> graph_0x%08x;\n",
1150 (int) call, (int) ced->callEd);
1153 fprintf (dot, "\n");
1155 cinfo = cinfo->prev;
1157 fprintf (dot, "\n");
1159 ainfo = ginfo->allocs;
1161 fprintf (dot, "\t/* now the allocs */\n");
1163 fprintf (dot, "\t/* no allocs */\n");
1167 while (NULL != ainfo) {
1168 ir_node *alloc = ainfo->alloc;
1169 const char *name = get_type_name (ainfo->tp);
1170 const char *color = "red1";
1172 fprintf (dot, "\talloc_0x%08x [label=\"%s\", color=\"%s\"];\n",
1173 (int) alloc, name, color);
1174 fprintf (dot, "\tgraph_0x%08x -> alloc_0x%08x;\n",
1175 (int) graph, (int) alloc);
1177 ainfo = ainfo->prev;
1183 const int max_ctxs = 30;
1184 const int n_ctxs = (ginfo->n_ctxs > max_ctxs) ? max_ctxs : ginfo->n_ctxs;
1186 fprintf (dot, "\t/* now the ctxs */\n");
1187 fprintf (dot, "\tctx_0x%08x [label=\"<HEAD>", (int) graph);
1189 assert (ginfo->ctxs && "no ctx");
1190 for (i = 0; i < n_ctxs; i ++) {
1191 ctx_info_t *ctx_info = ginfo->ctxs [i];
1193 if (NULL != ctx_info->enc) {
1194 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\-\\>%i\\]\\l",
1199 fprintf (dot, "ctx_info \\[%i\\] = ctx\\[%i\\]\\l",
1203 if (i+1 != n_ctxs) {
1208 if (0 < ginfo->n_ctxs - max_ctxs) {
1209 fprintf (dot, "(%i more)\\l", ginfo->n_ctxs - max_ctxs);
1212 fprintf (dot, "\", color=\"green3\"];\n");
1215 "\tgraph_0x%p -> ctx_0x%p:HEAD [label=\"ctx\", dir=\"none\", style=\"dotted\"];\n",
1219 fprintf (dot, "\t/* graph is not called */\n");
1220 } /* end all graphs */
1222 fprintf (dot, "}\n");
1225 fprintf (stdout, " max_callEds: %i\n", _max_callEds);
1226 fprintf (stdout, " max_callEds_callR: \"%s\"\n",
1227 get_entity_name (_max_callEds_callR));
1233 Experimental: Print the ecg
1238 ir_graph *main_graph = get_irp_main_irg ();
1244 memset (spaces, '.', BUF_SIZE);
1245 spaces [BUF_SIZE-1] = '\0';
1247 ecg_ecg_count (main_graph);
1248 fprintf (stdout, "n_graphs: %i\n", _graphs);
1249 fprintf (stdout, "max_depth = %i\n", _max_depth);
1257 dot = fopen ("ecg.dot", "w");
1259 fprintf (dot, "digraph \"ecg\" {\n");
1260 fprintf (dot, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11, 7\", rotate=\"90\", ratio=\"fill\"];\n");
1261 fprintf (dot, "\tnode [shape=\"record\", style=\"filled\"];\n");
1262 fprintf (dot, "\tedge [color=\"black\"];\n");
1263 fprintf (dot, "\n");
1264 fprintf (dot, "\n");
1266 /* ir_graph *main_graph = get_irp_main_irg (); */
1267 ecg_ecg_graph (dot, main_graph);
1269 fprintf (dot, "\t/* Grand Total: */\n");
1270 fprintf (dot, "\t/* calls: %i */\n", (int) _calls);
1271 fprintf (dot, "\t/* graphs: %i */\n", (int) _graphs);
1272 fprintf (dot, "\t/* allocs: %i */\n", (int) _allocs);
1273 fprintf (dot, "\t/* (sales tax not included) */\n");
1275 fprintf (dot, "}\n");
1284 Revision 1.23 2006/12/13 19:46:47 beck
1285 rename type entity into ir_entity
1287 Revision 1.22 2006/01/13 22:55:03 beck
1288 renamed all types 'type' to 'ir_type'
1290 Revision 1.21 2005/12/31 15:58:57 beck
1291 added missing includes
1293 Revision 1.20 2005/12/05 12:01:06 beck
1294 needed include added
1296 Revision 1.19 2005/03/22 13:55:51 liekweg
1297 Need to initialise typalise now
1299 Revision 1.18 2005/01/14 14:14:43 liekweg
1302 Revision 1.17 2005/01/14 13:34:25 liekweg
1303 Factor out call_info_t ctor; fix mallocs; fix initialisation
1305 Revision 1.16 2005/01/10 17:26:34 liekweg
1306 fixup printfs, don't put environments on the stack
1308 Revision 1.15 2004/12/23 15:40:03 beck
1311 Revision 1.14 2004/12/22 14:43:14 beck
1312 made allocations C-like
1314 Revision 1.13 2004/12/21 14:21:16 beck
1315 removed C99 constructs
1317 Revision 1.12 2004/12/20 17:34:34 liekweg
1318 fix recursion handling
1320 Revision 1.11 2004/12/15 09:18:18 liekweg
1323 Revision 1.10 2004/12/06 12:55:06 liekweg
1326 Revision 1.9 2004/12/02 16:17:50 beck
1327 fixed config.h include
1329 Revision 1.8 2004/11/30 14:45:44 liekweg
1330 fix graph dumping, remove 'HERE's
1332 Revision 1.7 2004/11/26 16:01:56 liekweg
1333 debugging annotations
1335 Revision 1.6 2004/11/24 14:53:55 liekweg
1338 Revision 1.5 2004/11/20 21:20:29 liekweg
1339 Added iterator functions
1341 Revision 1.4 2004/11/18 16:36:37 liekweg
1342 Added unique ids for debugging, added access functions
1344 Revision 1.3 2004/11/04 14:54:44 liekweg
1347 Revision 1.2 2004/10/21 11:09:37 liekweg
1348 Moved memwalk stuf into irmemwalk
1349 Moved lset stuff into lset
1350 Moved typalise stuff into typalise
1352 Revision 1.1 2004/10/20 14:59:41 liekweg
1353 Added ana2, added ecg and pto
1355 Revision 1.6 2004/10/18 12:47:19 liekweg
1358 Revision 1.5 2004/10/14 11:31:28 liekweg
1361 Revision 1.4 2004/10/12 11:02:01 liekweg