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_type_name_ex(type *tp, int *bad)
115 return get_type_name(tp);
120 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
125 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
126 fprintf(F, " targetname: "); PRINT_TYPEID(T);
127 vfprintf(F, fmt, ap);
132 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
137 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
138 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
139 vfprintf(F, fmt, ap);
144 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
149 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
150 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
151 vfprintf(F, fmt, ap);
156 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
161 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
162 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
163 vfprintf(F, fmt, ap);
168 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
173 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
174 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
175 vfprintf(F, fmt, ap);
180 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
185 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
186 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
188 vfprintf(F, fmt, ap);
193 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
198 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
199 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
200 vfprintf(F, fmt, ap);
205 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
210 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
211 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
212 vfprintf(F, fmt, ap);
217 /*******************************************************************/
218 /* global and ahead declarations */
219 /*******************************************************************/
221 /* A suffix to manipulate the file name. */
222 char *dump_file_suffix = "";
224 char *dump_file_filter = "";
226 /* file to dump to */
229 static void dump_whole_node(ir_node *n, void* env);
230 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
232 /*******************************************************************/
233 /* Helper functions. */
234 /*******************************************************************/
236 /* Use private link attr to be able to call dumper anywhere without
237 destroying link fields. */
239 static pmap *irdump_link_map = NULL;
241 static void init_irdump(void) {
242 /* We need a new, empty map. */
243 if (irdump_link_map) pmap_destroy(irdump_link_map);
244 irdump_link_map = pmap_create();
248 void *ird_get_irn_link(ir_node *n) {
250 if (!irdump_link_map) return NULL;
252 if (pmap_contains(irdump_link_map, (void *)n))
253 res = pmap_get(irdump_link_map, (void *)n);
257 void ird_set_irn_link(ir_node *n, void *x) {
258 if (!irdump_link_map) init_irdump();
259 pmap_insert(irdump_link_map, (void *)n, x);
262 void *ird_get_irg_link(ir_graph *irg) {
264 if (!irdump_link_map) return NULL;
266 if (pmap_contains(irdump_link_map, (void *)irg))
267 res = pmap_get(irdump_link_map, (void *)irg);
271 void ird_set_irg_link(ir_graph *irg, void *x) {
272 if (!irdump_link_map) init_irdump();
273 pmap_insert(irdump_link_map, (void *)irg, x);
276 static void clear_link(ir_node * node, void * env) {
277 ird_set_irn_link(node, NULL);
281 static int node_floats(ir_node *n) {
282 return ((get_op_pinned(get_irn_op(n)) == floats) &&
283 (get_irg_pinned(current_ir_graph) == floats));
286 static const char *get_ent_dump_name(entity *ent) {
288 return "<NULL entity>";
289 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
290 if (ent->ld_name) return get_id_str(ent->ld_name);
291 return get_id_str(ent->name);
294 static const char *get_irg_dump_name(ir_graph *irg) {
295 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
296 entity *ent = get_irg_ent(irg);
297 return get_ent_dump_name(ent);
300 static void collect_node(ir_node * node, void *env) {
303 || get_irn_op(node) == op_Bad
304 || get_irn_op(node) == op_Unknown) {
305 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
306 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
307 ARR_APP1(ir_node *, arr, node);
308 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
310 ir_node * block = get_nodes_block(node);
311 ird_set_irn_link(node, ird_get_irn_link(block));
312 ird_set_irn_link(block, node);
316 /** Construct lists to walk ir block-wise.
318 * Collects all blocks, nodes not pinned,
319 * Bad and Unknown into a flexible array in link field of
320 * irg they belong to. Sets the irg link field to NULL in all
321 * graphs not visited.
322 * Free the list with DEL_ARR_F. */
323 static ir_node ** construct_block_lists(ir_graph *irg) {
324 int i, rem_view = interprocedural_view;
325 ir_graph *rem = current_ir_graph;
326 current_ir_graph = irg;
328 for (i = 0; i < get_irp_n_irgs(); i++)
329 ird_set_irg_link(get_irp_irg(i), NULL);
331 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
333 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
334 interprocedural_view = 0;
335 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
336 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
337 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
338 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
339 interprocedural_view = rem_view;
341 current_ir_graph = rem;
342 return ird_get_irg_link(irg);
345 /*******************************************************************/
346 /* flags to steer output */
347 /*******************************************************************/
349 /* A compiler option to turn off edge labels */
351 /* A compiler option to turn off dumping values of constant entities */
352 int const_entities = 1;
353 /* A compiler option to dump the keep alive edges */
354 int dump_keepalive = 0;
355 /* Compiler options to dump analysis information in dump_ir_graph */
356 int dump_out_edge_flag = 0;
357 int dump_dominator_information_flag = 0;
358 int dump_loop_information_flag = 0;
359 int dump_backedge_information_flag = 1;
360 int dump_const_local = 0;
361 bool opt_dump_analysed_type_info = 1;
362 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
364 char* overrule_nodecolor = NULL;
366 INLINE bool get_opt_dump_const_local(void) {
367 if (!dump_out_edge_flag && !dump_loop_information_flag)
368 return dump_const_local;
373 /* To turn off display of edge labels. Edge labels offen cause xvcg to
374 abort with a segmentation fault. */
375 void turn_off_edge_labels(void) {
379 void dump_consts_local(bool b) {
380 dump_const_local = b;
383 void turn_off_constant_entity_values(void) {
387 void dump_keepalive_edges(bool b) {
391 bool get_opt_dump_keepalive_edges(void) {
392 return dump_keepalive;
395 void dump_out_edges(void) {
396 dump_out_edge_flag = 1;
399 void dump_dominator_information(void) {
400 dump_dominator_information_flag = 1;
403 void dump_loop_information(void) {
404 dump_loop_information_flag = 1;
407 void dont_dump_loop_information(void) {
408 dump_loop_information_flag = 0;
411 void dump_backedge_information(bool b) {
412 dump_backedge_information_flag = b;
415 /* Dump the information of type field specified in ana/irtypeinfo.h.
416 * If the flag is set, the type name is output in [] in the node label,
417 * else it is output as info.
419 void dump_analysed_type_info(bool b) {
420 opt_dump_analysed_type_info = b;
423 void dump_pointer_values_to_info(bool b) {
424 opt_dump_pointer_values_to_info = b;
427 /*******************************************************************/
428 /* Routines to dump information about a single ir node. */
429 /*******************************************************************/
432 dump_node_opcode(FILE *F, ir_node *n)
436 switch(get_irn_opcode(n)) {
441 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
442 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
447 if (get_SymConst_kind(n) == linkage_ptr_info) {
448 /* don't use get_SymConst_ptr_info as it mangles the name. */
449 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
451 assert(get_kind(get_SymConst_type(n)) == k_type);
452 assert(get_type_ident(get_SymConst_type(n)));
453 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
454 if (get_SymConst_kind(n) == type_tag)
462 if (!interprocedural_view) fprintf(F, "Proj'");
463 else fprintf(F, "%s", get_irn_opname(n));
467 if (interprocedural_view) {
468 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
474 fprintf (F, "%s", get_irn_opname(n));
482 dump_node_mode (ir_node *n)
484 switch (get_irn_opcode(n)) {
503 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
510 static int dump_node_typeinfo(ir_node *n) {
513 if (opt_dump_analysed_type_info) {
514 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
515 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
516 type *tp = get_irn_type(n);
518 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
527 dump_node_nodeattr (ir_node *n)
531 switch (get_irn_opcode(n)) {
533 if (false && interprocedural_view) {
534 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
538 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
539 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
541 fprintf (F, "%ld", get_Proj_proj(n));
545 fprintf (F, "%ld", get_Filter_proj(n));
548 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
551 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
554 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
564 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
567 fprintf(F, "color: red");
570 switch (get_irn_opcode(n)) {
577 fprintf (F, "color: blue");
580 fprintf (F, "color: lightyellow");
583 fprintf (F, "color: green");
589 fprintf (F, "color: yellow");
592 PRINT_DEFAULT_NODE_ATTR;
595 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
598 static INLINE int dump_node_info(ir_node *n)
604 fprintf (F, " info1: \"");
605 if (opt_dump_pointer_values_to_info)
606 fprintf (F, "addr: %p \n", (void *)n);
607 fprintf (F, "visited: %ld \n", get_irn_visited(n));
608 irg = get_irn_irg(n);
609 if (irg != get_const_code_irg())
610 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
612 fprintf(F, "arity: %d", get_irn_arity(n));
613 if ((get_irn_op(n) == op_Block) ||
614 (get_irn_op(n) == op_Phi) ||
615 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
616 fprintf(F, " backedges:");
618 for (i = 0; i < get_irn_arity(n); i++)
619 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
623 /* Loop node Someone else please tell me what's wrong ...
624 if (get_irn_loop(n)) {
625 ir_loop *loop = get_irn_loop(n);
627 fprintf(F, " in loop %d with depth %d\n",
628 get_loop_loop_nr(loop), get_loop_depth(loop));
633 switch (get_irn_opcode(n)) {
635 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
636 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
637 for (i = 0; i < get_method_n_params(tp); ++i)
638 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
641 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
644 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
647 entity *ent = get_Sel_entity(n);
650 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
651 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
654 fprintf(F, "<NULL entity>\n");
659 type *tp = get_Call_type(n);
660 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
661 for (i = 0; i < get_method_n_params(tp); ++i)
662 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
663 for (i = 0; i < get_method_n_ress(tp); ++i)
664 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
665 if (Call_has_callees(n)) {
666 fprintf(F, "possible callees: \n");
667 for (i = 0; i < get_Call_n_callees(n); i++) {
668 if (!get_Call_callee(n, i)) {
669 fprintf(F, " %d external method\n", i);
671 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
676 case iro_CallBegin: {
677 ir_node *call = get_CallBegin_call(n);
678 if (Call_has_callees(call)) {
679 fprintf(F, "possible callees: \n");
680 for (i = 0; i < get_Call_n_callees(call); i++) {
681 if (!get_Call_callee(call, i)) {
682 fprintf(F, " %d external method\n", i);
684 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
690 if (!interprocedural_view) {
691 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
692 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
693 for (i = 0; i < get_method_n_ress(tp); ++i)
694 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
698 type *tp = get_Const_type(n);
699 assert(tp != none_type);
700 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
704 if (interprocedural_view) {
705 fprintf(F, "intra predecessor nodes:\n");
706 for (i = 0; i < get_irn_intra_arity(n); i++) {
707 ir_node *pred = get_irn_intra_n(n, i);
708 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
711 fprintf(F, "inter predecessor nodes:\n");
712 for (i = 0; i < get_irn_inter_arity(n); i++) {
713 ir_node *pred = get_irn_inter_n(n, i);
714 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
715 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
722 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
723 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
724 if (get_irn_type(n) != none_type)
725 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
734 bool is_constlike_node(ir_node *n) {
735 ir_op *op = get_irn_op(n);
736 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
740 /* outputs the predecessors of n, that are constants, local. I.e.,
741 generates a copy of the constant predecessors for each node called with. */
742 static void dump_const_node_local(ir_node *n) {
744 if (!get_opt_dump_const_local()) return;
746 /* Use visited flag to avoid outputting nodes twice.
747 initialize it first. */
748 for (i = 0; i < get_irn_arity(n); i++) {
749 ir_node *con = get_irn_n(n, i);
750 if (is_constlike_node(con)) {
751 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
755 for (i = 0; i < get_irn_arity(n); i++) {
756 ir_node *con = get_irn_n(n, i);
757 if (is_constlike_node(con) && irn_not_visited(con)) {
760 mark_irn_visited(con);
761 /* Generate a new name for the node by appending the names of
763 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
764 fprintf(F, " label: \"");
765 bad |= dump_node_opcode(F, con);
766 dump_node_mode (con);
767 bad |= dump_node_typeinfo(con);
769 bad |= dump_node_nodeattr(con);
770 fprintf(F, " %ld", get_irn_node_nr(con));
772 bad |= dump_node_info(con);
773 dump_node_vcgattr(con, bad);
779 static void print_node_error(const char *p)
784 fprintf (F, " info2: \"%s\"", p);
787 static void dump_node(ir_node *n)
792 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
794 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
796 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
797 bad |= dump_node_opcode(F, n);
799 bad |= dump_node_typeinfo(n);
801 bad |= dump_node_nodeattr(n);
802 fprintf(F, " %ld", get_irn_node_nr(n));
804 bad |= dump_node_info(n);
806 dump_node_vcgattr(n, bad);
808 dump_const_node_local(n);
815 /* dump the edge to the block this node belongs to */
817 dump_ir_block_edge(ir_node *n) {
818 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
819 if (is_no_Block(n)) {
820 fprintf (F, "edge: { sourcename: \"");
822 fprintf (F, "\" targetname: \"");
823 PRINT_NODEID(get_nodes_block(n));
824 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
829 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
830 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
831 fprintf (F, INTRA_DATA_EDGE_ATTR);
833 fprintf (F, INTER_DATA_EDGE_ATTR);
837 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
838 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
839 fprintf (F, INTRA_MEM_EDGE_ATTR);
841 fprintf (F, INTER_MEM_EDGE_ATTR);
845 print_edge_vcgattr(ir_node *from, int to) {
848 if (dump_backedge_information_flag && is_backedge(from, to))
849 fprintf (F, BACK_EDGE_ATTR);
851 switch (get_irn_opcode(from)) {
853 fprintf (F, CF_EDGE_ATTR);
855 case iro_Start: break;
858 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
859 fprintf (F, CF_EDGE_ATTR);
860 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
861 fprintf (F, INTER_MEM_EDGE_ATTR);
869 print_data_edge_vcgattr(F, from, to);
874 print_mem_edge_vcgattr(F, from, to);
876 print_data_edge_vcgattr(F, from, to);
880 print_data_edge_vcgattr(F, from, to);
885 print_mem_edge_vcgattr(F, from, to);
887 print_data_edge_vcgattr(F, from, to);
894 print_data_edge_vcgattr(F, from, to);
901 print_mem_edge_vcgattr(F, from, to);
903 print_data_edge_vcgattr(F, from, to);
915 print_data_edge_vcgattr(F, from, to);
918 if (get_irn_modecode(from) == irm_M)
919 fprintf (F, INTER_MEM_EDGE_ATTR);
921 print_data_edge_vcgattr(F, from, to);
928 print_mem_edge_vcgattr(F, from, to);
930 print_data_edge_vcgattr(F, from, to);
933 print_mem_edge_vcgattr(F, from, to);
935 case iro_Tuple: break;
938 switch (get_irn_modecode(from)) {
940 fprintf (F, CF_EDGE_ATTR);
943 fprintf (F, INTER_MEM_EDGE_ATTR);
946 print_data_edge_vcgattr(F, from, to);
951 case iro_Unknown: break;
958 /* dump edges to our inputs */
960 dump_ir_data_edges(ir_node *n) {
961 int i, visited = get_irn_visited(n);
963 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
966 for (i = 0; i < get_irn_arity(n); i++) {
967 ir_node * pred = get_irn_n(n, i);
970 if ((interprocedural_view && get_irn_visited(pred) < visited))
971 continue; /* pred not dumped */
973 if (dump_backedge_information_flag && is_backedge(n, i))
974 fprintf (F, "backedge: {sourcename: \"");
976 fprintf (F, "edge: {sourcename: \"");
978 fprintf (F, "\" targetname: ");
979 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
980 PRINT_CONSTID(n, pred);
982 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
984 fprintf (F, " label: \"%d\" ", i);
985 print_edge_vcgattr(n, i);
990 /** Dumps a node and its edges but not the block edge
993 dump_node_wo_blockedge (ir_node *n, void* env) {
995 dump_ir_data_edges(n);
998 /** Dumps a node and its edges.
1001 dump_whole_node (ir_node *n, void* env) {
1002 dump_node_wo_blockedge(n, env);
1003 if (!node_floats(n)) dump_ir_block_edge(n);
1007 dump_const_node(ir_node *n, void *env) {
1008 if (is_Block(n)) return;
1009 dump_node_wo_blockedge(n, env);
1012 /***********************************************************************/
1013 /* the following routines dump the nodes/irgs bracketed to graphs. */
1014 /***********************************************************************/
1016 /** Dumps a constant expression as entity initializer, array bound ...
1018 static void dump_const_expression(ir_node *value) {
1019 ir_graph *rem = current_ir_graph;
1020 int rem_dump_const_local = dump_const_local;
1021 dump_const_local = 0;
1022 current_ir_graph = get_const_code_irg();
1023 irg_walk(value, dump_const_node, NULL, NULL);
1024 /* Decrease visited flag so that we walk with the same flag for the next
1025 expresssion. This guarantees that we don't dump the same node twice,
1026 as for const expressions cse is performed to save memory. */
1027 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1028 current_ir_graph = rem;
1029 dump_const_local = rem_dump_const_local;
1032 /** Dump a block as graph containing its nodes.
1034 * Expects to find nodes belonging to the block as list in its
1036 * Dumps the edges of all nodes including itself. */
1038 dump_whole_block(ir_node *block) {
1040 assert(is_Block(block));
1042 fprintf(F, "graph: { title: \"");
1043 PRINT_NODEID(block);
1044 fprintf(F, "\" label: \"");
1045 dump_node_opcode(F, block);
1046 fprintf (F, " %ld", get_irn_node_nr(block));
1048 if (get_opt_dump_abstvals())
1049 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1051 fprintf(F, "\" status:clustered color:%s \n",
1052 get_Block_matured(block) ? "yellow" : "red");
1054 /* dump the blocks edges */
1055 dump_ir_data_edges(block);
1057 /* dump the nodes that go into the block */
1058 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1060 dump_ir_data_edges(node);
1063 /* Close the vcg information for the block */
1065 dump_const_node_local(block);
1067 dump_chi_term(F, block);
1072 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1073 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1075 dump_block_graph(ir_graph *irg) {
1077 ir_graph *rem = current_ir_graph;
1078 ir_node **arr = ird_get_irg_link(irg);
1079 current_ir_graph = irg;
1081 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1082 ir_node * node = arr[i];
1083 if (is_Block(node)) {
1084 /* Dumps the block and all the nodes in the block, which are to
1085 be found in Block->link. */
1086 dump_whole_block(node);
1088 /* Nodes that are not in a Block. */
1090 dump_ir_data_edges(node);
1094 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1096 current_ir_graph = rem;
1099 /** Dumps an irg as a graph.
1100 * If interprocedural view edges can point to nodes out of this graph.
1102 static void dump_graph(ir_graph *irg) {
1104 fprintf(F, "graph: { title: \"");
1106 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1107 get_ent_dump_name(get_irg_ent(irg)));
1109 dump_block_graph (irg);
1111 /* Close the vcg information for the irg */
1112 fprintf(F, "}\n\n");
1115 /*******************************************************************/
1116 /* Basic type and entity nodes and edges. */
1117 /*******************************************************************/
1119 /* dumps the edges between nodes and their type or entity attributes. */
1120 static void dump_node2type_edges (ir_node *n, void *env)
1124 switch (get_irn_opcode(n)) {
1126 /* @@@ some consts have an entity */
1129 if ( (get_SymConst_kind(n) == type_tag)
1130 || (get_SymConst_kind(n) == size))
1132 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1136 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1139 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1142 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1145 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1148 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1156 static void print_type_info(type *tp) {
1157 if (get_type_state(tp) == layout_undefined) {
1158 fprintf(F, "state: layout_undefined\n");
1160 fprintf(F, "state: layout_fixed,\n");
1162 if (get_type_mode(tp))
1163 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1164 fprintf(F, "size: %dB,\n", get_type_size(tp));
1167 static void print_typespecific_info(type *tp) {
1168 switch (get_type_tpop_code(tp)) {
1171 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1178 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1179 fprintf(F, "params: %d\n", get_method_n_params(tp));
1180 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1188 case tpo_enumeration:
1202 static void print_typespecific_vcgattr(type *tp) {
1203 switch (get_type_tpop_code(tp)) {
1206 if (peculiarity_existent == get_class_peculiarity(tp))
1207 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1209 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1213 fprintf (F, " " TYPE_METH_NODE_ATTR);
1224 case tpo_enumeration:
1237 static int print_type_node(type *tp)
1241 fprintf (F, "node: {title: ");
1243 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1244 fprintf (F, " info1: \"");
1245 print_type_info(tp);
1246 print_typespecific_info(tp);
1248 print_typespecific_vcgattr(tp);
1254 #define X(a) case a: fprintf(F, #a); break
1255 void dump_entity_node(entity *ent)
1257 fprintf (F, "node: {title: \"");
1258 PRINT_ENTID(ent); fprintf(F, "\"");
1259 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1260 fprintf (F, "label: ");
1261 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1262 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1264 fprintf (F, "\nallocation: ");
1265 switch (get_entity_allocation(ent)) {
1266 X(allocation_dynamic);
1267 X(allocation_automatic);
1268 X(allocation_static);
1269 X(allocation_parameter);
1272 fprintf (F, "\nvisibility: ");
1273 switch (get_entity_visibility(ent)) {
1274 X(visibility_local);
1275 X(visibility_external_visible);
1276 X(visibility_external_allocated);
1279 fprintf (F, "\nvariability: ");
1280 switch (get_entity_variability(ent)) {
1281 X(variability_uninitialized);
1282 X(variability_initialized);
1283 X(variability_part_constant);
1284 X(variability_constant);
1287 fprintf (F, "\nvolatility: ");
1288 switch (get_entity_volatility(ent)) {
1289 X(volatility_non_volatile);
1290 X(volatility_is_volatile);
1293 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1294 fprintf(F, "\nname: %s\nld_name: %s",
1295 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1296 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1297 if (is_method_type(get_entity_type(ent))) {
1298 if (get_entity_irg(ent)) /* can be null */
1299 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1301 { fprintf (F, "\nirg = NULL"); }
1303 fprintf(F, "\"\n}\n");
1307 static void dump_enum_item(type *tp, int pos)
1310 ident *id = get_enumeration_nameid(tp, pos);
1311 tarval *tv = get_enumeration_enum(tp, pos);
1313 tarval_snprintf(buf, sizeof(buf), tv);
1314 fprintf (F, "node: {title: \"");
1315 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1316 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1317 fprintf (F, "label: ");
1318 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1319 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1322 /* dumps a type or entity and it's edges. */
1324 dump_type_info (type_or_ent *tore, void *env) {
1325 int i = 0; /* to shutup gcc */
1327 /* dump this type or entity */
1329 switch (get_kind(tore)) {
1332 entity *ent = (entity *)tore;
1335 dump_entity_node(ent);
1337 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1338 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1339 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1340 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1341 if(is_class_type(get_entity_owner(ent))) {
1342 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1343 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1346 /* attached subgraphs */
1347 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1348 if (is_atomic_entity(ent)) {
1349 value = get_atomic_ent_value(ent);
1351 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1352 /* DDMN(value); $$$ */
1353 dump_const_expression(value);
1356 if (is_compound_entity(ent)) {
1357 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1358 value = get_compound_ent_value(ent, i);
1360 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1361 dump_const_expression(value);
1362 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1364 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1365 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1366 get_compound_ent_value_member(ent, i), i);
1375 type *tp = (type *)tore;
1376 print_type_node(tp);
1377 /* and now the edges */
1378 switch (get_type_tpop_code(tp)) {
1381 for (i=0; i < get_class_n_supertypes(tp); i++) {
1382 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1385 for (i=0; i < get_class_n_members(tp); i++) {
1386 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1391 for (i=0; i < get_struct_n_members(tp); i++) {
1392 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1397 for (i = 0; i < get_method_n_params(tp); i++)
1399 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1401 for (i = 0; i < get_method_n_ress(tp); i++)
1403 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1408 for (i = 0; i < get_union_n_members(tp); i++)
1410 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1415 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1416 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1417 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1418 ir_node *upper = get_array_upper_bound(tp, i);
1419 ir_node *lower = get_array_lower_bound(tp, i);
1420 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1421 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1422 dump_const_expression(upper);
1423 dump_const_expression(lower);
1427 case tpo_enumeration:
1429 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1430 dump_enum_item(tp, i);
1431 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1436 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1444 break; /* case k_type */
1447 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1449 } /* switch kind_or_entity */
1452 /** For dumping class hierarchies.
1453 * Dumps a class type node and a superclass edge.
1454 * If env != null dumps entities of classes and overwrites edges.
1457 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1458 int i = 0; /* to shutup gcc */
1460 /* dump this type or entity */
1461 switch (get_kind(tore)) {
1463 entity *ent = (entity *)tore;
1464 if (get_entity_owner(ent) == get_glob_type()) break;
1465 if ((env) && is_class_type(get_entity_owner(ent))) {
1467 dump_entity_node(ent);
1469 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1470 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1472 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1475 } break; /* case k_entity */
1478 type *tp = (type *)tore;
1479 if (tp == get_glob_type()) break;
1480 switch (get_type_tpop_code(tp)) {
1482 print_type_node(tp);
1483 /* and now the edges */
1484 for (i=0; i < get_class_n_supertypes(tp); i++)
1486 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1492 break; /* case k_type */
1495 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1497 } /* switch kind_or_entity */
1500 /*******************************************************************/
1501 /* dump analysis information that is expressed in graph terms. */
1502 /*******************************************************************/
1504 /* dump out edges */
1506 dump_out_edge (ir_node *n, void* env) {
1508 for (i = 0; i < get_irn_n_outs(n); i++) {
1509 assert(get_irn_out(n, i));
1510 fprintf (F, "edge: {sourcename: \"");
1512 fprintf (F, "\" targetname: \"");
1513 PRINT_NODEID(get_irn_out(n, i));
1514 fprintf (F, "\" color: red linestyle: dashed");
1520 dump_loop_label(ir_loop *loop) {
1521 fprintf (F, "loop %d, %d sons, %d nodes",
1522 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1525 static INLINE void dump_loop_info(ir_loop *loop) {
1526 fprintf (F, " info1: \"");
1527 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1528 #if DEBUG_libfirm /* GL @@@ debug analyses */
1529 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1535 dump_loop_node(ir_loop *loop) {
1536 fprintf (F, "node: {title: \"");
1538 fprintf (F, "\" label: \"");
1539 dump_loop_label(loop);
1541 dump_loop_info(loop);
1547 dump_loop_node_edge (ir_loop *loop, int i) {
1549 fprintf (F, "edge: {sourcename: \"");
1551 fprintf (F, "\" targetname: \"");
1552 PRINT_NODEID(get_loop_node(loop, i));
1553 fprintf (F, "\" color: green");
1558 dump_loop_son_edge (ir_loop *loop, int i) {
1560 fprintf (F, "edge: {sourcename: \"");
1562 fprintf (F, "\" targetname: \"");
1563 PRINT_LOOPID(get_loop_son(loop, i));
1564 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1565 get_loop_element_pos(loop, get_loop_son(loop, i)));
1569 void dump_loops (ir_loop *loop) {
1571 /* dump this loop node */
1572 dump_loop_node(loop);
1574 /* dump edges to nodes in loop -- only if it is a real loop */
1575 if (get_loop_depth(loop) != 0) {
1576 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1577 dump_loop_node_edge(loop, i);
1580 for (i = 0; i < get_loop_n_sons(loop); i++) {
1581 dump_loops(get_loop_son(loop, i));
1582 dump_loop_son_edge(loop, i);
1587 void dump_loop_nodes_into_graph(ir_graph *irg) {
1588 ir_graph *rem = current_ir_graph;
1589 current_ir_graph = irg;
1591 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1593 current_ir_graph = rem;
1597 /************************************************************************/
1598 /* open and close vcg file */
1599 /************************************************************************/
1602 dump_vcg_header(const char *name, const char *orientation) {
1611 if (!orientation) orientation = "bottom_to_top";
1615 "graph: { title: \"ir graph of %s\"\n"
1616 "display_edge_labels: %s\n"
1617 "layoutalgorithm: mindepth\n"
1618 "manhattan_edges: yes\n"
1619 "port_sharing: no\n"
1621 "classname 1: \"intrablock Data\"\n"
1622 "classname 16: \"interblock Data\"\n"
1623 "classname 2: \"Block\"\n"
1624 "classname 13: \"Control Flow\"\n"
1625 "classname 14: \"intrablock Memory\"\n"
1626 "classname 17: \"interblock Memory\"\n"
1627 "classname 15: \"Dominators\"\n"
1628 "classname 3: \"Entity type\"\n"
1629 "classname 4: \"Entity owner\"\n"
1630 "classname 5: \"Method Param\"\n"
1631 "classname 6: \"Method Res\"\n"
1632 "classname 7: \"Super\"\n"
1633 "classname 8: \"Union\"\n"
1634 "classname 9: \"Points-to\"\n"
1635 "classname 10: \"Array Element Type\"\n"
1636 "classname 11: \"Overwrites\"\n"
1637 "classname 12: \"Member\"\n"
1638 "infoname 1: \"Attribute\"\n"
1639 "infoname 2: \"Verification errors\"\n",
1640 name, label, orientation);
1642 fprintf (F, "\n"); /* a separator */
1645 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1646 const char *nm = get_irg_dump_name(irg);
1647 int len = strlen(nm), i, j;
1648 char *fname; /* filename to put the vcg information in */
1650 if (!suffix1) suffix1 = "";
1651 if (!suffix2) suffix2 = "";
1653 /** open file for vcg graph */
1654 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1656 /* strncpy (fname, nm, len); */ /* copy the filename */
1658 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1660 fname[j] = '@'; j++; fname[j] = '1'; j++;
1661 } else if (nm[i] == '@') {
1662 fname[j] = '@'; j++; fname[j] = '2'; j++;
1664 fname[j] = nm[i]; j++;
1668 strcat (fname, suffix1); /* append file suffix */
1669 strcat (fname, suffix2); /* append file suffix */
1670 strcat (fname, ".vcg"); /* append the .vcg suffix */
1671 F = fopen (fname, "w"); /* open file for writing */
1673 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1678 static void vcg_open_name (const char *name, char *suffix) {
1679 char *fname; /* filename to put the vcg information in */
1680 int i, j, len = strlen(name);
1682 if (!suffix) suffix = "";
1684 /** open file for vcg graph */
1685 fname = malloc (len * 2 + 5 + strlen(suffix));
1686 /* strcpy (fname, name);*/ /* copy the filename */
1688 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1689 if (name[i] == '/') {
1690 fname[j] = '@'; j++; fname[j] = '1'; j++;
1691 } else if (name[i] == '@') {
1692 fname[j] = '@'; j++; fname[j] = '2'; j++;
1694 fname[j] = name[i]; j++;
1698 strcat (fname, suffix);
1699 strcat (fname, ".vcg"); /* append the .vcg suffix */
1700 F = fopen (fname, "w"); /* open file for writing */
1702 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1707 static INLINE void dump_vcg_footer (void) {
1713 dump_vcg_footer(); /* print footer */
1714 fclose (F); /* close vcg file */
1717 /************************************************************************/
1718 /************************************************************************/
1719 /* Routines that dump all or parts of the firm representation to a file */
1720 /************************************************************************/
1721 /************************************************************************/
1723 /************************************************************************/
1724 /* Dump ir graphs, differnt formats and additional information. */
1725 /************************************************************************/
1727 /** Routine to dump a graph, blocks as conventional nodes.
1730 dump_ir_graph (ir_graph *irg)
1734 rem = current_ir_graph;
1736 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1738 current_ir_graph = irg;
1739 if (interprocedural_view) suffix = "-pure-ip";
1740 else suffix = "-pure";
1741 vcg_open (irg, dump_file_suffix, suffix);
1742 dump_vcg_header(get_irg_dump_name(irg), NULL);
1744 /* walk over the graph */
1745 /* dump_whole_node must be called in post visiting predecessors */
1746 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1748 /* dump the out edges in a separate walk */
1749 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1750 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1755 current_ir_graph = rem;
1760 dump_ir_block_graph (ir_graph *irg)
1765 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1767 if (interprocedural_view) suffix = "-ip";
1769 vcg_open (irg, dump_file_suffix, suffix);
1770 dump_vcg_header(get_irg_dump_name(irg), NULL);
1772 construct_block_lists(irg);
1774 for (i = 0; i < get_irp_n_irgs(); i++) {
1775 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1777 dump_graph(get_irp_irg(i));
1785 /** dumps a graph with type information
1788 dump_ir_graph_w_types (ir_graph *irg)
1790 ir_graph *rem = current_ir_graph;
1793 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1795 current_ir_graph = irg;
1797 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1798 else suffix = "-pure-wtypes";
1799 vcg_open (irg, dump_file_suffix, suffix);
1800 dump_vcg_header(get_irg_dump_name(irg), NULL);
1802 /* dump common ir graph */
1803 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1804 /* dump type info */
1805 type_walk_irg(irg, dump_type_info, NULL, NULL);
1806 inc_irg_visited(get_const_code_irg());
1807 /* dump edges from graph to type info */
1808 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1811 current_ir_graph = rem;
1815 dump_ir_block_graph_w_types (ir_graph *irg)
1819 ir_graph *rem = current_ir_graph;
1821 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1823 if (interprocedural_view) suffix = "-wtypes-ip";
1824 else suffix = "-wtypes";
1825 vcg_open (irg, dump_file_suffix, suffix);
1826 dump_vcg_header(get_irg_dump_name(irg), NULL);
1828 /* dump common blocked ir graph */
1829 construct_block_lists(irg);
1831 for (i = 0; i < get_irp_n_irgs(); i++) {
1832 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1834 dump_graph(get_irp_irg(i));
1839 /* dump type info */
1840 current_ir_graph = irg;
1841 type_walk_irg(irg, dump_type_info, NULL, NULL);
1842 inc_irg_visited(get_const_code_irg());
1844 /* dump edges from graph to type info */
1845 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1847 current_ir_graph = rem;
1851 /***********************************************************************/
1852 /* The following routines dump a control flow graph. */
1853 /***********************************************************************/
1856 dump_block_to_cfg (ir_node *block, void *env) {
1860 if (is_Block(block)) {
1861 /* This is a block. Dump a node for the block. */
1862 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1863 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1864 PRINT_NODEID(block);
1866 if (dump_dominator_information_flag)
1867 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1869 /* Dump the edges */
1870 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1871 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1872 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1873 fprintf (F, "edge: { sourcename: \"");
1874 PRINT_NODEID(block);
1875 fprintf (F, "\" targetname: \"");
1877 fprintf (F, "\"}\n");
1880 /* Dump dominator edge */
1881 if (dump_dominator_information_flag && get_Block_idom(block)) {
1882 pred = get_Block_idom(block);
1883 fprintf (F, "edge: { sourcename: \"");
1884 PRINT_NODEID(block);
1885 fprintf (F, "\" targetname: \"");
1887 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1893 dump_cfg (ir_graph *irg)
1895 ir_graph *rem = current_ir_graph;
1896 int ddif = dump_dominator_information_flag;
1897 int ipv = interprocedural_view;
1899 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1901 current_ir_graph = irg;
1903 vcg_open (irg, dump_file_suffix, "-cfg");
1904 dump_vcg_header(get_irg_dump_name(irg), NULL);
1906 if (interprocedural_view) {
1907 printf("Warning: dumping cfg not in interprocedural view!\n");
1908 interprocedural_view = 0;
1911 if (get_irg_dom_state(irg) != dom_consistent)
1912 dump_dominator_information_flag = 0;
1914 /* walk over the blocks in the graph */
1915 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1916 dump_node (get_irg_bad(irg));
1918 dump_dominator_information_flag = ddif;
1919 interprocedural_view = ipv;
1921 current_ir_graph = rem;
1926 /* Dump all irgs in interprocedural view to a single file. */
1927 void dump_all_cg_block_graph(void) {
1929 int rem_view = interprocedural_view;
1930 interprocedural_view = 1;
1932 vcg_open_name ("All_graphs", dump_file_suffix);
1933 dump_vcg_header("All_graphs", NULL);
1935 /* collect nodes in all irgs reachable in call graph*/
1936 for (i = 0; i < get_irp_n_irgs(); i++)
1937 ird_set_irg_link(get_irp_irg(i), NULL);
1939 cg_walk(clear_link, collect_node, NULL);
1941 /* dump all graphs */
1942 for (i = 0; i < get_irp_n_irgs(); i++) {
1943 current_ir_graph = get_irp_irg(i);
1944 assert(ird_get_irg_link(current_ir_graph));
1945 dump_graph(current_ir_graph);
1946 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1950 interprocedural_view = rem_view;
1953 /***********************************************************************/
1954 /* the following routines dumps type information without any ir nodes. */
1955 /***********************************************************************/
1958 dump_type_graph (ir_graph *irg)
1961 rem = current_ir_graph;
1963 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1965 current_ir_graph = irg;
1967 vcg_open (irg, dump_file_suffix, "-type");
1968 dump_vcg_header(get_irg_dump_name(irg), NULL);
1970 /* walk over the blocks in the graph */
1971 type_walk_irg(irg, dump_type_info, NULL, NULL);
1972 /* The walker for the const code can be called several times for the
1973 same (sub) experssion. So that no nodes are dumped several times
1974 we decrease the visited flag of the corresponding graph after each
1975 walk. So now increase it finally. */
1976 inc_irg_visited(get_const_code_irg());
1979 current_ir_graph = rem;
1983 dump_all_types (void)
1985 vcg_open_name ("All_types", dump_file_suffix);
1986 dump_vcg_header("All_types", NULL);
1987 type_walk(dump_type_info, NULL, NULL);
1988 inc_irg_visited(get_const_code_irg());
1993 dump_class_hierarchy (bool entities)
1995 vcg_open_name ("class_hierarchy", dump_file_suffix);
1996 dump_vcg_header("class_hierarchy", NULL);
1998 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2000 type_walk(dump_class_hierarchy_node, NULL, NULL);
2004 /***********************************************************************/
2005 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2007 /* dump_ir_block_graph */
2009 /* dump_type_graph */
2010 /* dump_ir_graph_w_types */
2011 /***********************************************************************/
2013 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2015 for (i=0; i < get_irp_n_irgs(); i++) {
2016 dmp_grph(get_irp_irg(i));
2021 /**********************************************************************************
2022 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2023 * packed together in one subgraph *
2024 **********************************************************************************/
2028 void dump_loops_standalone (ir_loop *loop) {
2029 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2031 ir_loop *son = NULL;
2033 /* Dump a new loop node. */
2034 dump_loop_node(loop);
2036 /* Dump the loop elements. */
2038 for(i = 0; i < get_loop_n_elements(loop); i++)
2040 le = get_loop_element(loop, i);
2042 if (get_kind(son) == k_ir_loop) {
2044 /* We are a loop son -> Recurse */
2046 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2047 fprintf(F, "\" }\n");
2048 fprintf (F, "edge: {sourcename: \"");
2050 fprintf (F, "\" targetname: \"");
2052 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2053 loop_node_started = 0;
2055 dump_loop_son_edge(loop, son_number++);
2056 dump_loops_standalone(son);
2059 /* We are a loop node -> Collect firm nodes */
2061 ir_node *n = le.node;
2063 if (!loop_node_started) {
2064 /* Start a new node which contains all firm nodes of the current loop */
2065 fprintf (F, "node: { title: \"");
2067 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2068 loop_node_started = 1;
2074 dump_node_opcode(F, n);
2076 dump_node_typeinfo(n);
2078 dump_node_nodeattr(n);
2079 fprintf (F, " %ld", get_irn_node_nr(n));
2083 if (loop_node_started) {
2084 fprintf(F, "\" }\n");
2085 fprintf (F, "edge: {sourcename: \"");
2087 fprintf (F, "\" targetname: \"");
2089 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2090 loop_node_started = 0;
2094 void dump_loop_tree(ir_graph *irg, char *suffix)
2096 ir_graph *rem = current_ir_graph;
2097 int el_rem = edge_label;
2100 /* @@@ AS: What does that do? */
2101 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2103 current_ir_graph = irg;
2105 vcg_open(irg, suffix, "-looptree");
2106 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2108 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2112 edge_label = el_rem;
2113 current_ir_graph = rem;
2117 /*******************************************************************************/
2118 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2119 /*******************************************************************************/
2121 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2122 int i, son_number = 0, node_number = 0;
2124 if (dump_loop_information_flag) dump_loop_node(loop);
2126 for (i = 0; i < get_loop_n_elements(loop); i++) {
2127 loop_element le = get_loop_element(loop, i);
2128 if (*(le.kind) == k_ir_loop) {
2129 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2131 collect_nodeloop(le.son, loopnodes);
2133 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2134 eset_insert(loopnodes, le.node);
2139 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2142 for(i = 0; i < get_loop_n_elements(loop); i++) {
2143 loop_element le = get_loop_element(loop, i);
2144 if (*(le.kind) == k_ir_loop) {
2146 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2148 if (is_Block(le.node)) start = 0; else start = -1;
2149 for (j = start; j < get_irn_arity(le.node); j++) {
2150 ir_node *pred = get_irn_n(le.node, j);
2151 if (!eset_contains(loopnodes, pred)) {
2152 eset_insert(extnodes, pred);
2153 if (!is_Block(pred)) {
2154 pred = get_nodes_block(pred);
2155 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2163 void dump_loop (ir_loop *l, char *suffix) {
2165 eset *loopnodes = eset_create();
2166 eset *extnodes = eset_create();
2169 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2170 vcg_open_name (name, suffix);
2171 dump_vcg_header(name, NULL);
2173 /* collect all nodes to dump */
2174 collect_nodeloop(l, loopnodes);
2175 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2177 /* build block lists */
2178 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2179 set_irn_link(n, NULL);
2180 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2181 set_irn_link(n, NULL);
2182 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2184 b = get_nodes_block(n);
2185 set_irn_link(n, get_irn_link(b));
2188 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2190 b = get_nodes_block(n);
2191 set_irn_link(n, get_irn_link(b));
2195 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2197 fprintf(F, "graph: { title: \"");
2199 fprintf(F, "\" label: \"");
2200 dump_node_opcode(F, b);
2201 fprintf (F, " %ld", get_irn_node_nr(b));
2202 fprintf(F, "\" status:clustered color:yellow\n");
2204 /* dump the blocks edges */
2205 dump_ir_data_edges(b);
2207 /* dump the nodes that go into the block */
2208 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2209 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2211 overrule_nodecolor = NULL;
2212 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2215 /* Close the vcg information for the block */
2217 dump_const_node_local(b);
2220 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2222 fprintf(F, "graph: { title: \"");
2224 fprintf(F, "\" label: \"");
2225 dump_node_opcode(F, b);
2226 fprintf (F, " %ld", get_irn_node_nr(b));
2227 fprintf(F, "\" status:clustered color:lightblue\n");
2229 /* dump the nodes that go into the block */
2230 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2231 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2233 overrule_nodecolor = NULL;
2234 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2237 /* Close the vcg information for the block */
2239 dump_const_node_local(b);
2243 eset_destroy(loopnodes);
2244 eset_destroy(extnodes);