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 = ','; }
614 /* Loop node Someone else please tell me what's wrong ...
615 if (get_irn_loop(n)) {
616 ir_loop *loop = get_irn_loop(n);
618 fprintf(F, " in loop %d with depth %d\n",
619 get_loop_loop_nr(loop), get_loop_depth(loop));
624 switch (get_irn_opcode(n)) {
626 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
627 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
628 for (i = 0; i < get_method_n_params(tp); ++i)
629 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
632 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
635 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
638 entity *ent = get_Sel_entity(n);
641 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
642 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
645 fprintf(F, "<NULL entity>\n");
650 type *tp = get_Call_type(n);
651 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
652 for (i = 0; i < get_method_n_params(tp); ++i)
653 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
654 for (i = 0; i < get_method_n_ress(tp); ++i)
655 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
656 if (Call_has_callees(n)) {
657 fprintf(F, "possible callees: \n");
658 for (i = 0; i < get_Call_n_callees(n); i++) {
659 if (!get_Call_callee(n, i)) {
660 fprintf(F, " %d external method\n", i);
662 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
667 case iro_CallBegin: {
668 ir_node *call = get_CallBegin_call(n);
669 if (Call_has_callees(call)) {
670 fprintf(F, "possible callees: \n");
671 for (i = 0; i < get_Call_n_callees(call); i++) {
672 if (!get_Call_callee(call, i)) {
673 fprintf(F, " %d external method\n", i);
675 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
681 if (!interprocedural_view) {
682 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
683 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
684 for (i = 0; i < get_method_n_ress(tp); ++i)
685 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
689 type *tp = get_Const_type(n);
690 assert(tp != none_type);
691 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
695 if (interprocedural_view) {
696 fprintf(F, "intra predecessor nodes:\n");
697 for (i = 0; i < get_irn_intra_arity(n); i++) {
698 ir_node *pred = get_irn_intra_n(n, i);
699 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
702 fprintf(F, "inter predecessor nodes:\n");
703 for (i = 0; i < get_irn_inter_arity(n); i++) {
704 ir_node *pred = get_irn_inter_n(n, i);
705 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
706 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
713 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
714 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
715 if (get_irn_type(n) != none_type)
716 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
725 bool is_constlike_node(ir_node *n) {
726 ir_op *op = get_irn_op(n);
727 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
731 /* outputs the predecessors of n, that are constants, local. I.e.,
732 generates a copy of the constant predecessors for each node called with. */
733 static void dump_const_node_local(ir_node *n) {
735 if (!get_opt_dump_const_local()) return;
737 /* Use visited flag to avoid outputting nodes twice.
738 initialize it first. */
739 for (i = 0; i < get_irn_arity(n); i++) {
740 ir_node *con = get_irn_n(n, i);
741 if (is_constlike_node(con)) {
742 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
746 for (i = 0; i < get_irn_arity(n); i++) {
747 ir_node *con = get_irn_n(n, i);
748 if (is_constlike_node(con) && irn_not_visited(con)) {
751 mark_irn_visited(con);
752 /* Generate a new name for the node by appending the names of
754 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
755 fprintf(F, " label: \"");
756 bad |= dump_node_opcode(F, con);
757 dump_node_mode (con);
758 bad |= dump_node_typeinfo(con);
760 bad |= dump_node_nodeattr(con);
761 fprintf(F, " %ld", get_irn_node_nr(con));
763 bad |= dump_node_info(con);
764 dump_node_vcgattr(con, bad);
770 static void print_node_error(const char *p)
775 fprintf (F, " info2: \"%s\"", p);
778 static void dump_node(ir_node *n)
783 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
785 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
787 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
788 bad |= dump_node_opcode(F, n);
790 bad |= dump_node_typeinfo(n);
792 bad |= dump_node_nodeattr(n);
793 fprintf(F, " %ld", get_irn_node_nr(n));
795 bad |= dump_node_info(n);
797 dump_node_vcgattr(n, bad);
799 dump_const_node_local(n);
806 /* dump the edge to the block this node belongs to */
808 dump_ir_block_edge(ir_node *n) {
809 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
810 if (is_no_Block(n)) {
811 fprintf (F, "edge: { sourcename: \"");
813 fprintf (F, "\" targetname: \"");
814 PRINT_NODEID(get_nodes_block(n));
815 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
819 static void print_edge_vcgattr(ir_node *from, int to) {
822 if (dump_backedge_information_flag && is_backedge(from, to))
823 fprintf (F, BACK_EDGE_ATTR);
825 switch (get_irn_opcode(from)) {
827 fprintf (F, CF_EDGE_ATTR);
829 case iro_Start: break;
832 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
833 fprintf (F, CF_EDGE_ATTR);
834 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
835 fprintf (F, MEM_EDGE_ATTR);
838 case iro_EndReg: break;
839 case iro_EndExcept: break;
841 case iro_Break: break;
842 case iro_Cond: break;
845 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
847 case iro_Const: break;
848 case iro_SymConst:break;
851 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
853 case iro_CallBegin: break;
856 case iro_Minus: break;
862 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
870 case iro_Shrs: break;
873 case iro_Conv: break;
875 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
881 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
884 fprintf (F, MEM_EDGE_ATTR);
886 case iro_Tuple: break;
889 switch (get_irn_modecode(from)) {
891 fprintf (F, CF_EDGE_ATTR);
894 fprintf (F, MEM_EDGE_ATTR);
900 case iro_Unknown: break;
907 /* dump edges to our inputs */
909 dump_ir_data_edges(ir_node *n) {
910 int i, visited = get_irn_visited(n);
912 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
915 for (i = 0; i < get_irn_arity(n); i++) {
916 ir_node * pred = get_irn_n(n, i);
919 if ((interprocedural_view && get_irn_visited(pred) < visited))
920 continue; /* pred not dumped */
922 if (dump_backedge_information_flag && is_backedge(n, i))
923 fprintf (F, "backedge: {sourcename: \"");
925 fprintf (F, "edge: {sourcename: \"");
927 fprintf (F, "\" targetname: ");
928 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
929 PRINT_CONSTID(n, pred);
931 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
933 fprintf (F, " label: \"%d\" ", i);
934 print_edge_vcgattr(n, i);
939 /** Dumps a node and its edges but not the block edge
942 dump_node_wo_blockedge (ir_node *n, void* env) {
944 dump_ir_data_edges(n);
947 /** Dumps a node and its edges.
950 dump_whole_node (ir_node *n, void* env) {
951 dump_node_wo_blockedge(n, env);
952 if (!node_floats(n)) dump_ir_block_edge(n);
956 dump_const_node(ir_node *n, void *env) {
957 if (is_Block(n)) return;
958 dump_node_wo_blockedge(n, env);
961 /***********************************************************************/
962 /* the following routines dump the nodes/irgs bracketed to graphs. */
963 /***********************************************************************/
965 /** Dumps a constant expression as entity initializer, array bound ...
967 static void dump_const_expression(ir_node *value) {
968 ir_graph *rem = current_ir_graph;
969 int rem_dump_const_local = dump_const_local;
970 dump_const_local = 0;
971 current_ir_graph = get_const_code_irg();
972 irg_walk(value, dump_const_node, NULL, NULL);
973 /* Decrease visited flag so that we walk with the same flag for the next
974 expresssion. This guarantees that we don't dump the same node twice,
975 as for const expressions cse is performed to save memory. */
976 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
977 current_ir_graph = rem;
978 dump_const_local = rem_dump_const_local;
981 /** Dump a block as graph containing its nodes.
983 * Expects to find nodes belonging to the block as list in its
985 * Dumps the edges of all nodes including itself. */
987 dump_whole_block(ir_node *block) {
989 assert(is_Block(block));
991 fprintf(F, "graph: { title: \"");
993 fprintf(F, "\" label: \"");
994 dump_node_opcode(F, block);
995 fprintf (F, " %ld", get_irn_node_nr(block));
997 if (get_opt_dump_abstvals())
998 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1000 fprintf(F, "\" status:clustered color:%s \n",
1001 get_Block_matured(block) ? "yellow" : "red");
1003 /* dump the blocks edges */
1004 dump_ir_data_edges(block);
1006 /* dump the nodes that go into the block */
1007 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1009 dump_ir_data_edges(node);
1012 /* Close the vcg information for the block */
1014 dump_const_node_local(block);
1016 dump_chi_term(F, block);
1021 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1022 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1024 dump_block_graph(ir_graph *irg) {
1026 ir_graph *rem = current_ir_graph;
1027 ir_node **arr = ird_get_irg_link(irg);
1028 current_ir_graph = irg;
1030 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1031 ir_node * node = arr[i];
1032 if (is_Block(node)) {
1033 /* Dumps the block and all the nodes in the block, which are to
1034 be found in Block->link. */
1035 dump_whole_block(node);
1037 /* Nodes that are not in a Block. */
1039 dump_ir_data_edges(node);
1043 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1045 current_ir_graph = rem;
1048 /** Dumps an irg as a graph.
1049 * If interprocedural view edges can point to nodes out of this graph.
1051 static void dump_graph(ir_graph *irg) {
1053 fprintf(F, "graph: { title: \"");
1055 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1056 get_ent_dump_name(get_irg_ent(irg)));
1058 dump_block_graph (irg);
1060 /* Close the vcg information for the irg */
1061 fprintf(F, "}\n\n");
1064 /*******************************************************************/
1065 /* Basic type and entity nodes and edges. */
1066 /*******************************************************************/
1068 /* dumps the edges between nodes and their type or entity attributes. */
1069 static void dump_node2type_edges (ir_node *n, void *env)
1073 switch (get_irn_opcode(n)) {
1075 /* @@@ some consts have an entity */
1078 if ( (get_SymConst_kind(n) == type_tag)
1079 || (get_SymConst_kind(n) == size))
1081 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1085 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1088 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1091 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1094 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1097 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1105 static void print_type_info(type *tp) {
1106 if (get_type_state(tp) == layout_undefined) {
1107 fprintf(F, "state: layout_undefined\n");
1109 fprintf(F, "state: layout_fixed,\n");
1111 if (get_type_mode(tp))
1112 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1113 fprintf(F, "size: %dB,\n", get_type_size(tp));
1116 static void print_typespecific_info(type *tp) {
1117 switch (get_type_tpop_code(tp)) {
1120 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1127 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1128 fprintf(F, "params: %d\n", get_method_n_params(tp));
1129 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1137 case tpo_enumeration:
1151 static void print_typespecific_vcgattr(type *tp) {
1152 switch (get_type_tpop_code(tp)) {
1155 if (peculiarity_existent == get_class_peculiarity(tp))
1156 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1158 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1162 fprintf (F, " " TYPE_METH_NODE_ATTR);
1173 case tpo_enumeration:
1186 static int print_type_node(type *tp)
1190 fprintf (F, "node: {title: ");
1192 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1193 fprintf (F, " info1: \"");
1194 print_type_info(tp);
1195 print_typespecific_info(tp);
1197 print_typespecific_vcgattr(tp);
1203 #define X(a) case a: fprintf(F, #a); break
1204 void dump_entity_node(entity *ent)
1206 fprintf (F, "node: {title: \"");
1207 PRINT_ENTID(ent); fprintf(F, "\"");
1208 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1209 fprintf (F, "label: ");
1210 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1211 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1213 fprintf (F, "\nallocation: ");
1214 switch (get_entity_allocation(ent)) {
1215 X(allocation_dynamic);
1216 X(allocation_automatic);
1217 X(allocation_static);
1218 X(allocation_parameter);
1221 fprintf (F, "\nvisibility: ");
1222 switch (get_entity_visibility(ent)) {
1223 X(visibility_local);
1224 X(visibility_external_visible);
1225 X(visibility_external_allocated);
1228 fprintf (F, "\nvariability: ");
1229 switch (get_entity_variability(ent)) {
1230 X(variability_uninitialized);
1231 X(variability_initialized);
1232 X(variability_part_constant);
1233 X(variability_constant);
1236 fprintf (F, "\nvolatility: ");
1237 switch (get_entity_volatility(ent)) {
1238 X(volatility_non_volatile);
1239 X(volatility_is_volatile);
1242 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1243 fprintf(F, "\nname: %s\nld_name: %s",
1244 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1245 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1246 if (is_method_type(get_entity_type(ent))) {
1247 if (get_entity_irg(ent)) /* can be null */
1248 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1250 { fprintf (F, "\nirg = NULL"); }
1252 fprintf(F, "\"\n}\n");
1256 static void dump_enum_item(type *tp, int pos)
1259 ident *id = get_enumeration_nameid(tp, pos);
1260 tarval *tv = get_enumeration_enum(tp, pos);
1262 tarval_snprintf(buf, sizeof(buf), tv);
1263 fprintf (F, "node: {title: \"");
1264 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1265 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1266 fprintf (F, "label: ");
1267 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1268 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1271 /* dumps a type or entity and it's edges. */
1273 dump_type_info (type_or_ent *tore, void *env) {
1274 int i = 0; /* to shutup gcc */
1276 /* dump this type or entity */
1278 switch (get_kind(tore)) {
1281 entity *ent = (entity *)tore;
1284 dump_entity_node(ent);
1286 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1287 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1288 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1289 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1290 if(is_class_type(get_entity_owner(ent))) {
1291 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1292 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1295 /* attached subgraphs */
1296 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1297 if (is_atomic_entity(ent)) {
1298 value = get_atomic_ent_value(ent);
1300 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1301 /* DDMN(value); $$$ */
1302 dump_const_expression(value);
1305 if (is_compound_entity(ent)) {
1306 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1307 value = get_compound_ent_value(ent, i);
1309 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1310 dump_const_expression(value);
1311 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1313 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1314 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1315 get_compound_ent_value_member(ent, i), i);
1324 type *tp = (type *)tore;
1325 print_type_node(tp);
1326 /* and now the edges */
1327 switch (get_type_tpop_code(tp)) {
1330 for (i=0; i < get_class_n_supertypes(tp); i++) {
1331 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1334 for (i=0; i < get_class_n_members(tp); i++) {
1335 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1340 for (i=0; i < get_struct_n_members(tp); i++) {
1341 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1346 for (i = 0; i < get_method_n_params(tp); i++)
1348 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1350 for (i = 0; i < get_method_n_ress(tp); i++)
1352 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1357 for (i = 0; i < get_union_n_members(tp); i++)
1359 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1364 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1365 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1366 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1367 ir_node *upper = get_array_upper_bound(tp, i);
1368 ir_node *lower = get_array_lower_bound(tp, i);
1369 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1370 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1371 dump_const_expression(upper);
1372 dump_const_expression(lower);
1376 case tpo_enumeration:
1378 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1379 dump_enum_item(tp, i);
1380 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1385 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1393 break; /* case k_type */
1396 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1398 } /* switch kind_or_entity */
1401 /** For dumping class hierarchies.
1402 * Dumps a class type node and a superclass edge.
1403 * If env != null dumps entities of classes and overwrites edges.
1406 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1407 int i = 0; /* to shutup gcc */
1409 /* dump this type or entity */
1410 switch (get_kind(tore)) {
1412 entity *ent = (entity *)tore;
1413 if (get_entity_owner(ent) == get_glob_type()) break;
1414 if ((env) && is_class_type(get_entity_owner(ent))) {
1416 dump_entity_node(ent);
1418 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1419 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1421 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1424 } break; /* case k_entity */
1427 type *tp = (type *)tore;
1428 if (tp == get_glob_type()) break;
1429 switch (get_type_tpop_code(tp)) {
1431 print_type_node(tp);
1432 /* and now the edges */
1433 for (i=0; i < get_class_n_supertypes(tp); i++)
1435 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1441 break; /* case k_type */
1444 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1446 } /* switch kind_or_entity */
1449 /*******************************************************************/
1450 /* dump analysis information that is expressed in graph terms. */
1451 /*******************************************************************/
1453 /* dump out edges */
1455 dump_out_edge (ir_node *n, void* env) {
1457 for (i = 0; i < get_irn_n_outs(n); i++) {
1458 assert(get_irn_out(n, i));
1459 fprintf (F, "edge: {sourcename: \"");
1461 fprintf (F, "\" targetname: \"");
1462 PRINT_NODEID(get_irn_out(n, i));
1463 fprintf (F, "\" color: red linestyle: dashed");
1469 dump_loop_label(ir_loop *loop) {
1470 fprintf (F, "loop %d, %d sons, %d nodes",
1471 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1474 static INLINE void dump_loop_info(ir_loop *loop) {
1475 fprintf (F, " info1: \"");
1476 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1477 #if DEBUG_libfirm /* GL @@@ debug analyses */
1478 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1484 dump_loop_node(ir_loop *loop) {
1485 fprintf (F, "node: {title: \"");
1487 fprintf (F, "\" label: \"");
1488 dump_loop_label(loop);
1490 dump_loop_info(loop);
1496 dump_loop_node_edge (ir_loop *loop, int i) {
1498 fprintf (F, "edge: {sourcename: \"");
1500 fprintf (F, "\" targetname: \"");
1501 PRINT_NODEID(get_loop_node(loop, i));
1502 fprintf (F, "\" color: green");
1507 dump_loop_son_edge (ir_loop *loop, int i) {
1509 fprintf (F, "edge: {sourcename: \"");
1511 fprintf (F, "\" targetname: \"");
1512 PRINT_LOOPID(get_loop_son(loop, i));
1513 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1514 get_loop_element_pos(loop, get_loop_son(loop, i)));
1518 void dump_loops (ir_loop *loop) {
1520 /* dump this loop node */
1521 dump_loop_node(loop);
1523 /* dump edges to nodes in loop -- only if it is a real loop */
1524 if (get_loop_depth(loop) != 0) {
1525 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1526 dump_loop_node_edge(loop, i);
1529 for (i = 0; i < get_loop_n_sons(loop); i++) {
1530 dump_loops(get_loop_son(loop, i));
1531 dump_loop_son_edge(loop, i);
1536 void dump_loop_nodes_into_graph(ir_graph *irg) {
1537 ir_graph *rem = current_ir_graph;
1538 current_ir_graph = irg;
1540 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1542 current_ir_graph = rem;
1546 /************************************************************************/
1547 /* open and close vcg file */
1548 /************************************************************************/
1551 dump_vcg_header(const char *name, const char *orientation) {
1560 if (!orientation) orientation = "bottom_to_top";
1564 "graph: { title: \"ir graph of %s\"\n"
1565 "display_edge_labels: %s\n"
1566 "layoutalgorithm: mindepth\n"
1567 "manhattan_edges: yes\n"
1568 "port_sharing: no\n"
1570 "classname 1: \"Data\"\n"
1571 "classname 2: \"Block\"\n"
1572 "classname 13:\"Control Flow\"\n"
1573 "classname 14:\"Memory\"\n"
1574 "classname 15:\"Dominators\"\n"
1575 "classname 3: \"Entity type\"\n"
1576 "classname 4: \"Entity owner\"\n"
1577 "classname 5: \"Method Param\"\n"
1578 "classname 6: \"Method Res\"\n"
1579 "classname 7: \"Super\"\n"
1580 "classname 8: \"Union\"\n"
1581 "classname 9: \"Points-to\"\n"
1582 "classname 10: \"Array Element Type\"\n"
1583 "classname 11: \"Overwrites\"\n"
1584 "classname 12: \"Member\"\n"
1585 "infoname 1: \"Attribute\"\n"
1586 "infoname 2: \"Verification errors\"\n",
1587 name, label, orientation);
1589 fprintf (F, "\n"); /* a separator */
1592 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1593 const char *nm = get_irg_dump_name(irg);
1594 int len = strlen(nm), i, j;
1595 char *fname; /* filename to put the vcg information in */
1597 if (!suffix1) suffix1 = "";
1598 if (!suffix2) suffix2 = "";
1600 /** open file for vcg graph */
1601 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1603 //strncpy (fname, nm, len); /* copy the filename */
1605 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1607 fname[j] = '@'; j++; fname[j] = '1'; j++;
1608 } else if (nm[i] == '@') {
1609 fname[j] = '@'; j++; fname[j] = '2'; j++;
1611 fname[j] = nm[i]; j++;
1615 strcat (fname, suffix1); /* append file suffix */
1616 strcat (fname, suffix2); /* append file suffix */
1617 strcat (fname, ".vcg"); /* append the .vcg suffix */
1618 F = fopen (fname, "w"); /* open file for writing */
1620 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1625 static void vcg_open_name (const char *name, char *suffix) {
1626 char *fname; /* filename to put the vcg information in */
1627 int i, j, len = strlen(name);
1629 if (!suffix) suffix = "";
1631 /** open file for vcg graph */
1632 fname = malloc (len * 2 + 5 + strlen(suffix));
1633 //strcpy (fname, name); /* copy the filename */
1635 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1636 if (name[i] == '/') {
1637 fname[j] = '@'; j++; fname[j] = '1'; j++;
1638 } else if (name[i] == '@') {
1639 fname[j] = '@'; j++; fname[j] = '2'; j++;
1641 fname[j] = name[i]; j++;
1645 strcat (fname, suffix);
1646 strcat (fname, ".vcg"); /* append the .vcg suffix */
1647 F = fopen (fname, "w"); /* open file for writing */
1649 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1654 static INLINE void dump_vcg_footer (void) {
1660 dump_vcg_footer(); /* print footer */
1661 fclose (F); /* close vcg file */
1664 /************************************************************************/
1665 /************************************************************************/
1666 /* Routines that dump all or parts of the firm representation to a file */
1667 /************************************************************************/
1668 /************************************************************************/
1670 /************************************************************************/
1671 /* Dump ir graphs, differnt formats and additional information. */
1672 /************************************************************************/
1674 /** Routine to dump a graph, blocks as conventional nodes.
1677 dump_ir_graph (ir_graph *irg)
1681 rem = current_ir_graph;
1683 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1685 current_ir_graph = irg;
1686 if (interprocedural_view) suffix = "-pure-ip";
1687 else suffix = "-pure";
1688 vcg_open (irg, dump_file_suffix, suffix);
1689 dump_vcg_header(get_irg_dump_name(irg), NULL);
1691 /* walk over the graph */
1692 /* dump_whole_node must be called in post visiting predecessors */
1693 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1695 /* dump the out edges in a separate walk */
1696 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1697 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1702 current_ir_graph = rem;
1707 dump_ir_block_graph (ir_graph *irg)
1712 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1714 if (interprocedural_view) suffix = "-ip";
1716 vcg_open (irg, dump_file_suffix, suffix);
1717 dump_vcg_header(get_irg_dump_name(irg), NULL);
1719 construct_block_lists(irg);
1721 for (i = 0; i < get_irp_n_irgs(); i++) {
1722 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1724 dump_graph(get_irp_irg(i));
1732 /** dumps a graph with type information
1735 dump_ir_graph_w_types (ir_graph *irg)
1737 ir_graph *rem = current_ir_graph;
1740 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1742 current_ir_graph = irg;
1744 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1745 else suffix = "-pure-wtypes";
1746 vcg_open (irg, dump_file_suffix, suffix);
1747 dump_vcg_header(get_irg_dump_name(irg), NULL);
1749 /* dump common ir graph */
1750 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1751 /* dump type info */
1752 type_walk_irg(irg, dump_type_info, NULL, NULL);
1753 inc_irg_visited(get_const_code_irg());
1754 /* dump edges from graph to type info */
1755 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1758 current_ir_graph = rem;
1762 dump_ir_block_graph_w_types (ir_graph *irg)
1766 ir_graph *rem = current_ir_graph;
1768 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1770 if (interprocedural_view) suffix = "-wtypes-ip";
1771 else suffix = "-wtypes";
1772 vcg_open (irg, dump_file_suffix, suffix);
1773 dump_vcg_header(get_irg_dump_name(irg), NULL);
1775 /* dump common blocked ir graph */
1776 construct_block_lists(irg);
1778 for (i = 0; i < get_irp_n_irgs(); i++) {
1779 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1781 dump_graph(get_irp_irg(i));
1786 /* dump type info */
1787 current_ir_graph = irg;
1788 type_walk_irg(irg, dump_type_info, NULL, NULL);
1789 inc_irg_visited(get_const_code_irg());
1791 /* dump edges from graph to type info */
1792 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1794 current_ir_graph = rem;
1798 /***********************************************************************/
1799 /* The following routines dump a control flow graph. */
1800 /***********************************************************************/
1803 dump_block_to_cfg (ir_node *block, void *env) {
1807 if (is_Block(block)) {
1808 /* This is a block. Dump a node for the block. */
1809 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1810 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1811 PRINT_NODEID(block);
1813 if (dump_dominator_information_flag)
1814 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1816 /* Dump the edges */
1817 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1818 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1819 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1820 fprintf (F, "edge: { sourcename: \"");
1821 PRINT_NODEID(block);
1822 fprintf (F, "\" targetname: \"");
1824 fprintf (F, "\"}\n");
1827 /* Dump dominator edge */
1828 if (dump_dominator_information_flag && get_Block_idom(block)) {
1829 pred = get_Block_idom(block);
1830 fprintf (F, "edge: { sourcename: \"");
1831 PRINT_NODEID(block);
1832 fprintf (F, "\" targetname: \"");
1834 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1840 dump_cfg (ir_graph *irg)
1842 ir_graph *rem = current_ir_graph;
1843 int ddif = dump_dominator_information_flag;
1844 int ipv = interprocedural_view;
1846 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1848 current_ir_graph = irg;
1850 vcg_open (irg, dump_file_suffix, "-cfg");
1851 dump_vcg_header(get_irg_dump_name(irg), NULL);
1853 if (interprocedural_view) {
1854 printf("Warning: dumping cfg not in interprocedural view!\n");
1855 interprocedural_view = 0;
1858 if (get_irg_dom_state(irg) != dom_consistent)
1859 dump_dominator_information_flag = 0;
1861 /* walk over the blocks in the graph */
1862 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1863 dump_node (get_irg_bad(irg));
1865 dump_dominator_information_flag = ddif;
1866 interprocedural_view = ipv;
1868 current_ir_graph = rem;
1873 /* Dump all irgs in interprocedural view to a single file. */
1874 void dump_all_cg_block_graph(void) {
1876 int rem_view = interprocedural_view;
1877 interprocedural_view = 1;
1879 vcg_open_name ("All_graphs", dump_file_suffix);
1880 dump_vcg_header("All_graphs", NULL);
1882 /* collect nodes in all irgs reachable in call graph*/
1883 for (i = 0; i < get_irp_n_irgs(); i++)
1884 ird_set_irg_link(get_irp_irg(i), NULL);
1886 cg_walk(clear_link, collect_node, NULL);
1888 /* dump all graphs */
1889 for (i = 0; i < get_irp_n_irgs(); i++) {
1890 current_ir_graph = get_irp_irg(i);
1891 assert(ird_get_irg_link(current_ir_graph));
1892 dump_graph(current_ir_graph);
1893 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1897 interprocedural_view = rem_view;
1900 /***********************************************************************/
1901 /* the following routines dumps type information without any ir nodes. */
1902 /***********************************************************************/
1905 dump_type_graph (ir_graph *irg)
1908 rem = current_ir_graph;
1910 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1912 current_ir_graph = irg;
1914 vcg_open (irg, dump_file_suffix, "-type");
1915 dump_vcg_header(get_irg_dump_name(irg), NULL);
1917 /* walk over the blocks in the graph */
1918 type_walk_irg(irg, dump_type_info, NULL, NULL);
1919 /* The walker for the const code can be called several times for the
1920 same (sub) experssion. So that no nodes are dumped several times
1921 we decrease the visited flag of the corresponding graph after each
1922 walk. So now increase it finally. */
1923 inc_irg_visited(get_const_code_irg());
1926 current_ir_graph = rem;
1930 dump_all_types (void)
1932 vcg_open_name ("All_types", dump_file_suffix);
1933 dump_vcg_header("All_types", NULL);
1934 type_walk(dump_type_info, NULL, NULL);
1935 inc_irg_visited(get_const_code_irg());
1940 dump_class_hierarchy (bool entities)
1942 vcg_open_name ("class_hierarchy", dump_file_suffix);
1943 dump_vcg_header("class_hierarchy", NULL);
1945 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1947 type_walk(dump_class_hierarchy_node, NULL, NULL);
1951 /***********************************************************************/
1952 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1954 /* dump_ir_block_graph */
1956 /* dump_type_graph */
1957 /* dump_ir_graph_w_types */
1958 /***********************************************************************/
1960 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1962 for (i=0; i < get_irp_n_irgs(); i++) {
1963 dmp_grph(get_irp_irg(i));
1968 /**********************************************************************************
1969 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1970 * packed together in one subgraph *
1971 **********************************************************************************/
1975 void dump_loops_standalone (ir_loop *loop) {
1976 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
1978 ir_loop *son = NULL;
1980 /* Dump a new loop node. */
1981 dump_loop_node(loop);
1983 /* Dump the loop elements. */
1985 if (get_kind(son) == k_ir_loop)
1987 /* We are a loop son -> Recurse */
1988 le = get_loop_element(loop, i);
1991 if (get_kind(son) == k_ir_loop) {
1992 /* We are a loop son -> Recurse */
1994 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
1995 fprintf(F, "\" }\n");
1996 fprintf (F, "edge: {sourcename: \"");
1998 fprintf (F, "\" targetname: \"");
2000 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2001 loop_node_started = 0;
2003 dump_loop_son_edge(loop, son_number++);
2004 dump_loops_standalone(son);
2007 /* We are a loop node -> Collect firm nodes */
2009 ir_node *n = le.node;
2011 if (!loop_node_started) {
2012 /* Start a new node which contains all firm nodes of the current loop */
2013 fprintf (F, "node: { title: \"");
2015 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2016 loop_node_started = 1;
2022 dump_node_opcode(F, n);
2024 dump_node_typeinfo(n);
2026 dump_node_nodeattr(n);
2027 fprintf (F, " %ld", get_irn_node_nr(n));
2031 if (loop_node_started) {
2032 fprintf(F, "\" }\n");
2033 fprintf (F, "edge: {sourcename: \"");
2035 fprintf (F, "\" targetname: \"");
2037 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2038 loop_node_started = 0;
2042 void dump_loop_tree(ir_graph *irg, char *suffix)
2044 ir_graph *rem = current_ir_graph;
2045 int el_rem = edge_label;
2048 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2050 current_ir_graph = irg;
2052 vcg_open(irg, suffix, "-looptree");
2053 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2055 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2059 edge_label = el_rem;
2060 current_ir_graph = rem;
2064 /*******************************************************************************/
2065 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2066 /*******************************************************************************/
2068 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2069 int i, son_number = 0, node_number = 0;
2071 if (dump_loop_information_flag) dump_loop_node(loop);
2073 for (i = 0; i < get_loop_n_elements(loop); i++) {
2074 loop_element le = get_loop_element(loop, i);
2075 if (*(le.kind) == k_ir_loop) {
2076 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2078 collect_nodeloop(le.son, loopnodes);
2080 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2081 eset_insert(loopnodes, le.node);
2086 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2089 for(i = 0; i < get_loop_n_elements(loop); i++) {
2090 loop_element le = get_loop_element(loop, i);
2091 if (*(le.kind) == k_ir_loop) {
2093 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2095 if (is_Block(le.node)) start = 0; else start = -1;
2096 for (j = start; j < get_irn_arity(le.node); j++) {
2097 ir_node *pred = get_irn_n(le.node, j);
2098 if (!eset_contains(loopnodes, pred)) {
2099 eset_insert(extnodes, pred);
2100 if (!is_Block(pred)) {
2101 pred = get_nodes_block(pred);
2102 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2110 void dump_loop (ir_loop *l, char *suffix) {
2112 eset *loopnodes = eset_create();
2113 eset *extnodes = eset_create();
2116 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2117 vcg_open_name (name, suffix);
2118 dump_vcg_header(name, NULL);
2120 /* collect all nodes to dump */
2121 collect_nodeloop(l, loopnodes);
2122 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2124 /* build block lists */
2125 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2126 set_irn_link(n, NULL);
2127 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2128 set_irn_link(n, NULL);
2129 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2131 b = get_nodes_block(n);
2132 set_irn_link(n, get_irn_link(b));
2135 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2137 b = get_nodes_block(n);
2138 set_irn_link(n, get_irn_link(b));
2142 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2144 fprintf(F, "graph: { title: \"");
2146 fprintf(F, "\" label: \"");
2147 dump_node_opcode(F, b);
2148 fprintf (F, " %ld", get_irn_node_nr(b));
2149 fprintf(F, "\" status:clustered color:yellow\n");
2151 /* dump the blocks edges */
2152 dump_ir_data_edges(b);
2154 /* dump the nodes that go into the block */
2155 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2156 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2158 overrule_nodecolor = NULL;
2159 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2162 /* Close the vcg information for the block */
2164 dump_const_node_local(b);
2167 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2169 fprintf(F, "graph: { title: \"");
2171 fprintf(F, "\" label: \"");
2172 dump_node_opcode(F, b);
2173 fprintf (F, " %ld", get_irn_node_nr(b));
2174 fprintf(F, "\" status:clustered color:lightblue\n");
2176 /* dump the nodes that go into the block */
2177 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2178 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2180 overrule_nodecolor = NULL;
2181 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2184 /* Close the vcg information for the block */
2186 dump_const_node_local(b);
2190 eset_destroy(loopnodes);
2191 eset_destroy(extnodes);