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"
26 #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))
115 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
118 return get_mode_name(mode);
123 static const char *get_type_name_ex(type *tp, int *bad)
126 return get_type_name(tp);
131 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
136 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
137 fprintf(F, " targetname: "); PRINT_TYPEID(T);
138 vfprintf(F, fmt, ap);
143 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
148 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
149 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
150 vfprintf(F, fmt, ap);
155 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
161 fprintf(F, "backedge: { sourcename: \"");
163 fprintf(F, "edge: { sourcename: \"");
165 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
166 vfprintf(F, fmt, ap);
171 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
176 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
177 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
178 vfprintf(F, fmt, ap);
183 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
188 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
189 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
190 vfprintf(F, fmt, ap);
195 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
200 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
201 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
203 vfprintf(F, fmt, ap);
208 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
213 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
214 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
215 vfprintf(F, fmt, ap);
220 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
225 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
226 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
227 vfprintf(F, fmt, ap);
232 /*******************************************************************/
233 /* global and ahead declarations */
234 /*******************************************************************/
236 /* A suffix to manipulate the file name. */
238 char *dump_file_filter = "";
240 static void dump_whole_node(ir_node *n, void *env);
241 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
243 /*******************************************************************/
244 /* Helper functions. */
245 /*******************************************************************/
247 /* Use private link attr to be able to call dumper anywhere without
248 destroying link fields. */
250 static pmap *irdump_link_map = NULL;
252 static void init_irdump(void) {
253 /* We need a new, empty map. */
254 if (irdump_link_map) pmap_destroy(irdump_link_map);
255 irdump_link_map = pmap_create();
259 void *ird_get_irn_link(ir_node *n) {
261 if (!irdump_link_map) return NULL;
263 if (pmap_contains(irdump_link_map, (void *)n))
264 res = pmap_get(irdump_link_map, (void *)n);
268 void ird_set_irn_link(ir_node *n, void *x) {
269 if (!irdump_link_map) init_irdump();
270 pmap_insert(irdump_link_map, (void *)n, x);
273 void *ird_get_irg_link(ir_graph *irg) {
275 if (!irdump_link_map) return NULL;
277 if (pmap_contains(irdump_link_map, (void *)irg))
278 res = pmap_get(irdump_link_map, (void *)irg);
282 void ird_set_irg_link(ir_graph *irg, void *x) {
283 if (!irdump_link_map) init_irdump();
284 pmap_insert(irdump_link_map, (void *)irg, x);
287 static void clear_link(ir_node * node, void * env) {
288 ird_set_irn_link(node, NULL);
292 static int node_floats(ir_node *n) {
293 return ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
294 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
297 static const char *get_ent_dump_name(entity *ent) {
299 return "<NULL entity>";
300 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
301 if (ent->ld_name) return get_id_str(ent->ld_name);
302 return get_id_str(ent->name);
305 static const char *get_irg_dump_name(ir_graph *irg) {
306 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
307 entity *ent = get_irg_entity(irg);
308 return get_ent_dump_name(ent);
311 static void collect_node(ir_node * node, void *env) {
314 || get_irn_op(node) == op_Bad
315 || get_irn_op(node) == op_Unknown) {
316 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
317 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
318 ARR_APP1(ir_node *, arr, node);
319 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
321 ir_node * block = get_nodes_block(node);
322 ird_set_irn_link(node, ird_get_irn_link(block));
323 ird_set_irn_link(block, node);
327 /** Construct lists to walk ir block-wise.
329 * Collects all blocks, nodes not op_pin_state_pinned,
330 * Bad and Unknown into a flexible array in link field of
331 * irg they belong to. Sets the irg link field to NULL in all
332 * graphs not visited.
333 * Free the list with DEL_ARR_F. */
334 static ir_node ** construct_block_lists(ir_graph *irg) {
335 int i, rem_view = interprocedural_view;
336 ir_graph *rem = current_ir_graph;
337 current_ir_graph = irg;
339 for (i = 0; i < get_irp_n_irgs(); i++)
340 ird_set_irg_link(get_irp_irg(i), NULL);
342 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
344 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
345 interprocedural_view = 0;
346 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
347 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
348 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
349 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
350 interprocedural_view = rem_view;
352 current_ir_graph = rem;
353 return ird_get_irg_link(irg);
356 /*******************************************************************/
357 /* flags to steer output */
358 /*******************************************************************/
360 /* A compiler option to turn off edge labels */
362 /* A compiler option to turn off dumping values of constant entities */
363 int const_entities = 1;
364 /* A compiler option to dump the keep alive edges */
365 int dump_keepalive = 0;
366 /* Compiler options to dump analysis information in dump_ir_graph */
367 int dump_out_edge_flag = 0;
368 int dump_dominator_information_flag = 0;
369 int dump_loop_information_flag = 0;
370 int dump_backedge_information_flag = 1;
371 int dump_const_local = 0;
372 bool opt_dump_analysed_type_info = 1;
373 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
375 char* overrule_nodecolor = NULL;
377 INLINE bool get_opt_dump_const_local(void) {
378 if (!dump_out_edge_flag && !dump_loop_information_flag)
379 return dump_const_local;
384 /* To turn off display of edge labels. Edge labels offen cause xvcg to
385 abort with a segmentation fault. */
386 void turn_off_edge_labels(void) {
390 void dump_consts_local(bool b) {
391 dump_const_local = b;
394 void turn_off_constant_entity_values(void) {
398 void dump_keepalive_edges(bool b) {
402 bool get_opt_dump_keepalive_edges(void) {
403 return dump_keepalive;
406 void dump_out_edges(void) {
407 dump_out_edge_flag = 1;
410 void dump_dominator_information(void) {
411 dump_dominator_information_flag = 1;
414 void dump_loop_information(void) {
415 dump_loop_information_flag = 1;
418 void dont_dump_loop_information(void) {
419 dump_loop_information_flag = 0;
422 void dump_backedge_information(bool b) {
423 dump_backedge_information_flag = b;
426 /* Dump the information of type field specified in ana/irtypeinfo.h.
427 * If the flag is set, the type name is output in [] in the node label,
428 * else it is output as info.
430 void dump_analysed_type_info(bool b) {
431 opt_dump_analysed_type_info = b;
434 void dump_pointer_values_to_info(bool b) {
435 opt_dump_pointer_values_to_info = b;
438 /*******************************************************************/
439 /* Routines to dump information about a single ir node. */
440 /*******************************************************************/
443 dump_node_opcode(FILE *F, ir_node *n)
447 switch(get_irn_opcode(n)) {
452 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
453 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
458 if (get_SymConst_kind(n) == symconst_addr_name) {
459 /* don't use get_SymConst_ptr_info as it mangles the name. */
460 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
461 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
462 assert(get_SymConst_entity(n));
463 assert(is_entity(get_SymConst_entity(n)));
464 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
466 assert(get_kind(get_SymConst_type(n)) == k_type);
467 assert(get_type_ident(get_SymConst_type(n)));
468 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
469 if (get_SymConst_kind(n) == symconst_type_tag)
477 if (!interprocedural_view) fprintf(F, "Proj'");
478 else fprintf(F, "%s", get_irn_opname(n));
482 ir_node *pred = get_Proj_pred(n);
484 if (get_irn_opcode(pred) == iro_Cond
485 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
486 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
487 fprintf (F, "defProj");
489 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
490 * fprintf (F, "Arg");
493 fprintf (F, "%s", get_irn_opname(n));
497 if (interprocedural_view) {
498 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
504 fprintf (F, "%s", get_irn_opname(n));
512 dump_node_mode(FILE *F, ir_node *n)
516 switch (get_irn_opcode(n)) {
535 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
543 static int dump_node_typeinfo(FILE *F, ir_node *n) {
546 if (opt_dump_analysed_type_info) {
547 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
548 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
549 type *tp = get_irn_type(n);
551 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
560 dump_node_nodeattr(FILE *F, ir_node *n)
564 switch (get_irn_opcode(n)) {
566 if (false && interprocedural_view) {
567 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
571 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
572 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
574 fprintf (F, "%ld", get_Proj_proj(n));
578 fprintf (F, "%ld", get_Filter_proj(n));
581 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
584 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
587 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
597 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
600 fprintf(F, "color: red");
603 switch (get_irn_opcode(n)) {
610 fprintf (F, "color: blue");
613 fprintf (F, "color: lightyellow");
616 fprintf (F, "color: green");
622 fprintf (F, "color: yellow");
625 PRINT_DEFAULT_NODE_ATTR;
628 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
631 static INLINE int dump_node_info(FILE *F, ir_node *n)
637 fprintf (F, " info1: \"");
638 if (opt_dump_pointer_values_to_info)
639 fprintf (F, "addr: %p \n", (void *)n);
640 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
641 fprintf (F, "visited: %ld \n", get_irn_visited(n));
642 irg = get_irn_irg(n);
643 if (irg != get_const_code_irg())
644 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
646 fprintf(F, "arity: %d", get_irn_arity(n));
647 if ((get_irn_op(n) == op_Block) ||
648 (get_irn_op(n) == op_Phi) ||
649 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
650 fprintf(F, " backedges:");
652 for (i = 0; i < get_irn_arity(n); i++)
653 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
657 /* Loop node Someone else please tell me what's wrong ...
658 if (get_irn_loop(n)) {
659 ir_loop *loop = get_irn_loop(n);
661 fprintf(F, " in loop %d with depth %d\n",
662 get_loop_loop_nr(loop), get_loop_depth(loop));
667 switch (get_irn_opcode(n)) {
669 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
670 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
671 for (i = 0; i < get_method_n_params(tp); ++i)
672 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
675 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
678 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
681 entity *ent = get_Sel_entity(n);
684 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
685 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
688 fprintf(F, "<NULL entity>\n");
693 type *tp = get_Call_type(n);
694 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
695 for (i = 0; i < get_method_n_params(tp); ++i)
696 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
697 for (i = 0; i < get_method_n_ress(tp); ++i)
698 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
699 if (Call_has_callees(n)) {
700 fprintf(F, "possible callees: \n");
701 for (i = 0; i < get_Call_n_callees(n); i++) {
702 if (!get_Call_callee(n, i)) {
703 fprintf(F, " %d external method\n", i);
705 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
710 case iro_CallBegin: {
711 ir_node *call = get_CallBegin_call(n);
712 if (Call_has_callees(call)) {
713 fprintf(F, "possible callees: \n");
714 for (i = 0; i < get_Call_n_callees(call); i++) {
715 if (!get_Call_callee(call, i)) {
716 fprintf(F, " %d external method\n", i);
718 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
724 if (!interprocedural_view) {
725 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
726 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
727 for (i = 0; i < get_method_n_ress(tp); ++i)
728 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
732 type *tp = get_Const_type(n);
733 assert(tp != none_type);
734 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
738 if (interprocedural_view) {
739 fprintf(F, "intra predecessor nodes:\n");
740 for (i = 0; i < get_irn_intra_arity(n); i++) {
741 ir_node *pred = get_irn_intra_n(n, i);
742 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
745 fprintf(F, "inter predecessor nodes:\n");
746 for (i = 0; i < get_irn_inter_arity(n); i++) {
747 ir_node *pred = get_irn_inter_n(n, i);
748 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
749 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
756 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
757 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
758 if (get_irn_type(n) != none_type)
759 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
768 bool is_constlike_node(ir_node *n) {
769 ir_op *op = get_irn_op(n);
770 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
774 /* outputs the predecessors of n, that are constants, local. I.e.,
775 generates a copy of the constant predecessors for each node called with. */
776 static void dump_const_node_local(FILE *F, ir_node *n) {
778 if (!get_opt_dump_const_local()) return;
780 /* Use visited flag to avoid outputting nodes twice.
781 initialize it first. */
782 for (i = 0; i < get_irn_arity(n); i++) {
783 ir_node *con = get_irn_n(n, i);
784 if (is_constlike_node(con)) {
785 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
789 for (i = 0; i < get_irn_arity(n); i++) {
790 ir_node *con = get_irn_n(n, i);
791 if (is_constlike_node(con) && irn_not_visited(con)) {
794 mark_irn_visited(con);
795 /* Generate a new name for the node by appending the names of
797 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
798 fprintf(F, " label: \"");
799 bad |= dump_node_opcode(F, con);
800 bad |= dump_node_mode(F, con);
801 bad |= dump_node_typeinfo(F, con);
803 bad |= dump_node_nodeattr(F, con);
804 fprintf(F, " %ld", get_irn_node_nr(con));
806 bad |= dump_node_info(F, con);
807 dump_node_vcgattr(F, con, bad);
813 static void INLINE print_node_error(FILE *F, const char *p)
818 fprintf (F, " info2: \"%s\"", p);
821 static void dump_node(FILE *F, ir_node *n)
826 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
828 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
830 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
831 bad |= dump_node_opcode(F, n);
832 bad |= dump_node_mode(F, n);
833 bad |= dump_node_typeinfo(F, n);
835 bad |= dump_node_nodeattr(F, n);
836 fprintf(F, " %ld", get_irn_node_nr(n));
838 bad |= dump_node_info(F, n);
839 print_node_error(F, p);
840 dump_node_vcgattr(F, n, bad);
842 dump_const_node_local(F, n);
849 /* dump the edge to the block this node belongs to */
851 dump_ir_block_edge(FILE *F, ir_node *n) {
852 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
853 if (is_no_Block(n)) {
854 fprintf (F, "edge: { sourcename: \"");
856 fprintf (F, "\" targetname: \"");
857 PRINT_NODEID(get_nodes_block(n));
858 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
863 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
864 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
865 fprintf (F, INTRA_DATA_EDGE_ATTR);
867 fprintf (F, INTER_DATA_EDGE_ATTR);
871 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
872 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
873 fprintf (F, INTRA_MEM_EDGE_ATTR);
875 fprintf (F, INTER_MEM_EDGE_ATTR);
879 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
882 if (dump_backedge_information_flag && is_backedge(from, to))
883 fprintf (F, BACK_EDGE_ATTR);
885 switch (get_irn_opcode(from)) {
887 fprintf (F, CF_EDGE_ATTR);
889 case iro_Start: break;
892 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
893 fprintf (F, CF_EDGE_ATTR);
894 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
895 fprintf (F, INTER_MEM_EDGE_ATTR);
903 print_data_edge_vcgattr(F, from, to);
908 print_mem_edge_vcgattr(F, from, to);
910 print_data_edge_vcgattr(F, from, to);
914 print_data_edge_vcgattr(F, from, to);
919 print_mem_edge_vcgattr(F, from, to);
921 print_data_edge_vcgattr(F, from, to);
928 print_data_edge_vcgattr(F, from, to);
935 print_mem_edge_vcgattr(F, from, to);
937 print_data_edge_vcgattr(F, from, to);
949 print_data_edge_vcgattr(F, from, to);
952 if (get_irn_modecode(from) == irm_M)
953 fprintf (F, INTER_MEM_EDGE_ATTR);
955 print_data_edge_vcgattr(F, from, to);
962 print_mem_edge_vcgattr(F, from, to);
964 print_data_edge_vcgattr(F, from, to);
967 print_mem_edge_vcgattr(F, from, to);
969 case iro_Tuple: break;
972 switch (get_irn_modecode(from)) {
974 fprintf (F, CF_EDGE_ATTR);
977 fprintf (F, INTER_MEM_EDGE_ATTR);
980 print_data_edge_vcgattr(F, from, to);
985 case iro_Unknown: break;
987 switch (get_irn_modecode(from)) {
989 fprintf (F, INTRA_MEM_EDGE_ATTR);
992 fprintf (F, CF_EDGE_ATTR);
995 print_data_edge_vcgattr(F, from, to);
1003 /* dump edges to our inputs */
1005 dump_ir_data_edges(FILE *F, ir_node *n) {
1006 int i, visited = get_irn_visited(n);
1008 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1011 for (i = 0; i < get_irn_arity(n); i++) {
1012 ir_node * pred = get_irn_n(n, i);
1015 if ((interprocedural_view && get_irn_visited(pred) < visited))
1016 continue; /* pred not dumped */
1018 if (dump_backedge_information_flag && is_backedge(n, i))
1019 fprintf (F, "backedge: {sourcename: \"");
1021 fprintf (F, "edge: {sourcename: \"");
1023 fprintf (F, "\" targetname: ");
1024 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1025 PRINT_CONSTID(n, pred);
1027 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1029 fprintf (F, " label: \"%d\" ", i);
1030 print_edge_vcgattr(F, n, i);
1035 /** Dumps a node and its edges but not the block edge
1038 dump_node_wo_blockedge (ir_node *n, void *env) {
1041 dump_ir_data_edges(F, n);
1044 /** Dumps a node and its edges.
1047 dump_whole_node (ir_node *n, void *env) {
1049 dump_node_wo_blockedge(n, env);
1050 if (!node_floats(n)) dump_ir_block_edge(F, n);
1054 dump_const_node(ir_node *n, void *env) {
1055 if (is_Block(n)) return;
1056 dump_node_wo_blockedge(n, env);
1059 /***********************************************************************/
1060 /* the following routines dump the nodes/irgs bracketed to graphs. */
1061 /***********************************************************************/
1063 /** Dumps a constant expression as entity initializer, array bound ...
1065 static void dump_const_expression(FILE *F, ir_node *value) {
1066 ir_graph *rem = current_ir_graph;
1067 int rem_dump_const_local = dump_const_local;
1068 dump_const_local = 0;
1069 current_ir_graph = get_const_code_irg();
1070 irg_walk(value, dump_const_node, NULL, F);
1071 /* Decrease visited flag so that we walk with the same flag for the next
1072 expresssion. This guarantees that we don't dump the same node twice,
1073 as for const expressions cse is performed to save memory. */
1074 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1075 current_ir_graph = rem;
1076 dump_const_local = rem_dump_const_local;
1079 /** Dump a block as graph containing its nodes.
1081 * Expects to find nodes belonging to the block as list in its
1083 * Dumps the edges of all nodes including itself. */
1085 dump_whole_block(FILE *F, ir_node *block) {
1087 assert(is_Block(block));
1089 fprintf(F, "graph: { title: \"");
1090 PRINT_NODEID(block);
1091 fprintf(F, "\" label: \"");
1092 dump_node_opcode(F, block);
1093 fprintf (F, " %ld", get_irn_node_nr(block));
1095 if (get_opt_dump_abstvals())
1096 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1098 fprintf(F, "\" status:clustered color:%s \n",
1099 get_Block_matured(block) ? "yellow" : "red");
1101 /* dump the blocks edges */
1102 dump_ir_data_edges(F, block);
1104 /* dump the nodes that go into the block */
1105 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1107 dump_ir_data_edges(F, node);
1110 /* Close the vcg information for the block */
1112 dump_const_node_local(F, block);
1114 dump_chi_term(F, block);
1119 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1120 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1122 dump_block_graph(FILE *F, ir_graph *irg) {
1124 ir_graph *rem = current_ir_graph;
1125 ir_node **arr = ird_get_irg_link(irg);
1126 current_ir_graph = irg;
1128 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1129 ir_node * node = arr[i];
1130 if (is_Block(node)) {
1131 /* Dumps the block and all the nodes in the block, which are to
1132 be found in Block->link. */
1133 dump_whole_block(F, node);
1135 /* Nodes that are not in a Block. */
1137 dump_ir_data_edges(F, node);
1141 if (dump_loop_information_flag) dump_loop_nodes_into_graph(F, irg);
1143 current_ir_graph = rem;
1146 /** Dumps an irg as a graph.
1147 * If interprocedural view edges can point to nodes out of this graph.
1149 static void dump_graph(FILE *F, ir_graph *irg) {
1151 fprintf(F, "graph: { title: \"");
1153 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1154 get_ent_dump_name(get_irg_entity(irg)));
1156 dump_block_graph(F, irg);
1158 /* Close the vcg information for the irg */
1159 fprintf(F, "}\n\n");
1162 /*******************************************************************/
1163 /* Basic type and entity nodes and edges. */
1164 /*******************************************************************/
1166 /* dumps the edges between nodes and their type or entity attributes. */
1167 static void dump_node2type_edges(ir_node *n, void *env)
1172 switch (get_irn_opcode(n)) {
1174 /* @@@ some consts have an entity */
1177 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1178 || (get_SymConst_kind(n) ==symconst_size))
1180 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1184 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1187 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1190 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1193 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1196 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1204 static int print_type_info(FILE *F, type *tp) {
1207 if (get_type_state(tp) == layout_undefined) {
1208 fprintf(F, "state: layout_undefined\n");
1210 fprintf(F, "state: layout_fixed,\n");
1212 if (get_type_mode(tp))
1213 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1214 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1219 static void print_typespecific_info(FILE *F, type *tp) {
1220 switch (get_type_tpop_code(tp)) {
1223 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1230 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1231 fprintf(F, "params: %d\n", get_method_n_params(tp));
1232 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1240 case tpo_enumeration:
1254 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1255 switch (get_type_tpop_code(tp)) {
1258 if (peculiarity_existent == get_class_peculiarity(tp))
1259 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1261 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1265 fprintf (F, " " TYPE_METH_NODE_ATTR);
1276 case tpo_enumeration:
1289 static int print_type_node(FILE *F, type *tp)
1293 fprintf (F, "node: {title: ");
1295 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1296 fprintf (F, " info1: \"");
1297 bad |= print_type_info(F, tp);
1298 print_typespecific_info(F, tp);
1300 print_typespecific_vcgattr(F, tp);
1306 #define X(a) case a: fprintf(F, #a); break
1307 void dump_entity_node(FILE *F, entity *ent)
1309 fprintf (F, "node: {title: \"");
1310 PRINT_ENTID(ent); fprintf(F, "\"");
1311 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1312 fprintf (F, "label: ");
1313 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1314 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1316 fprintf (F, "\nallocation: ");
1317 switch (get_entity_allocation(ent)) {
1318 X(allocation_dynamic);
1319 X(allocation_automatic);
1320 X(allocation_static);
1321 X(allocation_parameter);
1324 fprintf (F, "\nvisibility: ");
1325 switch (get_entity_visibility(ent)) {
1326 X(visibility_local);
1327 X(visibility_external_visible);
1328 X(visibility_external_allocated);
1331 fprintf (F, "\nvariability: ");
1332 switch (get_entity_variability(ent)) {
1333 X(variability_uninitialized);
1334 X(variability_initialized);
1335 X(variability_part_constant);
1336 X(variability_constant);
1339 fprintf (F, "\nvolatility: ");
1340 switch (get_entity_volatility(ent)) {
1341 X(volatility_non_volatile);
1342 X(volatility_is_volatile);
1345 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1346 fprintf(F, "\nname: %s\nld_name: %s",
1347 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1348 fprintf(F, "\noffset(bits): %d", get_entity_offset_bits(ent));
1349 if (is_method_type(get_entity_type(ent))) {
1350 if (get_entity_irg(ent)) /* can be null */
1351 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1353 { fprintf (F, "\nirg = NULL"); }
1355 fprintf(F, "\"\n}\n");
1359 static void dump_enum_item(FILE *F, type *tp, int pos)
1362 ident *id = get_enumeration_nameid(tp, pos);
1363 tarval *tv = get_enumeration_enum(tp, pos);
1365 tarval_snprintf(buf, sizeof(buf), tv);
1366 fprintf (F, "node: {title: \"");
1367 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1368 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1369 fprintf (F, "label: ");
1370 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1371 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1374 /* dumps a type or entity and it's edges. */
1376 dump_type_info(type_or_ent *tore, void *env) {
1378 int i = 0; /* to shutup gcc */
1380 /* dump this type or entity */
1382 switch (get_kind(tore)) {
1385 entity *ent = (entity *)tore;
1388 dump_entity_node(F, ent);
1390 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1391 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1392 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1393 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1394 if(is_class_type(get_entity_owner(ent))) {
1395 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1396 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1398 /* attached subgraphs */
1399 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1400 if (is_atomic_entity(ent)) {
1401 value = get_atomic_ent_value(ent);
1403 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1404 /* DDMN(value); $$$ */
1405 dump_const_expression(F, value);
1408 if (is_compound_entity(ent)) {
1409 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1410 value = get_compound_ent_value(ent, i);
1412 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1413 dump_const_expression(F, value);
1414 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1416 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1417 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1418 get_compound_ent_value_member(ent, i), i);
1427 type *tp = (type *)tore;
1428 print_type_node(F, tp);
1429 /* and now the edges */
1430 switch (get_type_tpop_code(tp)) {
1433 for (i=0; i < get_class_n_supertypes(tp); i++)
1434 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1435 for (i=0; i < get_class_n_members(tp); i++)
1436 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1440 for (i=0; i < get_struct_n_members(tp); i++)
1441 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1445 for (i = 0; i < get_method_n_params(tp); i++)
1446 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1447 for (i = 0; i < get_method_n_ress(tp); i++)
1448 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1452 for (i = 0; i < get_union_n_members(tp); i++)
1453 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1457 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1458 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1459 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1460 ir_node *upper = get_array_upper_bound(tp, i);
1461 ir_node *lower = get_array_lower_bound(tp, i);
1462 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1463 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1464 dump_const_expression(F, upper);
1465 dump_const_expression(F, lower);
1469 case tpo_enumeration:
1471 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1472 dump_enum_item(F, tp, i);
1473 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1478 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1486 break; /* case k_type */
1489 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1491 } /* switch kind_or_entity */
1494 typedef struct _h_env {
1499 /** For dumping class hierarchies.
1500 * Dumps a class type node and a superclass edge.
1501 * If env->dump_ent dumps entities of classes and overwrites edges.
1504 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1507 int i = 0; /* to shutup gcc */
1509 /* dump this type or entity */
1510 switch (get_kind(tore)) {
1512 entity *ent = (entity *)tore;
1513 if (get_entity_owner(ent) == get_glob_type()) break;
1514 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1516 dump_entity_node(F, ent);
1518 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1519 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1520 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1522 } break; /* case k_entity */
1525 type *tp = (type *)tore;
1526 if (tp == get_glob_type()) break;
1527 switch (get_type_tpop_code(tp)) {
1529 print_type_node(F, tp);
1530 /* and now the edges */
1531 for (i=0; i < get_class_n_supertypes(tp); i++)
1533 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1539 break; /* case k_type */
1542 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1544 } /* switch kind_or_entity */
1547 /*******************************************************************/
1548 /* dump analysis information that is expressed in graph terms. */
1549 /*******************************************************************/
1551 /* dump out edges */
1553 dump_out_edge(ir_node *n, void *env) {
1556 for (i = 0; i < get_irn_n_outs(n); i++) {
1557 assert(get_irn_out(n, i));
1558 fprintf (F, "edge: {sourcename: \"");
1560 fprintf (F, "\" targetname: \"");
1561 PRINT_NODEID(get_irn_out(n, i));
1562 fprintf (F, "\" color: red linestyle: dashed");
1568 dump_loop_label(FILE *F, ir_loop *loop) {
1569 fprintf (F, "loop %d, %d sons, %d nodes",
1570 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1573 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1574 fprintf (F, " info1: \"");
1575 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1576 #if DEBUG_libfirm /* GL @@@ debug analyses */
1577 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1583 dump_loop_node(FILE *F, ir_loop *loop) {
1584 fprintf (F, "node: {title: \"");
1586 fprintf (F, "\" label: \"");
1587 dump_loop_label(F, loop);
1589 dump_loop_info(F, loop);
1595 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1597 fprintf (F, "edge: {sourcename: \"");
1599 fprintf (F, "\" targetname: \"");
1600 PRINT_NODEID(get_loop_node(loop, i));
1601 fprintf (F, "\" color: green");
1606 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1608 fprintf (F, "edge: {sourcename: \"");
1610 fprintf (F, "\" targetname: \"");
1611 PRINT_LOOPID(get_loop_son(loop, i));
1612 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1613 get_loop_element_pos(loop, get_loop_son(loop, i)));
1617 void dump_loops(FILE *F, ir_loop *loop) {
1619 /* dump this loop node */
1620 dump_loop_node(F, loop);
1622 /* dump edges to nodes in loop -- only if it is a real loop */
1623 if (get_loop_depth(loop) != 0) {
1624 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1625 dump_loop_node_edge(F, loop, i);
1628 for (i = 0; i < get_loop_n_sons(loop); i++) {
1629 dump_loops(F, get_loop_son(loop, i));
1630 dump_loop_son_edge(F, loop, i);
1635 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1636 ir_graph *rem = current_ir_graph;
1637 current_ir_graph = irg;
1639 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1641 current_ir_graph = rem;
1646 * dumps the VCG header
1649 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1658 if (!orientation) orientation = "bottom_to_top";
1662 "graph: { title: \"ir graph of %s\"\n"
1663 "display_edge_labels: %s\n"
1664 "layoutalgorithm: mindepth\n"
1665 "manhattan_edges: yes\n"
1666 "port_sharing: no\n"
1668 "classname 1: \"intrablock Data\"\n"
1669 "classname 16: \"interblock Data\"\n"
1670 "classname 2: \"Block\"\n"
1671 "classname 13: \"Control Flow\"\n"
1672 "classname 14: \"intrablock Memory\"\n"
1673 "classname 17: \"interblock Memory\"\n"
1674 "classname 15: \"Dominators\"\n"
1675 "classname 3: \"Entity type\"\n"
1676 "classname 4: \"Entity owner\"\n"
1677 "classname 5: \"Method Param\"\n"
1678 "classname 6: \"Method Res\"\n"
1679 "classname 7: \"Super\"\n"
1680 "classname 8: \"Union\"\n"
1681 "classname 9: \"Points-to\"\n"
1682 "classname 10: \"Array Element Type\"\n"
1683 "classname 11: \"Overwrites\"\n"
1684 "classname 12: \"Member\"\n"
1685 "infoname 1: \"Attribute\"\n"
1686 "infoname 2: \"Verification errors\"\n",
1687 name, label, orientation);
1689 fprintf (F, "\n"); /* a separator */
1695 * @param irg The graph to be dumped
1696 * @param suffix1 first filename suffix
1697 * @param suffix2 second filename suffix
1699 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1701 const char *nm = get_irg_dump_name(irg);
1702 int len = strlen(nm), i, j;
1703 char *fname; /* filename to put the vcg information in */
1705 if (!suffix1) suffix1 = "";
1706 if (!suffix2) suffix2 = "";
1708 /* open file for vcg graph */
1709 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1711 /* strncpy (fname, nm, len); */ /* copy the filename */
1713 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1715 fname[j] = '@'; j++; fname[j] = '1'; j++;
1716 } else if (nm[i] == '@') {
1717 fname[j] = '@'; j++; fname[j] = '2'; j++;
1719 fname[j] = nm[i]; j++;
1723 strcat (fname, suffix1); /* append file suffix */
1724 strcat (fname, suffix2); /* append file suffix */
1725 strcat (fname, ".vcg"); /* append the .vcg suffix */
1726 F = fopen (fname, "w"); /* open file for writing */
1728 panic("cannot open %s for writing (%m)", fname); /* not reached */
1738 * @param irg The graph to be dumped
1739 * @param suffix filename suffix
1741 static FILE *vcg_open_name (const char *name, const char *suffix) {
1743 char *fname; /* filename to put the vcg information in */
1744 int i, j, len = strlen(name);
1746 if (!suffix) suffix = "";
1748 /** open file for vcg graph */
1749 fname = malloc (len * 2 + 5 + strlen(suffix));
1750 /* strcpy (fname, name);*/ /* copy the filename */
1752 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1753 if (name[i] == '/') {
1754 fname[j] = '@'; j++; fname[j] = '1'; j++;
1755 } else if (name[i] == '@') {
1756 fname[j] = '@'; j++; fname[j] = '2'; j++;
1758 fname[j] = name[i]; j++;
1762 strcat (fname, suffix);
1763 strcat (fname, ".vcg"); /* append the .vcg suffix */
1764 F = fopen (fname, "w"); /* open file for writing */
1766 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1774 * Dumps the vcg file footer
1776 static INLINE void dump_vcg_footer (FILE *F) {
1781 * close the vcg file
1784 vcg_close (FILE *F) {
1785 dump_vcg_footer(F); /* print footer */
1786 fclose (F); /* close vcg file */
1789 /************************************************************************/
1790 /************************************************************************/
1791 /* Routines that dump all or parts of the firm representation to a file */
1792 /************************************************************************/
1793 /************************************************************************/
1795 /************************************************************************/
1796 /* Dump ir graphs, differnt formats and additional information. */
1797 /************************************************************************/
1799 /** Routine to dump a graph, blocks as conventional nodes.
1802 dump_ir_graph (ir_graph *irg, char *suffix )
1807 rem = current_ir_graph;
1809 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1810 current_ir_graph = irg;
1811 if (interprocedural_view) suffix1 = "-pure-ip";
1812 else suffix1 = "-pure";
1813 f = vcg_open(irg, suffix, suffix1);
1814 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1816 /* walk over the graph */
1817 /* dump_whole_node must be called in post visiting predecessors */
1818 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1820 /* dump the out edges in a separate walk */
1821 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1822 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1827 current_ir_graph = rem;
1832 dump_ir_block_graph (ir_graph *irg, char *suffix)
1838 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1839 if (interprocedural_view) suffix1 = "-ip";
1841 f = vcg_open(irg, suffix, suffix1);
1842 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1844 construct_block_lists(irg);
1846 for (i = 0; i < get_irp_n_irgs(); i++) {
1847 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1849 dump_graph(f, get_irp_irg(i));
1857 /** dumps a graph with type information
1860 dump_ir_graph_w_types (ir_graph *irg, char *suffix)
1863 ir_graph *rem = current_ir_graph;
1866 /* if a filter is set, dump only the irg's that match the filter */
1867 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1870 current_ir_graph = irg;
1872 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1873 else suffix1 = "-pure-wtypes";
1874 f = vcg_open(irg,suffix, suffix1);
1875 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1877 /* dump common ir graph */
1878 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1879 /* dump type info */
1880 type_walk_irg(irg, dump_type_info, NULL, f);
1881 inc_irg_visited(get_const_code_irg());
1882 /* dump edges from graph to type info */
1883 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1886 current_ir_graph = rem;
1890 dump_ir_block_graph_w_types (ir_graph *irg, char *suffix)
1895 ir_graph *rem = current_ir_graph;
1897 /* if a filter is set, dump only the irg's that match the filter */
1898 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1901 if (interprocedural_view) suffix1 = "-wtypes-ip";
1902 else suffix1 = "-wtypes";
1903 f = vcg_open(irg, suffix, suffix1);
1904 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1906 /* dump common blocked ir graph */
1907 construct_block_lists(irg);
1909 for (i = 0; i < get_irp_n_irgs(); i++) {
1910 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1912 dump_graph(f, get_irp_irg(i));
1917 /* dump type info */
1918 current_ir_graph = irg;
1919 type_walk_irg(irg, dump_type_info, NULL, f);
1920 inc_irg_visited(get_const_code_irg());
1922 /* dump edges from graph to type info */
1923 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1925 current_ir_graph = rem;
1929 /***********************************************************************/
1930 /* The following routines dump a control flow graph. */
1931 /***********************************************************************/
1934 dump_block_to_cfg(ir_node *block, void *env) {
1939 if (is_Block(block)) {
1940 /* This is a block. Dump a node for the block. */
1941 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1942 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1943 PRINT_NODEID(block);
1945 if (dump_dominator_information_flag)
1946 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1948 /* Dump the edges */
1949 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1950 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1951 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1952 fprintf (F, "edge: { sourcename: \"");
1953 PRINT_NODEID(block);
1954 fprintf (F, "\" targetname: \"");
1956 fprintf (F, "\"}\n");
1959 /* Dump dominator edge */
1960 if (dump_dominator_information_flag && get_Block_idom(block)) {
1961 pred = get_Block_idom(block);
1962 fprintf (F, "edge: { sourcename: \"");
1963 PRINT_NODEID(block);
1964 fprintf (F, "\" targetname: \"");
1966 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1972 dump_cfg (ir_graph *irg, char *suffix)
1975 ir_graph *rem = current_ir_graph;
1976 int ddif = dump_dominator_information_flag;
1977 int ipv = interprocedural_view;
1979 /* if a filter is set, dump only the irg's that match the filter */
1980 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
1983 current_ir_graph = irg;
1985 f = vcg_open(irg, suffix, "-cfg");
1986 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1988 if (interprocedural_view) {
1989 printf("Warning: dumping cfg not in interprocedural view!\n");
1990 interprocedural_view = 0;
1993 if (get_irg_dom_state(irg) != dom_consistent)
1994 dump_dominator_information_flag = 0;
1996 /* walk over the blocks in the graph */
1997 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
1998 dump_node(f, get_irg_bad(irg));
2000 dump_dominator_information_flag = ddif;
2001 interprocedural_view = ipv;
2003 current_ir_graph = rem;
2008 void dump_callgraph(char *filesuffix) {
2010 int i, n_irgs = get_irp_n_irgs();
2012 F = vcg_open_name("Callgraph", filesuffix);
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\" color:red" :
2028 print_ent_ent_edge(F, ent, c, be, attr);
2036 /* Dump all irgs in interprocedural view to a single file. */
2037 void dump_all_cg_block_graph(char *suffix) {
2040 int rem_view = interprocedural_view;
2041 interprocedural_view = 1;
2043 f = vcg_open_name("All_graphs", suffix);
2044 dump_vcg_header(f, "All_graphs", NULL);
2046 /* collect nodes in all irgs reachable in call graph*/
2047 for (i = 0; i < get_irp_n_irgs(); i++)
2048 ird_set_irg_link(get_irp_irg(i), NULL);
2050 cg_walk(clear_link, collect_node, NULL);
2052 /* dump all graphs */
2053 for (i = 0; i < get_irp_n_irgs(); i++) {
2054 current_ir_graph = get_irp_irg(i);
2055 assert(ird_get_irg_link(current_ir_graph));
2056 dump_graph(f, current_ir_graph);
2057 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2061 interprocedural_view = rem_view;
2064 /***********************************************************************/
2065 /* the following routines dumps type information without any ir nodes. */
2066 /***********************************************************************/
2069 dump_type_graph (ir_graph *irg, char *suffix)
2073 rem = current_ir_graph;
2075 /* if a filter is set, dump only the irg's that match the filter */
2076 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2078 current_ir_graph = irg;
2080 f = vcg_open(irg, suffix, "-type");
2081 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2083 /* walk over the blocks in the graph */
2084 type_walk_irg(irg, dump_type_info, NULL, f);
2085 /* The walker for the const code can be called several times for the
2086 same (sub) experssion. So that no nodes are dumped several times
2087 we decrease the visited flag of the corresponding graph after each
2088 walk. So now increase it finally. */
2089 inc_irg_visited(get_const_code_irg());
2092 current_ir_graph = rem;
2096 dump_all_types (char *suffix)
2098 FILE *f = vcg_open_name("All_types", suffix);
2099 dump_vcg_header(f, "All_types", NULL);
2100 type_walk(dump_type_info, NULL, f);
2101 inc_irg_visited(get_const_code_irg());
2106 dump_class_hierarchy (bool entities, char *suffix)
2108 FILE *f = vcg_open_name("class_hierarchy", suffix);
2112 dump_vcg_header(f, "class_hierarchy", NULL);
2117 type_walk(dump_class_hierarchy_node, NULL, &env);
2121 /***********************************************************************/
2122 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2124 /* dump_ir_block_graph */
2126 /* dump_type_graph */
2127 /* dump_ir_graph_w_types */
2128 /***********************************************************************/
2130 void dump_all_ir_graphs(dump_graph_func *dmp_grph, char *suffix) {
2132 for (i=0; i < get_irp_n_irgs(); i++) {
2133 dmp_grph(get_irp_irg(i), suffix);
2138 /**********************************************************************************
2139 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2140 * packed together in one subgraph *
2141 **********************************************************************************/
2145 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2146 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2148 ir_loop *son = NULL;
2150 /* Dump a new loop node. */
2151 dump_loop_node(F, loop);
2153 /* Dump the loop elements. */
2155 for(i = 0; i < get_loop_n_elements(loop); i++) {
2156 le = get_loop_element(loop, i);
2158 if (get_kind(son) == k_ir_loop) {
2160 /* We are a loop son -> Recurse */
2162 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2163 fprintf(F, "\" }\n");
2164 fprintf (F, "edge: {sourcename: \"");
2166 fprintf (F, "\" targetname: \"");
2168 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2169 loop_node_started = 0;
2171 dump_loop_son_edge(F, loop, son_number++);
2172 dump_loops_standalone(F, son);
2173 } else if (get_kind(son) == k_ir_node) {
2174 /* We are a loop node -> Collect firm nodes */
2176 ir_node *n = le.node;
2179 if (!loop_node_started) {
2180 /* Start a new node which contains all firm nodes of the current loop */
2181 fprintf (F, "node: { title: \"");
2183 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2184 loop_node_started = 1;
2190 bad |= dump_node_opcode(F, n);
2191 bad |= dump_node_mode(F, n);
2192 bad |= dump_node_typeinfo(F, n);
2194 bad |= dump_node_nodeattr(F, n);
2195 fprintf (F, " %ld", get_irn_node_nr(n));
2197 #if CALLGRAPH_LOOP_TREE
2199 assert(get_kind(son) == k_ir_graph);
2200 /* We are a loop node -> Collect firm graphs */
2202 ir_graph *n = (ir_graph *)le.node;
2204 if (!loop_node_started) {
2205 /* Start a new node which contains all firm nodes of the current loop */
2206 fprintf (F, "node: { title: \"");
2208 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2209 loop_node_started = 1;
2215 fprintf (F, " %s", get_irg_dump_name(n));
2220 if (loop_node_started) {
2221 fprintf(F, "\" }\n");
2222 fprintf (F, "edge: {sourcename: \"");
2224 fprintf (F, "\" targetname: \"");
2226 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2227 loop_node_started = 0;
2231 void dump_loop_tree(ir_graph *irg, char *suffix)
2234 ir_graph *rem = current_ir_graph;
2235 int el_rem = edge_label;
2238 /* if a filter is set, dump only the irg's that match the filter */
2239 if (strncmp(get_irg_dump_name(irg), dump_file_filter, strlen(dump_file_filter)) != 0)
2242 current_ir_graph = irg;
2244 f = vcg_open(irg, suffix, "-looptree");
2245 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2247 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2251 edge_label = el_rem;
2252 current_ir_graph = rem;
2255 #if CALLGRAPH_LOOP_TREE
2256 /* works, but the tree is meaningless. */
2257 void dump_callgraph_loop_tree(ir_loop *l, char *suffix) {
2258 vcg_open_name("callgraph_looptree", suffix);
2259 dump_vcg_header("callgraph_looptree", "top_to_bottom");
2260 dump_loops_standalone(l);
2266 /*******************************************************************************/
2267 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2268 /*******************************************************************************/
2270 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2271 int i, son_number = 0, node_number = 0;
2273 if (dump_loop_information_flag) dump_loop_node(F, loop);
2275 for (i = 0; i < get_loop_n_elements(loop); i++) {
2276 loop_element le = get_loop_element(loop, i);
2277 if (*(le.kind) == k_ir_loop) {
2278 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2280 collect_nodeloop(F, le.son, loopnodes);
2282 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2283 eset_insert(loopnodes, le.node);
2288 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2291 for(i = 0; i < get_loop_n_elements(loop); i++) {
2292 loop_element le = get_loop_element(loop, i);
2293 if (*(le.kind) == k_ir_loop) {
2295 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2297 if (is_Block(le.node)) start = 0; else start = -1;
2298 for (j = start; j < get_irn_arity(le.node); j++) {
2299 ir_node *pred = get_irn_n(le.node, j);
2300 if (!eset_contains(loopnodes, pred)) {
2301 eset_insert(extnodes, pred);
2302 if (!is_Block(pred)) {
2303 pred = get_nodes_block(pred);
2304 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2312 void dump_loop(ir_loop *l, char *suffix) {
2315 eset *loopnodes = eset_create();
2316 eset *extnodes = eset_create();
2319 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2320 F = vcg_open_name (name, suffix);
2321 dump_vcg_header(F, name, NULL);
2323 /* collect all nodes to dump */
2324 collect_nodeloop(F, l, loopnodes);
2325 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2327 /* build block lists */
2328 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2329 set_irn_link(n, NULL);
2330 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2331 set_irn_link(n, NULL);
2332 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2334 b = get_nodes_block(n);
2335 set_irn_link(n, get_irn_link(b));
2338 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2340 b = get_nodes_block(n);
2341 set_irn_link(n, get_irn_link(b));
2345 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2347 fprintf(F, "graph: { title: \"");
2349 fprintf(F, "\" label: \"");
2350 dump_node_opcode(F, b);
2351 fprintf (F, " %ld", get_irn_node_nr(b));
2352 fprintf(F, "\" status:clustered color:yellow\n");
2354 /* dump the blocks edges */
2355 dump_ir_data_edges(F, b);
2357 /* dump the nodes that go into the block */
2358 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2359 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2361 overrule_nodecolor = NULL;
2362 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2365 /* Close the vcg information for the block */
2367 dump_const_node_local(F, b);
2370 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2372 fprintf(F, "graph: { title: \"");
2374 fprintf(F, "\" label: \"");
2375 dump_node_opcode(F, b);
2376 fprintf (F, " %ld", get_irn_node_nr(b));
2377 fprintf(F, "\" status:clustered color:lightblue\n");
2379 /* dump the nodes that go into the block */
2380 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2381 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2383 overrule_nodecolor = NULL;
2384 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2387 /* Close the vcg information for the block */
2389 dump_const_node_local(F, b);
2393 eset_destroy(loopnodes);
2394 eset_destroy(extnodes);