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.
18 #include "firm_common_t.h"
21 #include "irgraph_t.h"
32 #include "type_or_entity.h"
36 #include "callgraph.h"
46 void dump_chi_term(FILE *FL, ir_node *n);
47 void dump_state(FILE *FL, ir_node *n);
48 int get_opt_dump_abstvals(void);
49 typedef unsigned long SeqNo;
50 SeqNo get_Block_seqno(ir_node *n);
53 /* basis for a color range for vcg */
54 static int n_colors = 0;
55 static int base_color = 0;
57 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
60 return get_mode_name(mode);
65 static const char *get_type_name_ex(type *tp, int *bad)
68 return get_type_name(tp);
73 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
78 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
79 fprintf(F, " targetname: "); PRINT_TYPEID(T);
85 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
90 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
91 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
97 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
103 fprintf(F, "backedge: { sourcename: \"");
105 fprintf(F, "edge: { sourcename: \"");
107 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
108 vfprintf(F, fmt, ap);
113 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
118 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
119 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
120 vfprintf(F, fmt, ap);
125 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
130 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
131 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
132 vfprintf(F, fmt, ap);
137 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
142 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
143 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
145 vfprintf(F, fmt, ap);
150 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
155 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
156 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
157 vfprintf(F, fmt, ap);
162 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
167 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
168 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
169 vfprintf(F, fmt, ap);
174 /*******************************************************************/
175 /* global and ahead declarations */
176 /*******************************************************************/
178 static void dump_whole_node(ir_node *n, void *env);
179 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
181 /*******************************************************************/
182 /* Helper functions. */
183 /*******************************************************************/
185 /* Use private link attr to be able to call dumper anywhere without
186 destroying link fields. */
188 static pmap *irdump_link_map = NULL;
190 static void init_irdump(void) {
191 /* We need a new, empty map. */
192 if (irdump_link_map) pmap_destroy(irdump_link_map);
193 irdump_link_map = pmap_create();
197 void *ird_get_irn_link(ir_node *n) {
199 if (!irdump_link_map) return NULL;
201 if (pmap_contains(irdump_link_map, (void *)n))
202 res = pmap_get(irdump_link_map, (void *)n);
206 void ird_set_irn_link(ir_node *n, void *x) {
207 if (!irdump_link_map) init_irdump();
208 pmap_insert(irdump_link_map, (void *)n, x);
211 void *ird_get_irg_link(ir_graph *irg) {
213 if (!irdump_link_map) return NULL;
215 if (pmap_contains(irdump_link_map, (void *)irg))
216 res = pmap_get(irdump_link_map, (void *)irg);
220 void ird_set_irg_link(ir_graph *irg, void *x) {
221 if (!irdump_link_map) init_irdump();
222 pmap_insert(irdump_link_map, (void *)irg, x);
225 static void clear_link(ir_node * node, void * env) {
226 ird_set_irn_link(node, NULL);
230 static int node_floats(ir_node *n) {
231 return ((get_irn_pinned(n) == op_pin_state_floats) &&
232 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
235 const char *get_ent_dump_name(entity *ent) {
237 return "<NULL entity>";
238 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
239 if (ent->ld_name) return get_id_str(ent->ld_name);
240 return get_id_str(ent->name);
243 const char *get_irg_dump_name(ir_graph *irg) {
244 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
245 entity *ent = get_irg_entity(irg);
246 return get_ent_dump_name(ent);
249 static void collect_node(ir_node * node, void *env) {
252 || get_irn_op(node) == op_Bad
253 || get_irn_op(node) == op_Unknown) {
254 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
255 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
256 ARR_APP1(ir_node *, arr, node);
257 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
259 ir_node * block = get_nodes_block(node);
260 ird_set_irn_link(node, ird_get_irn_link(block));
261 ird_set_irn_link(block, node);
265 /** Construct lists to walk ir block-wise.
267 * Collects all blocks, nodes not op_pin_state_pinned,
268 * Bad and Unknown into a flexible array in link field of
269 * irg they belong to. Sets the irg link field to NULL in all
270 * graphs not visited.
271 * Free the list with DEL_ARR_F. */
272 static ir_node ** construct_block_lists(ir_graph *irg) {
273 int i, rem_view = get_interprocedural_view();
274 ir_graph *rem = current_ir_graph;
275 current_ir_graph = irg;
277 for (i = 0; i < get_irp_n_irgs(); i++)
278 ird_set_irg_link(get_irp_irg(i), NULL);
280 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
282 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
283 set_interprocedural_view(false);
284 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
285 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
286 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
287 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
288 set_interprocedural_view(rem_view);
290 current_ir_graph = rem;
291 return ird_get_irg_link(irg);
294 /*******************************************************************/
295 /* flags to steer output */
296 /*******************************************************************/
298 const char *dump_file_filter = "";
300 /* A compiler option to turn off edge labels */
302 /* A compiler option to turn off dumping values of constant entities */
303 int const_entities = 1;
304 /* A compiler option to dump the keep alive edges */
305 int dump_keepalive = 0;
306 /* Compiler options to dump analysis information in dump_ir_graph */
307 int dump_out_edge_flag = 0;
308 int dump_dominator_information_flag = 0;
309 int dump_loop_information_flag = 0;
310 int dump_backedge_information_flag = 1;
311 int dump_const_local = 0;
312 bool opt_dump_analysed_type_info = 1;
313 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
315 char* overrule_nodecolor = NULL;
317 INLINE bool get_opt_dump_const_local(void) {
318 if (!dump_out_edge_flag && !dump_loop_information_flag)
319 return dump_const_local;
324 void only_dump_method_with_name(ident *name) {
325 dump_file_filter = get_id_str(name);
329 /* To turn off display of edge labels. Edge labels offen cause xvcg to
330 abort with a segmentation fault. */
331 void turn_off_edge_labels(void) {
335 void dump_consts_local(bool b) {
336 dump_const_local = b;
339 void turn_off_constant_entity_values(void) {
343 void dump_keepalive_edges(bool b) {
347 bool get_opt_dump_keepalive_edges(void) {
348 return dump_keepalive;
351 void dump_out_edges(void) {
352 dump_out_edge_flag = 1;
355 void dump_dominator_information(void) {
356 dump_dominator_information_flag = 1;
359 void dump_loop_information(void) {
360 dump_loop_information_flag = 1;
363 void dont_dump_loop_information(void) {
364 dump_loop_information_flag = 0;
367 void dump_backedge_information(bool b) {
368 dump_backedge_information_flag = b;
371 /* Dump the information of type field specified in ana/irtypeinfo.h.
372 * If the flag is set, the type name is output in [] in the node label,
373 * else it is output as info.
375 void dump_analysed_type_info(bool b) {
376 opt_dump_analysed_type_info = b;
379 void dump_pointer_values_to_info(bool b) {
380 opt_dump_pointer_values_to_info = b;
383 /*-----------------------------------------------------------------*/
384 /* Routines to dump information about a single ir node. */
385 /*-----------------------------------------------------------------*/
388 dump_node_opcode(FILE *F, ir_node *n)
392 switch(get_irn_opcode(n)) {
397 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
398 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
403 if (get_SymConst_kind(n) == symconst_addr_name) {
404 /* don't use get_SymConst_ptr_info as it mangles the name. */
405 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
406 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
407 assert(get_SymConst_entity(n));
408 assert(is_entity(get_SymConst_entity(n)));
409 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
411 assert(get_kind(get_SymConst_type(n)) == k_type);
412 assert(get_type_ident(get_SymConst_type(n)));
413 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
414 if (get_SymConst_kind(n) == symconst_type_tag)
422 if (!get_interprocedural_view())
429 ir_node *pred = get_Proj_pred(n);
431 if (get_irn_opcode(pred) == iro_Cond
432 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
433 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
434 fprintf (F, "defProj");
436 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
437 * fprintf (F, "Arg");
446 if (get_interprocedural_view()) {
447 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
452 case iro_CallBegin: {
453 ir_node *addr = get_CallBegin_ptr(n);
455 if (get_irn_op(addr) == op_Sel)
456 ent = get_Sel_entity(addr);
457 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
458 ent = get_SymConst_entity(addr);
459 fprintf (F, "%s", get_irn_opname(n));
460 if (ent) fprintf (F, " %s", get_entity_name(ent));
464 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
469 fprintf (F, "%s", get_irn_opname(n));
477 dump_node_mode(FILE *F, ir_node *n)
480 opcode iro = get_irn_opcode(n);
492 ir_mode *mode = get_irn_mode(n);
494 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
495 (mode != mode_T || iro == iro_Proj))
496 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
503 static int dump_node_typeinfo(FILE *F, ir_node *n) {
506 if (opt_dump_analysed_type_info) {
507 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
508 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
509 type *tp = get_irn_typeinfo_type(n);
511 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
520 dump_node_nodeattr(FILE *F, ir_node *n)
524 switch (get_irn_opcode(n)) {
526 if (false && get_interprocedural_view()) {
527 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
531 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
532 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
534 fprintf (F, "%ld", get_Proj_proj(n));
538 fprintf (F, "%ld", get_Filter_proj(n));
541 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
544 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
547 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
557 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
560 fprintf(F, "color: red");
563 switch (get_irn_opcode(n)) {
570 fprintf (F, "color: blue");
573 fprintf (F, "color: lightyellow");
576 fprintf (F, "color: green");
582 fprintf (F, "color: yellow");
585 PRINT_DEFAULT_NODE_ATTR;
588 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
591 static INLINE int dump_node_info(FILE *F, ir_node *n)
597 fprintf (F, " info1: \"");
598 if (opt_dump_pointer_values_to_info)
599 fprintf (F, "addr: %p \n", (void *)n);
600 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
601 fprintf (F, "visited: %ld \n", get_irn_visited(n));
602 irg = get_irn_irg(n);
603 if (irg != get_const_code_irg())
604 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
606 if (get_irn_pinned(n) == op_pin_state_floats &&
607 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
608 fprintf(F, "node was pinned in ");
609 dump_node_opcode(F, get_nodes_block(n));
610 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
614 /* show all predecessor nodes */
615 fprintf(F, "pred nodes: \n");
618 dump_node_opcode(F, get_nodes_block(n));
619 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
621 for ( i = 0; i < get_irn_arity(n); ++i) {
622 fprintf(F, " %d: ", i);
623 dump_node_opcode(F, get_irn_n(n, i));
624 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
628 fprintf(F, "arity: %d", get_irn_arity(n));
629 if ((get_irn_op(n) == op_Block) ||
630 (get_irn_op(n) == op_Phi) ||
631 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
632 fprintf(F, " backedges:");
634 for (i = 0; i < get_irn_arity(n); i++)
635 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
639 /* Loop node Someone else please tell me what's wrong ...
640 if (get_irn_loop(n)) {
641 ir_loop *loop = get_irn_loop(n);
643 fprintf(F, " in loop %d with depth %d\n",
644 get_loop_loop_nr(loop), get_loop_depth(loop));
649 switch (get_irn_opcode(n)) {
651 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
652 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
653 for (i = 0; i < get_method_n_params(tp); ++i)
654 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
655 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
656 ir_node *sbl = get_nodes_block(n);
657 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
658 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
659 for (i = 0; i < n_cfgpreds; ++i) {
660 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
661 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
662 get_irg_dump_name(get_irn_irg(cfgpred)));
667 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
670 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
673 entity *ent = get_Sel_entity(n);
676 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
677 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
680 fprintf(F, "<NULL entity>\n");
685 type *tp = get_Call_type(n);
686 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
687 if(get_unknown_type() != tp) {
688 for (i = 0; i < get_method_n_params(tp); ++i)
689 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
690 for (i = 0; i < get_method_n_ress(tp); ++i)
691 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
693 if (Call_has_callees(n)) {
694 fprintf(F, "possible callees: \n");
695 for (i = 0; i < get_Call_n_callees(n); i++) {
696 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
700 case iro_CallBegin: {
701 ir_node *call = get_CallBegin_call(n);
702 if (Call_has_callees(call)) {
703 fprintf(F, "possible callees: \n");
704 for (i = 0; i < get_Call_n_callees(call); i++) {
705 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
710 if (!get_interprocedural_view()) {
711 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
712 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
713 for (i = 0; i < get_method_n_ress(tp); ++i)
714 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
718 type *tp = get_Const_type(n);
719 assert(tp != none_type);
720 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
723 switch(get_SymConst_kind(n)) {
724 case symconst_addr_name:
725 fprintf(F, "kind addr_name\n");
727 case symconst_addr_ent:
728 fprintf(F, "kind addr_ent\n");
729 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
731 case symconst_type_tag:
732 fprintf(F, "kind type_tag\n");
735 fprintf(F, "kind size\n");
738 fprintf(F, "SymConst of type %s \n", get_type_name_ex(get_SymConst_value_type(n), &bad));
742 if (get_interprocedural_view()) {
743 fprintf(F, "intra predecessor nodes:\n");
744 for (i = 0; i < get_irn_intra_arity(n); i++) {
745 ir_node *pred = get_irn_intra_n(n, i);
746 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
749 fprintf(F, "inter predecessor nodes:\n");
750 for (i = 0; i < get_irn_inter_arity(n); i++) {
751 ir_node *pred = get_irn_inter_n(n, i);
752 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
753 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
758 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
761 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
767 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
768 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
769 if (get_irn_typeinfo_type(n) != none_type)
770 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
779 bool is_constlike_node(ir_node *n) {
780 ir_op *op = get_irn_op(n);
781 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
785 /* outputs the predecessors of n, that are constants, local. I.e.,
786 generates a copy of the constant predecessors for each node called with. */
787 static void dump_const_node_local(FILE *F, ir_node *n) {
789 if (!get_opt_dump_const_local()) return;
791 /* Use visited flag to avoid outputting nodes twice.
792 initialize it first. */
793 for (i = 0; i < get_irn_arity(n); i++) {
794 ir_node *con = get_irn_n(n, i);
795 if (is_constlike_node(con)) {
796 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
800 for (i = 0; i < get_irn_arity(n); i++) {
801 ir_node *con = get_irn_n(n, i);
802 if (is_constlike_node(con) && irn_not_visited(con)) {
805 mark_irn_visited(con);
806 /* Generate a new name for the node by appending the names of
808 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
809 fprintf(F, " label: \"");
810 bad |= dump_node_opcode(F, con);
811 bad |= dump_node_mode(F, con);
812 bad |= dump_node_typeinfo(F, con);
814 bad |= dump_node_nodeattr(F, con);
815 fprintf(F, " %ld", get_irn_node_nr(con));
817 bad |= dump_node_info(F, con);
818 dump_node_vcgattr(F, con, bad);
824 static void INLINE print_node_error(FILE *F, const char *p)
829 fprintf (F, " info2: \"%s\"", p);
832 static void dump_node(FILE *F, ir_node *n)
837 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
839 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
841 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
842 bad |= dump_node_opcode(F, n);
843 bad |= dump_node_mode(F, n);
844 bad |= dump_node_typeinfo(F, n);
846 bad |= dump_node_nodeattr(F, n);
847 fprintf(F, " %ld", get_irn_node_nr(n));
849 bad |= dump_node_info(F, n);
850 print_node_error(F, p);
851 dump_node_vcgattr(F, n, bad);
853 dump_const_node_local(F, n);
860 /* dump the edge to the block this node belongs to */
862 dump_ir_block_edge(FILE *F, ir_node *n) {
863 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
864 if (is_no_Block(n)) {
865 ir_node *block = get_nodes_block(n);
867 fprintf (F, "edge: { sourcename: \"");
869 fprintf (F, "\" targetname: ");
870 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
871 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
876 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
877 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
878 fprintf (F, INTRA_DATA_EDGE_ATTR);
880 fprintf (F, INTER_DATA_EDGE_ATTR);
884 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
885 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
886 fprintf (F, INTRA_MEM_EDGE_ATTR);
888 fprintf (F, INTER_MEM_EDGE_ATTR);
892 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
895 if (dump_backedge_information_flag && is_backedge(from, to))
896 fprintf (F, BACK_EDGE_ATTR);
898 switch (get_irn_opcode(from)) {
900 fprintf (F, CF_EDGE_ATTR);
902 case iro_Start: break;
905 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
906 fprintf (F, CF_EDGE_ATTR);
907 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
908 fprintf (F, INTER_MEM_EDGE_ATTR);
916 print_data_edge_vcgattr(F, from, to);
921 print_mem_edge_vcgattr(F, from, to);
923 print_data_edge_vcgattr(F, from, to);
927 print_data_edge_vcgattr(F, from, to);
932 print_mem_edge_vcgattr(F, from, to);
934 print_data_edge_vcgattr(F, from, to);
941 print_data_edge_vcgattr(F, from, to);
948 print_mem_edge_vcgattr(F, from, to);
950 print_data_edge_vcgattr(F, from, to);
962 print_data_edge_vcgattr(F, from, to);
965 if (get_irn_modecode(from) == irm_M)
966 fprintf (F, INTER_MEM_EDGE_ATTR);
968 print_data_edge_vcgattr(F, from, to);
975 print_mem_edge_vcgattr(F, from, to);
977 print_data_edge_vcgattr(F, from, to);
980 print_mem_edge_vcgattr(F, from, to);
982 case iro_Tuple: break;
985 switch (get_irn_modecode(from)) {
987 fprintf (F, CF_EDGE_ATTR);
990 fprintf (F, INTER_MEM_EDGE_ATTR);
993 print_data_edge_vcgattr(F, from, to);
998 case iro_Unknown: break;
1000 switch (get_irn_modecode(from)) {
1002 fprintf (F, INTRA_MEM_EDGE_ATTR);
1005 fprintf (F, CF_EDGE_ATTR);
1008 print_data_edge_vcgattr(F, from, to);
1016 /* dump edges to our inputs */
1018 dump_ir_data_edges(FILE *F, ir_node *n) {
1019 int i, visited = get_irn_visited(n);
1021 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1024 for (i = 0; i < get_irn_arity(n); i++) {
1025 ir_node * pred = get_irn_n(n, i);
1028 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1029 continue; /* pred not dumped */
1031 if (dump_backedge_information_flag && is_backedge(n, i))
1032 fprintf (F, "backedge: {sourcename: \"");
1034 fprintf (F, "edge: {sourcename: \"");
1036 fprintf (F, "\" targetname: ");
1037 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1038 PRINT_CONSTID(n, pred);
1040 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1042 fprintf (F, " label: \"%d\" ", i);
1043 print_edge_vcgattr(F, n, i);
1048 /** Dumps a node and its edges but not the block edge
1051 dump_node_wo_blockedge (ir_node *n, void *env) {
1054 dump_ir_data_edges(F, n);
1057 /** Dumps a node and its edges.
1060 dump_whole_node (ir_node *n, void *env) {
1062 dump_node_wo_blockedge(n, env);
1063 if (!node_floats(n)) dump_ir_block_edge(F, n);
1067 dump_const_node(ir_node *n, void *env) {
1068 if (is_Block(n)) return;
1069 dump_node_wo_blockedge(n, env);
1072 /***********************************************************************/
1073 /* the following routines dump the nodes/irgs bracketed to graphs. */
1074 /***********************************************************************/
1076 /** Dumps a constant expression as entity initializer, array bound ...
1078 static void dump_const_expression(FILE *F, ir_node *value) {
1079 ir_graph *rem = current_ir_graph;
1080 int rem_dump_const_local = dump_const_local;
1081 dump_const_local = 0;
1082 current_ir_graph = get_const_code_irg();
1083 irg_walk(value, dump_const_node, NULL, F);
1084 /* Decrease visited flag so that we walk with the same flag for the next
1085 expresssion. This guarantees that we don't dump the same node twice,
1086 as for const expressions cse is performed to save memory. */
1087 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1088 current_ir_graph = rem;
1089 dump_const_local = rem_dump_const_local;
1092 /** Dump a block as graph containing its nodes.
1094 * Expects to find nodes belonging to the block as list in its
1096 * Dumps the edges of all nodes including itself. */
1098 dump_whole_block(FILE *F, ir_node *block) {
1100 assert(is_Block(block));
1102 fprintf(F, "graph: { title: \"");
1103 PRINT_NODEID(block);
1104 fprintf(F, "\" label: \"");
1105 dump_node_opcode(F, block);
1106 fprintf (F, " %ld", get_irn_node_nr(block));
1108 if (get_opt_dump_abstvals())
1109 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1111 fprintf(F, "\" status:clustered color:%s \n",
1112 get_Block_matured(block) ? "yellow" : "red");
1114 /* dump the blocks edges */
1115 dump_ir_data_edges(F, block);
1117 /* dump the nodes that go into the block */
1118 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1120 dump_ir_data_edges(F, node);
1123 /* Close the vcg information for the block */
1125 dump_const_node_local(F, block);
1127 dump_chi_term(F, block);
1132 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1133 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1135 dump_block_graph(FILE *F, ir_graph *irg) {
1137 ir_graph *rem = current_ir_graph;
1138 ir_node **arr = ird_get_irg_link(irg);
1139 current_ir_graph = irg;
1141 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1142 ir_node * node = arr[i];
1143 if (is_Block(node)) {
1144 /* Dumps the block and all the nodes in the block, which are to
1145 be found in Block->link. */
1146 dump_whole_block(F, node);
1148 /* Nodes that are not in a Block. */
1150 dump_ir_data_edges(F, node);
1154 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1155 dump_loop_nodes_into_graph(F, irg);
1157 current_ir_graph = rem;
1160 /** Dumps an irg as a graph.
1161 * If interprocedural view edges can point to nodes out of this graph.
1163 static void dump_graph(FILE *F, ir_graph *irg) {
1165 fprintf(F, "graph: { title: \"");
1167 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1168 get_ent_dump_name(get_irg_entity(irg)));
1170 dump_block_graph(F, irg);
1172 /* Close the vcg information for the irg */
1173 fprintf(F, "}\n\n");
1176 /*******************************************************************/
1177 /* Basic type and entity nodes and edges. */
1178 /*******************************************************************/
1180 /* dumps the edges between nodes and their type or entity attributes. */
1181 static void dump_node2type_edges(ir_node *n, void *env)
1186 switch (get_irn_opcode(n)) {
1188 /* @@@ some consts have an entity */
1191 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1192 || (get_SymConst_kind(n) ==symconst_size))
1194 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1198 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1201 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1204 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1207 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1210 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1218 static int print_type_info(FILE *F, type *tp) {
1221 if (get_type_state(tp) == layout_undefined) {
1222 fprintf(F, "state: layout_undefined\n");
1224 fprintf(F, "state: layout_fixed,\n");
1226 if (get_type_mode(tp))
1227 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1228 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1233 static void print_typespecific_info(FILE *F, type *tp) {
1234 switch (get_type_tpop_code(tp)) {
1237 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1244 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1245 fprintf(F, "params: %d\n", get_method_n_params(tp));
1246 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1254 case tpo_enumeration:
1268 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1269 switch (get_type_tpop_code(tp)) {
1272 if (peculiarity_existent == get_class_peculiarity(tp))
1273 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1275 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1279 fprintf (F, " " TYPE_METH_NODE_ATTR);
1290 case tpo_enumeration:
1303 static int print_type_node(FILE *F, type *tp)
1307 fprintf (F, "node: {title: ");
1309 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1310 fprintf (F, " info1: \"");
1311 bad |= print_type_info(F, tp);
1312 print_typespecific_info(F, tp);
1314 print_typespecific_vcgattr(F, tp);
1320 #define X(a) case a: fprintf(F, #a); break
1321 void dump_entity_node(FILE *F, entity *ent, int color)
1323 fprintf (F, "node: {title: \"");
1324 PRINT_ENTID(ent); fprintf(F, "\"");
1325 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1326 fprintf (F, "label: ");
1327 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1329 fprintf(F, "color: %d", color);
1331 fprintf (F, ENTITY_NODE_ATTR);
1332 fprintf (F, "\n info1: \"");
1334 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1336 fprintf(F, "\"\n}\n");
1340 static void dump_enum_item(FILE *F, type *tp, int pos)
1343 ident *id = get_enumeration_nameid(tp, pos);
1344 tarval *tv = get_enumeration_enum(tp, pos);
1346 tarval_snprintf(buf, sizeof(buf), tv);
1347 fprintf (F, "node: {title: \"");
1348 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1349 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1350 fprintf (F, "label: ");
1351 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1352 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1355 /* dumps a type or entity and it's edges. */
1357 dump_type_info(type_or_ent *tore, void *env) {
1359 int i = 0; /* to shutup gcc */
1361 /* dump this type or entity */
1363 switch (get_kind(tore)) {
1366 entity *ent = (entity *)tore;
1369 dump_entity_node(F, ent, 0);
1371 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1372 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1373 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1374 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1375 if(is_class_type(get_entity_owner(ent))) {
1376 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1377 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1379 /* attached subgraphs */
1380 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1381 if (is_atomic_entity(ent)) {
1382 value = get_atomic_ent_value(ent);
1384 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1385 /* DDMN(value); $$$ */
1386 dump_const_expression(F, value);
1389 if (is_compound_entity(ent)) {
1390 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1391 value = get_compound_ent_value(ent, i);
1393 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1394 dump_const_expression(F, value);
1395 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1397 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1398 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1399 get_compound_ent_value_member(ent, i), i);
1408 type *tp = (type *)tore;
1409 print_type_node(F, tp);
1410 /* and now the edges */
1411 switch (get_type_tpop_code(tp)) {
1414 for (i=0; i < get_class_n_supertypes(tp); i++)
1415 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1416 for (i=0; i < get_class_n_members(tp); i++)
1417 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1421 for (i=0; i < get_struct_n_members(tp); i++)
1422 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1426 for (i = 0; i < get_method_n_params(tp); i++)
1427 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1428 for (i = 0; i < get_method_n_ress(tp); i++)
1429 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1433 for (i = 0; i < get_union_n_members(tp); i++)
1434 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1438 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1439 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1440 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1441 ir_node *upper = get_array_upper_bound(tp, i);
1442 ir_node *lower = get_array_lower_bound(tp, i);
1443 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1444 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1445 dump_const_expression(F, upper);
1446 dump_const_expression(F, lower);
1450 case tpo_enumeration:
1452 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1453 dump_enum_item(F, tp, i);
1454 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1459 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1467 break; /* case k_type */
1470 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1472 } /* switch kind_or_entity */
1475 typedef struct _h_env {
1480 /** For dumping class hierarchies.
1481 * Dumps a class type node and a superclass edge.
1482 * If env->dump_ent dumps entities of classes and overwrites edges.
1485 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1488 int i = 0; /* to shutup gcc */
1490 /* dump this type or entity */
1491 switch (get_kind(tore)) {
1493 entity *ent = (entity *)tore;
1494 if (get_entity_owner(ent) == get_glob_type()) break;
1495 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1496 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1498 dump_entity_node(F, ent, 0);
1500 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1501 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1502 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1504 } break; /* case k_entity */
1507 type *tp = (type *)tore;
1508 if (tp == get_glob_type()) break;
1509 switch (get_type_tpop_code(tp)) {
1511 print_type_node(F, tp);
1512 /* and now the edges */
1513 for (i=0; i < get_class_n_supertypes(tp); i++)
1515 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1521 break; /* case k_type */
1524 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1526 } /* switch kind_or_entity */
1529 /*******************************************************************/
1530 /* dump analysis information that is expressed in graph terms. */
1531 /*******************************************************************/
1533 /* dump out edges */
1535 dump_out_edge(ir_node *n, void *env) {
1538 for (i = 0; i < get_irn_n_outs(n); i++) {
1539 assert(get_irn_out(n, i));
1540 fprintf (F, "edge: {sourcename: \"");
1542 fprintf (F, "\" targetname: \"");
1543 PRINT_NODEID(get_irn_out(n, i));
1544 fprintf (F, "\" color: red linestyle: dashed");
1550 dump_loop_label(FILE *F, ir_loop *loop) {
1551 fprintf (F, "loop %d, %d sons, %d nodes",
1552 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1555 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1556 fprintf (F, " info1: \"");
1557 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1558 #if DEBUG_libfirm /* GL @@@ debug analyses */
1559 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1565 dump_loop_node(FILE *F, ir_loop *loop) {
1566 fprintf (F, "node: {title: \"");
1568 fprintf (F, "\" label: \"");
1569 dump_loop_label(F, loop);
1571 dump_loop_info(F, loop);
1577 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1579 fprintf (F, "edge: {sourcename: \"");
1581 fprintf (F, "\" targetname: \"");
1582 PRINT_NODEID(get_loop_node(loop, i));
1583 fprintf (F, "\" color: green");
1588 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1590 fprintf (F, "edge: {sourcename: \"");
1592 fprintf (F, "\" targetname: \"");
1593 PRINT_LOOPID(get_loop_son(loop, i));
1594 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1595 get_loop_element_pos(loop, get_loop_son(loop, i)));
1599 void dump_loops(FILE *F, ir_loop *loop) {
1601 /* dump this loop node */
1602 dump_loop_node(F, loop);
1604 /* dump edges to nodes in loop -- only if it is a real loop */
1605 if (get_loop_depth(loop) != 0) {
1606 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1607 dump_loop_node_edge(F, loop, i);
1610 for (i = 0; i < get_loop_n_sons(loop); i++) {
1611 dump_loops(F, get_loop_son(loop, i));
1612 dump_loop_son_edge(F, loop, i);
1617 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1618 ir_graph *rem = current_ir_graph;
1619 current_ir_graph = irg;
1621 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1623 current_ir_graph = rem;
1628 * dumps the VCG header
1630 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1639 if (!orientation) orientation = "bottom_to_top";
1643 "graph: { title: \"ir graph of %s\"\n"
1644 "display_edge_labels: %s\n"
1645 "layoutalgorithm: mindepth\n"
1646 "manhattan_edges: yes\n"
1647 "port_sharing: no\n"
1649 "classname 1: \"intrablock Data\"\n"
1650 "classname 16: \"interblock Data\"\n"
1651 "classname 2: \"Block\"\n"
1652 "classname 13: \"Control Flow\"\n"
1653 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1654 "classname 14: \"intrablock Memory\"\n"
1655 "classname 17: \"interblock Memory\"\n"
1656 "classname 15: \"Dominators\"\n"
1657 "classname 3: \"Entity type\"\n"
1658 "classname 4: \"Entity owner\"\n"
1659 "classname 5: \"Method Param\"\n"
1660 "classname 6: \"Method Res\"\n"
1661 "classname 7: \"Super\"\n"
1662 "classname 8: \"Union\"\n"
1663 "classname 9: \"Points-to\"\n"
1664 "classname 10: \"Array Element Type\"\n"
1665 "classname 11: \"Overwrites\"\n"
1666 "classname 12: \"Member\"\n"
1667 "infoname 1: \"Attribute\"\n"
1668 "infoname 2: \"Verification errors\"\n",
1669 name, label, orientation);
1671 /* don't use all, the range is too whith/black. */
1675 "colorentry 100: 0 0 0\n"
1676 "colorentry 101: 20 0 0\n"
1677 "colorentry 102: 40 0 0\n"
1678 "colorentry 103: 60 0 0\n"
1679 "colorentry 104: 80 0 0\n"
1680 "colorentry 105: 100 0 0\n"
1681 "colorentry 106: 120 0 0\n"
1682 "colorentry 107: 140 0 0\n"
1683 "colorentry 108: 150 0 0\n"
1684 "colorentry 109: 180 0 0\n"
1685 "colorentry 110: 200 0 0\n"
1686 "colorentry 111: 220 0 0\n"
1687 "colorentry 112: 240 0 0\n"
1688 "colorentry 113: 255 0 0\n"
1689 "colorentry 113: 255 20 20\n"
1690 "colorentry 114: 255 40 40\n"
1691 "colorentry 115: 255 60 60\n"
1692 "colorentry 116: 255 80 80\n"
1693 "colorentry 117: 255 100 100\n"
1694 "colorentry 118: 255 120 120\n"
1695 "colorentry 119: 255 140 140\n"
1696 "colorentry 120: 255 150 150\n"
1697 "colorentry 121: 255 180 180\n"
1698 "colorentry 122: 255 200 200\n"
1699 "colorentry 123: 255 220 220\n"
1700 "colorentry 124: 255 240 240\n"
1701 "colorentry 125: 255 250 250\n"
1704 fprintf (F, "\n"); /* a separator */
1710 * @param irg The graph to be dumped
1711 * @param suffix1 first filename suffix
1712 * @param suffix2 second filename suffix
1714 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1716 const char *nm = get_irg_dump_name(irg);
1717 int len = strlen(nm), i, j;
1718 char *fname; /* filename to put the vcg information in */
1720 if (!suffix1) suffix1 = "";
1721 if (!suffix2) suffix2 = "";
1723 /* open file for vcg graph */
1724 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1726 /* strncpy (fname, nm, len); */ /* copy the filename */
1728 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1730 fname[j] = '@'; j++; fname[j] = '1'; j++;
1731 } else if (nm[i] == '@') {
1732 fname[j] = '@'; j++; fname[j] = '2'; j++;
1734 fname[j] = nm[i]; j++;
1738 strcat (fname, suffix1); /* append file suffix */
1739 strcat (fname, suffix2); /* append file suffix */
1740 strcat (fname, ".vcg"); /* append the .vcg suffix */
1741 F = fopen (fname, "w"); /* open file for writing */
1743 panic("cannot open %s for writing (%m)", fname); /* not reached */
1753 * @param irg The graph to be dumped
1754 * @param suffix filename suffix
1756 static FILE *vcg_open_name (const char *name, const char *suffix) {
1758 char *fname; /* filename to put the vcg information in */
1759 int i, j, len = strlen(name);
1761 if (!suffix) suffix = "";
1763 /** open file for vcg graph */
1764 fname = malloc (len * 2 + 5 + strlen(suffix));
1765 /* strcpy (fname, name);*/ /* copy the filename */
1767 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1768 if (name[i] == '/') {
1769 fname[j] = '@'; j++; fname[j] = '1'; j++;
1770 } else if (name[i] == '@') {
1771 fname[j] = '@'; j++; fname[j] = '2'; j++;
1773 fname[j] = name[i]; j++;
1777 strcat (fname, suffix);
1778 strcat (fname, ".vcg"); /* append the .vcg suffix */
1779 F = fopen (fname, "w"); /* open file for writing */
1781 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1789 * Dumps the vcg file footer
1791 static INLINE void dump_vcg_footer (FILE *F) {
1796 * close the vcg file
1798 void vcg_close (FILE *F) {
1799 dump_vcg_footer(F); /* print footer */
1800 fclose (F); /* close vcg file */
1803 /************************************************************************/
1804 /************************************************************************/
1805 /* Routines that dump all or parts of the firm representation to a file */
1806 /************************************************************************/
1807 /************************************************************************/
1809 /************************************************************************/
1810 /* Dump ir graphs, differnt formats and additional information. */
1811 /************************************************************************/
1813 /** Routine to dump a graph, blocks as conventional nodes.
1816 dump_ir_graph (ir_graph *irg, const char *suffix )
1821 rem = current_ir_graph;
1823 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1824 current_ir_graph = irg;
1825 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1826 else suffix1 = "-pure";
1827 f = vcg_open(irg, suffix, suffix1);
1828 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1830 /* walk over the graph */
1831 /* dump_whole_node must be called in post visiting predecessors */
1832 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1834 /* dump the out edges in a separate walk */
1835 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1836 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1841 current_ir_graph = rem;
1846 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1852 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1855 if (get_interprocedural_view()) suffix1 = "-ip";
1857 f = vcg_open(irg, suffix, suffix1);
1858 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1860 construct_block_lists(irg);
1862 for (i = 0; i < get_irp_n_irgs(); i++) {
1863 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1865 dump_graph(f, get_irp_irg(i));
1873 /** dumps a graph with type information
1876 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1879 ir_graph *rem = current_ir_graph;
1882 /* if a filter is set, dump only the irg's that match the filter */
1883 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1886 current_ir_graph = irg;
1888 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1889 else suffix1 = "-pure-wtypes";
1890 f = vcg_open(irg,suffix, suffix1);
1891 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1893 /* dump common ir graph */
1894 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1895 /* dump type info */
1896 type_walk_irg(irg, dump_type_info, NULL, f);
1897 inc_irg_visited(get_const_code_irg());
1898 /* dump edges from graph to type info */
1899 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1902 current_ir_graph = rem;
1906 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1911 ir_graph *rem = current_ir_graph;
1913 /* if a filter is set, dump only the irg's that match the filter */
1914 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1917 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1918 else suffix1 = "-wtypes";
1919 f = vcg_open(irg, suffix, suffix1);
1920 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1922 /* dump common blocked ir graph */
1923 construct_block_lists(irg);
1925 for (i = 0; i < get_irp_n_irgs(); i++) {
1926 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1928 dump_graph(f, get_irp_irg(i));
1933 /* dump type info */
1934 current_ir_graph = irg;
1935 type_walk_irg(irg, dump_type_info, NULL, f);
1936 inc_irg_visited(get_const_code_irg());
1938 /* dump edges from graph to type info */
1939 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1941 current_ir_graph = rem;
1945 /*---------------------------------------------------------------------*/
1946 /* The following routines dump a control flow graph. */
1947 /*---------------------------------------------------------------------*/
1950 dump_block_to_cfg(ir_node *block, void *env) {
1955 if (is_Block(block)) {
1956 /* This is a block. Dump a node for the block. */
1957 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1958 fprintf (F, "\" label: \"");
1959 if (block == get_irg_start_block(get_irn_irg(block)))
1960 fprintf(F, "Start ");
1961 if (block == get_irg_end_block(get_irn_irg(block)))
1964 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1965 PRINT_NODEID(block);
1967 fprintf(F, "info1:\"");
1968 if (dump_dominator_information_flag)
1969 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1971 /* show arity and possible Bad predecessors of the block */
1972 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1973 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1974 ir_node *pred = get_Block_cfgpred(block, i);
1977 fprintf(F, "Bad pred at pos: ");
1978 fprintf(F, "%d ", i);
1985 fprintf (F, "\""); /* closing quote of info */
1987 if ((block == get_irg_start_block(get_irn_irg(block))) ||
1988 (block == get_irg_end_block(get_irn_irg(block))) )
1989 fprintf(F, " color:blue ");
1991 fprintf(F, " color:yellow ");
1994 /* Dump the edges */
1995 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1996 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1997 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1998 fprintf (F, "edge: { sourcename: \"");
1999 PRINT_NODEID(block);
2000 fprintf (F, "\" targetname: \"");
2002 fprintf (F, "\"}\n");
2005 /* Dump dominator edge */
2006 if (dump_dominator_information_flag && get_Block_idom(block)) {
2007 pred = get_Block_idom(block);
2008 fprintf (F, "edge: { sourcename: \"");
2009 PRINT_NODEID(block);
2010 fprintf (F, "\" targetname: \"");
2012 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2018 dump_cfg (ir_graph *irg, const char *suffix)
2021 ir_graph *rem = current_ir_graph;
2022 int ddif = dump_dominator_information_flag;
2023 int ipv = get_interprocedural_view();
2025 /* if a filter is set, dump only the irg's that match the filter */
2026 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2029 current_ir_graph = irg;
2031 f = vcg_open(irg, suffix, "-cfg");
2032 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2035 printf("Warning: dumping cfg not in interprocedural view!\n");
2036 set_interprocedural_view(false);
2039 if (get_irg_dom_state(irg) != dom_consistent)
2040 dump_dominator_information_flag = 0;
2042 /* walk over the blocks in the graph */
2043 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2044 dump_node(f, get_irg_bad(irg));
2046 dump_dominator_information_flag = ddif;
2047 set_interprocedural_view(ipv);
2049 current_ir_graph = rem;
2052 static int weight_overall(int rec, int loop) {
2053 return 2*rec + loop;
2056 static int compute_color (int my, int max) {
2061 /* if small, scale to the full color range. */
2063 my = my * (n_colors/max);
2065 int step = 1 + (max / n_colors);
2069 return base_color + n_colors - color;
2072 static int get_entity_color(entity *ent) {
2073 assert(get_entity_irg(ent));
2074 ir_graph *irg = get_entity_irg(ent);
2076 int rec_depth = get_irg_recursion_depth(irg);
2077 int loop_depth = get_irg_loop_depth(irg);
2078 int overall_depth = weight_overall(rec_depth, loop_depth);
2080 int max_rec_depth = irp->max_callgraph_recursion_depth;
2081 int max_loop_depth = irp->max_callgraph_loop_depth;
2082 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2084 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2085 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2086 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2088 return my_overall_color;
2091 void dump_callgraph(const char *suffix) {
2093 int i, n_irgs = get_irp_n_irgs();
2094 int rem = edge_label;
2096 //ident *prefix = new_id_from_str("java/");
2098 F = vcg_open_name("Callgraph", suffix);
2099 dump_vcg_header(F, "Callgraph", NULL);
2101 for (i = 0; i < n_irgs; ++i) {
2102 ir_graph *irg = get_irp_irg(i);
2103 entity *ent = get_irg_entity(irg);
2104 int j, n_callees = get_irg_n_callees(irg);
2106 /* Do not dump runtime system. */
2107 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2109 dump_entity_node(F, ent, get_entity_color(ent));
2110 for (j = 0; j < n_callees; ++j) {
2111 entity *c = get_irg_entity(get_irg_callee(irg, j));
2112 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2113 int be = is_irg_callee_backedge(irg, j);
2116 "label:\"recursion %d\" color: %d" :
2117 "label:\"calls %d\" color: %d";
2118 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2126 /* Dump all irgs in interprocedural view to a single file. */
2127 void dump_all_cg_block_graph(const char *suffix) {
2130 int rem_view = get_interprocedural_view();
2131 set_interprocedural_view(true);
2133 f = vcg_open_name("All_graphs", suffix);
2134 dump_vcg_header(f, "All_graphs", NULL);
2136 /* collect nodes in all irgs reachable in call graph*/
2137 for (i = 0; i < get_irp_n_irgs(); i++)
2138 ird_set_irg_link(get_irp_irg(i), NULL);
2140 cg_walk(clear_link, collect_node, NULL);
2142 /* dump all graphs */
2143 for (i = 0; i < get_irp_n_irgs(); i++) {
2144 current_ir_graph = get_irp_irg(i);
2145 assert(ird_get_irg_link(current_ir_graph));
2146 dump_graph(f, current_ir_graph);
2147 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2151 set_interprocedural_view(rem_view);
2154 /***********************************************************************/
2155 /* the following routines dumps type information without any ir nodes. */
2156 /***********************************************************************/
2159 dump_type_graph (ir_graph *irg, const char *suffix)
2163 rem = current_ir_graph;
2165 /* if a filter is set, dump only the irg's that match the filter */
2166 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2168 current_ir_graph = irg;
2170 f = vcg_open(irg, suffix, "-type");
2171 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2173 /* walk over the blocks in the graph */
2174 type_walk_irg(irg, dump_type_info, NULL, f);
2175 /* The walker for the const code can be called several times for the
2176 same (sub) experssion. So that no nodes are dumped several times
2177 we decrease the visited flag of the corresponding graph after each
2178 walk. So now increase it finally. */
2179 inc_irg_visited(get_const_code_irg());
2182 current_ir_graph = rem;
2186 dump_all_types (const char *suffix)
2188 FILE *f = vcg_open_name("All_types", suffix);
2189 dump_vcg_header(f, "All_types", NULL);
2190 type_walk(dump_type_info, NULL, f);
2191 inc_irg_visited(get_const_code_irg());
2196 dump_class_hierarchy (bool entities, const char *suffix)
2198 FILE *f = vcg_open_name("class_hierarchy", suffix);
2202 dump_vcg_header(f, "class_hierarchy", NULL);
2207 type_walk(dump_class_hierarchy_node, NULL, &env);
2211 /***********************************************************************/
2212 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2214 /* dump_ir_block_graph */
2216 /* dump_type_graph */
2217 /* dump_ir_graph_w_types */
2218 /***********************************************************************/
2220 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2221 int i, n_irgs = get_irp_n_irgs();
2222 for (i = 0; i < n_irgs; ++i) {
2223 dmp_grph(get_irp_irg(i), suffix);
2228 /**********************************************************************************
2229 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2230 * packed together in one subgraph/box *
2231 **********************************************************************************/
2233 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2234 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2236 ir_loop *son = NULL;
2238 /* Dump a new loop node. */
2239 dump_loop_node(F, loop);
2241 /* Dump the loop elements. */
2243 for(i = 0; i < get_loop_n_elements(loop); i++) {
2244 le = get_loop_element(loop, i);
2246 if (get_kind(son) == k_ir_loop) {
2248 /* We are a loop son -> Recurse */
2250 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2251 fprintf(F, "\" }\n");
2252 fprintf (F, "edge: {sourcename: \"");
2254 fprintf (F, "\" targetname: \"");
2256 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2257 loop_node_started = 0;
2259 dump_loop_son_edge(F, loop, son_number++);
2260 dump_loops_standalone(F, son);
2261 } else if (get_kind(son) == k_ir_node) {
2262 /* We are a loop node -> Collect firm nodes */
2264 ir_node *n = le.node;
2267 if (!loop_node_started) {
2268 /* Start a new node which contains all firm nodes of the current loop */
2269 fprintf (F, "node: { title: \"");
2271 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2272 loop_node_started = 1;
2278 bad |= dump_node_opcode(F, n);
2279 bad |= dump_node_mode(F, n);
2280 bad |= dump_node_typeinfo(F, n);
2282 bad |= dump_node_nodeattr(F, n);
2283 fprintf (F, " %ld", get_irn_node_nr(n));
2284 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2285 if (has_backedges(n)) fprintf(F, "\t loop head!");
2286 } else { /* for callgraph loop tree */
2287 assert(get_kind(son) == k_ir_graph);
2288 /* We are a loop node -> Collect firm graphs */
2289 ir_graph *n = (ir_graph *)le.node;
2290 if (!loop_node_started) {
2291 /* Start a new node which contains all firm nodes of the current loop */
2292 fprintf (F, "node: { title: \"");
2294 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2295 loop_node_started = 1;
2300 fprintf (F, " %s", get_irg_dump_name(n));
2301 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2305 if (loop_node_started) {
2306 fprintf(F, "\" }\n");
2307 fprintf (F, "edge: {sourcename: \"");
2309 fprintf (F, "\" targetname: \"");
2311 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2312 loop_node_started = 0;
2316 void dump_loop_tree(ir_graph *irg, const char *suffix)
2319 ir_graph *rem = current_ir_graph;
2320 int el_rem = edge_label;
2323 /* if a filter is set, dump only the irg's that match the filter */
2324 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2327 current_ir_graph = irg;
2329 f = vcg_open(irg, suffix, "-looptree");
2330 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2332 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2336 edge_label = el_rem;
2337 current_ir_graph = rem;
2340 void dump_callgraph_loop_tree(const char *suffix) {
2342 F = vcg_open_name("Callgraph_looptree", suffix);
2343 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2344 dump_loops_standalone(F, irp->outermost_cg_loop);
2349 /*******************************************************************************/
2350 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2351 /*******************************************************************************/
2353 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2354 int i, son_number = 0, node_number = 0;
2356 if (dump_loop_information_flag) dump_loop_node(F, loop);
2358 for (i = 0; i < get_loop_n_elements(loop); i++) {
2359 loop_element le = get_loop_element(loop, i);
2360 if (*(le.kind) == k_ir_loop) {
2361 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2363 collect_nodeloop(F, le.son, loopnodes);
2365 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2366 eset_insert(loopnodes, le.node);
2371 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2374 for(i = 0; i < get_loop_n_elements(loop); i++) {
2375 loop_element le = get_loop_element(loop, i);
2376 if (*(le.kind) == k_ir_loop) {
2378 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2380 if (is_Block(le.node)) start = 0; else start = -1;
2381 for (j = start; j < get_irn_arity(le.node); j++) {
2382 ir_node *pred = get_irn_n(le.node, j);
2383 if (!eset_contains(loopnodes, pred)) {
2384 eset_insert(extnodes, pred);
2385 if (!is_Block(pred)) {
2386 pred = get_nodes_block(pred);
2387 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2395 void dump_loop(ir_loop *l, const char *suffix) {
2398 eset *loopnodes = eset_create();
2399 eset *extnodes = eset_create();
2402 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2403 F = vcg_open_name (name, suffix);
2404 dump_vcg_header(F, name, NULL);
2406 /* collect all nodes to dump */
2407 collect_nodeloop(F, l, loopnodes);
2408 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2410 /* build block lists */
2411 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2412 set_irn_link(n, NULL);
2413 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2414 set_irn_link(n, NULL);
2415 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2417 b = get_nodes_block(n);
2418 set_irn_link(n, get_irn_link(b));
2421 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2423 b = get_nodes_block(n);
2424 set_irn_link(n, get_irn_link(b));
2428 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2430 fprintf(F, "graph: { title: \"");
2432 fprintf(F, "\" label: \"");
2433 dump_node_opcode(F, b);
2434 fprintf (F, " %ld", get_irn_node_nr(b));
2435 fprintf(F, "\" status:clustered color:yellow\n");
2437 /* dump the blocks edges */
2438 dump_ir_data_edges(F, b);
2440 /* dump the nodes that go into the block */
2441 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2442 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2444 overrule_nodecolor = NULL;
2445 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2448 /* Close the vcg information for the block */
2450 dump_const_node_local(F, b);
2453 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2455 fprintf(F, "graph: { title: \"");
2457 fprintf(F, "\" label: \"");
2458 dump_node_opcode(F, b);
2459 fprintf (F, " %ld", get_irn_node_nr(b));
2460 fprintf(F, "\" status:clustered color:lightblue\n");
2462 /* dump the nodes that go into the block */
2463 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2464 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2466 overrule_nodecolor = NULL;
2467 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2470 /* Close the vcg information for the block */
2472 dump_const_node_local(F, b);
2476 eset_destroy(loopnodes);
2477 eset_destroy(extnodes);