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.
24 #include "firm_common_t.h"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
51 void dump_chi_term(FILE *FL, ir_node *n);
52 void dump_state(FILE *FL, ir_node *n);
53 int get_opt_dump_abstvals(void);
54 typedef unsigned long SeqNo;
55 SeqNo get_Block_seqno(ir_node *n);
58 /* basis for a color range for vcg */
59 static int n_colors = 0;
60 static int base_color = 0;
62 #define ERROR_TXT "<ERROR>"
65 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
66 * in the later case, sets bad
68 const char *get_mode_name_ex(ir_mode *mode, int *bad)
71 return get_mode_name(mode);
77 * returns the name of a type or <ERROR> if mode is NOT a mode object.
78 * in the later case, sets bad
80 const char *get_type_name_ex(type *tp, int *bad)
83 return get_type_name(tp);
89 * prints the edge from a type S to a type T with additional info fmt, ...
92 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
97 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
98 fprintf(F, " targetname: "); PRINT_TYPEID(T);
105 * prints the edge from a type T to an entity E with additional info fmt, ...
108 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
113 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
114 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
115 vfprintf(F, fmt, ap);
121 * prints the edge from an entity E to an entity T with additional info fmt, ...
124 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
130 fprintf(F, "backedge: { sourcename: \"");
132 fprintf(F, "edge: { sourcename: \"");
134 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
135 vfprintf(F, fmt, ap);
141 * prints the edge from an entity E to a type T with additional info fmt, ...
144 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
149 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
150 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
151 vfprintf(F, fmt, ap);
157 * prints the edge from a node N to a type T with additional info fmt, ...
160 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
165 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
166 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
167 vfprintf(F, fmt, ap);
173 * prints the edge from a node N to an entity E with additional info fmt, ...
176 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
181 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
182 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
184 vfprintf(F, fmt, ap);
190 * prints the edge from an entity E to a node N with additional info fmt, ...
193 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
198 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
199 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
200 vfprintf(F, fmt, ap);
206 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
209 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
214 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
215 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
216 vfprintf(F, fmt, ap);
221 /*-----------------------------------------------------------------*/
222 /* global and ahead declarations */
223 /*-----------------------------------------------------------------*/
225 static void dump_whole_node(ir_node *n, void *env);
226 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
228 /*-----------------------------------------------------------------*/
229 /* Helper functions. */
230 /*-----------------------------------------------------------------*/
233 * This map is used as a private link attr to be able to call dumper
234 * anywhere without destroying link fields.
236 static pmap *irdump_link_map = NULL;
238 /** Creates the link attribut map. */
239 static void init_irdump(void) {
240 /* We need a new, empty map. */
241 if (irdump_link_map) pmap_destroy(irdump_link_map);
242 irdump_link_map = pmap_create();
246 * Returns the private link field.
248 static void *ird_get_irn_link(ir_node *n) {
250 if (!irdump_link_map) return NULL;
252 if (pmap_contains(irdump_link_map, (void *)n))
253 res = pmap_get(irdump_link_map, (void *)n);
258 * Sets the private link field.
260 static void ird_set_irn_link(ir_node *n, void *x) {
261 if (!irdump_link_map) init_irdump();
262 pmap_insert(irdump_link_map, (void *)n, x);
266 * Gets the private link field of an irg.
268 static void *ird_get_irg_link(ir_graph *irg) {
270 if (!irdump_link_map) return NULL;
272 if (pmap_contains(irdump_link_map, (void *)irg))
273 res = pmap_get(irdump_link_map, (void *)irg);
278 * Sets the private link field of an irg.
280 static void ird_set_irg_link(ir_graph *irg, void *x) {
281 if (!irdump_link_map) init_irdump();
282 pmap_insert(irdump_link_map, (void *)irg, x);
286 * Walker, clears tzhe private link field
288 static void clear_link(ir_node * node, void * env) {
289 ird_set_irn_link(node, NULL);
293 * If the entity has a ld_name, returns it, else returns the name of the entity.
295 const char *get_ent_dump_name(entity *ent) {
297 return "<NULL entity>";
298 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
299 if (ent->ld_name) return get_id_str(ent->ld_name);
300 return get_id_str(ent->name);
303 /* Returns the name of an IRG. */
304 const char *get_irg_dump_name(ir_graph *irg) {
305 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
306 entity *ent = get_irg_entity(irg);
307 return get_ent_dump_name(ent);
311 * Returns non-zero if a node is in floating state.
313 static int node_floats(ir_node *n) {
314 return ((get_irn_pinned(n) == op_pin_state_floats) &&
315 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
319 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
321 static void collect_node(ir_node * node, void *env) {
324 || get_irn_op(node) == op_Bad
325 || get_irn_op(node) == op_Unknown
326 || get_irn_op(node) == op_NoMem) {
327 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
328 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
329 ARR_APP1(ir_node *, arr, node);
330 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
332 ir_node * block = get_nodes_block(node);
335 /* this node is in a Bad block, so we must place it into the graph's list */
336 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
337 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
338 ARR_APP1(ir_node *, arr, node);
339 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
342 ird_set_irn_link(node, ird_get_irn_link(block));
343 ird_set_irn_link(block, node);
348 /** Construct lists to walk ir block-wise.
350 * Collects all blocks, nodes not op_pin_state_pinned,
351 * Bad, NoMem and Unknown into a flexible array in link field of
352 * irg they belong to. Sets the irg link field to NULL in all
353 * graphs not visited.
354 * Free the list with DEL_ARR_F().
356 static ir_node ** construct_block_lists(ir_graph *irg) {
357 int i, rem_view = get_interprocedural_view();
358 ir_graph *rem = current_ir_graph;
359 current_ir_graph = irg;
361 for (i = 0; i < get_irp_n_irgs(); i++)
362 ird_set_irg_link(get_irp_irg(i), NULL);
364 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
366 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
367 set_interprocedural_view(false);
369 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
370 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
371 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
372 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
374 set_interprocedural_view(rem_view);
376 current_ir_graph = rem;
377 return ird_get_irg_link(irg);
380 /*******************************************************************/
381 /* flags to steer output */
382 /*******************************************************************/
384 /** Dump only irgs with names start with this string */
385 const char *dump_file_filter = "";
387 /** A compiler option to turn off edge labels */
388 static int edge_label = 1;
389 /** A compiler option to turn off dumping values of constant entities */
390 static int const_entities = 1;
391 /** A compiler option to dump the keep alive edges */
392 static int dump_keepalive = 0;
393 /** Compiler options to dump analysis information in dump_ir_graph */
394 int dump_out_edge_flag = 0;
395 int dump_dominator_information_flag = 0;
396 int dump_loop_information_flag = 0;
397 int dump_backedge_information_flag = 1;
398 int dump_const_local = 0;
399 bool opt_dump_analysed_type_info = 1;
400 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
402 static const char *overrule_nodecolor = NULL;
404 /** The vcg attribute hook. */
405 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
408 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
410 dump_node_vcgattr_hook = hook;
413 INLINE bool get_opt_dump_const_local(void) {
414 if (!dump_out_edge_flag && !dump_loop_information_flag)
415 return dump_const_local;
420 void only_dump_method_with_name(ident *name) {
421 dump_file_filter = get_id_str(name);
425 /* To turn off display of edge labels. Edge labels offen cause xvcg to
426 abort with a segmentation fault. */
427 void turn_off_edge_labels(void) {
431 void dump_consts_local(bool b) {
432 dump_const_local = b;
435 void turn_off_constant_entity_values(void) {
439 void dump_keepalive_edges(bool b) {
443 bool get_opt_dump_keepalive_edges(void) {
444 return dump_keepalive;
447 void dump_out_edges(void) {
448 dump_out_edge_flag = 1;
451 void dump_dominator_information(void) {
452 dump_dominator_information_flag = 1;
455 void dump_loop_information(void) {
456 dump_loop_information_flag = 1;
459 void dont_dump_loop_information(void) {
460 dump_loop_information_flag = 0;
463 void dump_backedge_information(bool b) {
464 dump_backedge_information_flag = b;
467 /* Dump the information of type field specified in ana/irtypeinfo.h.
468 * If the flag is set, the type name is output in [] in the node label,
469 * else it is output as info.
471 void dump_analysed_type_info(bool b) {
472 opt_dump_analysed_type_info = b;
475 void dump_pointer_values_to_info(bool b) {
476 opt_dump_pointer_values_to_info = b;
479 /*-----------------------------------------------------------------*/
480 /* Routines to dump information about a single ir node. */
481 /*-----------------------------------------------------------------*/
484 * dump the name of a node n to the File F.
487 dump_node_opcode(FILE *F, ir_node *n)
491 switch(get_irn_opcode(n)) {
496 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
497 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
502 if (get_SymConst_kind(n) == symconst_addr_name) {
503 /* don't use get_SymConst_ptr_info as it mangles the name. */
504 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
505 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
506 assert(get_SymConst_entity(n));
507 assert(is_entity(get_SymConst_entity(n)));
508 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
510 assert(get_kind(get_SymConst_type(n)) == k_type);
511 assert(get_type_ident(get_SymConst_type(n)));
512 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
513 if (get_SymConst_kind(n) == symconst_type_tag)
521 if (!get_interprocedural_view())
528 ir_node *pred = get_Proj_pred(n);
530 if (get_irn_opcode(pred) == iro_Cond
531 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
532 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
533 fprintf (F, "defProj");
535 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
536 * fprintf (F, "Arg");
545 if (get_interprocedural_view()) {
546 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
551 case iro_CallBegin: {
552 ir_node *addr = get_CallBegin_ptr(n);
554 if (get_irn_op(addr) == op_Sel)
555 ent = get_Sel_entity(addr);
556 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
557 ent = get_SymConst_entity(addr);
558 fprintf (F, "%s", get_irn_opname(n));
559 if (ent) fprintf (F, " %s", get_entity_name(ent));
563 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
568 fprintf (F, "%s", get_irn_opname(n));
576 * Dump the mode of a node n to a file F.
577 * Ignore modes that are "always known".
580 dump_node_mode(FILE *F, ir_node *n)
583 opcode iro = get_irn_opcode(n);
596 ir_mode *mode = get_irn_mode(n);
598 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
599 (mode != mode_T || iro == iro_Proj))
600 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
608 * Dump the tpe of a node n to a file F if it's known.
610 static int dump_node_typeinfo(FILE *F, ir_node *n) {
613 if (opt_dump_analysed_type_info) {
614 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
615 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
616 type *tp = get_irn_typeinfo_type(n);
618 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
627 * Dump addinional node attributes of some nodes to a file F.
630 dump_node_nodeattr(FILE *F, ir_node *n)
634 switch (get_irn_opcode(n)) {
636 if (false && get_interprocedural_view()) {
637 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
641 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
642 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
644 fprintf (F, "%ld", get_Proj_proj(n));
648 fprintf (F, "%ld", get_Filter_proj(n));
651 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
654 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
657 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
668 * dumps the attributes of a node n into the file F.
669 * Currently this is only the color of a node.
671 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
676 fprintf(F, "color: red");
680 if (dump_node_vcgattr_hook)
681 if (dump_node_vcgattr_hook(F, node, local))
684 n = local ? local : node;
686 switch (get_irn_opcode(n)) {
693 fprintf (F, "color: blue");
696 if (is_Block_dead(n))
697 fprintf (F, "color: lightred");
699 fprintf (F, "color: lightyellow");
702 fprintf (F, "color: green");
708 fprintf (F, "color: yellow");
711 PRINT_DEFAULT_NODE_ATTR;
714 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
719 * Dump the node information of a node n to a file F.
721 static INLINE int dump_node_info(FILE *F, ir_node *n)
723 fprintf (F, " info1: \"");
724 bad = dump_irnode_to_file(F, n);
730 * checks wheater a node is "constant-like", ie can be treated "block-less"
733 bool is_constlike_node(ir_node *n) {
734 ir_op *op = get_irn_op(n);
735 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
739 /** outputs the predecessors of n, that are constants, local. I.e.,
740 generates a copy of the constant predecessors for each node called with. */
741 static void dump_const_node_local(FILE *F, ir_node *n) {
743 if (!get_opt_dump_const_local()) return;
745 /* Use visited flag to avoid outputting nodes twice.
746 initialize it first. */
747 for (i = 0; i < get_irn_arity(n); i++) {
748 ir_node *con = get_irn_n(n, i);
749 if (is_constlike_node(con)) {
750 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
754 for (i = 0; i < get_irn_arity(n); i++) {
755 ir_node *con = get_irn_n(n, i);
756 if (is_constlike_node(con) && irn_not_visited(con)) {
759 mark_irn_visited(con);
760 /* Generate a new name for the node by appending the names of
762 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
763 fprintf(F, " label: \"");
764 bad |= dump_node_opcode(F, con);
765 bad |= dump_node_mode(F, con);
766 bad |= dump_node_typeinfo(F, con);
768 bad |= dump_node_nodeattr(F, con);
769 fprintf(F, " %ld", get_irn_node_nr(con));
771 bad |= dump_node_info(F, con);
772 dump_node_vcgattr(F, n, con, bad);
778 /** If the block of an edge is a const_like node, dump it local with an edge */
779 static void dump_const_block_local(FILE *F, ir_node *n) {
780 if (!get_opt_dump_const_local()) return;
782 ir_node *blk = get_nodes_block(n);
783 if (is_constlike_node(blk)) {
786 /* Generate a new name for the node by appending the names of
788 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
789 fprintf(F, "\" label: \"");
790 bad |= dump_node_opcode(F, blk);
791 bad |= dump_node_mode(F, blk);
792 bad |= dump_node_typeinfo(F, blk);
794 bad |= dump_node_nodeattr(F, blk);
795 fprintf(F, " %ld", get_irn_node_nr(blk));
797 bad |= dump_node_info(F, blk);
798 dump_node_vcgattr(F, n, blk, bad);
801 fprintf (F, "edge: { sourcename: \"");
803 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
804 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
809 * prints the error message of a node to a file F as info2.
811 static void INLINE print_node_error(FILE *F, const char *err_msg)
816 fprintf (F, " info2: \"%s\"", err_msg);
822 static void dump_node(FILE *F, ir_node *n)
827 if (get_opt_dump_const_local() && is_constlike_node(n))
831 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
833 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
834 bad |= dump_node_opcode(F, n);
835 bad |= dump_node_mode(F, n);
836 bad |= dump_node_typeinfo(F, n);
838 bad |= dump_node_nodeattr(F, n);
839 fprintf(F, " %ld", get_irn_node_nr(n));
841 bad |= dump_node_info(F, n);
842 print_node_error(F, p);
843 dump_node_vcgattr(F, n, NULL, bad);
845 dump_const_node_local(F, n);
852 /** dump the edge to the block this node belongs to */
854 dump_ir_block_edge(FILE *F, ir_node *n) {
855 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
856 if (is_no_Block(n)) {
857 ir_node *block = get_nodes_block(n);
859 if (get_opt_dump_const_local() && is_constlike_node(block)) {
860 dump_const_block_local(F, n);
863 fprintf (F, "edge: { sourcename: \"");
865 fprintf (F, "\" targetname: ");
866 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
867 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
873 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
874 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
875 fprintf (F, INTRA_DATA_EDGE_ATTR);
877 fprintf (F, INTER_DATA_EDGE_ATTR);
881 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
882 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
883 fprintf (F, INTRA_MEM_EDGE_ATTR);
885 fprintf (F, INTER_MEM_EDGE_ATTR);
889 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
892 if (dump_backedge_information_flag && is_backedge(from, to))
893 fprintf (F, BACK_EDGE_ATTR);
895 switch (get_irn_opcode(from)) {
897 fprintf (F, CF_EDGE_ATTR);
899 case iro_Start: break;
902 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
903 fprintf (F, CF_EDGE_ATTR);
904 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
905 fprintf (F, INTER_MEM_EDGE_ATTR);
913 print_data_edge_vcgattr(F, from, to);
918 print_mem_edge_vcgattr(F, from, to);
920 print_data_edge_vcgattr(F, from, to);
924 print_data_edge_vcgattr(F, from, to);
929 print_mem_edge_vcgattr(F, from, to);
931 print_data_edge_vcgattr(F, from, to);
938 print_data_edge_vcgattr(F, from, to);
945 print_mem_edge_vcgattr(F, from, to);
947 print_data_edge_vcgattr(F, from, to);
959 print_data_edge_vcgattr(F, from, to);
962 if (get_irn_modecode(from) == irm_M)
963 fprintf (F, INTER_MEM_EDGE_ATTR);
965 print_data_edge_vcgattr(F, from, to);
972 print_mem_edge_vcgattr(F, from, to);
974 print_data_edge_vcgattr(F, from, to);
977 print_mem_edge_vcgattr(F, from, to);
979 case iro_Tuple: break;
982 switch (get_irn_modecode(from)) {
984 fprintf (F, CF_EDGE_ATTR);
987 fprintf (F, INTER_MEM_EDGE_ATTR);
990 print_data_edge_vcgattr(F, from, to);
995 case iro_Unknown: break;
997 switch (get_irn_modecode(from)) {
999 fprintf (F, INTRA_MEM_EDGE_ATTR);
1002 fprintf (F, CF_EDGE_ATTR);
1005 print_data_edge_vcgattr(F, from, to);
1013 /* dump edges to our inputs */
1015 dump_ir_data_edges(FILE *F, ir_node *n) {
1016 int i, visited = get_irn_visited(n);
1018 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1021 for (i = 0; i < get_irn_arity(n); i++) {
1022 ir_node * pred = get_irn_n(n, i);
1025 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1026 continue; /* pred not dumped */
1028 if (dump_backedge_information_flag && is_backedge(n, i))
1029 fprintf (F, "backedge: {sourcename: \"");
1031 fprintf (F, "edge: {sourcename: \"");
1033 fprintf (F, "\" targetname: ");
1034 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1035 PRINT_CONSTID(n, pred);
1037 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1039 fprintf (F, " label: \"%d\" ", i);
1040 print_edge_vcgattr(F, n, i);
1045 /** Dumps a node and its edges but not the block edge
1048 dump_node_wo_blockedge (ir_node *n, void *env) {
1051 dump_ir_data_edges(F, n);
1054 /** Dumps a node and its edges.
1057 dump_whole_node (ir_node *n, void *env) {
1059 dump_node_wo_blockedge(n, env);
1060 if (!node_floats(n)) dump_ir_block_edge(F, n);
1064 dump_const_node(ir_node *n, void *env) {
1065 if (is_Block(n)) return;
1066 dump_node_wo_blockedge(n, env);
1069 /***********************************************************************/
1070 /* the following routines dump the nodes/irgs bracketed to graphs. */
1071 /***********************************************************************/
1073 /** Dumps a constant expression as entity initializer, array bound ...
1075 static void dump_const_expression(FILE *F, ir_node *value) {
1076 ir_graph *rem = current_ir_graph;
1077 int rem_dump_const_local = dump_const_local;
1078 dump_const_local = 0;
1079 current_ir_graph = get_const_code_irg();
1080 irg_walk(value, dump_const_node, NULL, F);
1081 /* Decrease visited flag so that we walk with the same flag for the next
1082 expresssion. This guarantees that we don't dump the same node twice,
1083 as for const expressions cse is performed to save memory. */
1084 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1085 current_ir_graph = rem;
1086 dump_const_local = rem_dump_const_local;
1089 /** Dump a block as graph containing its nodes.
1091 * Expects to find nodes belonging to the block as list in its
1093 * Dumps the edges of all nodes including itself. */
1095 dump_whole_block(FILE *F, ir_node *block) {
1097 assert(is_Block(block));
1099 fprintf(F, "graph: { title: \"");
1100 PRINT_NODEID(block);
1101 fprintf(F, "\" label: \"");
1102 dump_node_opcode(F, block);
1103 fprintf (F, " %ld", get_irn_node_nr(block));
1105 if (get_opt_dump_abstvals())
1106 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1108 fprintf(F, "\" status:clustered color:%s \n",
1109 get_Block_matured(block) ? "yellow" : "red");
1111 /* dump the blocks edges */
1112 dump_ir_data_edges(F, block);
1114 /* dump the nodes that go into the block */
1115 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1117 dump_ir_data_edges(F, node);
1120 /* Close the vcg information for the block */
1122 dump_const_node_local(F, block);
1124 dump_chi_term(F, block);
1129 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1130 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1132 dump_block_graph(FILE *F, ir_graph *irg) {
1134 ir_graph *rem = current_ir_graph;
1135 ir_node **arr = ird_get_irg_link(irg);
1136 current_ir_graph = irg;
1138 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1139 ir_node * node = arr[i];
1140 if (is_Block(node)) {
1141 /* Dumps the block and all the nodes in the block, which are to
1142 be found in Block->link. */
1143 dump_whole_block(F, node);
1145 /* Nodes that are not in a Block. */
1147 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1148 dump_const_block_local(F, node);
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_from_list(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. */
1815 dump_ir_graph (ir_graph *irg, const char *suffix )
1820 rem = current_ir_graph;
1822 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1823 current_ir_graph = irg;
1824 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1825 else suffix1 = "-pure";
1826 f = vcg_open(irg, suffix, suffix1);
1827 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1829 /* walk over the graph */
1830 /* dump_whole_node must be called in post visiting predecessors */
1831 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1833 /* dump the out edges in a separate walk */
1834 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1835 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1840 current_ir_graph = rem;
1845 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1851 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1854 if (get_interprocedural_view()) suffix1 = "-ip";
1856 f = vcg_open(irg, suffix, suffix1);
1857 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1859 construct_block_lists(irg);
1861 for (i = 0; i < get_irp_n_irgs(); i++) {
1862 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1864 dump_graph_from_list(f, get_irp_irg(i));
1872 /** dumps a graph with type information */
1874 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1877 ir_graph *rem = current_ir_graph;
1880 /* if a filter is set, dump only the irg's that match the filter */
1881 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1884 current_ir_graph = irg;
1886 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1887 else suffix1 = "-pure-wtypes";
1888 f = vcg_open(irg,suffix, suffix1);
1889 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1891 /* dump common ir graph */
1892 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1893 /* dump type info */
1894 type_walk_irg(irg, dump_type_info, NULL, f);
1895 inc_irg_visited(get_const_code_irg());
1896 /* dump edges from graph to type info */
1897 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1900 current_ir_graph = rem;
1904 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1909 ir_graph *rem = current_ir_graph;
1911 /* if a filter is set, dump only the irg's that match the filter */
1912 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1915 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1916 else suffix1 = "-wtypes";
1917 f = vcg_open(irg, suffix, suffix1);
1918 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1920 /* dump common blocked ir graph */
1921 construct_block_lists(irg);
1923 for (i = 0; i < get_irp_n_irgs(); i++) {
1924 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1926 dump_graph_from_list(f, get_irp_irg(i));
1931 /* dump type info */
1932 current_ir_graph = irg;
1933 type_walk_irg(irg, dump_type_info, NULL, f);
1934 inc_irg_visited(get_const_code_irg());
1936 /* dump edges from graph to type info */
1937 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1939 current_ir_graph = rem;
1943 /*---------------------------------------------------------------------*/
1944 /* The following routines dump a control flow graph. */
1945 /*---------------------------------------------------------------------*/
1948 dump_block_to_cfg(ir_node *block, void *env) {
1953 if (is_Block(block)) {
1954 /* This is a block. Dump a node for the block. */
1955 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1956 fprintf (F, "\" label: \"");
1957 if (block == get_irg_start_block(get_irn_irg(block)))
1958 fprintf(F, "Start ");
1959 if (block == get_irg_end_block(get_irn_irg(block)))
1962 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1963 PRINT_NODEID(block);
1965 fprintf(F, "info1:\"");
1966 if (dump_dominator_information_flag)
1967 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1969 /* show arity and possible Bad predecessors of the block */
1970 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1971 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1972 ir_node *pred = get_Block_cfgpred(block, i);
1975 fprintf(F, "Bad pred at pos: ");
1976 fprintf(F, "%d ", i);
1983 fprintf (F, "\""); /* closing quote of info */
1985 if ((block == get_irg_start_block(get_irn_irg(block))) ||
1986 (block == get_irg_end_block(get_irn_irg(block))) )
1987 fprintf(F, " color:blue ");
1989 fprintf(F, " color:yellow ");
1992 /* Dump the edges */
1993 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1994 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1995 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1996 fprintf (F, "edge: { sourcename: \"");
1997 PRINT_NODEID(block);
1998 fprintf (F, "\" targetname: \"");
2000 fprintf (F, "\"}\n");
2003 /* Dump dominator edge */
2004 if (dump_dominator_information_flag && get_Block_idom(block)) {
2005 pred = get_Block_idom(block);
2006 fprintf (F, "edge: { sourcename: \"");
2007 PRINT_NODEID(block);
2008 fprintf (F, "\" targetname: \"");
2010 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2016 dump_cfg (ir_graph *irg, const char *suffix)
2019 ir_graph *rem = current_ir_graph;
2020 int ddif = dump_dominator_information_flag;
2021 int ipv = get_interprocedural_view();
2023 /* if a filter is set, dump only the irg's that match the filter */
2024 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2027 current_ir_graph = irg;
2029 f = vcg_open(irg, suffix, "-cfg");
2030 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2033 printf("Warning: dumping cfg not in interprocedural view!\n");
2034 set_interprocedural_view(false);
2037 if (get_irg_dom_state(irg) != dom_consistent)
2038 dump_dominator_information_flag = 0;
2040 /* walk over the blocks in the graph */
2041 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2042 dump_node(f, get_irg_bad(irg));
2044 dump_dominator_information_flag = ddif;
2045 set_interprocedural_view(ipv);
2047 current_ir_graph = rem;
2050 static int weight_overall(int rec, int loop) {
2051 return 2*rec + loop;
2054 static int compute_color (int my, int max) {
2059 /* if small, scale to the full color range. */
2061 my = my * (n_colors/max);
2063 int step = 1 + (max / n_colors);
2067 return base_color + n_colors - color;
2070 static int get_entity_color(entity *ent) {
2071 assert(get_entity_irg(ent));
2072 ir_graph *irg = get_entity_irg(ent);
2074 int rec_depth = get_irg_recursion_depth(irg);
2075 int loop_depth = get_irg_loop_depth(irg);
2076 int overall_depth = weight_overall(rec_depth, loop_depth);
2078 int max_rec_depth = irp->max_callgraph_recursion_depth;
2079 int max_loop_depth = irp->max_callgraph_loop_depth;
2080 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2082 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2083 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2084 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2086 return my_overall_color;
2089 void dump_callgraph(const char *suffix) {
2091 int i, n_irgs = get_irp_n_irgs();
2092 int rem = edge_label;
2094 //ident *prefix = new_id_from_str("java/");
2096 F = vcg_open_name("Callgraph", suffix);
2097 dump_vcg_header(F, "Callgraph", NULL);
2099 for (i = 0; i < n_irgs; ++i) {
2100 ir_graph *irg = get_irp_irg(i);
2101 entity *ent = get_irg_entity(irg);
2102 int j, n_callees = get_irg_n_callees(irg);
2104 /* Do not dump runtime system. */
2105 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2107 dump_entity_node(F, ent, get_entity_color(ent));
2108 for (j = 0; j < n_callees; ++j) {
2109 entity *c = get_irg_entity(get_irg_callee(irg, j));
2110 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2111 int be = is_irg_callee_backedge(irg, j);
2114 "label:\"recursion %d\" color: %d" :
2115 "label:\"calls %d\" color: %d";
2116 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2124 /* Dump all irgs in interprocedural view to a single file. */
2125 void dump_all_cg_block_graph(const char *suffix) {
2128 int rem_view = get_interprocedural_view();
2129 set_interprocedural_view(true);
2131 f = vcg_open_name("All_graphs", suffix);
2132 dump_vcg_header(f, "All_graphs", NULL);
2134 /* collect nodes in all irgs reachable in call graph*/
2135 for (i = 0; i < get_irp_n_irgs(); i++)
2136 ird_set_irg_link(get_irp_irg(i), NULL);
2138 cg_walk(clear_link, collect_node, NULL);
2140 /* dump all graphs */
2141 for (i = 0; i < get_irp_n_irgs(); i++) {
2142 current_ir_graph = get_irp_irg(i);
2143 assert(ird_get_irg_link(current_ir_graph));
2144 dump_graph_from_list(f, current_ir_graph);
2145 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2149 set_interprocedural_view(rem_view);
2152 /*---------------------------------------------------------------------*/
2153 /* the following routines dumps type information without any ir nodes. */
2154 /*---------------------------------------------------------------------*/
2157 dump_type_graph (ir_graph *irg, const char *suffix)
2161 rem = current_ir_graph;
2163 /* if a filter is set, dump only the irg's that match the filter */
2164 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2166 current_ir_graph = irg;
2168 f = vcg_open(irg, suffix, "-type");
2169 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2171 /* walk over the blocks in the graph */
2172 type_walk_irg(irg, dump_type_info, NULL, f);
2173 /* The walker for the const code can be called several times for the
2174 same (sub) experssion. So that no nodes are dumped several times
2175 we decrease the visited flag of the corresponding graph after each
2176 walk. So now increase it finally. */
2177 inc_irg_visited(get_const_code_irg());
2180 current_ir_graph = rem;
2184 dump_all_types (const char *suffix)
2186 FILE *f = vcg_open_name("All_types", suffix);
2187 dump_vcg_header(f, "All_types", NULL);
2188 type_walk(dump_type_info, NULL, f);
2189 inc_irg_visited(get_const_code_irg());
2194 dump_class_hierarchy (bool entities, const char *suffix)
2196 FILE *f = vcg_open_name("class_hierarchy", suffix);
2200 dump_vcg_header(f, "class_hierarchy", NULL);
2205 type_walk(dump_class_hierarchy_node, NULL, &env);
2209 /*---------------------------------------------------------------------*/
2210 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2212 /* dump_ir_block_graph */
2214 /* dump_type_graph */
2215 /* dump_ir_graph_w_types */
2216 /*---------------------------------------------------------------------*/
2218 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2219 int i, n_irgs = get_irp_n_irgs();
2220 for (i = 0; i < n_irgs; ++i) {
2221 dmp_grph(get_irp_irg(i), suffix);
2226 /*--------------------------------------------------------------------------------*
2227 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2228 * packed together in one subgraph/box *
2229 *--------------------------------------------------------------------------------*/
2231 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2232 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2234 ir_loop *son = NULL;
2236 /* Dump a new loop node. */
2237 dump_loop_node(F, loop);
2239 /* Dump the loop elements. */
2241 for(i = 0; i < get_loop_n_elements(loop); i++) {
2242 le = get_loop_element(loop, i);
2244 if (get_kind(son) == k_ir_loop) {
2246 /* We are a loop son -> Recurse */
2248 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2249 fprintf(F, "\" }\n");
2250 fprintf (F, "edge: {sourcename: \"");
2252 fprintf (F, "\" targetname: \"");
2254 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2255 loop_node_started = 0;
2257 dump_loop_son_edge(F, loop, son_number++);
2258 dump_loops_standalone(F, son);
2259 } else if (get_kind(son) == k_ir_node) {
2260 /* We are a loop node -> Collect firm nodes */
2262 ir_node *n = le.node;
2265 if (!loop_node_started) {
2266 /* Start a new node which contains all firm nodes of the current loop */
2267 fprintf (F, "node: { title: \"");
2269 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2270 loop_node_started = 1;
2276 bad |= dump_node_opcode(F, n);
2277 bad |= dump_node_mode(F, n);
2278 bad |= dump_node_typeinfo(F, n);
2280 bad |= dump_node_nodeattr(F, n);
2281 fprintf (F, " %ld", get_irn_node_nr(n));
2282 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2283 if (has_backedges(n)) fprintf(F, "\t loop head!");
2284 } else { /* for callgraph loop tree */
2285 assert(get_kind(son) == k_ir_graph);
2286 /* We are a loop node -> Collect firm graphs */
2287 ir_graph *n = (ir_graph *)le.node;
2288 if (!loop_node_started) {
2289 /* Start a new node which contains all firm nodes of the current loop */
2290 fprintf (F, "node: { title: \"");
2292 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2293 loop_node_started = 1;
2298 fprintf (F, " %s", get_irg_dump_name(n));
2299 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2303 if (loop_node_started) {
2304 fprintf(F, "\" }\n");
2305 fprintf (F, "edge: {sourcename: \"");
2307 fprintf (F, "\" targetname: \"");
2309 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2310 loop_node_started = 0;
2314 void dump_loop_tree(ir_graph *irg, const char *suffix)
2317 ir_graph *rem = current_ir_graph;
2318 int el_rem = edge_label;
2321 /* if a filter is set, dump only the irg's that match the filter */
2322 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2325 current_ir_graph = irg;
2327 f = vcg_open(irg, suffix, "-looptree");
2328 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2330 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2334 edge_label = el_rem;
2335 current_ir_graph = rem;
2338 void dump_callgraph_loop_tree(const char *suffix) {
2340 F = vcg_open_name("Callgraph_looptree", suffix);
2341 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2342 dump_loops_standalone(F, irp->outermost_cg_loop);
2347 /*-----------------------------------------------------------------------------*/
2348 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2349 /*-----------------------------------------------------------------------------*/
2351 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2352 int i, son_number = 0, node_number = 0;
2354 if (dump_loop_information_flag) dump_loop_node(F, loop);
2356 for (i = 0; i < get_loop_n_elements(loop); i++) {
2357 loop_element le = get_loop_element(loop, i);
2358 if (*(le.kind) == k_ir_loop) {
2359 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2361 collect_nodeloop(F, le.son, loopnodes);
2363 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2364 eset_insert(loopnodes, le.node);
2369 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2372 for(i = 0; i < get_loop_n_elements(loop); i++) {
2373 loop_element le = get_loop_element(loop, i);
2374 if (*(le.kind) == k_ir_loop) {
2376 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2378 if (is_Block(le.node)) start = 0; else start = -1;
2379 for (j = start; j < get_irn_arity(le.node); j++) {
2380 ir_node *pred = get_irn_n(le.node, j);
2381 if (!eset_contains(loopnodes, pred)) {
2382 eset_insert(extnodes, pred);
2383 if (!is_Block(pred)) {
2384 pred = get_nodes_block(pred);
2385 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2393 void dump_loop(ir_loop *l, const char *suffix) {
2396 eset *loopnodes = eset_create();
2397 eset *extnodes = eset_create();
2400 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2401 F = vcg_open_name (name, suffix);
2402 dump_vcg_header(F, name, NULL);
2404 /* collect all nodes to dump */
2405 collect_nodeloop(F, l, loopnodes);
2406 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2408 /* build block lists */
2409 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2410 set_irn_link(n, NULL);
2411 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2412 set_irn_link(n, NULL);
2413 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2415 b = get_nodes_block(n);
2416 set_irn_link(n, get_irn_link(b));
2419 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2421 b = get_nodes_block(n);
2422 set_irn_link(n, get_irn_link(b));
2426 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2428 fprintf(F, "graph: { title: \"");
2430 fprintf(F, "\" label: \"");
2431 dump_node_opcode(F, b);
2432 fprintf (F, " %ld", get_irn_node_nr(b));
2433 fprintf(F, "\" status:clustered color:yellow\n");
2435 /* dump the blocks edges */
2436 dump_ir_data_edges(F, b);
2438 /* dump the nodes that go into the block */
2439 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2440 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2442 overrule_nodecolor = NULL;
2443 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2446 /* Close the vcg information for the block */
2448 dump_const_node_local(F, b);
2451 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2453 fprintf(F, "graph: { title: \"");
2455 fprintf(F, "\" label: \"");
2456 dump_node_opcode(F, b);
2457 fprintf (F, " %ld", get_irn_node_nr(b));
2458 fprintf(F, "\" status:clustered color:lightblue\n");
2460 /* dump the nodes that go into the block */
2461 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2462 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2464 overrule_nodecolor = NULL;
2465 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2468 /* Close the vcg information for the block */
2470 dump_const_node_local(F, b);
2474 eset_destroy(loopnodes);
2475 eset_destroy(extnodes);