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 INTRA_DATA_EDGE_ATTR "class:1 priority:50"
61 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
62 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
63 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
64 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
65 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
66 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
68 #define BACK_EDGE_ATTR "linestyle:dashed "
70 /* Attributes of edges between Firm nodes and type/entity nodes */
71 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
73 /* Attributes of edges in type/entity graphs. */
74 #define TYPE_METH_NODE_ATTR "color: lightyellow"
75 #define TYPE_CLASS_NODE_ATTR "color: green"
76 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
77 #define ENTITY_NODE_ATTR "color: yellow"
78 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
79 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
80 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
81 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
82 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
83 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
84 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
85 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
86 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
87 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
88 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
89 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
90 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
91 #define ENUM_ITEM_NODE_ATTR "color: green"
93 #if DEBUG_libfirm && NODEID_AS_LABEL
94 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
95 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
96 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
97 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
98 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
99 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
100 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
103 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
104 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
105 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
106 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
107 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
108 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
109 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
112 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
115 return get_mode_name(mode);
120 static const char *get_type_name_ex(type *tp, int *bad)
123 return get_type_name(tp);
128 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
133 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
134 fprintf(F, " targetname: "); PRINT_TYPEID(T);
135 vfprintf(F, fmt, ap);
140 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
145 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
146 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
147 vfprintf(F, fmt, ap);
152 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
157 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
158 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
159 vfprintf(F, fmt, ap);
164 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
169 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
170 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
171 vfprintf(F, fmt, ap);
176 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
181 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
182 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
183 vfprintf(F, fmt, ap);
188 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
193 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
194 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
196 vfprintf(F, fmt, ap);
201 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
206 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
207 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
208 vfprintf(F, fmt, ap);
213 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
218 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
219 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
220 vfprintf(F, fmt, ap);
225 /*******************************************************************/
226 /* global and ahead declarations */
227 /*******************************************************************/
229 /* A suffix to manipulate the file name. */
230 char *dump_file_suffix = "";
232 char *dump_file_filter = "";
234 /* file to dump to */
237 static void dump_whole_node(ir_node *n, void* env);
238 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
240 /*******************************************************************/
241 /* Helper functions. */
242 /*******************************************************************/
244 /* Use private link attr to be able to call dumper anywhere without
245 destroying link fields. */
247 static pmap *irdump_link_map = NULL;
249 static void init_irdump(void) {
250 /* We need a new, empty map. */
251 if (irdump_link_map) pmap_destroy(irdump_link_map);
252 irdump_link_map = pmap_create();
256 void *ird_get_irn_link(ir_node *n) {
258 if (!irdump_link_map) return NULL;
260 if (pmap_contains(irdump_link_map, (void *)n))
261 res = pmap_get(irdump_link_map, (void *)n);
265 void ird_set_irn_link(ir_node *n, void *x) {
266 if (!irdump_link_map) init_irdump();
267 pmap_insert(irdump_link_map, (void *)n, x);
270 void *ird_get_irg_link(ir_graph *irg) {
272 if (!irdump_link_map) return NULL;
274 if (pmap_contains(irdump_link_map, (void *)irg))
275 res = pmap_get(irdump_link_map, (void *)irg);
279 void ird_set_irg_link(ir_graph *irg, void *x) {
280 if (!irdump_link_map) init_irdump();
281 pmap_insert(irdump_link_map, (void *)irg, x);
284 static void clear_link(ir_node * node, void * env) {
285 ird_set_irn_link(node, NULL);
289 static int node_floats(ir_node *n) {
290 return ((get_op_pinned(get_irn_op(n)) == floats) &&
291 (get_irg_pinned(current_ir_graph) == floats));
294 static const char *get_ent_dump_name(entity *ent) {
296 return "<NULL entity>";
297 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
298 if (ent->ld_name) return get_id_str(ent->ld_name);
299 return get_id_str(ent->name);
302 static const char *get_irg_dump_name(ir_graph *irg) {
303 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
304 entity *ent = get_irg_ent(irg);
305 return get_ent_dump_name(ent);
308 static void collect_node(ir_node * node, void *env) {
311 || get_irn_op(node) == op_Bad
312 || get_irn_op(node) == op_Unknown) {
313 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
314 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
315 ARR_APP1(ir_node *, arr, node);
316 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
318 ir_node * block = get_nodes_block(node);
319 ird_set_irn_link(node, ird_get_irn_link(block));
320 ird_set_irn_link(block, node);
324 /** Construct lists to walk ir block-wise.
326 * Collects all blocks, nodes not pinned,
327 * Bad and Unknown into a flexible array in link field of
328 * irg they belong to. Sets the irg link field to NULL in all
329 * graphs not visited.
330 * Free the list with DEL_ARR_F. */
331 static ir_node ** construct_block_lists(ir_graph *irg) {
332 int i, rem_view = interprocedural_view;
333 ir_graph *rem = current_ir_graph;
334 current_ir_graph = irg;
336 for (i = 0; i < get_irp_n_irgs(); i++)
337 ird_set_irg_link(get_irp_irg(i), NULL);
339 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
341 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
342 interprocedural_view = 0;
343 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
344 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
345 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
346 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
347 interprocedural_view = rem_view;
349 current_ir_graph = rem;
350 return ird_get_irg_link(irg);
353 /*******************************************************************/
354 /* flags to steer output */
355 /*******************************************************************/
357 /* A compiler option to turn off edge labels */
359 /* A compiler option to turn off dumping values of constant entities */
360 int const_entities = 1;
361 /* A compiler option to dump the keep alive edges */
362 int dump_keepalive = 0;
363 /* Compiler options to dump analysis information in dump_ir_graph */
364 int dump_out_edge_flag = 0;
365 int dump_dominator_information_flag = 0;
366 int dump_loop_information_flag = 0;
367 int dump_backedge_information_flag = 1;
368 int dump_const_local = 0;
369 bool opt_dump_analysed_type_info = 1;
370 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
372 char* overrule_nodecolor = NULL;
374 INLINE bool get_opt_dump_const_local(void) {
375 if (!dump_out_edge_flag && !dump_loop_information_flag)
376 return dump_const_local;
381 /* To turn off display of edge labels. Edge labels offen cause xvcg to
382 abort with a segmentation fault. */
383 void turn_off_edge_labels(void) {
387 void dump_consts_local(bool b) {
388 dump_const_local = b;
391 void turn_off_constant_entity_values(void) {
395 void dump_keepalive_edges(bool b) {
399 bool get_opt_dump_keepalive_edges(void) {
400 return dump_keepalive;
403 void dump_out_edges(void) {
404 dump_out_edge_flag = 1;
407 void dump_dominator_information(void) {
408 dump_dominator_information_flag = 1;
411 void dump_loop_information(void) {
412 dump_loop_information_flag = 1;
415 void dont_dump_loop_information(void) {
416 dump_loop_information_flag = 0;
419 void dump_backedge_information(bool b) {
420 dump_backedge_information_flag = b;
423 /* Dump the information of type field specified in ana/irtypeinfo.h.
424 * If the flag is set, the type name is output in [] in the node label,
425 * else it is output as info.
427 void dump_analysed_type_info(bool b) {
428 opt_dump_analysed_type_info = b;
431 void dump_pointer_values_to_info(bool b) {
432 opt_dump_pointer_values_to_info = b;
435 /*******************************************************************/
436 /* Routines to dump information about a single ir node. */
437 /*******************************************************************/
440 dump_node_opcode(FILE *F, ir_node *n)
444 switch(get_irn_opcode(n)) {
449 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
450 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
455 if (get_SymConst_kind(n) == linkage_ptr_info) {
456 /* don't use get_SymConst_ptr_info as it mangles the name. */
457 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
459 assert(get_kind(get_SymConst_type(n)) == k_type);
460 assert(get_type_ident(get_SymConst_type(n)));
461 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
462 if (get_SymConst_kind(n) == type_tag)
470 if (!interprocedural_view) fprintf(F, "Proj'");
471 else fprintf(F, "%s", get_irn_opname(n));
475 ir_node *cond = get_Proj_pred(n);
477 if (get_irn_opcode(cond) == iro_Cond
478 && get_Proj_proj(n) == get_Cond_defaultProj(cond)
479 && get_irn_mode(get_Cond_selector(cond)) != mode_b)
480 fprintf (F, "defProj");
482 fprintf (F, "%s", get_irn_opname(n));
486 if (interprocedural_view) {
487 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
493 fprintf (F, "%s", get_irn_opname(n));
501 dump_node_mode (ir_node *n)
505 switch (get_irn_opcode(n)) {
524 fprintf (F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
532 static int dump_node_typeinfo(ir_node *n) {
535 if (opt_dump_analysed_type_info) {
536 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
537 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
538 type *tp = get_irn_type(n);
540 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
549 dump_node_nodeattr (ir_node *n)
553 switch (get_irn_opcode(n)) {
555 if (false && interprocedural_view) {
556 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
560 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
561 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
563 fprintf (F, "%ld", get_Proj_proj(n));
567 fprintf (F, "%ld", get_Filter_proj(n));
570 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
573 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
576 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
586 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
589 fprintf(F, "color: red");
592 switch (get_irn_opcode(n)) {
599 fprintf (F, "color: blue");
602 fprintf (F, "color: lightyellow");
605 fprintf (F, "color: green");
611 fprintf (F, "color: yellow");
614 PRINT_DEFAULT_NODE_ATTR;
617 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
620 static INLINE int dump_node_info(ir_node *n)
626 fprintf (F, " info1: \"");
627 if (opt_dump_pointer_values_to_info)
628 fprintf (F, "addr: %p \n", (void *)n);
629 fprintf (F, "visited: %ld \n", get_irn_visited(n));
630 irg = get_irn_irg(n);
631 if (irg != get_const_code_irg())
632 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
634 fprintf(F, "arity: %d", get_irn_arity(n));
635 if ((get_irn_op(n) == op_Block) ||
636 (get_irn_op(n) == op_Phi) ||
637 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
638 fprintf(F, " backedges:");
640 for (i = 0; i < get_irn_arity(n); i++)
641 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
645 /* Loop node Someone else please tell me what's wrong ...
646 if (get_irn_loop(n)) {
647 ir_loop *loop = get_irn_loop(n);
649 fprintf(F, " in loop %d with depth %d\n",
650 get_loop_loop_nr(loop), get_loop_depth(loop));
655 switch (get_irn_opcode(n)) {
657 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
658 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
659 for (i = 0; i < get_method_n_params(tp); ++i)
660 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
663 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
666 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
669 entity *ent = get_Sel_entity(n);
672 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
673 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
676 fprintf(F, "<NULL entity>\n");
681 type *tp = get_Call_type(n);
682 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
683 for (i = 0; i < get_method_n_params(tp); ++i)
684 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
685 for (i = 0; i < get_method_n_ress(tp); ++i)
686 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
687 if (Call_has_callees(n)) {
688 fprintf(F, "possible callees: \n");
689 for (i = 0; i < get_Call_n_callees(n); i++) {
690 if (!get_Call_callee(n, i)) {
691 fprintf(F, " %d external method\n", i);
693 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
698 case iro_CallBegin: {
699 ir_node *call = get_CallBegin_call(n);
700 if (Call_has_callees(call)) {
701 fprintf(F, "possible callees: \n");
702 for (i = 0; i < get_Call_n_callees(call); i++) {
703 if (!get_Call_callee(call, i)) {
704 fprintf(F, " %d external method\n", i);
706 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
712 if (!interprocedural_view) {
713 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
714 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
715 for (i = 0; i < get_method_n_ress(tp); ++i)
716 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
720 type *tp = get_Const_type(n);
721 assert(tp != none_type);
722 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
726 if (interprocedural_view) {
727 fprintf(F, "intra predecessor nodes:\n");
728 for (i = 0; i < get_irn_intra_arity(n); i++) {
729 ir_node *pred = get_irn_intra_n(n, i);
730 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
733 fprintf(F, "inter predecessor nodes:\n");
734 for (i = 0; i < get_irn_inter_arity(n); i++) {
735 ir_node *pred = get_irn_inter_n(n, i);
736 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
737 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
744 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
745 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
746 if (get_irn_type(n) != none_type)
747 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
756 bool is_constlike_node(ir_node *n) {
757 ir_op *op = get_irn_op(n);
758 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
762 /* outputs the predecessors of n, that are constants, local. I.e.,
763 generates a copy of the constant predecessors for each node called with. */
764 static void dump_const_node_local(ir_node *n) {
766 if (!get_opt_dump_const_local()) return;
768 /* Use visited flag to avoid outputting nodes twice.
769 initialize it first. */
770 for (i = 0; i < get_irn_arity(n); i++) {
771 ir_node *con = get_irn_n(n, i);
772 if (is_constlike_node(con)) {
773 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
777 for (i = 0; i < get_irn_arity(n); i++) {
778 ir_node *con = get_irn_n(n, i);
779 if (is_constlike_node(con) && irn_not_visited(con)) {
782 mark_irn_visited(con);
783 /* Generate a new name for the node by appending the names of
785 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
786 fprintf(F, " label: \"");
787 bad |= dump_node_opcode(F, con);
788 bad |= dump_node_mode (con);
789 bad |= dump_node_typeinfo(con);
791 bad |= dump_node_nodeattr(con);
792 fprintf(F, " %ld", get_irn_node_nr(con));
794 bad |= dump_node_info(con);
795 dump_node_vcgattr(con, bad);
801 static void print_node_error(const char *p)
806 fprintf (F, " info2: \"%s\"", p);
809 static void dump_node(ir_node *n)
814 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
816 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
818 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
819 bad |= dump_node_opcode(F, n);
820 bad |= dump_node_mode (n);
821 bad |= dump_node_typeinfo(n);
823 bad |= dump_node_nodeattr(n);
824 fprintf(F, " %ld", get_irn_node_nr(n));
826 bad |= dump_node_info(n);
828 dump_node_vcgattr(n, bad);
830 dump_const_node_local(n);
837 /* dump the edge to the block this node belongs to */
839 dump_ir_block_edge(ir_node *n) {
840 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
841 if (is_no_Block(n)) {
842 fprintf (F, "edge: { sourcename: \"");
844 fprintf (F, "\" targetname: \"");
845 PRINT_NODEID(get_nodes_block(n));
846 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
851 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
852 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
853 fprintf (F, INTRA_DATA_EDGE_ATTR);
855 fprintf (F, INTER_DATA_EDGE_ATTR);
859 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
860 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
861 fprintf (F, INTRA_MEM_EDGE_ATTR);
863 fprintf (F, INTER_MEM_EDGE_ATTR);
867 print_edge_vcgattr(ir_node *from, int to) {
870 if (dump_backedge_information_flag && is_backedge(from, to))
871 fprintf (F, BACK_EDGE_ATTR);
873 switch (get_irn_opcode(from)) {
875 fprintf (F, CF_EDGE_ATTR);
877 case iro_Start: break;
880 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
881 fprintf (F, CF_EDGE_ATTR);
882 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
883 fprintf (F, INTER_MEM_EDGE_ATTR);
891 print_data_edge_vcgattr(F, from, to);
896 print_mem_edge_vcgattr(F, from, to);
898 print_data_edge_vcgattr(F, from, to);
902 print_data_edge_vcgattr(F, from, to);
907 print_mem_edge_vcgattr(F, from, to);
909 print_data_edge_vcgattr(F, from, to);
916 print_data_edge_vcgattr(F, from, to);
923 print_mem_edge_vcgattr(F, from, to);
925 print_data_edge_vcgattr(F, from, to);
937 print_data_edge_vcgattr(F, from, to);
940 if (get_irn_modecode(from) == irm_M)
941 fprintf (F, INTER_MEM_EDGE_ATTR);
943 print_data_edge_vcgattr(F, from, to);
950 print_mem_edge_vcgattr(F, from, to);
952 print_data_edge_vcgattr(F, from, to);
955 print_mem_edge_vcgattr(F, from, to);
957 case iro_Tuple: break;
960 switch (get_irn_modecode(from)) {
962 fprintf (F, CF_EDGE_ATTR);
965 fprintf (F, INTER_MEM_EDGE_ATTR);
968 print_data_edge_vcgattr(F, from, to);
973 case iro_Unknown: break;
975 switch (get_irn_modecode(from)) {
977 fprintf (F, INTRA_MEM_EDGE_ATTR);
980 fprintf (F, CF_EDGE_ATTR);
983 print_data_edge_vcgattr(F, from, to);
991 /* dump edges to our inputs */
993 dump_ir_data_edges(ir_node *n) {
994 int i, visited = get_irn_visited(n);
996 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
999 for (i = 0; i < get_irn_arity(n); i++) {
1000 ir_node * pred = get_irn_n(n, i);
1003 if ((interprocedural_view && get_irn_visited(pred) < visited))
1004 continue; /* pred not dumped */
1006 if (dump_backedge_information_flag && is_backedge(n, i))
1007 fprintf (F, "backedge: {sourcename: \"");
1009 fprintf (F, "edge: {sourcename: \"");
1011 fprintf (F, "\" targetname: ");
1012 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1013 PRINT_CONSTID(n, pred);
1015 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1017 fprintf (F, " label: \"%d\" ", i);
1018 print_edge_vcgattr(n, i);
1023 /** Dumps a node and its edges but not the block edge
1026 dump_node_wo_blockedge (ir_node *n, void* env) {
1028 dump_ir_data_edges(n);
1031 /** Dumps a node and its edges.
1034 dump_whole_node (ir_node *n, void* env) {
1035 dump_node_wo_blockedge(n, env);
1036 if (!node_floats(n)) dump_ir_block_edge(n);
1040 dump_const_node(ir_node *n, void *env) {
1041 if (is_Block(n)) return;
1042 dump_node_wo_blockedge(n, env);
1045 /***********************************************************************/
1046 /* the following routines dump the nodes/irgs bracketed to graphs. */
1047 /***********************************************************************/
1049 /** Dumps a constant expression as entity initializer, array bound ...
1051 static void dump_const_expression(ir_node *value) {
1052 ir_graph *rem = current_ir_graph;
1053 int rem_dump_const_local = dump_const_local;
1054 dump_const_local = 0;
1055 current_ir_graph = get_const_code_irg();
1056 irg_walk(value, dump_const_node, NULL, NULL);
1057 /* Decrease visited flag so that we walk with the same flag for the next
1058 expresssion. This guarantees that we don't dump the same node twice,
1059 as for const expressions cse is performed to save memory. */
1060 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1061 current_ir_graph = rem;
1062 dump_const_local = rem_dump_const_local;
1065 /** Dump a block as graph containing its nodes.
1067 * Expects to find nodes belonging to the block as list in its
1069 * Dumps the edges of all nodes including itself. */
1071 dump_whole_block(ir_node *block) {
1073 assert(is_Block(block));
1075 fprintf(F, "graph: { title: \"");
1076 PRINT_NODEID(block);
1077 fprintf(F, "\" label: \"");
1078 dump_node_opcode(F, block);
1079 fprintf (F, " %ld", get_irn_node_nr(block));
1081 if (get_opt_dump_abstvals())
1082 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1084 fprintf(F, "\" status:clustered color:%s \n",
1085 get_Block_matured(block) ? "yellow" : "red");
1087 /* dump the blocks edges */
1088 dump_ir_data_edges(block);
1090 /* dump the nodes that go into the block */
1091 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1093 dump_ir_data_edges(node);
1096 /* Close the vcg information for the block */
1098 dump_const_node_local(block);
1100 dump_chi_term(F, block);
1105 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1106 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1108 dump_block_graph(ir_graph *irg) {
1110 ir_graph *rem = current_ir_graph;
1111 ir_node **arr = ird_get_irg_link(irg);
1112 current_ir_graph = irg;
1114 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1115 ir_node * node = arr[i];
1116 if (is_Block(node)) {
1117 /* Dumps the block and all the nodes in the block, which are to
1118 be found in Block->link. */
1119 dump_whole_block(node);
1121 /* Nodes that are not in a Block. */
1123 dump_ir_data_edges(node);
1127 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1129 current_ir_graph = rem;
1132 /** Dumps an irg as a graph.
1133 * If interprocedural view edges can point to nodes out of this graph.
1135 static void dump_graph(ir_graph *irg) {
1137 fprintf(F, "graph: { title: \"");
1139 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1140 get_ent_dump_name(get_irg_ent(irg)));
1142 dump_block_graph (irg);
1144 /* Close the vcg information for the irg */
1145 fprintf(F, "}\n\n");
1148 /*******************************************************************/
1149 /* Basic type and entity nodes and edges. */
1150 /*******************************************************************/
1152 /* dumps the edges between nodes and their type or entity attributes. */
1153 static void dump_node2type_edges (ir_node *n, void *env)
1157 switch (get_irn_opcode(n)) {
1159 /* @@@ some consts have an entity */
1162 if ( (get_SymConst_kind(n) == type_tag)
1163 || (get_SymConst_kind(n) == size))
1165 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1169 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1172 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1175 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1178 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1181 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1189 static int print_type_info(type *tp) {
1192 if (get_type_state(tp) == layout_undefined) {
1193 fprintf(F, "state: layout_undefined\n");
1195 fprintf(F, "state: layout_fixed,\n");
1197 if (get_type_mode(tp))
1198 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1199 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1204 static void print_typespecific_info(type *tp) {
1205 switch (get_type_tpop_code(tp)) {
1208 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1215 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1216 fprintf(F, "params: %d\n", get_method_n_params(tp));
1217 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1225 case tpo_enumeration:
1239 static void print_typespecific_vcgattr(type *tp) {
1240 switch (get_type_tpop_code(tp)) {
1243 if (peculiarity_existent == get_class_peculiarity(tp))
1244 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1246 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1250 fprintf (F, " " TYPE_METH_NODE_ATTR);
1261 case tpo_enumeration:
1274 static int print_type_node(type *tp)
1278 fprintf (F, "node: {title: ");
1280 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1281 fprintf (F, " info1: \"");
1282 bad |= print_type_info(tp);
1283 print_typespecific_info(tp);
1285 print_typespecific_vcgattr(tp);
1291 #define X(a) case a: fprintf(F, #a); break
1292 void dump_entity_node(entity *ent)
1294 fprintf (F, "node: {title: \"");
1295 PRINT_ENTID(ent); fprintf(F, "\"");
1296 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1297 fprintf (F, "label: ");
1298 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1299 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1301 fprintf (F, "\nallocation: ");
1302 switch (get_entity_allocation(ent)) {
1303 X(allocation_dynamic);
1304 X(allocation_automatic);
1305 X(allocation_static);
1306 X(allocation_parameter);
1309 fprintf (F, "\nvisibility: ");
1310 switch (get_entity_visibility(ent)) {
1311 X(visibility_local);
1312 X(visibility_external_visible);
1313 X(visibility_external_allocated);
1316 fprintf (F, "\nvariability: ");
1317 switch (get_entity_variability(ent)) {
1318 X(variability_uninitialized);
1319 X(variability_initialized);
1320 X(variability_part_constant);
1321 X(variability_constant);
1324 fprintf (F, "\nvolatility: ");
1325 switch (get_entity_volatility(ent)) {
1326 X(volatility_non_volatile);
1327 X(volatility_is_volatile);
1330 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1331 fprintf(F, "\nname: %s\nld_name: %s",
1332 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1333 fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1334 if (is_method_type(get_entity_type(ent))) {
1335 if (get_entity_irg(ent)) /* can be null */
1336 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1338 { fprintf (F, "\nirg = NULL"); }
1340 fprintf(F, "\"\n}\n");
1344 static void dump_enum_item(type *tp, int pos)
1347 ident *id = get_enumeration_nameid(tp, pos);
1348 tarval *tv = get_enumeration_enum(tp, pos);
1350 tarval_snprintf(buf, sizeof(buf), tv);
1351 fprintf (F, "node: {title: \"");
1352 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1353 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1354 fprintf (F, "label: ");
1355 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1356 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1359 /* dumps a type or entity and it's edges. */
1361 dump_type_info (type_or_ent *tore, void *env) {
1362 int i = 0; /* to shutup gcc */
1364 /* dump this type or entity */
1366 switch (get_kind(tore)) {
1369 entity *ent = (entity *)tore;
1372 dump_entity_node(ent);
1374 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1375 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1376 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1377 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1378 if(is_class_type(get_entity_owner(ent))) {
1379 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1380 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1383 /* attached subgraphs */
1384 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1385 if (is_atomic_entity(ent)) {
1386 value = get_atomic_ent_value(ent);
1388 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1389 /* DDMN(value); $$$ */
1390 dump_const_expression(value);
1393 if (is_compound_entity(ent)) {
1394 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1395 value = get_compound_ent_value(ent, i);
1397 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1398 dump_const_expression(value);
1399 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1401 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1402 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1403 get_compound_ent_value_member(ent, i), i);
1412 type *tp = (type *)tore;
1413 print_type_node(tp);
1414 /* and now the edges */
1415 switch (get_type_tpop_code(tp)) {
1418 for (i=0; i < get_class_n_supertypes(tp); i++) {
1419 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1422 for (i=0; i < get_class_n_members(tp); i++) {
1423 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1428 for (i=0; i < get_struct_n_members(tp); i++) {
1429 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1434 for (i = 0; i < get_method_n_params(tp); i++)
1436 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1438 for (i = 0; i < get_method_n_ress(tp); i++)
1440 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1445 for (i = 0; i < get_union_n_members(tp); i++)
1447 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1452 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1453 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1454 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1455 ir_node *upper = get_array_upper_bound(tp, i);
1456 ir_node *lower = get_array_lower_bound(tp, i);
1457 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1458 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1459 dump_const_expression(upper);
1460 dump_const_expression(lower);
1464 case tpo_enumeration:
1466 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1467 dump_enum_item(tp, i);
1468 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1473 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1481 break; /* case k_type */
1484 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1486 } /* switch kind_or_entity */
1489 /** For dumping class hierarchies.
1490 * Dumps a class type node and a superclass edge.
1491 * If env != null dumps entities of classes and overwrites edges.
1494 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1495 int i = 0; /* to shutup gcc */
1497 /* dump this type or entity */
1498 switch (get_kind(tore)) {
1500 entity *ent = (entity *)tore;
1501 if (get_entity_owner(ent) == get_glob_type()) break;
1502 if ((env) && is_class_type(get_entity_owner(ent))) {
1504 dump_entity_node(ent);
1506 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1507 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1509 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1512 } break; /* case k_entity */
1515 type *tp = (type *)tore;
1516 if (tp == get_glob_type()) break;
1517 switch (get_type_tpop_code(tp)) {
1519 print_type_node(tp);
1520 /* and now the edges */
1521 for (i=0; i < get_class_n_supertypes(tp); i++)
1523 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1529 break; /* case k_type */
1532 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1534 } /* switch kind_or_entity */
1537 /*******************************************************************/
1538 /* dump analysis information that is expressed in graph terms. */
1539 /*******************************************************************/
1541 /* dump out edges */
1543 dump_out_edge (ir_node *n, void* env) {
1545 for (i = 0; i < get_irn_n_outs(n); i++) {
1546 assert(get_irn_out(n, i));
1547 fprintf (F, "edge: {sourcename: \"");
1549 fprintf (F, "\" targetname: \"");
1550 PRINT_NODEID(get_irn_out(n, i));
1551 fprintf (F, "\" color: red linestyle: dashed");
1557 dump_loop_label(ir_loop *loop) {
1558 fprintf (F, "loop %d, %d sons, %d nodes",
1559 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1562 static INLINE void dump_loop_info(ir_loop *loop) {
1563 fprintf (F, " info1: \"");
1564 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1565 #if DEBUG_libfirm /* GL @@@ debug analyses */
1566 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1572 dump_loop_node(ir_loop *loop) {
1573 fprintf (F, "node: {title: \"");
1575 fprintf (F, "\" label: \"");
1576 dump_loop_label(loop);
1578 dump_loop_info(loop);
1584 dump_loop_node_edge (ir_loop *loop, int i) {
1586 fprintf (F, "edge: {sourcename: \"");
1588 fprintf (F, "\" targetname: \"");
1589 PRINT_NODEID(get_loop_node(loop, i));
1590 fprintf (F, "\" color: green");
1595 dump_loop_son_edge (ir_loop *loop, int i) {
1597 fprintf (F, "edge: {sourcename: \"");
1599 fprintf (F, "\" targetname: \"");
1600 PRINT_LOOPID(get_loop_son(loop, i));
1601 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1602 get_loop_element_pos(loop, get_loop_son(loop, i)));
1606 void dump_loops (ir_loop *loop) {
1608 /* dump this loop node */
1609 dump_loop_node(loop);
1611 /* dump edges to nodes in loop -- only if it is a real loop */
1612 if (get_loop_depth(loop) != 0) {
1613 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1614 dump_loop_node_edge(loop, i);
1617 for (i = 0; i < get_loop_n_sons(loop); i++) {
1618 dump_loops(get_loop_son(loop, i));
1619 dump_loop_son_edge(loop, i);
1624 void dump_loop_nodes_into_graph(ir_graph *irg) {
1625 ir_graph *rem = current_ir_graph;
1626 current_ir_graph = irg;
1628 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1630 current_ir_graph = rem;
1634 /************************************************************************/
1635 /* open and close vcg file */
1636 /************************************************************************/
1639 dump_vcg_header(const char *name, const char *orientation) {
1648 if (!orientation) orientation = "bottom_to_top";
1652 "graph: { title: \"ir graph of %s\"\n"
1653 "display_edge_labels: %s\n"
1654 "layoutalgorithm: mindepth\n"
1655 "manhattan_edges: yes\n"
1656 "port_sharing: no\n"
1658 "classname 1: \"intrablock Data\"\n"
1659 "classname 16: \"interblock Data\"\n"
1660 "classname 2: \"Block\"\n"
1661 "classname 13: \"Control Flow\"\n"
1662 "classname 14: \"intrablock Memory\"\n"
1663 "classname 17: \"interblock Memory\"\n"
1664 "classname 15: \"Dominators\"\n"
1665 "classname 3: \"Entity type\"\n"
1666 "classname 4: \"Entity owner\"\n"
1667 "classname 5: \"Method Param\"\n"
1668 "classname 6: \"Method Res\"\n"
1669 "classname 7: \"Super\"\n"
1670 "classname 8: \"Union\"\n"
1671 "classname 9: \"Points-to\"\n"
1672 "classname 10: \"Array Element Type\"\n"
1673 "classname 11: \"Overwrites\"\n"
1674 "classname 12: \"Member\"\n"
1675 "infoname 1: \"Attribute\"\n"
1676 "infoname 2: \"Verification errors\"\n",
1677 name, label, orientation);
1679 fprintf (F, "\n"); /* a separator */
1682 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1683 const char *nm = get_irg_dump_name(irg);
1684 int len = strlen(nm), i, j;
1685 char *fname; /* filename to put the vcg information in */
1687 if (!suffix1) suffix1 = "";
1688 if (!suffix2) suffix2 = "";
1690 /** open file for vcg graph */
1691 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1693 /* strncpy (fname, nm, len); */ /* copy the filename */
1695 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1697 fname[j] = '@'; j++; fname[j] = '1'; j++;
1698 } else if (nm[i] == '@') {
1699 fname[j] = '@'; j++; fname[j] = '2'; j++;
1701 fname[j] = nm[i]; j++;
1705 strcat (fname, suffix1); /* append file suffix */
1706 strcat (fname, suffix2); /* append file suffix */
1707 strcat (fname, ".vcg"); /* append the .vcg suffix */
1708 F = fopen (fname, "w"); /* open file for writing */
1710 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1715 static void vcg_open_name (const char *name, char *suffix) {
1716 char *fname; /* filename to put the vcg information in */
1717 int i, j, len = strlen(name);
1719 if (!suffix) suffix = "";
1721 /** open file for vcg graph */
1722 fname = malloc (len * 2 + 5 + strlen(suffix));
1723 /* strcpy (fname, name);*/ /* copy the filename */
1725 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1726 if (name[i] == '/') {
1727 fname[j] = '@'; j++; fname[j] = '1'; j++;
1728 } else if (name[i] == '@') {
1729 fname[j] = '@'; j++; fname[j] = '2'; j++;
1731 fname[j] = name[i]; j++;
1735 strcat (fname, suffix);
1736 strcat (fname, ".vcg"); /* append the .vcg suffix */
1737 F = fopen (fname, "w"); /* open file for writing */
1739 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1744 static INLINE void dump_vcg_footer (void) {
1750 dump_vcg_footer(); /* print footer */
1751 fclose (F); /* close vcg file */
1754 /************************************************************************/
1755 /************************************************************************/
1756 /* Routines that dump all or parts of the firm representation to a file */
1757 /************************************************************************/
1758 /************************************************************************/
1760 /************************************************************************/
1761 /* Dump ir graphs, differnt formats and additional information. */
1762 /************************************************************************/
1764 /** Routine to dump a graph, blocks as conventional nodes.
1767 dump_ir_graph (ir_graph *irg)
1771 rem = current_ir_graph;
1773 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1775 current_ir_graph = irg;
1776 if (interprocedural_view) suffix = "-pure-ip";
1777 else suffix = "-pure";
1778 vcg_open (irg, dump_file_suffix, suffix);
1779 dump_vcg_header(get_irg_dump_name(irg), NULL);
1781 /* walk over the graph */
1782 /* dump_whole_node must be called in post visiting predecessors */
1783 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1785 /* dump the out edges in a separate walk */
1786 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1787 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1792 current_ir_graph = rem;
1797 dump_ir_block_graph (ir_graph *irg)
1802 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1804 if (interprocedural_view) suffix = "-ip";
1806 vcg_open (irg, dump_file_suffix, suffix);
1807 dump_vcg_header(get_irg_dump_name(irg), NULL);
1809 construct_block_lists(irg);
1811 for (i = 0; i < get_irp_n_irgs(); i++) {
1812 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1814 dump_graph(get_irp_irg(i));
1822 /** dumps a graph with type information
1825 dump_ir_graph_w_types (ir_graph *irg)
1827 ir_graph *rem = current_ir_graph;
1830 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1832 current_ir_graph = irg;
1834 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1835 else suffix = "-pure-wtypes";
1836 vcg_open (irg, dump_file_suffix, suffix);
1837 dump_vcg_header(get_irg_dump_name(irg), NULL);
1839 /* dump common ir graph */
1840 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1841 /* dump type info */
1842 type_walk_irg(irg, dump_type_info, NULL, NULL);
1843 inc_irg_visited(get_const_code_irg());
1844 /* dump edges from graph to type info */
1845 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1848 current_ir_graph = rem;
1852 dump_ir_block_graph_w_types (ir_graph *irg)
1856 ir_graph *rem = current_ir_graph;
1858 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1860 if (interprocedural_view) suffix = "-wtypes-ip";
1861 else suffix = "-wtypes";
1862 vcg_open (irg, dump_file_suffix, suffix);
1863 dump_vcg_header(get_irg_dump_name(irg), NULL);
1865 /* dump common blocked ir graph */
1866 construct_block_lists(irg);
1868 for (i = 0; i < get_irp_n_irgs(); i++) {
1869 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1871 dump_graph(get_irp_irg(i));
1876 /* dump type info */
1877 current_ir_graph = irg;
1878 type_walk_irg(irg, dump_type_info, NULL, NULL);
1879 inc_irg_visited(get_const_code_irg());
1881 /* dump edges from graph to type info */
1882 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1884 current_ir_graph = rem;
1888 /***********************************************************************/
1889 /* The following routines dump a control flow graph. */
1890 /***********************************************************************/
1893 dump_block_to_cfg (ir_node *block, void *env) {
1897 if (is_Block(block)) {
1898 /* This is a block. Dump a node for the block. */
1899 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1900 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1901 PRINT_NODEID(block);
1903 if (dump_dominator_information_flag)
1904 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1906 /* Dump the edges */
1907 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1908 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1909 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1910 fprintf (F, "edge: { sourcename: \"");
1911 PRINT_NODEID(block);
1912 fprintf (F, "\" targetname: \"");
1914 fprintf (F, "\"}\n");
1917 /* Dump dominator edge */
1918 if (dump_dominator_information_flag && get_Block_idom(block)) {
1919 pred = get_Block_idom(block);
1920 fprintf (F, "edge: { sourcename: \"");
1921 PRINT_NODEID(block);
1922 fprintf (F, "\" targetname: \"");
1924 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1930 dump_cfg (ir_graph *irg)
1932 ir_graph *rem = current_ir_graph;
1933 int ddif = dump_dominator_information_flag;
1934 int ipv = interprocedural_view;
1936 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1938 current_ir_graph = irg;
1940 vcg_open (irg, dump_file_suffix, "-cfg");
1941 dump_vcg_header(get_irg_dump_name(irg), NULL);
1943 if (interprocedural_view) {
1944 printf("Warning: dumping cfg not in interprocedural view!\n");
1945 interprocedural_view = 0;
1948 if (get_irg_dom_state(irg) != dom_consistent)
1949 dump_dominator_information_flag = 0;
1951 /* walk over the blocks in the graph */
1952 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1953 dump_node (get_irg_bad(irg));
1955 dump_dominator_information_flag = ddif;
1956 interprocedural_view = ipv;
1958 current_ir_graph = rem;
1963 /* Dump all irgs in interprocedural view to a single file. */
1964 void dump_all_cg_block_graph(void) {
1966 int rem_view = interprocedural_view;
1967 interprocedural_view = 1;
1969 vcg_open_name ("All_graphs", dump_file_suffix);
1970 dump_vcg_header("All_graphs", NULL);
1972 /* collect nodes in all irgs reachable in call graph*/
1973 for (i = 0; i < get_irp_n_irgs(); i++)
1974 ird_set_irg_link(get_irp_irg(i), NULL);
1976 cg_walk(clear_link, collect_node, NULL);
1978 /* dump all graphs */
1979 for (i = 0; i < get_irp_n_irgs(); i++) {
1980 current_ir_graph = get_irp_irg(i);
1981 assert(ird_get_irg_link(current_ir_graph));
1982 dump_graph(current_ir_graph);
1983 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1987 interprocedural_view = rem_view;
1990 /***********************************************************************/
1991 /* the following routines dumps type information without any ir nodes. */
1992 /***********************************************************************/
1995 dump_type_graph (ir_graph *irg)
1998 rem = current_ir_graph;
2000 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2002 current_ir_graph = irg;
2004 vcg_open (irg, dump_file_suffix, "-type");
2005 dump_vcg_header(get_irg_dump_name(irg), NULL);
2007 /* walk over the blocks in the graph */
2008 type_walk_irg(irg, dump_type_info, NULL, NULL);
2009 /* The walker for the const code can be called several times for the
2010 same (sub) experssion. So that no nodes are dumped several times
2011 we decrease the visited flag of the corresponding graph after each
2012 walk. So now increase it finally. */
2013 inc_irg_visited(get_const_code_irg());
2016 current_ir_graph = rem;
2020 dump_all_types (void)
2022 vcg_open_name ("All_types", dump_file_suffix);
2023 dump_vcg_header("All_types", NULL);
2024 type_walk(dump_type_info, NULL, NULL);
2025 inc_irg_visited(get_const_code_irg());
2030 dump_class_hierarchy (bool entities)
2032 vcg_open_name ("class_hierarchy", dump_file_suffix);
2033 dump_vcg_header("class_hierarchy", NULL);
2035 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2037 type_walk(dump_class_hierarchy_node, NULL, NULL);
2041 /***********************************************************************/
2042 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2044 /* dump_ir_block_graph */
2046 /* dump_type_graph */
2047 /* dump_ir_graph_w_types */
2048 /***********************************************************************/
2050 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2052 for (i=0; i < get_irp_n_irgs(); i++) {
2053 dmp_grph(get_irp_irg(i));
2058 /**********************************************************************************
2059 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2060 * packed together in one subgraph *
2061 **********************************************************************************/
2065 void dump_loops_standalone (ir_loop *loop) {
2066 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2068 ir_loop *son = NULL;
2070 /* Dump a new loop node. */
2071 dump_loop_node(loop);
2073 /* Dump the loop elements. */
2075 for(i = 0; i < get_loop_n_elements(loop); i++)
2077 le = get_loop_element(loop, i);
2079 if (get_kind(son) == k_ir_loop) {
2081 /* We are a loop son -> Recurse */
2083 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2084 fprintf(F, "\" }\n");
2085 fprintf (F, "edge: {sourcename: \"");
2087 fprintf (F, "\" targetname: \"");
2089 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2090 loop_node_started = 0;
2092 dump_loop_son_edge(loop, son_number++);
2093 dump_loops_standalone(son);
2096 /* We are a loop node -> Collect firm nodes */
2098 ir_node *n = le.node;
2101 if (!loop_node_started) {
2102 /* Start a new node which contains all firm nodes of the current loop */
2103 fprintf (F, "node: { title: \"");
2105 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2106 loop_node_started = 1;
2112 bad |= dump_node_opcode(F, n);
2113 bad |= dump_node_mode (n);
2114 bad |= dump_node_typeinfo(n);
2116 bad |= dump_node_nodeattr(n);
2117 fprintf (F, " %ld", get_irn_node_nr(n));
2121 if (loop_node_started) {
2122 fprintf(F, "\" }\n");
2123 fprintf (F, "edge: {sourcename: \"");
2125 fprintf (F, "\" targetname: \"");
2127 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2128 loop_node_started = 0;
2132 void dump_loop_tree(ir_graph *irg, char *suffix)
2134 ir_graph *rem = current_ir_graph;
2135 int el_rem = edge_label;
2138 /* @@@ AS: What does that do? */
2139 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2141 current_ir_graph = irg;
2143 vcg_open(irg, suffix, "-looptree");
2144 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2146 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2150 edge_label = el_rem;
2151 current_ir_graph = rem;
2155 /*******************************************************************************/
2156 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2157 /*******************************************************************************/
2159 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2160 int i, son_number = 0, node_number = 0;
2162 if (dump_loop_information_flag) dump_loop_node(loop);
2164 for (i = 0; i < get_loop_n_elements(loop); i++) {
2165 loop_element le = get_loop_element(loop, i);
2166 if (*(le.kind) == k_ir_loop) {
2167 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2169 collect_nodeloop(le.son, loopnodes);
2171 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2172 eset_insert(loopnodes, le.node);
2177 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2180 for(i = 0; i < get_loop_n_elements(loop); i++) {
2181 loop_element le = get_loop_element(loop, i);
2182 if (*(le.kind) == k_ir_loop) {
2184 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2186 if (is_Block(le.node)) start = 0; else start = -1;
2187 for (j = start; j < get_irn_arity(le.node); j++) {
2188 ir_node *pred = get_irn_n(le.node, j);
2189 if (!eset_contains(loopnodes, pred)) {
2190 eset_insert(extnodes, pred);
2191 if (!is_Block(pred)) {
2192 pred = get_nodes_block(pred);
2193 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2201 void dump_loop (ir_loop *l, char *suffix) {
2203 eset *loopnodes = eset_create();
2204 eset *extnodes = eset_create();
2207 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2208 vcg_open_name (name, suffix);
2209 dump_vcg_header(name, NULL);
2211 /* collect all nodes to dump */
2212 collect_nodeloop(l, loopnodes);
2213 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2215 /* build block lists */
2216 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2217 set_irn_link(n, NULL);
2218 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2219 set_irn_link(n, NULL);
2220 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2222 b = get_nodes_block(n);
2223 set_irn_link(n, get_irn_link(b));
2226 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2228 b = get_nodes_block(n);
2229 set_irn_link(n, get_irn_link(b));
2233 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2235 fprintf(F, "graph: { title: \"");
2237 fprintf(F, "\" label: \"");
2238 dump_node_opcode(F, b);
2239 fprintf (F, " %ld", get_irn_node_nr(b));
2240 fprintf(F, "\" status:clustered color:yellow\n");
2242 /* dump the blocks edges */
2243 dump_ir_data_edges(b);
2245 /* dump the nodes that go into the block */
2246 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2247 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2249 overrule_nodecolor = NULL;
2250 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2253 /* Close the vcg information for the block */
2255 dump_const_node_local(b);
2258 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2260 fprintf(F, "graph: { title: \"");
2262 fprintf(F, "\" label: \"");
2263 dump_node_opcode(F, b);
2264 fprintf (F, " %ld", get_irn_node_nr(b));
2265 fprintf(F, "\" status:clustered color:lightblue\n");
2267 /* dump the nodes that go into the block */
2268 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2269 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2271 overrule_nodecolor = NULL;
2272 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2275 /* Close the vcg information for the block */
2277 dump_const_node_local(b);
2281 eset_destroy(loopnodes);
2282 eset_destroy(extnodes);