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.
22 # include "irnode_t.h"
23 # include "irgraph_t.h"
24 # include "entity_t.h"
26 # include "firm_common_t.h"
31 # include "typewalk.h"
34 # include "type_or_entity.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 BLOCK_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
63 #define CF_EDGE_ATTR "class:13 color:red"
64 #define MEM_EDGE_ATTR "class:14 color:blue"
65 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
67 #define BACK_EDGE_ATTR "linestyle:dashed "
69 /* Attributes of edges between Firm nodes and type/entity nodes */
70 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
72 /* Attributes of edges in type/entity graphs. */
73 #define TYPE_METH_NODE_ATTR "color: lightyellow"
74 #define TYPE_CLASS_NODE_ATTR "color: green"
75 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
76 #define ENTITY_NODE_ATTR "color: yellow"
77 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
78 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
79 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
80 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
81 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
82 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
83 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
84 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
85 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
86 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
87 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
88 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
89 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
90 #define ENUM_ITEM_NODE_ATTR "color: green"
92 #if DEBUG_libfirm && NODEID_AS_LABEL
93 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
94 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
95 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
96 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
97 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
98 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
99 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
102 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
103 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
104 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
105 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
106 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
107 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
108 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
111 static const char *get_type_name_ex(type *tp, int *bad)
114 return get_type_name(tp);
119 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
124 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
125 fprintf(F, " targetname: "); PRINT_TYPEID(T);
126 vfprintf(F, fmt, ap);
131 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
136 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
137 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
138 vfprintf(F, fmt, ap);
143 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
148 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
149 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
150 vfprintf(F, fmt, ap);
155 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
160 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
161 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
162 vfprintf(F, fmt, ap);
167 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
172 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
173 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
174 vfprintf(F, fmt, ap);
179 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
184 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
185 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
187 vfprintf(F, fmt, ap);
192 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
197 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
198 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
199 vfprintf(F, fmt, ap);
204 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
209 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
210 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
211 vfprintf(F, fmt, ap);
216 /*******************************************************************/
217 /* global and ahead declarations */
218 /*******************************************************************/
220 /* A suffix to manipulate the file name. */
221 char *dump_file_suffix = "";
223 char *dump_file_filter = "";
225 /* file to dump to */
228 static void dump_whole_node(ir_node *n, void* env);
229 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
231 /*******************************************************************/
232 /* Helper functions. */
233 /*******************************************************************/
235 /* Use private link attr to be able to call dumper anywhere without
236 destroying link fields. */
238 static pmap *irdump_link_map = NULL;
240 static void init_irdump(void) {
241 /* We need a new, empty map. */
242 if (irdump_link_map) pmap_destroy(irdump_link_map);
243 irdump_link_map = pmap_create();
247 void *ird_get_irn_link(ir_node *n) {
249 if (!irdump_link_map) return NULL;
251 if (pmap_contains(irdump_link_map, (void *)n))
252 res = pmap_get(irdump_link_map, (void *)n);
256 void ird_set_irn_link(ir_node *n, void *x) {
257 if (!irdump_link_map) init_irdump();
258 pmap_insert(irdump_link_map, (void *)n, x);
261 void *ird_get_irg_link(ir_graph *irg) {
263 if (!irdump_link_map) return NULL;
265 if (pmap_contains(irdump_link_map, (void *)irg))
266 res = pmap_get(irdump_link_map, (void *)irg);
270 void ird_set_irg_link(ir_graph *irg, void *x) {
271 if (!irdump_link_map) init_irdump();
272 pmap_insert(irdump_link_map, (void *)irg, x);
275 static void clear_link(ir_node * node, void * env) {
276 ird_set_irn_link(node, NULL);
280 static int node_floats(ir_node *n) {
281 return ((get_op_pinned(get_irn_op(n)) == floats) &&
282 (get_irg_pinned(current_ir_graph) == floats));
285 static const char *get_ent_dump_name(entity *ent) {
287 return "<NULL entity>";
288 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
289 if (ent->ld_name) return get_id_str(ent->ld_name);
290 return get_id_str(ent->name);
293 static const char *get_irg_dump_name(ir_graph *irg) {
294 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
295 entity *ent = get_irg_ent(irg);
296 return get_ent_dump_name(ent);
299 static void collect_node(ir_node * node, void *env) {
302 || get_irn_op(node) == op_Bad
303 || get_irn_op(node) == op_Unknown) {
304 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
305 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
306 ARR_APP1(ir_node *, arr, node);
307 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
309 ir_node * block = get_nodes_block(node);
310 ird_set_irn_link(node, ird_get_irn_link(block));
311 ird_set_irn_link(block, node);
315 /** Construct lists to walk ir block-wise.
317 * Collects all blocks, nodes not pinned,
318 * Bad and Unknown into a flexible array in link field of
319 * irg they belong to. Sets the irg link field to NULL in all
320 * graphs not visited.
321 * Free the list with DEL_ARR_F. */
322 static ir_node ** construct_block_lists(ir_graph *irg) {
324 ir_graph *rem = current_ir_graph;
325 current_ir_graph = irg;
327 for (i = 0; i < get_irp_n_irgs(); i++)
328 ird_set_irg_link(get_irp_irg(i), NULL);
330 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
332 current_ir_graph = rem;
333 return ird_get_irg_link(irg);
336 /*******************************************************************/
337 /* flags to steer output */
338 /*******************************************************************/
340 /* A compiler option to turn off edge labels */
342 /* A compiler option to turn off dumping values of constant entities */
343 int const_entities = 1;
344 /* A compiler option to dump the keep alive edges */
345 int dump_keepalive = 0;
346 /* Compiler options to dump analysis information in dump_ir_graph */
347 int dump_out_edge_flag = 0;
348 int dump_dominator_information_flag = 0;
349 int dump_loop_information_flag = 0;
350 int dump_backedge_information_flag = 1;
351 int dump_const_local = 0;
352 bool opt_dump_analysed_type_info = 1;
353 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
355 char* overrule_nodecolor = NULL;
357 INLINE bool get_opt_dump_const_local(void) {
358 if (!dump_out_edge_flag && !dump_loop_information_flag)
359 return dump_const_local;
364 /* To turn off display of edge labels. Edge labels offen cause xvcg to
365 abort with a segmentation fault. */
366 void turn_off_edge_labels(void) {
370 void dump_consts_local(bool b) {
371 dump_const_local = b;
374 void turn_off_constant_entity_values(void) {
378 void dump_keepalive_edges(bool b) {
382 bool get_opt_dump_keepalive_edges(void) {
383 return dump_keepalive;
386 void dump_out_edges(void) {
387 dump_out_edge_flag = 1;
390 void dump_dominator_information(void) {
391 dump_dominator_information_flag = 1;
394 void dump_loop_information(void) {
395 dump_loop_information_flag = 1;
398 void dont_dump_loop_information(void) {
399 dump_loop_information_flag = 0;
402 void dump_backedge_information(bool b) {
403 dump_backedge_information_flag = b;
406 /* Dump the information of type field specified in ana/irtypeinfo.h.
407 * If the flag is set, the type name is output in [] in the node label,
408 * else it is output as info.
410 void dump_analysed_type_info(bool b) {
411 opt_dump_analysed_type_info = b;
414 void dump_pointer_values_to_info(bool b) {
415 opt_dump_pointer_values_to_info = b;
418 /*******************************************************************/
419 /* Routines to dump information about a single ir node. */
420 /*******************************************************************/
423 dump_node_opcode(FILE *F, ir_node *n)
427 switch(get_irn_opcode(n)) {
432 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
433 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
438 if (get_SymConst_kind(n) == linkage_ptr_info) {
439 /* don't use get_SymConst_ptr_info as it mangles the name. */
440 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
442 assert(get_kind(get_SymConst_type(n)) == k_type);
443 assert(get_type_ident(get_SymConst_type(n)));
444 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
445 if (get_SymConst_kind(n) == type_tag)
453 if (!interprocedural_view) fprintf(F, "Proj'");
454 else fprintf(F, "%s", get_irn_opname(n));
458 if (interprocedural_view) {
459 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
465 fprintf (F, "%s", get_irn_opname(n));
473 dump_node_mode (ir_node *n)
475 switch (get_irn_opcode(n)) {
494 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
501 static int dump_node_typeinfo(ir_node *n) {
504 if (opt_dump_analysed_type_info) {
505 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
506 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
507 type *tp = get_irn_type(n);
509 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
518 dump_node_nodeattr (ir_node *n)
522 switch (get_irn_opcode(n)) {
524 if (false && interprocedural_view) {
525 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
529 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
530 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
532 fprintf (F, "%ld", get_Proj_proj(n));
536 fprintf (F, "%ld", get_Filter_proj(n));
539 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
542 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
545 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
555 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
558 fprintf(F, "color: red");
561 switch (get_irn_opcode(n)) {
568 fprintf (F, "color: blue");
571 fprintf (F, "color: lightyellow");
574 fprintf (F, "color: green");
580 fprintf (F, "color: yellow");
583 PRINT_DEFAULT_NODE_ATTR;
586 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
589 static INLINE int dump_node_info(ir_node *n)
595 fprintf (F, " info1: \"");
596 if (opt_dump_pointer_values_to_info)
597 fprintf (F, "addr: %p \n", (void *)n);
598 fprintf (F, "visited: %ld \n", get_irn_visited(n));
599 irg = get_irn_irg(n);
600 if (irg != get_const_code_irg())
601 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
603 fprintf(F, "arity: %d", get_irn_arity(n));
604 if ((get_irn_op(n) == op_Block) ||
605 (get_irn_op(n) == op_Phi) ||
606 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
607 fprintf(F, " backedges:");
609 for (i = 0; i < get_irn_arity(n); i++)
610 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
615 switch (get_irn_opcode(n)) {
617 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
618 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
619 for (i = 0; i < get_method_n_params(tp); ++i)
620 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
623 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
626 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
629 entity *ent = get_Sel_entity(n);
632 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
633 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
636 fprintf(F, "<NULL entity>\n");
641 type *tp = get_Call_type(n);
642 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
643 for (i = 0; i < get_method_n_params(tp); ++i)
644 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
645 for (i = 0; i < get_method_n_ress(tp); ++i)
646 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
647 if (Call_has_callees(n)) {
648 fprintf(F, "possible callees: \n");
649 for (i = 0; i < get_Call_n_callees(n); i++) {
650 if (!get_Call_callee(n, i)) {
651 fprintf(F, " %d external method\n", i);
653 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
658 case iro_CallBegin: {
659 ir_node *call = get_CallBegin_call(n);
660 if (Call_has_callees(call)) {
661 fprintf(F, "possible callees: \n");
662 for (i = 0; i < get_Call_n_callees(call); i++) {
663 if (!get_Call_callee(call, i)) {
664 fprintf(F, " %d external method\n", i);
666 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
672 if (!interprocedural_view) {
673 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
674 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
675 for (i = 0; i < get_method_n_ress(tp); ++i)
676 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
680 type *tp = get_Const_type(n);
681 assert(tp != none_type);
682 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
686 if (interprocedural_view) {
687 fprintf(F, "intra predecessor nodes:\n");
688 for (i = 0; i < get_irn_intra_arity(n); i++) {
689 ir_node *pred = get_irn_intra_n(n, i);
690 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
693 fprintf(F, "inter predecessor nodes:\n");
694 for (i = 0; i < get_irn_inter_arity(n); i++) {
695 ir_node *pred = get_irn_inter_n(n, i);
696 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
697 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
704 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
705 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
706 if (get_irn_type(n) != none_type)
707 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
716 bool is_constlike_node(ir_node *n) {
717 ir_op *op = get_irn_op(n);
718 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
722 /* outputs the predecessors of n, that are constants, local. I.e.,
723 generates a copy of the constant predecessors for each node called with. */
724 static void dump_const_node_local(ir_node *n) {
726 if (!get_opt_dump_const_local()) return;
728 /* Use visited flag to avoid outputting nodes twice.
729 initialize it first. */
730 for (i = 0; i < get_irn_arity(n); i++) {
731 ir_node *con = get_irn_n(n, i);
732 if (is_constlike_node(con)) {
733 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
737 for (i = 0; i < get_irn_arity(n); i++) {
738 ir_node *con = get_irn_n(n, i);
739 if (is_constlike_node(con) && irn_not_visited(con)) {
742 mark_irn_visited(con);
743 /* Generate a new name for the node by appending the names of
745 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
746 fprintf(F, " label: \"");
747 bad |= dump_node_opcode(F, con);
748 dump_node_mode (con);
749 bad |= dump_node_typeinfo(con);
751 bad |= dump_node_nodeattr(con);
752 fprintf(F, " %ld", get_irn_node_nr(con));
754 bad |= dump_node_info(con);
755 dump_node_vcgattr(con, bad);
761 static void print_node_error(const char *p)
766 fprintf (F, " info2: \"%s\"", p);
769 static void dump_node(ir_node *n)
774 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
776 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
778 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
779 bad |= dump_node_opcode(F, n);
781 bad |= dump_node_typeinfo(n);
783 bad |= dump_node_nodeattr(n);
784 fprintf(F, " %ld", get_irn_node_nr(n));
786 bad |= dump_node_info(n);
788 dump_node_vcgattr(n, bad);
790 dump_const_node_local(n);
797 /* dump the edge to the block this node belongs to */
799 dump_ir_block_edge(ir_node *n) {
800 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
801 if (is_no_Block(n)) {
802 fprintf (F, "edge: { sourcename: \"");
804 fprintf (F, "\" targetname: \"");
805 PRINT_NODEID(get_nodes_block(n));
806 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
810 static void print_edge_vcgattr(ir_node *from, int to) {
813 if (dump_backedge_information_flag && is_backedge(from, to))
814 fprintf (F, BACK_EDGE_ATTR);
816 switch (get_irn_opcode(from)) {
818 fprintf (F, CF_EDGE_ATTR);
820 case iro_Start: break;
823 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
824 fprintf (F, CF_EDGE_ATTR);
825 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
826 fprintf (F, MEM_EDGE_ATTR);
829 case iro_EndReg: break;
830 case iro_EndExcept: break;
832 case iro_Break: break;
833 case iro_Cond: break;
836 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
838 case iro_Const: break;
839 case iro_SymConst:break;
842 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
844 case iro_CallBegin: break;
847 case iro_Minus: break;
853 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
861 case iro_Shrs: break;
864 case iro_Conv: break;
866 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
872 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
875 fprintf (F, MEM_EDGE_ATTR);
877 case iro_Tuple: break;
880 switch (get_irn_modecode(from)) {
882 fprintf (F, CF_EDGE_ATTR);
885 fprintf (F, MEM_EDGE_ATTR);
891 case iro_Unknown: break;
898 /* dump edges to our inputs */
900 dump_ir_data_edges(ir_node *n) {
901 int i, visited = get_irn_visited(n);
903 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
906 for (i = 0; i < get_irn_arity(n); i++) {
907 ir_node * pred = get_irn_n(n, i);
910 if ((interprocedural_view && get_irn_visited(pred) < visited))
911 continue; /* pred not dumped */
913 if (dump_backedge_information_flag && is_backedge(n, i))
914 fprintf (F, "backedge: {sourcename: \"");
916 fprintf (F, "edge: {sourcename: \"");
918 fprintf (F, "\" targetname: ");
919 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
920 PRINT_CONSTID(n, pred);
922 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
924 fprintf (F, " label: \"%d\" ", i);
925 print_edge_vcgattr(n, i);
930 /** Dumps a node and its edges but not the block edge
933 dump_node_wo_blockedge (ir_node *n, void* env) {
935 dump_ir_data_edges(n);
938 /** Dumps a node and its edges.
941 dump_whole_node (ir_node *n, void* env) {
942 dump_node_wo_blockedge(n, env);
943 if (!node_floats(n)) dump_ir_block_edge(n);
947 dump_const_node(ir_node *n, void *env) {
948 if (is_Block(n)) return;
949 dump_node_wo_blockedge(n, env);
952 /***********************************************************************/
953 /* the following routines dump the nodes/irgs bracketed to graphs. */
954 /***********************************************************************/
956 /** Dumps a constant expression as entity initializer, array bound ...
958 static void dump_const_expression(ir_node *value) {
959 ir_graph *rem = current_ir_graph;
960 int rem_dump_const_local = dump_const_local;
961 dump_const_local = 0;
962 current_ir_graph = get_const_code_irg();
963 irg_walk(value, dump_const_node, NULL, NULL);
964 /* Decrease visited flag so that we walk with the same flag for the next
965 expresssion. This guarantees that we don't dump the same node twice,
966 as for const expressions cse is performed to save memory. */
967 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
968 current_ir_graph = rem;
969 dump_const_local = rem_dump_const_local;
972 /** Dump a block as graph containing its nodes.
974 * Expects to find nodes belonging to the block as list in its
976 * Dumps the edges of all nodes including itself. */
978 dump_whole_block(ir_node *block) {
980 assert(is_Block(block));
982 fprintf(F, "graph: { title: \"");
984 fprintf(F, "\" label: \"");
985 dump_node_opcode(F, block);
986 fprintf (F, " %ld", get_irn_node_nr(block));
988 if (get_opt_dump_abstvals())
989 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
991 fprintf(F, "\" status:clustered color:%s \n",
992 get_Block_matured(block) ? "yellow" : "red");
994 /* dump the blocks edges */
995 dump_ir_data_edges(block);
997 /* dump the nodes that go into the block */
998 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1000 dump_ir_data_edges(node);
1003 /* Close the vcg information for the block */
1005 dump_const_node_local(block);
1007 dump_chi_term(F, block);
1012 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1013 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1015 dump_block_graph(ir_graph *irg) {
1017 ir_graph *rem = current_ir_graph;
1018 ir_node **arr = ird_get_irg_link(irg);
1019 current_ir_graph = irg;
1021 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1022 ir_node * node = arr[i];
1023 if (is_Block(node)) {
1024 /* Dumps the block and all the nodes in the block, which are to
1025 be found in Block->link. */
1026 dump_whole_block(node);
1028 /* Nodes that are not in a Block. */
1030 dump_ir_data_edges(node);
1034 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1036 current_ir_graph = rem;
1039 /** Dumps an irg as a graph.
1040 * If interprocedural view edges can point to nodes out of this graph.
1042 static void dump_graph(ir_graph *irg) {
1044 fprintf(F, "graph: { title: \"");
1046 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1047 get_ent_dump_name(get_irg_ent(irg)));
1049 dump_block_graph (irg);
1051 /* Close the vcg information for the irg */
1052 fprintf(F, "}\n\n");
1055 /*******************************************************************/
1056 /* Basic type and entity nodes and edges. */
1057 /*******************************************************************/
1059 /* dumps the edges between nodes and their type or entity attributes. */
1060 static void dump_node2type_edges (ir_node *n, void *env)
1064 switch (get_irn_opcode(n)) {
1066 /* @@@ some consts have an entity */
1069 if ( (get_SymConst_kind(n) == type_tag)
1070 || (get_SymConst_kind(n) == size))
1072 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1076 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1079 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1082 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1085 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1088 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1096 static void print_type_info(type *tp) {
1097 if (get_type_state(tp) == layout_undefined) {
1098 fprintf(F, "state: layout_undefined\n");
1100 fprintf(F, "state: layout_fixed,\n");
1102 if (get_type_mode(tp))
1103 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1104 fprintf(F, "size: %dB,\n", get_type_size(tp));
1107 static void print_typespecific_info(type *tp) {
1108 switch (get_type_tpop_code(tp)) {
1111 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1118 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1119 fprintf(F, "params: %d\n", get_method_n_params(tp));
1120 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1128 case tpo_enumeration:
1142 static void print_typespecific_vcgattr(type *tp) {
1143 switch (get_type_tpop_code(tp)) {
1146 if (peculiarity_existent == get_class_peculiarity(tp))
1147 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1149 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1153 fprintf (F, " " TYPE_METH_NODE_ATTR);
1164 case tpo_enumeration:
1177 static int print_type_node(type *tp)
1181 fprintf (F, "node: {title: ");
1183 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1184 fprintf (F, " info1: \"");
1185 print_type_info(tp);
1186 print_typespecific_info(tp);
1188 print_typespecific_vcgattr(tp);
1194 #define X(a) case a: fprintf(F, #a); break
1195 void dump_entity_node(entity *ent)
1197 fprintf (F, "node: {title: \"");
1198 PRINT_ENTID(ent); fprintf(F, "\"");
1199 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1200 fprintf (F, "label: ");
1201 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1202 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1204 fprintf (F, "\nallocation: ");
1205 switch (get_entity_allocation(ent)) {
1206 X(allocation_dynamic);
1207 X(allocation_automatic);
1208 X(allocation_static);
1209 X(allocation_parameter);
1212 fprintf (F, "\nvisibility: ");
1213 switch (get_entity_visibility(ent)) {
1214 X(visibility_local);
1215 X(visibility_external_visible);
1216 X(visibility_external_allocated);
1219 fprintf (F, "\nvariability: ");
1220 switch (get_entity_variability(ent)) {
1221 X(variability_uninitialized);
1222 X(variability_initialized);
1223 X(variability_part_constant);
1224 X(variability_constant);
1227 fprintf (F, "\nvolatility: ");
1228 switch (get_entity_volatility(ent)) {
1229 X(volatility_non_volatile);
1230 X(volatility_is_volatile);
1233 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1234 fprintf(F, "\nname: %s\nld_name: %s",
1235 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1236 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1237 if (is_method_type(get_entity_type(ent))) {
1238 if (get_entity_irg(ent)) /* can be null */
1239 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1241 { fprintf (F, "\nirg = NULL"); }
1243 fprintf(F, "\"\n}\n");
1247 static void dump_enum_item(type *tp, int pos)
1250 ident *id = get_enumeration_nameid(tp, pos);
1251 tarval *tv = get_enumeration_enum(tp, pos);
1253 tarval_snprintf(buf, sizeof(buf), tv);
1254 fprintf (F, "node: {title: \"");
1255 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1256 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1257 fprintf (F, "label: ");
1258 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1259 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1262 /* dumps a type or entity and it's edges. */
1264 dump_type_info (type_or_ent *tore, void *env) {
1265 int i = 0; /* to shutup gcc */
1267 /* dump this type or entity */
1269 switch (get_kind(tore)) {
1272 entity *ent = (entity *)tore;
1275 dump_entity_node(ent);
1277 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1278 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1279 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1280 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1281 if(is_class_type(get_entity_owner(ent))) {
1282 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1283 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1286 /* attached subgraphs */
1287 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1288 if (is_atomic_entity(ent)) {
1289 value = get_atomic_ent_value(ent);
1291 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1292 /* DDMN(value); $$$ */
1293 dump_const_expression(value);
1296 if (is_compound_entity(ent)) {
1297 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1298 value = get_compound_ent_value(ent, i);
1300 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1301 dump_const_expression(value);
1302 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1304 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1305 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1306 get_compound_ent_value_member(ent, i), i);
1315 type *tp = (type *)tore;
1316 print_type_node(tp);
1317 /* and now the edges */
1318 switch (get_type_tpop_code(tp)) {
1321 for (i=0; i < get_class_n_supertypes(tp); i++) {
1322 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1325 for (i=0; i < get_class_n_members(tp); i++) {
1326 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1331 for (i=0; i < get_struct_n_members(tp); i++) {
1332 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1337 for (i = 0; i < get_method_n_params(tp); i++)
1339 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1341 for (i = 0; i < get_method_n_ress(tp); i++)
1343 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1348 for (i = 0; i < get_union_n_members(tp); i++)
1350 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1355 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1356 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1357 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1358 ir_node *upper = get_array_upper_bound(tp, i);
1359 ir_node *lower = get_array_lower_bound(tp, i);
1360 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1361 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1362 dump_const_expression(upper);
1363 dump_const_expression(lower);
1367 case tpo_enumeration:
1369 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1370 dump_enum_item(tp, i);
1371 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1376 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1384 break; /* case k_type */
1387 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1389 } /* switch kind_or_entity */
1392 /** For dumping class hierarchies.
1393 * Dumps a class type node and a superclass edge.
1394 * If env != null dumps entities of classes and overwrites edges.
1397 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1398 int i = 0; /* to shutup gcc */
1400 /* dump this type or entity */
1401 switch (get_kind(tore)) {
1403 entity *ent = (entity *)tore;
1404 if (get_entity_owner(ent) == get_glob_type()) break;
1405 if ((env) && is_class_type(get_entity_owner(ent))) {
1407 dump_entity_node(ent);
1409 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1410 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1412 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1415 } break; /* case k_entity */
1418 type *tp = (type *)tore;
1419 if (tp == get_glob_type()) break;
1420 switch (get_type_tpop_code(tp)) {
1422 print_type_node(tp);
1423 /* and now the edges */
1424 for (i=0; i < get_class_n_supertypes(tp); i++)
1426 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1432 break; /* case k_type */
1435 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1437 } /* switch kind_or_entity */
1440 /*******************************************************************/
1441 /* dump analysis information that is expressed in graph terms. */
1442 /*******************************************************************/
1444 /* dump out edges */
1446 dump_out_edge (ir_node *n, void* env) {
1448 for (i = 0; i < get_irn_n_outs(n); i++) {
1449 assert(get_irn_out(n, i));
1450 fprintf (F, "edge: {sourcename: \"");
1452 fprintf (F, "\" targetname: \"");
1453 PRINT_NODEID(get_irn_out(n, i));
1454 fprintf (F, "\" color: red linestyle: dashed");
1460 dump_loop_label(ir_loop *loop) {
1461 fprintf (F, "loop %d, %d sons, %d nodes",
1462 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1465 static INLINE void dump_loop_info(ir_loop *loop) {
1466 fprintf (F, " info1: \"");
1467 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1468 #if DEBUG_libfirm /* GL @@@ debug analyses */
1469 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1475 dump_loop_node(ir_loop *loop) {
1476 fprintf (F, "node: {title: \"");
1478 fprintf (F, "\" label: \"");
1479 dump_loop_label(loop);
1481 dump_loop_info(loop);
1487 dump_loop_node_edge (ir_loop *loop, int i) {
1489 fprintf (F, "edge: {sourcename: \"");
1491 fprintf (F, "\" targetname: \"");
1492 PRINT_NODEID(get_loop_node(loop, i));
1493 fprintf (F, "\" color: green");
1498 dump_loop_son_edge (ir_loop *loop, int i) {
1500 fprintf (F, "edge: {sourcename: \"");
1502 fprintf (F, "\" targetname: \"");
1503 PRINT_LOOPID(get_loop_son(loop, i));
1504 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1505 get_loop_element_pos(loop, get_loop_son(loop, i)));
1509 void dump_loops (ir_loop *loop) {
1511 /* dump this loop node */
1512 dump_loop_node(loop);
1514 /* dump edges to nodes in loop -- only if it is a real loop */
1515 if (get_loop_depth(loop) != 0) {
1516 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1517 dump_loop_node_edge(loop, i);
1520 for (i = 0; i < get_loop_n_sons(loop); i++) {
1521 dump_loops(get_loop_son(loop, i));
1522 dump_loop_son_edge(loop, i);
1527 void dump_loop_nodes_into_graph(ir_graph *irg) {
1528 ir_graph *rem = current_ir_graph;
1529 current_ir_graph = irg;
1531 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1533 current_ir_graph = rem;
1537 /************************************************************************/
1538 /* open and close vcg file */
1539 /************************************************************************/
1542 dump_vcg_header(const char *name, const char *orientation) {
1551 if (!orientation) orientation = "bottom_to_top";
1555 "graph: { title: \"ir graph of %s\"\n"
1556 "display_edge_labels: %s\n"
1557 "layoutalgorithm: mindepth\n"
1558 "manhattan_edges: yes\n"
1559 "port_sharing: no\n"
1561 "classname 1: \"Data\"\n"
1562 "classname 2: \"Block\"\n"
1563 "classname 13:\"Control Flow\"\n"
1564 "classname 14:\"Memory\"\n"
1565 "classname 15:\"Dominators\"\n"
1566 "classname 3: \"Entity type\"\n"
1567 "classname 4: \"Entity owner\"\n"
1568 "classname 5: \"Method Param\"\n"
1569 "classname 6: \"Method Res\"\n"
1570 "classname 7: \"Super\"\n"
1571 "classname 8: \"Union\"\n"
1572 "classname 9: \"Points-to\"\n"
1573 "classname 10: \"Array Element Type\"\n"
1574 "classname 11: \"Overwrites\"\n"
1575 "classname 12: \"Member\"\n"
1576 "infoname 1: \"Attribute\"\n"
1577 "infoname 2: \"Verification errors\"\n",
1578 name, label, orientation);
1580 fprintf (F, "\n"); /* a separator */
1583 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1584 const char *nm = get_irg_dump_name(irg);
1585 int len = strlen(nm), i, j;
1586 char *fname; /* filename to put the vcg information in */
1588 if (!suffix1) suffix1 = "";
1589 if (!suffix2) suffix2 = "";
1591 /** open file for vcg graph */
1592 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1594 //strncpy (fname, nm, len); /* copy the filename */
1596 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1598 fname[j] = '@'; j++; fname[j] = '1'; j++;
1599 } else if (nm[i] == '@') {
1600 fname[j] = '@'; j++; fname[j] = '2'; j++;
1602 fname[j] = nm[i]; j++;
1606 strcat (fname, suffix1); /* append file suffix */
1607 strcat (fname, suffix2); /* append file suffix */
1608 strcat (fname, ".vcg"); /* append the .vcg suffix */
1609 F = fopen (fname, "w"); /* open file for writing */
1611 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1616 static void vcg_open_name (const char *name, char *suffix) {
1617 char *fname; /* filename to put the vcg information in */
1618 int i, j, len = strlen(name);
1620 if (!suffix) suffix = "";
1622 /** open file for vcg graph */
1623 fname = malloc (len * 2 + 5 + strlen(suffix));
1624 //strcpy (fname, name); /* copy the filename */
1626 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1627 if (name[i] == '/') {
1628 fname[j] = '@'; j++; fname[j] = '1'; j++;
1629 } else if (name[i] == '@') {
1630 fname[j] = '@'; j++; fname[j] = '2'; j++;
1632 fname[j] = name[i]; j++;
1636 strcat (fname, suffix);
1637 strcat (fname, ".vcg"); /* append the .vcg suffix */
1638 F = fopen (fname, "w"); /* open file for writing */
1640 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1645 static INLINE void dump_vcg_footer (void) {
1651 dump_vcg_footer(); /* print footer */
1652 fclose (F); /* close vcg file */
1655 /************************************************************************/
1656 /************************************************************************/
1657 /* Routines that dump all or parts of the firm representation to a file */
1658 /************************************************************************/
1659 /************************************************************************/
1661 /************************************************************************/
1662 /* Dump ir graphs, differnt formats and additional information. */
1663 /************************************************************************/
1665 /** Routine to dump a graph, blocks as conventional nodes.
1668 dump_ir_graph (ir_graph *irg)
1672 rem = current_ir_graph;
1674 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1676 current_ir_graph = irg;
1677 if (interprocedural_view) suffix = "-pure-ip";
1678 else suffix = "-pure";
1679 vcg_open (irg, dump_file_suffix, suffix);
1680 dump_vcg_header(get_irg_dump_name(irg), NULL);
1682 /* walk over the graph */
1683 /* dump_whole_node must be called in post visiting predecessors */
1684 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1686 /* dump the out edges in a separate walk */
1687 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1688 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1693 current_ir_graph = rem;
1698 dump_ir_block_graph (ir_graph *irg)
1703 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1705 if (interprocedural_view) suffix = "-ip";
1707 vcg_open (irg, dump_file_suffix, suffix);
1708 dump_vcg_header(get_irg_dump_name(irg), NULL);
1710 construct_block_lists(irg);
1712 for (i = 0; i < get_irp_n_irgs(); i++) {
1713 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1715 dump_graph(get_irp_irg(i));
1723 /** dumps a graph with type information
1726 dump_ir_graph_w_types (ir_graph *irg)
1728 ir_graph *rem = current_ir_graph;
1731 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1733 current_ir_graph = irg;
1735 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1736 else suffix = "-pure-wtypes";
1737 vcg_open (irg, dump_file_suffix, suffix);
1738 dump_vcg_header(get_irg_dump_name(irg), NULL);
1740 /* dump common ir graph */
1741 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1742 /* dump type info */
1743 type_walk_irg(irg, dump_type_info, NULL, NULL);
1744 inc_irg_visited(get_const_code_irg());
1745 /* dump edges from graph to type info */
1746 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1749 current_ir_graph = rem;
1753 dump_ir_block_graph_w_types (ir_graph *irg)
1757 ir_graph *rem = current_ir_graph;
1759 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1761 if (interprocedural_view) suffix = "-wtypes-ip";
1762 else suffix = "-wtypes";
1763 vcg_open (irg, dump_file_suffix, suffix);
1764 dump_vcg_header(get_irg_dump_name(irg), NULL);
1766 /* dump common blocked ir graph */
1767 construct_block_lists(irg);
1769 for (i = 0; i < get_irp_n_irgs(); i++) {
1770 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1772 dump_graph(get_irp_irg(i));
1777 /* dump type info */
1778 current_ir_graph = irg;
1779 type_walk_irg(irg, dump_type_info, NULL, NULL);
1780 inc_irg_visited(get_const_code_irg());
1782 /* dump edges from graph to type info */
1783 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1785 current_ir_graph = rem;
1789 /***********************************************************************/
1790 /* The following routines dump a control flow graph. */
1791 /***********************************************************************/
1794 dump_block_to_cfg (ir_node *block, void *env) {
1798 if (is_Block(block)) {
1799 /* This is a block. Dump a node for the block. */
1800 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1801 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1802 PRINT_NODEID(block);
1804 if (dump_dominator_information_flag)
1805 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1807 /* Dump the edges */
1808 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1809 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1810 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1811 fprintf (F, "edge: { sourcename: \"");
1812 PRINT_NODEID(block);
1813 fprintf (F, "\" targetname: \"");
1815 fprintf (F, "\"}\n");
1818 /* Dump dominator edge */
1819 if (dump_dominator_information_flag && get_Block_idom(block)) {
1820 pred = get_Block_idom(block);
1821 fprintf (F, "edge: { sourcename: \"");
1822 PRINT_NODEID(block);
1823 fprintf (F, "\" targetname: \"");
1825 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1831 dump_cfg (ir_graph *irg)
1833 ir_graph *rem = current_ir_graph;
1834 int ddif = dump_dominator_information_flag;
1835 int ipv = interprocedural_view;
1837 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1839 current_ir_graph = irg;
1841 vcg_open (irg, dump_file_suffix, "-cfg");
1842 dump_vcg_header(get_irg_dump_name(irg), NULL);
1844 if (interprocedural_view) {
1845 printf("Warning: dumping cfg not in interprocedural view!\n");
1846 interprocedural_view = 0;
1849 if (get_irg_dom_state(irg) != dom_consistent)
1850 dump_dominator_information_flag = 0;
1852 /* walk over the blocks in the graph */
1853 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1854 dump_node (get_irg_bad(irg));
1856 dump_dominator_information_flag = ddif;
1857 interprocedural_view = ipv;
1859 current_ir_graph = rem;
1864 /* Dump all irgs in interprocedural view to a single file. */
1865 void dump_all_cg_block_graph(void) {
1867 int rem_view = interprocedural_view;
1868 interprocedural_view = 1;
1870 vcg_open_name ("All_graphs", dump_file_suffix);
1871 dump_vcg_header("All_graphs", NULL);
1873 /* collect nodes in all irgs reachable in call graph*/
1874 for (i = 0; i < get_irp_n_irgs(); i++)
1875 ird_set_irg_link(get_irp_irg(i), NULL);
1877 cg_walk(clear_link, collect_node, NULL);
1879 /* dump all graphs */
1880 for (i = 0; i < get_irp_n_irgs(); i++) {
1881 current_ir_graph = get_irp_irg(i);
1882 assert(ird_get_irg_link(current_ir_graph));
1883 dump_graph(current_ir_graph);
1884 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1888 interprocedural_view = rem_view;
1891 /***********************************************************************/
1892 /* the following routines dumps type information without any ir nodes. */
1893 /***********************************************************************/
1896 dump_type_graph (ir_graph *irg)
1899 rem = current_ir_graph;
1901 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1903 current_ir_graph = irg;
1905 vcg_open (irg, dump_file_suffix, "-type");
1906 dump_vcg_header(get_irg_dump_name(irg), NULL);
1908 /* walk over the blocks in the graph */
1909 type_walk_irg(irg, dump_type_info, NULL, NULL);
1910 /* The walker for the const code can be called several times for the
1911 same (sub) experssion. So that no nodes are dumped several times
1912 we decrease the visited flag of the corresponding graph after each
1913 walk. So now increase it finally. */
1914 inc_irg_visited(get_const_code_irg());
1917 current_ir_graph = rem;
1921 dump_all_types (void)
1923 vcg_open_name ("All_types", dump_file_suffix);
1924 dump_vcg_header("All_types", NULL);
1925 type_walk(dump_type_info, NULL, NULL);
1926 inc_irg_visited(get_const_code_irg());
1931 dump_class_hierarchy (bool entities)
1933 vcg_open_name ("class_hierarchy", dump_file_suffix);
1934 dump_vcg_header("class_hierarchy", NULL);
1936 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1938 type_walk(dump_class_hierarchy_node, NULL, NULL);
1942 /***********************************************************************/
1943 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1945 /* dump_ir_block_graph */
1947 /* dump_type_graph */
1948 /* dump_ir_graph_w_types */
1949 /***********************************************************************/
1951 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1953 for (i=0; i < get_irp_n_irgs(); i++) {
1954 dmp_grph(get_irp_irg(i));
1959 /**********************************************************************************
1960 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1961 * packed together in one subgraph *
1962 **********************************************************************************/
1966 void dump_loops_standalone (ir_loop *loop) {
1967 int i, loop_node_started = 0, son_number = 0, first = 0;
1969 ir_loop *son = NULL;
1971 /* Dump a new loop node. */
1972 dump_loop_node(loop);
1974 /* Dump the loop elements. */
1976 if (get_kind(son) == k_ir_loop)
1978 /* We are a loop son -> Recurse */
1979 le = get_loop_element(loop, i);
1982 if (get_kind(son) == k_ir_loop) {
1983 /* We are a loop son -> Recurse */
1985 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
1986 fprintf(F, "\" }\n");
1987 fprintf (F, "edge: {sourcename: \"");
1989 fprintf (F, "\" targetname: \"");
1991 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1992 loop_node_started = 0;
1994 dump_loop_son_edge(loop, son_number++);
1995 dump_loops_standalone(son);
1998 /* We are a loop node -> Collect firm nodes */
2000 ir_node *n = le.node;
2002 if (!loop_node_started) {
2003 /* Start a new node which contains all firm nodes of the current loop */
2004 fprintf (F, "node: { title: \"");
2006 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2007 loop_node_started = 1;
2013 dump_node_opcode(F, n);
2015 dump_node_typeinfo(n);
2017 dump_node_nodeattr(n);
2018 fprintf (F, " %ld", get_irn_node_nr(n));
2022 if (loop_node_started) {
2023 fprintf(F, "\" }\n");
2024 fprintf (F, "edge: {sourcename: \"");
2026 fprintf (F, "\" targetname: \"");
2028 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2029 loop_node_started = 0;
2033 void dump_loop_tree(ir_graph *irg, char *suffix)
2035 ir_graph *rem = current_ir_graph;
2036 int el_rem = edge_label;
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, suffix, "-looptree");
2044 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2046 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2050 edge_label = el_rem;
2051 current_ir_graph = rem;
2055 /*******************************************************************************/
2056 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2057 /*******************************************************************************/
2059 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2060 int i, son_number = 0, node_number = 0;
2062 if (dump_loop_information_flag) dump_loop_node(loop);
2064 for (i = 0; i < get_loop_n_elements(loop); i++) {
2065 loop_element le = get_loop_element(loop, i);
2066 if (*(le.kind) == k_ir_loop) {
2067 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2069 collect_nodeloop(le.son, loopnodes);
2071 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2072 eset_insert(loopnodes, le.node);
2077 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2080 for(i = 0; i < get_loop_n_elements(loop); i++) {
2081 loop_element le = get_loop_element(loop, i);
2082 if (*(le.kind) == k_ir_loop) {
2084 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2086 if (is_Block(le.node)) start = 0; else start = -1;
2087 for (j = start; j < get_irn_arity(le.node); j++) {
2088 ir_node *pred = get_irn_n(le.node, j);
2089 if (!eset_contains(loopnodes, pred)) {
2090 eset_insert(extnodes, pred);
2091 if (!is_Block(pred)) {
2092 pred = get_nodes_block(pred);
2093 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2101 void dump_loop (ir_loop *l, char *suffix) {
2103 eset *loopnodes = eset_create();
2104 eset *extnodes = eset_create();
2107 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2108 vcg_open_name (name, suffix);
2109 dump_vcg_header(name, NULL);
2111 /* collect all nodes to dump */
2112 collect_nodeloop(l, loopnodes);
2113 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2115 /* build block lists */
2116 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2117 set_irn_link(n, NULL);
2118 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2119 set_irn_link(n, NULL);
2120 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2122 b = get_nodes_block(n);
2123 set_irn_link(n, get_irn_link(b));
2126 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2128 b = get_nodes_block(n);
2129 set_irn_link(n, get_irn_link(b));
2133 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2135 fprintf(F, "graph: { title: \"");
2137 fprintf(F, "\" label: \"");
2138 dump_node_opcode(F, b);
2139 fprintf (F, " %ld", get_irn_node_nr(b));
2140 fprintf(F, "\" status:clustered color:yellow\n");
2142 /* dump the blocks edges */
2143 dump_ir_data_edges(b);
2145 /* dump the nodes that go into the block */
2146 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2147 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2149 overrule_nodecolor = NULL;
2150 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2153 /* Close the vcg information for the block */
2155 dump_const_node_local(b);
2158 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2160 fprintf(F, "graph: { title: \"");
2162 fprintf(F, "\" label: \"");
2163 dump_node_opcode(F, b);
2164 fprintf (F, " %ld", get_irn_node_nr(b));
2165 fprintf(F, "\" status:clustered color:lightblue\n");
2167 /* dump the nodes that go into the block */
2168 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2169 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2171 overrule_nodecolor = NULL;
2172 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2175 /* Close the vcg information for the block */
2177 dump_const_node_local(b);
2181 eset_destroy(loopnodes);
2182 eset_destroy(extnodes);