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"
46 void dump_chi_term(FILE *FL, ir_node *n);
47 void dump_state(FILE *FL, ir_node *n);
48 int get_opt_dump_abstvals(void);
49 typedef unsigned long SeqNo;
50 SeqNo get_Block_seqno(ir_node *n);
53 /* Attributes of nodes */
54 #define PRINT_DEFAULT_NODE_ATTR
55 #define DEFAULT_NODE_ATTR " "
56 #define DEFAULT_TYPE_ATTRIBUTE " "
57 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
59 /* Attributes of edges between Firm nodes */
60 #define BLOCK_EDGE_ATTR "class:2 priority: 2 linestyle: dotted"
61 #define CF_EDGE_ATTR "class:13 color: red"
62 #define MEM_EDGE_ATTR "class:14 color: blue"
63 #define DOMINATOR_EDGE_ATTR "class:15 color: red"
65 #define BACK_EDGE_ATTR "linestyle: dashed "
67 /* Attributes of edges between Firm nodes and type/entity nodes */
68 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
70 /* Attributes of edges in type/entity graphs. */
71 #define TYPE_METH_NODE_ATTR "color: lightyellow"
72 #define TYPE_CLASS_NODE_ATTR "color: green"
73 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
74 #define ENTITY_NODE_ATTR "color: yellow"
75 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
76 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
77 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
78 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
79 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
80 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
81 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
82 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
83 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
84 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
85 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
86 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
87 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
88 #define ENUM_ITEM_NODE_ATTR "color: green"
90 #if DEBUG_libfirm && NODEID_AS_LABEL
91 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
92 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
93 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
94 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
95 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
96 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
97 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%ld", get_type_nr(X), (Y))
100 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
101 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
102 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
103 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
104 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
105 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
106 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (P))
110 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
115 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
116 fprintf(F, " targetname: "); PRINT_TYPEID(T);
117 vfprintf(F, fmt, ap);
122 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
127 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
128 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
129 vfprintf(F, fmt, ap);
134 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
139 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
140 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
141 vfprintf(F, fmt, ap);
146 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
151 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
152 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
153 vfprintf(F, fmt, ap);
158 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
163 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
164 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
165 vfprintf(F, fmt, ap);
170 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
175 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
176 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
178 vfprintf(F, fmt, ap);
183 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
188 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
189 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
190 vfprintf(F, fmt, ap);
195 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
200 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
201 fprintf(F, " targetname: \""); PRINT_ITEMID(E,item); fprintf(F, "\" ");
202 vfprintf(F, fmt, ap);
207 /*******************************************************************/
208 /* global and ahead declarations */
209 /*******************************************************************/
211 /* A suffix to manipulate the file name. */
212 char *dump_file_suffix = "";
214 char *dump_file_filter = "";
216 /* file to dump to */
219 static void dump_whole_node(ir_node *n, void* env);
220 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
222 /*******************************************************************/
223 /* Helper functions. */
224 /*******************************************************************/
226 /* Use private link attr to be able to call dumper anywhere without
227 destroying link fields. */
229 static pmap *irdump_link_map = NULL;
231 static void init_irdump(void) {
232 /* We need a new, empty map. */
233 if (irdump_link_map) pmap_destroy(irdump_link_map);
234 irdump_link_map = pmap_create();
238 void *ird_get_irn_link(ir_node *n) {
240 if (!irdump_link_map) return NULL;
242 if (pmap_contains(irdump_link_map, (void *)n))
243 res = pmap_get(irdump_link_map, (void *)n);
247 void ird_set_irn_link(ir_node *n, void *x) {
248 if (!irdump_link_map) init_irdump();
249 pmap_insert(irdump_link_map, (void *)n, x);
252 void *ird_get_irg_link(ir_graph *irg) {
254 if (!irdump_link_map) return NULL;
256 if (pmap_contains(irdump_link_map, (void *)irg))
257 res = pmap_get(irdump_link_map, (void *)irg);
261 void ird_set_irg_link(ir_graph *irg, void *x) {
262 if (!irdump_link_map) init_irdump();
263 pmap_insert(irdump_link_map, (void *)irg, x);
266 static void clear_link(ir_node * node, void * env) {
267 ird_set_irn_link(node, NULL);
271 static int node_floats(ir_node *n) {
272 return ((get_op_pinned(get_irn_op(n)) == floats) &&
273 (get_irg_pinned(current_ir_graph) == floats));
276 static const char *get_ent_dump_name (entity *ent) {
277 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
278 if (ent->ld_name) return get_id_str(ent->ld_name);
279 return get_id_str(ent->name);
282 static const char *get_irg_dump_name (ir_graph *irg) {
283 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
284 entity *ent = get_irg_ent(irg);
285 return get_ent_dump_name(ent);
288 static void collect_node(ir_node * node, void *env) {
291 || get_irn_op(node) == op_Bad
292 || get_irn_op(node) == op_Unknown) {
293 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
294 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
295 ARR_APP1(ir_node *, arr, node);
296 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
298 ir_node * block = get_nodes_block(node);
299 ird_set_irn_link(node, ird_get_irn_link(block));
300 ird_set_irn_link(block, node);
304 /** Construct lists to walk ir block-wise.
306 * Collects all blocks, nodes not pinned,
307 * Bad and Unknown into a flexible array in link field of
308 * irg they belong to. Sets the irg link field to NULL in all
309 * graphs not visited.
310 * Free the list with DEL_ARR_F. */
311 static ir_node ** construct_block_lists(ir_graph *irg) {
313 ir_graph *rem = current_ir_graph;
314 current_ir_graph = irg;
316 for (i = 0; i < get_irp_n_irgs(); i++)
317 ird_set_irg_link(get_irp_irg(i), NULL);
319 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
321 current_ir_graph = rem;
322 return ird_get_irg_link(irg);
325 /*******************************************************************/
326 /* flags to steer output */
327 /*******************************************************************/
329 /* A compiler option to turn off edge labels */
331 /* A compiler option to turn off dumping values of constant entities */
332 int const_entities = 1;
333 /* A compiler option to dump the keep alive edges */
334 int dump_keepalive = 0;
335 /* Compiler options to dump analysis information in dump_ir_graph */
336 int dump_out_edge_flag = 0;
337 int dump_dominator_information_flag = 0;
338 int dump_loop_information_flag = 0;
339 int dump_backedge_information_flag = 1;
340 int dump_const_local = 0;
341 bool opt_dump_analysed_type_info = 1;
342 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
344 char* overrule_nodecolor = NULL;
346 INLINE bool get_opt_dump_const_local(void) {
347 if (!dump_out_edge_flag && !dump_loop_information_flag)
348 return dump_const_local;
353 /* To turn off display of edge labels. Edge labels offen cause xvcg to
354 abort with a segmentation fault. */
355 void turn_off_edge_labels(void) {
359 void dump_consts_local(bool b) {
360 dump_const_local = b;
363 void turn_off_constant_entity_values(void) {
367 void dump_keepalive_edges(bool b) {
371 bool get_opt_dump_keepalive_edges(void) {
372 return dump_keepalive;
375 void dump_out_edges(void) {
376 dump_out_edge_flag = 1;
379 void dump_dominator_information(void) {
380 dump_dominator_information_flag = 1;
383 void dump_loop_information(void) {
384 dump_loop_information_flag = 1;
387 void dont_dump_loop_information(void) {
388 dump_loop_information_flag = 0;
391 void dump_backedge_information(bool b) {
392 dump_backedge_information_flag = b;
395 /* Dump the information of type field specified in ana/irtypeinfo.h.
396 * If the flag is set, the type name is output in [] in the node label,
397 * else it is output as info.
399 void dump_analysed_type_info(bool b) {
400 opt_dump_analysed_type_info = b;
403 void dump_pointer_values_to_info(bool b) {
404 opt_dump_pointer_values_to_info = b;
407 /*******************************************************************/
408 /* Routines to dump information about a single ir node. */
409 /*******************************************************************/
412 dump_node_opcode (ir_node *n)
415 switch(get_irn_opcode(n)) {
420 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
421 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
426 if (get_SymConst_kind(n) == linkage_ptr_info) {
427 /* don't use get_SymConst_ptr_info as it mangles the name. */
428 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
430 assert(get_kind(get_SymConst_type(n)) == k_type);
431 assert(get_type_ident(get_SymConst_type(n)));
432 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
433 if (get_SymConst_kind(n) == type_tag)
441 if (!interprocedural_view) fprintf(F, "Proj'");
442 else fprintf(F, "%s", get_irn_opname(n));
446 if (interprocedural_view) {
447 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
453 fprintf (F, "%s", get_irn_opname(n));
460 dump_node_mode (ir_node *n)
462 switch (get_irn_opcode(n)) {
481 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
488 static void dump_node_typeinfo(ir_node *n) {
489 if (!opt_dump_analysed_type_info) return;
490 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
491 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
492 type *tp = get_irn_type(n);
494 fprintf (F, " [%s]", get_type_name(tp));
501 dump_node_nodeattr (ir_node *n)
503 switch (get_irn_opcode(n)) {
505 if (false && interprocedural_view) {
506 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
510 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
511 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
513 fprintf (F, "%ld", get_Proj_proj(n));
517 fprintf (F, "%ld", get_Filter_proj(n));
520 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
523 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
526 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
535 dump_node_vcgattr (ir_node *n)
537 switch (get_irn_opcode(n)) {
544 fprintf (F, "color: blue");
547 fprintf (F, "color: lightyellow");
550 fprintf (F, "color: green");
556 fprintf (F, "color: yellow");
559 PRINT_DEFAULT_NODE_ATTR;
562 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
566 dump_node_info (ir_node *n) {
570 fprintf (F, " info1: \"");
571 if (opt_dump_pointer_values_to_info)
572 fprintf (F, "addr: %p \n", (void *)n);
573 fprintf (F, "visited: %ld \n", get_irn_visited(n));
574 irg = get_irn_irg(n);
575 if (irg != get_const_code_irg())
576 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
578 fprintf(F, "arity: %d", get_irn_arity(n));
579 if ((get_irn_op(n) == op_Block) ||
580 (get_irn_op(n) == op_Phi) ||
581 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
582 fprintf(F, " backedges:");
584 for (i = 0; i < get_irn_arity(n); i++)
585 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
591 switch (get_irn_opcode(n)) {
593 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
594 fprintf(F, "start of method of type %s \n", get_type_name(tp));
595 for (i = 0; i < get_method_n_params(tp); ++i)
596 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
599 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
602 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
605 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
606 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
609 type *tp = get_Call_type(n);
610 fprintf(F, "calling method of type %s \n", get_type_name(tp));
611 for (i = 0; i < get_method_n_params(tp); ++i)
612 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
613 for (i = 0; i < get_method_n_ress(tp); ++i)
614 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
615 if (Call_has_callees(n)) {
616 fprintf(F, "possible callees: \n");
617 for (i = 0; i < get_Call_n_callees(n); i++) {
618 if (!get_Call_callee(n, i)) {
619 fprintf(F, " %d external method\n", i);
621 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
626 case iro_CallBegin: {
627 ir_node *call = get_CallBegin_call(n);
628 if (Call_has_callees(call)) {
629 fprintf(F, "possible callees: \n");
630 for (i = 0; i < get_Call_n_callees(call); i++) {
631 if (!get_Call_callee(call, i)) {
632 fprintf(F, " %d external method\n", i);
634 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
640 if (!interprocedural_view) {
641 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
642 fprintf(F, "return in method of type %s \n", get_type_name(tp));
643 for (i = 0; i < get_method_n_ress(tp); ++i)
644 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
648 type *tp = get_Const_type(n);
649 assert(tp != none_type);
650 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
654 if (interprocedural_view) {
655 fprintf(F, "intra predecessor nodes:\n");
656 for (i = 0; i < get_irn_intra_arity(n); i++) {
657 ir_node *pred = get_irn_intra_n(n, i);
658 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
661 fprintf(F, "inter predecessor nodes:\n");
662 for (i = 0; i < get_irn_inter_arity(n); i++) {
663 ir_node *pred = get_irn_inter_n(n, i);
664 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
665 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
673 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
674 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
675 if (get_irn_type(n) != none_type)
676 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
683 bool is_constlike_node(ir_node *n) {
684 ir_op *op = get_irn_op(n);
685 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
689 /* outputs the predecessors of n, that are constants, local. I.e.,
690 generates a copy of the constant predecessors for each node called with. */
691 static void dump_const_node_local(ir_node *n) {
693 if (!get_opt_dump_const_local()) return;
695 /* Use visited flag to avoid outputting nodes twice.
696 initialize it first. */
697 for (i = 0; i < get_irn_arity(n); i++) {
698 ir_node *con = get_irn_n(n, i);
699 if (is_constlike_node(con)) {
700 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
704 for (i = 0; i < get_irn_arity(n); i++) {
705 ir_node *con = get_irn_n(n, i);
706 if (is_constlike_node(con) && irn_not_visited(con)) {
707 mark_irn_visited(con);
708 /* Generate a new name for the node by appending the names of
710 fprintf (F, "node: {title: "); PRINT_CONSTID(n, con);
711 fprintf(F, " label: \"");
712 dump_node_opcode(con);
713 dump_node_mode (con);
714 dump_node_typeinfo(con);
716 dump_node_nodeattr(con);
717 fprintf (F, " %ld", get_irn_node_nr(con));
719 dump_node_vcgattr(con);
727 dump_node (ir_node *n) {
728 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
730 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
734 dump_node_typeinfo(n);
736 dump_node_nodeattr(n);
737 fprintf (F, " %ld", get_irn_node_nr(n));
739 dump_node_vcgattr(n);
742 dump_const_node_local(n);
749 /* dump the edge to the block this node belongs to */
751 dump_ir_block_edge(ir_node *n) {
752 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
753 if (is_no_Block(n)) {
754 fprintf (F, "edge: { sourcename: \"");
756 fprintf (F, "\" targetname: \"");
757 PRINT_NODEID(get_nodes_block(n));
758 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
762 static void print_edge_vcgattr(ir_node *from, int to) {
765 if (dump_backedge_information_flag && is_backedge(from, to))
766 fprintf (F, BACK_EDGE_ATTR);
768 switch (get_irn_opcode(from)) {
770 fprintf (F, CF_EDGE_ATTR);
772 case iro_Start: break;
775 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
776 fprintf (F, CF_EDGE_ATTR);
777 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
778 fprintf (F, MEM_EDGE_ATTR);
781 case iro_EndReg: break;
782 case iro_EndExcept: break;
784 case iro_Break: break;
785 case iro_Cond: break;
788 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
790 case iro_Const: break;
791 case iro_SymConst:break;
794 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
796 case iro_CallBegin: break;
799 case iro_Minus: break;
805 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
813 case iro_Shrs: break;
816 case iro_Conv: break;
818 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
824 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
827 fprintf (F, MEM_EDGE_ATTR);
829 case iro_Tuple: break;
832 switch (get_irn_modecode(from)) {
834 fprintf (F, CF_EDGE_ATTR);
837 fprintf (F, MEM_EDGE_ATTR);
843 case iro_Unknown: break;
850 /* dump edges to our inputs */
852 dump_ir_data_edges(ir_node *n) {
853 int i, visited = get_irn_visited(n);
855 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
858 for (i = 0; i < get_irn_arity(n); i++) {
859 ir_node * pred = get_irn_n(n, i);
862 if ((interprocedural_view && get_irn_visited(pred) < visited))
863 continue; /* pred not dumped */
865 if (dump_backedge_information_flag && is_backedge(n, i))
866 fprintf (F, "backedge: {sourcename: \"");
868 fprintf (F, "edge: {sourcename: \"");
870 fprintf (F, "\" targetname: ");
871 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
872 PRINT_CONSTID(n, pred);
874 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
876 fprintf (F, " label: \"%d\" ", i);
877 print_edge_vcgattr(n, i);
882 /** Dumps a node and its edges but not the block edge
885 dump_node_wo_blockedge (ir_node *n, void* env) {
887 dump_ir_data_edges(n);
890 /** Dumps a node and its edges.
893 dump_whole_node (ir_node *n, void* env) {
894 dump_node_wo_blockedge(n, env);
895 if (!node_floats(n)) dump_ir_block_edge(n);
899 dump_const_node(ir_node *n, void *env) {
900 if (is_Block(n)) return;
901 dump_node_wo_blockedge(n, env);
904 /***********************************************************************/
905 /* the following routines dump the nodes/irgs bracketed to graphs. */
906 /***********************************************************************/
908 /** Dumps a constant expression as entity initializer, array bound ...
910 static void dump_const_expression(ir_node *value) {
911 ir_graph *rem = current_ir_graph;
912 int rem_dump_const_local = dump_const_local;
913 dump_const_local = 0;
914 current_ir_graph = get_const_code_irg();
915 irg_walk(value, dump_const_node, NULL, NULL);
916 /* Decrease visited flag so that we walk with the same flag for the next
917 expresssion. This guarantees that we don't dump the same node twice,
918 as for const expressions cse is performed to save memory. */
919 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
920 current_ir_graph = rem;
921 dump_const_local = rem_dump_const_local;
924 /** Dump a block as graph containing its nodes.
926 * Expects to find nodes belonging to the block as list in its
928 * Dumps the edges of all nodes including itself. */
930 dump_whole_block(ir_node *block) {
932 assert(is_Block(block));
934 fprintf(F, "graph: { title: \"");
936 fprintf(F, "\" label: \"");
937 dump_node_opcode(block);
938 fprintf (F, " %ld", get_irn_node_nr(block));
940 if (get_opt_dump_abstvals())
941 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
943 fprintf(F, "\" status:clustered color:%s \n",
944 get_Block_matured(block) ? "yellow" : "red");
946 /* dump the blocks edges */
947 dump_ir_data_edges(block);
949 /* dump the nodes that go into the block */
950 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
952 dump_ir_data_edges(node);
955 /* Close the vcg information for the block */
957 dump_const_node_local(block);
959 dump_chi_term(F, block);
964 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
965 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
967 dump_block_graph (ir_graph *irg) {
969 ir_graph *rem = current_ir_graph;
970 ir_node **arr = ird_get_irg_link(irg);
971 current_ir_graph = irg;
973 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
974 ir_node * node = arr[i];
975 if (is_Block(node)) {
976 /* Dumps the block and all the nodes in the block, which are to
977 be found in Block->link. */
978 dump_whole_block(node);
980 /* Nodes that are not in a Block. */
982 dump_ir_data_edges(node);
986 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
988 current_ir_graph = rem;
991 /** Dumps an irg as a graph.
992 * If interprocedural view edges can point to nodes out of this graph.
994 static void dump_graph(ir_graph *irg) {
996 fprintf(F, "graph: { title: \"");
998 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
999 get_ent_dump_name(get_irg_ent(irg)));
1001 dump_block_graph (irg);
1003 /* Close the vcg information for the irg */
1004 fprintf(F, "}\n\n");
1007 /*******************************************************************/
1008 /* Basic type and entity nodes and edges. */
1009 /*******************************************************************/
1011 /* dumps the edges between nodes and their type or entity attributes. */
1012 static void dump_node2type_edges (ir_node *n, void *env)
1016 switch (get_irn_opcode(n)) {
1018 /* @@@ some consts have an entity */
1021 if ( (get_SymConst_kind(n) == type_tag)
1022 || (get_SymConst_kind(n) == size))
1024 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1028 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1031 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1034 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1037 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1040 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1048 static void print_type_info(type *tp) {
1049 if (get_type_state(tp) == layout_undefined) {
1050 fprintf(F, "state: layout_undefined\n");
1052 fprintf(F, "state: layout_fixed,\n");
1054 if (get_type_mode(tp))
1055 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1056 fprintf(F, "size: %dB,\n", get_type_size(tp));
1059 static void print_typespecific_info(type *tp) {
1060 switch (get_type_tpop_code(tp)) {
1063 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1077 case tpo_enumeration:
1091 static void print_typespecific_vcgattr(type *tp) {
1092 switch (get_type_tpop_code(tp)) {
1095 if (peculiarity_existent == get_class_peculiarity(tp))
1096 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1098 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1102 fprintf (F, " " TYPE_METH_NODE_ATTR);
1113 case tpo_enumeration:
1126 static void print_type_node(type *tp)
1128 fprintf (F, "node: {title: ");
1130 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
1131 fprintf (F, " info1: \"");
1132 print_type_info(tp);
1133 print_typespecific_info(tp);
1135 print_typespecific_vcgattr(tp);
1139 #define X(a) case a: fprintf(F, #a); break
1140 void dump_entity_node(entity *ent)
1142 fprintf (F, "node: {title: \"");
1143 PRINT_ENTID(ent); fprintf(F, "\"");
1144 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1145 fprintf (F, "label: ");
1146 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1147 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1149 fprintf (F, "\nallocation: ");
1150 switch (get_entity_allocation(ent)) {
1151 X(allocation_dynamic);
1152 X(allocation_automatic);
1153 X(allocation_static);
1154 X(allocation_parameter);
1157 fprintf (F, "\nvisibility: ");
1158 switch (get_entity_visibility(ent)) {
1159 X(visibility_local);
1160 X(visibility_external_visible);
1161 X(visibility_external_allocated);
1164 fprintf (F, "\nvariability: ");
1165 switch (get_entity_variability(ent)) {
1166 X(variability_uninitialized);
1167 X(variability_initialized);
1168 X(variability_part_constant);
1169 X(variability_constant);
1172 fprintf (F, "\nvolatility: ");
1173 switch (get_entity_volatility(ent)) {
1174 X(volatility_non_volatile);
1175 X(volatility_is_volatile);
1178 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1179 fprintf(F, "\nname: %s\nld_name: %s",
1180 get_ent_dump_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1181 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1182 if (is_method_type(get_entity_type(ent))) {
1183 if (get_entity_irg(ent)) /* can be null */
1184 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1186 { fprintf (F, "\nirg = NULL"); }
1188 fprintf(F, "\"\n}\n");
1192 static void dump_enum_item(type *tp, int pos)
1195 ident *id = get_enumeration_nameid(tp, pos);
1196 tarval *tv = get_enumeration_enum(tp, pos);
1198 tarval_snprintf(buf, sizeof(buf), tv);
1199 fprintf (F, "node: {title: \"");
1200 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1201 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1202 fprintf (F, "label: ");
1203 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1204 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1207 /* dumps a type or entity and it's edges. */
1209 dump_type_info (type_or_ent *tore, void *env) {
1210 int i = 0; /* to shutup gcc */
1212 /* dump this type or entity */
1214 switch (get_kind(tore)) {
1217 entity *ent = (entity *)tore;
1220 dump_entity_node(ent);
1222 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1223 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1224 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1225 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1226 if(is_class_type(get_entity_owner(ent))) {
1227 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1228 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1231 /* attached subgraphs */
1232 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1233 if (is_atomic_entity(ent)) {
1234 value = get_atomic_ent_value(ent);
1236 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1237 /* DDMN(value); $$$ */
1238 dump_const_expression(value);
1241 if (is_compound_entity(ent)) {
1242 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1243 value = get_compound_ent_value(ent, i);
1245 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1246 dump_const_expression(value);
1247 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1249 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1250 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1251 get_compound_ent_value_member(ent, i), i);
1260 type *tp = (type *)tore;
1261 print_type_node(tp);
1262 /* and now the edges */
1263 switch (get_type_tpop_code(tp)) {
1266 for (i=0; i < get_class_n_supertypes(tp); i++) {
1267 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1270 for (i=0; i < get_class_n_members(tp); i++) {
1271 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1276 for (i=0; i < get_struct_n_members(tp); i++) {
1277 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1282 for (i = 0; i < get_method_n_params(tp); i++)
1284 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1286 for (i = 0; i < get_method_n_ress(tp); i++)
1288 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1293 for (i = 0; i < get_union_n_members(tp); i++)
1295 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1300 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1301 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1302 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1303 ir_node *upper = get_array_upper_bound(tp, i);
1304 ir_node *lower = get_array_lower_bound(tp, i);
1305 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1306 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1307 dump_const_expression(upper);
1308 dump_const_expression(lower);
1312 case tpo_enumeration:
1314 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1315 dump_enum_item(tp, i);
1316 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1321 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1329 break; /* case k_type */
1332 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1334 } /* switch kind_or_entity */
1337 /** For dumping class hierarchies.
1338 * Dumps a class type node and a superclass edge.
1339 * If env != null dumps entities of classes and overwrites edges.
1342 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1343 int i = 0; /* to shutup gcc */
1345 /* dump this type or entity */
1346 switch (get_kind(tore)) {
1348 entity *ent = (entity *)tore;
1349 if (get_entity_owner(ent) == get_glob_type()) break;
1350 if ((env) && is_class_type(get_entity_owner(ent))) {
1352 dump_entity_node(ent);
1354 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1355 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1357 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1360 } break; /* case k_entity */
1363 type *tp = (type *)tore;
1364 if (tp == get_glob_type()) break;
1365 switch (get_type_tpop_code(tp)) {
1367 print_type_node(tp);
1368 /* and now the edges */
1369 for (i=0; i < get_class_n_supertypes(tp); i++)
1371 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1377 break; /* case k_type */
1380 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1382 } /* switch kind_or_entity */
1385 /*******************************************************************/
1386 /* dump analysis information that is expressed in graph terms. */
1387 /*******************************************************************/
1389 /* dump out edges */
1391 dump_out_edge (ir_node *n, void* env) {
1393 for (i = 0; i < get_irn_n_outs(n); i++) {
1394 assert(get_irn_out(n, i));
1395 fprintf (F, "edge: {sourcename: \"");
1397 fprintf (F, "\" targetname: \"");
1398 PRINT_NODEID(get_irn_out(n, i));
1399 fprintf (F, "\" color: red linestyle: dashed");
1405 dump_loop_label(ir_loop *loop) {
1406 fprintf (F, "loop %d, %d sons, %d nodes",
1407 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1410 static INLINE void dump_loop_info(ir_loop *loop) {
1411 fprintf (F, " info1: \"");
1412 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1413 #if DEBUG_libfirm /* GL @@@ debug analyses */
1414 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1420 dump_loop_node(ir_loop *loop) {
1421 fprintf (F, "node: {title: \"");
1423 fprintf (F, "\" label: \"");
1424 dump_loop_label(loop);
1426 dump_loop_info(loop);
1432 dump_loop_node_edge (ir_loop *loop, int i) {
1434 fprintf (F, "edge: {sourcename: \"");
1436 fprintf (F, "\" targetname: \"");
1437 PRINT_NODEID(get_loop_node(loop, i));
1438 fprintf (F, "\" color: green");
1443 dump_loop_son_edge (ir_loop *loop, int i) {
1445 fprintf (F, "edge: {sourcename: \"");
1447 fprintf (F, "\" targetname: \"");
1448 PRINT_LOOPID(get_loop_son(loop, i));
1449 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1450 get_loop_element_pos(loop, get_loop_son(loop, i)));
1454 void dump_loops (ir_loop *loop) {
1456 /* dump this loop node */
1457 dump_loop_node(loop);
1459 /* dump edges to nodes in loop -- only if it is a real loop */
1460 if (get_loop_depth(loop) != 0) {
1461 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1462 dump_loop_node_edge(loop, i);
1465 for (i = 0; i < get_loop_n_sons(loop); i++) {
1466 dump_loops(get_loop_son(loop, i));
1467 dump_loop_son_edge(loop, i);
1472 void dump_loop_nodes_into_graph(ir_graph *irg) {
1473 ir_graph *rem = current_ir_graph;
1474 current_ir_graph = irg;
1476 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1478 current_ir_graph = rem;
1482 /************************************************************************/
1483 /* open and close vcg file */
1484 /************************************************************************/
1487 dump_vcg_header(const char *name, const char *orientation) {
1496 if (!orientation) orientation = "bottom_to_top";
1500 "graph: { title: \"ir graph of %s\"\n"
1501 "display_edge_labels: %s\n"
1502 "layoutalgorithm: mindepth\n"
1503 "manhattan_edges: yes\n"
1504 "port_sharing: no\n"
1506 "classname 1: \"Data\"\n"
1507 "classname 2: \"Block\"\n"
1508 "classname 13:\"Control Flow\"\n"
1509 "classname 14:\"Memory\"\n"
1510 "classname 15:\"Dominators\"\n"
1511 "classname 3: \"Entity type\"\n"
1512 "classname 4: \"Entity owner\"\n"
1513 "classname 5: \"Method Param\"\n"
1514 "classname 6: \"Method Res\"\n"
1515 "classname 7: \"Super\"\n"
1516 "classname 8: \"Union\"\n"
1517 "classname 9: \"Points-to\"\n"
1518 "classname 10: \"Array Element Type\"\n"
1519 "classname 11: \"Overwrites\"\n"
1520 "classname 12: \"Member\"\n",
1521 name, label, orientation);
1523 fprintf (F, "\n"); /* a separator */
1526 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1527 const char *nm = get_irg_dump_name(irg);
1528 int len = strlen(nm);
1529 char *fname; /* filename to put the vcg information in */
1531 if (!suffix1) suffix1 = "";
1532 if (!suffix2) suffix2 = "";
1534 /** open file for vcg graph */
1535 fname = malloc (len + strlen(suffix1) + strlen(suffix2) + 5);
1536 strncpy (fname, nm, len); /* copy the filename */
1538 strcat (fname, suffix1); /* append file suffix */
1539 strcat (fname, suffix2); /* append file suffix */
1540 strcat (fname, ".vcg"); /* append the .vcg suffix */
1541 F = fopen (fname, "w"); /* open file for writing */
1543 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1548 static void vcg_open_name (const char *name, char *suffix) {
1549 char *fname; /* filename to put the vcg information in */
1551 if (!suffix) suffix = "";
1553 /** open file for vcg graph */
1554 fname = malloc (strlen(name) + 5 + strlen(suffix));
1555 strcpy (fname, name); /* copy the filename */
1556 strcat (fname, suffix);
1557 strcat (fname, ".vcg"); /* append the .vcg suffix */
1558 F = fopen (fname, "w"); /* open file for writing */
1560 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1565 static INLINE void dump_vcg_footer (void) {
1571 dump_vcg_footer(); /* print footer */
1572 fclose (F); /* close vcg file */
1575 /************************************************************************/
1576 /************************************************************************/
1577 /* Routines that dump all or parts of the firm representation to a file */
1578 /************************************************************************/
1579 /************************************************************************/
1581 /************************************************************************/
1582 /* Dump ir graphs, differnt formats and additional information. */
1583 /************************************************************************/
1585 /** Routine to dump a graph, blocks as conventional nodes.
1588 dump_ir_graph (ir_graph *irg)
1592 rem = current_ir_graph;
1594 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1596 current_ir_graph = irg;
1597 if (interprocedural_view) suffix = "-pure-ip";
1598 else suffix = "-pure";
1599 vcg_open (irg, dump_file_suffix, suffix);
1600 dump_vcg_header(get_irg_dump_name(irg), NULL);
1602 /* walk over the graph */
1603 /* dump_whole_node must be called in post visiting predecessors */
1604 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1606 /* dump the out edges in a separate walk */
1607 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1608 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1613 current_ir_graph = rem;
1618 dump_ir_block_graph (ir_graph *irg)
1623 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1625 if (interprocedural_view) suffix = "-ip";
1627 vcg_open (irg, dump_file_suffix, suffix);
1628 dump_vcg_header(get_irg_dump_name(irg), NULL);
1630 construct_block_lists(irg);
1632 for (i = 0; i < get_irp_n_irgs(); i++) {
1633 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1635 dump_graph(get_irp_irg(i));
1643 /** dumps a graph with type information
1646 dump_ir_graph_w_types (ir_graph *irg)
1648 ir_graph *rem = current_ir_graph;
1651 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1653 current_ir_graph = irg;
1655 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1656 else suffix = "-pure-wtypes";
1657 vcg_open (irg, dump_file_suffix, suffix);
1658 dump_vcg_header(get_irg_dump_name(irg), NULL);
1660 /* dump common ir graph */
1661 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1662 /* dump type info */
1663 type_walk_irg(irg, dump_type_info, NULL, NULL);
1664 inc_irg_visited(get_const_code_irg());
1665 /* dump edges from graph to type info */
1666 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1669 current_ir_graph = rem;
1673 dump_ir_block_graph_w_types (ir_graph *irg)
1677 ir_graph *rem = current_ir_graph;
1679 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1681 if (interprocedural_view) suffix = "-wtypes-ip";
1682 else suffix = "-wtypes";
1683 vcg_open (irg, dump_file_suffix, suffix);
1684 dump_vcg_header(get_irg_dump_name(irg), NULL);
1686 /* dump common blocked ir graph */
1687 construct_block_lists(irg);
1689 for (i = 0; i < get_irp_n_irgs(); i++) {
1690 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1692 dump_graph(get_irp_irg(i));
1697 /* dump type info */
1698 current_ir_graph = irg;
1699 type_walk_irg(irg, dump_type_info, NULL, NULL);
1700 inc_irg_visited(get_const_code_irg());
1702 /* dump edges from graph to type info */
1703 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1705 current_ir_graph = rem;
1709 /***********************************************************************/
1710 /* The following routines dump a control flow graph. */
1711 /***********************************************************************/
1714 dump_block_to_cfg (ir_node *block, void *env) {
1718 if (is_Block(block)) {
1719 /* This is a block. Dump a node for the block. */
1720 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1721 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1722 PRINT_NODEID(block);
1724 if (dump_dominator_information_flag)
1725 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1727 /* Dump the edges */
1728 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1729 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1730 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1731 fprintf (F, "edge: { sourcename: \"");
1732 PRINT_NODEID(block);
1733 fprintf (F, "\" targetname: \"");
1735 fprintf (F, "\"}\n");
1738 /* Dump dominator edge */
1739 if (dump_dominator_information_flag && get_Block_idom(block)) {
1740 pred = get_Block_idom(block);
1741 fprintf (F, "edge: { sourcename: \"");
1742 PRINT_NODEID(block);
1743 fprintf (F, "\" targetname: \"");
1745 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1751 dump_cfg (ir_graph *irg)
1753 ir_graph *rem = current_ir_graph;
1754 int ddif = dump_dominator_information_flag;
1755 int ipv = interprocedural_view;
1757 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1759 current_ir_graph = irg;
1761 vcg_open (irg, dump_file_suffix, "-cfg");
1762 dump_vcg_header(get_irg_dump_name(irg), NULL);
1764 if (interprocedural_view) {
1765 printf("Warning: dumping cfg not in interprocedural view!\n");
1766 interprocedural_view = 0;
1769 if (get_irg_dom_state(irg) != dom_consistent)
1770 dump_dominator_information_flag = 0;
1772 /* walk over the blocks in the graph */
1773 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1774 dump_node (get_irg_bad(irg));
1776 dump_dominator_information_flag = ddif;
1777 interprocedural_view = ipv;
1779 current_ir_graph = rem;
1784 /* Dump all irgs in interprocedural view to a single file. */
1785 void dump_all_cg_block_graph(void) {
1787 int rem_view = interprocedural_view;
1788 interprocedural_view = 1;
1790 vcg_open_name ("All_graphs", dump_file_suffix);
1791 dump_vcg_header("All_graphs", NULL);
1793 /* collect nodes in all irgs reachable in call graph*/
1794 for (i = 0; i < get_irp_n_irgs(); i++)
1795 ird_set_irg_link(get_irp_irg(i), NULL);
1797 cg_walk(clear_link, collect_node, NULL);
1799 /* dump all graphs */
1800 for (i = 0; i < get_irp_n_irgs(); i++) {
1801 current_ir_graph = get_irp_irg(i);
1802 assert(ird_get_irg_link(current_ir_graph));
1803 dump_graph(current_ir_graph);
1804 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1808 interprocedural_view = rem_view;
1811 /***********************************************************************/
1812 /* the following routines dumps type information without any ir nodes. */
1813 /***********************************************************************/
1816 dump_type_graph (ir_graph *irg)
1819 rem = current_ir_graph;
1821 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1823 current_ir_graph = irg;
1825 vcg_open (irg, dump_file_suffix, "-type");
1826 dump_vcg_header(get_irg_dump_name(irg), NULL);
1828 /* walk over the blocks in the graph */
1829 type_walk_irg(irg, dump_type_info, NULL, NULL);
1830 /* The walker for the const code can be called several times for the
1831 same (sub) experssion. So that no nodes are dumped several times
1832 we decrease the visited flag of the corresponding graph after each
1833 walk. So now increase it finally. */
1834 inc_irg_visited(get_const_code_irg());
1837 current_ir_graph = rem;
1841 dump_all_types (void)
1843 vcg_open_name ("All_types", dump_file_suffix);
1844 dump_vcg_header("All_types", NULL);
1845 type_walk(dump_type_info, NULL, NULL);
1846 inc_irg_visited(get_const_code_irg());
1851 dump_class_hierarchy (bool entities)
1853 vcg_open_name ("class_hierarchy", dump_file_suffix);
1854 dump_vcg_header("class_hierarchy", NULL);
1856 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1858 type_walk(dump_class_hierarchy_node, NULL, NULL);
1862 /***********************************************************************/
1863 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1865 /* dump_ir_block_graph */
1867 /* dump_type_graph */
1868 /* dump_ir_graph_w_types */
1869 /***********************************************************************/
1871 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1873 for (i=0; i < get_irp_n_irgs(); i++) {
1874 dmp_grph(get_irp_irg(i));
1879 /**********************************************************************************
1880 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1881 * packed together in one subgraph *
1882 **********************************************************************************/
1886 void dump_loops_standalone (ir_loop *loop) {
1887 int i, loop_node_started = 0, son_number = 0, first = 0;
1890 /* Dump a new loop node. */
1891 dump_loop_node(loop);
1893 /* Dump the loop elements. */
1894 for(i = 0; i < get_loop_n_elements(loop); i++) {
1897 le = get_loop_element(loop, i);
1900 if (get_kind(son) == k_ir_loop) {
1901 /* We are a loop son -> Recurse */
1903 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
1904 fprintf(F, "\" }\n");
1905 fprintf (F, "edge: {sourcename: \"");
1907 fprintf (F, "\" targetname: \"");
1909 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1910 loop_node_started = 0;
1912 dump_loop_son_edge(loop, son_number++);
1913 dump_loops_standalone(son);
1916 /* We are a loop node -> Collect firm nodes */
1918 ir_node *n = le.node;
1920 if (!loop_node_started) {
1921 /* Start a new node which contains all firm nodes of the current loop */
1922 fprintf (F, "node: { title: \"");
1924 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
1925 loop_node_started = 1;
1931 dump_node_opcode(n);
1933 dump_node_typeinfo(n);
1935 dump_node_nodeattr(n);
1936 fprintf (F, " %ld", get_irn_node_nr(n));
1940 if (loop_node_started) {
1941 fprintf(F, "\" }\n");
1942 fprintf (F, "edge: {sourcename: \"");
1944 fprintf (F, "\" targetname: \"");
1946 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1947 loop_node_started = 0;
1951 void dump_loop_tree(ir_graph *irg, char *suffix)
1953 ir_graph *rem = current_ir_graph;
1954 int el_rem = edge_label;
1957 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1959 current_ir_graph = irg;
1961 vcg_open(irg, suffix, "-looptree");
1962 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
1964 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
1968 edge_label = el_rem;
1969 current_ir_graph = rem;
1973 /*******************************************************************************/
1974 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
1975 /*******************************************************************************/
1977 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
1978 int i, son_number = 0, node_number = 0;
1980 if (dump_loop_information_flag) dump_loop_node(loop);
1982 for (i = 0; i < get_loop_n_elements(loop); i++) {
1983 loop_element le = get_loop_element(loop, i);
1984 if (*(le.kind) == k_ir_loop) {
1985 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
1987 collect_nodeloop(le.son, loopnodes);
1989 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
1990 eset_insert(loopnodes, le.node);
1995 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
1998 for(i = 0; i < get_loop_n_elements(loop); i++) {
1999 loop_element le = get_loop_element(loop, i);
2000 if (*(le.kind) == k_ir_loop) {
2002 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2004 if (is_Block(le.node)) start = 0; else start = -1;
2005 for (j = start; j < get_irn_arity(le.node); j++) {
2006 ir_node *pred = get_irn_n(le.node, j);
2007 if (!eset_contains(loopnodes, pred)) {
2008 eset_insert(extnodes, pred);
2009 if (!is_Block(pred)) {
2010 pred = get_nodes_block(pred);
2011 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2019 void dump_loop (ir_loop *l, char *suffix) {
2021 eset *loopnodes = eset_create();
2022 eset *extnodes = eset_create();
2025 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2026 vcg_open_name (name, suffix);
2027 dump_vcg_header(name, NULL);
2029 /* collect all nodes to dump */
2030 collect_nodeloop(l, loopnodes);
2031 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2033 /* build block lists */
2034 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2035 set_irn_link(n, NULL);
2036 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2037 set_irn_link(n, NULL);
2038 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2040 b = get_nodes_block(n);
2041 set_irn_link(n, get_irn_link(b));
2044 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2046 b = get_nodes_block(n);
2047 set_irn_link(n, get_irn_link(b));
2051 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2053 fprintf(F, "graph: { title: \"");
2055 fprintf(F, "\" label: \"");
2056 dump_node_opcode(b);
2057 fprintf (F, " %ld", get_irn_node_nr(b));
2058 fprintf(F, "\" status:clustered color:yellow\n");
2060 /* dump the blocks edges */
2061 dump_ir_data_edges(b);
2063 /* dump the nodes that go into the block */
2064 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2065 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2067 overrule_nodecolor = NULL;
2068 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2071 /* Close the vcg information for the block */
2073 dump_const_node_local(b);
2076 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2078 fprintf(F, "graph: { title: \"");
2080 fprintf(F, "\" label: \"");
2081 dump_node_opcode(b);
2082 fprintf (F, " %ld", get_irn_node_nr(b));
2083 fprintf(F, "\" status:clustered color:lightblue\n");
2085 /* dump the nodes that go into the block */
2086 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2087 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2089 overrule_nodecolor = NULL;
2090 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2093 /* Close the vcg information for the block */
2095 dump_const_node_local(b);
2099 eset_destroy(loopnodes);
2100 eset_destroy(extnodes);