3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
23 #include "irgraph_t.h"
26 #include "firm_common_t.h"
34 #include "type_or_entity.h"
38 #include "callgraph.h"
48 void dump_chi_term(FILE *FL, ir_node *n);
49 void dump_state(FILE *FL, ir_node *n);
50 int get_opt_dump_abstvals(void);
51 typedef unsigned long SeqNo;
52 SeqNo get_Block_seqno(ir_node *n);
55 /* Attributes of nodes */
56 #define PRINT_DEFAULT_NODE_ATTR
57 #define DEFAULT_NODE_ATTR " "
58 #define DEFAULT_TYPE_ATTRIBUTE " "
59 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
61 /* Attributes of edges between Firm nodes */
62 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
63 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
64 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
65 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
66 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
67 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
68 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
70 #define BACK_EDGE_ATTR "linestyle:dashed "
72 /* Attributes of edges between Firm nodes and type/entity nodes */
73 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
75 /* Attributes of edges in type/entity graphs. */
76 #define TYPE_METH_NODE_ATTR "color: lightyellow"
77 #define TYPE_CLASS_NODE_ATTR "color: green"
78 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
79 #define ENTITY_NODE_ATTR "color: yellow"
80 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
81 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
82 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
83 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
84 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
85 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
86 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
87 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
88 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
89 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
90 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
91 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
92 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
93 #define ENUM_ITEM_NODE_ATTR "color: green"
94 #define CALLGRAPH_EDGE_ATTR "calls"
96 #if DEBUG_libfirm && NODEID_AS_LABEL
97 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
98 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
99 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
100 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
101 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
102 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
103 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
106 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
107 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
108 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
109 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
110 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
111 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
112 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
115 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
118 return get_mode_name(mode);
123 static const char *get_type_name_ex(type *tp, int *bad)
126 return get_type_name(tp);
131 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
136 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
137 fprintf(F, " targetname: "); PRINT_TYPEID(T);
138 vfprintf(F, fmt, ap);
143 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
148 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
149 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
150 vfprintf(F, fmt, ap);
155 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
161 fprintf(F, "backedge: { sourcename: \"");
163 fprintf(F, "edge: { sourcename: \"");
165 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
166 vfprintf(F, fmt, ap);
171 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
176 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
177 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
178 vfprintf(F, fmt, ap);
183 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
188 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
189 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
190 vfprintf(F, fmt, ap);
195 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
200 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
201 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
203 vfprintf(F, fmt, ap);
208 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
213 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
214 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
215 vfprintf(F, fmt, ap);
220 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
225 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
226 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
227 vfprintf(F, fmt, ap);
232 /*******************************************************************/
233 /* global and ahead declarations */
234 /*******************************************************************/
236 /* A suffix to manipulate the file name. */
237 char *dump_file_suffix = "";
239 char *dump_file_filter = "";
241 /* file to dump to */
244 static void dump_whole_node(ir_node *n, void* env);
245 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
247 /*******************************************************************/
248 /* Helper functions. */
249 /*******************************************************************/
251 /* Use private link attr to be able to call dumper anywhere without
252 destroying link fields. */
254 static pmap *irdump_link_map = NULL;
256 static void init_irdump(void) {
257 /* We need a new, empty map. */
258 if (irdump_link_map) pmap_destroy(irdump_link_map);
259 irdump_link_map = pmap_create();
263 void *ird_get_irn_link(ir_node *n) {
265 if (!irdump_link_map) return NULL;
267 if (pmap_contains(irdump_link_map, (void *)n))
268 res = pmap_get(irdump_link_map, (void *)n);
272 void ird_set_irn_link(ir_node *n, void *x) {
273 if (!irdump_link_map) init_irdump();
274 pmap_insert(irdump_link_map, (void *)n, x);
277 void *ird_get_irg_link(ir_graph *irg) {
279 if (!irdump_link_map) return NULL;
281 if (pmap_contains(irdump_link_map, (void *)irg))
282 res = pmap_get(irdump_link_map, (void *)irg);
286 void ird_set_irg_link(ir_graph *irg, void *x) {
287 if (!irdump_link_map) init_irdump();
288 pmap_insert(irdump_link_map, (void *)irg, x);
291 static void clear_link(ir_node * node, void * env) {
292 ird_set_irn_link(node, NULL);
296 static int node_floats(ir_node *n) {
297 return ((get_op_pinned(get_irn_op(n)) == floats) &&
298 (get_irg_pinned(current_ir_graph) == floats));
301 static const char *get_ent_dump_name(entity *ent) {
303 return "<NULL entity>";
304 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
305 if (ent->ld_name) return get_id_str(ent->ld_name);
306 return get_id_str(ent->name);
309 static const char *get_irg_dump_name(ir_graph *irg) {
310 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
311 entity *ent = get_irg_ent(irg);
312 return get_ent_dump_name(ent);
315 static void collect_node(ir_node * node, void *env) {
318 || get_irn_op(node) == op_Bad
319 || get_irn_op(node) == op_Unknown) {
320 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
321 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
322 ARR_APP1(ir_node *, arr, node);
323 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
325 ir_node * block = get_nodes_block(node);
326 ird_set_irn_link(node, ird_get_irn_link(block));
327 ird_set_irn_link(block, node);
331 /** Construct lists to walk ir block-wise.
333 * Collects all blocks, nodes not pinned,
334 * Bad and Unknown into a flexible array in link field of
335 * irg they belong to. Sets the irg link field to NULL in all
336 * graphs not visited.
337 * Free the list with DEL_ARR_F. */
338 static ir_node ** construct_block_lists(ir_graph *irg) {
339 int i, rem_view = interprocedural_view;
340 ir_graph *rem = current_ir_graph;
341 current_ir_graph = irg;
343 for (i = 0; i < get_irp_n_irgs(); i++)
344 ird_set_irg_link(get_irp_irg(i), NULL);
346 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
348 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
349 interprocedural_view = 0;
350 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
351 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
352 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
353 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
354 interprocedural_view = rem_view;
356 current_ir_graph = rem;
357 return ird_get_irg_link(irg);
360 /*******************************************************************/
361 /* flags to steer output */
362 /*******************************************************************/
364 /* A compiler option to turn off edge labels */
366 /* A compiler option to turn off dumping values of constant entities */
367 int const_entities = 1;
368 /* A compiler option to dump the keep alive edges */
369 int dump_keepalive = 0;
370 /* Compiler options to dump analysis information in dump_ir_graph */
371 int dump_out_edge_flag = 0;
372 int dump_dominator_information_flag = 0;
373 int dump_loop_information_flag = 0;
374 int dump_backedge_information_flag = 1;
375 int dump_const_local = 0;
376 bool opt_dump_analysed_type_info = 1;
377 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
379 char* overrule_nodecolor = NULL;
381 INLINE bool get_opt_dump_const_local(void) {
382 if (!dump_out_edge_flag && !dump_loop_information_flag)
383 return dump_const_local;
388 /* To turn off display of edge labels. Edge labels offen cause xvcg to
389 abort with a segmentation fault. */
390 void turn_off_edge_labels(void) {
394 void dump_consts_local(bool b) {
395 dump_const_local = b;
398 void turn_off_constant_entity_values(void) {
402 void dump_keepalive_edges(bool b) {
406 bool get_opt_dump_keepalive_edges(void) {
407 return dump_keepalive;
410 void dump_out_edges(void) {
411 dump_out_edge_flag = 1;
414 void dump_dominator_information(void) {
415 dump_dominator_information_flag = 1;
418 void dump_loop_information(void) {
419 dump_loop_information_flag = 1;
422 void dont_dump_loop_information(void) {
423 dump_loop_information_flag = 0;
426 void dump_backedge_information(bool b) {
427 dump_backedge_information_flag = b;
430 /* Dump the information of type field specified in ana/irtypeinfo.h.
431 * If the flag is set, the type name is output in [] in the node label,
432 * else it is output as info.
434 void dump_analysed_type_info(bool b) {
435 opt_dump_analysed_type_info = b;
438 void dump_pointer_values_to_info(bool b) {
439 opt_dump_pointer_values_to_info = b;
442 /*******************************************************************/
443 /* Routines to dump information about a single ir node. */
444 /*******************************************************************/
447 dump_node_opcode(FILE *F, ir_node *n)
451 switch(get_irn_opcode(n)) {
456 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
457 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
462 if (get_SymConst_kind(n) == symconst_addr_name) {
463 /* don't use get_SymConst_ptr_info as it mangles the name. */
464 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
465 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
466 assert(get_SymConst_entity(n));
467 assert(is_entity(get_SymConst_entity(n)));
468 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
470 assert(get_kind(get_SymConst_type(n)) == k_type);
471 assert(get_type_ident(get_SymConst_type(n)));
472 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
473 if (get_SymConst_kind(n) == symconst_type_tag)
481 if (!interprocedural_view) fprintf(F, "Proj'");
482 else fprintf(F, "%s", get_irn_opname(n));
486 ir_node *cond = get_Proj_pred(n);
488 if (get_irn_opcode(cond) == iro_Cond
489 && get_Proj_proj(n) == get_Cond_defaultProj(cond)
490 && get_irn_mode(get_Cond_selector(cond)) != mode_b)
491 fprintf (F, "defProj");
493 fprintf (F, "%s", get_irn_opname(n));
497 if (interprocedural_view) {
498 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
504 fprintf (F, "%s", get_irn_opname(n));
512 dump_node_mode (ir_node *n)
516 switch (get_irn_opcode(n)) {
535 fprintf (F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
543 static int dump_node_typeinfo(ir_node *n) {
546 if (opt_dump_analysed_type_info) {
547 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
548 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
549 type *tp = get_irn_type(n);
551 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
560 dump_node_nodeattr (ir_node *n)
564 switch (get_irn_opcode(n)) {
566 if (false && interprocedural_view) {
567 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
571 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
572 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
574 fprintf (F, "%ld", get_Proj_proj(n));
578 fprintf (F, "%ld", get_Filter_proj(n));
581 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
584 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
587 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
597 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
600 fprintf(F, "color: red");
603 switch (get_irn_opcode(n)) {
610 fprintf (F, "color: blue");
613 fprintf (F, "color: lightyellow");
616 fprintf (F, "color: green");
622 fprintf (F, "color: yellow");
625 PRINT_DEFAULT_NODE_ATTR;
628 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
631 static INLINE int dump_node_info(ir_node *n)
637 fprintf (F, " info1: \"");
638 if (opt_dump_pointer_values_to_info)
639 fprintf (F, "addr: %p \n", (void *)n);
640 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
641 fprintf (F, "visited: %ld \n", get_irn_visited(n));
642 irg = get_irn_irg(n);
643 if (irg != get_const_code_irg())
644 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
646 fprintf(F, "arity: %d", get_irn_arity(n));
647 if ((get_irn_op(n) == op_Block) ||
648 (get_irn_op(n) == op_Phi) ||
649 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
650 fprintf(F, " backedges:");
652 for (i = 0; i < get_irn_arity(n); i++)
653 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
657 /* Loop node Someone else please tell me what's wrong ...
658 if (get_irn_loop(n)) {
659 ir_loop *loop = get_irn_loop(n);
661 fprintf(F, " in loop %d with depth %d\n",
662 get_loop_loop_nr(loop), get_loop_depth(loop));
667 switch (get_irn_opcode(n)) {
669 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
670 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
671 for (i = 0; i < get_method_n_params(tp); ++i)
672 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
675 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
678 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
681 entity *ent = get_Sel_entity(n);
684 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
685 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
688 fprintf(F, "<NULL entity>\n");
693 type *tp = get_Call_type(n);
694 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
695 for (i = 0; i < get_method_n_params(tp); ++i)
696 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
697 for (i = 0; i < get_method_n_ress(tp); ++i)
698 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
699 if (Call_has_callees(n)) {
700 fprintf(F, "possible callees: \n");
701 for (i = 0; i < get_Call_n_callees(n); i++) {
702 if (!get_Call_callee(n, i)) {
703 fprintf(F, " %d external method\n", i);
705 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
710 case iro_CallBegin: {
711 ir_node *call = get_CallBegin_call(n);
712 if (Call_has_callees(call)) {
713 fprintf(F, "possible callees: \n");
714 for (i = 0; i < get_Call_n_callees(call); i++) {
715 if (!get_Call_callee(call, i)) {
716 fprintf(F, " %d external method\n", i);
718 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
724 if (!interprocedural_view) {
725 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
726 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
727 for (i = 0; i < get_method_n_ress(tp); ++i)
728 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
732 type *tp = get_Const_type(n);
733 assert(tp != none_type);
734 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
738 if (interprocedural_view) {
739 fprintf(F, "intra predecessor nodes:\n");
740 for (i = 0; i < get_irn_intra_arity(n); i++) {
741 ir_node *pred = get_irn_intra_n(n, i);
742 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
745 fprintf(F, "inter predecessor nodes:\n");
746 for (i = 0; i < get_irn_inter_arity(n); i++) {
747 ir_node *pred = get_irn_inter_n(n, i);
748 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
749 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
756 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
757 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
758 if (get_irn_type(n) != none_type)
759 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
768 bool is_constlike_node(ir_node *n) {
769 ir_op *op = get_irn_op(n);
770 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
774 /* outputs the predecessors of n, that are constants, local. I.e.,
775 generates a copy of the constant predecessors for each node called with. */
776 static void dump_const_node_local(ir_node *n) {
778 if (!get_opt_dump_const_local()) return;
780 /* Use visited flag to avoid outputting nodes twice.
781 initialize it first. */
782 for (i = 0; i < get_irn_arity(n); i++) {
783 ir_node *con = get_irn_n(n, i);
784 if (is_constlike_node(con)) {
785 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
789 for (i = 0; i < get_irn_arity(n); i++) {
790 ir_node *con = get_irn_n(n, i);
791 if (is_constlike_node(con) && irn_not_visited(con)) {
794 mark_irn_visited(con);
795 /* Generate a new name for the node by appending the names of
797 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
798 fprintf(F, " label: \"");
799 bad |= dump_node_opcode(F, con);
800 bad |= dump_node_mode (con);
801 bad |= dump_node_typeinfo(con);
803 bad |= dump_node_nodeattr(con);
804 fprintf(F, " %ld", get_irn_node_nr(con));
806 bad |= dump_node_info(con);
807 dump_node_vcgattr(con, bad);
813 static void print_node_error(const char *p)
818 fprintf (F, " info2: \"%s\"", p);
821 static void dump_node(ir_node *n)
826 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
828 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
830 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
831 bad |= dump_node_opcode(F, n);
832 bad |= dump_node_mode (n);
833 bad |= dump_node_typeinfo(n);
835 bad |= dump_node_nodeattr(n);
836 fprintf(F, " %ld", get_irn_node_nr(n));
838 bad |= dump_node_info(n);
840 dump_node_vcgattr(n, bad);
842 dump_const_node_local(n);
849 /* dump the edge to the block this node belongs to */
851 dump_ir_block_edge(ir_node *n) {
852 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
853 if (is_no_Block(n)) {
854 fprintf (F, "edge: { sourcename: \"");
856 fprintf (F, "\" targetname: \"");
857 PRINT_NODEID(get_nodes_block(n));
858 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
863 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
864 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
865 fprintf (F, INTRA_DATA_EDGE_ATTR);
867 fprintf (F, INTER_DATA_EDGE_ATTR);
871 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
872 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
873 fprintf (F, INTRA_MEM_EDGE_ATTR);
875 fprintf (F, INTER_MEM_EDGE_ATTR);
879 print_edge_vcgattr(ir_node *from, int to) {
882 if (dump_backedge_information_flag && is_backedge(from, to))
883 fprintf (F, BACK_EDGE_ATTR);
885 switch (get_irn_opcode(from)) {
887 fprintf (F, CF_EDGE_ATTR);
889 case iro_Start: break;
892 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
893 fprintf (F, CF_EDGE_ATTR);
894 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
895 fprintf (F, INTER_MEM_EDGE_ATTR);
903 print_data_edge_vcgattr(F, from, to);
908 print_mem_edge_vcgattr(F, from, to);
910 print_data_edge_vcgattr(F, from, to);
914 print_data_edge_vcgattr(F, from, to);
919 print_mem_edge_vcgattr(F, from, to);
921 print_data_edge_vcgattr(F, from, to);
928 print_data_edge_vcgattr(F, from, to);
935 print_mem_edge_vcgattr(F, from, to);
937 print_data_edge_vcgattr(F, from, to);
949 print_data_edge_vcgattr(F, from, to);
952 if (get_irn_modecode(from) == irm_M)
953 fprintf (F, INTER_MEM_EDGE_ATTR);
955 print_data_edge_vcgattr(F, from, to);
962 print_mem_edge_vcgattr(F, from, to);
964 print_data_edge_vcgattr(F, from, to);
967 print_mem_edge_vcgattr(F, from, to);
969 case iro_Tuple: break;
972 switch (get_irn_modecode(from)) {
974 fprintf (F, CF_EDGE_ATTR);
977 fprintf (F, INTER_MEM_EDGE_ATTR);
980 print_data_edge_vcgattr(F, from, to);
985 case iro_Unknown: break;
987 switch (get_irn_modecode(from)) {
989 fprintf (F, INTRA_MEM_EDGE_ATTR);
992 fprintf (F, CF_EDGE_ATTR);
995 print_data_edge_vcgattr(F, from, to);
1003 /* dump edges to our inputs */
1005 dump_ir_data_edges(ir_node *n) {
1006 int i, visited = get_irn_visited(n);
1008 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1011 for (i = 0; i < get_irn_arity(n); i++) {
1012 ir_node * pred = get_irn_n(n, i);
1015 if ((interprocedural_view && get_irn_visited(pred) < visited))
1016 continue; /* pred not dumped */
1018 if (dump_backedge_information_flag && is_backedge(n, i))
1019 fprintf (F, "backedge: {sourcename: \"");
1021 fprintf (F, "edge: {sourcename: \"");
1023 fprintf (F, "\" targetname: ");
1024 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1025 PRINT_CONSTID(n, pred);
1027 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1029 fprintf (F, " label: \"%d\" ", i);
1030 print_edge_vcgattr(n, i);
1035 /** Dumps a node and its edges but not the block edge
1038 dump_node_wo_blockedge (ir_node *n, void* env) {
1040 dump_ir_data_edges(n);
1043 /** Dumps a node and its edges.
1046 dump_whole_node (ir_node *n, void* env) {
1047 dump_node_wo_blockedge(n, env);
1048 if (!node_floats(n)) dump_ir_block_edge(n);
1052 dump_const_node(ir_node *n, void *env) {
1053 if (is_Block(n)) return;
1054 dump_node_wo_blockedge(n, env);
1057 /***********************************************************************/
1058 /* the following routines dump the nodes/irgs bracketed to graphs. */
1059 /***********************************************************************/
1061 /** Dumps a constant expression as entity initializer, array bound ...
1063 static void dump_const_expression(ir_node *value) {
1064 ir_graph *rem = current_ir_graph;
1065 int rem_dump_const_local = dump_const_local;
1066 dump_const_local = 0;
1067 current_ir_graph = get_const_code_irg();
1068 irg_walk(value, dump_const_node, NULL, NULL);
1069 /* Decrease visited flag so that we walk with the same flag for the next
1070 expresssion. This guarantees that we don't dump the same node twice,
1071 as for const expressions cse is performed to save memory. */
1072 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1073 current_ir_graph = rem;
1074 dump_const_local = rem_dump_const_local;
1077 /** Dump a block as graph containing its nodes.
1079 * Expects to find nodes belonging to the block as list in its
1081 * Dumps the edges of all nodes including itself. */
1083 dump_whole_block(ir_node *block) {
1085 assert(is_Block(block));
1087 fprintf(F, "graph: { title: \"");
1088 PRINT_NODEID(block);
1089 fprintf(F, "\" label: \"");
1090 dump_node_opcode(F, block);
1091 fprintf (F, " %ld", get_irn_node_nr(block));
1093 if (get_opt_dump_abstvals())
1094 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1096 fprintf(F, "\" status:clustered color:%s \n",
1097 get_Block_matured(block) ? "yellow" : "red");
1099 /* dump the blocks edges */
1100 dump_ir_data_edges(block);
1102 /* dump the nodes that go into the block */
1103 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1105 dump_ir_data_edges(node);
1108 /* Close the vcg information for the block */
1110 dump_const_node_local(block);
1112 dump_chi_term(F, block);
1117 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1118 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1120 dump_block_graph(ir_graph *irg) {
1122 ir_graph *rem = current_ir_graph;
1123 ir_node **arr = ird_get_irg_link(irg);
1124 current_ir_graph = irg;
1126 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1127 ir_node * node = arr[i];
1128 if (is_Block(node)) {
1129 /* Dumps the block and all the nodes in the block, which are to
1130 be found in Block->link. */
1131 dump_whole_block(node);
1133 /* Nodes that are not in a Block. */
1135 dump_ir_data_edges(node);
1139 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1141 current_ir_graph = rem;
1144 /** Dumps an irg as a graph.
1145 * If interprocedural view edges can point to nodes out of this graph.
1147 static void dump_graph(ir_graph *irg) {
1149 fprintf(F, "graph: { title: \"");
1151 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1152 get_ent_dump_name(get_irg_ent(irg)));
1154 dump_block_graph (irg);
1156 /* Close the vcg information for the irg */
1157 fprintf(F, "}\n\n");
1160 /*******************************************************************/
1161 /* Basic type and entity nodes and edges. */
1162 /*******************************************************************/
1164 /* dumps the edges between nodes and their type or entity attributes. */
1165 static void dump_node2type_edges (ir_node *n, void *env)
1169 switch (get_irn_opcode(n)) {
1171 /* @@@ some consts have an entity */
1174 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1175 || (get_SymConst_kind(n) ==symconst_size))
1177 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1181 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1184 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1187 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1190 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1193 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1201 static int print_type_info(type *tp) {
1204 if (get_type_state(tp) == layout_undefined) {
1205 fprintf(F, "state: layout_undefined\n");
1207 fprintf(F, "state: layout_fixed,\n");
1209 if (get_type_mode(tp))
1210 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1211 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1216 static void print_typespecific_info(type *tp) {
1217 switch (get_type_tpop_code(tp)) {
1220 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1227 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1228 fprintf(F, "params: %d\n", get_method_n_params(tp));
1229 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1237 case tpo_enumeration:
1251 static void print_typespecific_vcgattr(type *tp) {
1252 switch (get_type_tpop_code(tp)) {
1255 if (peculiarity_existent == get_class_peculiarity(tp))
1256 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1258 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1262 fprintf (F, " " TYPE_METH_NODE_ATTR);
1273 case tpo_enumeration:
1286 static int print_type_node(type *tp)
1290 fprintf (F, "node: {title: ");
1292 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1293 fprintf (F, " info1: \"");
1294 bad |= print_type_info(tp);
1295 print_typespecific_info(tp);
1297 print_typespecific_vcgattr(tp);
1303 #define X(a) case a: fprintf(F, #a); break
1304 void dump_entity_node(entity *ent)
1306 fprintf (F, "node: {title: \"");
1307 PRINT_ENTID(ent); fprintf(F, "\"");
1308 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1309 fprintf (F, "label: ");
1310 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1311 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1313 fprintf (F, "\nallocation: ");
1314 switch (get_entity_allocation(ent)) {
1315 X(allocation_dynamic);
1316 X(allocation_automatic);
1317 X(allocation_static);
1318 X(allocation_parameter);
1321 fprintf (F, "\nvisibility: ");
1322 switch (get_entity_visibility(ent)) {
1323 X(visibility_local);
1324 X(visibility_external_visible);
1325 X(visibility_external_allocated);
1328 fprintf (F, "\nvariability: ");
1329 switch (get_entity_variability(ent)) {
1330 X(variability_uninitialized);
1331 X(variability_initialized);
1332 X(variability_part_constant);
1333 X(variability_constant);
1336 fprintf (F, "\nvolatility: ");
1337 switch (get_entity_volatility(ent)) {
1338 X(volatility_non_volatile);
1339 X(volatility_is_volatile);
1342 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1343 fprintf(F, "\nname: %s\nld_name: %s",
1344 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1345 fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1346 if (is_method_type(get_entity_type(ent))) {
1347 if (get_entity_irg(ent)) /* can be null */
1348 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1350 { fprintf (F, "\nirg = NULL"); }
1352 fprintf(F, "\"\n}\n");
1356 static void dump_enum_item(type *tp, int pos)
1359 ident *id = get_enumeration_nameid(tp, pos);
1360 tarval *tv = get_enumeration_enum(tp, pos);
1362 tarval_snprintf(buf, sizeof(buf), tv);
1363 fprintf (F, "node: {title: \"");
1364 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1365 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1366 fprintf (F, "label: ");
1367 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1368 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1371 /* dumps a type or entity and it's edges. */
1373 dump_type_info (type_or_ent *tore, void *env) {
1374 int i = 0; /* to shutup gcc */
1376 /* dump this type or entity */
1378 switch (get_kind(tore)) {
1381 entity *ent = (entity *)tore;
1384 dump_entity_node(ent);
1386 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1387 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1388 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1389 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1390 if(is_class_type(get_entity_owner(ent))) {
1391 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1392 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1395 /* attached subgraphs */
1396 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1397 if (is_atomic_entity(ent)) {
1398 value = get_atomic_ent_value(ent);
1400 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1401 /* DDMN(value); $$$ */
1402 dump_const_expression(value);
1405 if (is_compound_entity(ent)) {
1406 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1407 value = get_compound_ent_value(ent, i);
1409 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1410 dump_const_expression(value);
1411 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1413 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1414 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1415 get_compound_ent_value_member(ent, i), i);
1424 type *tp = (type *)tore;
1425 print_type_node(tp);
1426 /* and now the edges */
1427 switch (get_type_tpop_code(tp)) {
1430 for (i=0; i < get_class_n_supertypes(tp); i++) {
1431 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1434 for (i=0; i < get_class_n_members(tp); i++) {
1435 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1440 for (i=0; i < get_struct_n_members(tp); i++) {
1441 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1446 for (i = 0; i < get_method_n_params(tp); i++)
1448 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1450 for (i = 0; i < get_method_n_ress(tp); i++)
1452 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1457 for (i = 0; i < get_union_n_members(tp); i++)
1459 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1464 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1465 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1466 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1467 ir_node *upper = get_array_upper_bound(tp, i);
1468 ir_node *lower = get_array_lower_bound(tp, i);
1469 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1470 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1471 dump_const_expression(upper);
1472 dump_const_expression(lower);
1476 case tpo_enumeration:
1478 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1479 dump_enum_item(tp, i);
1480 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1485 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1493 break; /* case k_type */
1496 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1498 } /* switch kind_or_entity */
1501 /** For dumping class hierarchies.
1502 * Dumps a class type node and a superclass edge.
1503 * If env != null dumps entities of classes and overwrites edges.
1506 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1507 int i = 0; /* to shutup gcc */
1509 /* dump this type or entity */
1510 switch (get_kind(tore)) {
1512 entity *ent = (entity *)tore;
1513 if (get_entity_owner(ent) == get_glob_type()) break;
1514 if ((env) && is_class_type(get_entity_owner(ent))) {
1516 dump_entity_node(ent);
1518 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1519 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1521 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1524 } break; /* case k_entity */
1527 type *tp = (type *)tore;
1528 if (tp == get_glob_type()) break;
1529 switch (get_type_tpop_code(tp)) {
1531 print_type_node(tp);
1532 /* and now the edges */
1533 for (i=0; i < get_class_n_supertypes(tp); i++)
1535 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1541 break; /* case k_type */
1544 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1546 } /* switch kind_or_entity */
1549 /*******************************************************************/
1550 /* dump analysis information that is expressed in graph terms. */
1551 /*******************************************************************/
1553 /* dump out edges */
1555 dump_out_edge (ir_node *n, void* env) {
1557 for (i = 0; i < get_irn_n_outs(n); i++) {
1558 assert(get_irn_out(n, i));
1559 fprintf (F, "edge: {sourcename: \"");
1561 fprintf (F, "\" targetname: \"");
1562 PRINT_NODEID(get_irn_out(n, i));
1563 fprintf (F, "\" color: red linestyle: dashed");
1569 dump_loop_label(ir_loop *loop) {
1570 fprintf (F, "loop %d, %d sons, %d nodes",
1571 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1574 static INLINE void dump_loop_info(ir_loop *loop) {
1575 fprintf (F, " info1: \"");
1576 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1577 #if DEBUG_libfirm /* GL @@@ debug analyses */
1578 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1584 dump_loop_node(ir_loop *loop) {
1585 fprintf (F, "node: {title: \"");
1587 fprintf (F, "\" label: \"");
1588 dump_loop_label(loop);
1590 dump_loop_info(loop);
1596 dump_loop_node_edge (ir_loop *loop, int i) {
1598 fprintf (F, "edge: {sourcename: \"");
1600 fprintf (F, "\" targetname: \"");
1601 PRINT_NODEID(get_loop_node(loop, i));
1602 fprintf (F, "\" color: green");
1607 dump_loop_son_edge (ir_loop *loop, int i) {
1609 fprintf (F, "edge: {sourcename: \"");
1611 fprintf (F, "\" targetname: \"");
1612 PRINT_LOOPID(get_loop_son(loop, i));
1613 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1614 get_loop_element_pos(loop, get_loop_son(loop, i)));
1618 void dump_loops (ir_loop *loop) {
1620 /* dump this loop node */
1621 dump_loop_node(loop);
1623 /* dump edges to nodes in loop -- only if it is a real loop */
1624 if (get_loop_depth(loop) != 0) {
1625 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1626 dump_loop_node_edge(loop, i);
1629 for (i = 0; i < get_loop_n_sons(loop); i++) {
1630 dump_loops(get_loop_son(loop, i));
1631 dump_loop_son_edge(loop, i);
1636 void dump_loop_nodes_into_graph(ir_graph *irg) {
1637 ir_graph *rem = current_ir_graph;
1638 current_ir_graph = irg;
1640 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1642 current_ir_graph = rem;
1646 /************************************************************************/
1647 /* open and close vcg file */
1648 /************************************************************************/
1651 dump_vcg_header(const char *name, const char *orientation) {
1660 if (!orientation) orientation = "bottom_to_top";
1664 "graph: { title: \"ir graph of %s\"\n"
1665 "display_edge_labels: %s\n"
1666 "layoutalgorithm: mindepth\n"
1667 "manhattan_edges: yes\n"
1668 "port_sharing: no\n"
1670 "classname 1: \"intrablock Data\"\n"
1671 "classname 16: \"interblock Data\"\n"
1672 "classname 2: \"Block\"\n"
1673 "classname 13: \"Control Flow\"\n"
1674 "classname 14: \"intrablock Memory\"\n"
1675 "classname 17: \"interblock Memory\"\n"
1676 "classname 15: \"Dominators\"\n"
1677 "classname 3: \"Entity type\"\n"
1678 "classname 4: \"Entity owner\"\n"
1679 "classname 5: \"Method Param\"\n"
1680 "classname 6: \"Method Res\"\n"
1681 "classname 7: \"Super\"\n"
1682 "classname 8: \"Union\"\n"
1683 "classname 9: \"Points-to\"\n"
1684 "classname 10: \"Array Element Type\"\n"
1685 "classname 11: \"Overwrites\"\n"
1686 "classname 12: \"Member\"\n"
1687 "infoname 1: \"Attribute\"\n"
1688 "infoname 2: \"Verification errors\"\n",
1689 name, label, orientation);
1691 fprintf (F, "\n"); /* a separator */
1694 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1695 const char *nm = get_irg_dump_name(irg);
1696 int len = strlen(nm), i, j;
1697 char *fname; /* filename to put the vcg information in */
1699 if (!suffix1) suffix1 = "";
1700 if (!suffix2) suffix2 = "";
1702 /** open file for vcg graph */
1703 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1705 /* strncpy (fname, nm, len); */ /* copy the filename */
1707 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1709 fname[j] = '@'; j++; fname[j] = '1'; j++;
1710 } else if (nm[i] == '@') {
1711 fname[j] = '@'; j++; fname[j] = '2'; j++;
1713 fname[j] = nm[i]; j++;
1717 strcat (fname, suffix1); /* append file suffix */
1718 strcat (fname, suffix2); /* append file suffix */
1719 strcat (fname, ".vcg"); /* append the .vcg suffix */
1720 F = fopen (fname, "w"); /* open file for writing */
1722 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1727 static void vcg_open_name (const char *name, char *suffix) {
1728 char *fname; /* filename to put the vcg information in */
1729 int i, j, len = strlen(name);
1731 if (!suffix) suffix = "";
1733 /** open file for vcg graph */
1734 fname = malloc (len * 2 + 5 + strlen(suffix));
1735 /* strcpy (fname, name);*/ /* copy the filename */
1737 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1738 if (name[i] == '/') {
1739 fname[j] = '@'; j++; fname[j] = '1'; j++;
1740 } else if (name[i] == '@') {
1741 fname[j] = '@'; j++; fname[j] = '2'; j++;
1743 fname[j] = name[i]; j++;
1747 strcat (fname, suffix);
1748 strcat (fname, ".vcg"); /* append the .vcg suffix */
1749 F = fopen (fname, "w"); /* open file for writing */
1751 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1756 static INLINE void dump_vcg_footer (void) {
1762 dump_vcg_footer(); /* print footer */
1763 fclose (F); /* close vcg file */
1766 /************************************************************************/
1767 /************************************************************************/
1768 /* Routines that dump all or parts of the firm representation to a file */
1769 /************************************************************************/
1770 /************************************************************************/
1772 /************************************************************************/
1773 /* Dump ir graphs, differnt formats and additional information. */
1774 /************************************************************************/
1776 /** Routine to dump a graph, blocks as conventional nodes.
1779 dump_ir_graph (ir_graph *irg)
1783 rem = current_ir_graph;
1785 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1787 current_ir_graph = irg;
1788 if (interprocedural_view) suffix = "-pure-ip";
1789 else suffix = "-pure";
1790 vcg_open (irg, dump_file_suffix, suffix);
1791 dump_vcg_header(get_irg_dump_name(irg), NULL);
1793 /* walk over the graph */
1794 /* dump_whole_node must be called in post visiting predecessors */
1795 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1797 /* dump the out edges in a separate walk */
1798 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1799 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1804 current_ir_graph = rem;
1809 dump_ir_block_graph (ir_graph *irg)
1814 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1816 if (interprocedural_view) suffix = "-ip";
1818 vcg_open (irg, dump_file_suffix, suffix);
1819 dump_vcg_header(get_irg_dump_name(irg), NULL);
1821 construct_block_lists(irg);
1823 for (i = 0; i < get_irp_n_irgs(); i++) {
1824 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1826 dump_graph(get_irp_irg(i));
1834 /** dumps a graph with type information
1837 dump_ir_graph_w_types (ir_graph *irg)
1839 ir_graph *rem = current_ir_graph;
1842 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1844 current_ir_graph = irg;
1846 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1847 else suffix = "-pure-wtypes";
1848 vcg_open (irg, dump_file_suffix, suffix);
1849 dump_vcg_header(get_irg_dump_name(irg), NULL);
1851 /* dump common ir graph */
1852 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1853 /* dump type info */
1854 type_walk_irg(irg, dump_type_info, NULL, NULL);
1855 inc_irg_visited(get_const_code_irg());
1856 /* dump edges from graph to type info */
1857 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1860 current_ir_graph = rem;
1864 dump_ir_block_graph_w_types (ir_graph *irg)
1868 ir_graph *rem = current_ir_graph;
1870 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1872 if (interprocedural_view) suffix = "-wtypes-ip";
1873 else suffix = "-wtypes";
1874 vcg_open (irg, dump_file_suffix, suffix);
1875 dump_vcg_header(get_irg_dump_name(irg), NULL);
1877 /* dump common blocked ir graph */
1878 construct_block_lists(irg);
1880 for (i = 0; i < get_irp_n_irgs(); i++) {
1881 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1883 dump_graph(get_irp_irg(i));
1888 /* dump type info */
1889 current_ir_graph = irg;
1890 type_walk_irg(irg, dump_type_info, NULL, NULL);
1891 inc_irg_visited(get_const_code_irg());
1893 /* dump edges from graph to type info */
1894 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1896 current_ir_graph = rem;
1900 /***********************************************************************/
1901 /* The following routines dump a control flow graph. */
1902 /***********************************************************************/
1905 dump_block_to_cfg (ir_node *block, void *env) {
1909 if (is_Block(block)) {
1910 /* This is a block. Dump a node for the block. */
1911 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1912 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1913 PRINT_NODEID(block);
1915 if (dump_dominator_information_flag)
1916 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1918 /* Dump the edges */
1919 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1920 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1921 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1922 fprintf (F, "edge: { sourcename: \"");
1923 PRINT_NODEID(block);
1924 fprintf (F, "\" targetname: \"");
1926 fprintf (F, "\"}\n");
1929 /* Dump dominator edge */
1930 if (dump_dominator_information_flag && get_Block_idom(block)) {
1931 pred = get_Block_idom(block);
1932 fprintf (F, "edge: { sourcename: \"");
1933 PRINT_NODEID(block);
1934 fprintf (F, "\" targetname: \"");
1936 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1942 dump_cfg (ir_graph *irg)
1944 ir_graph *rem = current_ir_graph;
1945 int ddif = dump_dominator_information_flag;
1946 int ipv = interprocedural_view;
1948 if(strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1950 current_ir_graph = irg;
1952 vcg_open (irg, dump_file_suffix, "-cfg");
1953 dump_vcg_header(get_irg_dump_name(irg), NULL);
1955 if (interprocedural_view) {
1956 printf("Warning: dumping cfg not in interprocedural view!\n");
1957 interprocedural_view = 0;
1960 if (get_irg_dom_state(irg) != dom_consistent)
1961 dump_dominator_information_flag = 0;
1963 /* walk over the blocks in the graph */
1964 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1965 dump_node (get_irg_bad(irg));
1967 dump_dominator_information_flag = ddif;
1968 interprocedural_view = ipv;
1970 current_ir_graph = rem;
1975 void dump_callgraph(char *filesuffix) {
1976 int i, n_irgs = get_irp_n_irgs();
1978 vcg_open_name ("Callgraph", filesuffix);
1979 dump_vcg_header("Callgraph", NULL);
1981 for (i = 0; i < n_irgs; ++i) {
1982 ir_graph *irg = get_irp_irg(i);
1983 entity *ent = get_irg_ent(irg);
1984 int j, n_callees = get_irg_n_callees(irg);
1986 dump_entity_node(ent);
1987 for (j = 0; j < n_callees; ++j) {
1988 entity *c = get_irg_entity(get_irg_callee(irg, j));
1989 int be = is_irg_callee_backedge(irg, j);
1992 "label:\"recursion\" color:red" :
1994 print_ent_ent_edge(F, ent, c, be, attr);
2002 /* Dump all irgs in interprocedural view to a single file. */
2003 void dump_all_cg_block_graph(void) {
2005 int rem_view = interprocedural_view;
2006 interprocedural_view = 1;
2008 vcg_open_name ("All_graphs", dump_file_suffix);
2009 dump_vcg_header("All_graphs", NULL);
2011 /* collect nodes in all irgs reachable in call graph*/
2012 for (i = 0; i < get_irp_n_irgs(); i++)
2013 ird_set_irg_link(get_irp_irg(i), NULL);
2015 cg_walk(clear_link, collect_node, NULL);
2017 /* dump all graphs */
2018 for (i = 0; i < get_irp_n_irgs(); i++) {
2019 current_ir_graph = get_irp_irg(i);
2020 assert(ird_get_irg_link(current_ir_graph));
2021 dump_graph(current_ir_graph);
2022 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2026 interprocedural_view = rem_view;
2029 /***********************************************************************/
2030 /* the following routines dumps type information without any ir nodes. */
2031 /***********************************************************************/
2034 dump_type_graph (ir_graph *irg)
2037 rem = current_ir_graph;
2039 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2041 current_ir_graph = irg;
2043 vcg_open (irg, dump_file_suffix, "-type");
2044 dump_vcg_header(get_irg_dump_name(irg), NULL);
2046 /* walk over the blocks in the graph */
2047 type_walk_irg(irg, dump_type_info, NULL, NULL);
2048 /* The walker for the const code can be called several times for the
2049 same (sub) experssion. So that no nodes are dumped several times
2050 we decrease the visited flag of the corresponding graph after each
2051 walk. So now increase it finally. */
2052 inc_irg_visited(get_const_code_irg());
2055 current_ir_graph = rem;
2059 dump_all_types (void)
2061 vcg_open_name ("All_types", dump_file_suffix);
2062 dump_vcg_header("All_types", NULL);
2063 type_walk(dump_type_info, NULL, NULL);
2064 inc_irg_visited(get_const_code_irg());
2069 dump_class_hierarchy (bool entities)
2071 vcg_open_name ("class_hierarchy", dump_file_suffix);
2072 dump_vcg_header("class_hierarchy", NULL);
2074 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2076 type_walk(dump_class_hierarchy_node, NULL, NULL);
2080 /***********************************************************************/
2081 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2083 /* dump_ir_block_graph */
2085 /* dump_type_graph */
2086 /* dump_ir_graph_w_types */
2087 /***********************************************************************/
2089 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2091 for (i=0; i < get_irp_n_irgs(); i++) {
2092 dmp_grph(get_irp_irg(i));
2097 /**********************************************************************************
2098 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2099 * packed together in one subgraph *
2100 **********************************************************************************/
2104 void dump_loops_standalone (ir_loop *loop) {
2105 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2107 ir_loop *son = NULL;
2109 /* Dump a new loop node. */
2110 dump_loop_node(loop);
2112 /* Dump the loop elements. */
2114 for(i = 0; i < get_loop_n_elements(loop); i++)
2116 le = get_loop_element(loop, i);
2118 if (get_kind(son) == k_ir_loop) {
2120 /* We are a loop son -> Recurse */
2122 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2123 fprintf(F, "\" }\n");
2124 fprintf (F, "edge: {sourcename: \"");
2126 fprintf (F, "\" targetname: \"");
2128 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2129 loop_node_started = 0;
2131 dump_loop_son_edge(loop, son_number++);
2132 dump_loops_standalone(son);
2134 else if (get_kind(son) == k_ir_node) {
2135 /* We are a loop node -> Collect firm nodes */
2137 ir_node *n = le.node;
2140 if (!loop_node_started) {
2141 /* Start a new node which contains all firm nodes of the current loop */
2142 fprintf (F, "node: { title: \"");
2144 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2145 loop_node_started = 1;
2151 bad |= dump_node_opcode(F, n);
2152 bad |= dump_node_mode (n);
2153 bad |= dump_node_typeinfo(n);
2155 bad |= dump_node_nodeattr(n);
2156 fprintf (F, " %ld", get_irn_node_nr(n));
2158 #if CALLGRAPH_LOOP_TREE
2160 assert(get_kind(son) == k_ir_graph);
2161 /* We are a loop node -> Collect firm graphs */
2163 ir_graph *n = (ir_graph *)le.node;
2165 if (!loop_node_started) {
2166 /* Start a new node which contains all firm nodes of the current loop */
2167 fprintf (F, "node: { title: \"");
2169 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2170 loop_node_started = 1;
2176 fprintf (F, " %s", get_irg_dump_name(n));
2181 if (loop_node_started) {
2182 fprintf(F, "\" }\n");
2183 fprintf (F, "edge: {sourcename: \"");
2185 fprintf (F, "\" targetname: \"");
2187 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2188 loop_node_started = 0;
2192 void dump_loop_tree(ir_graph *irg, char *suffix)
2194 ir_graph *rem = current_ir_graph;
2195 int el_rem = edge_label;
2198 /* @@@ AS: What does that do? */
2199 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2201 current_ir_graph = irg;
2203 vcg_open(irg, suffix, "-looptree");
2204 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2206 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2210 edge_label = el_rem;
2211 current_ir_graph = rem;
2214 #if CALLGRAPH_LOOP_TREE
2215 /* works, but the tree is meaningless. */
2216 void dump_callgraph_loop_tree(ir_loop *l, char *suffix) {
2217 vcg_open_name("callgraph_looptree", suffix);
2218 dump_vcg_header("callgraph_looptree", "top_to_bottom");
2219 dump_loops_standalone(l);
2225 /*******************************************************************************/
2226 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2227 /*******************************************************************************/
2229 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2230 int i, son_number = 0, node_number = 0;
2232 if (dump_loop_information_flag) dump_loop_node(loop);
2234 for (i = 0; i < get_loop_n_elements(loop); i++) {
2235 loop_element le = get_loop_element(loop, i);
2236 if (*(le.kind) == k_ir_loop) {
2237 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2239 collect_nodeloop(le.son, loopnodes);
2241 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2242 eset_insert(loopnodes, le.node);
2247 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2250 for(i = 0; i < get_loop_n_elements(loop); i++) {
2251 loop_element le = get_loop_element(loop, i);
2252 if (*(le.kind) == k_ir_loop) {
2254 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2256 if (is_Block(le.node)) start = 0; else start = -1;
2257 for (j = start; j < get_irn_arity(le.node); j++) {
2258 ir_node *pred = get_irn_n(le.node, j);
2259 if (!eset_contains(loopnodes, pred)) {
2260 eset_insert(extnodes, pred);
2261 if (!is_Block(pred)) {
2262 pred = get_nodes_block(pred);
2263 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2271 void dump_loop (ir_loop *l, char *suffix) {
2273 eset *loopnodes = eset_create();
2274 eset *extnodes = eset_create();
2277 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2278 vcg_open_name (name, suffix);
2279 dump_vcg_header(name, NULL);
2281 /* collect all nodes to dump */
2282 collect_nodeloop(l, loopnodes);
2283 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2285 /* build block lists */
2286 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2287 set_irn_link(n, NULL);
2288 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2289 set_irn_link(n, NULL);
2290 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2292 b = get_nodes_block(n);
2293 set_irn_link(n, get_irn_link(b));
2296 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2298 b = get_nodes_block(n);
2299 set_irn_link(n, get_irn_link(b));
2303 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2305 fprintf(F, "graph: { title: \"");
2307 fprintf(F, "\" label: \"");
2308 dump_node_opcode(F, b);
2309 fprintf (F, " %ld", get_irn_node_nr(b));
2310 fprintf(F, "\" status:clustered color:yellow\n");
2312 /* dump the blocks edges */
2313 dump_ir_data_edges(b);
2315 /* dump the nodes that go into the block */
2316 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2317 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2319 overrule_nodecolor = NULL;
2320 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2323 /* Close the vcg information for the block */
2325 dump_const_node_local(b);
2328 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2330 fprintf(F, "graph: { title: \"");
2332 fprintf(F, "\" label: \"");
2333 dump_node_opcode(F, b);
2334 fprintf (F, " %ld", get_irn_node_nr(b));
2335 fprintf(F, "\" status:clustered color:lightblue\n");
2337 /* dump the nodes that go into the block */
2338 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2339 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2341 overrule_nodecolor = NULL;
2342 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2345 /* Close the vcg information for the block */
2347 dump_const_node_local(b);
2351 eset_destroy(loopnodes);
2352 eset_destroy(extnodes);