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) == symconst_addr_name) {
456 /* don't use get_SymConst_ptr_info as it mangles the name. */
457 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
458 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
459 assert(get_SymConst_entity(n));
460 assert(is_entity(get_SymConst_entity(n)));
461 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
463 assert(get_kind(get_SymConst_type(n)) == k_type);
464 assert(get_type_ident(get_SymConst_type(n)));
465 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
466 if (get_SymConst_kind(n) == symconst_type_tag)
474 if (!interprocedural_view) fprintf(F, "Proj'");
475 else fprintf(F, "%s", get_irn_opname(n));
479 ir_node *cond = get_Proj_pred(n);
481 if (get_irn_opcode(cond) == iro_Cond
482 && get_Proj_proj(n) == get_Cond_defaultProj(cond)
483 && get_irn_mode(get_Cond_selector(cond)) != mode_b)
484 fprintf (F, "defProj");
486 fprintf (F, "%s", get_irn_opname(n));
490 if (interprocedural_view) {
491 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
497 fprintf (F, "%s", get_irn_opname(n));
505 dump_node_mode (ir_node *n)
509 switch (get_irn_opcode(n)) {
528 fprintf (F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
536 static int dump_node_typeinfo(ir_node *n) {
539 if (opt_dump_analysed_type_info) {
540 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
541 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
542 type *tp = get_irn_type(n);
544 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
553 dump_node_nodeattr (ir_node *n)
557 switch (get_irn_opcode(n)) {
559 if (false && interprocedural_view) {
560 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
564 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
565 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
567 fprintf (F, "%ld", get_Proj_proj(n));
571 fprintf (F, "%ld", get_Filter_proj(n));
574 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
577 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
580 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
590 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
593 fprintf(F, "color: red");
596 switch (get_irn_opcode(n)) {
603 fprintf (F, "color: blue");
606 fprintf (F, "color: lightyellow");
609 fprintf (F, "color: green");
615 fprintf (F, "color: yellow");
618 PRINT_DEFAULT_NODE_ATTR;
621 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
624 static INLINE int dump_node_info(ir_node *n)
630 fprintf (F, " info1: \"");
631 if (opt_dump_pointer_values_to_info)
632 fprintf (F, "addr: %p \n", (void *)n);
633 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
634 fprintf (F, "visited: %ld \n", get_irn_visited(n));
635 irg = get_irn_irg(n);
636 if (irg != get_const_code_irg())
637 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
639 fprintf(F, "arity: %d", get_irn_arity(n));
640 if ((get_irn_op(n) == op_Block) ||
641 (get_irn_op(n) == op_Phi) ||
642 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
643 fprintf(F, " backedges:");
645 for (i = 0; i < get_irn_arity(n); i++)
646 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
650 /* Loop node Someone else please tell me what's wrong ...
651 if (get_irn_loop(n)) {
652 ir_loop *loop = get_irn_loop(n);
654 fprintf(F, " in loop %d with depth %d\n",
655 get_loop_loop_nr(loop), get_loop_depth(loop));
660 switch (get_irn_opcode(n)) {
662 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
663 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
664 for (i = 0; i < get_method_n_params(tp); ++i)
665 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
668 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
671 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
674 entity *ent = get_Sel_entity(n);
677 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
678 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
681 fprintf(F, "<NULL entity>\n");
686 type *tp = get_Call_type(n);
687 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
688 for (i = 0; i < get_method_n_params(tp); ++i)
689 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
690 for (i = 0; i < get_method_n_ress(tp); ++i)
691 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
692 if (Call_has_callees(n)) {
693 fprintf(F, "possible callees: \n");
694 for (i = 0; i < get_Call_n_callees(n); i++) {
695 if (!get_Call_callee(n, i)) {
696 fprintf(F, " %d external method\n", i);
698 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
703 case iro_CallBegin: {
704 ir_node *call = get_CallBegin_call(n);
705 if (Call_has_callees(call)) {
706 fprintf(F, "possible callees: \n");
707 for (i = 0; i < get_Call_n_callees(call); i++) {
708 if (!get_Call_callee(call, i)) {
709 fprintf(F, " %d external method\n", i);
711 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
717 if (!interprocedural_view) {
718 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
719 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
720 for (i = 0; i < get_method_n_ress(tp); ++i)
721 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
725 type *tp = get_Const_type(n);
726 assert(tp != none_type);
727 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
731 if (interprocedural_view) {
732 fprintf(F, "intra predecessor nodes:\n");
733 for (i = 0; i < get_irn_intra_arity(n); i++) {
734 ir_node *pred = get_irn_intra_n(n, i);
735 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
738 fprintf(F, "inter predecessor nodes:\n");
739 for (i = 0; i < get_irn_inter_arity(n); i++) {
740 ir_node *pred = get_irn_inter_n(n, i);
741 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
742 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
749 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
750 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
751 if (get_irn_type(n) != none_type)
752 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
761 bool is_constlike_node(ir_node *n) {
762 ir_op *op = get_irn_op(n);
763 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
767 /* outputs the predecessors of n, that are constants, local. I.e.,
768 generates a copy of the constant predecessors for each node called with. */
769 static void dump_const_node_local(ir_node *n) {
771 if (!get_opt_dump_const_local()) return;
773 /* Use visited flag to avoid outputting nodes twice.
774 initialize it first. */
775 for (i = 0; i < get_irn_arity(n); i++) {
776 ir_node *con = get_irn_n(n, i);
777 if (is_constlike_node(con)) {
778 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
782 for (i = 0; i < get_irn_arity(n); i++) {
783 ir_node *con = get_irn_n(n, i);
784 if (is_constlike_node(con) && irn_not_visited(con)) {
787 mark_irn_visited(con);
788 /* Generate a new name for the node by appending the names of
790 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
791 fprintf(F, " label: \"");
792 bad |= dump_node_opcode(F, con);
793 bad |= dump_node_mode (con);
794 bad |= dump_node_typeinfo(con);
796 bad |= dump_node_nodeattr(con);
797 fprintf(F, " %ld", get_irn_node_nr(con));
799 bad |= dump_node_info(con);
800 dump_node_vcgattr(con, bad);
806 static void print_node_error(const char *p)
811 fprintf (F, " info2: \"%s\"", p);
814 static void dump_node(ir_node *n)
819 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
821 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
823 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
824 bad |= dump_node_opcode(F, n);
825 bad |= dump_node_mode (n);
826 bad |= dump_node_typeinfo(n);
828 bad |= dump_node_nodeattr(n);
829 fprintf(F, " %ld", get_irn_node_nr(n));
831 bad |= dump_node_info(n);
833 dump_node_vcgattr(n, bad);
835 dump_const_node_local(n);
842 /* dump the edge to the block this node belongs to */
844 dump_ir_block_edge(ir_node *n) {
845 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
846 if (is_no_Block(n)) {
847 fprintf (F, "edge: { sourcename: \"");
849 fprintf (F, "\" targetname: \"");
850 PRINT_NODEID(get_nodes_block(n));
851 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
856 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
857 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
858 fprintf (F, INTRA_DATA_EDGE_ATTR);
860 fprintf (F, INTER_DATA_EDGE_ATTR);
864 print_mem_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_MEM_EDGE_ATTR);
868 fprintf (F, INTER_MEM_EDGE_ATTR);
872 print_edge_vcgattr(ir_node *from, int to) {
875 if (dump_backedge_information_flag && is_backedge(from, to))
876 fprintf (F, BACK_EDGE_ATTR);
878 switch (get_irn_opcode(from)) {
880 fprintf (F, CF_EDGE_ATTR);
882 case iro_Start: break;
885 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
886 fprintf (F, CF_EDGE_ATTR);
887 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
888 fprintf (F, INTER_MEM_EDGE_ATTR);
896 print_data_edge_vcgattr(F, from, to);
901 print_mem_edge_vcgattr(F, from, to);
903 print_data_edge_vcgattr(F, from, to);
907 print_data_edge_vcgattr(F, from, to);
912 print_mem_edge_vcgattr(F, from, to);
914 print_data_edge_vcgattr(F, from, to);
921 print_data_edge_vcgattr(F, from, to);
928 print_mem_edge_vcgattr(F, from, to);
930 print_data_edge_vcgattr(F, from, to);
942 print_data_edge_vcgattr(F, from, to);
945 if (get_irn_modecode(from) == irm_M)
946 fprintf (F, INTER_MEM_EDGE_ATTR);
948 print_data_edge_vcgattr(F, from, to);
955 print_mem_edge_vcgattr(F, from, to);
957 print_data_edge_vcgattr(F, from, to);
960 print_mem_edge_vcgattr(F, from, to);
962 case iro_Tuple: break;
965 switch (get_irn_modecode(from)) {
967 fprintf (F, CF_EDGE_ATTR);
970 fprintf (F, INTER_MEM_EDGE_ATTR);
973 print_data_edge_vcgattr(F, from, to);
978 case iro_Unknown: break;
980 switch (get_irn_modecode(from)) {
982 fprintf (F, INTRA_MEM_EDGE_ATTR);
985 fprintf (F, CF_EDGE_ATTR);
988 print_data_edge_vcgattr(F, from, to);
996 /* dump edges to our inputs */
998 dump_ir_data_edges(ir_node *n) {
999 int i, visited = get_irn_visited(n);
1001 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1004 for (i = 0; i < get_irn_arity(n); i++) {
1005 ir_node * pred = get_irn_n(n, i);
1008 if ((interprocedural_view && get_irn_visited(pred) < visited))
1009 continue; /* pred not dumped */
1011 if (dump_backedge_information_flag && is_backedge(n, i))
1012 fprintf (F, "backedge: {sourcename: \"");
1014 fprintf (F, "edge: {sourcename: \"");
1016 fprintf (F, "\" targetname: ");
1017 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1018 PRINT_CONSTID(n, pred);
1020 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1022 fprintf (F, " label: \"%d\" ", i);
1023 print_edge_vcgattr(n, i);
1028 /** Dumps a node and its edges but not the block edge
1031 dump_node_wo_blockedge (ir_node *n, void* env) {
1033 dump_ir_data_edges(n);
1036 /** Dumps a node and its edges.
1039 dump_whole_node (ir_node *n, void* env) {
1040 dump_node_wo_blockedge(n, env);
1041 if (!node_floats(n)) dump_ir_block_edge(n);
1045 dump_const_node(ir_node *n, void *env) {
1046 if (is_Block(n)) return;
1047 dump_node_wo_blockedge(n, env);
1050 /***********************************************************************/
1051 /* the following routines dump the nodes/irgs bracketed to graphs. */
1052 /***********************************************************************/
1054 /** Dumps a constant expression as entity initializer, array bound ...
1056 static void dump_const_expression(ir_node *value) {
1057 ir_graph *rem = current_ir_graph;
1058 int rem_dump_const_local = dump_const_local;
1059 dump_const_local = 0;
1060 current_ir_graph = get_const_code_irg();
1061 irg_walk(value, dump_const_node, NULL, NULL);
1062 /* Decrease visited flag so that we walk with the same flag for the next
1063 expresssion. This guarantees that we don't dump the same node twice,
1064 as for const expressions cse is performed to save memory. */
1065 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1066 current_ir_graph = rem;
1067 dump_const_local = rem_dump_const_local;
1070 /** Dump a block as graph containing its nodes.
1072 * Expects to find nodes belonging to the block as list in its
1074 * Dumps the edges of all nodes including itself. */
1076 dump_whole_block(ir_node *block) {
1078 assert(is_Block(block));
1080 fprintf(F, "graph: { title: \"");
1081 PRINT_NODEID(block);
1082 fprintf(F, "\" label: \"");
1083 dump_node_opcode(F, block);
1084 fprintf (F, " %ld", get_irn_node_nr(block));
1086 if (get_opt_dump_abstvals())
1087 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1089 fprintf(F, "\" status:clustered color:%s \n",
1090 get_Block_matured(block) ? "yellow" : "red");
1092 /* dump the blocks edges */
1093 dump_ir_data_edges(block);
1095 /* dump the nodes that go into the block */
1096 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1098 dump_ir_data_edges(node);
1101 /* Close the vcg information for the block */
1103 dump_const_node_local(block);
1105 dump_chi_term(F, block);
1110 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1111 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1113 dump_block_graph(ir_graph *irg) {
1115 ir_graph *rem = current_ir_graph;
1116 ir_node **arr = ird_get_irg_link(irg);
1117 current_ir_graph = irg;
1119 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1120 ir_node * node = arr[i];
1121 if (is_Block(node)) {
1122 /* Dumps the block and all the nodes in the block, which are to
1123 be found in Block->link. */
1124 dump_whole_block(node);
1126 /* Nodes that are not in a Block. */
1128 dump_ir_data_edges(node);
1132 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1134 current_ir_graph = rem;
1137 /** Dumps an irg as a graph.
1138 * If interprocedural view edges can point to nodes out of this graph.
1140 static void dump_graph(ir_graph *irg) {
1142 fprintf(F, "graph: { title: \"");
1144 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1145 get_ent_dump_name(get_irg_ent(irg)));
1147 dump_block_graph (irg);
1149 /* Close the vcg information for the irg */
1150 fprintf(F, "}\n\n");
1153 /*******************************************************************/
1154 /* Basic type and entity nodes and edges. */
1155 /*******************************************************************/
1157 /* dumps the edges between nodes and their type or entity attributes. */
1158 static void dump_node2type_edges (ir_node *n, void *env)
1162 switch (get_irn_opcode(n)) {
1164 /* @@@ some consts have an entity */
1167 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1168 || (get_SymConst_kind(n) ==symconst_size))
1170 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1174 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1177 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1180 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1183 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1186 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1194 static int print_type_info(type *tp) {
1197 if (get_type_state(tp) == layout_undefined) {
1198 fprintf(F, "state: layout_undefined\n");
1200 fprintf(F, "state: layout_fixed,\n");
1202 if (get_type_mode(tp))
1203 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1204 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1209 static void print_typespecific_info(type *tp) {
1210 switch (get_type_tpop_code(tp)) {
1213 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1220 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1221 fprintf(F, "params: %d\n", get_method_n_params(tp));
1222 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1230 case tpo_enumeration:
1244 static void print_typespecific_vcgattr(type *tp) {
1245 switch (get_type_tpop_code(tp)) {
1248 if (peculiarity_existent == get_class_peculiarity(tp))
1249 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1251 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1255 fprintf (F, " " TYPE_METH_NODE_ATTR);
1266 case tpo_enumeration:
1279 static int print_type_node(type *tp)
1283 fprintf (F, "node: {title: ");
1285 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1286 fprintf (F, " info1: \"");
1287 bad |= print_type_info(tp);
1288 print_typespecific_info(tp);
1290 print_typespecific_vcgattr(tp);
1296 #define X(a) case a: fprintf(F, #a); break
1297 void dump_entity_node(entity *ent)
1299 fprintf (F, "node: {title: \"");
1300 PRINT_ENTID(ent); fprintf(F, "\"");
1301 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1302 fprintf (F, "label: ");
1303 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1304 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1306 fprintf (F, "\nallocation: ");
1307 switch (get_entity_allocation(ent)) {
1308 X(allocation_dynamic);
1309 X(allocation_automatic);
1310 X(allocation_static);
1311 X(allocation_parameter);
1314 fprintf (F, "\nvisibility: ");
1315 switch (get_entity_visibility(ent)) {
1316 X(visibility_local);
1317 X(visibility_external_visible);
1318 X(visibility_external_allocated);
1321 fprintf (F, "\nvariability: ");
1322 switch (get_entity_variability(ent)) {
1323 X(variability_uninitialized);
1324 X(variability_initialized);
1325 X(variability_part_constant);
1326 X(variability_constant);
1329 fprintf (F, "\nvolatility: ");
1330 switch (get_entity_volatility(ent)) {
1331 X(volatility_non_volatile);
1332 X(volatility_is_volatile);
1335 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1336 fprintf(F, "\nname: %s\nld_name: %s",
1337 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1338 fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1339 if (is_method_type(get_entity_type(ent))) {
1340 if (get_entity_irg(ent)) /* can be null */
1341 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1343 { fprintf (F, "\nirg = NULL"); }
1345 fprintf(F, "\"\n}\n");
1349 static void dump_enum_item(type *tp, int pos)
1352 ident *id = get_enumeration_nameid(tp, pos);
1353 tarval *tv = get_enumeration_enum(tp, pos);
1355 tarval_snprintf(buf, sizeof(buf), tv);
1356 fprintf (F, "node: {title: \"");
1357 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1358 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1359 fprintf (F, "label: ");
1360 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1361 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1364 /* dumps a type or entity and it's edges. */
1366 dump_type_info (type_or_ent *tore, void *env) {
1367 int i = 0; /* to shutup gcc */
1369 /* dump this type or entity */
1371 switch (get_kind(tore)) {
1374 entity *ent = (entity *)tore;
1377 dump_entity_node(ent);
1379 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1380 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1381 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1382 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1383 if(is_class_type(get_entity_owner(ent))) {
1384 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1385 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1388 /* attached subgraphs */
1389 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1390 if (is_atomic_entity(ent)) {
1391 value = get_atomic_ent_value(ent);
1393 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1394 /* DDMN(value); $$$ */
1395 dump_const_expression(value);
1398 if (is_compound_entity(ent)) {
1399 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1400 value = get_compound_ent_value(ent, i);
1402 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1403 dump_const_expression(value);
1404 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1406 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1407 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1408 get_compound_ent_value_member(ent, i), i);
1417 type *tp = (type *)tore;
1418 print_type_node(tp);
1419 /* and now the edges */
1420 switch (get_type_tpop_code(tp)) {
1423 for (i=0; i < get_class_n_supertypes(tp); i++) {
1424 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1427 for (i=0; i < get_class_n_members(tp); i++) {
1428 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1433 for (i=0; i < get_struct_n_members(tp); i++) {
1434 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1439 for (i = 0; i < get_method_n_params(tp); i++)
1441 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1443 for (i = 0; i < get_method_n_ress(tp); i++)
1445 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1450 for (i = 0; i < get_union_n_members(tp); i++)
1452 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1457 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1458 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1459 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1460 ir_node *upper = get_array_upper_bound(tp, i);
1461 ir_node *lower = get_array_lower_bound(tp, i);
1462 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1463 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1464 dump_const_expression(upper);
1465 dump_const_expression(lower);
1469 case tpo_enumeration:
1471 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1472 dump_enum_item(tp, i);
1473 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1478 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1486 break; /* case k_type */
1489 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1491 } /* switch kind_or_entity */
1494 /** For dumping class hierarchies.
1495 * Dumps a class type node and a superclass edge.
1496 * If env != null dumps entities of classes and overwrites edges.
1499 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1500 int i = 0; /* to shutup gcc */
1502 /* dump this type or entity */
1503 switch (get_kind(tore)) {
1505 entity *ent = (entity *)tore;
1506 if (get_entity_owner(ent) == get_glob_type()) break;
1507 if ((env) && is_class_type(get_entity_owner(ent))) {
1509 dump_entity_node(ent);
1511 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1512 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1514 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1517 } break; /* case k_entity */
1520 type *tp = (type *)tore;
1521 if (tp == get_glob_type()) break;
1522 switch (get_type_tpop_code(tp)) {
1524 print_type_node(tp);
1525 /* and now the edges */
1526 for (i=0; i < get_class_n_supertypes(tp); i++)
1528 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1534 break; /* case k_type */
1537 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1539 } /* switch kind_or_entity */
1542 /*******************************************************************/
1543 /* dump analysis information that is expressed in graph terms. */
1544 /*******************************************************************/
1546 /* dump out edges */
1548 dump_out_edge (ir_node *n, void* env) {
1550 for (i = 0; i < get_irn_n_outs(n); i++) {
1551 assert(get_irn_out(n, i));
1552 fprintf (F, "edge: {sourcename: \"");
1554 fprintf (F, "\" targetname: \"");
1555 PRINT_NODEID(get_irn_out(n, i));
1556 fprintf (F, "\" color: red linestyle: dashed");
1562 dump_loop_label(ir_loop *loop) {
1563 fprintf (F, "loop %d, %d sons, %d nodes",
1564 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1567 static INLINE void dump_loop_info(ir_loop *loop) {
1568 fprintf (F, " info1: \"");
1569 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1570 #if DEBUG_libfirm /* GL @@@ debug analyses */
1571 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1577 dump_loop_node(ir_loop *loop) {
1578 fprintf (F, "node: {title: \"");
1580 fprintf (F, "\" label: \"");
1581 dump_loop_label(loop);
1583 dump_loop_info(loop);
1589 dump_loop_node_edge (ir_loop *loop, int i) {
1591 fprintf (F, "edge: {sourcename: \"");
1593 fprintf (F, "\" targetname: \"");
1594 PRINT_NODEID(get_loop_node(loop, i));
1595 fprintf (F, "\" color: green");
1600 dump_loop_son_edge (ir_loop *loop, int i) {
1602 fprintf (F, "edge: {sourcename: \"");
1604 fprintf (F, "\" targetname: \"");
1605 PRINT_LOOPID(get_loop_son(loop, i));
1606 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1607 get_loop_element_pos(loop, get_loop_son(loop, i)));
1611 void dump_loops (ir_loop *loop) {
1613 /* dump this loop node */
1614 dump_loop_node(loop);
1616 /* dump edges to nodes in loop -- only if it is a real loop */
1617 if (get_loop_depth(loop) != 0) {
1618 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1619 dump_loop_node_edge(loop, i);
1622 for (i = 0; i < get_loop_n_sons(loop); i++) {
1623 dump_loops(get_loop_son(loop, i));
1624 dump_loop_son_edge(loop, i);
1629 void dump_loop_nodes_into_graph(ir_graph *irg) {
1630 ir_graph *rem = current_ir_graph;
1631 current_ir_graph = irg;
1633 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1635 current_ir_graph = rem;
1639 /************************************************************************/
1640 /* open and close vcg file */
1641 /************************************************************************/
1644 dump_vcg_header(const char *name, const char *orientation) {
1653 if (!orientation) orientation = "bottom_to_top";
1657 "graph: { title: \"ir graph of %s\"\n"
1658 "display_edge_labels: %s\n"
1659 "layoutalgorithm: mindepth\n"
1660 "manhattan_edges: yes\n"
1661 "port_sharing: no\n"
1663 "classname 1: \"intrablock Data\"\n"
1664 "classname 16: \"interblock Data\"\n"
1665 "classname 2: \"Block\"\n"
1666 "classname 13: \"Control Flow\"\n"
1667 "classname 14: \"intrablock Memory\"\n"
1668 "classname 17: \"interblock Memory\"\n"
1669 "classname 15: \"Dominators\"\n"
1670 "classname 3: \"Entity type\"\n"
1671 "classname 4: \"Entity owner\"\n"
1672 "classname 5: \"Method Param\"\n"
1673 "classname 6: \"Method Res\"\n"
1674 "classname 7: \"Super\"\n"
1675 "classname 8: \"Union\"\n"
1676 "classname 9: \"Points-to\"\n"
1677 "classname 10: \"Array Element Type\"\n"
1678 "classname 11: \"Overwrites\"\n"
1679 "classname 12: \"Member\"\n"
1680 "infoname 1: \"Attribute\"\n"
1681 "infoname 2: \"Verification errors\"\n",
1682 name, label, orientation);
1684 fprintf (F, "\n"); /* a separator */
1687 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1688 const char *nm = get_irg_dump_name(irg);
1689 int len = strlen(nm), i, j;
1690 char *fname; /* filename to put the vcg information in */
1692 if (!suffix1) suffix1 = "";
1693 if (!suffix2) suffix2 = "";
1695 /** open file for vcg graph */
1696 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1698 /* strncpy (fname, nm, len); */ /* copy the filename */
1700 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1702 fname[j] = '@'; j++; fname[j] = '1'; j++;
1703 } else if (nm[i] == '@') {
1704 fname[j] = '@'; j++; fname[j] = '2'; j++;
1706 fname[j] = nm[i]; j++;
1710 strcat (fname, suffix1); /* append file suffix */
1711 strcat (fname, suffix2); /* append file suffix */
1712 strcat (fname, ".vcg"); /* append the .vcg suffix */
1713 F = fopen (fname, "w"); /* open file for writing */
1715 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1720 static void vcg_open_name (const char *name, char *suffix) {
1721 char *fname; /* filename to put the vcg information in */
1722 int i, j, len = strlen(name);
1724 if (!suffix) suffix = "";
1726 /** open file for vcg graph */
1727 fname = malloc (len * 2 + 5 + strlen(suffix));
1728 /* strcpy (fname, name);*/ /* copy the filename */
1730 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1731 if (name[i] == '/') {
1732 fname[j] = '@'; j++; fname[j] = '1'; j++;
1733 } else if (name[i] == '@') {
1734 fname[j] = '@'; j++; fname[j] = '2'; j++;
1736 fname[j] = name[i]; j++;
1740 strcat (fname, suffix);
1741 strcat (fname, ".vcg"); /* append the .vcg suffix */
1742 F = fopen (fname, "w"); /* open file for writing */
1744 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1749 static INLINE void dump_vcg_footer (void) {
1755 dump_vcg_footer(); /* print footer */
1756 fclose (F); /* close vcg file */
1759 /************************************************************************/
1760 /************************************************************************/
1761 /* Routines that dump all or parts of the firm representation to a file */
1762 /************************************************************************/
1763 /************************************************************************/
1765 /************************************************************************/
1766 /* Dump ir graphs, differnt formats and additional information. */
1767 /************************************************************************/
1769 /** Routine to dump a graph, blocks as conventional nodes.
1772 dump_ir_graph (ir_graph *irg)
1776 rem = current_ir_graph;
1778 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1780 current_ir_graph = irg;
1781 if (interprocedural_view) suffix = "-pure-ip";
1782 else suffix = "-pure";
1783 vcg_open (irg, dump_file_suffix, suffix);
1784 dump_vcg_header(get_irg_dump_name(irg), NULL);
1786 /* walk over the graph */
1787 /* dump_whole_node must be called in post visiting predecessors */
1788 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1790 /* dump the out edges in a separate walk */
1791 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1792 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1797 current_ir_graph = rem;
1802 dump_ir_block_graph (ir_graph *irg)
1807 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1809 if (interprocedural_view) suffix = "-ip";
1811 vcg_open (irg, dump_file_suffix, suffix);
1812 dump_vcg_header(get_irg_dump_name(irg), NULL);
1814 construct_block_lists(irg);
1816 for (i = 0; i < get_irp_n_irgs(); i++) {
1817 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1819 dump_graph(get_irp_irg(i));
1827 /** dumps a graph with type information
1830 dump_ir_graph_w_types (ir_graph *irg)
1832 ir_graph *rem = current_ir_graph;
1835 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1837 current_ir_graph = irg;
1839 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1840 else suffix = "-pure-wtypes";
1841 vcg_open (irg, dump_file_suffix, suffix);
1842 dump_vcg_header(get_irg_dump_name(irg), NULL);
1844 /* dump common ir graph */
1845 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1846 /* dump type info */
1847 type_walk_irg(irg, dump_type_info, NULL, NULL);
1848 inc_irg_visited(get_const_code_irg());
1849 /* dump edges from graph to type info */
1850 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1853 current_ir_graph = rem;
1857 dump_ir_block_graph_w_types (ir_graph *irg)
1861 ir_graph *rem = current_ir_graph;
1863 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1865 if (interprocedural_view) suffix = "-wtypes-ip";
1866 else suffix = "-wtypes";
1867 vcg_open (irg, dump_file_suffix, suffix);
1868 dump_vcg_header(get_irg_dump_name(irg), NULL);
1870 /* dump common blocked ir graph */
1871 construct_block_lists(irg);
1873 for (i = 0; i < get_irp_n_irgs(); i++) {
1874 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1876 dump_graph(get_irp_irg(i));
1881 /* dump type info */
1882 current_ir_graph = irg;
1883 type_walk_irg(irg, dump_type_info, NULL, NULL);
1884 inc_irg_visited(get_const_code_irg());
1886 /* dump edges from graph to type info */
1887 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1889 current_ir_graph = rem;
1893 /***********************************************************************/
1894 /* The following routines dump a control flow graph. */
1895 /***********************************************************************/
1898 dump_block_to_cfg (ir_node *block, void *env) {
1902 if (is_Block(block)) {
1903 /* This is a block. Dump a node for the block. */
1904 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1905 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1906 PRINT_NODEID(block);
1908 if (dump_dominator_information_flag)
1909 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1911 /* Dump the edges */
1912 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1913 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1914 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1915 fprintf (F, "edge: { sourcename: \"");
1916 PRINT_NODEID(block);
1917 fprintf (F, "\" targetname: \"");
1919 fprintf (F, "\"}\n");
1922 /* Dump dominator edge */
1923 if (dump_dominator_information_flag && get_Block_idom(block)) {
1924 pred = get_Block_idom(block);
1925 fprintf (F, "edge: { sourcename: \"");
1926 PRINT_NODEID(block);
1927 fprintf (F, "\" targetname: \"");
1929 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1935 dump_cfg (ir_graph *irg)
1937 ir_graph *rem = current_ir_graph;
1938 int ddif = dump_dominator_information_flag;
1939 int ipv = interprocedural_view;
1941 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1943 current_ir_graph = irg;
1945 vcg_open (irg, dump_file_suffix, "-cfg");
1946 dump_vcg_header(get_irg_dump_name(irg), NULL);
1948 if (interprocedural_view) {
1949 printf("Warning: dumping cfg not in interprocedural view!\n");
1950 interprocedural_view = 0;
1953 if (get_irg_dom_state(irg) != dom_consistent)
1954 dump_dominator_information_flag = 0;
1956 /* walk over the blocks in the graph */
1957 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1958 dump_node (get_irg_bad(irg));
1960 dump_dominator_information_flag = ddif;
1961 interprocedural_view = ipv;
1963 current_ir_graph = rem;
1968 /* Dump all irgs in interprocedural view to a single file. */
1969 void dump_all_cg_block_graph(void) {
1971 int rem_view = interprocedural_view;
1972 interprocedural_view = 1;
1974 vcg_open_name ("All_graphs", dump_file_suffix);
1975 dump_vcg_header("All_graphs", NULL);
1977 /* collect nodes in all irgs reachable in call graph*/
1978 for (i = 0; i < get_irp_n_irgs(); i++)
1979 ird_set_irg_link(get_irp_irg(i), NULL);
1981 cg_walk(clear_link, collect_node, NULL);
1983 /* dump all graphs */
1984 for (i = 0; i < get_irp_n_irgs(); i++) {
1985 current_ir_graph = get_irp_irg(i);
1986 assert(ird_get_irg_link(current_ir_graph));
1987 dump_graph(current_ir_graph);
1988 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1992 interprocedural_view = rem_view;
1995 /***********************************************************************/
1996 /* the following routines dumps type information without any ir nodes. */
1997 /***********************************************************************/
2000 dump_type_graph (ir_graph *irg)
2003 rem = current_ir_graph;
2005 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2007 current_ir_graph = irg;
2009 vcg_open (irg, dump_file_suffix, "-type");
2010 dump_vcg_header(get_irg_dump_name(irg), NULL);
2012 /* walk over the blocks in the graph */
2013 type_walk_irg(irg, dump_type_info, NULL, NULL);
2014 /* The walker for the const code can be called several times for the
2015 same (sub) experssion. So that no nodes are dumped several times
2016 we decrease the visited flag of the corresponding graph after each
2017 walk. So now increase it finally. */
2018 inc_irg_visited(get_const_code_irg());
2021 current_ir_graph = rem;
2025 dump_all_types (void)
2027 vcg_open_name ("All_types", dump_file_suffix);
2028 dump_vcg_header("All_types", NULL);
2029 type_walk(dump_type_info, NULL, NULL);
2030 inc_irg_visited(get_const_code_irg());
2035 dump_class_hierarchy (bool entities)
2037 vcg_open_name ("class_hierarchy", dump_file_suffix);
2038 dump_vcg_header("class_hierarchy", NULL);
2040 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2042 type_walk(dump_class_hierarchy_node, NULL, NULL);
2046 /***********************************************************************/
2047 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2049 /* dump_ir_block_graph */
2051 /* dump_type_graph */
2052 /* dump_ir_graph_w_types */
2053 /***********************************************************************/
2055 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2057 for (i=0; i < get_irp_n_irgs(); i++) {
2058 dmp_grph(get_irp_irg(i));
2063 /**********************************************************************************
2064 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2065 * packed together in one subgraph *
2066 **********************************************************************************/
2070 void dump_loops_standalone (ir_loop *loop) {
2071 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2073 ir_loop *son = NULL;
2075 /* Dump a new loop node. */
2076 dump_loop_node(loop);
2078 /* Dump the loop elements. */
2080 for(i = 0; i < get_loop_n_elements(loop); i++)
2082 le = get_loop_element(loop, i);
2084 if (get_kind(son) == k_ir_loop) {
2086 /* We are a loop son -> Recurse */
2088 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2089 fprintf(F, "\" }\n");
2090 fprintf (F, "edge: {sourcename: \"");
2092 fprintf (F, "\" targetname: \"");
2094 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2095 loop_node_started = 0;
2097 dump_loop_son_edge(loop, son_number++);
2098 dump_loops_standalone(son);
2101 /* We are a loop node -> Collect firm nodes */
2103 ir_node *n = le.node;
2106 if (!loop_node_started) {
2107 /* Start a new node which contains all firm nodes of the current loop */
2108 fprintf (F, "node: { title: \"");
2110 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2111 loop_node_started = 1;
2117 bad |= dump_node_opcode(F, n);
2118 bad |= dump_node_mode (n);
2119 bad |= dump_node_typeinfo(n);
2121 bad |= dump_node_nodeattr(n);
2122 fprintf (F, " %ld", get_irn_node_nr(n));
2126 if (loop_node_started) {
2127 fprintf(F, "\" }\n");
2128 fprintf (F, "edge: {sourcename: \"");
2130 fprintf (F, "\" targetname: \"");
2132 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2133 loop_node_started = 0;
2137 void dump_loop_tree(ir_graph *irg, char *suffix)
2139 ir_graph *rem = current_ir_graph;
2140 int el_rem = edge_label;
2143 /* @@@ AS: What does that do? */
2144 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2146 current_ir_graph = irg;
2148 vcg_open(irg, suffix, "-looptree");
2149 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2151 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2155 edge_label = el_rem;
2156 current_ir_graph = rem;
2160 /*******************************************************************************/
2161 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2162 /*******************************************************************************/
2164 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2165 int i, son_number = 0, node_number = 0;
2167 if (dump_loop_information_flag) dump_loop_node(loop);
2169 for (i = 0; i < get_loop_n_elements(loop); i++) {
2170 loop_element le = get_loop_element(loop, i);
2171 if (*(le.kind) == k_ir_loop) {
2172 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2174 collect_nodeloop(le.son, loopnodes);
2176 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2177 eset_insert(loopnodes, le.node);
2182 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2185 for(i = 0; i < get_loop_n_elements(loop); i++) {
2186 loop_element le = get_loop_element(loop, i);
2187 if (*(le.kind) == k_ir_loop) {
2189 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2191 if (is_Block(le.node)) start = 0; else start = -1;
2192 for (j = start; j < get_irn_arity(le.node); j++) {
2193 ir_node *pred = get_irn_n(le.node, j);
2194 if (!eset_contains(loopnodes, pred)) {
2195 eset_insert(extnodes, pred);
2196 if (!is_Block(pred)) {
2197 pred = get_nodes_block(pred);
2198 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2206 void dump_loop (ir_loop *l, char *suffix) {
2208 eset *loopnodes = eset_create();
2209 eset *extnodes = eset_create();
2212 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2213 vcg_open_name (name, suffix);
2214 dump_vcg_header(name, NULL);
2216 /* collect all nodes to dump */
2217 collect_nodeloop(l, loopnodes);
2218 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2220 /* build block lists */
2221 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2222 set_irn_link(n, NULL);
2223 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2224 set_irn_link(n, NULL);
2225 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2227 b = get_nodes_block(n);
2228 set_irn_link(n, get_irn_link(b));
2231 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2233 b = get_nodes_block(n);
2234 set_irn_link(n, get_irn_link(b));
2238 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2240 fprintf(F, "graph: { title: \"");
2242 fprintf(F, "\" label: \"");
2243 dump_node_opcode(F, b);
2244 fprintf (F, " %ld", get_irn_node_nr(b));
2245 fprintf(F, "\" status:clustered color:yellow\n");
2247 /* dump the blocks edges */
2248 dump_ir_data_edges(b);
2250 /* dump the nodes that go into the block */
2251 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2252 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2254 overrule_nodecolor = NULL;
2255 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2258 /* Close the vcg information for the block */
2260 dump_const_node_local(b);
2263 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2265 fprintf(F, "graph: { title: \"");
2267 fprintf(F, "\" label: \"");
2268 dump_node_opcode(F, b);
2269 fprintf (F, " %ld", get_irn_node_nr(b));
2270 fprintf(F, "\" status:clustered color:lightblue\n");
2272 /* dump the nodes that go into the block */
2273 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2274 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2276 overrule_nodecolor = NULL;
2277 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2280 /* Close the vcg information for the block */
2282 dump_const_node_local(b);
2286 eset_destroy(loopnodes);
2287 eset_destroy(extnodes);