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"
47 void dump_chi_term(FILE *FL, ir_node *n);
48 void dump_state(FILE *FL, ir_node *n);
49 int get_opt_dump_abstvals(void);
50 typedef unsigned long SeqNo;
51 SeqNo get_Block_seqno(ir_node *n);
54 /* Attributes of nodes */
55 #define PRINT_DEFAULT_NODE_ATTR
56 #define DEFAULT_NODE_ATTR " "
57 #define DEFAULT_TYPE_ATTRIBUTE " "
58 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
60 /* Attributes of edges between Firm nodes */
61 #define BLOCK_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
62 #define CF_EDGE_ATTR "class:13 color:red"
63 #define MEM_EDGE_ATTR "class:14 color:blue"
64 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
66 #define BACK_EDGE_ATTR "linestyle:dashed "
68 /* Attributes of edges between Firm nodes and type/entity nodes */
69 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
71 /* Attributes of edges in type/entity graphs. */
72 #define TYPE_METH_NODE_ATTR "color: lightyellow"
73 #define TYPE_CLASS_NODE_ATTR "color: green"
74 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
75 #define ENTITY_NODE_ATTR "color: yellow"
76 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
77 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
78 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
79 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
80 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
81 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
82 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
83 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
84 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
85 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
86 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
87 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
88 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
89 #define ENUM_ITEM_NODE_ATTR "color: green"
91 #if DEBUG_libfirm && NODEID_AS_LABEL
92 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
93 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
94 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
95 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
96 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
97 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
98 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
101 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
102 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
103 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
104 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
105 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
106 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
107 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
110 static const char *get_type_name_ex(type *tp, int *bad)
113 return get_type_name(tp);
118 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
123 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
124 fprintf(F, " targetname: "); PRINT_TYPEID(T);
125 vfprintf(F, fmt, ap);
130 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
135 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
136 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
137 vfprintf(F, fmt, ap);
142 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
147 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
148 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
149 vfprintf(F, fmt, ap);
154 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
159 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
160 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
161 vfprintf(F, fmt, ap);
166 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
171 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
172 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
173 vfprintf(F, fmt, ap);
178 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
183 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
184 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
186 vfprintf(F, fmt, ap);
191 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
196 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
197 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
198 vfprintf(F, fmt, ap);
203 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
208 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
209 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
210 vfprintf(F, fmt, ap);
215 /*******************************************************************/
216 /* global and ahead declarations */
217 /*******************************************************************/
219 /* A suffix to manipulate the file name. */
220 char *dump_file_suffix = "";
222 char *dump_file_filter = "";
224 /* file to dump to */
227 static void dump_whole_node(ir_node *n, void* env);
228 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
230 /*******************************************************************/
231 /* Helper functions. */
232 /*******************************************************************/
234 /* Use private link attr to be able to call dumper anywhere without
235 destroying link fields. */
237 static pmap *irdump_link_map = NULL;
239 static void init_irdump(void) {
240 /* We need a new, empty map. */
241 if (irdump_link_map) pmap_destroy(irdump_link_map);
242 irdump_link_map = pmap_create();
246 void *ird_get_irn_link(ir_node *n) {
248 if (!irdump_link_map) return NULL;
250 if (pmap_contains(irdump_link_map, (void *)n))
251 res = pmap_get(irdump_link_map, (void *)n);
255 void ird_set_irn_link(ir_node *n, void *x) {
256 if (!irdump_link_map) init_irdump();
257 pmap_insert(irdump_link_map, (void *)n, x);
260 void *ird_get_irg_link(ir_graph *irg) {
262 if (!irdump_link_map) return NULL;
264 if (pmap_contains(irdump_link_map, (void *)irg))
265 res = pmap_get(irdump_link_map, (void *)irg);
269 void ird_set_irg_link(ir_graph *irg, void *x) {
270 if (!irdump_link_map) init_irdump();
271 pmap_insert(irdump_link_map, (void *)irg, x);
274 static void clear_link(ir_node * node, void * env) {
275 ird_set_irn_link(node, NULL);
279 static int node_floats(ir_node *n) {
280 return ((get_op_pinned(get_irn_op(n)) == floats) &&
281 (get_irg_pinned(current_ir_graph) == floats));
284 static const char *get_ent_dump_name(entity *ent) {
286 return "<NULL entity>";
287 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
288 if (ent->ld_name) return get_id_str(ent->ld_name);
289 return get_id_str(ent->name);
292 static const char *get_irg_dump_name(ir_graph *irg) {
293 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
294 entity *ent = get_irg_ent(irg);
295 return get_ent_dump_name(ent);
298 static void collect_node(ir_node * node, void *env) {
301 || get_irn_op(node) == op_Bad
302 || get_irn_op(node) == op_Unknown) {
303 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
304 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
305 ARR_APP1(ir_node *, arr, node);
306 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
308 ir_node * block = get_nodes_block(node);
309 ird_set_irn_link(node, ird_get_irn_link(block));
310 ird_set_irn_link(block, node);
314 /** Construct lists to walk ir block-wise.
316 * Collects all blocks, nodes not pinned,
317 * Bad and Unknown into a flexible array in link field of
318 * irg they belong to. Sets the irg link field to NULL in all
319 * graphs not visited.
320 * Free the list with DEL_ARR_F. */
321 static ir_node ** construct_block_lists(ir_graph *irg) {
323 ir_graph *rem = current_ir_graph;
324 current_ir_graph = irg;
326 for (i = 0; i < get_irp_n_irgs(); i++)
327 ird_set_irg_link(get_irp_irg(i), NULL);
329 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
331 current_ir_graph = rem;
332 return ird_get_irg_link(irg);
335 /*******************************************************************/
336 /* flags to steer output */
337 /*******************************************************************/
339 /* A compiler option to turn off edge labels */
341 /* A compiler option to turn off dumping values of constant entities */
342 int const_entities = 1;
343 /* A compiler option to dump the keep alive edges */
344 int dump_keepalive = 0;
345 /* Compiler options to dump analysis information in dump_ir_graph */
346 int dump_out_edge_flag = 0;
347 int dump_dominator_information_flag = 0;
348 int dump_loop_information_flag = 0;
349 int dump_backedge_information_flag = 1;
350 int dump_const_local = 0;
351 bool opt_dump_analysed_type_info = 1;
352 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
354 char* overrule_nodecolor = NULL;
356 INLINE bool get_opt_dump_const_local(void) {
357 if (!dump_out_edge_flag && !dump_loop_information_flag)
358 return dump_const_local;
363 /* To turn off display of edge labels. Edge labels offen cause xvcg to
364 abort with a segmentation fault. */
365 void turn_off_edge_labels(void) {
369 void dump_consts_local(bool b) {
370 dump_const_local = b;
373 void turn_off_constant_entity_values(void) {
377 void dump_keepalive_edges(bool b) {
381 bool get_opt_dump_keepalive_edges(void) {
382 return dump_keepalive;
385 void dump_out_edges(void) {
386 dump_out_edge_flag = 1;
389 void dump_dominator_information(void) {
390 dump_dominator_information_flag = 1;
393 void dump_loop_information(void) {
394 dump_loop_information_flag = 1;
397 void dont_dump_loop_information(void) {
398 dump_loop_information_flag = 0;
401 void dump_backedge_information(bool b) {
402 dump_backedge_information_flag = b;
405 /* Dump the information of type field specified in ana/irtypeinfo.h.
406 * If the flag is set, the type name is output in [] in the node label,
407 * else it is output as info.
409 void dump_analysed_type_info(bool b) {
410 opt_dump_analysed_type_info = b;
413 void dump_pointer_values_to_info(bool b) {
414 opt_dump_pointer_values_to_info = b;
417 /*******************************************************************/
418 /* Routines to dump information about a single ir node. */
419 /*******************************************************************/
422 dump_node_opcode(ir_node *n)
426 switch(get_irn_opcode(n)) {
431 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
432 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
437 if (get_SymConst_kind(n) == linkage_ptr_info) {
438 /* don't use get_SymConst_ptr_info as it mangles the name. */
439 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
441 assert(get_kind(get_SymConst_type(n)) == k_type);
442 assert(get_type_ident(get_SymConst_type(n)));
443 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
444 if (get_SymConst_kind(n) == type_tag)
452 if (!interprocedural_view) fprintf(F, "Proj'");
453 else fprintf(F, "%s", get_irn_opname(n));
457 if (interprocedural_view) {
458 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
464 fprintf (F, "%s", get_irn_opname(n));
472 dump_node_mode (ir_node *n)
474 switch (get_irn_opcode(n)) {
493 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
500 static int dump_node_typeinfo(ir_node *n) {
503 if (opt_dump_analysed_type_info) {
504 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
505 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
506 type *tp = get_irn_type(n);
508 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
517 dump_node_nodeattr (ir_node *n)
521 switch (get_irn_opcode(n)) {
523 if (false && interprocedural_view) {
524 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
528 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
529 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
531 fprintf (F, "%ld", get_Proj_proj(n));
535 fprintf (F, "%ld", get_Filter_proj(n));
538 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
541 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
544 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
554 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
557 fprintf(F, "color: red");
560 switch (get_irn_opcode(n)) {
567 fprintf (F, "color: blue");
570 fprintf (F, "color: lightyellow");
573 fprintf (F, "color: green");
579 fprintf (F, "color: yellow");
582 PRINT_DEFAULT_NODE_ATTR;
585 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
588 static INLINE int dump_node_info(ir_node *n)
594 fprintf (F, " info1: \"");
595 if (opt_dump_pointer_values_to_info)
596 fprintf (F, "addr: %p \n", (void *)n);
597 fprintf (F, "visited: %ld \n", get_irn_visited(n));
598 irg = get_irn_irg(n);
599 if (irg != get_const_code_irg())
600 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
602 fprintf(F, "arity: %d", get_irn_arity(n));
603 if ((get_irn_op(n) == op_Block) ||
604 (get_irn_op(n) == op_Phi) ||
605 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
606 fprintf(F, " backedges:");
608 for (i = 0; i < get_irn_arity(n); i++)
609 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
614 switch (get_irn_opcode(n)) {
616 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
617 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
618 for (i = 0; i < get_method_n_params(tp); ++i)
619 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
622 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
625 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
628 entity *ent = get_Sel_entity(n);
631 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
632 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
635 fprintf(F, "<NULL entity>\n");
640 type *tp = get_Call_type(n);
641 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
642 for (i = 0; i < get_method_n_params(tp); ++i)
643 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
644 for (i = 0; i < get_method_n_ress(tp); ++i)
645 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
646 if (Call_has_callees(n)) {
647 fprintf(F, "possible callees: \n");
648 for (i = 0; i < get_Call_n_callees(n); i++) {
649 if (!get_Call_callee(n, i)) {
650 fprintf(F, " %d external method\n", i);
652 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
657 case iro_CallBegin: {
658 ir_node *call = get_CallBegin_call(n);
659 if (Call_has_callees(call)) {
660 fprintf(F, "possible callees: \n");
661 for (i = 0; i < get_Call_n_callees(call); i++) {
662 if (!get_Call_callee(call, i)) {
663 fprintf(F, " %d external method\n", i);
665 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
671 if (!interprocedural_view) {
672 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
673 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
674 for (i = 0; i < get_method_n_ress(tp); ++i)
675 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
679 type *tp = get_Const_type(n);
680 assert(tp != none_type);
681 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
685 if (interprocedural_view) {
686 fprintf(F, "intra predecessor nodes:\n");
687 for (i = 0; i < get_irn_intra_arity(n); i++) {
688 ir_node *pred = get_irn_intra_n(n, i);
689 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
692 fprintf(F, "inter predecessor nodes:\n");
693 for (i = 0; i < get_irn_inter_arity(n); i++) {
694 ir_node *pred = get_irn_inter_n(n, i);
695 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
696 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
703 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
704 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
705 if (get_irn_type(n) != none_type)
706 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
715 bool is_constlike_node(ir_node *n) {
716 ir_op *op = get_irn_op(n);
717 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
721 /* outputs the predecessors of n, that are constants, local. I.e.,
722 generates a copy of the constant predecessors for each node called with. */
723 static void dump_const_node_local(ir_node *n) {
725 if (!get_opt_dump_const_local()) return;
727 /* Use visited flag to avoid outputting nodes twice.
728 initialize it first. */
729 for (i = 0; i < get_irn_arity(n); i++) {
730 ir_node *con = get_irn_n(n, i);
731 if (is_constlike_node(con)) {
732 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
736 for (i = 0; i < get_irn_arity(n); i++) {
737 ir_node *con = get_irn_n(n, i);
738 if (is_constlike_node(con) && irn_not_visited(con)) {
741 mark_irn_visited(con);
742 /* Generate a new name for the node by appending the names of
744 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
745 fprintf(F, " label: \"");
746 bad |= dump_node_opcode(con);
747 dump_node_mode (con);
748 bad |= dump_node_typeinfo(con);
750 bad |= dump_node_nodeattr(con);
751 fprintf(F, " %ld", get_irn_node_nr(con));
753 bad |= dump_node_info(con);
754 dump_node_vcgattr(con, bad);
760 static void print_node_error(const char *p)
765 fprintf (F, " info2: \"%s\"", p);
768 static void dump_node(ir_node *n)
773 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
775 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
777 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
778 bad |= dump_node_opcode(n);
780 bad |= dump_node_typeinfo(n);
782 bad |= dump_node_nodeattr(n);
783 fprintf(F, " %ld", get_irn_node_nr(n));
785 bad |= dump_node_info(n);
787 dump_node_vcgattr(n, bad);
789 dump_const_node_local(n);
796 /* dump the edge to the block this node belongs to */
798 dump_ir_block_edge(ir_node *n) {
799 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
800 if (is_no_Block(n)) {
801 fprintf (F, "edge: { sourcename: \"");
803 fprintf (F, "\" targetname: \"");
804 PRINT_NODEID(get_nodes_block(n));
805 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
809 static void print_edge_vcgattr(ir_node *from, int to) {
812 if (dump_backedge_information_flag && is_backedge(from, to))
813 fprintf (F, BACK_EDGE_ATTR);
815 switch (get_irn_opcode(from)) {
817 fprintf (F, CF_EDGE_ATTR);
819 case iro_Start: break;
822 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
823 fprintf (F, CF_EDGE_ATTR);
824 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
825 fprintf (F, MEM_EDGE_ATTR);
828 case iro_EndReg: break;
829 case iro_EndExcept: break;
831 case iro_Break: break;
832 case iro_Cond: break;
835 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
837 case iro_Const: break;
838 case iro_SymConst:break;
841 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
843 case iro_CallBegin: break;
846 case iro_Minus: break;
852 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
860 case iro_Shrs: break;
863 case iro_Conv: break;
865 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
871 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
874 fprintf (F, MEM_EDGE_ATTR);
876 case iro_Tuple: break;
879 switch (get_irn_modecode(from)) {
881 fprintf (F, CF_EDGE_ATTR);
884 fprintf (F, MEM_EDGE_ATTR);
890 case iro_Unknown: break;
897 /* dump edges to our inputs */
899 dump_ir_data_edges(ir_node *n) {
900 int i, visited = get_irn_visited(n);
902 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
905 for (i = 0; i < get_irn_arity(n); i++) {
906 ir_node * pred = get_irn_n(n, i);
909 if ((interprocedural_view && get_irn_visited(pred) < visited))
910 continue; /* pred not dumped */
912 if (dump_backedge_information_flag && is_backedge(n, i))
913 fprintf (F, "backedge: {sourcename: \"");
915 fprintf (F, "edge: {sourcename: \"");
917 fprintf (F, "\" targetname: ");
918 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
919 PRINT_CONSTID(n, pred);
921 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
923 fprintf (F, " label: \"%d\" ", i);
924 print_edge_vcgattr(n, i);
929 /** Dumps a node and its edges but not the block edge
932 dump_node_wo_blockedge (ir_node *n, void* env) {
934 dump_ir_data_edges(n);
937 /** Dumps a node and its edges.
940 dump_whole_node (ir_node *n, void* env) {
941 dump_node_wo_blockedge(n, env);
942 if (!node_floats(n)) dump_ir_block_edge(n);
946 dump_const_node(ir_node *n, void *env) {
947 if (is_Block(n)) return;
948 dump_node_wo_blockedge(n, env);
951 /***********************************************************************/
952 /* the following routines dump the nodes/irgs bracketed to graphs. */
953 /***********************************************************************/
955 /** Dumps a constant expression as entity initializer, array bound ...
957 static void dump_const_expression(ir_node *value) {
958 ir_graph *rem = current_ir_graph;
959 int rem_dump_const_local = dump_const_local;
960 dump_const_local = 0;
961 current_ir_graph = get_const_code_irg();
962 irg_walk(value, dump_const_node, NULL, NULL);
963 /* Decrease visited flag so that we walk with the same flag for the next
964 expresssion. This guarantees that we don't dump the same node twice,
965 as for const expressions cse is performed to save memory. */
966 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
967 current_ir_graph = rem;
968 dump_const_local = rem_dump_const_local;
971 /** Dump a block as graph containing its nodes.
973 * Expects to find nodes belonging to the block as list in its
975 * Dumps the edges of all nodes including itself. */
977 dump_whole_block(ir_node *block) {
979 assert(is_Block(block));
981 fprintf(F, "graph: { title: \"");
983 fprintf(F, "\" label: \"");
984 dump_node_opcode(block);
985 fprintf (F, " %ld", get_irn_node_nr(block));
987 if (get_opt_dump_abstvals())
988 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
990 fprintf(F, "\" status:clustered color:%s \n",
991 get_Block_matured(block) ? "yellow" : "red");
993 /* dump the blocks edges */
994 dump_ir_data_edges(block);
996 /* dump the nodes that go into the block */
997 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
999 dump_ir_data_edges(node);
1002 /* Close the vcg information for the block */
1004 dump_const_node_local(block);
1006 dump_chi_term(F, block);
1011 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1012 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1014 dump_block_graph(ir_graph *irg) {
1016 ir_graph *rem = current_ir_graph;
1017 ir_node **arr = ird_get_irg_link(irg);
1018 current_ir_graph = irg;
1020 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1021 ir_node * node = arr[i];
1022 if (is_Block(node)) {
1023 /* Dumps the block and all the nodes in the block, which are to
1024 be found in Block->link. */
1025 dump_whole_block(node);
1027 /* Nodes that are not in a Block. */
1029 dump_ir_data_edges(node);
1033 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1035 current_ir_graph = rem;
1038 /** Dumps an irg as a graph.
1039 * If interprocedural view edges can point to nodes out of this graph.
1041 static void dump_graph(ir_graph *irg) {
1043 fprintf(F, "graph: { title: \"");
1045 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1046 get_ent_dump_name(get_irg_ent(irg)));
1048 dump_block_graph (irg);
1050 /* Close the vcg information for the irg */
1051 fprintf(F, "}\n\n");
1054 /*******************************************************************/
1055 /* Basic type and entity nodes and edges. */
1056 /*******************************************************************/
1058 /* dumps the edges between nodes and their type or entity attributes. */
1059 static void dump_node2type_edges (ir_node *n, void *env)
1063 switch (get_irn_opcode(n)) {
1065 /* @@@ some consts have an entity */
1068 if ( (get_SymConst_kind(n) == type_tag)
1069 || (get_SymConst_kind(n) == size))
1071 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1075 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1078 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1081 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1084 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1087 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1095 static void print_type_info(type *tp) {
1096 if (get_type_state(tp) == layout_undefined) {
1097 fprintf(F, "state: layout_undefined\n");
1099 fprintf(F, "state: layout_fixed,\n");
1101 if (get_type_mode(tp))
1102 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1103 fprintf(F, "size: %dB,\n", get_type_size(tp));
1106 static void print_typespecific_info(type *tp) {
1107 switch (get_type_tpop_code(tp)) {
1110 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1117 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1118 fprintf(F, "params: %d\n", get_method_n_params(tp));
1119 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1127 case tpo_enumeration:
1141 static void print_typespecific_vcgattr(type *tp) {
1142 switch (get_type_tpop_code(tp)) {
1145 if (peculiarity_existent == get_class_peculiarity(tp))
1146 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1148 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1152 fprintf (F, " " TYPE_METH_NODE_ATTR);
1163 case tpo_enumeration:
1176 static int print_type_node(type *tp)
1180 fprintf (F, "node: {title: ");
1182 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1183 fprintf (F, " info1: \"");
1184 print_type_info(tp);
1185 print_typespecific_info(tp);
1187 print_typespecific_vcgattr(tp);
1193 #define X(a) case a: fprintf(F, #a); break
1194 void dump_entity_node(entity *ent)
1196 fprintf (F, "node: {title: \"");
1197 PRINT_ENTID(ent); fprintf(F, "\"");
1198 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1199 fprintf (F, "label: ");
1200 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1201 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1203 fprintf (F, "\nallocation: ");
1204 switch (get_entity_allocation(ent)) {
1205 X(allocation_dynamic);
1206 X(allocation_automatic);
1207 X(allocation_static);
1208 X(allocation_parameter);
1211 fprintf (F, "\nvisibility: ");
1212 switch (get_entity_visibility(ent)) {
1213 X(visibility_local);
1214 X(visibility_external_visible);
1215 X(visibility_external_allocated);
1218 fprintf (F, "\nvariability: ");
1219 switch (get_entity_variability(ent)) {
1220 X(variability_uninitialized);
1221 X(variability_initialized);
1222 X(variability_part_constant);
1223 X(variability_constant);
1226 fprintf (F, "\nvolatility: ");
1227 switch (get_entity_volatility(ent)) {
1228 X(volatility_non_volatile);
1229 X(volatility_is_volatile);
1232 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1233 fprintf(F, "\nname: %s\nld_name: %s",
1234 get_ent_dump_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1235 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1236 if (is_method_type(get_entity_type(ent))) {
1237 if (get_entity_irg(ent)) /* can be null */
1238 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1240 { fprintf (F, "\nirg = NULL"); }
1242 fprintf(F, "\"\n}\n");
1246 static void dump_enum_item(type *tp, int pos)
1249 ident *id = get_enumeration_nameid(tp, pos);
1250 tarval *tv = get_enumeration_enum(tp, pos);
1252 tarval_snprintf(buf, sizeof(buf), tv);
1253 fprintf (F, "node: {title: \"");
1254 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1255 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1256 fprintf (F, "label: ");
1257 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1258 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1261 /* dumps a type or entity and it's edges. */
1263 dump_type_info (type_or_ent *tore, void *env) {
1264 int i = 0; /* to shutup gcc */
1266 /* dump this type or entity */
1268 switch (get_kind(tore)) {
1271 entity *ent = (entity *)tore;
1274 dump_entity_node(ent);
1276 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1277 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1278 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1279 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1280 if(is_class_type(get_entity_owner(ent))) {
1281 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1282 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1285 /* attached subgraphs */
1286 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1287 if (is_atomic_entity(ent)) {
1288 value = get_atomic_ent_value(ent);
1290 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1291 /* DDMN(value); $$$ */
1292 dump_const_expression(value);
1295 if (is_compound_entity(ent)) {
1296 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1297 value = get_compound_ent_value(ent, i);
1299 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1300 dump_const_expression(value);
1301 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1303 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1304 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1305 get_compound_ent_value_member(ent, i), i);
1314 type *tp = (type *)tore;
1315 print_type_node(tp);
1316 /* and now the edges */
1317 switch (get_type_tpop_code(tp)) {
1320 for (i=0; i < get_class_n_supertypes(tp); i++) {
1321 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1324 for (i=0; i < get_class_n_members(tp); i++) {
1325 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1330 for (i=0; i < get_struct_n_members(tp); i++) {
1331 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1336 for (i = 0; i < get_method_n_params(tp); i++)
1338 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1340 for (i = 0; i < get_method_n_ress(tp); i++)
1342 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1347 for (i = 0; i < get_union_n_members(tp); i++)
1349 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1354 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1355 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1356 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1357 ir_node *upper = get_array_upper_bound(tp, i);
1358 ir_node *lower = get_array_lower_bound(tp, i);
1359 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1360 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1361 dump_const_expression(upper);
1362 dump_const_expression(lower);
1366 case tpo_enumeration:
1368 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1369 dump_enum_item(tp, i);
1370 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1375 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1383 break; /* case k_type */
1386 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1388 } /* switch kind_or_entity */
1391 /** For dumping class hierarchies.
1392 * Dumps a class type node and a superclass edge.
1393 * If env != null dumps entities of classes and overwrites edges.
1396 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1397 int i = 0; /* to shutup gcc */
1399 /* dump this type or entity */
1400 switch (get_kind(tore)) {
1402 entity *ent = (entity *)tore;
1403 if (get_entity_owner(ent) == get_glob_type()) break;
1404 if ((env) && is_class_type(get_entity_owner(ent))) {
1406 dump_entity_node(ent);
1408 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1409 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1411 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1414 } break; /* case k_entity */
1417 type *tp = (type *)tore;
1418 if (tp == get_glob_type()) break;
1419 switch (get_type_tpop_code(tp)) {
1421 print_type_node(tp);
1422 /* and now the edges */
1423 for (i=0; i < get_class_n_supertypes(tp); i++)
1425 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1431 break; /* case k_type */
1434 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1436 } /* switch kind_or_entity */
1439 /*******************************************************************/
1440 /* dump analysis information that is expressed in graph terms. */
1441 /*******************************************************************/
1443 /* dump out edges */
1445 dump_out_edge (ir_node *n, void* env) {
1447 for (i = 0; i < get_irn_n_outs(n); i++) {
1448 assert(get_irn_out(n, i));
1449 fprintf (F, "edge: {sourcename: \"");
1451 fprintf (F, "\" targetname: \"");
1452 PRINT_NODEID(get_irn_out(n, i));
1453 fprintf (F, "\" color: red linestyle: dashed");
1459 dump_loop_label(ir_loop *loop) {
1460 fprintf (F, "loop %d, %d sons, %d nodes",
1461 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1464 static INLINE void dump_loop_info(ir_loop *loop) {
1465 fprintf (F, " info1: \"");
1466 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1467 #if DEBUG_libfirm /* GL @@@ debug analyses */
1468 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1474 dump_loop_node(ir_loop *loop) {
1475 fprintf (F, "node: {title: \"");
1477 fprintf (F, "\" label: \"");
1478 dump_loop_label(loop);
1480 dump_loop_info(loop);
1486 dump_loop_node_edge (ir_loop *loop, int i) {
1488 fprintf (F, "edge: {sourcename: \"");
1490 fprintf (F, "\" targetname: \"");
1491 PRINT_NODEID(get_loop_node(loop, i));
1492 fprintf (F, "\" color: green");
1497 dump_loop_son_edge (ir_loop *loop, int i) {
1499 fprintf (F, "edge: {sourcename: \"");
1501 fprintf (F, "\" targetname: \"");
1502 PRINT_LOOPID(get_loop_son(loop, i));
1503 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1504 get_loop_element_pos(loop, get_loop_son(loop, i)));
1508 void dump_loops (ir_loop *loop) {
1510 /* dump this loop node */
1511 dump_loop_node(loop);
1513 /* dump edges to nodes in loop -- only if it is a real loop */
1514 if (get_loop_depth(loop) != 0) {
1515 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1516 dump_loop_node_edge(loop, i);
1519 for (i = 0; i < get_loop_n_sons(loop); i++) {
1520 dump_loops(get_loop_son(loop, i));
1521 dump_loop_son_edge(loop, i);
1526 void dump_loop_nodes_into_graph(ir_graph *irg) {
1527 ir_graph *rem = current_ir_graph;
1528 current_ir_graph = irg;
1530 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1532 current_ir_graph = rem;
1536 /************************************************************************/
1537 /* open and close vcg file */
1538 /************************************************************************/
1541 dump_vcg_header(const char *name, const char *orientation) {
1550 if (!orientation) orientation = "bottom_to_top";
1554 "graph: { title: \"ir graph of %s\"\n"
1555 "display_edge_labels: %s\n"
1556 "layoutalgorithm: mindepth\n"
1557 "manhattan_edges: yes\n"
1558 "port_sharing: no\n"
1560 "classname 1: \"Data\"\n"
1561 "classname 2: \"Block\"\n"
1562 "classname 13:\"Control Flow\"\n"
1563 "classname 14:\"Memory\"\n"
1564 "classname 15:\"Dominators\"\n"
1565 "classname 3: \"Entity type\"\n"
1566 "classname 4: \"Entity owner\"\n"
1567 "classname 5: \"Method Param\"\n"
1568 "classname 6: \"Method Res\"\n"
1569 "classname 7: \"Super\"\n"
1570 "classname 8: \"Union\"\n"
1571 "classname 9: \"Points-to\"\n"
1572 "classname 10: \"Array Element Type\"\n"
1573 "classname 11: \"Overwrites\"\n"
1574 "classname 12: \"Member\"\n"
1575 "infoname 1: \"Attribute\"\n"
1576 "infoname 2: \"Verification errors\"\n",
1577 name, label, orientation);
1579 fprintf (F, "\n"); /* a separator */
1582 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1583 const char *nm = get_irg_dump_name(irg);
1584 int len = strlen(nm), i, j;
1585 char *fname; /* filename to put the vcg information in */
1587 if (!suffix1) suffix1 = "";
1588 if (!suffix2) suffix2 = "";
1590 /** open file for vcg graph */
1591 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1593 //strncpy (fname, nm, len); /* copy the filename */
1595 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1597 fname[j] = '@'; j++; fname[j] = '1'; j++;
1598 } else if (nm[i] == '@') {
1599 fname[j] = '@'; j++; fname[j] = '2'; j++;
1601 fname[j] = nm[i]; j++;
1605 strcat (fname, suffix1); /* append file suffix */
1606 strcat (fname, suffix2); /* append file suffix */
1607 strcat (fname, ".vcg"); /* append the .vcg suffix */
1608 F = fopen (fname, "w"); /* open file for writing */
1610 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1615 static void vcg_open_name (const char *name, char *suffix) {
1616 char *fname; /* filename to put the vcg information in */
1617 int i, j, len = strlen(name);
1619 if (!suffix) suffix = "";
1621 /** open file for vcg graph */
1622 fname = malloc (len * 2 + 5 + strlen(suffix));
1623 //strcpy (fname, name); /* copy the filename */
1625 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1626 if (name[i] == '/') {
1627 fname[j] = '@'; j++; fname[j] = '1'; j++;
1628 } else if (name[i] == '@') {
1629 fname[j] = '@'; j++; fname[j] = '2'; j++;
1631 fname[j] = name[i]; j++;
1635 strcat (fname, suffix);
1636 strcat (fname, ".vcg"); /* append the .vcg suffix */
1637 F = fopen (fname, "w"); /* open file for writing */
1639 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1644 static INLINE void dump_vcg_footer (void) {
1650 dump_vcg_footer(); /* print footer */
1651 fclose (F); /* close vcg file */
1654 /************************************************************************/
1655 /************************************************************************/
1656 /* Routines that dump all or parts of the firm representation to a file */
1657 /************************************************************************/
1658 /************************************************************************/
1660 /************************************************************************/
1661 /* Dump ir graphs, differnt formats and additional information. */
1662 /************************************************************************/
1664 /** Routine to dump a graph, blocks as conventional nodes.
1667 dump_ir_graph (ir_graph *irg)
1671 rem = current_ir_graph;
1673 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1675 current_ir_graph = irg;
1676 if (interprocedural_view) suffix = "-pure-ip";
1677 else suffix = "-pure";
1678 vcg_open (irg, dump_file_suffix, suffix);
1679 dump_vcg_header(get_irg_dump_name(irg), NULL);
1681 /* walk over the graph */
1682 /* dump_whole_node must be called in post visiting predecessors */
1683 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1685 /* dump the out edges in a separate walk */
1686 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1687 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1692 current_ir_graph = rem;
1697 dump_ir_block_graph (ir_graph *irg)
1702 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1704 if (interprocedural_view) suffix = "-ip";
1706 vcg_open (irg, dump_file_suffix, suffix);
1707 dump_vcg_header(get_irg_dump_name(irg), NULL);
1709 construct_block_lists(irg);
1711 for (i = 0; i < get_irp_n_irgs(); i++) {
1712 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1714 dump_graph(get_irp_irg(i));
1722 /** dumps a graph with type information
1725 dump_ir_graph_w_types (ir_graph *irg)
1727 ir_graph *rem = current_ir_graph;
1730 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1732 current_ir_graph = irg;
1734 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1735 else suffix = "-pure-wtypes";
1736 vcg_open (irg, dump_file_suffix, suffix);
1737 dump_vcg_header(get_irg_dump_name(irg), NULL);
1739 /* dump common ir graph */
1740 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1741 /* dump type info */
1742 type_walk_irg(irg, dump_type_info, NULL, NULL);
1743 inc_irg_visited(get_const_code_irg());
1744 /* dump edges from graph to type info */
1745 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1748 current_ir_graph = rem;
1752 dump_ir_block_graph_w_types (ir_graph *irg)
1756 ir_graph *rem = current_ir_graph;
1758 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1760 if (interprocedural_view) suffix = "-wtypes-ip";
1761 else suffix = "-wtypes";
1762 vcg_open (irg, dump_file_suffix, suffix);
1763 dump_vcg_header(get_irg_dump_name(irg), NULL);
1765 /* dump common blocked ir graph */
1766 construct_block_lists(irg);
1768 for (i = 0; i < get_irp_n_irgs(); i++) {
1769 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1771 dump_graph(get_irp_irg(i));
1776 /* dump type info */
1777 current_ir_graph = irg;
1778 type_walk_irg(irg, dump_type_info, NULL, NULL);
1779 inc_irg_visited(get_const_code_irg());
1781 /* dump edges from graph to type info */
1782 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1784 current_ir_graph = rem;
1788 /***********************************************************************/
1789 /* The following routines dump a control flow graph. */
1790 /***********************************************************************/
1793 dump_block_to_cfg (ir_node *block, void *env) {
1797 if (is_Block(block)) {
1798 /* This is a block. Dump a node for the block. */
1799 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1800 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1801 PRINT_NODEID(block);
1803 if (dump_dominator_information_flag)
1804 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1806 /* Dump the edges */
1807 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1808 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1809 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1810 fprintf (F, "edge: { sourcename: \"");
1811 PRINT_NODEID(block);
1812 fprintf (F, "\" targetname: \"");
1814 fprintf (F, "\"}\n");
1817 /* Dump dominator edge */
1818 if (dump_dominator_information_flag && get_Block_idom(block)) {
1819 pred = get_Block_idom(block);
1820 fprintf (F, "edge: { sourcename: \"");
1821 PRINT_NODEID(block);
1822 fprintf (F, "\" targetname: \"");
1824 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1830 dump_cfg (ir_graph *irg)
1832 ir_graph *rem = current_ir_graph;
1833 int ddif = dump_dominator_information_flag;
1834 int ipv = interprocedural_view;
1836 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1838 current_ir_graph = irg;
1840 vcg_open (irg, dump_file_suffix, "-cfg");
1841 dump_vcg_header(get_irg_dump_name(irg), NULL);
1843 if (interprocedural_view) {
1844 printf("Warning: dumping cfg not in interprocedural view!\n");
1845 interprocedural_view = 0;
1848 if (get_irg_dom_state(irg) != dom_consistent)
1849 dump_dominator_information_flag = 0;
1851 /* walk over the blocks in the graph */
1852 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1853 dump_node (get_irg_bad(irg));
1855 dump_dominator_information_flag = ddif;
1856 interprocedural_view = ipv;
1858 current_ir_graph = rem;
1863 /* Dump all irgs in interprocedural view to a single file. */
1864 void dump_all_cg_block_graph(void) {
1866 int rem_view = interprocedural_view;
1867 interprocedural_view = 1;
1869 vcg_open_name ("All_graphs", dump_file_suffix);
1870 dump_vcg_header("All_graphs", NULL);
1872 /* collect nodes in all irgs reachable in call graph*/
1873 for (i = 0; i < get_irp_n_irgs(); i++)
1874 ird_set_irg_link(get_irp_irg(i), NULL);
1876 cg_walk(clear_link, collect_node, NULL);
1878 /* dump all graphs */
1879 for (i = 0; i < get_irp_n_irgs(); i++) {
1880 current_ir_graph = get_irp_irg(i);
1881 assert(ird_get_irg_link(current_ir_graph));
1882 dump_graph(current_ir_graph);
1883 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1887 interprocedural_view = rem_view;
1890 /***********************************************************************/
1891 /* the following routines dumps type information without any ir nodes. */
1892 /***********************************************************************/
1895 dump_type_graph (ir_graph *irg)
1898 rem = current_ir_graph;
1900 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1902 current_ir_graph = irg;
1904 vcg_open (irg, dump_file_suffix, "-type");
1905 dump_vcg_header(get_irg_dump_name(irg), NULL);
1907 /* walk over the blocks in the graph */
1908 type_walk_irg(irg, dump_type_info, NULL, NULL);
1909 /* The walker for the const code can be called several times for the
1910 same (sub) experssion. So that no nodes are dumped several times
1911 we decrease the visited flag of the corresponding graph after each
1912 walk. So now increase it finally. */
1913 inc_irg_visited(get_const_code_irg());
1916 current_ir_graph = rem;
1920 dump_all_types (void)
1922 vcg_open_name ("All_types", dump_file_suffix);
1923 dump_vcg_header("All_types", NULL);
1924 type_walk(dump_type_info, NULL, NULL);
1925 inc_irg_visited(get_const_code_irg());
1930 dump_class_hierarchy (bool entities)
1932 vcg_open_name ("class_hierarchy", dump_file_suffix);
1933 dump_vcg_header("class_hierarchy", NULL);
1935 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1937 type_walk(dump_class_hierarchy_node, NULL, NULL);
1941 /***********************************************************************/
1942 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1944 /* dump_ir_block_graph */
1946 /* dump_type_graph */
1947 /* dump_ir_graph_w_types */
1948 /***********************************************************************/
1950 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1952 for (i=0; i < get_irp_n_irgs(); i++) {
1953 dmp_grph(get_irp_irg(i));
1958 /**********************************************************************************
1959 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1960 * packed together in one subgraph *
1961 **********************************************************************************/
1965 void dump_loops_standalone (ir_loop *loop) {
1966 int i, loop_node_started = 0, son_number = 0, first = 0;
1969 /* Dump a new loop node. */
1970 dump_loop_node(loop);
1972 /* Dump the loop elements. */
1973 for(i = 0; i < get_loop_n_elements(loop); i++) {
1976 le = get_loop_element(loop, i);
1979 if (get_kind(son) == k_ir_loop) {
1980 /* We are a loop son -> Recurse */
1982 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
1983 fprintf(F, "\" }\n");
1984 fprintf (F, "edge: {sourcename: \"");
1986 fprintf (F, "\" targetname: \"");
1988 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1989 loop_node_started = 0;
1991 dump_loop_son_edge(loop, son_number++);
1992 dump_loops_standalone(son);
1995 /* We are a loop node -> Collect firm nodes */
1997 ir_node *n = le.node;
1999 if (!loop_node_started) {
2000 /* Start a new node which contains all firm nodes of the current loop */
2001 fprintf (F, "node: { title: \"");
2003 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2004 loop_node_started = 1;
2010 dump_node_opcode(n);
2012 dump_node_typeinfo(n);
2014 dump_node_nodeattr(n);
2015 fprintf (F, " %ld", get_irn_node_nr(n));
2019 if (loop_node_started) {
2020 fprintf(F, "\" }\n");
2021 fprintf (F, "edge: {sourcename: \"");
2023 fprintf (F, "\" targetname: \"");
2025 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2026 loop_node_started = 0;
2030 void dump_loop_tree(ir_graph *irg, char *suffix)
2032 ir_graph *rem = current_ir_graph;
2033 int el_rem = edge_label;
2036 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2038 current_ir_graph = irg;
2040 vcg_open(irg, suffix, "-looptree");
2041 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2043 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2047 edge_label = el_rem;
2048 current_ir_graph = rem;
2052 /*******************************************************************************/
2053 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2054 /*******************************************************************************/
2056 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2057 int i, son_number = 0, node_number = 0;
2059 if (dump_loop_information_flag) dump_loop_node(loop);
2061 for (i = 0; i < get_loop_n_elements(loop); i++) {
2062 loop_element le = get_loop_element(loop, i);
2063 if (*(le.kind) == k_ir_loop) {
2064 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2066 collect_nodeloop(le.son, loopnodes);
2068 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2069 eset_insert(loopnodes, le.node);
2074 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2077 for(i = 0; i < get_loop_n_elements(loop); i++) {
2078 loop_element le = get_loop_element(loop, i);
2079 if (*(le.kind) == k_ir_loop) {
2081 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2083 if (is_Block(le.node)) start = 0; else start = -1;
2084 for (j = start; j < get_irn_arity(le.node); j++) {
2085 ir_node *pred = get_irn_n(le.node, j);
2086 if (!eset_contains(loopnodes, pred)) {
2087 eset_insert(extnodes, pred);
2088 if (!is_Block(pred)) {
2089 pred = get_nodes_block(pred);
2090 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2098 void dump_loop (ir_loop *l, char *suffix) {
2100 eset *loopnodes = eset_create();
2101 eset *extnodes = eset_create();
2104 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2105 vcg_open_name (name, suffix);
2106 dump_vcg_header(name, NULL);
2108 /* collect all nodes to dump */
2109 collect_nodeloop(l, loopnodes);
2110 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2112 /* build block lists */
2113 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2114 set_irn_link(n, NULL);
2115 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2116 set_irn_link(n, NULL);
2117 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2119 b = get_nodes_block(n);
2120 set_irn_link(n, get_irn_link(b));
2123 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2125 b = get_nodes_block(n);
2126 set_irn_link(n, get_irn_link(b));
2130 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2132 fprintf(F, "graph: { title: \"");
2134 fprintf(F, "\" label: \"");
2135 dump_node_opcode(b);
2136 fprintf (F, " %ld", get_irn_node_nr(b));
2137 fprintf(F, "\" status:clustered color:yellow\n");
2139 /* dump the blocks edges */
2140 dump_ir_data_edges(b);
2142 /* dump the nodes that go into the block */
2143 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2144 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2146 overrule_nodecolor = NULL;
2147 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2150 /* Close the vcg information for the block */
2152 dump_const_node_local(b);
2155 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2157 fprintf(F, "graph: { title: \"");
2159 fprintf(F, "\" label: \"");
2160 dump_node_opcode(b);
2161 fprintf (F, " %ld", get_irn_node_nr(b));
2162 fprintf(F, "\" status:clustered color:lightblue\n");
2164 /* dump the nodes that go into the block */
2165 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2166 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2168 overrule_nodecolor = NULL;
2169 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2172 /* Close the vcg information for the block */
2174 dump_const_node_local(b);
2178 eset_destroy(loopnodes);
2179 eset_destroy(extnodes);