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.
23 #include "irgraph_t.h"
26 #include "firm_common_t.h"
34 #include "type_or_entity.h"
38 #include "callgraph.h"
48 void dump_chi_term(FILE *FL, ir_node *n);
49 void dump_state(FILE *FL, ir_node *n);
50 int get_opt_dump_abstvals(void);
51 typedef unsigned long SeqNo;
52 SeqNo get_Block_seqno(ir_node *n);
55 /* Attributes of nodes */
56 #define PRINT_DEFAULT_NODE_ATTR
57 #define DEFAULT_NODE_ATTR " "
58 #define DEFAULT_TYPE_ATTRIBUTE " "
59 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
61 /* Attributes of edges between Firm nodes */
62 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
63 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
64 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
65 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
66 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
67 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
68 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
70 #define BACK_EDGE_ATTR "linestyle:dashed "
72 /* Attributes of edges between Firm nodes and type/entity nodes */
73 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
75 /* Attributes of edges in type/entity graphs. */
76 #define TYPE_METH_NODE_ATTR "color: lightyellow"
77 #define TYPE_CLASS_NODE_ATTR "color: green"
78 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
79 #define ENTITY_NODE_ATTR "color: yellow"
80 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
81 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
82 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
83 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
84 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
85 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
86 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
87 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
88 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
89 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
90 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
91 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
92 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
93 #define ENUM_ITEM_NODE_ATTR "color: green"
94 #define CALLGRAPH_EDGE_ATTR "calls"
96 #if DEBUG_libfirm && NODEID_AS_LABEL
97 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
98 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
99 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
100 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
101 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
102 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
103 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
106 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
107 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
108 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
109 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
110 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
111 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
112 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
115 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
118 return get_mode_name(mode);
123 static const char *get_type_name_ex(type *tp, int *bad)
126 return get_type_name(tp);
131 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
136 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
137 fprintf(F, " targetname: "); PRINT_TYPEID(T);
138 vfprintf(F, fmt, ap);
143 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
148 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
149 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
150 vfprintf(F, fmt, ap);
155 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
161 fprintf(F, "backedge: { sourcename: \"");
163 fprintf(F, "edge: { sourcename: \"");
165 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
166 vfprintf(F, fmt, ap);
171 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
176 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
177 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
178 vfprintf(F, fmt, ap);
183 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
188 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
189 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
190 vfprintf(F, fmt, ap);
195 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
200 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
201 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
203 vfprintf(F, fmt, ap);
208 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
213 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
214 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
215 vfprintf(F, fmt, ap);
220 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
225 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
226 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
227 vfprintf(F, fmt, ap);
232 /*******************************************************************/
233 /* global and ahead declarations */
234 /*******************************************************************/
236 /* A suffix to manipulate the file name. */
237 char *dump_file_suffix = "";
239 char *dump_file_filter = "";
241 static void dump_whole_node(ir_node *n, void *env);
242 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
244 /*******************************************************************/
245 /* Helper functions. */
246 /*******************************************************************/
248 /* Use private link attr to be able to call dumper anywhere without
249 destroying link fields. */
251 static pmap *irdump_link_map = NULL;
253 static void init_irdump(void) {
254 /* We need a new, empty map. */
255 if (irdump_link_map) pmap_destroy(irdump_link_map);
256 irdump_link_map = pmap_create();
260 void *ird_get_irn_link(ir_node *n) {
262 if (!irdump_link_map) return NULL;
264 if (pmap_contains(irdump_link_map, (void *)n))
265 res = pmap_get(irdump_link_map, (void *)n);
269 void ird_set_irn_link(ir_node *n, void *x) {
270 if (!irdump_link_map) init_irdump();
271 pmap_insert(irdump_link_map, (void *)n, x);
274 void *ird_get_irg_link(ir_graph *irg) {
276 if (!irdump_link_map) return NULL;
278 if (pmap_contains(irdump_link_map, (void *)irg))
279 res = pmap_get(irdump_link_map, (void *)irg);
283 void ird_set_irg_link(ir_graph *irg, void *x) {
284 if (!irdump_link_map) init_irdump();
285 pmap_insert(irdump_link_map, (void *)irg, x);
288 static void clear_link(ir_node * node, void * env) {
289 ird_set_irn_link(node, NULL);
293 static int node_floats(ir_node *n) {
294 return ((get_op_pinned(get_irn_op(n)) == floats) &&
295 (get_irg_pinned(current_ir_graph) == floats));
298 static const char *get_ent_dump_name(entity *ent) {
300 return "<NULL entity>";
301 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
302 if (ent->ld_name) return get_id_str(ent->ld_name);
303 return get_id_str(ent->name);
306 static const char *get_irg_dump_name(ir_graph *irg) {
307 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
308 entity *ent = get_irg_ent(irg);
309 return get_ent_dump_name(ent);
312 static void collect_node(ir_node * node, void *env) {
315 || get_irn_op(node) == op_Bad
316 || get_irn_op(node) == op_Unknown) {
317 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
318 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
319 ARR_APP1(ir_node *, arr, node);
320 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
322 ir_node * block = get_nodes_block(node);
323 ird_set_irn_link(node, ird_get_irn_link(block));
324 ird_set_irn_link(block, node);
328 /** Construct lists to walk ir block-wise.
330 * Collects all blocks, nodes not pinned,
331 * Bad and Unknown into a flexible array in link field of
332 * irg they belong to. Sets the irg link field to NULL in all
333 * graphs not visited.
334 * Free the list with DEL_ARR_F. */
335 static ir_node ** construct_block_lists(ir_graph *irg) {
336 int i, rem_view = interprocedural_view;
337 ir_graph *rem = current_ir_graph;
338 current_ir_graph = irg;
340 for (i = 0; i < get_irp_n_irgs(); i++)
341 ird_set_irg_link(get_irp_irg(i), NULL);
343 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
345 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
346 interprocedural_view = 0;
347 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
348 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
349 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
350 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
351 interprocedural_view = rem_view;
353 current_ir_graph = rem;
354 return ird_get_irg_link(irg);
357 /*******************************************************************/
358 /* flags to steer output */
359 /*******************************************************************/
361 /* A compiler option to turn off edge labels */
363 /* A compiler option to turn off dumping values of constant entities */
364 int const_entities = 1;
365 /* A compiler option to dump the keep alive edges */
366 int dump_keepalive = 0;
367 /* Compiler options to dump analysis information in dump_ir_graph */
368 int dump_out_edge_flag = 0;
369 int dump_dominator_information_flag = 0;
370 int dump_loop_information_flag = 0;
371 int dump_backedge_information_flag = 1;
372 int dump_const_local = 0;
373 bool opt_dump_analysed_type_info = 1;
374 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
376 char* overrule_nodecolor = NULL;
378 INLINE bool get_opt_dump_const_local(void) {
379 if (!dump_out_edge_flag && !dump_loop_information_flag)
380 return dump_const_local;
385 /* To turn off display of edge labels. Edge labels offen cause xvcg to
386 abort with a segmentation fault. */
387 void turn_off_edge_labels(void) {
391 void dump_consts_local(bool b) {
392 dump_const_local = b;
395 void turn_off_constant_entity_values(void) {
399 void dump_keepalive_edges(bool b) {
403 bool get_opt_dump_keepalive_edges(void) {
404 return dump_keepalive;
407 void dump_out_edges(void) {
408 dump_out_edge_flag = 1;
411 void dump_dominator_information(void) {
412 dump_dominator_information_flag = 1;
415 void dump_loop_information(void) {
416 dump_loop_information_flag = 1;
419 void dont_dump_loop_information(void) {
420 dump_loop_information_flag = 0;
423 void dump_backedge_information(bool b) {
424 dump_backedge_information_flag = b;
427 /* Dump the information of type field specified in ana/irtypeinfo.h.
428 * If the flag is set, the type name is output in [] in the node label,
429 * else it is output as info.
431 void dump_analysed_type_info(bool b) {
432 opt_dump_analysed_type_info = b;
435 void dump_pointer_values_to_info(bool b) {
436 opt_dump_pointer_values_to_info = b;
439 /*******************************************************************/
440 /* Routines to dump information about a single ir node. */
441 /*******************************************************************/
444 dump_node_opcode(FILE *F, ir_node *n)
448 switch(get_irn_opcode(n)) {
453 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
454 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
459 if (get_SymConst_kind(n) == symconst_addr_name) {
460 /* don't use get_SymConst_ptr_info as it mangles the name. */
461 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
462 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
463 assert(get_SymConst_entity(n));
464 assert(is_entity(get_SymConst_entity(n)));
465 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
467 assert(get_kind(get_SymConst_type(n)) == k_type);
468 assert(get_type_ident(get_SymConst_type(n)));
469 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
470 if (get_SymConst_kind(n) == symconst_type_tag)
478 if (!interprocedural_view) fprintf(F, "Proj'");
479 else fprintf(F, "%s", get_irn_opname(n));
483 ir_node *pred = get_Proj_pred(n);
485 if (get_irn_opcode(pred) == iro_Cond
486 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
487 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
488 fprintf (F, "defProj");
490 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
491 * fprintf (F, "Arg");
494 fprintf (F, "%s", get_irn_opname(n));
498 if (interprocedural_view) {
499 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
505 fprintf (F, "%s", get_irn_opname(n));
513 dump_node_mode(FILE *F, ir_node *n)
517 switch (get_irn_opcode(n)) {
536 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
544 static int dump_node_typeinfo(FILE *F, ir_node *n) {
547 if (opt_dump_analysed_type_info) {
548 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
549 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
550 type *tp = get_irn_type(n);
552 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
561 dump_node_nodeattr(FILE *F, ir_node *n)
565 switch (get_irn_opcode(n)) {
567 if (false && interprocedural_view) {
568 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
572 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
573 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
575 fprintf (F, "%ld", get_Proj_proj(n));
579 fprintf (F, "%ld", get_Filter_proj(n));
582 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
585 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
588 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
598 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
601 fprintf(F, "color: red");
604 switch (get_irn_opcode(n)) {
611 fprintf (F, "color: blue");
614 fprintf (F, "color: lightyellow");
617 fprintf (F, "color: green");
623 fprintf (F, "color: yellow");
626 PRINT_DEFAULT_NODE_ATTR;
629 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
632 static INLINE int dump_node_info(FILE *F, ir_node *n)
638 fprintf (F, " info1: \"");
639 if (opt_dump_pointer_values_to_info)
640 fprintf (F, "addr: %p \n", (void *)n);
641 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
642 fprintf (F, "visited: %ld \n", get_irn_visited(n));
643 irg = get_irn_irg(n);
644 if (irg != get_const_code_irg())
645 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
647 fprintf(F, "arity: %d", get_irn_arity(n));
648 if ((get_irn_op(n) == op_Block) ||
649 (get_irn_op(n) == op_Phi) ||
650 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
651 fprintf(F, " backedges:");
653 for (i = 0; i < get_irn_arity(n); i++)
654 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
658 /* Loop node Someone else please tell me what's wrong ...
659 if (get_irn_loop(n)) {
660 ir_loop *loop = get_irn_loop(n);
662 fprintf(F, " in loop %d with depth %d\n",
663 get_loop_loop_nr(loop), get_loop_depth(loop));
668 switch (get_irn_opcode(n)) {
670 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
671 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
672 for (i = 0; i < get_method_n_params(tp); ++i)
673 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
676 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
679 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
682 entity *ent = get_Sel_entity(n);
685 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
686 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
689 fprintf(F, "<NULL entity>\n");
694 type *tp = get_Call_type(n);
695 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
696 for (i = 0; i < get_method_n_params(tp); ++i)
697 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
698 for (i = 0; i < get_method_n_ress(tp); ++i)
699 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
700 if (Call_has_callees(n)) {
701 fprintf(F, "possible callees: \n");
702 for (i = 0; i < get_Call_n_callees(n); i++) {
703 if (!get_Call_callee(n, i)) {
704 fprintf(F, " %d external method\n", i);
706 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
711 case iro_CallBegin: {
712 ir_node *call = get_CallBegin_call(n);
713 if (Call_has_callees(call)) {
714 fprintf(F, "possible callees: \n");
715 for (i = 0; i < get_Call_n_callees(call); i++) {
716 if (!get_Call_callee(call, i)) {
717 fprintf(F, " %d external method\n", i);
719 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
725 if (!interprocedural_view) {
726 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
727 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
728 for (i = 0; i < get_method_n_ress(tp); ++i)
729 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
733 type *tp = get_Const_type(n);
734 assert(tp != none_type);
735 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
739 if (interprocedural_view) {
740 fprintf(F, "intra predecessor nodes:\n");
741 for (i = 0; i < get_irn_intra_arity(n); i++) {
742 ir_node *pred = get_irn_intra_n(n, i);
743 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
746 fprintf(F, "inter predecessor nodes:\n");
747 for (i = 0; i < get_irn_inter_arity(n); i++) {
748 ir_node *pred = get_irn_inter_n(n, i);
749 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
750 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
757 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
758 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
759 if (get_irn_type(n) != none_type)
760 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
769 bool is_constlike_node(ir_node *n) {
770 ir_op *op = get_irn_op(n);
771 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
775 /* outputs the predecessors of n, that are constants, local. I.e.,
776 generates a copy of the constant predecessors for each node called with. */
777 static void dump_const_node_local(FILE *F, ir_node *n) {
779 if (!get_opt_dump_const_local()) return;
781 /* Use visited flag to avoid outputting nodes twice.
782 initialize it first. */
783 for (i = 0; i < get_irn_arity(n); i++) {
784 ir_node *con = get_irn_n(n, i);
785 if (is_constlike_node(con)) {
786 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
790 for (i = 0; i < get_irn_arity(n); i++) {
791 ir_node *con = get_irn_n(n, i);
792 if (is_constlike_node(con) && irn_not_visited(con)) {
795 mark_irn_visited(con);
796 /* Generate a new name for the node by appending the names of
798 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
799 fprintf(F, " label: \"");
800 bad |= dump_node_opcode(F, con);
801 bad |= dump_node_mode(F, con);
802 bad |= dump_node_typeinfo(F, con);
804 bad |= dump_node_nodeattr(F, con);
805 fprintf(F, " %ld", get_irn_node_nr(con));
807 bad |= dump_node_info(F, con);
808 dump_node_vcgattr(F, con, bad);
814 static void INLINE print_node_error(FILE *F, const char *p)
819 fprintf (F, " info2: \"%s\"", p);
822 static void dump_node(FILE *F, ir_node *n)
827 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
829 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
831 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
832 bad |= dump_node_opcode(F, n);
833 bad |= dump_node_mode(F, n);
834 bad |= dump_node_typeinfo(F, n);
836 bad |= dump_node_nodeattr(F, n);
837 fprintf(F, " %ld", get_irn_node_nr(n));
839 bad |= dump_node_info(F, n);
840 print_node_error(F, p);
841 dump_node_vcgattr(F, n, bad);
843 dump_const_node_local(F, n);
850 /* dump the edge to the block this node belongs to */
852 dump_ir_block_edge(FILE *F, ir_node *n) {
853 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
854 if (is_no_Block(n)) {
855 fprintf (F, "edge: { sourcename: \"");
857 fprintf (F, "\" targetname: \"");
858 PRINT_NODEID(get_nodes_block(n));
859 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
864 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
865 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
866 fprintf (F, INTRA_DATA_EDGE_ATTR);
868 fprintf (F, INTER_DATA_EDGE_ATTR);
872 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
873 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
874 fprintf (F, INTRA_MEM_EDGE_ATTR);
876 fprintf (F, INTER_MEM_EDGE_ATTR);
880 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
883 if (dump_backedge_information_flag && is_backedge(from, to))
884 fprintf (F, BACK_EDGE_ATTR);
886 switch (get_irn_opcode(from)) {
888 fprintf (F, CF_EDGE_ATTR);
890 case iro_Start: break;
893 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
894 fprintf (F, CF_EDGE_ATTR);
895 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
896 fprintf (F, INTER_MEM_EDGE_ATTR);
904 print_data_edge_vcgattr(F, from, to);
909 print_mem_edge_vcgattr(F, from, to);
911 print_data_edge_vcgattr(F, from, to);
915 print_data_edge_vcgattr(F, from, to);
920 print_mem_edge_vcgattr(F, from, to);
922 print_data_edge_vcgattr(F, from, to);
929 print_data_edge_vcgattr(F, from, to);
936 print_mem_edge_vcgattr(F, from, to);
938 print_data_edge_vcgattr(F, from, to);
950 print_data_edge_vcgattr(F, from, to);
953 if (get_irn_modecode(from) == irm_M)
954 fprintf (F, INTER_MEM_EDGE_ATTR);
956 print_data_edge_vcgattr(F, from, to);
963 print_mem_edge_vcgattr(F, from, to);
965 print_data_edge_vcgattr(F, from, to);
968 print_mem_edge_vcgattr(F, from, to);
970 case iro_Tuple: break;
973 switch (get_irn_modecode(from)) {
975 fprintf (F, CF_EDGE_ATTR);
978 fprintf (F, INTER_MEM_EDGE_ATTR);
981 print_data_edge_vcgattr(F, from, to);
986 case iro_Unknown: break;
988 switch (get_irn_modecode(from)) {
990 fprintf (F, INTRA_MEM_EDGE_ATTR);
993 fprintf (F, CF_EDGE_ATTR);
996 print_data_edge_vcgattr(F, from, to);
1004 /* dump edges to our inputs */
1006 dump_ir_data_edges(FILE *F, ir_node *n) {
1007 int i, visited = get_irn_visited(n);
1009 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1012 for (i = 0; i < get_irn_arity(n); i++) {
1013 ir_node * pred = get_irn_n(n, i);
1016 if ((interprocedural_view && get_irn_visited(pred) < visited))
1017 continue; /* pred not dumped */
1019 if (dump_backedge_information_flag && is_backedge(n, i))
1020 fprintf (F, "backedge: {sourcename: \"");
1022 fprintf (F, "edge: {sourcename: \"");
1024 fprintf (F, "\" targetname: ");
1025 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1026 PRINT_CONSTID(n, pred);
1028 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1030 fprintf (F, " label: \"%d\" ", i);
1031 print_edge_vcgattr(F, n, i);
1036 /** Dumps a node and its edges but not the block edge
1039 dump_node_wo_blockedge (ir_node *n, void *env) {
1042 dump_ir_data_edges(F, n);
1045 /** Dumps a node and its edges.
1048 dump_whole_node (ir_node *n, void *env) {
1050 dump_node_wo_blockedge(n, env);
1051 if (!node_floats(n)) dump_ir_block_edge(F, n);
1055 dump_const_node(ir_node *n, void *env) {
1056 if (is_Block(n)) return;
1057 dump_node_wo_blockedge(n, env);
1060 /***********************************************************************/
1061 /* the following routines dump the nodes/irgs bracketed to graphs. */
1062 /***********************************************************************/
1064 /** Dumps a constant expression as entity initializer, array bound ...
1066 static void dump_const_expression(FILE *F, ir_node *value) {
1067 ir_graph *rem = current_ir_graph;
1068 int rem_dump_const_local = dump_const_local;
1069 dump_const_local = 0;
1070 current_ir_graph = get_const_code_irg();
1071 irg_walk(value, dump_const_node, NULL, F);
1072 /* Decrease visited flag so that we walk with the same flag for the next
1073 expresssion. This guarantees that we don't dump the same node twice,
1074 as for const expressions cse is performed to save memory. */
1075 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1076 current_ir_graph = rem;
1077 dump_const_local = rem_dump_const_local;
1080 /** Dump a block as graph containing its nodes.
1082 * Expects to find nodes belonging to the block as list in its
1084 * Dumps the edges of all nodes including itself. */
1086 dump_whole_block(FILE *F, ir_node *block) {
1088 assert(is_Block(block));
1090 fprintf(F, "graph: { title: \"");
1091 PRINT_NODEID(block);
1092 fprintf(F, "\" label: \"");
1093 dump_node_opcode(F, block);
1094 fprintf (F, " %ld", get_irn_node_nr(block));
1096 if (get_opt_dump_abstvals())
1097 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1099 fprintf(F, "\" status:clustered color:%s \n",
1100 get_Block_matured(block) ? "yellow" : "red");
1102 /* dump the blocks edges */
1103 dump_ir_data_edges(F, block);
1105 /* dump the nodes that go into the block */
1106 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1108 dump_ir_data_edges(F, node);
1111 /* Close the vcg information for the block */
1113 dump_const_node_local(F, block);
1115 dump_chi_term(F, block);
1120 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1121 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1123 dump_block_graph(FILE *F, ir_graph *irg) {
1125 ir_graph *rem = current_ir_graph;
1126 ir_node **arr = ird_get_irg_link(irg);
1127 current_ir_graph = irg;
1129 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1130 ir_node * node = arr[i];
1131 if (is_Block(node)) {
1132 /* Dumps the block and all the nodes in the block, which are to
1133 be found in Block->link. */
1134 dump_whole_block(F, node);
1136 /* Nodes that are not in a Block. */
1138 dump_ir_data_edges(F, node);
1142 if (dump_loop_information_flag) dump_loop_nodes_into_graph(F, irg);
1144 current_ir_graph = rem;
1147 /** Dumps an irg as a graph.
1148 * If interprocedural view edges can point to nodes out of this graph.
1150 static void dump_graph(FILE *F, ir_graph *irg) {
1152 fprintf(F, "graph: { title: \"");
1154 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1155 get_ent_dump_name(get_irg_ent(irg)));
1157 dump_block_graph(F, irg);
1159 /* Close the vcg information for the irg */
1160 fprintf(F, "}\n\n");
1163 /*******************************************************************/
1164 /* Basic type and entity nodes and edges. */
1165 /*******************************************************************/
1167 /* dumps the edges between nodes and their type or entity attributes. */
1168 static void dump_node2type_edges(ir_node *n, void *env)
1173 switch (get_irn_opcode(n)) {
1175 /* @@@ some consts have an entity */
1178 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1179 || (get_SymConst_kind(n) ==symconst_size))
1181 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1185 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1188 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1191 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1194 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1197 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1205 static int print_type_info(FILE *F, type *tp) {
1208 if (get_type_state(tp) == layout_undefined) {
1209 fprintf(F, "state: layout_undefined\n");
1211 fprintf(F, "state: layout_fixed,\n");
1213 if (get_type_mode(tp))
1214 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1215 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1220 static void print_typespecific_info(FILE *F, type *tp) {
1221 switch (get_type_tpop_code(tp)) {
1224 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1231 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1232 fprintf(F, "params: %d\n", get_method_n_params(tp));
1233 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1241 case tpo_enumeration:
1255 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1256 switch (get_type_tpop_code(tp)) {
1259 if (peculiarity_existent == get_class_peculiarity(tp))
1260 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1262 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1266 fprintf (F, " " TYPE_METH_NODE_ATTR);
1277 case tpo_enumeration:
1290 static int print_type_node(FILE *F, type *tp)
1294 fprintf (F, "node: {title: ");
1296 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1297 fprintf (F, " info1: \"");
1298 bad |= print_type_info(F, tp);
1299 print_typespecific_info(F, tp);
1301 print_typespecific_vcgattr(F, tp);
1307 #define X(a) case a: fprintf(F, #a); break
1308 void dump_entity_node(FILE *F, entity *ent)
1310 fprintf (F, "node: {title: \"");
1311 PRINT_ENTID(ent); fprintf(F, "\"");
1312 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1313 fprintf (F, "label: ");
1314 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1315 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1317 fprintf (F, "\nallocation: ");
1318 switch (get_entity_allocation(ent)) {
1319 X(allocation_dynamic);
1320 X(allocation_automatic);
1321 X(allocation_static);
1322 X(allocation_parameter);
1325 fprintf (F, "\nvisibility: ");
1326 switch (get_entity_visibility(ent)) {
1327 X(visibility_local);
1328 X(visibility_external_visible);
1329 X(visibility_external_allocated);
1332 fprintf (F, "\nvariability: ");
1333 switch (get_entity_variability(ent)) {
1334 X(variability_uninitialized);
1335 X(variability_initialized);
1336 X(variability_part_constant);
1337 X(variability_constant);
1340 fprintf (F, "\nvolatility: ");
1341 switch (get_entity_volatility(ent)) {
1342 X(volatility_non_volatile);
1343 X(volatility_is_volatile);
1346 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1347 fprintf(F, "\nname: %s\nld_name: %s",
1348 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1349 fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1350 if (is_method_type(get_entity_type(ent))) {
1351 if (get_entity_irg(ent)) /* can be null */
1352 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1354 { fprintf (F, "\nirg = NULL"); }
1356 fprintf(F, "\"\n}\n");
1360 static void dump_enum_item(FILE *F, type *tp, int pos)
1363 ident *id = get_enumeration_nameid(tp, pos);
1364 tarval *tv = get_enumeration_enum(tp, pos);
1366 tarval_snprintf(buf, sizeof(buf), tv);
1367 fprintf (F, "node: {title: \"");
1368 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1369 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1370 fprintf (F, "label: ");
1371 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1372 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1375 /* dumps a type or entity and it's edges. */
1377 dump_type_info(type_or_ent *tore, void *env) {
1379 int i = 0; /* to shutup gcc */
1381 /* dump this type or entity */
1383 switch (get_kind(tore)) {
1386 entity *ent = (entity *)tore;
1389 dump_entity_node(F, ent);
1391 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1392 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1393 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1394 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1395 if(is_class_type(get_entity_owner(ent))) {
1396 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1397 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1399 /* attached subgraphs */
1400 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1401 if (is_atomic_entity(ent)) {
1402 value = get_atomic_ent_value(ent);
1404 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1405 /* DDMN(value); $$$ */
1406 dump_const_expression(F, value);
1409 if (is_compound_entity(ent)) {
1410 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1411 value = get_compound_ent_value(ent, i);
1413 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1414 dump_const_expression(F, value);
1415 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1417 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1418 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1419 get_compound_ent_value_member(ent, i), i);
1428 type *tp = (type *)tore;
1429 print_type_node(F, tp);
1430 /* and now the edges */
1431 switch (get_type_tpop_code(tp)) {
1434 for (i=0; i < get_class_n_supertypes(tp); i++)
1435 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1436 for (i=0; i < get_class_n_members(tp); i++)
1437 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1441 for (i=0; i < get_struct_n_members(tp); i++)
1442 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1446 for (i = 0; i < get_method_n_params(tp); i++)
1447 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1448 for (i = 0; i < get_method_n_ress(tp); i++)
1449 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1453 for (i = 0; i < get_union_n_members(tp); i++)
1454 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1458 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1459 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1460 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1461 ir_node *upper = get_array_upper_bound(tp, i);
1462 ir_node *lower = get_array_lower_bound(tp, i);
1463 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1464 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1465 dump_const_expression(F, upper);
1466 dump_const_expression(F, lower);
1470 case tpo_enumeration:
1472 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1473 dump_enum_item(F, tp, i);
1474 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1479 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1487 break; /* case k_type */
1490 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1492 } /* switch kind_or_entity */
1495 typedef struct _h_env {
1500 /** For dumping class hierarchies.
1501 * Dumps a class type node and a superclass edge.
1502 * If env->dump_ent dumps entities of classes and overwrites edges.
1505 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1508 int i = 0; /* to shutup gcc */
1510 /* dump this type or entity */
1511 switch (get_kind(tore)) {
1513 entity *ent = (entity *)tore;
1514 if (get_entity_owner(ent) == get_glob_type()) break;
1515 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1517 dump_entity_node(F, ent);
1519 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1520 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1521 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1523 } break; /* case k_entity */
1526 type *tp = (type *)tore;
1527 if (tp == get_glob_type()) break;
1528 switch (get_type_tpop_code(tp)) {
1530 print_type_node(F, tp);
1531 /* and now the edges */
1532 for (i=0; i < get_class_n_supertypes(tp); i++)
1534 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1540 break; /* case k_type */
1543 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1545 } /* switch kind_or_entity */
1548 /*******************************************************************/
1549 /* dump analysis information that is expressed in graph terms. */
1550 /*******************************************************************/
1552 /* dump out edges */
1554 dump_out_edge(ir_node *n, void *env) {
1557 for (i = 0; i < get_irn_n_outs(n); i++) {
1558 assert(get_irn_out(n, i));
1559 fprintf (F, "edge: {sourcename: \"");
1561 fprintf (F, "\" targetname: \"");
1562 PRINT_NODEID(get_irn_out(n, i));
1563 fprintf (F, "\" color: red linestyle: dashed");
1569 dump_loop_label(FILE *F, ir_loop *loop) {
1570 fprintf (F, "loop %d, %d sons, %d nodes",
1571 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1574 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1575 fprintf (F, " info1: \"");
1576 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1577 #if DEBUG_libfirm /* GL @@@ debug analyses */
1578 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1584 dump_loop_node(FILE *F, ir_loop *loop) {
1585 fprintf (F, "node: {title: \"");
1587 fprintf (F, "\" label: \"");
1588 dump_loop_label(F, loop);
1590 dump_loop_info(F, loop);
1596 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1598 fprintf (F, "edge: {sourcename: \"");
1600 fprintf (F, "\" targetname: \"");
1601 PRINT_NODEID(get_loop_node(loop, i));
1602 fprintf (F, "\" color: green");
1607 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1609 fprintf (F, "edge: {sourcename: \"");
1611 fprintf (F, "\" targetname: \"");
1612 PRINT_LOOPID(get_loop_son(loop, i));
1613 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1614 get_loop_element_pos(loop, get_loop_son(loop, i)));
1618 void dump_loops(FILE *F, ir_loop *loop) {
1620 /* dump this loop node */
1621 dump_loop_node(F, loop);
1623 /* dump edges to nodes in loop -- only if it is a real loop */
1624 if (get_loop_depth(loop) != 0) {
1625 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1626 dump_loop_node_edge(F, loop, i);
1629 for (i = 0; i < get_loop_n_sons(loop); i++) {
1630 dump_loops(F, get_loop_son(loop, i));
1631 dump_loop_son_edge(F, loop, i);
1636 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1637 ir_graph *rem = current_ir_graph;
1638 current_ir_graph = irg;
1640 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1642 current_ir_graph = rem;
1647 * dumps the VCG header
1650 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1659 if (!orientation) orientation = "bottom_to_top";
1663 "graph: { title: \"ir graph of %s\"\n"
1664 "display_edge_labels: %s\n"
1665 "layoutalgorithm: mindepth\n"
1666 "manhattan_edges: yes\n"
1667 "port_sharing: no\n"
1669 "classname 1: \"intrablock Data\"\n"
1670 "classname 16: \"interblock Data\"\n"
1671 "classname 2: \"Block\"\n"
1672 "classname 13: \"Control Flow\"\n"
1673 "classname 14: \"intrablock Memory\"\n"
1674 "classname 17: \"interblock Memory\"\n"
1675 "classname 15: \"Dominators\"\n"
1676 "classname 3: \"Entity type\"\n"
1677 "classname 4: \"Entity owner\"\n"
1678 "classname 5: \"Method Param\"\n"
1679 "classname 6: \"Method Res\"\n"
1680 "classname 7: \"Super\"\n"
1681 "classname 8: \"Union\"\n"
1682 "classname 9: \"Points-to\"\n"
1683 "classname 10: \"Array Element Type\"\n"
1684 "classname 11: \"Overwrites\"\n"
1685 "classname 12: \"Member\"\n"
1686 "infoname 1: \"Attribute\"\n"
1687 "infoname 2: \"Verification errors\"\n",
1688 name, label, orientation);
1690 fprintf (F, "\n"); /* a separator */
1696 * @param irg The graph to be dumped
1697 * @param suffix1 first filename suffix
1698 * @param suffix2 second filename suffix
1700 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1702 const char *nm = get_irg_dump_name(irg);
1703 int len = strlen(nm), i, j;
1704 char *fname; /* filename to put the vcg information in */
1706 if (!suffix1) suffix1 = "";
1707 if (!suffix2) suffix2 = "";
1709 /* open file for vcg graph */
1710 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1712 /* strncpy (fname, nm, len); */ /* copy the filename */
1714 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1716 fname[j] = '@'; j++; fname[j] = '1'; j++;
1717 } else if (nm[i] == '@') {
1718 fname[j] = '@'; j++; fname[j] = '2'; j++;
1720 fname[j] = nm[i]; j++;
1724 strcat (fname, suffix1); /* append file suffix */
1725 strcat (fname, suffix2); /* append file suffix */
1726 strcat (fname, ".vcg"); /* append the .vcg suffix */
1727 F = fopen (fname, "w"); /* open file for writing */
1729 panic("cannot open %s for writing (%m)", fname); /* not reached */
1739 * @param irg The graph to be dumped
1740 * @param suffix filename suffix
1742 static FILE *vcg_open_name (const char *name, const char *suffix) {
1744 char *fname; /* filename to put the vcg information in */
1745 int i, j, len = strlen(name);
1747 if (!suffix) suffix = "";
1749 /** open file for vcg graph */
1750 fname = malloc (len * 2 + 5 + strlen(suffix));
1751 /* strcpy (fname, name);*/ /* copy the filename */
1753 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1754 if (name[i] == '/') {
1755 fname[j] = '@'; j++; fname[j] = '1'; j++;
1756 } else if (name[i] == '@') {
1757 fname[j] = '@'; j++; fname[j] = '2'; j++;
1759 fname[j] = name[i]; j++;
1763 strcat (fname, suffix);
1764 strcat (fname, ".vcg"); /* append the .vcg suffix */
1765 F = fopen (fname, "w"); /* open file for writing */
1767 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1775 * Dumps the vcg file footer
1777 static INLINE void dump_vcg_footer (FILE *F) {
1782 * close the vcg file
1785 vcg_close (FILE *F) {
1786 dump_vcg_footer(F); /* print footer */
1787 fclose (F); /* close vcg file */
1790 /************************************************************************/
1791 /************************************************************************/
1792 /* Routines that dump all or parts of the firm representation to a file */
1793 /************************************************************************/
1794 /************************************************************************/
1796 /************************************************************************/
1797 /* Dump ir graphs, differnt formats and additional information. */
1798 /************************************************************************/
1800 /** Routine to dump a graph, blocks as conventional nodes.
1803 dump_ir_graph (ir_graph *irg)
1808 rem = current_ir_graph;
1810 /* if a filter is set, dump only the irg's that match the filter */
1811 if (strncmp(get_entity_name(get_irg_ent(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1814 current_ir_graph = irg;
1815 if (interprocedural_view) suffix = "-pure-ip";
1816 else suffix = "-pure";
1817 f = vcg_open(irg, dump_file_suffix, suffix);
1818 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1820 /* walk over the graph */
1821 /* dump_whole_node must be called in post visiting predecessors */
1822 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1824 /* dump the out edges in a separate walk */
1825 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1826 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1831 current_ir_graph = rem;
1836 dump_ir_block_graph (ir_graph *irg)
1842 /* if a filter is set, dump only the irg's that match the filter */
1843 if (strncmp(get_entity_name(get_irg_ent(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1846 if (interprocedural_view) suffix = "-ip";
1848 f = vcg_open(irg, dump_file_suffix, suffix);
1849 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1851 construct_block_lists(irg);
1853 for (i = 0; i < get_irp_n_irgs(); i++) {
1854 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1856 dump_graph(f, get_irp_irg(i));
1864 /** dumps a graph with type information
1867 dump_ir_graph_w_types (ir_graph *irg)
1870 ir_graph *rem = current_ir_graph;
1873 /* if a filter is set, dump only the irg's that match the filter */
1874 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1877 current_ir_graph = irg;
1879 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1880 else suffix = "-pure-wtypes";
1881 f = vcg_open(irg, dump_file_suffix, suffix);
1882 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1884 /* dump common ir graph */
1885 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1886 /* dump type info */
1887 type_walk_irg(irg, dump_type_info, NULL, f);
1888 inc_irg_visited(get_const_code_irg());
1889 /* dump edges from graph to type info */
1890 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1893 current_ir_graph = rem;
1897 dump_ir_block_graph_w_types (ir_graph *irg)
1902 ir_graph *rem = current_ir_graph;
1904 /* if a filter is set, dump only the irg's that match the filter */
1905 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1908 if (interprocedural_view) suffix = "-wtypes-ip";
1909 else suffix = "-wtypes";
1910 f = vcg_open(irg, dump_file_suffix, suffix);
1911 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1913 /* dump common blocked ir graph */
1914 construct_block_lists(irg);
1916 for (i = 0; i < get_irp_n_irgs(); i++) {
1917 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1919 dump_graph(f, get_irp_irg(i));
1924 /* dump type info */
1925 current_ir_graph = irg;
1926 type_walk_irg(irg, dump_type_info, NULL, f);
1927 inc_irg_visited(get_const_code_irg());
1929 /* dump edges from graph to type info */
1930 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1932 current_ir_graph = rem;
1936 /***********************************************************************/
1937 /* The following routines dump a control flow graph. */
1938 /***********************************************************************/
1941 dump_block_to_cfg(ir_node *block, void *env) {
1946 if (is_Block(block)) {
1947 /* This is a block. Dump a node for the block. */
1948 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1949 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1950 PRINT_NODEID(block);
1952 if (dump_dominator_information_flag)
1953 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1955 /* Dump the edges */
1956 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1957 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1958 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1959 fprintf (F, "edge: { sourcename: \"");
1960 PRINT_NODEID(block);
1961 fprintf (F, "\" targetname: \"");
1963 fprintf (F, "\"}\n");
1966 /* Dump dominator edge */
1967 if (dump_dominator_information_flag && get_Block_idom(block)) {
1968 pred = get_Block_idom(block);
1969 fprintf (F, "edge: { sourcename: \"");
1970 PRINT_NODEID(block);
1971 fprintf (F, "\" targetname: \"");
1973 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1979 dump_cfg (ir_graph *irg)
1982 ir_graph *rem = current_ir_graph;
1983 int ddif = dump_dominator_information_flag;
1984 int ipv = interprocedural_view;
1986 /* if a filter is set, dump only the irg's that match the filter */
1987 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1990 current_ir_graph = irg;
1992 f = vcg_open(irg, dump_file_suffix, "-cfg");
1993 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1995 if (interprocedural_view) {
1996 printf("Warning: dumping cfg not in interprocedural view!\n");
1997 interprocedural_view = 0;
2000 if (get_irg_dom_state(irg) != dom_consistent)
2001 dump_dominator_information_flag = 0;
2003 /* walk over the blocks in the graph */
2004 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2005 dump_node(f, get_irg_bad(irg));
2007 dump_dominator_information_flag = ddif;
2008 interprocedural_view = ipv;
2010 current_ir_graph = rem;
2015 void dump_callgraph(char *filesuffix) {
2017 int i, n_irgs = get_irp_n_irgs();
2019 F = vcg_open_name("Callgraph", filesuffix);
2020 dump_vcg_header(F, "Callgraph", NULL);
2022 for (i = 0; i < n_irgs; ++i) {
2023 ir_graph *irg = get_irp_irg(i);
2024 entity *ent = get_irg_ent(irg);
2025 int j, n_callees = get_irg_n_callees(irg);
2027 dump_entity_node(F, ent);
2028 for (j = 0; j < n_callees; ++j) {
2029 entity *c = get_irg_entity(get_irg_callee(irg, j));
2030 int be = is_irg_callee_backedge(irg, j);
2033 "label:\"recursion\" color:red" :
2035 print_ent_ent_edge(F, ent, c, be, attr);
2043 /* Dump all irgs in interprocedural view to a single file. */
2044 void dump_all_cg_block_graph(void) {
2047 int rem_view = interprocedural_view;
2048 interprocedural_view = 1;
2050 f = vcg_open_name("All_graphs", dump_file_suffix);
2051 dump_vcg_header(f, "All_graphs", NULL);
2053 /* collect nodes in all irgs reachable in call graph*/
2054 for (i = 0; i < get_irp_n_irgs(); i++)
2055 ird_set_irg_link(get_irp_irg(i), NULL);
2057 cg_walk(clear_link, collect_node, NULL);
2059 /* dump all graphs */
2060 for (i = 0; i < get_irp_n_irgs(); i++) {
2061 current_ir_graph = get_irp_irg(i);
2062 assert(ird_get_irg_link(current_ir_graph));
2063 dump_graph(f, current_ir_graph);
2064 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2068 interprocedural_view = rem_view;
2071 /***********************************************************************/
2072 /* the following routines dumps type information without any ir nodes. */
2073 /***********************************************************************/
2076 dump_type_graph (ir_graph *irg)
2080 rem = current_ir_graph;
2082 /* if a filter is set, dump only the irg's that match the filter */
2083 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2085 current_ir_graph = irg;
2087 f = vcg_open(irg, dump_file_suffix, "-type");
2088 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2090 /* walk over the blocks in the graph */
2091 type_walk_irg(irg, dump_type_info, NULL, f);
2092 /* The walker for the const code can be called several times for the
2093 same (sub) experssion. So that no nodes are dumped several times
2094 we decrease the visited flag of the corresponding graph after each
2095 walk. So now increase it finally. */
2096 inc_irg_visited(get_const_code_irg());
2099 current_ir_graph = rem;
2103 dump_all_types (void)
2105 FILE *f = vcg_open_name("All_types", dump_file_suffix);
2106 dump_vcg_header(f, "All_types", NULL);
2107 type_walk(dump_type_info, NULL, f);
2108 inc_irg_visited(get_const_code_irg());
2113 dump_class_hierarchy (bool entities)
2115 FILE *f = vcg_open_name("class_hierarchy", dump_file_suffix);
2119 dump_vcg_header(f, "class_hierarchy", NULL);
2124 type_walk(dump_class_hierarchy_node, NULL, &env);
2128 /***********************************************************************/
2129 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2131 /* dump_ir_block_graph */
2133 /* dump_type_graph */
2134 /* dump_ir_graph_w_types */
2135 /***********************************************************************/
2137 void dump_all_ir_graphs(dump_graph_func *dmp_grph) {
2139 for (i=0; i < get_irp_n_irgs(); i++) {
2140 dmp_grph(get_irp_irg(i));
2145 /**********************************************************************************
2146 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2147 * packed together in one subgraph *
2148 **********************************************************************************/
2152 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2153 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2155 ir_loop *son = NULL;
2157 /* Dump a new loop node. */
2158 dump_loop_node(F, loop);
2160 /* Dump the loop elements. */
2162 for(i = 0; i < get_loop_n_elements(loop); i++) {
2163 le = get_loop_element(loop, i);
2165 if (get_kind(son) == k_ir_loop) {
2167 /* We are a loop son -> Recurse */
2169 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2170 fprintf(F, "\" }\n");
2171 fprintf (F, "edge: {sourcename: \"");
2173 fprintf (F, "\" targetname: \"");
2175 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2176 loop_node_started = 0;
2178 dump_loop_son_edge(F, loop, son_number++);
2179 dump_loops_standalone(F, son);
2180 } else if (get_kind(son) == k_ir_node) {
2181 /* We are a loop node -> Collect firm nodes */
2183 ir_node *n = le.node;
2186 if (!loop_node_started) {
2187 /* Start a new node which contains all firm nodes of the current loop */
2188 fprintf (F, "node: { title: \"");
2190 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2191 loop_node_started = 1;
2197 bad |= dump_node_opcode(F, n);
2198 bad |= dump_node_mode(F, n);
2199 bad |= dump_node_typeinfo(F, n);
2201 bad |= dump_node_nodeattr(F, n);
2202 fprintf (F, " %ld", get_irn_node_nr(n));
2204 #if CALLGRAPH_LOOP_TREE
2206 assert(get_kind(son) == k_ir_graph);
2207 /* We are a loop node -> Collect firm graphs */
2209 ir_graph *n = (ir_graph *)le.node;
2211 if (!loop_node_started) {
2212 /* Start a new node which contains all firm nodes of the current loop */
2213 fprintf (F, "node: { title: \"");
2215 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2216 loop_node_started = 1;
2222 fprintf (F, " %s", get_irg_dump_name(n));
2227 if (loop_node_started) {
2228 fprintf(F, "\" }\n");
2229 fprintf (F, "edge: {sourcename: \"");
2231 fprintf (F, "\" targetname: \"");
2233 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2234 loop_node_started = 0;
2238 void dump_loop_tree(ir_graph *irg, char *suffix)
2241 ir_graph *rem = current_ir_graph;
2242 int el_rem = edge_label;
2245 /* if a filter is set, dump only the irg's that match the filter */
2246 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
2249 current_ir_graph = irg;
2251 f = vcg_open(irg, suffix, "-looptree");
2252 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2254 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2258 edge_label = el_rem;
2259 current_ir_graph = rem;
2262 #if CALLGRAPH_LOOP_TREE
2263 /* works, but the tree is meaningless. */
2264 void dump_callgraph_loop_tree(ir_loop *l, char *suffix) {
2265 vcg_open_name("callgraph_looptree", suffix);
2266 dump_vcg_header("callgraph_looptree", "top_to_bottom");
2267 dump_loops_standalone(l);
2273 /*******************************************************************************/
2274 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2275 /*******************************************************************************/
2277 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2278 int i, son_number = 0, node_number = 0;
2280 if (dump_loop_information_flag) dump_loop_node(F, loop);
2282 for (i = 0; i < get_loop_n_elements(loop); i++) {
2283 loop_element le = get_loop_element(loop, i);
2284 if (*(le.kind) == k_ir_loop) {
2285 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2287 collect_nodeloop(F, le.son, loopnodes);
2289 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2290 eset_insert(loopnodes, le.node);
2295 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2298 for(i = 0; i < get_loop_n_elements(loop); i++) {
2299 loop_element le = get_loop_element(loop, i);
2300 if (*(le.kind) == k_ir_loop) {
2302 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2304 if (is_Block(le.node)) start = 0; else start = -1;
2305 for (j = start; j < get_irn_arity(le.node); j++) {
2306 ir_node *pred = get_irn_n(le.node, j);
2307 if (!eset_contains(loopnodes, pred)) {
2308 eset_insert(extnodes, pred);
2309 if (!is_Block(pred)) {
2310 pred = get_nodes_block(pred);
2311 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2319 void dump_loop(ir_loop *l, char *suffix) {
2322 eset *loopnodes = eset_create();
2323 eset *extnodes = eset_create();
2326 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2327 F = vcg_open_name (name, suffix);
2328 dump_vcg_header(F, name, NULL);
2330 /* collect all nodes to dump */
2331 collect_nodeloop(F, l, loopnodes);
2332 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2334 /* build block lists */
2335 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2336 set_irn_link(n, NULL);
2337 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2338 set_irn_link(n, NULL);
2339 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2341 b = get_nodes_block(n);
2342 set_irn_link(n, get_irn_link(b));
2345 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2347 b = get_nodes_block(n);
2348 set_irn_link(n, get_irn_link(b));
2352 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2354 fprintf(F, "graph: { title: \"");
2356 fprintf(F, "\" label: \"");
2357 dump_node_opcode(F, b);
2358 fprintf (F, " %ld", get_irn_node_nr(b));
2359 fprintf(F, "\" status:clustered color:yellow\n");
2361 /* dump the blocks edges */
2362 dump_ir_data_edges(F, b);
2364 /* dump the nodes that go into the block */
2365 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2366 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2368 overrule_nodecolor = NULL;
2369 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2372 /* Close the vcg information for the block */
2374 dump_const_node_local(F, b);
2377 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2379 fprintf(F, "graph: { title: \"");
2381 fprintf(F, "\" label: \"");
2382 dump_node_opcode(F, b);
2383 fprintf (F, " %ld", get_irn_node_nr(b));
2384 fprintf(F, "\" status:clustered color:lightblue\n");
2386 /* dump the nodes that go into the block */
2387 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2388 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2390 overrule_nodecolor = NULL;
2391 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2394 /* Close the vcg information for the block */
2396 dump_const_node_local(F, b);
2400 eset_destroy(loopnodes);
2401 eset_destroy(extnodes);