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 ir_node *cond = get_Proj_pred(n);
469 if (get_irn_opcode(cond) == iro_Cond
470 && get_Proj_proj(n) == get_Cond_defaultProj(cond)
471 && get_irn_mode(get_Cond_selector(cond)) != mode_b)
472 fprintf (F, "defProj");
474 fprintf (F, "%s", get_irn_opname(n));
478 if (interprocedural_view) {
479 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
485 fprintf (F, "%s", get_irn_opname(n));
493 dump_node_mode (ir_node *n)
495 switch (get_irn_opcode(n)) {
514 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
521 static int dump_node_typeinfo(ir_node *n) {
524 if (opt_dump_analysed_type_info) {
525 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
526 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
527 type *tp = get_irn_type(n);
529 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
538 dump_node_nodeattr (ir_node *n)
542 switch (get_irn_opcode(n)) {
544 if (false && interprocedural_view) {
545 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
549 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
550 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
552 fprintf (F, "%ld", get_Proj_proj(n));
556 fprintf (F, "%ld", get_Filter_proj(n));
559 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
562 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
565 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
575 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
578 fprintf(F, "color: red");
581 switch (get_irn_opcode(n)) {
588 fprintf (F, "color: blue");
591 fprintf (F, "color: lightyellow");
594 fprintf (F, "color: green");
600 fprintf (F, "color: yellow");
603 PRINT_DEFAULT_NODE_ATTR;
606 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
609 static INLINE int dump_node_info(ir_node *n)
615 fprintf (F, " info1: \"");
616 if (opt_dump_pointer_values_to_info)
617 fprintf (F, "addr: %p \n", (void *)n);
618 fprintf (F, "visited: %ld \n", get_irn_visited(n));
619 irg = get_irn_irg(n);
620 if (irg != get_const_code_irg())
621 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
623 fprintf(F, "arity: %d", get_irn_arity(n));
624 if ((get_irn_op(n) == op_Block) ||
625 (get_irn_op(n) == op_Phi) ||
626 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
627 fprintf(F, " backedges:");
629 for (i = 0; i < get_irn_arity(n); i++)
630 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
634 /* Loop node Someone else please tell me what's wrong ...
635 if (get_irn_loop(n)) {
636 ir_loop *loop = get_irn_loop(n);
638 fprintf(F, " in loop %d with depth %d\n",
639 get_loop_loop_nr(loop), get_loop_depth(loop));
644 switch (get_irn_opcode(n)) {
646 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
647 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
648 for (i = 0; i < get_method_n_params(tp); ++i)
649 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
652 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
655 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
658 entity *ent = get_Sel_entity(n);
661 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
662 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
665 fprintf(F, "<NULL entity>\n");
670 type *tp = get_Call_type(n);
671 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
672 for (i = 0; i < get_method_n_params(tp); ++i)
673 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
674 for (i = 0; i < get_method_n_ress(tp); ++i)
675 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
676 if (Call_has_callees(n)) {
677 fprintf(F, "possible callees: \n");
678 for (i = 0; i < get_Call_n_callees(n); i++) {
679 if (!get_Call_callee(n, i)) {
680 fprintf(F, " %d external method\n", i);
682 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
687 case iro_CallBegin: {
688 ir_node *call = get_CallBegin_call(n);
689 if (Call_has_callees(call)) {
690 fprintf(F, "possible callees: \n");
691 for (i = 0; i < get_Call_n_callees(call); i++) {
692 if (!get_Call_callee(call, i)) {
693 fprintf(F, " %d external method\n", i);
695 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
701 if (!interprocedural_view) {
702 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
703 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
704 for (i = 0; i < get_method_n_ress(tp); ++i)
705 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
709 type *tp = get_Const_type(n);
710 assert(tp != none_type);
711 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
715 if (interprocedural_view) {
716 fprintf(F, "intra predecessor nodes:\n");
717 for (i = 0; i < get_irn_intra_arity(n); i++) {
718 ir_node *pred = get_irn_intra_n(n, i);
719 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
722 fprintf(F, "inter predecessor nodes:\n");
723 for (i = 0; i < get_irn_inter_arity(n); i++) {
724 ir_node *pred = get_irn_inter_n(n, i);
725 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
726 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
733 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
734 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
735 if (get_irn_type(n) != none_type)
736 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
745 bool is_constlike_node(ir_node *n) {
746 ir_op *op = get_irn_op(n);
747 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
751 /* outputs the predecessors of n, that are constants, local. I.e.,
752 generates a copy of the constant predecessors for each node called with. */
753 static void dump_const_node_local(ir_node *n) {
755 if (!get_opt_dump_const_local()) return;
757 /* Use visited flag to avoid outputting nodes twice.
758 initialize it first. */
759 for (i = 0; i < get_irn_arity(n); i++) {
760 ir_node *con = get_irn_n(n, i);
761 if (is_constlike_node(con)) {
762 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
766 for (i = 0; i < get_irn_arity(n); i++) {
767 ir_node *con = get_irn_n(n, i);
768 if (is_constlike_node(con) && irn_not_visited(con)) {
771 mark_irn_visited(con);
772 /* Generate a new name for the node by appending the names of
774 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
775 fprintf(F, " label: \"");
776 bad |= dump_node_opcode(F, con);
777 dump_node_mode (con);
778 bad |= dump_node_typeinfo(con);
780 bad |= dump_node_nodeattr(con);
781 fprintf(F, " %ld", get_irn_node_nr(con));
783 bad |= dump_node_info(con);
784 dump_node_vcgattr(con, bad);
790 static void print_node_error(const char *p)
795 fprintf (F, " info2: \"%s\"", p);
798 static void dump_node(ir_node *n)
803 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
805 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
807 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
808 bad |= dump_node_opcode(F, n);
810 bad |= dump_node_typeinfo(n);
812 bad |= dump_node_nodeattr(n);
813 fprintf(F, " %ld", get_irn_node_nr(n));
815 bad |= dump_node_info(n);
817 dump_node_vcgattr(n, bad);
819 dump_const_node_local(n);
826 /* dump the edge to the block this node belongs to */
828 dump_ir_block_edge(ir_node *n) {
829 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
830 if (is_no_Block(n)) {
831 fprintf (F, "edge: { sourcename: \"");
833 fprintf (F, "\" targetname: \"");
834 PRINT_NODEID(get_nodes_block(n));
835 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
840 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
841 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
842 fprintf (F, INTRA_DATA_EDGE_ATTR);
844 fprintf (F, INTER_DATA_EDGE_ATTR);
848 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
849 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
850 fprintf (F, INTRA_MEM_EDGE_ATTR);
852 fprintf (F, INTER_MEM_EDGE_ATTR);
856 print_edge_vcgattr(ir_node *from, int to) {
859 if (dump_backedge_information_flag && is_backedge(from, to))
860 fprintf (F, BACK_EDGE_ATTR);
862 switch (get_irn_opcode(from)) {
864 fprintf (F, CF_EDGE_ATTR);
866 case iro_Start: break;
869 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
870 fprintf (F, CF_EDGE_ATTR);
871 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
872 fprintf (F, INTER_MEM_EDGE_ATTR);
880 print_data_edge_vcgattr(F, from, to);
885 print_mem_edge_vcgattr(F, from, to);
887 print_data_edge_vcgattr(F, from, to);
891 print_data_edge_vcgattr(F, from, to);
896 print_mem_edge_vcgattr(F, from, to);
898 print_data_edge_vcgattr(F, from, to);
905 print_data_edge_vcgattr(F, from, to);
912 print_mem_edge_vcgattr(F, from, to);
914 print_data_edge_vcgattr(F, from, to);
926 print_data_edge_vcgattr(F, from, to);
929 if (get_irn_modecode(from) == irm_M)
930 fprintf (F, INTER_MEM_EDGE_ATTR);
932 print_data_edge_vcgattr(F, from, to);
939 print_mem_edge_vcgattr(F, from, to);
941 print_data_edge_vcgattr(F, from, to);
944 print_mem_edge_vcgattr(F, from, to);
946 case iro_Tuple: break;
949 switch (get_irn_modecode(from)) {
951 fprintf (F, CF_EDGE_ATTR);
954 fprintf (F, INTER_MEM_EDGE_ATTR);
957 print_data_edge_vcgattr(F, from, to);
962 case iro_Unknown: break;
969 /* dump edges to our inputs */
971 dump_ir_data_edges(ir_node *n) {
972 int i, visited = get_irn_visited(n);
974 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
977 for (i = 0; i < get_irn_arity(n); i++) {
978 ir_node * pred = get_irn_n(n, i);
981 if ((interprocedural_view && get_irn_visited(pred) < visited))
982 continue; /* pred not dumped */
984 if (dump_backedge_information_flag && is_backedge(n, i))
985 fprintf (F, "backedge: {sourcename: \"");
987 fprintf (F, "edge: {sourcename: \"");
989 fprintf (F, "\" targetname: ");
990 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
991 PRINT_CONSTID(n, pred);
993 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
995 fprintf (F, " label: \"%d\" ", i);
996 print_edge_vcgattr(n, i);
1001 /** Dumps a node and its edges but not the block edge
1004 dump_node_wo_blockedge (ir_node *n, void* env) {
1006 dump_ir_data_edges(n);
1009 /** Dumps a node and its edges.
1012 dump_whole_node (ir_node *n, void* env) {
1013 dump_node_wo_blockedge(n, env);
1014 if (!node_floats(n)) dump_ir_block_edge(n);
1018 dump_const_node(ir_node *n, void *env) {
1019 if (is_Block(n)) return;
1020 dump_node_wo_blockedge(n, env);
1023 /***********************************************************************/
1024 /* the following routines dump the nodes/irgs bracketed to graphs. */
1025 /***********************************************************************/
1027 /** Dumps a constant expression as entity initializer, array bound ...
1029 static void dump_const_expression(ir_node *value) {
1030 ir_graph *rem = current_ir_graph;
1031 int rem_dump_const_local = dump_const_local;
1032 dump_const_local = 0;
1033 current_ir_graph = get_const_code_irg();
1034 irg_walk(value, dump_const_node, NULL, NULL);
1035 /* Decrease visited flag so that we walk with the same flag for the next
1036 expresssion. This guarantees that we don't dump the same node twice,
1037 as for const expressions cse is performed to save memory. */
1038 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1039 current_ir_graph = rem;
1040 dump_const_local = rem_dump_const_local;
1043 /** Dump a block as graph containing its nodes.
1045 * Expects to find nodes belonging to the block as list in its
1047 * Dumps the edges of all nodes including itself. */
1049 dump_whole_block(ir_node *block) {
1051 assert(is_Block(block));
1053 fprintf(F, "graph: { title: \"");
1054 PRINT_NODEID(block);
1055 fprintf(F, "\" label: \"");
1056 dump_node_opcode(F, block);
1057 fprintf (F, " %ld", get_irn_node_nr(block));
1059 if (get_opt_dump_abstvals())
1060 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1062 fprintf(F, "\" status:clustered color:%s \n",
1063 get_Block_matured(block) ? "yellow" : "red");
1065 /* dump the blocks edges */
1066 dump_ir_data_edges(block);
1068 /* dump the nodes that go into the block */
1069 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1071 dump_ir_data_edges(node);
1074 /* Close the vcg information for the block */
1076 dump_const_node_local(block);
1078 dump_chi_term(F, block);
1083 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1084 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1086 dump_block_graph(ir_graph *irg) {
1088 ir_graph *rem = current_ir_graph;
1089 ir_node **arr = ird_get_irg_link(irg);
1090 current_ir_graph = irg;
1092 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1093 ir_node * node = arr[i];
1094 if (is_Block(node)) {
1095 /* Dumps the block and all the nodes in the block, which are to
1096 be found in Block->link. */
1097 dump_whole_block(node);
1099 /* Nodes that are not in a Block. */
1101 dump_ir_data_edges(node);
1105 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1107 current_ir_graph = rem;
1110 /** Dumps an irg as a graph.
1111 * If interprocedural view edges can point to nodes out of this graph.
1113 static void dump_graph(ir_graph *irg) {
1115 fprintf(F, "graph: { title: \"");
1117 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1118 get_ent_dump_name(get_irg_ent(irg)));
1120 dump_block_graph (irg);
1122 /* Close the vcg information for the irg */
1123 fprintf(F, "}\n\n");
1126 /*******************************************************************/
1127 /* Basic type and entity nodes and edges. */
1128 /*******************************************************************/
1130 /* dumps the edges between nodes and their type or entity attributes. */
1131 static void dump_node2type_edges (ir_node *n, void *env)
1135 switch (get_irn_opcode(n)) {
1137 /* @@@ some consts have an entity */
1140 if ( (get_SymConst_kind(n) == type_tag)
1141 || (get_SymConst_kind(n) == size))
1143 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1147 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1150 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1153 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1156 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1159 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1167 static void print_type_info(type *tp) {
1168 if (get_type_state(tp) == layout_undefined) {
1169 fprintf(F, "state: layout_undefined\n");
1171 fprintf(F, "state: layout_fixed,\n");
1173 if (get_type_mode(tp))
1174 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1175 fprintf(F, "size: %dB,\n", get_type_size(tp));
1178 static void print_typespecific_info(type *tp) {
1179 switch (get_type_tpop_code(tp)) {
1182 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1189 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1190 fprintf(F, "params: %d\n", get_method_n_params(tp));
1191 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1199 case tpo_enumeration:
1213 static void print_typespecific_vcgattr(type *tp) {
1214 switch (get_type_tpop_code(tp)) {
1217 if (peculiarity_existent == get_class_peculiarity(tp))
1218 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1220 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1224 fprintf (F, " " TYPE_METH_NODE_ATTR);
1235 case tpo_enumeration:
1248 static int print_type_node(type *tp)
1252 fprintf (F, "node: {title: ");
1254 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1255 fprintf (F, " info1: \"");
1256 print_type_info(tp);
1257 print_typespecific_info(tp);
1259 print_typespecific_vcgattr(tp);
1265 #define X(a) case a: fprintf(F, #a); break
1266 void dump_entity_node(entity *ent)
1268 fprintf (F, "node: {title: \"");
1269 PRINT_ENTID(ent); fprintf(F, "\"");
1270 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1271 fprintf (F, "label: ");
1272 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1273 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1275 fprintf (F, "\nallocation: ");
1276 switch (get_entity_allocation(ent)) {
1277 X(allocation_dynamic);
1278 X(allocation_automatic);
1279 X(allocation_static);
1280 X(allocation_parameter);
1283 fprintf (F, "\nvisibility: ");
1284 switch (get_entity_visibility(ent)) {
1285 X(visibility_local);
1286 X(visibility_external_visible);
1287 X(visibility_external_allocated);
1290 fprintf (F, "\nvariability: ");
1291 switch (get_entity_variability(ent)) {
1292 X(variability_uninitialized);
1293 X(variability_initialized);
1294 X(variability_part_constant);
1295 X(variability_constant);
1298 fprintf (F, "\nvolatility: ");
1299 switch (get_entity_volatility(ent)) {
1300 X(volatility_non_volatile);
1301 X(volatility_is_volatile);
1304 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1305 fprintf(F, "\nname: %s\nld_name: %s",
1306 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1307 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1308 if (is_method_type(get_entity_type(ent))) {
1309 if (get_entity_irg(ent)) /* can be null */
1310 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1312 { fprintf (F, "\nirg = NULL"); }
1314 fprintf(F, "\"\n}\n");
1318 static void dump_enum_item(type *tp, int pos)
1321 ident *id = get_enumeration_nameid(tp, pos);
1322 tarval *tv = get_enumeration_enum(tp, pos);
1324 tarval_snprintf(buf, sizeof(buf), tv);
1325 fprintf (F, "node: {title: \"");
1326 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1327 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1328 fprintf (F, "label: ");
1329 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1330 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1333 /* dumps a type or entity and it's edges. */
1335 dump_type_info (type_or_ent *tore, void *env) {
1336 int i = 0; /* to shutup gcc */
1338 /* dump this type or entity */
1340 switch (get_kind(tore)) {
1343 entity *ent = (entity *)tore;
1346 dump_entity_node(ent);
1348 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1349 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1350 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1351 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1352 if(is_class_type(get_entity_owner(ent))) {
1353 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1354 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1357 /* attached subgraphs */
1358 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1359 if (is_atomic_entity(ent)) {
1360 value = get_atomic_ent_value(ent);
1362 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1363 /* DDMN(value); $$$ */
1364 dump_const_expression(value);
1367 if (is_compound_entity(ent)) {
1368 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1369 value = get_compound_ent_value(ent, i);
1371 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1372 dump_const_expression(value);
1373 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1375 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1376 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1377 get_compound_ent_value_member(ent, i), i);
1386 type *tp = (type *)tore;
1387 print_type_node(tp);
1388 /* and now the edges */
1389 switch (get_type_tpop_code(tp)) {
1392 for (i=0; i < get_class_n_supertypes(tp); i++) {
1393 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1396 for (i=0; i < get_class_n_members(tp); i++) {
1397 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1402 for (i=0; i < get_struct_n_members(tp); i++) {
1403 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1408 for (i = 0; i < get_method_n_params(tp); i++)
1410 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1412 for (i = 0; i < get_method_n_ress(tp); i++)
1414 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1419 for (i = 0; i < get_union_n_members(tp); i++)
1421 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1426 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1427 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1428 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1429 ir_node *upper = get_array_upper_bound(tp, i);
1430 ir_node *lower = get_array_lower_bound(tp, i);
1431 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1432 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1433 dump_const_expression(upper);
1434 dump_const_expression(lower);
1438 case tpo_enumeration:
1440 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1441 dump_enum_item(tp, i);
1442 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1447 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1455 break; /* case k_type */
1458 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1460 } /* switch kind_or_entity */
1463 /** For dumping class hierarchies.
1464 * Dumps a class type node and a superclass edge.
1465 * If env != null dumps entities of classes and overwrites edges.
1468 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1469 int i = 0; /* to shutup gcc */
1471 /* dump this type or entity */
1472 switch (get_kind(tore)) {
1474 entity *ent = (entity *)tore;
1475 if (get_entity_owner(ent) == get_glob_type()) break;
1476 if ((env) && is_class_type(get_entity_owner(ent))) {
1478 dump_entity_node(ent);
1480 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1481 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1483 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1486 } break; /* case k_entity */
1489 type *tp = (type *)tore;
1490 if (tp == get_glob_type()) break;
1491 switch (get_type_tpop_code(tp)) {
1493 print_type_node(tp);
1494 /* and now the edges */
1495 for (i=0; i < get_class_n_supertypes(tp); i++)
1497 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1503 break; /* case k_type */
1506 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1508 } /* switch kind_or_entity */
1511 /*******************************************************************/
1512 /* dump analysis information that is expressed in graph terms. */
1513 /*******************************************************************/
1515 /* dump out edges */
1517 dump_out_edge (ir_node *n, void* env) {
1519 for (i = 0; i < get_irn_n_outs(n); i++) {
1520 assert(get_irn_out(n, i));
1521 fprintf (F, "edge: {sourcename: \"");
1523 fprintf (F, "\" targetname: \"");
1524 PRINT_NODEID(get_irn_out(n, i));
1525 fprintf (F, "\" color: red linestyle: dashed");
1531 dump_loop_label(ir_loop *loop) {
1532 fprintf (F, "loop %d, %d sons, %d nodes",
1533 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1536 static INLINE void dump_loop_info(ir_loop *loop) {
1537 fprintf (F, " info1: \"");
1538 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1539 #if DEBUG_libfirm /* GL @@@ debug analyses */
1540 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1546 dump_loop_node(ir_loop *loop) {
1547 fprintf (F, "node: {title: \"");
1549 fprintf (F, "\" label: \"");
1550 dump_loop_label(loop);
1552 dump_loop_info(loop);
1558 dump_loop_node_edge (ir_loop *loop, int i) {
1560 fprintf (F, "edge: {sourcename: \"");
1562 fprintf (F, "\" targetname: \"");
1563 PRINT_NODEID(get_loop_node(loop, i));
1564 fprintf (F, "\" color: green");
1569 dump_loop_son_edge (ir_loop *loop, int i) {
1571 fprintf (F, "edge: {sourcename: \"");
1573 fprintf (F, "\" targetname: \"");
1574 PRINT_LOOPID(get_loop_son(loop, i));
1575 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1576 get_loop_element_pos(loop, get_loop_son(loop, i)));
1580 void dump_loops (ir_loop *loop) {
1582 /* dump this loop node */
1583 dump_loop_node(loop);
1585 /* dump edges to nodes in loop -- only if it is a real loop */
1586 if (get_loop_depth(loop) != 0) {
1587 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1588 dump_loop_node_edge(loop, i);
1591 for (i = 0; i < get_loop_n_sons(loop); i++) {
1592 dump_loops(get_loop_son(loop, i));
1593 dump_loop_son_edge(loop, i);
1598 void dump_loop_nodes_into_graph(ir_graph *irg) {
1599 ir_graph *rem = current_ir_graph;
1600 current_ir_graph = irg;
1602 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1604 current_ir_graph = rem;
1608 /************************************************************************/
1609 /* open and close vcg file */
1610 /************************************************************************/
1613 dump_vcg_header(const char *name, const char *orientation) {
1622 if (!orientation) orientation = "bottom_to_top";
1626 "graph: { title: \"ir graph of %s\"\n"
1627 "display_edge_labels: %s\n"
1628 "layoutalgorithm: mindepth\n"
1629 "manhattan_edges: yes\n"
1630 "port_sharing: no\n"
1632 "classname 1: \"intrablock Data\"\n"
1633 "classname 16: \"interblock Data\"\n"
1634 "classname 2: \"Block\"\n"
1635 "classname 13: \"Control Flow\"\n"
1636 "classname 14: \"intrablock Memory\"\n"
1637 "classname 17: \"interblock Memory\"\n"
1638 "classname 15: \"Dominators\"\n"
1639 "classname 3: \"Entity type\"\n"
1640 "classname 4: \"Entity owner\"\n"
1641 "classname 5: \"Method Param\"\n"
1642 "classname 6: \"Method Res\"\n"
1643 "classname 7: \"Super\"\n"
1644 "classname 8: \"Union\"\n"
1645 "classname 9: \"Points-to\"\n"
1646 "classname 10: \"Array Element Type\"\n"
1647 "classname 11: \"Overwrites\"\n"
1648 "classname 12: \"Member\"\n"
1649 "infoname 1: \"Attribute\"\n"
1650 "infoname 2: \"Verification errors\"\n",
1651 name, label, orientation);
1653 fprintf (F, "\n"); /* a separator */
1656 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1657 const char *nm = get_irg_dump_name(irg);
1658 int len = strlen(nm), i, j;
1659 char *fname; /* filename to put the vcg information in */
1661 if (!suffix1) suffix1 = "";
1662 if (!suffix2) suffix2 = "";
1664 /** open file for vcg graph */
1665 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1667 /* strncpy (fname, nm, len); */ /* copy the filename */
1669 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1671 fname[j] = '@'; j++; fname[j] = '1'; j++;
1672 } else if (nm[i] == '@') {
1673 fname[j] = '@'; j++; fname[j] = '2'; j++;
1675 fname[j] = nm[i]; j++;
1679 strcat (fname, suffix1); /* append file suffix */
1680 strcat (fname, suffix2); /* append file suffix */
1681 strcat (fname, ".vcg"); /* append the .vcg suffix */
1682 F = fopen (fname, "w"); /* open file for writing */
1684 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1689 static void vcg_open_name (const char *name, char *suffix) {
1690 char *fname; /* filename to put the vcg information in */
1691 int i, j, len = strlen(name);
1693 if (!suffix) suffix = "";
1695 /** open file for vcg graph */
1696 fname = malloc (len * 2 + 5 + strlen(suffix));
1697 /* strcpy (fname, name);*/ /* copy the filename */
1699 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1700 if (name[i] == '/') {
1701 fname[j] = '@'; j++; fname[j] = '1'; j++;
1702 } else if (name[i] == '@') {
1703 fname[j] = '@'; j++; fname[j] = '2'; j++;
1705 fname[j] = name[i]; j++;
1709 strcat (fname, suffix);
1710 strcat (fname, ".vcg"); /* append the .vcg suffix */
1711 F = fopen (fname, "w"); /* open file for writing */
1713 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1718 static INLINE void dump_vcg_footer (void) {
1724 dump_vcg_footer(); /* print footer */
1725 fclose (F); /* close vcg file */
1728 /************************************************************************/
1729 /************************************************************************/
1730 /* Routines that dump all or parts of the firm representation to a file */
1731 /************************************************************************/
1732 /************************************************************************/
1734 /************************************************************************/
1735 /* Dump ir graphs, differnt formats and additional information. */
1736 /************************************************************************/
1738 /** Routine to dump a graph, blocks as conventional nodes.
1741 dump_ir_graph (ir_graph *irg)
1745 rem = current_ir_graph;
1747 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1749 current_ir_graph = irg;
1750 if (interprocedural_view) suffix = "-pure-ip";
1751 else suffix = "-pure";
1752 vcg_open (irg, dump_file_suffix, suffix);
1753 dump_vcg_header(get_irg_dump_name(irg), NULL);
1755 /* walk over the graph */
1756 /* dump_whole_node must be called in post visiting predecessors */
1757 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1759 /* dump the out edges in a separate walk */
1760 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1761 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1766 current_ir_graph = rem;
1771 dump_ir_block_graph (ir_graph *irg)
1776 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1778 if (interprocedural_view) suffix = "-ip";
1780 vcg_open (irg, dump_file_suffix, suffix);
1781 dump_vcg_header(get_irg_dump_name(irg), NULL);
1783 construct_block_lists(irg);
1785 for (i = 0; i < get_irp_n_irgs(); i++) {
1786 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1788 dump_graph(get_irp_irg(i));
1796 /** dumps a graph with type information
1799 dump_ir_graph_w_types (ir_graph *irg)
1801 ir_graph *rem = current_ir_graph;
1804 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1806 current_ir_graph = irg;
1808 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1809 else suffix = "-pure-wtypes";
1810 vcg_open (irg, dump_file_suffix, suffix);
1811 dump_vcg_header(get_irg_dump_name(irg), NULL);
1813 /* dump common ir graph */
1814 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1815 /* dump type info */
1816 type_walk_irg(irg, dump_type_info, NULL, NULL);
1817 inc_irg_visited(get_const_code_irg());
1818 /* dump edges from graph to type info */
1819 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1822 current_ir_graph = rem;
1826 dump_ir_block_graph_w_types (ir_graph *irg)
1830 ir_graph *rem = current_ir_graph;
1832 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1834 if (interprocedural_view) suffix = "-wtypes-ip";
1835 else suffix = "-wtypes";
1836 vcg_open (irg, dump_file_suffix, suffix);
1837 dump_vcg_header(get_irg_dump_name(irg), NULL);
1839 /* dump common blocked ir graph */
1840 construct_block_lists(irg);
1842 for (i = 0; i < get_irp_n_irgs(); i++) {
1843 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1845 dump_graph(get_irp_irg(i));
1850 /* dump type info */
1851 current_ir_graph = irg;
1852 type_walk_irg(irg, dump_type_info, NULL, NULL);
1853 inc_irg_visited(get_const_code_irg());
1855 /* dump edges from graph to type info */
1856 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1858 current_ir_graph = rem;
1862 /***********************************************************************/
1863 /* The following routines dump a control flow graph. */
1864 /***********************************************************************/
1867 dump_block_to_cfg (ir_node *block, void *env) {
1871 if (is_Block(block)) {
1872 /* This is a block. Dump a node for the block. */
1873 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1874 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1875 PRINT_NODEID(block);
1877 if (dump_dominator_information_flag)
1878 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1880 /* Dump the edges */
1881 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1882 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1883 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1884 fprintf (F, "edge: { sourcename: \"");
1885 PRINT_NODEID(block);
1886 fprintf (F, "\" targetname: \"");
1888 fprintf (F, "\"}\n");
1891 /* Dump dominator edge */
1892 if (dump_dominator_information_flag && get_Block_idom(block)) {
1893 pred = get_Block_idom(block);
1894 fprintf (F, "edge: { sourcename: \"");
1895 PRINT_NODEID(block);
1896 fprintf (F, "\" targetname: \"");
1898 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1904 dump_cfg (ir_graph *irg)
1906 ir_graph *rem = current_ir_graph;
1907 int ddif = dump_dominator_information_flag;
1908 int ipv = interprocedural_view;
1910 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1912 current_ir_graph = irg;
1914 vcg_open (irg, dump_file_suffix, "-cfg");
1915 dump_vcg_header(get_irg_dump_name(irg), NULL);
1917 if (interprocedural_view) {
1918 printf("Warning: dumping cfg not in interprocedural view!\n");
1919 interprocedural_view = 0;
1922 if (get_irg_dom_state(irg) != dom_consistent)
1923 dump_dominator_information_flag = 0;
1925 /* walk over the blocks in the graph */
1926 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1927 dump_node (get_irg_bad(irg));
1929 dump_dominator_information_flag = ddif;
1930 interprocedural_view = ipv;
1932 current_ir_graph = rem;
1937 /* Dump all irgs in interprocedural view to a single file. */
1938 void dump_all_cg_block_graph(void) {
1940 int rem_view = interprocedural_view;
1941 interprocedural_view = 1;
1943 vcg_open_name ("All_graphs", dump_file_suffix);
1944 dump_vcg_header("All_graphs", NULL);
1946 /* collect nodes in all irgs reachable in call graph*/
1947 for (i = 0; i < get_irp_n_irgs(); i++)
1948 ird_set_irg_link(get_irp_irg(i), NULL);
1950 cg_walk(clear_link, collect_node, NULL);
1952 /* dump all graphs */
1953 for (i = 0; i < get_irp_n_irgs(); i++) {
1954 current_ir_graph = get_irp_irg(i);
1955 assert(ird_get_irg_link(current_ir_graph));
1956 dump_graph(current_ir_graph);
1957 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1961 interprocedural_view = rem_view;
1964 /***********************************************************************/
1965 /* the following routines dumps type information without any ir nodes. */
1966 /***********************************************************************/
1969 dump_type_graph (ir_graph *irg)
1972 rem = current_ir_graph;
1974 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1976 current_ir_graph = irg;
1978 vcg_open (irg, dump_file_suffix, "-type");
1979 dump_vcg_header(get_irg_dump_name(irg), NULL);
1981 /* walk over the blocks in the graph */
1982 type_walk_irg(irg, dump_type_info, NULL, NULL);
1983 /* The walker for the const code can be called several times for the
1984 same (sub) experssion. So that no nodes are dumped several times
1985 we decrease the visited flag of the corresponding graph after each
1986 walk. So now increase it finally. */
1987 inc_irg_visited(get_const_code_irg());
1990 current_ir_graph = rem;
1994 dump_all_types (void)
1996 vcg_open_name ("All_types", dump_file_suffix);
1997 dump_vcg_header("All_types", NULL);
1998 type_walk(dump_type_info, NULL, NULL);
1999 inc_irg_visited(get_const_code_irg());
2004 dump_class_hierarchy (bool entities)
2006 vcg_open_name ("class_hierarchy", dump_file_suffix);
2007 dump_vcg_header("class_hierarchy", NULL);
2009 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2011 type_walk(dump_class_hierarchy_node, NULL, NULL);
2015 /***********************************************************************/
2016 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2018 /* dump_ir_block_graph */
2020 /* dump_type_graph */
2021 /* dump_ir_graph_w_types */
2022 /***********************************************************************/
2024 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2026 for (i=0; i < get_irp_n_irgs(); i++) {
2027 dmp_grph(get_irp_irg(i));
2032 /**********************************************************************************
2033 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2034 * packed together in one subgraph *
2035 **********************************************************************************/
2039 void dump_loops_standalone (ir_loop *loop) {
2040 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2042 ir_loop *son = NULL;
2044 /* Dump a new loop node. */
2045 dump_loop_node(loop);
2047 /* Dump the loop elements. */
2049 for(i = 0; i < get_loop_n_elements(loop); i++)
2051 le = get_loop_element(loop, i);
2053 if (get_kind(son) == k_ir_loop) {
2055 /* We are a loop son -> Recurse */
2057 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2058 fprintf(F, "\" }\n");
2059 fprintf (F, "edge: {sourcename: \"");
2061 fprintf (F, "\" targetname: \"");
2063 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2064 loop_node_started = 0;
2066 dump_loop_son_edge(loop, son_number++);
2067 dump_loops_standalone(son);
2070 /* We are a loop node -> Collect firm nodes */
2072 ir_node *n = le.node;
2074 if (!loop_node_started) {
2075 /* Start a new node which contains all firm nodes of the current loop */
2076 fprintf (F, "node: { title: \"");
2078 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2079 loop_node_started = 1;
2085 dump_node_opcode(F, n);
2087 dump_node_typeinfo(n);
2089 dump_node_nodeattr(n);
2090 fprintf (F, " %ld", get_irn_node_nr(n));
2094 if (loop_node_started) {
2095 fprintf(F, "\" }\n");
2096 fprintf (F, "edge: {sourcename: \"");
2098 fprintf (F, "\" targetname: \"");
2100 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2101 loop_node_started = 0;
2105 void dump_loop_tree(ir_graph *irg, char *suffix)
2107 ir_graph *rem = current_ir_graph;
2108 int el_rem = edge_label;
2111 /* @@@ AS: What does that do? */
2112 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2114 current_ir_graph = irg;
2116 vcg_open(irg, suffix, "-looptree");
2117 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2119 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2123 edge_label = el_rem;
2124 current_ir_graph = rem;
2128 /*******************************************************************************/
2129 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2130 /*******************************************************************************/
2132 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2133 int i, son_number = 0, node_number = 0;
2135 if (dump_loop_information_flag) dump_loop_node(loop);
2137 for (i = 0; i < get_loop_n_elements(loop); i++) {
2138 loop_element le = get_loop_element(loop, i);
2139 if (*(le.kind) == k_ir_loop) {
2140 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2142 collect_nodeloop(le.son, loopnodes);
2144 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2145 eset_insert(loopnodes, le.node);
2150 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2153 for(i = 0; i < get_loop_n_elements(loop); i++) {
2154 loop_element le = get_loop_element(loop, i);
2155 if (*(le.kind) == k_ir_loop) {
2157 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2159 if (is_Block(le.node)) start = 0; else start = -1;
2160 for (j = start; j < get_irn_arity(le.node); j++) {
2161 ir_node *pred = get_irn_n(le.node, j);
2162 if (!eset_contains(loopnodes, pred)) {
2163 eset_insert(extnodes, pred);
2164 if (!is_Block(pred)) {
2165 pred = get_nodes_block(pred);
2166 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2174 void dump_loop (ir_loop *l, char *suffix) {
2176 eset *loopnodes = eset_create();
2177 eset *extnodes = eset_create();
2180 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2181 vcg_open_name (name, suffix);
2182 dump_vcg_header(name, NULL);
2184 /* collect all nodes to dump */
2185 collect_nodeloop(l, loopnodes);
2186 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2188 /* build block lists */
2189 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2190 set_irn_link(n, NULL);
2191 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2192 set_irn_link(n, NULL);
2193 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2195 b = get_nodes_block(n);
2196 set_irn_link(n, get_irn_link(b));
2199 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2201 b = get_nodes_block(n);
2202 set_irn_link(n, get_irn_link(b));
2206 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2208 fprintf(F, "graph: { title: \"");
2210 fprintf(F, "\" label: \"");
2211 dump_node_opcode(F, b);
2212 fprintf (F, " %ld", get_irn_node_nr(b));
2213 fprintf(F, "\" status:clustered color:yellow\n");
2215 /* dump the blocks edges */
2216 dump_ir_data_edges(b);
2218 /* dump the nodes that go into the block */
2219 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2220 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2222 overrule_nodecolor = NULL;
2223 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2226 /* Close the vcg information for the block */
2228 dump_const_node_local(b);
2231 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2233 fprintf(F, "graph: { title: \"");
2235 fprintf(F, "\" label: \"");
2236 dump_node_opcode(F, b);
2237 fprintf (F, " %ld", get_irn_node_nr(b));
2238 fprintf(F, "\" status:clustered color:lightblue\n");
2240 /* dump the nodes that go into the block */
2241 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2242 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2244 overrule_nodecolor = NULL;
2245 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2248 /* Close the vcg information for the block */
2250 dump_const_node_local(b);
2254 eset_destroy(loopnodes);
2255 eset_destroy(extnodes);