3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
22 # include "irnode_t.h"
23 # include "irgraph_t.h"
24 # include "entity_t.h"
26 # include "firm_common_t.h"
31 # include "typewalk.h"
34 # include "type_or_entity.h"
46 void dump_chi_term(FILE *FL, ir_node *n);
47 void dump_state(FILE *FL, ir_node *n);
48 int get_opt_dump_abstvals(void);
49 typedef unsigned long SeqNo;
50 SeqNo get_Block_seqno(ir_node *n);
53 /* Attributes of nodes */
54 #define PRINT_DEFAULT_NODE_ATTR
55 #define DEFAULT_NODE_ATTR " "
56 #define DEFAULT_TYPE_ATTRIBUTE " "
57 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
59 /* Attributes of edges between Firm nodes */
60 #define BLOCK_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
61 #define CF_EDGE_ATTR "class:13 color:red"
62 #define MEM_EDGE_ATTR "class:14 color:blue"
63 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
65 #define BACK_EDGE_ATTR "linestyle:dashed "
67 /* Attributes of edges between Firm nodes and type/entity nodes */
68 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
70 /* Attributes of edges in type/entity graphs. */
71 #define TYPE_METH_NODE_ATTR "color: lightyellow"
72 #define TYPE_CLASS_NODE_ATTR "color: green"
73 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
74 #define ENTITY_NODE_ATTR "color: yellow"
75 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
76 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
77 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
78 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
79 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
80 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
81 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
82 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
83 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
84 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
85 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
86 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
87 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
88 #define ENUM_ITEM_NODE_ATTR "color: green"
90 #if DEBUG_libfirm && NODEID_AS_LABEL
91 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
92 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
93 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
94 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
95 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
96 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
97 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
100 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
101 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
102 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
103 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
104 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
105 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
106 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
109 static const char *get_type_name_ex(type *tp, int *bad)
112 return get_type_name(tp);
117 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
122 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
123 fprintf(F, " targetname: "); PRINT_TYPEID(T);
124 vfprintf(F, fmt, ap);
129 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
134 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
135 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
136 vfprintf(F, fmt, ap);
141 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
146 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
147 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
148 vfprintf(F, fmt, ap);
153 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
158 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
159 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
160 vfprintf(F, fmt, ap);
165 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
170 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
171 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
172 vfprintf(F, fmt, ap);
177 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
182 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
183 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
185 vfprintf(F, fmt, ap);
190 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
195 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
196 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
197 vfprintf(F, fmt, ap);
202 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
207 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
208 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
209 vfprintf(F, fmt, ap);
214 /*******************************************************************/
215 /* global and ahead declarations */
216 /*******************************************************************/
218 /* A suffix to manipulate the file name. */
219 char *dump_file_suffix = "";
221 char *dump_file_filter = "";
223 /* file to dump to */
226 static void dump_whole_node(ir_node *n, void* env);
227 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
229 /*******************************************************************/
230 /* Helper functions. */
231 /*******************************************************************/
233 /* Use private link attr to be able to call dumper anywhere without
234 destroying link fields. */
236 static pmap *irdump_link_map = NULL;
238 static void init_irdump(void) {
239 /* We need a new, empty map. */
240 if (irdump_link_map) pmap_destroy(irdump_link_map);
241 irdump_link_map = pmap_create();
245 void *ird_get_irn_link(ir_node *n) {
247 if (!irdump_link_map) return NULL;
249 if (pmap_contains(irdump_link_map, (void *)n))
250 res = pmap_get(irdump_link_map, (void *)n);
254 void ird_set_irn_link(ir_node *n, void *x) {
255 if (!irdump_link_map) init_irdump();
256 pmap_insert(irdump_link_map, (void *)n, x);
259 void *ird_get_irg_link(ir_graph *irg) {
261 if (!irdump_link_map) return NULL;
263 if (pmap_contains(irdump_link_map, (void *)irg))
264 res = pmap_get(irdump_link_map, (void *)irg);
268 void ird_set_irg_link(ir_graph *irg, void *x) {
269 if (!irdump_link_map) init_irdump();
270 pmap_insert(irdump_link_map, (void *)irg, x);
273 static void clear_link(ir_node * node, void * env) {
274 ird_set_irn_link(node, NULL);
278 static int node_floats(ir_node *n) {
279 return ((get_op_pinned(get_irn_op(n)) == floats) &&
280 (get_irg_pinned(current_ir_graph) == floats));
283 static const char *get_ent_dump_name(entity *ent) {
285 return "<NULL entity>";
286 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
287 if (ent->ld_name) return get_id_str(ent->ld_name);
288 return get_id_str(ent->name);
291 static const char *get_irg_dump_name(ir_graph *irg) {
292 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
293 entity *ent = get_irg_ent(irg);
294 return get_ent_dump_name(ent);
297 static void collect_node(ir_node * node, void *env) {
300 || get_irn_op(node) == op_Bad
301 || get_irn_op(node) == op_Unknown) {
302 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
303 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
304 ARR_APP1(ir_node *, arr, node);
305 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
307 ir_node * block = get_nodes_block(node);
308 ird_set_irn_link(node, ird_get_irn_link(block));
309 ird_set_irn_link(block, node);
313 /** Construct lists to walk ir block-wise.
315 * Collects all blocks, nodes not pinned,
316 * Bad and Unknown into a flexible array in link field of
317 * irg they belong to. Sets the irg link field to NULL in all
318 * graphs not visited.
319 * Free the list with DEL_ARR_F. */
320 static ir_node ** construct_block_lists(ir_graph *irg) {
321 int i, rem_view = interprocedural_view;
322 ir_graph *rem = current_ir_graph;
323 current_ir_graph = irg;
325 for (i = 0; i < get_irp_n_irgs(); i++)
326 ird_set_irg_link(get_irp_irg(i), NULL);
328 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
330 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
331 interprocedural_view = 0;
332 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
333 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
334 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
335 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
336 interprocedural_view = rem_view;
338 current_ir_graph = rem;
339 return ird_get_irg_link(irg);
342 /*******************************************************************/
343 /* flags to steer output */
344 /*******************************************************************/
346 /* A compiler option to turn off edge labels */
348 /* A compiler option to turn off dumping values of constant entities */
349 int const_entities = 1;
350 /* A compiler option to dump the keep alive edges */
351 int dump_keepalive = 0;
352 /* Compiler options to dump analysis information in dump_ir_graph */
353 int dump_out_edge_flag = 0;
354 int dump_dominator_information_flag = 0;
355 int dump_loop_information_flag = 0;
356 int dump_backedge_information_flag = 1;
357 int dump_const_local = 0;
358 bool opt_dump_analysed_type_info = 1;
359 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
361 char* overrule_nodecolor = NULL;
363 INLINE bool get_opt_dump_const_local(void) {
364 if (!dump_out_edge_flag && !dump_loop_information_flag)
365 return dump_const_local;
370 /* To turn off display of edge labels. Edge labels offen cause xvcg to
371 abort with a segmentation fault. */
372 void turn_off_edge_labels(void) {
376 void dump_consts_local(bool b) {
377 dump_const_local = b;
380 void turn_off_constant_entity_values(void) {
384 void dump_keepalive_edges(bool b) {
388 bool get_opt_dump_keepalive_edges(void) {
389 return dump_keepalive;
392 void dump_out_edges(void) {
393 dump_out_edge_flag = 1;
396 void dump_dominator_information(void) {
397 dump_dominator_information_flag = 1;
400 void dump_loop_information(void) {
401 dump_loop_information_flag = 1;
404 void dont_dump_loop_information(void) {
405 dump_loop_information_flag = 0;
408 void dump_backedge_information(bool b) {
409 dump_backedge_information_flag = b;
412 /* Dump the information of type field specified in ana/irtypeinfo.h.
413 * If the flag is set, the type name is output in [] in the node label,
414 * else it is output as info.
416 void dump_analysed_type_info(bool b) {
417 opt_dump_analysed_type_info = b;
420 void dump_pointer_values_to_info(bool b) {
421 opt_dump_pointer_values_to_info = b;
424 /*******************************************************************/
425 /* Routines to dump information about a single ir node. */
426 /*******************************************************************/
429 dump_node_opcode(FILE *F, ir_node *n)
433 switch(get_irn_opcode(n)) {
438 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
439 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
444 if (get_SymConst_kind(n) == linkage_ptr_info) {
445 /* don't use get_SymConst_ptr_info as it mangles the name. */
446 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
448 assert(get_kind(get_SymConst_type(n)) == k_type);
449 assert(get_type_ident(get_SymConst_type(n)));
450 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
451 if (get_SymConst_kind(n) == type_tag)
459 if (!interprocedural_view) fprintf(F, "Proj'");
460 else fprintf(F, "%s", get_irn_opname(n));
464 if (interprocedural_view) {
465 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
471 fprintf (F, "%s", get_irn_opname(n));
479 dump_node_mode (ir_node *n)
481 switch (get_irn_opcode(n)) {
500 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
507 static int dump_node_typeinfo(ir_node *n) {
510 if (opt_dump_analysed_type_info) {
511 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
512 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
513 type *tp = get_irn_type(n);
515 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
524 dump_node_nodeattr (ir_node *n)
528 switch (get_irn_opcode(n)) {
530 if (false && interprocedural_view) {
531 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
535 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
536 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
538 fprintf (F, "%ld", get_Proj_proj(n));
542 fprintf (F, "%ld", get_Filter_proj(n));
545 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
548 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
551 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
561 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
564 fprintf(F, "color: red");
567 switch (get_irn_opcode(n)) {
574 fprintf (F, "color: blue");
577 fprintf (F, "color: lightyellow");
580 fprintf (F, "color: green");
586 fprintf (F, "color: yellow");
589 PRINT_DEFAULT_NODE_ATTR;
592 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
595 static INLINE int dump_node_info(ir_node *n)
601 fprintf (F, " info1: \"");
602 if (opt_dump_pointer_values_to_info)
603 fprintf (F, "addr: %p \n", (void *)n);
604 fprintf (F, "visited: %ld \n", get_irn_visited(n));
605 irg = get_irn_irg(n);
606 if (irg != get_const_code_irg())
607 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
609 fprintf(F, "arity: %d", get_irn_arity(n));
610 if ((get_irn_op(n) == op_Block) ||
611 (get_irn_op(n) == op_Phi) ||
612 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
613 fprintf(F, " backedges:");
615 for (i = 0; i < get_irn_arity(n); i++)
616 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
620 /* Loop node Someone else please tell me what's wrong ...
621 if (get_irn_loop(n)) {
622 ir_loop *loop = get_irn_loop(n);
624 fprintf(F, " in loop %d with depth %d\n",
625 get_loop_loop_nr(loop), get_loop_depth(loop));
630 switch (get_irn_opcode(n)) {
632 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
633 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
634 for (i = 0; i < get_method_n_params(tp); ++i)
635 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
638 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
641 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
644 entity *ent = get_Sel_entity(n);
647 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
648 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
651 fprintf(F, "<NULL entity>\n");
656 type *tp = get_Call_type(n);
657 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
658 for (i = 0; i < get_method_n_params(tp); ++i)
659 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
660 for (i = 0; i < get_method_n_ress(tp); ++i)
661 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
662 if (Call_has_callees(n)) {
663 fprintf(F, "possible callees: \n");
664 for (i = 0; i < get_Call_n_callees(n); i++) {
665 if (!get_Call_callee(n, i)) {
666 fprintf(F, " %d external method\n", i);
668 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
673 case iro_CallBegin: {
674 ir_node *call = get_CallBegin_call(n);
675 if (Call_has_callees(call)) {
676 fprintf(F, "possible callees: \n");
677 for (i = 0; i < get_Call_n_callees(call); i++) {
678 if (!get_Call_callee(call, i)) {
679 fprintf(F, " %d external method\n", i);
681 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
687 if (!interprocedural_view) {
688 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
689 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
690 for (i = 0; i < get_method_n_ress(tp); ++i)
691 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
695 type *tp = get_Const_type(n);
696 assert(tp != none_type);
697 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
701 if (interprocedural_view) {
702 fprintf(F, "intra predecessor nodes:\n");
703 for (i = 0; i < get_irn_intra_arity(n); i++) {
704 ir_node *pred = get_irn_intra_n(n, i);
705 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
708 fprintf(F, "inter predecessor nodes:\n");
709 for (i = 0; i < get_irn_inter_arity(n); i++) {
710 ir_node *pred = get_irn_inter_n(n, i);
711 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
712 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
719 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
720 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
721 if (get_irn_type(n) != none_type)
722 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
731 bool is_constlike_node(ir_node *n) {
732 ir_op *op = get_irn_op(n);
733 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
737 /* outputs the predecessors of n, that are constants, local. I.e.,
738 generates a copy of the constant predecessors for each node called with. */
739 static void dump_const_node_local(ir_node *n) {
741 if (!get_opt_dump_const_local()) return;
743 /* Use visited flag to avoid outputting nodes twice.
744 initialize it first. */
745 for (i = 0; i < get_irn_arity(n); i++) {
746 ir_node *con = get_irn_n(n, i);
747 if (is_constlike_node(con)) {
748 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
752 for (i = 0; i < get_irn_arity(n); i++) {
753 ir_node *con = get_irn_n(n, i);
754 if (is_constlike_node(con) && irn_not_visited(con)) {
757 mark_irn_visited(con);
758 /* Generate a new name for the node by appending the names of
760 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
761 fprintf(F, " label: \"");
762 bad |= dump_node_opcode(F, con);
763 dump_node_mode (con);
764 bad |= dump_node_typeinfo(con);
766 bad |= dump_node_nodeattr(con);
767 fprintf(F, " %ld", get_irn_node_nr(con));
769 bad |= dump_node_info(con);
770 dump_node_vcgattr(con, bad);
776 static void print_node_error(const char *p)
781 fprintf (F, " info2: \"%s\"", p);
784 static void dump_node(ir_node *n)
789 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
791 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
793 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
794 bad |= dump_node_opcode(F, n);
796 bad |= dump_node_typeinfo(n);
798 bad |= dump_node_nodeattr(n);
799 fprintf(F, " %ld", get_irn_node_nr(n));
801 bad |= dump_node_info(n);
803 dump_node_vcgattr(n, bad);
805 dump_const_node_local(n);
812 /* dump the edge to the block this node belongs to */
814 dump_ir_block_edge(ir_node *n) {
815 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
816 if (is_no_Block(n)) {
817 fprintf (F, "edge: { sourcename: \"");
819 fprintf (F, "\" targetname: \"");
820 PRINT_NODEID(get_nodes_block(n));
821 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
825 static void print_edge_vcgattr(ir_node *from, int to) {
828 if (dump_backedge_information_flag && is_backedge(from, to))
829 fprintf (F, BACK_EDGE_ATTR);
831 switch (get_irn_opcode(from)) {
833 fprintf (F, CF_EDGE_ATTR);
835 case iro_Start: break;
838 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
839 fprintf (F, CF_EDGE_ATTR);
840 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
841 fprintf (F, MEM_EDGE_ATTR);
844 case iro_EndReg: break;
845 case iro_EndExcept: break;
847 case iro_Break: break;
848 case iro_Cond: break;
851 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
853 case iro_Const: break;
854 case iro_SymConst:break;
857 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
859 case iro_CallBegin: break;
862 case iro_Minus: break;
868 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
876 case iro_Shrs: break;
879 case iro_Conv: break;
881 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
887 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
890 fprintf (F, MEM_EDGE_ATTR);
892 case iro_Tuple: break;
895 switch (get_irn_modecode(from)) {
897 fprintf (F, CF_EDGE_ATTR);
900 fprintf (F, MEM_EDGE_ATTR);
906 case iro_Unknown: break;
913 /* dump edges to our inputs */
915 dump_ir_data_edges(ir_node *n) {
916 int i, visited = get_irn_visited(n);
918 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
921 for (i = 0; i < get_irn_arity(n); i++) {
922 ir_node * pred = get_irn_n(n, i);
925 if ((interprocedural_view && get_irn_visited(pred) < visited))
926 continue; /* pred not dumped */
928 if (dump_backedge_information_flag && is_backedge(n, i))
929 fprintf (F, "backedge: {sourcename: \"");
931 fprintf (F, "edge: {sourcename: \"");
933 fprintf (F, "\" targetname: ");
934 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
935 PRINT_CONSTID(n, pred);
937 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
939 fprintf (F, " label: \"%d\" ", i);
940 print_edge_vcgattr(n, i);
945 /** Dumps a node and its edges but not the block edge
948 dump_node_wo_blockedge (ir_node *n, void* env) {
950 dump_ir_data_edges(n);
953 /** Dumps a node and its edges.
956 dump_whole_node (ir_node *n, void* env) {
957 dump_node_wo_blockedge(n, env);
958 if (!node_floats(n)) dump_ir_block_edge(n);
962 dump_const_node(ir_node *n, void *env) {
963 if (is_Block(n)) return;
964 dump_node_wo_blockedge(n, env);
967 /***********************************************************************/
968 /* the following routines dump the nodes/irgs bracketed to graphs. */
969 /***********************************************************************/
971 /** Dumps a constant expression as entity initializer, array bound ...
973 static void dump_const_expression(ir_node *value) {
974 ir_graph *rem = current_ir_graph;
975 int rem_dump_const_local = dump_const_local;
976 dump_const_local = 0;
977 current_ir_graph = get_const_code_irg();
978 irg_walk(value, dump_const_node, NULL, NULL);
979 /* Decrease visited flag so that we walk with the same flag for the next
980 expresssion. This guarantees that we don't dump the same node twice,
981 as for const expressions cse is performed to save memory. */
982 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
983 current_ir_graph = rem;
984 dump_const_local = rem_dump_const_local;
987 /** Dump a block as graph containing its nodes.
989 * Expects to find nodes belonging to the block as list in its
991 * Dumps the edges of all nodes including itself. */
993 dump_whole_block(ir_node *block) {
995 assert(is_Block(block));
997 fprintf(F, "graph: { title: \"");
999 fprintf(F, "\" label: \"");
1000 dump_node_opcode(F, block);
1001 fprintf (F, " %ld", get_irn_node_nr(block));
1003 if (get_opt_dump_abstvals())
1004 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1006 fprintf(F, "\" status:clustered color:%s \n",
1007 get_Block_matured(block) ? "yellow" : "red");
1009 /* dump the blocks edges */
1010 dump_ir_data_edges(block);
1012 /* dump the nodes that go into the block */
1013 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1015 dump_ir_data_edges(node);
1018 /* Close the vcg information for the block */
1020 dump_const_node_local(block);
1022 dump_chi_term(F, block);
1027 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1028 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1030 dump_block_graph(ir_graph *irg) {
1032 ir_graph *rem = current_ir_graph;
1033 ir_node **arr = ird_get_irg_link(irg);
1034 current_ir_graph = irg;
1036 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1037 ir_node * node = arr[i];
1038 if (is_Block(node)) {
1039 /* Dumps the block and all the nodes in the block, which are to
1040 be found in Block->link. */
1041 dump_whole_block(node);
1043 /* Nodes that are not in a Block. */
1045 dump_ir_data_edges(node);
1049 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1051 current_ir_graph = rem;
1054 /** Dumps an irg as a graph.
1055 * If interprocedural view edges can point to nodes out of this graph.
1057 static void dump_graph(ir_graph *irg) {
1059 fprintf(F, "graph: { title: \"");
1061 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1062 get_ent_dump_name(get_irg_ent(irg)));
1064 dump_block_graph (irg);
1066 /* Close the vcg information for the irg */
1067 fprintf(F, "}\n\n");
1070 /*******************************************************************/
1071 /* Basic type and entity nodes and edges. */
1072 /*******************************************************************/
1074 /* dumps the edges between nodes and their type or entity attributes. */
1075 static void dump_node2type_edges (ir_node *n, void *env)
1079 switch (get_irn_opcode(n)) {
1081 /* @@@ some consts have an entity */
1084 if ( (get_SymConst_kind(n) == type_tag)
1085 || (get_SymConst_kind(n) == size))
1087 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1091 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1094 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1097 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1100 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1103 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1111 static void print_type_info(type *tp) {
1112 if (get_type_state(tp) == layout_undefined) {
1113 fprintf(F, "state: layout_undefined\n");
1115 fprintf(F, "state: layout_fixed,\n");
1117 if (get_type_mode(tp))
1118 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1119 fprintf(F, "size: %dB,\n", get_type_size(tp));
1122 static void print_typespecific_info(type *tp) {
1123 switch (get_type_tpop_code(tp)) {
1126 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1133 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1134 fprintf(F, "params: %d\n", get_method_n_params(tp));
1135 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1143 case tpo_enumeration:
1157 static void print_typespecific_vcgattr(type *tp) {
1158 switch (get_type_tpop_code(tp)) {
1161 if (peculiarity_existent == get_class_peculiarity(tp))
1162 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1164 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1168 fprintf (F, " " TYPE_METH_NODE_ATTR);
1179 case tpo_enumeration:
1192 static int print_type_node(type *tp)
1196 fprintf (F, "node: {title: ");
1198 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1199 fprintf (F, " info1: \"");
1200 print_type_info(tp);
1201 print_typespecific_info(tp);
1203 print_typespecific_vcgattr(tp);
1209 #define X(a) case a: fprintf(F, #a); break
1210 void dump_entity_node(entity *ent)
1212 fprintf (F, "node: {title: \"");
1213 PRINT_ENTID(ent); fprintf(F, "\"");
1214 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1215 fprintf (F, "label: ");
1216 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1217 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1219 fprintf (F, "\nallocation: ");
1220 switch (get_entity_allocation(ent)) {
1221 X(allocation_dynamic);
1222 X(allocation_automatic);
1223 X(allocation_static);
1224 X(allocation_parameter);
1227 fprintf (F, "\nvisibility: ");
1228 switch (get_entity_visibility(ent)) {
1229 X(visibility_local);
1230 X(visibility_external_visible);
1231 X(visibility_external_allocated);
1234 fprintf (F, "\nvariability: ");
1235 switch (get_entity_variability(ent)) {
1236 X(variability_uninitialized);
1237 X(variability_initialized);
1238 X(variability_part_constant);
1239 X(variability_constant);
1242 fprintf (F, "\nvolatility: ");
1243 switch (get_entity_volatility(ent)) {
1244 X(volatility_non_volatile);
1245 X(volatility_is_volatile);
1248 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1249 fprintf(F, "\nname: %s\nld_name: %s",
1250 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1251 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1252 if (is_method_type(get_entity_type(ent))) {
1253 if (get_entity_irg(ent)) /* can be null */
1254 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1256 { fprintf (F, "\nirg = NULL"); }
1258 fprintf(F, "\"\n}\n");
1262 static void dump_enum_item(type *tp, int pos)
1265 ident *id = get_enumeration_nameid(tp, pos);
1266 tarval *tv = get_enumeration_enum(tp, pos);
1268 tarval_snprintf(buf, sizeof(buf), tv);
1269 fprintf (F, "node: {title: \"");
1270 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1271 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1272 fprintf (F, "label: ");
1273 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1274 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1277 /* dumps a type or entity and it's edges. */
1279 dump_type_info (type_or_ent *tore, void *env) {
1280 int i = 0; /* to shutup gcc */
1282 /* dump this type or entity */
1284 switch (get_kind(tore)) {
1287 entity *ent = (entity *)tore;
1290 dump_entity_node(ent);
1292 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1293 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1294 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1295 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1296 if(is_class_type(get_entity_owner(ent))) {
1297 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1298 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1301 /* attached subgraphs */
1302 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1303 if (is_atomic_entity(ent)) {
1304 value = get_atomic_ent_value(ent);
1306 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1307 /* DDMN(value); $$$ */
1308 dump_const_expression(value);
1311 if (is_compound_entity(ent)) {
1312 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1313 value = get_compound_ent_value(ent, i);
1315 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1316 dump_const_expression(value);
1317 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1319 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1320 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1321 get_compound_ent_value_member(ent, i), i);
1330 type *tp = (type *)tore;
1331 print_type_node(tp);
1332 /* and now the edges */
1333 switch (get_type_tpop_code(tp)) {
1336 for (i=0; i < get_class_n_supertypes(tp); i++) {
1337 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1340 for (i=0; i < get_class_n_members(tp); i++) {
1341 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1346 for (i=0; i < get_struct_n_members(tp); i++) {
1347 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1352 for (i = 0; i < get_method_n_params(tp); i++)
1354 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1356 for (i = 0; i < get_method_n_ress(tp); i++)
1358 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1363 for (i = 0; i < get_union_n_members(tp); i++)
1365 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1370 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1371 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1372 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1373 ir_node *upper = get_array_upper_bound(tp, i);
1374 ir_node *lower = get_array_lower_bound(tp, i);
1375 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1376 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1377 dump_const_expression(upper);
1378 dump_const_expression(lower);
1382 case tpo_enumeration:
1384 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1385 dump_enum_item(tp, i);
1386 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1391 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1399 break; /* case k_type */
1402 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1404 } /* switch kind_or_entity */
1407 /** For dumping class hierarchies.
1408 * Dumps a class type node and a superclass edge.
1409 * If env != null dumps entities of classes and overwrites edges.
1412 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1413 int i = 0; /* to shutup gcc */
1415 /* dump this type or entity */
1416 switch (get_kind(tore)) {
1418 entity *ent = (entity *)tore;
1419 if (get_entity_owner(ent) == get_glob_type()) break;
1420 if ((env) && is_class_type(get_entity_owner(ent))) {
1422 dump_entity_node(ent);
1424 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1425 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1427 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1430 } break; /* case k_entity */
1433 type *tp = (type *)tore;
1434 if (tp == get_glob_type()) break;
1435 switch (get_type_tpop_code(tp)) {
1437 print_type_node(tp);
1438 /* and now the edges */
1439 for (i=0; i < get_class_n_supertypes(tp); i++)
1441 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1447 break; /* case k_type */
1450 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1452 } /* switch kind_or_entity */
1455 /*******************************************************************/
1456 /* dump analysis information that is expressed in graph terms. */
1457 /*******************************************************************/
1459 /* dump out edges */
1461 dump_out_edge (ir_node *n, void* env) {
1463 for (i = 0; i < get_irn_n_outs(n); i++) {
1464 assert(get_irn_out(n, i));
1465 fprintf (F, "edge: {sourcename: \"");
1467 fprintf (F, "\" targetname: \"");
1468 PRINT_NODEID(get_irn_out(n, i));
1469 fprintf (F, "\" color: red linestyle: dashed");
1475 dump_loop_label(ir_loop *loop) {
1476 fprintf (F, "loop %d, %d sons, %d nodes",
1477 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1480 static INLINE void dump_loop_info(ir_loop *loop) {
1481 fprintf (F, " info1: \"");
1482 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1483 #if DEBUG_libfirm /* GL @@@ debug analyses */
1484 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1490 dump_loop_node(ir_loop *loop) {
1491 fprintf (F, "node: {title: \"");
1493 fprintf (F, "\" label: \"");
1494 dump_loop_label(loop);
1496 dump_loop_info(loop);
1502 dump_loop_node_edge (ir_loop *loop, int i) {
1504 fprintf (F, "edge: {sourcename: \"");
1506 fprintf (F, "\" targetname: \"");
1507 PRINT_NODEID(get_loop_node(loop, i));
1508 fprintf (F, "\" color: green");
1513 dump_loop_son_edge (ir_loop *loop, int i) {
1515 fprintf (F, "edge: {sourcename: \"");
1517 fprintf (F, "\" targetname: \"");
1518 PRINT_LOOPID(get_loop_son(loop, i));
1519 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1520 get_loop_element_pos(loop, get_loop_son(loop, i)));
1524 void dump_loops (ir_loop *loop) {
1526 /* dump this loop node */
1527 dump_loop_node(loop);
1529 /* dump edges to nodes in loop -- only if it is a real loop */
1530 if (get_loop_depth(loop) != 0) {
1531 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1532 dump_loop_node_edge(loop, i);
1535 for (i = 0; i < get_loop_n_sons(loop); i++) {
1536 dump_loops(get_loop_son(loop, i));
1537 dump_loop_son_edge(loop, i);
1542 void dump_loop_nodes_into_graph(ir_graph *irg) {
1543 ir_graph *rem = current_ir_graph;
1544 current_ir_graph = irg;
1546 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1548 current_ir_graph = rem;
1552 /************************************************************************/
1553 /* open and close vcg file */
1554 /************************************************************************/
1557 dump_vcg_header(const char *name, const char *orientation) {
1566 if (!orientation) orientation = "bottom_to_top";
1570 "graph: { title: \"ir graph of %s\"\n"
1571 "display_edge_labels: %s\n"
1572 "layoutalgorithm: mindepth\n"
1573 "manhattan_edges: yes\n"
1574 "port_sharing: no\n"
1576 "classname 1: \"Data\"\n"
1577 "classname 2: \"Block\"\n"
1578 "classname 13:\"Control Flow\"\n"
1579 "classname 14:\"Memory\"\n"
1580 "classname 15:\"Dominators\"\n"
1581 "classname 3: \"Entity type\"\n"
1582 "classname 4: \"Entity owner\"\n"
1583 "classname 5: \"Method Param\"\n"
1584 "classname 6: \"Method Res\"\n"
1585 "classname 7: \"Super\"\n"
1586 "classname 8: \"Union\"\n"
1587 "classname 9: \"Points-to\"\n"
1588 "classname 10: \"Array Element Type\"\n"
1589 "classname 11: \"Overwrites\"\n"
1590 "classname 12: \"Member\"\n"
1591 "infoname 1: \"Attribute\"\n"
1592 "infoname 2: \"Verification errors\"\n",
1593 name, label, orientation);
1595 fprintf (F, "\n"); /* a separator */
1598 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1599 const char *nm = get_irg_dump_name(irg);
1600 int len = strlen(nm), i, j;
1601 char *fname; /* filename to put the vcg information in */
1603 if (!suffix1) suffix1 = "";
1604 if (!suffix2) suffix2 = "";
1606 /** open file for vcg graph */
1607 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1609 /* strncpy (fname, nm, len); */ /* copy the filename */
1611 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1613 fname[j] = '@'; j++; fname[j] = '1'; j++;
1614 } else if (nm[i] == '@') {
1615 fname[j] = '@'; j++; fname[j] = '2'; j++;
1617 fname[j] = nm[i]; j++;
1621 strcat (fname, suffix1); /* append file suffix */
1622 strcat (fname, suffix2); /* append file suffix */
1623 strcat (fname, ".vcg"); /* append the .vcg suffix */
1624 F = fopen (fname, "w"); /* open file for writing */
1626 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1631 static void vcg_open_name (const char *name, char *suffix) {
1632 char *fname; /* filename to put the vcg information in */
1633 int i, j, len = strlen(name);
1635 if (!suffix) suffix = "";
1637 /** open file for vcg graph */
1638 fname = malloc (len * 2 + 5 + strlen(suffix));
1639 /* strcpy (fname, name);*/ /* copy the filename */
1641 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1642 if (name[i] == '/') {
1643 fname[j] = '@'; j++; fname[j] = '1'; j++;
1644 } else if (name[i] == '@') {
1645 fname[j] = '@'; j++; fname[j] = '2'; j++;
1647 fname[j] = name[i]; j++;
1651 strcat (fname, suffix);
1652 strcat (fname, ".vcg"); /* append the .vcg suffix */
1653 F = fopen (fname, "w"); /* open file for writing */
1655 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1660 static INLINE void dump_vcg_footer (void) {
1666 dump_vcg_footer(); /* print footer */
1667 fclose (F); /* close vcg file */
1670 /************************************************************************/
1671 /************************************************************************/
1672 /* Routines that dump all or parts of the firm representation to a file */
1673 /************************************************************************/
1674 /************************************************************************/
1676 /************************************************************************/
1677 /* Dump ir graphs, differnt formats and additional information. */
1678 /************************************************************************/
1680 /** Routine to dump a graph, blocks as conventional nodes.
1683 dump_ir_graph (ir_graph *irg)
1687 rem = current_ir_graph;
1689 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1691 current_ir_graph = irg;
1692 if (interprocedural_view) suffix = "-pure-ip";
1693 else suffix = "-pure";
1694 vcg_open (irg, dump_file_suffix, suffix);
1695 dump_vcg_header(get_irg_dump_name(irg), NULL);
1697 /* walk over the graph */
1698 /* dump_whole_node must be called in post visiting predecessors */
1699 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1701 /* dump the out edges in a separate walk */
1702 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1703 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1708 current_ir_graph = rem;
1713 dump_ir_block_graph (ir_graph *irg)
1718 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1720 if (interprocedural_view) suffix = "-ip";
1722 vcg_open (irg, dump_file_suffix, suffix);
1723 dump_vcg_header(get_irg_dump_name(irg), NULL);
1725 construct_block_lists(irg);
1727 for (i = 0; i < get_irp_n_irgs(); i++) {
1728 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1730 dump_graph(get_irp_irg(i));
1738 /** dumps a graph with type information
1741 dump_ir_graph_w_types (ir_graph *irg)
1743 ir_graph *rem = current_ir_graph;
1746 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1748 current_ir_graph = irg;
1750 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1751 else suffix = "-pure-wtypes";
1752 vcg_open (irg, dump_file_suffix, suffix);
1753 dump_vcg_header(get_irg_dump_name(irg), NULL);
1755 /* dump common ir graph */
1756 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1757 /* dump type info */
1758 type_walk_irg(irg, dump_type_info, NULL, NULL);
1759 inc_irg_visited(get_const_code_irg());
1760 /* dump edges from graph to type info */
1761 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1764 current_ir_graph = rem;
1768 dump_ir_block_graph_w_types (ir_graph *irg)
1772 ir_graph *rem = current_ir_graph;
1774 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1776 if (interprocedural_view) suffix = "-wtypes-ip";
1777 else suffix = "-wtypes";
1778 vcg_open (irg, dump_file_suffix, suffix);
1779 dump_vcg_header(get_irg_dump_name(irg), NULL);
1781 /* dump common blocked ir graph */
1782 construct_block_lists(irg);
1784 for (i = 0; i < get_irp_n_irgs(); i++) {
1785 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1787 dump_graph(get_irp_irg(i));
1792 /* dump type info */
1793 current_ir_graph = irg;
1794 type_walk_irg(irg, dump_type_info, NULL, NULL);
1795 inc_irg_visited(get_const_code_irg());
1797 /* dump edges from graph to type info */
1798 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1800 current_ir_graph = rem;
1804 /***********************************************************************/
1805 /* The following routines dump a control flow graph. */
1806 /***********************************************************************/
1809 dump_block_to_cfg (ir_node *block, void *env) {
1813 if (is_Block(block)) {
1814 /* This is a block. Dump a node for the block. */
1815 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1816 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1817 PRINT_NODEID(block);
1819 if (dump_dominator_information_flag)
1820 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1822 /* Dump the edges */
1823 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1824 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1825 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1826 fprintf (F, "edge: { sourcename: \"");
1827 PRINT_NODEID(block);
1828 fprintf (F, "\" targetname: \"");
1830 fprintf (F, "\"}\n");
1833 /* Dump dominator edge */
1834 if (dump_dominator_information_flag && get_Block_idom(block)) {
1835 pred = get_Block_idom(block);
1836 fprintf (F, "edge: { sourcename: \"");
1837 PRINT_NODEID(block);
1838 fprintf (F, "\" targetname: \"");
1840 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1846 dump_cfg (ir_graph *irg)
1848 ir_graph *rem = current_ir_graph;
1849 int ddif = dump_dominator_information_flag;
1850 int ipv = interprocedural_view;
1852 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1854 current_ir_graph = irg;
1856 vcg_open (irg, dump_file_suffix, "-cfg");
1857 dump_vcg_header(get_irg_dump_name(irg), NULL);
1859 if (interprocedural_view) {
1860 printf("Warning: dumping cfg not in interprocedural view!\n");
1861 interprocedural_view = 0;
1864 if (get_irg_dom_state(irg) != dom_consistent)
1865 dump_dominator_information_flag = 0;
1867 /* walk over the blocks in the graph */
1868 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1869 dump_node (get_irg_bad(irg));
1871 dump_dominator_information_flag = ddif;
1872 interprocedural_view = ipv;
1874 current_ir_graph = rem;
1879 /* Dump all irgs in interprocedural view to a single file. */
1880 void dump_all_cg_block_graph(void) {
1882 int rem_view = interprocedural_view;
1883 interprocedural_view = 1;
1885 vcg_open_name ("All_graphs", dump_file_suffix);
1886 dump_vcg_header("All_graphs", NULL);
1888 /* collect nodes in all irgs reachable in call graph*/
1889 for (i = 0; i < get_irp_n_irgs(); i++)
1890 ird_set_irg_link(get_irp_irg(i), NULL);
1892 cg_walk(clear_link, collect_node, NULL);
1894 /* dump all graphs */
1895 for (i = 0; i < get_irp_n_irgs(); i++) {
1896 current_ir_graph = get_irp_irg(i);
1897 assert(ird_get_irg_link(current_ir_graph));
1898 dump_graph(current_ir_graph);
1899 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1903 interprocedural_view = rem_view;
1906 /***********************************************************************/
1907 /* the following routines dumps type information without any ir nodes. */
1908 /***********************************************************************/
1911 dump_type_graph (ir_graph *irg)
1914 rem = current_ir_graph;
1916 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1918 current_ir_graph = irg;
1920 vcg_open (irg, dump_file_suffix, "-type");
1921 dump_vcg_header(get_irg_dump_name(irg), NULL);
1923 /* walk over the blocks in the graph */
1924 type_walk_irg(irg, dump_type_info, NULL, NULL);
1925 /* The walker for the const code can be called several times for the
1926 same (sub) experssion. So that no nodes are dumped several times
1927 we decrease the visited flag of the corresponding graph after each
1928 walk. So now increase it finally. */
1929 inc_irg_visited(get_const_code_irg());
1932 current_ir_graph = rem;
1936 dump_all_types (void)
1938 vcg_open_name ("All_types", dump_file_suffix);
1939 dump_vcg_header("All_types", NULL);
1940 type_walk(dump_type_info, NULL, NULL);
1941 inc_irg_visited(get_const_code_irg());
1946 dump_class_hierarchy (bool entities)
1948 vcg_open_name ("class_hierarchy", dump_file_suffix);
1949 dump_vcg_header("class_hierarchy", NULL);
1951 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1953 type_walk(dump_class_hierarchy_node, NULL, NULL);
1957 /***********************************************************************/
1958 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1960 /* dump_ir_block_graph */
1962 /* dump_type_graph */
1963 /* dump_ir_graph_w_types */
1964 /***********************************************************************/
1966 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1968 for (i=0; i < get_irp_n_irgs(); i++) {
1969 dmp_grph(get_irp_irg(i));
1974 /**********************************************************************************
1975 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1976 * packed together in one subgraph *
1977 **********************************************************************************/
1981 void dump_loops_standalone (ir_loop *loop) {
1982 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
1984 ir_loop *son = NULL;
1986 /* Dump a new loop node. */
1987 dump_loop_node(loop);
1989 /* Dump the loop elements. */
1991 for(i = 0; i < get_loop_n_elements(loop); i++)
1993 le = get_loop_element(loop, i);
1995 if (get_kind(son) == k_ir_loop) {
1997 /* We are a loop son -> Recurse */
1999 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2000 fprintf(F, "\" }\n");
2001 fprintf (F, "edge: {sourcename: \"");
2003 fprintf (F, "\" targetname: \"");
2005 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2006 loop_node_started = 0;
2008 dump_loop_son_edge(loop, son_number++);
2009 dump_loops_standalone(son);
2012 /* We are a loop node -> Collect firm nodes */
2014 ir_node *n = le.node;
2016 if (!loop_node_started) {
2017 /* Start a new node which contains all firm nodes of the current loop */
2018 fprintf (F, "node: { title: \"");
2020 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2021 loop_node_started = 1;
2027 dump_node_opcode(F, n);
2029 dump_node_typeinfo(n);
2031 dump_node_nodeattr(n);
2032 fprintf (F, " %ld", get_irn_node_nr(n));
2036 if (loop_node_started) {
2037 fprintf(F, "\" }\n");
2038 fprintf (F, "edge: {sourcename: \"");
2040 fprintf (F, "\" targetname: \"");
2042 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2043 loop_node_started = 0;
2047 void dump_loop_tree(ir_graph *irg, char *suffix)
2049 ir_graph *rem = current_ir_graph;
2050 int el_rem = edge_label;
2053 /* @@@ AS: What does that do? */
2054 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2056 current_ir_graph = irg;
2058 vcg_open(irg, suffix, "-looptree");
2059 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2061 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2065 edge_label = el_rem;
2066 current_ir_graph = rem;
2070 /*******************************************************************************/
2071 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2072 /*******************************************************************************/
2074 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2075 int i, son_number = 0, node_number = 0;
2077 if (dump_loop_information_flag) dump_loop_node(loop);
2079 for (i = 0; i < get_loop_n_elements(loop); i++) {
2080 loop_element le = get_loop_element(loop, i);
2081 if (*(le.kind) == k_ir_loop) {
2082 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2084 collect_nodeloop(le.son, loopnodes);
2086 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2087 eset_insert(loopnodes, le.node);
2092 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2095 for(i = 0; i < get_loop_n_elements(loop); i++) {
2096 loop_element le = get_loop_element(loop, i);
2097 if (*(le.kind) == k_ir_loop) {
2099 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2101 if (is_Block(le.node)) start = 0; else start = -1;
2102 for (j = start; j < get_irn_arity(le.node); j++) {
2103 ir_node *pred = get_irn_n(le.node, j);
2104 if (!eset_contains(loopnodes, pred)) {
2105 eset_insert(extnodes, pred);
2106 if (!is_Block(pred)) {
2107 pred = get_nodes_block(pred);
2108 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2116 void dump_loop (ir_loop *l, char *suffix) {
2118 eset *loopnodes = eset_create();
2119 eset *extnodes = eset_create();
2122 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2123 vcg_open_name (name, suffix);
2124 dump_vcg_header(name, NULL);
2126 /* collect all nodes to dump */
2127 collect_nodeloop(l, loopnodes);
2128 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2130 /* build block lists */
2131 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2132 set_irn_link(n, NULL);
2133 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2134 set_irn_link(n, NULL);
2135 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2137 b = get_nodes_block(n);
2138 set_irn_link(n, get_irn_link(b));
2141 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2143 b = get_nodes_block(n);
2144 set_irn_link(n, get_irn_link(b));
2148 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2150 fprintf(F, "graph: { title: \"");
2152 fprintf(F, "\" label: \"");
2153 dump_node_opcode(F, b);
2154 fprintf (F, " %ld", get_irn_node_nr(b));
2155 fprintf(F, "\" status:clustered color:yellow\n");
2157 /* dump the blocks edges */
2158 dump_ir_data_edges(b);
2160 /* dump the nodes that go into the block */
2161 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2162 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2164 overrule_nodecolor = NULL;
2165 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2168 /* Close the vcg information for the block */
2170 dump_const_node_local(b);
2173 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2175 fprintf(F, "graph: { title: \"");
2177 fprintf(F, "\" label: \"");
2178 dump_node_opcode(F, b);
2179 fprintf (F, " %ld", get_irn_node_nr(b));
2180 fprintf(F, "\" status:clustered color:lightblue\n");
2182 /* dump the nodes that go into the block */
2183 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2184 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2186 overrule_nodecolor = NULL;
2187 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2190 /* Close the vcg information for the block */
2192 dump_const_node_local(b);
2196 eset_destroy(loopnodes);
2197 eset_destroy(extnodes);