3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
23 #include "irgraph_t.h"
27 #include "firm_common_t.h"
34 #include "type_or_entity.h"
38 #include "callgraph.h"
48 void dump_chi_term(FILE *FL, ir_node *n);
49 void dump_state(FILE *FL, ir_node *n);
50 int get_opt_dump_abstvals(void);
51 typedef unsigned long SeqNo;
52 SeqNo get_Block_seqno(ir_node *n);
55 /* Attributes of nodes */
56 #define PRINT_DEFAULT_NODE_ATTR
57 #define DEFAULT_NODE_ATTR " "
58 #define DEFAULT_TYPE_ATTRIBUTE " "
59 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
61 /* Attributes of edges between Firm nodes */
62 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
63 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
64 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
65 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
66 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
67 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
68 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
70 #define BACK_EDGE_ATTR "linestyle:dashed "
72 /* Attributes of edges between Firm nodes and type/entity nodes */
73 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
75 /* Attributes of edges in type/entity graphs. */
76 #define TYPE_METH_NODE_ATTR "color: lightyellow"
77 #define TYPE_CLASS_NODE_ATTR "color: green"
78 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
79 #define ENTITY_NODE_ATTR "color: yellow"
80 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
81 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
82 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
83 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
84 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
85 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
86 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
87 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
88 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
89 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
90 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
91 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
92 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
93 #define ENUM_ITEM_NODE_ATTR "color: green"
94 #define CALLGRAPH_EDGE_ATTR "calls"
96 #if DEBUG_libfirm && NODEID_AS_LABEL
97 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
98 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
99 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
100 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
101 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
102 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
103 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
106 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
107 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
108 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
109 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
110 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
111 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
112 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
116 int my_special_flag = 0;
118 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
121 return get_mode_name(mode);
126 static const char *get_type_name_ex(type *tp, int *bad)
129 return get_type_name(tp);
134 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
139 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
140 fprintf(F, " targetname: "); PRINT_TYPEID(T);
141 vfprintf(F, fmt, ap);
146 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
151 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
152 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
153 vfprintf(F, fmt, ap);
158 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
164 fprintf(F, "backedge: { sourcename: \"");
166 fprintf(F, "edge: { sourcename: \"");
168 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
169 vfprintf(F, fmt, ap);
174 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
179 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
180 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
181 vfprintf(F, fmt, ap);
186 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
191 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
192 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
193 vfprintf(F, fmt, ap);
198 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
203 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
204 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
206 vfprintf(F, fmt, ap);
211 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
216 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
217 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
218 vfprintf(F, fmt, ap);
223 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
228 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
229 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
230 vfprintf(F, fmt, ap);
235 /*******************************************************************/
236 /* global and ahead declarations */
237 /*******************************************************************/
239 /* A suffix to manipulate the file name. */
241 char *dump_file_filter = "";
243 static void dump_whole_node(ir_node *n, void *env);
244 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
246 /*******************************************************************/
247 /* Helper functions. */
248 /*******************************************************************/
250 /* Use private link attr to be able to call dumper anywhere without
251 destroying link fields. */
253 static pmap *irdump_link_map = NULL;
255 static void init_irdump(void) {
256 /* We need a new, empty map. */
257 if (irdump_link_map) pmap_destroy(irdump_link_map);
258 irdump_link_map = pmap_create();
262 void *ird_get_irn_link(ir_node *n) {
264 if (!irdump_link_map) return NULL;
266 if (pmap_contains(irdump_link_map, (void *)n))
267 res = pmap_get(irdump_link_map, (void *)n);
271 void ird_set_irn_link(ir_node *n, void *x) {
272 if (!irdump_link_map) init_irdump();
273 pmap_insert(irdump_link_map, (void *)n, x);
276 void *ird_get_irg_link(ir_graph *irg) {
278 if (!irdump_link_map) return NULL;
280 if (pmap_contains(irdump_link_map, (void *)irg))
281 res = pmap_get(irdump_link_map, (void *)irg);
285 void ird_set_irg_link(ir_graph *irg, void *x) {
286 if (!irdump_link_map) init_irdump();
287 pmap_insert(irdump_link_map, (void *)irg, x);
290 static void clear_link(ir_node * node, void * env) {
291 ird_set_irn_link(node, NULL);
295 static int node_floats(ir_node *n) {
296 return ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
297 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
300 static const char *get_ent_dump_name(entity *ent) {
302 return "<NULL entity>";
303 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
304 if (ent->ld_name) return get_id_str(ent->ld_name);
305 return get_id_str(ent->name);
308 static const char *get_irg_dump_name(ir_graph *irg) {
309 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
310 entity *ent = get_irg_entity(irg);
311 return get_ent_dump_name(ent);
314 static void collect_node(ir_node * node, void *env) {
317 || get_irn_op(node) == op_Bad
318 || get_irn_op(node) == op_Unknown) {
319 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
320 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
321 ARR_APP1(ir_node *, arr, node);
322 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
324 ir_node * block = get_nodes_block(node);
325 ird_set_irn_link(node, ird_get_irn_link(block));
326 ird_set_irn_link(block, node);
330 /** Construct lists to walk ir block-wise.
332 * Collects all blocks, nodes not op_pin_state_pinned,
333 * Bad and Unknown into a flexible array in link field of
334 * irg they belong to. Sets the irg link field to NULL in all
335 * graphs not visited.
336 * Free the list with DEL_ARR_F. */
337 static ir_node ** construct_block_lists(ir_graph *irg) {
338 int i, rem_view = interprocedural_view;
339 ir_graph *rem = current_ir_graph;
340 current_ir_graph = irg;
342 for (i = 0; i < get_irp_n_irgs(); i++)
343 ird_set_irg_link(get_irp_irg(i), NULL);
345 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
347 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
348 interprocedural_view = 0;
349 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
350 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
351 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
352 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
353 interprocedural_view = rem_view;
355 current_ir_graph = rem;
356 return ird_get_irg_link(irg);
359 /*******************************************************************/
360 /* flags to steer output */
361 /*******************************************************************/
363 /* A compiler option to turn off edge labels */
365 /* A compiler option to turn off dumping values of constant entities */
366 int const_entities = 1;
367 /* A compiler option to dump the keep alive edges */
368 int dump_keepalive = 0;
369 /* Compiler options to dump analysis information in dump_ir_graph */
370 int dump_out_edge_flag = 0;
371 int dump_dominator_information_flag = 0;
372 int dump_loop_information_flag = 0;
373 int dump_backedge_information_flag = 1;
374 int dump_const_local = 0;
375 bool opt_dump_analysed_type_info = 1;
376 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
378 char* overrule_nodecolor = NULL;
380 INLINE bool get_opt_dump_const_local(void) {
381 if (!dump_out_edge_flag && !dump_loop_information_flag)
382 return dump_const_local;
387 /* To turn off display of edge labels. Edge labels offen cause xvcg to
388 abort with a segmentation fault. */
389 void turn_off_edge_labels(void) {
393 void dump_consts_local(bool b) {
394 dump_const_local = b;
397 void turn_off_constant_entity_values(void) {
401 void dump_keepalive_edges(bool b) {
405 bool get_opt_dump_keepalive_edges(void) {
406 return dump_keepalive;
409 void dump_out_edges(void) {
410 dump_out_edge_flag = 1;
413 void dump_dominator_information(void) {
414 dump_dominator_information_flag = 1;
417 void dump_loop_information(void) {
418 dump_loop_information_flag = 1;
421 void dont_dump_loop_information(void) {
422 dump_loop_information_flag = 0;
425 void dump_backedge_information(bool b) {
426 dump_backedge_information_flag = b;
429 /* Dump the information of type field specified in ana/irtypeinfo.h.
430 * If the flag is set, the type name is output in [] in the node label,
431 * else it is output as info.
433 void dump_analysed_type_info(bool b) {
434 opt_dump_analysed_type_info = b;
437 void dump_pointer_values_to_info(bool b) {
438 opt_dump_pointer_values_to_info = b;
441 /*******************************************************************/
442 /* Routines to dump information about a single ir node. */
443 /*******************************************************************/
446 dump_node_opcode(FILE *F, ir_node *n)
450 switch(get_irn_opcode(n)) {
455 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
456 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
461 if (get_SymConst_kind(n) == symconst_addr_name) {
462 /* don't use get_SymConst_ptr_info as it mangles the name. */
463 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
464 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
465 assert(get_SymConst_entity(n));
466 assert(is_entity(get_SymConst_entity(n)));
467 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
469 assert(get_kind(get_SymConst_type(n)) == k_type);
470 assert(get_type_ident(get_SymConst_type(n)));
471 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
472 if (get_SymConst_kind(n) == symconst_type_tag)
480 if (!interprocedural_view) fprintf(F, "Proj'");
481 else goto default_case;
485 ir_node *pred = get_Proj_pred(n);
487 if (get_irn_opcode(pred) == iro_Cond
488 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
489 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
490 fprintf (F, "defProj");
492 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
493 * fprintf (F, "Arg");
502 if (interprocedural_view) {
503 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
508 case iro_CallBegin: {
509 ir_node *addr = get_CallBegin_ptr(n);
511 if (get_irn_op(addr) == op_Sel)
512 ent = get_Sel_entity(addr);
513 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
514 ent = get_SymConst_entity(addr);
515 fprintf (F, "%s", get_irn_opname(n));
516 if (ent) fprintf (F, " %s", get_entity_name(ent));
522 fprintf (F, "%s", get_irn_opname(n));
530 dump_node_mode(FILE *F, ir_node *n)
534 switch (get_irn_opcode(n)) {
553 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
561 static int dump_node_typeinfo(FILE *F, ir_node *n) {
564 if (opt_dump_analysed_type_info) {
565 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
566 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
567 type *tp = get_irn_type(n);
569 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
578 dump_node_nodeattr(FILE *F, ir_node *n)
582 switch (get_irn_opcode(n)) {
584 if (false && interprocedural_view) {
585 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
589 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
590 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
592 fprintf (F, "%ld", get_Proj_proj(n));
596 fprintf (F, "%ld", get_Filter_proj(n));
599 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
602 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
605 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
615 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
618 fprintf(F, "color: red");
621 switch (get_irn_opcode(n)) {
628 fprintf (F, "color: blue");
631 fprintf (F, "color: lightyellow");
634 fprintf (F, "color: green");
640 fprintf (F, "color: yellow");
643 PRINT_DEFAULT_NODE_ATTR;
646 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
649 static INLINE int dump_node_info(FILE *F, ir_node *n)
655 fprintf (F, " info1: \"");
656 if (opt_dump_pointer_values_to_info)
657 fprintf (F, "addr: %p \n", (void *)n);
658 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
659 fprintf (F, "visited: %ld \n", get_irn_visited(n));
660 irg = get_irn_irg(n);
661 if (irg != get_const_code_irg())
662 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
664 fprintf(F, "arity: %d", get_irn_arity(n));
665 if ((get_irn_op(n) == op_Block) ||
666 (get_irn_op(n) == op_Phi) ||
667 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
668 fprintf(F, " backedges:");
670 for (i = 0; i < get_irn_arity(n); i++)
671 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
675 /* Loop node Someone else please tell me what's wrong ...
676 if (get_irn_loop(n)) {
677 ir_loop *loop = get_irn_loop(n);
679 fprintf(F, " in loop %d with depth %d\n",
680 get_loop_loop_nr(loop), get_loop_depth(loop));
685 switch (get_irn_opcode(n)) {
687 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
688 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
689 for (i = 0; i < get_method_n_params(tp); ++i)
690 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
693 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
696 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
699 entity *ent = get_Sel_entity(n);
702 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
703 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
706 fprintf(F, "<NULL entity>\n");
711 type *tp = get_Call_type(n);
712 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
713 for (i = 0; i < get_method_n_params(tp); ++i)
714 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
715 for (i = 0; i < get_method_n_ress(tp); ++i)
716 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
717 if (0 && Call_has_callees(n)) {
718 fprintf(F, "possible callees: \n");
719 for (i = 0; i < get_Call_n_callees(n); i++) {
720 if (!get_Call_callee(n, i)) {
721 fprintf(F, " %d external method\n", i);
723 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
728 case iro_CallBegin: {
729 ir_node *call = get_CallBegin_call(n);
730 if (Call_has_callees(call)) {
731 fprintf(F, "possible callees: \n");
732 for (i = 0; i < get_Call_n_callees(call); i++) {
733 if (!get_Call_callee(call, i)) {
734 fprintf(F, " %d external method\n", i);
736 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
742 if (!interprocedural_view) {
743 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
744 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
745 for (i = 0; i < get_method_n_ress(tp); ++i)
746 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
750 type *tp = get_Const_type(n);
751 assert(tp != none_type);
752 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
755 switch(get_SymConst_kind(n)) {
756 case symconst_addr_name:
757 fprintf(F, "kind addr_name\n");
759 case symconst_addr_ent:
760 fprintf(F, "kind addr_ent\n");
762 case symconst_type_tag:
763 fprintf(F, "kind type_tag\n");
766 fprintf(F, "kind size\n");
772 if (interprocedural_view) {
773 fprintf(F, "intra predecessor nodes:\n");
774 for (i = 0; i < get_irn_intra_arity(n); i++) {
775 ir_node *pred = get_irn_intra_n(n, i);
776 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
779 fprintf(F, "inter predecessor nodes:\n");
780 for (i = 0; i < get_irn_inter_arity(n); i++) {
781 ir_node *pred = get_irn_inter_n(n, i);
782 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
783 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
790 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
791 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
792 if (get_irn_type(n) != none_type)
793 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
802 bool is_constlike_node(ir_node *n) {
803 ir_op *op = get_irn_op(n);
804 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
808 /* outputs the predecessors of n, that are constants, local. I.e.,
809 generates a copy of the constant predecessors for each node called with. */
810 static void dump_const_node_local(FILE *F, ir_node *n) {
812 if (!get_opt_dump_const_local()) return;
814 /* Use visited flag to avoid outputting nodes twice.
815 initialize it first. */
816 for (i = 0; i < get_irn_arity(n); i++) {
817 ir_node *con = get_irn_n(n, i);
818 if (is_constlike_node(con)) {
819 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
823 for (i = 0; i < get_irn_arity(n); i++) {
824 ir_node *con = get_irn_n(n, i);
825 if (is_constlike_node(con) && irn_not_visited(con)) {
828 mark_irn_visited(con);
829 /* Generate a new name for the node by appending the names of
831 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
832 fprintf(F, " label: \"");
833 bad |= dump_node_opcode(F, con);
834 bad |= dump_node_mode(F, con);
835 bad |= dump_node_typeinfo(F, con);
837 bad |= dump_node_nodeattr(F, con);
838 fprintf(F, " %ld", get_irn_node_nr(con));
840 bad |= dump_node_info(F, con);
841 dump_node_vcgattr(F, con, bad);
847 static void INLINE print_node_error(FILE *F, const char *p)
852 fprintf (F, " info2: \"%s\"", p);
855 static void dump_node(FILE *F, ir_node *n)
860 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
862 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
864 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
865 bad |= dump_node_opcode(F, n);
866 bad |= dump_node_mode(F, n);
867 bad |= dump_node_typeinfo(F, n);
869 bad |= dump_node_nodeattr(F, n);
870 fprintf(F, " %ld", get_irn_node_nr(n));
872 bad |= dump_node_info(F, n);
873 print_node_error(F, p);
874 dump_node_vcgattr(F, n, bad);
876 dump_const_node_local(F, n);
883 /* dump the edge to the block this node belongs to */
885 dump_ir_block_edge(FILE *F, ir_node *n) {
886 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
887 if (is_no_Block(n)) {
888 fprintf (F, "edge: { sourcename: \"");
890 fprintf (F, "\" targetname: \"");
891 PRINT_NODEID(get_nodes_block(n));
892 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
897 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
898 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
899 fprintf (F, INTRA_DATA_EDGE_ATTR);
901 fprintf (F, INTER_DATA_EDGE_ATTR);
905 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
906 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
907 fprintf (F, INTRA_MEM_EDGE_ATTR);
909 fprintf (F, INTER_MEM_EDGE_ATTR);
913 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
916 if (dump_backedge_information_flag && is_backedge(from, to))
917 fprintf (F, BACK_EDGE_ATTR);
919 switch (get_irn_opcode(from)) {
921 fprintf (F, CF_EDGE_ATTR);
923 case iro_Start: break;
926 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
927 fprintf (F, CF_EDGE_ATTR);
928 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
929 fprintf (F, INTER_MEM_EDGE_ATTR);
937 print_data_edge_vcgattr(F, from, to);
942 print_mem_edge_vcgattr(F, from, to);
944 print_data_edge_vcgattr(F, from, to);
948 print_data_edge_vcgattr(F, from, to);
953 print_mem_edge_vcgattr(F, from, to);
955 print_data_edge_vcgattr(F, from, to);
962 print_data_edge_vcgattr(F, from, to);
969 print_mem_edge_vcgattr(F, from, to);
971 print_data_edge_vcgattr(F, from, to);
983 print_data_edge_vcgattr(F, from, to);
986 if (get_irn_modecode(from) == irm_M)
987 fprintf (F, INTER_MEM_EDGE_ATTR);
989 print_data_edge_vcgattr(F, from, to);
996 print_mem_edge_vcgattr(F, from, to);
998 print_data_edge_vcgattr(F, from, to);
1001 print_mem_edge_vcgattr(F, from, to);
1003 case iro_Tuple: break;
1006 switch (get_irn_modecode(from)) {
1008 fprintf (F, CF_EDGE_ATTR);
1011 fprintf (F, INTER_MEM_EDGE_ATTR);
1014 print_data_edge_vcgattr(F, from, to);
1018 case iro_Bad: break;
1019 case iro_Unknown: break;
1021 switch (get_irn_modecode(from)) {
1023 fprintf (F, INTRA_MEM_EDGE_ATTR);
1026 fprintf (F, CF_EDGE_ATTR);
1029 print_data_edge_vcgattr(F, from, to);
1037 /* dump edges to our inputs */
1039 dump_ir_data_edges(FILE *F, ir_node *n) {
1040 int i, visited = get_irn_visited(n);
1042 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1045 for (i = 0; i < get_irn_arity(n); i++) {
1046 ir_node * pred = get_irn_n(n, i);
1049 if ((interprocedural_view && get_irn_visited(pred) < visited))
1050 continue; /* pred not dumped */
1052 if (dump_backedge_information_flag && is_backedge(n, i))
1053 fprintf (F, "backedge: {sourcename: \"");
1055 fprintf (F, "edge: {sourcename: \"");
1057 fprintf (F, "\" targetname: ");
1058 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1059 PRINT_CONSTID(n, pred);
1061 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1063 fprintf (F, " label: \"%d\" ", i);
1064 print_edge_vcgattr(F, n, i);
1069 /** Dumps a node and its edges but not the block edge
1072 dump_node_wo_blockedge (ir_node *n, void *env) {
1075 dump_ir_data_edges(F, n);
1078 /** Dumps a node and its edges.
1081 dump_whole_node (ir_node *n, void *env) {
1083 dump_node_wo_blockedge(n, env);
1084 if (!node_floats(n)) dump_ir_block_edge(F, n);
1088 dump_const_node(ir_node *n, void *env) {
1089 if (is_Block(n)) return;
1090 dump_node_wo_blockedge(n, env);
1093 /***********************************************************************/
1094 /* the following routines dump the nodes/irgs bracketed to graphs. */
1095 /***********************************************************************/
1097 /** Dumps a constant expression as entity initializer, array bound ...
1099 static void dump_const_expression(FILE *F, ir_node *value) {
1100 ir_graph *rem = current_ir_graph;
1101 int rem_dump_const_local = dump_const_local;
1102 dump_const_local = 0;
1103 current_ir_graph = get_const_code_irg();
1104 irg_walk(value, dump_const_node, NULL, F);
1105 /* Decrease visited flag so that we walk with the same flag for the next
1106 expresssion. This guarantees that we don't dump the same node twice,
1107 as for const expressions cse is performed to save memory. */
1108 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1109 current_ir_graph = rem;
1110 dump_const_local = rem_dump_const_local;
1113 /** Dump a block as graph containing its nodes.
1115 * Expects to find nodes belonging to the block as list in its
1117 * Dumps the edges of all nodes including itself. */
1119 dump_whole_block(FILE *F, ir_node *block) {
1121 assert(is_Block(block));
1123 fprintf(F, "graph: { title: \"");
1124 PRINT_NODEID(block);
1125 fprintf(F, "\" label: \"");
1126 dump_node_opcode(F, block);
1127 fprintf (F, " %ld", get_irn_node_nr(block));
1129 if (get_opt_dump_abstvals())
1130 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1132 fprintf(F, "\" status:clustered color:%s \n",
1133 get_Block_matured(block) ? "yellow" : "red");
1135 /* dump the blocks edges */
1136 dump_ir_data_edges(F, block);
1138 /* dump the nodes that go into the block */
1139 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1141 dump_ir_data_edges(F, node);
1144 /* Close the vcg information for the block */
1146 dump_const_node_local(F, block);
1148 dump_chi_term(F, block);
1153 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1154 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1156 dump_block_graph(FILE *F, ir_graph *irg) {
1158 ir_graph *rem = current_ir_graph;
1159 ir_node **arr = ird_get_irg_link(irg);
1160 current_ir_graph = irg;
1162 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1163 ir_node * node = arr[i];
1164 if (is_Block(node)) {
1165 /* Dumps the block and all the nodes in the block, which are to
1166 be found in Block->link. */
1167 dump_whole_block(F, node);
1169 /* Nodes that are not in a Block. */
1171 dump_ir_data_edges(F, node);
1175 if (dump_loop_information_flag) dump_loop_nodes_into_graph(F, irg);
1177 current_ir_graph = rem;
1180 /** Dumps an irg as a graph.
1181 * If interprocedural view edges can point to nodes out of this graph.
1183 static void dump_graph(FILE *F, ir_graph *irg) {
1185 fprintf(F, "graph: { title: \"");
1187 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1188 get_ent_dump_name(get_irg_entity(irg)));
1190 dump_block_graph(F, irg);
1192 /* Close the vcg information for the irg */
1193 fprintf(F, "}\n\n");
1196 /*******************************************************************/
1197 /* Basic type and entity nodes and edges. */
1198 /*******************************************************************/
1200 /* dumps the edges between nodes and their type or entity attributes. */
1201 static void dump_node2type_edges(ir_node *n, void *env)
1206 switch (get_irn_opcode(n)) {
1208 /* @@@ some consts have an entity */
1211 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1212 || (get_SymConst_kind(n) ==symconst_size))
1214 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1218 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1221 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1224 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1227 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1230 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1238 static int print_type_info(FILE *F, type *tp) {
1241 if (get_type_state(tp) == layout_undefined) {
1242 fprintf(F, "state: layout_undefined\n");
1244 fprintf(F, "state: layout_fixed,\n");
1246 if (get_type_mode(tp))
1247 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1248 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1253 static void print_typespecific_info(FILE *F, type *tp) {
1254 switch (get_type_tpop_code(tp)) {
1257 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1264 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1265 fprintf(F, "params: %d\n", get_method_n_params(tp));
1266 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1274 case tpo_enumeration:
1288 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1289 switch (get_type_tpop_code(tp)) {
1292 if (peculiarity_existent == get_class_peculiarity(tp))
1293 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1295 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1299 fprintf (F, " " TYPE_METH_NODE_ATTR);
1310 case tpo_enumeration:
1323 static int print_type_node(FILE *F, type *tp)
1327 fprintf (F, "node: {title: ");
1329 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1330 fprintf (F, " info1: \"");
1331 bad |= print_type_info(F, tp);
1332 print_typespecific_info(F, tp);
1334 print_typespecific_vcgattr(F, tp);
1340 #define X(a) case a: fprintf(F, #a); break
1341 void dump_entity_node(FILE *F, entity *ent)
1343 fprintf (F, "node: {title: \"");
1344 PRINT_ENTID(ent); fprintf(F, "\"");
1345 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1346 fprintf (F, "label: ");
1347 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1348 fprintf (F, "\n info1: \"");
1350 dump_entity_to_file(F, ent);
1352 fprintf(F, "\"\n}\n");
1356 static void dump_enum_item(FILE *F, type *tp, int pos)
1359 ident *id = get_enumeration_nameid(tp, pos);
1360 tarval *tv = get_enumeration_enum(tp, pos);
1362 tarval_snprintf(buf, sizeof(buf), tv);
1363 fprintf (F, "node: {title: \"");
1364 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1365 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1366 fprintf (F, "label: ");
1367 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1368 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1371 /* dumps a type or entity and it's edges. */
1373 dump_type_info(type_or_ent *tore, void *env) {
1375 int i = 0; /* to shutup gcc */
1377 /* dump this type or entity */
1379 switch (get_kind(tore)) {
1382 entity *ent = (entity *)tore;
1385 dump_entity_node(F, ent);
1387 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1388 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1389 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1390 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1391 if(is_class_type(get_entity_owner(ent))) {
1392 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1393 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1395 /* attached subgraphs */
1396 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1397 if (is_atomic_entity(ent)) {
1398 value = get_atomic_ent_value(ent);
1400 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1401 /* DDMN(value); $$$ */
1402 dump_const_expression(F, value);
1405 if (is_compound_entity(ent)) {
1406 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1407 value = get_compound_ent_value(ent, i);
1409 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1410 dump_const_expression(F, value);
1411 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1413 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1414 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1415 get_compound_ent_value_member(ent, i), i);
1424 type *tp = (type *)tore;
1425 print_type_node(F, tp);
1426 /* and now the edges */
1427 switch (get_type_tpop_code(tp)) {
1430 for (i=0; i < get_class_n_supertypes(tp); i++)
1431 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1432 for (i=0; i < get_class_n_members(tp); i++)
1433 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1437 for (i=0; i < get_struct_n_members(tp); i++)
1438 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1442 for (i = 0; i < get_method_n_params(tp); i++)
1443 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1444 for (i = 0; i < get_method_n_ress(tp); i++)
1445 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1449 for (i = 0; i < get_union_n_members(tp); i++)
1450 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1454 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1455 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1456 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1457 ir_node *upper = get_array_upper_bound(tp, i);
1458 ir_node *lower = get_array_lower_bound(tp, i);
1459 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1460 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1461 dump_const_expression(F, upper);
1462 dump_const_expression(F, lower);
1466 case tpo_enumeration:
1468 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1469 dump_enum_item(F, tp, i);
1470 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1475 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1483 break; /* case k_type */
1486 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1488 } /* switch kind_or_entity */
1491 typedef struct _h_env {
1496 /** For dumping class hierarchies.
1497 * Dumps a class type node and a superclass edge.
1498 * If env->dump_ent dumps entities of classes and overwrites edges.
1501 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1504 int i = 0; /* to shutup gcc */
1506 /* dump this type or entity */
1507 switch (get_kind(tore)) {
1509 entity *ent = (entity *)tore;
1510 if (get_entity_owner(ent) == get_glob_type()) break;
1511 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1512 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1514 dump_entity_node(F, ent);
1516 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1517 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1518 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1520 } break; /* case k_entity */
1523 type *tp = (type *)tore;
1524 if (tp == get_glob_type()) break;
1525 switch (get_type_tpop_code(tp)) {
1527 print_type_node(F, tp);
1528 /* and now the edges */
1529 for (i=0; i < get_class_n_supertypes(tp); i++)
1531 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1537 break; /* case k_type */
1540 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1542 } /* switch kind_or_entity */
1545 /*******************************************************************/
1546 /* dump analysis information that is expressed in graph terms. */
1547 /*******************************************************************/
1549 /* dump out edges */
1551 dump_out_edge(ir_node *n, void *env) {
1554 for (i = 0; i < get_irn_n_outs(n); i++) {
1555 assert(get_irn_out(n, i));
1556 fprintf (F, "edge: {sourcename: \"");
1558 fprintf (F, "\" targetname: \"");
1559 PRINT_NODEID(get_irn_out(n, i));
1560 fprintf (F, "\" color: red linestyle: dashed");
1566 dump_loop_label(FILE *F, ir_loop *loop) {
1567 fprintf (F, "loop %d, %d sons, %d nodes",
1568 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1571 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1572 fprintf (F, " info1: \"");
1573 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1574 #if DEBUG_libfirm /* GL @@@ debug analyses */
1575 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1581 dump_loop_node(FILE *F, ir_loop *loop) {
1582 fprintf (F, "node: {title: \"");
1584 fprintf (F, "\" label: \"");
1585 dump_loop_label(F, loop);
1587 dump_loop_info(F, loop);
1593 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1595 fprintf (F, "edge: {sourcename: \"");
1597 fprintf (F, "\" targetname: \"");
1598 PRINT_NODEID(get_loop_node(loop, i));
1599 fprintf (F, "\" color: green");
1604 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1606 fprintf (F, "edge: {sourcename: \"");
1608 fprintf (F, "\" targetname: \"");
1609 PRINT_LOOPID(get_loop_son(loop, i));
1610 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1611 get_loop_element_pos(loop, get_loop_son(loop, i)));
1615 void dump_loops(FILE *F, ir_loop *loop) {
1617 /* dump this loop node */
1618 dump_loop_node(F, loop);
1620 /* dump edges to nodes in loop -- only if it is a real loop */
1621 if (get_loop_depth(loop) != 0) {
1622 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1623 dump_loop_node_edge(F, loop, i);
1626 for (i = 0; i < get_loop_n_sons(loop); i++) {
1627 dump_loops(F, get_loop_son(loop, i));
1628 dump_loop_son_edge(F, loop, i);
1633 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1634 ir_graph *rem = current_ir_graph;
1635 current_ir_graph = irg;
1637 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1639 current_ir_graph = rem;
1644 * dumps the VCG header
1647 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1656 if (!orientation) orientation = "bottom_to_top";
1660 "graph: { title: \"ir graph of %s\"\n"
1661 "display_edge_labels: %s\n"
1662 "layoutalgorithm: mindepth\n"
1663 "manhattan_edges: yes\n"
1664 "port_sharing: no\n"
1666 "classname 1: \"intrablock Data\"\n"
1667 "classname 16: \"interblock Data\"\n"
1668 "classname 2: \"Block\"\n"
1669 "classname 13: \"Control Flow\"\n"
1670 "classname 14: \"intrablock Memory\"\n"
1671 "classname 17: \"interblock Memory\"\n"
1672 "classname 15: \"Dominators\"\n"
1673 "classname 3: \"Entity type\"\n"
1674 "classname 4: \"Entity owner\"\n"
1675 "classname 5: \"Method Param\"\n"
1676 "classname 6: \"Method Res\"\n"
1677 "classname 7: \"Super\"\n"
1678 "classname 8: \"Union\"\n"
1679 "classname 9: \"Points-to\"\n"
1680 "classname 10: \"Array Element Type\"\n"
1681 "classname 11: \"Overwrites\"\n"
1682 "classname 12: \"Member\"\n"
1683 "infoname 1: \"Attribute\"\n"
1684 "infoname 2: \"Verification errors\"\n",
1685 name, label, orientation);
1687 fprintf (F, "\n"); /* a separator */
1693 * @param irg The graph to be dumped
1694 * @param suffix1 first filename suffix
1695 * @param suffix2 second filename suffix
1697 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1699 const char *nm = get_irg_dump_name(irg);
1700 int len = strlen(nm), i, j;
1701 char *fname; /* filename to put the vcg information in */
1703 if (!suffix1) suffix1 = "";
1704 if (!suffix2) suffix2 = "";
1706 /* open file for vcg graph */
1707 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1709 /* strncpy (fname, nm, len); */ /* copy the filename */
1711 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1713 fname[j] = '@'; j++; fname[j] = '1'; j++;
1714 } else if (nm[i] == '@') {
1715 fname[j] = '@'; j++; fname[j] = '2'; j++;
1717 fname[j] = nm[i]; j++;
1721 strcat (fname, suffix1); /* append file suffix */
1722 strcat (fname, suffix2); /* append file suffix */
1723 strcat (fname, ".vcg"); /* append the .vcg suffix */
1724 F = fopen (fname, "w"); /* open file for writing */
1726 panic("cannot open %s for writing (%m)", fname); /* not reached */
1736 * @param irg The graph to be dumped
1737 * @param suffix filename suffix
1739 static FILE *vcg_open_name (const char *name, const char *suffix) {
1741 char *fname; /* filename to put the vcg information in */
1742 int i, j, len = strlen(name);
1744 if (!suffix) suffix = "";
1746 /** open file for vcg graph */
1747 fname = malloc (len * 2 + 5 + strlen(suffix));
1748 /* strcpy (fname, name);*/ /* copy the filename */
1750 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1751 if (name[i] == '/') {
1752 fname[j] = '@'; j++; fname[j] = '1'; j++;
1753 } else if (name[i] == '@') {
1754 fname[j] = '@'; j++; fname[j] = '2'; j++;
1756 fname[j] = name[i]; j++;
1760 strcat (fname, suffix);
1761 strcat (fname, ".vcg"); /* append the .vcg suffix */
1762 F = fopen (fname, "w"); /* open file for writing */
1764 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1772 * Dumps the vcg file footer
1774 static INLINE void dump_vcg_footer (FILE *F) {
1779 * close the vcg file
1782 vcg_close (FILE *F) {
1783 dump_vcg_footer(F); /* print footer */
1784 fclose (F); /* close vcg file */
1787 /************************************************************************/
1788 /************************************************************************/
1789 /* Routines that dump all or parts of the firm representation to a file */
1790 /************************************************************************/
1791 /************************************************************************/
1793 /************************************************************************/
1794 /* Dump ir graphs, differnt formats and additional information. */
1795 /************************************************************************/
1797 /** Routine to dump a graph, blocks as conventional nodes.
1800 dump_ir_graph (ir_graph *irg, const char *suffix )
1805 rem = current_ir_graph;
1807 if(strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter))!=0) return;
1808 current_ir_graph = irg;
1809 if (interprocedural_view) suffix1 = "-pure-ip";
1810 else suffix1 = "-pure";
1811 f = vcg_open(irg, suffix, suffix1);
1812 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1814 /* walk over the graph */
1815 /* dump_whole_node must be called in post visiting predecessors */
1816 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1818 /* dump the out edges in a separate walk */
1819 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1820 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1825 current_ir_graph = rem;
1830 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1836 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1837 if (interprocedural_view) suffix1 = "-ip";
1839 f = vcg_open(irg, suffix, suffix1);
1840 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1842 construct_block_lists(irg);
1844 for (i = 0; i < get_irp_n_irgs(); i++) {
1845 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1847 dump_graph(f, get_irp_irg(i));
1855 /** dumps a graph with type information
1858 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1861 ir_graph *rem = current_ir_graph;
1864 /* if a filter is set, dump only the irg's that match the filter */
1865 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1868 current_ir_graph = irg;
1870 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1871 else suffix1 = "-pure-wtypes";
1872 f = vcg_open(irg,suffix, suffix1);
1873 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1875 /* dump common ir graph */
1876 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1877 /* dump type info */
1878 type_walk_irg(irg, dump_type_info, NULL, f);
1879 inc_irg_visited(get_const_code_irg());
1880 /* dump edges from graph to type info */
1881 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1884 current_ir_graph = rem;
1888 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1893 ir_graph *rem = current_ir_graph;
1895 /* if a filter is set, dump only the irg's that match the filter */
1896 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1899 if (interprocedural_view) suffix1 = "-wtypes-ip";
1900 else suffix1 = "-wtypes";
1901 f = vcg_open(irg, suffix, suffix1);
1902 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1904 /* dump common blocked ir graph */
1905 construct_block_lists(irg);
1907 for (i = 0; i < get_irp_n_irgs(); i++) {
1908 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1910 dump_graph(f, get_irp_irg(i));
1915 /* dump type info */
1916 current_ir_graph = irg;
1917 type_walk_irg(irg, dump_type_info, NULL, f);
1918 inc_irg_visited(get_const_code_irg());
1920 /* dump edges from graph to type info */
1921 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1923 current_ir_graph = rem;
1927 /***********************************************************************/
1928 /* The following routines dump a control flow graph. */
1929 /***********************************************************************/
1932 dump_block_to_cfg(ir_node *block, void *env) {
1937 if (is_Block(block)) {
1938 /* This is a block. Dump a node for the block. */
1939 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1940 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1941 PRINT_NODEID(block);
1943 if (dump_dominator_information_flag)
1944 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1946 /* Dump the edges */
1947 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1948 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1949 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1950 fprintf (F, "edge: { sourcename: \"");
1951 PRINT_NODEID(block);
1952 fprintf (F, "\" targetname: \"");
1954 fprintf (F, "\"}\n");
1957 /* Dump dominator edge */
1958 if (dump_dominator_information_flag && get_Block_idom(block)) {
1959 pred = get_Block_idom(block);
1960 fprintf (F, "edge: { sourcename: \"");
1961 PRINT_NODEID(block);
1962 fprintf (F, "\" targetname: \"");
1964 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1970 dump_cfg (ir_graph *irg, const char *suffix)
1973 ir_graph *rem = current_ir_graph;
1974 int ddif = dump_dominator_information_flag;
1975 int ipv = interprocedural_view;
1977 /* if a filter is set, dump only the irg's that match the filter */
1978 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1981 current_ir_graph = irg;
1983 f = vcg_open(irg, suffix, "-cfg");
1984 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1986 if (interprocedural_view) {
1987 printf("Warning: dumping cfg not in interprocedural view!\n");
1988 interprocedural_view = 0;
1991 if (get_irg_dom_state(irg) != dom_consistent)
1992 dump_dominator_information_flag = 0;
1994 /* walk over the blocks in the graph */
1995 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
1996 dump_node(f, get_irg_bad(irg));
1998 dump_dominator_information_flag = ddif;
1999 interprocedural_view = ipv;
2001 current_ir_graph = rem;
2004 void dump_callgraph(const char *suffix) {
2006 int i, n_irgs = get_irp_n_irgs();
2007 int rem = edge_label;
2010 my_special_flag = 1;
2012 F = vcg_open_name("Callgraph", suffix);
2013 dump_vcg_header(F, "Callgraph", NULL);
2015 for (i = 0; i < n_irgs; ++i) {
2016 ir_graph *irg = get_irp_irg(i);
2017 entity *ent = get_irg_entity(irg);
2018 int j, n_callees = get_irg_n_callees(irg);
2020 dump_entity_node(F, ent);
2021 for (j = 0; j < n_callees; ++j) {
2022 entity *c = get_irg_entity(get_irg_callee(irg, j));
2023 int be = is_irg_callee_backedge(irg, j);
2026 "label:\"recursion %d\" color:red" :
2027 "label:\"calls %d\"";
2028 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j));
2032 my_special_flag = 0;
2037 /* Dump all irgs in interprocedural view to a single file. */
2038 void dump_all_cg_block_graph(const char *suffix) {
2041 int rem_view = interprocedural_view;
2042 interprocedural_view = 1;
2044 f = vcg_open_name("All_graphs", suffix);
2045 dump_vcg_header(f, "All_graphs", NULL);
2047 /* collect nodes in all irgs reachable in call graph*/
2048 for (i = 0; i < get_irp_n_irgs(); i++)
2049 ird_set_irg_link(get_irp_irg(i), NULL);
2051 cg_walk(clear_link, collect_node, NULL);
2053 /* dump all graphs */
2054 for (i = 0; i < get_irp_n_irgs(); i++) {
2055 current_ir_graph = get_irp_irg(i);
2056 assert(ird_get_irg_link(current_ir_graph));
2057 dump_graph(f, current_ir_graph);
2058 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2062 interprocedural_view = rem_view;
2065 /***********************************************************************/
2066 /* the following routines dumps type information without any ir nodes. */
2067 /***********************************************************************/
2070 dump_type_graph (ir_graph *irg, const char *suffix)
2074 rem = current_ir_graph;
2076 /* if a filter is set, dump only the irg's that match the filter */
2077 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2079 current_ir_graph = irg;
2081 f = vcg_open(irg, suffix, "-type");
2082 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2084 /* walk over the blocks in the graph */
2085 type_walk_irg(irg, dump_type_info, NULL, f);
2086 /* The walker for the const code can be called several times for the
2087 same (sub) experssion. So that no nodes are dumped several times
2088 we decrease the visited flag of the corresponding graph after each
2089 walk. So now increase it finally. */
2090 inc_irg_visited(get_const_code_irg());
2093 current_ir_graph = rem;
2097 dump_all_types (const char *suffix)
2099 FILE *f = vcg_open_name("All_types", suffix);
2100 dump_vcg_header(f, "All_types", NULL);
2101 type_walk(dump_type_info, NULL, f);
2102 inc_irg_visited(get_const_code_irg());
2107 dump_class_hierarchy (bool entities, const char *suffix)
2109 FILE *f = vcg_open_name("class_hierarchy", suffix);
2113 dump_vcg_header(f, "class_hierarchy", NULL);
2118 type_walk(dump_class_hierarchy_node, NULL, &env);
2122 /***********************************************************************/
2123 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2125 /* dump_ir_block_graph */
2127 /* dump_type_graph */
2128 /* dump_ir_graph_w_types */
2129 /***********************************************************************/
2131 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2133 for (i=0; i < get_irp_n_irgs(); i++) {
2134 dmp_grph(get_irp_irg(i), suffix);
2139 /**********************************************************************************
2140 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2141 * packed together in one subgraph/box *
2142 **********************************************************************************/
2144 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2145 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2147 ir_loop *son = NULL;
2149 /* Dump a new loop node. */
2150 dump_loop_node(F, loop);
2152 /* Dump the loop elements. */
2154 for(i = 0; i < get_loop_n_elements(loop); i++) {
2155 le = get_loop_element(loop, i);
2157 if (get_kind(son) == k_ir_loop) {
2159 /* We are a loop son -> Recurse */
2161 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2162 fprintf(F, "\" }\n");
2163 fprintf (F, "edge: {sourcename: \"");
2165 fprintf (F, "\" targetname: \"");
2167 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2168 loop_node_started = 0;
2170 dump_loop_son_edge(F, loop, son_number++);
2171 dump_loops_standalone(F, son);
2172 } else if (get_kind(son) == k_ir_node) {
2173 /* We are a loop node -> Collect firm nodes */
2175 ir_node *n = le.node;
2178 if (!loop_node_started) {
2179 /* Start a new node which contains all firm nodes of the current loop */
2180 fprintf (F, "node: { title: \"");
2182 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2183 loop_node_started = 1;
2189 bad |= dump_node_opcode(F, n);
2190 bad |= dump_node_mode(F, n);
2191 bad |= dump_node_typeinfo(F, n);
2193 bad |= dump_node_nodeattr(F, n);
2194 fprintf (F, " %ld", get_irn_node_nr(n));
2195 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2196 } else { /* for callgraph loop tree */
2197 assert(get_kind(son) == k_ir_graph);
2198 /* We are a loop node -> Collect firm graphs */
2199 ir_graph *n = (ir_graph *)le.node;
2200 if (!loop_node_started) {
2201 /* Start a new node which contains all firm nodes of the current loop */
2202 fprintf (F, "node: { title: \"");
2204 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2205 loop_node_started = 1;
2210 fprintf (F, " %s", get_irg_dump_name(n));
2211 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2215 if (loop_node_started) {
2216 fprintf(F, "\" }\n");
2217 fprintf (F, "edge: {sourcename: \"");
2219 fprintf (F, "\" targetname: \"");
2221 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2222 loop_node_started = 0;
2226 void dump_loop_tree(ir_graph *irg, const char *suffix)
2229 ir_graph *rem = current_ir_graph;
2230 int el_rem = edge_label;
2233 /* if a filter is set, dump only the irg's that match the filter */
2234 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2237 current_ir_graph = irg;
2239 f = vcg_open(irg, suffix, "-looptree");
2240 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2242 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2246 edge_label = el_rem;
2247 current_ir_graph = rem;
2250 void dump_callgraph_loop_tree(char *suffix) {
2252 F = vcg_open_name("Callgraph_looptree", suffix);
2253 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2254 dump_loops_standalone(F, irp->outermost_cg_loop);
2259 /*******************************************************************************/
2260 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2261 /*******************************************************************************/
2263 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2264 int i, son_number = 0, node_number = 0;
2266 if (dump_loop_information_flag) dump_loop_node(F, loop);
2268 for (i = 0; i < get_loop_n_elements(loop); i++) {
2269 loop_element le = get_loop_element(loop, i);
2270 if (*(le.kind) == k_ir_loop) {
2271 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2273 collect_nodeloop(F, le.son, loopnodes);
2275 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2276 eset_insert(loopnodes, le.node);
2281 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2284 for(i = 0; i < get_loop_n_elements(loop); i++) {
2285 loop_element le = get_loop_element(loop, i);
2286 if (*(le.kind) == k_ir_loop) {
2288 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2290 if (is_Block(le.node)) start = 0; else start = -1;
2291 for (j = start; j < get_irn_arity(le.node); j++) {
2292 ir_node *pred = get_irn_n(le.node, j);
2293 if (!eset_contains(loopnodes, pred)) {
2294 eset_insert(extnodes, pred);
2295 if (!is_Block(pred)) {
2296 pred = get_nodes_block(pred);
2297 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2305 void dump_loop(ir_loop *l, const char *suffix) {
2308 eset *loopnodes = eset_create();
2309 eset *extnodes = eset_create();
2312 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2313 F = vcg_open_name (name, suffix);
2314 dump_vcg_header(F, name, NULL);
2316 /* collect all nodes to dump */
2317 collect_nodeloop(F, l, loopnodes);
2318 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2320 /* build block lists */
2321 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2322 set_irn_link(n, NULL);
2323 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2324 set_irn_link(n, NULL);
2325 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2327 b = get_nodes_block(n);
2328 set_irn_link(n, get_irn_link(b));
2331 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2333 b = get_nodes_block(n);
2334 set_irn_link(n, get_irn_link(b));
2338 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2340 fprintf(F, "graph: { title: \"");
2342 fprintf(F, "\" label: \"");
2343 dump_node_opcode(F, b);
2344 fprintf (F, " %ld", get_irn_node_nr(b));
2345 fprintf(F, "\" status:clustered color:yellow\n");
2347 /* dump the blocks edges */
2348 dump_ir_data_edges(F, b);
2350 /* dump the nodes that go into the block */
2351 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2352 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2354 overrule_nodecolor = NULL;
2355 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2358 /* Close the vcg information for the block */
2360 dump_const_node_local(F, b);
2363 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2365 fprintf(F, "graph: { title: \"");
2367 fprintf(F, "\" label: \"");
2368 dump_node_opcode(F, b);
2369 fprintf (F, " %ld", get_irn_node_nr(b));
2370 fprintf(F, "\" status:clustered color:lightblue\n");
2372 /* dump the nodes that go into the block */
2373 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2374 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2376 overrule_nodecolor = NULL;
2377 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2380 /* Close the vcg information for the block */
2382 dump_const_node_local(F, b);
2386 eset_destroy(loopnodes);
2387 eset_destroy(extnodes);