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 dump_constant_entity_values(bool b) {
439 void dump_keepalive_edges(bool b) {
443 bool get_opt_dump_keepalive_edges(void) {
444 return dump_keepalive;
447 void dump_out_edges(bool b) {
448 dump_out_edge_flag = b;
451 void dump_dominator_information(bool b) {
452 dump_dominator_information_flag = b;
455 void dump_loop_information(bool b) {
456 dump_loop_information_flag = b;
459 void dump_backedge_information(bool b) {
460 dump_backedge_information_flag = b;
463 /* Dump the information of type field specified in ana/irtypeinfo.h.
464 * If the flag is set, the type name is output in [] in the node label,
465 * else it is output as info.
467 void dump_analysed_type_info(bool b) {
468 opt_dump_analysed_type_info = b;
471 void dump_pointer_values_to_info(bool b) {
472 opt_dump_pointer_values_to_info = b;
475 /*-----------------------------------------------------------------*/
476 /* Routines to dump information about a single ir node. */
477 /*-----------------------------------------------------------------*/
480 * dump the name of a node n to the File F.
483 dump_node_opcode(FILE *F, ir_node *n)
487 switch(get_irn_opcode(n)) {
492 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
493 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
498 if (get_SymConst_kind(n) == symconst_addr_name) {
499 /* don't use get_SymConst_ptr_info as it mangles the name. */
500 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
501 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
502 assert(get_SymConst_entity(n));
503 assert(is_entity(get_SymConst_entity(n)));
504 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
506 assert(get_kind(get_SymConst_type(n)) == k_type);
507 assert(get_type_ident(get_SymConst_type(n)));
508 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
509 if (get_SymConst_kind(n) == symconst_type_tag)
517 if (!get_interprocedural_view())
524 ir_node *pred = get_Proj_pred(n);
526 if (get_irn_opcode(pred) == iro_Cond
527 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
528 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
529 fprintf (F, "defProj");
531 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
532 * fprintf (F, "Arg");
541 if (get_interprocedural_view()) {
542 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
547 case iro_CallBegin: {
548 ir_node *addr = get_CallBegin_ptr(n);
550 if (get_irn_op(addr) == op_Sel)
551 ent = get_Sel_entity(addr);
552 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
553 ent = get_SymConst_entity(addr);
554 fprintf (F, "%s", get_irn_opname(n));
555 if (ent) fprintf (F, " %s", get_entity_name(ent));
559 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
564 fprintf (F, "%s", get_irn_opname(n));
572 * Dump the mode of a node n to a file F.
573 * Ignore modes that are "always known".
576 dump_node_mode(FILE *F, ir_node *n)
579 opcode iro = get_irn_opcode(n);
592 ir_mode *mode = get_irn_mode(n);
594 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
595 (mode != mode_T || iro == iro_Proj))
596 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
604 * Dump the tpe of a node n to a file F if it's known.
606 static int dump_node_typeinfo(FILE *F, ir_node *n) {
609 if (opt_dump_analysed_type_info) {
610 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
611 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
612 type *tp = get_irn_typeinfo_type(n);
614 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
623 * Dump addinional node attributes of some nodes to a file F.
626 dump_node_nodeattr(FILE *F, ir_node *n)
630 switch (get_irn_opcode(n)) {
632 if (false && get_interprocedural_view()) {
633 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
637 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
638 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
640 fprintf (F, "%ld", get_Proj_proj(n));
644 fprintf (F, "%ld", get_Filter_proj(n));
647 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
650 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
653 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
664 * dumps the attributes of a node n into the file F.
665 * Currently this is only the color of a node.
667 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
672 fprintf(F, "color: red");
676 if (dump_node_vcgattr_hook)
677 if (dump_node_vcgattr_hook(F, node, local))
680 n = local ? local : node;
682 switch (get_irn_opcode(n)) {
689 fprintf (F, "color: blue");
692 if (is_Block_dead(n))
693 fprintf (F, "color: lightred");
695 fprintf (F, "color: lightyellow");
698 fprintf (F, "color: green");
704 fprintf (F, "color: yellow");
707 PRINT_DEFAULT_NODE_ATTR;
710 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
715 * Dump the node information of a node n to a file F.
717 static INLINE int dump_node_info(FILE *F, ir_node *n)
719 fprintf (F, " info1: \"");
720 bad = dump_irnode_to_file(F, n);
726 * checks wheater a node is "constant-like", ie can be treated "block-less"
729 bool is_constlike_node(ir_node *n) {
730 ir_op *op = get_irn_op(n);
731 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
735 /** outputs the predecessors of n, that are constants, local. I.e.,
736 generates a copy of the constant predecessors for each node called with. */
737 static void dump_const_node_local(FILE *F, ir_node *n) {
739 if (!get_opt_dump_const_local()) return;
741 /* Use visited flag to avoid outputting nodes twice.
742 initialize it first. */
743 for (i = 0; i < get_irn_arity(n); i++) {
744 ir_node *con = get_irn_n(n, i);
745 if (is_constlike_node(con)) {
746 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
750 for (i = 0; i < get_irn_arity(n); i++) {
751 ir_node *con = get_irn_n(n, i);
752 if (is_constlike_node(con) && irn_not_visited(con)) {
755 mark_irn_visited(con);
756 /* Generate a new name for the node by appending the names of
758 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
759 fprintf(F, " label: \"");
760 bad |= dump_node_opcode(F, con);
761 bad |= dump_node_mode(F, con);
762 bad |= dump_node_typeinfo(F, con);
764 bad |= dump_node_nodeattr(F, con);
765 fprintf(F, " %ld", get_irn_node_nr(con));
767 bad |= dump_node_info(F, con);
768 dump_node_vcgattr(F, n, con, bad);
774 /** If the block of an edge is a const_like node, dump it local with an edge */
775 static void dump_const_block_local(FILE *F, ir_node *n) {
778 if (!get_opt_dump_const_local()) return;
780 blk = get_nodes_block(n);
781 if (is_constlike_node(blk)) {
784 /* Generate a new name for the node by appending the names of
786 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
787 fprintf(F, "\" label: \"");
788 bad |= dump_node_opcode(F, blk);
789 bad |= dump_node_mode(F, blk);
790 bad |= dump_node_typeinfo(F, blk);
792 bad |= dump_node_nodeattr(F, blk);
793 fprintf(F, " %ld", get_irn_node_nr(blk));
795 bad |= dump_node_info(F, blk);
796 dump_node_vcgattr(F, n, blk, bad);
799 fprintf (F, "edge: { sourcename: \"");
801 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
802 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
807 * prints the error message of a node to a file F as info2.
809 static void INLINE print_node_error(FILE *F, const char *err_msg)
814 fprintf (F, " info2: \"%s\"", err_msg);
820 static void dump_node(FILE *F, ir_node *n)
825 if (get_opt_dump_const_local() && is_constlike_node(n))
829 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
831 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
832 bad |= dump_node_opcode(F, n);
833 bad |= dump_node_mode(F, n);
834 bad |= dump_node_typeinfo(F, n);
836 bad |= dump_node_nodeattr(F, n);
837 fprintf(F, " %ld", get_irn_node_nr(n));
839 bad |= dump_node_info(F, n);
840 print_node_error(F, p);
841 dump_node_vcgattr(F, n, NULL, bad);
843 dump_const_node_local(F, n);
850 /** dump the edge to the block this node belongs to */
852 dump_ir_block_edge(FILE *F, ir_node *n) {
853 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
854 if (is_no_Block(n)) {
855 ir_node *block = get_nodes_block(n);
857 if (get_opt_dump_const_local() && is_constlike_node(block)) {
858 dump_const_block_local(F, n);
861 fprintf (F, "edge: { sourcename: \"");
863 fprintf (F, "\" targetname: ");
864 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
865 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
871 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
872 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
873 fprintf (F, INTRA_DATA_EDGE_ATTR);
875 fprintf (F, INTER_DATA_EDGE_ATTR);
879 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
880 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
881 fprintf (F, INTRA_MEM_EDGE_ATTR);
883 fprintf (F, INTER_MEM_EDGE_ATTR);
887 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
890 if (dump_backedge_information_flag && is_backedge(from, to))
891 fprintf (F, BACK_EDGE_ATTR);
893 switch (get_irn_opcode(from)) {
895 fprintf (F, CF_EDGE_ATTR);
897 case iro_Start: break;
900 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
901 fprintf (F, CF_EDGE_ATTR);
902 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
903 fprintf (F, INTER_MEM_EDGE_ATTR);
911 print_data_edge_vcgattr(F, from, to);
916 print_mem_edge_vcgattr(F, from, to);
918 print_data_edge_vcgattr(F, from, to);
922 print_data_edge_vcgattr(F, from, to);
927 print_mem_edge_vcgattr(F, from, to);
929 print_data_edge_vcgattr(F, from, to);
936 print_data_edge_vcgattr(F, from, to);
943 print_mem_edge_vcgattr(F, from, to);
945 print_data_edge_vcgattr(F, from, to);
957 print_data_edge_vcgattr(F, from, to);
960 if (get_irn_modecode(from) == irm_M)
961 fprintf (F, INTER_MEM_EDGE_ATTR);
963 print_data_edge_vcgattr(F, from, to);
970 print_mem_edge_vcgattr(F, from, to);
972 print_data_edge_vcgattr(F, from, to);
975 print_mem_edge_vcgattr(F, from, to);
977 case iro_Tuple: break;
980 switch (get_irn_modecode(from)) {
982 fprintf (F, CF_EDGE_ATTR);
985 fprintf (F, INTER_MEM_EDGE_ATTR);
988 print_data_edge_vcgattr(F, from, to);
993 case iro_Unknown: break;
995 switch (get_irn_modecode(from)) {
997 fprintf (F, INTRA_MEM_EDGE_ATTR);
1000 fprintf (F, CF_EDGE_ATTR);
1003 print_data_edge_vcgattr(F, from, to);
1011 /* dump edges to our inputs */
1013 dump_ir_data_edges(FILE *F, ir_node *n) {
1015 unsigned long visited = get_irn_visited(n);
1017 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1020 for (i = 0; i < get_irn_arity(n); i++) {
1021 ir_node * pred = get_irn_n(n, i);
1024 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1025 continue; /* pred not dumped */
1027 if (dump_backedge_information_flag && is_backedge(n, i))
1028 fprintf (F, "backedge: {sourcename: \"");
1030 fprintf (F, "edge: {sourcename: \"");
1032 fprintf (F, "\" targetname: ");
1033 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1034 PRINT_CONSTID(n, pred);
1036 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1038 fprintf (F, " label: \"%d\" ", i);
1039 print_edge_vcgattr(F, n, i);
1044 /** Dumps a node and its edges but not the block edge
1047 dump_node_wo_blockedge (ir_node *n, void *env) {
1050 dump_ir_data_edges(F, n);
1053 /** Dumps a node and its edges.
1056 dump_whole_node (ir_node *n, void *env) {
1058 dump_node_wo_blockedge(n, env);
1059 if (!node_floats(n)) dump_ir_block_edge(F, n);
1063 dump_const_node(ir_node *n, void *env) {
1064 if (is_Block(n)) return;
1065 dump_node_wo_blockedge(n, env);
1068 /***********************************************************************/
1069 /* the following routines dump the nodes/irgs bracketed to graphs. */
1070 /***********************************************************************/
1072 /** Dumps a constant expression as entity initializer, array bound ...
1074 static void dump_const_expression(FILE *F, ir_node *value) {
1075 ir_graph *rem = current_ir_graph;
1076 int rem_dump_const_local = dump_const_local;
1077 dump_const_local = 0;
1078 current_ir_graph = get_const_code_irg();
1079 irg_walk(value, dump_const_node, NULL, F);
1080 /* Decrease visited flag so that we walk with the same flag for the next
1081 expresssion. This guarantees that we don't dump the same node twice,
1082 as for const expressions cse is performed to save memory. */
1083 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1084 current_ir_graph = rem;
1085 dump_const_local = rem_dump_const_local;
1088 /** Dump a block as graph containing its nodes.
1090 * Expects to find nodes belonging to the block as list in its
1092 * Dumps the edges of all nodes including itself. */
1094 dump_whole_block(FILE *F, ir_node *block) {
1096 assert(is_Block(block));
1098 fprintf(F, "graph: { title: \"");
1099 PRINT_NODEID(block);
1100 fprintf(F, "\" label: \"");
1101 dump_node_opcode(F, block);
1102 fprintf (F, " %ld", get_irn_node_nr(block));
1104 if (get_opt_dump_abstvals())
1105 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1107 fprintf(F, "\" status:clustered color:%s \n",
1108 get_Block_matured(block) ? "yellow" : "red");
1110 /* dump the blocks edges */
1111 dump_ir_data_edges(F, block);
1113 /* dump the nodes that go into the block */
1114 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1116 dump_ir_data_edges(F, node);
1119 /* Close the vcg information for the block */
1121 dump_const_node_local(F, block);
1123 dump_chi_term(F, block);
1128 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1129 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1131 dump_block_graph(FILE *F, ir_graph *irg) {
1133 ir_graph *rem = current_ir_graph;
1134 ir_node **arr = ird_get_irg_link(irg);
1135 current_ir_graph = irg;
1137 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1138 ir_node * node = arr[i];
1139 if (is_Block(node)) {
1140 /* Dumps the block and all the nodes in the block, which are to
1141 be found in Block->link. */
1142 dump_whole_block(F, node);
1144 /* Nodes that are not in a Block. */
1146 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1147 dump_const_block_local(F, node);
1149 dump_ir_data_edges(F, node);
1153 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1154 dump_loop_nodes_into_graph(F, irg);
1156 current_ir_graph = rem;
1159 /** Dumps an irg as a graph.
1160 * If interprocedural view edges can point to nodes out of this graph.
1162 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1164 fprintf(F, "graph: { title: \"");
1166 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1167 get_ent_dump_name(get_irg_entity(irg)));
1169 dump_block_graph(F, irg);
1171 /* Close the vcg information for the irg */
1172 fprintf(F, "}\n\n");
1175 /*******************************************************************/
1176 /* Basic type and entity nodes and edges. */
1177 /*******************************************************************/
1179 /** dumps the edges between nodes and their type or entity attributes. */
1180 static void dump_node2type_edges(ir_node *n, void *env)
1185 switch (get_irn_opcode(n)) {
1187 /* @@@ some consts have an entity */
1190 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1191 || (get_SymConst_kind(n) ==symconst_size))
1193 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1197 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1200 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1203 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1206 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1209 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1217 static int print_type_info(FILE *F, type *tp) {
1220 if (get_type_state(tp) == layout_undefined) {
1221 fprintf(F, "state: layout_undefined\n");
1223 fprintf(F, "state: layout_fixed,\n");
1225 if (get_type_mode(tp))
1226 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1227 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1232 static void print_typespecific_info(FILE *F, type *tp) {
1233 switch (get_type_tpop_code(tp)) {
1236 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1243 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1244 fprintf(F, "params: %d\n", get_method_n_params(tp));
1245 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1253 case tpo_enumeration:
1267 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1268 switch (get_type_tpop_code(tp)) {
1271 if (peculiarity_existent == get_class_peculiarity(tp))
1272 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1274 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1278 fprintf (F, " " TYPE_METH_NODE_ATTR);
1289 case tpo_enumeration:
1302 static int print_type_node(FILE *F, type *tp)
1306 fprintf (F, "node: {title: ");
1308 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1309 fprintf (F, " info1: \"");
1310 bad |= print_type_info(F, tp);
1311 print_typespecific_info(F, tp);
1313 print_typespecific_vcgattr(F, tp);
1319 #define X(a) case a: fprintf(F, #a); break
1320 void dump_entity_node(FILE *F, entity *ent, int color)
1322 fprintf (F, "node: {title: \"");
1323 PRINT_ENTID(ent); fprintf(F, "\"");
1324 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1325 fprintf (F, "label: ");
1326 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1328 fprintf(F, "color: %d", color);
1330 fprintf (F, ENTITY_NODE_ATTR);
1331 fprintf (F, "\n info1: \"");
1333 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1335 fprintf(F, "\"\n}\n");
1339 static void dump_enum_item(FILE *F, type *tp, int pos)
1342 ident *id = get_enumeration_nameid(tp, pos);
1343 tarval *tv = get_enumeration_enum(tp, pos);
1345 tarval_snprintf(buf, sizeof(buf), tv);
1346 fprintf (F, "node: {title: \"");
1347 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1348 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1349 fprintf (F, "label: ");
1350 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1351 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1354 /* dumps a type or entity and it's edges. */
1356 dump_type_info(type_or_ent *tore, void *env) {
1358 int i = 0; /* to shutup gcc */
1360 /* dump this type or entity */
1362 switch (get_kind(tore)) {
1365 entity *ent = (entity *)tore;
1368 dump_entity_node(F, ent, 0);
1370 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1371 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1372 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1373 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1374 if(is_class_type(get_entity_owner(ent))) {
1375 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1376 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1378 /* attached subgraphs */
1379 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1380 if (is_atomic_entity(ent)) {
1381 value = get_atomic_ent_value(ent);
1383 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1384 /* DDMN(value); $$$ */
1385 dump_const_expression(F, value);
1388 if (is_compound_entity(ent)) {
1389 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1390 value = get_compound_ent_value(ent, i);
1392 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1393 dump_const_expression(F, value);
1394 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1396 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1397 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1398 get_compound_ent_value_member(ent, i), i);
1407 type *tp = (type *)tore;
1408 print_type_node(F, tp);
1409 /* and now the edges */
1410 switch (get_type_tpop_code(tp)) {
1413 for (i=0; i < get_class_n_supertypes(tp); i++)
1414 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1415 for (i=0; i < get_class_n_members(tp); i++)
1416 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1420 for (i=0; i < get_struct_n_members(tp); i++)
1421 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1425 for (i = 0; i < get_method_n_params(tp); i++)
1426 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1427 for (i = 0; i < get_method_n_ress(tp); i++)
1428 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1432 for (i = 0; i < get_union_n_members(tp); i++)
1433 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1437 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1438 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1439 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1440 ir_node *upper = get_array_upper_bound(tp, i);
1441 ir_node *lower = get_array_lower_bound(tp, i);
1442 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1443 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1444 dump_const_expression(F, upper);
1445 dump_const_expression(F, lower);
1449 case tpo_enumeration:
1451 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1452 dump_enum_item(F, tp, i);
1453 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1458 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1466 break; /* case k_type */
1469 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1471 } /* switch kind_or_entity */
1474 typedef struct _h_env {
1479 /** For dumping class hierarchies.
1480 * Dumps a class type node and a superclass edge.
1481 * If env->dump_ent dumps entities of classes and overwrites edges.
1484 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1487 int i = 0; /* to shutup gcc */
1489 /* dump this type or entity */
1490 switch (get_kind(tore)) {
1492 entity *ent = (entity *)tore;
1493 if (get_entity_owner(ent) == get_glob_type()) break;
1494 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1495 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1497 dump_entity_node(F, ent, 0);
1499 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1500 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1501 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1503 } break; /* case k_entity */
1506 type *tp = (type *)tore;
1507 if (tp == get_glob_type()) break;
1508 switch (get_type_tpop_code(tp)) {
1510 print_type_node(F, tp);
1511 /* and now the edges */
1512 for (i=0; i < get_class_n_supertypes(tp); i++)
1514 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1520 break; /* case k_type */
1523 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1525 } /* switch kind_or_entity */
1528 /*******************************************************************/
1529 /* dump analysis information that is expressed in graph terms. */
1530 /*******************************************************************/
1532 /* dump out edges */
1534 dump_out_edge(ir_node *n, void *env) {
1537 for (i = 0; i < get_irn_n_outs(n); i++) {
1538 assert(get_irn_out(n, i));
1539 fprintf (F, "edge: {sourcename: \"");
1541 fprintf (F, "\" targetname: \"");
1542 PRINT_NODEID(get_irn_out(n, i));
1543 fprintf (F, "\" color: red linestyle: dashed");
1549 dump_loop_label(FILE *F, ir_loop *loop) {
1550 fprintf (F, "loop %d, %d sons, %d nodes",
1551 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1554 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1555 fprintf (F, " info1: \"");
1556 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1557 #if DEBUG_libfirm /* GL @@@ debug analyses */
1558 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1564 dump_loop_node(FILE *F, ir_loop *loop) {
1565 fprintf (F, "node: {title: \"");
1567 fprintf (F, "\" label: \"");
1568 dump_loop_label(F, loop);
1570 dump_loop_info(F, loop);
1576 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1578 fprintf (F, "edge: {sourcename: \"");
1580 fprintf (F, "\" targetname: \"");
1581 PRINT_NODEID(get_loop_node(loop, i));
1582 fprintf (F, "\" color: green");
1587 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1589 fprintf (F, "edge: {sourcename: \"");
1591 fprintf (F, "\" targetname: \"");
1592 PRINT_LOOPID(get_loop_son(loop, i));
1593 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1594 get_loop_element_pos(loop, get_loop_son(loop, i)));
1598 void dump_loops(FILE *F, ir_loop *loop) {
1600 /* dump this loop node */
1601 dump_loop_node(F, loop);
1603 /* dump edges to nodes in loop -- only if it is a real loop */
1604 if (get_loop_depth(loop) != 0) {
1605 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1606 dump_loop_node_edge(F, loop, i);
1609 for (i = 0; i < get_loop_n_sons(loop); i++) {
1610 dump_loops(F, get_loop_son(loop, i));
1611 dump_loop_son_edge(F, loop, i);
1616 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1617 ir_graph *rem = current_ir_graph;
1618 current_ir_graph = irg;
1620 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1622 current_ir_graph = rem;
1627 * dumps the VCG header
1629 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1638 if (!orientation) orientation = "bottom_to_top";
1642 "graph: { title: \"ir graph of %s\"\n"
1643 "display_edge_labels: %s\n"
1644 "layoutalgorithm: mindepth\n"
1645 "manhattan_edges: yes\n"
1646 "port_sharing: no\n"
1648 "classname 1: \"intrablock Data\"\n"
1649 "classname 16: \"interblock Data\"\n"
1650 "classname 2: \"Block\"\n"
1651 "classname 13: \"Control Flow\"\n"
1652 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1653 "classname 14: \"intrablock Memory\"\n"
1654 "classname 17: \"interblock Memory\"\n"
1655 "classname 15: \"Dominators\"\n"
1656 "classname 3: \"Entity type\"\n"
1657 "classname 4: \"Entity owner\"\n"
1658 "classname 5: \"Method Param\"\n"
1659 "classname 6: \"Method Res\"\n"
1660 "classname 7: \"Super\"\n"
1661 "classname 8: \"Union\"\n"
1662 "classname 9: \"Points-to\"\n"
1663 "classname 10: \"Array Element Type\"\n"
1664 "classname 11: \"Overwrites\"\n"
1665 "classname 12: \"Member\"\n"
1666 "infoname 1: \"Attribute\"\n"
1667 "infoname 2: \"Verification errors\"\n",
1668 name, label, orientation);
1670 /* don't use all, the range is too whith/black. */
1674 "colorentry 100: 0 0 0\n"
1675 "colorentry 101: 20 0 0\n"
1676 "colorentry 102: 40 0 0\n"
1677 "colorentry 103: 60 0 0\n"
1678 "colorentry 104: 80 0 0\n"
1679 "colorentry 105: 100 0 0\n"
1680 "colorentry 106: 120 0 0\n"
1681 "colorentry 107: 140 0 0\n"
1682 "colorentry 108: 150 0 0\n"
1683 "colorentry 109: 180 0 0\n"
1684 "colorentry 110: 200 0 0\n"
1685 "colorentry 111: 220 0 0\n"
1686 "colorentry 112: 240 0 0\n"
1687 "colorentry 113: 255 0 0\n"
1688 "colorentry 113: 255 20 20\n"
1689 "colorentry 114: 255 40 40\n"
1690 "colorentry 115: 255 60 60\n"
1691 "colorentry 116: 255 80 80\n"
1692 "colorentry 117: 255 100 100\n"
1693 "colorentry 118: 255 120 120\n"
1694 "colorentry 119: 255 140 140\n"
1695 "colorentry 120: 255 150 150\n"
1696 "colorentry 121: 255 180 180\n"
1697 "colorentry 122: 255 200 200\n"
1698 "colorentry 123: 255 220 220\n"
1699 "colorentry 124: 255 240 240\n"
1700 "colorentry 125: 255 250 250\n"
1703 fprintf (F, "\n"); /* a separator */
1709 * @param irg The graph to be dumped
1710 * @param suffix1 first filename suffix
1711 * @param suffix2 second filename suffix
1713 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1715 const char *nm = get_irg_dump_name(irg);
1716 int len = strlen(nm), i, j;
1717 char *fname; /* filename to put the vcg information in */
1719 if (!suffix1) suffix1 = "";
1720 if (!suffix2) suffix2 = "";
1722 /* open file for vcg graph */
1723 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1725 /* strncpy (fname, nm, len); */ /* copy the filename */
1727 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1729 fname[j] = '@'; j++; fname[j] = '1'; j++;
1730 } else if (nm[i] == '@') {
1731 fname[j] = '@'; j++; fname[j] = '2'; j++;
1733 fname[j] = nm[i]; j++;
1737 strcat (fname, suffix1); /* append file suffix */
1738 strcat (fname, suffix2); /* append file suffix */
1739 strcat (fname, ".vcg"); /* append the .vcg suffix */
1740 F = fopen (fname, "w"); /* open file for writing */
1742 panic("cannot open %s for writing (%m)", fname); /* not reached */
1752 * @param irg The graph to be dumped
1753 * @param suffix filename suffix
1755 static FILE *vcg_open_name (const char *name, const char *suffix) {
1757 char *fname; /* filename to put the vcg information in */
1758 int i, j, len = strlen(name);
1760 if (!suffix) suffix = "";
1762 /** open file for vcg graph */
1763 fname = malloc (len * 2 + 5 + strlen(suffix));
1764 /* strcpy (fname, name);*/ /* copy the filename */
1766 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1767 if (name[i] == '/') {
1768 fname[j] = '@'; j++; fname[j] = '1'; j++;
1769 } else if (name[i] == '@') {
1770 fname[j] = '@'; j++; fname[j] = '2'; j++;
1772 fname[j] = name[i]; j++;
1776 strcat (fname, suffix);
1777 strcat (fname, ".vcg"); /* append the .vcg suffix */
1778 F = fopen (fname, "w"); /* open file for writing */
1780 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1788 * Dumps the vcg file footer
1790 static INLINE void dump_vcg_footer (FILE *F) {
1795 * close the vcg file
1797 void vcg_close (FILE *F) {
1798 dump_vcg_footer(F); /* print footer */
1799 fclose (F); /* close vcg file */
1802 /************************************************************************/
1803 /************************************************************************/
1804 /* Routines that dump all or parts of the firm representation to a file */
1805 /************************************************************************/
1806 /************************************************************************/
1808 /************************************************************************/
1809 /* Dump ir graphs, differnt formats and additional information. */
1810 /************************************************************************/
1812 /** Routine to dump a graph, blocks as conventional nodes. */
1814 dump_ir_graph (ir_graph *irg, const char *suffix )
1819 rem = current_ir_graph;
1821 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1822 current_ir_graph = irg;
1823 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1824 else suffix1 = "-pure";
1825 f = vcg_open(irg, suffix, suffix1);
1826 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1828 /* walk over the graph */
1829 /* dump_whole_node must be called in post visiting predecessors */
1830 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1832 /* dump the out edges in a separate walk */
1833 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1834 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1839 current_ir_graph = rem;
1844 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1850 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1853 if (get_interprocedural_view()) suffix1 = "-ip";
1855 f = vcg_open(irg, suffix, suffix1);
1856 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1858 construct_block_lists(irg);
1860 for (i = 0; i < get_irp_n_irgs(); i++) {
1861 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1863 dump_graph_from_list(f, get_irp_irg(i));
1871 /** dumps a graph with type information */
1873 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1876 ir_graph *rem = current_ir_graph;
1879 /* if a filter is set, dump only the irg's that match the filter */
1880 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1883 current_ir_graph = irg;
1885 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1886 else suffix1 = "-pure-wtypes";
1887 f = vcg_open(irg,suffix, suffix1);
1888 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1890 /* dump common ir graph */
1891 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1892 /* dump type info */
1893 type_walk_irg(irg, dump_type_info, NULL, f);
1894 inc_irg_visited(get_const_code_irg());
1895 /* dump edges from graph to type info */
1896 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1899 current_ir_graph = rem;
1903 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1908 ir_graph *rem = current_ir_graph;
1910 /* if a filter is set, dump only the irg's that match the filter */
1911 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1914 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1915 else suffix1 = "-wtypes";
1916 f = vcg_open(irg, suffix, suffix1);
1917 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1919 /* dump common blocked ir graph */
1920 construct_block_lists(irg);
1922 for (i = 0; i < get_irp_n_irgs(); i++) {
1923 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1925 dump_graph_from_list(f, get_irp_irg(i));
1930 /* dump type info */
1931 current_ir_graph = irg;
1932 type_walk_irg(irg, dump_type_info, NULL, f);
1933 inc_irg_visited(get_const_code_irg());
1935 /* dump edges from graph to type info */
1936 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1938 current_ir_graph = rem;
1942 /*---------------------------------------------------------------------*/
1943 /* The following routines dump a control flow graph. */
1944 /*---------------------------------------------------------------------*/
1947 dump_block_to_cfg(ir_node *block, void *env) {
1952 if (is_Block(block)) {
1953 /* This is a block. Dump a node for the block. */
1954 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1955 fprintf (F, "\" label: \"");
1956 if (block == get_irg_start_block(get_irn_irg(block)))
1957 fprintf(F, "Start ");
1958 if (block == get_irg_end_block(get_irn_irg(block)))
1961 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1962 PRINT_NODEID(block);
1964 fprintf(F, "info1:\"");
1965 if (dump_dominator_information_flag)
1966 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1968 /* show arity and possible Bad predecessors of the block */
1969 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1970 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1971 ir_node *pred = get_Block_cfgpred(block, i);
1974 fprintf(F, "Bad pred at pos: ");
1975 fprintf(F, "%d ", i);
1982 fprintf (F, "\""); /* closing quote of info */
1984 if ((block == get_irg_start_block(get_irn_irg(block))) ||
1985 (block == get_irg_end_block(get_irn_irg(block))) )
1986 fprintf(F, " color:blue ");
1988 fprintf(F, " color:yellow ");
1991 /* Dump the edges */
1992 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1993 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1994 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1995 fprintf (F, "edge: { sourcename: \"");
1996 PRINT_NODEID(block);
1997 fprintf (F, "\" targetname: \"");
1999 fprintf (F, "\"}\n");
2002 /* Dump dominator edge */
2003 if (dump_dominator_information_flag && get_Block_idom(block)) {
2004 pred = get_Block_idom(block);
2005 fprintf (F, "edge: { sourcename: \"");
2006 PRINT_NODEID(block);
2007 fprintf (F, "\" targetname: \"");
2009 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2015 dump_cfg (ir_graph *irg, const char *suffix)
2018 ir_graph *rem = current_ir_graph;
2019 int ddif = dump_dominator_information_flag;
2020 int ipv = get_interprocedural_view();
2022 /* if a filter is set, dump only the irg's that match the filter */
2023 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2026 current_ir_graph = irg;
2028 f = vcg_open(irg, suffix, "-cfg");
2029 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2032 printf("Warning: dumping cfg not in interprocedural view!\n");
2033 set_interprocedural_view(false);
2036 if (get_irg_dom_state(irg) != dom_consistent)
2037 dump_dominator_information_flag = 0;
2039 /* walk over the blocks in the graph */
2040 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2041 dump_node(f, get_irg_bad(irg));
2043 dump_dominator_information_flag = ddif;
2044 set_interprocedural_view(ipv);
2046 current_ir_graph = rem;
2049 static int weight_overall(int rec, int loop) {
2050 return 2*rec + loop;
2053 static int compute_color (int my, int max) {
2060 /* if small, scale to the full color range. */
2062 my = my * (n_colors/max);
2064 step = 1 + (max / n_colors);
2068 return base_color + n_colors - color;
2071 static int get_entity_color(entity *ent) {
2072 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;
2092 void dump_callgraph(const char *suffix) {
2094 int i, n_irgs = get_irp_n_irgs();
2095 int rem = edge_label;
2097 //ident *prefix = new_id_from_str("java/");
2099 F = vcg_open_name("Callgraph", suffix);
2100 dump_vcg_header(F, "Callgraph", NULL);
2102 for (i = 0; i < n_irgs; ++i) {
2103 ir_graph *irg = get_irp_irg(i);
2104 entity *ent = get_irg_entity(irg);
2105 int j, n_callees = get_irg_n_callees(irg);
2107 /* Do not dump runtime system. */
2108 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2110 dump_entity_node(F, ent, get_entity_color(ent));
2111 for (j = 0; j < n_callees; ++j) {
2112 entity *c = get_irg_entity(get_irg_callee(irg, j));
2113 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2114 int be = is_irg_callee_backedge(irg, j);
2117 "label:\"recursion %d\" color: %d" :
2118 "label:\"calls %d\" color: %d";
2119 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2127 /* Dump all irgs in interprocedural view to a single file. */
2128 void dump_all_cg_block_graph(const char *suffix) {
2131 int rem_view = get_interprocedural_view();
2132 set_interprocedural_view(true);
2134 f = vcg_open_name("All_graphs", suffix);
2135 dump_vcg_header(f, "All_graphs", NULL);
2137 /* collect nodes in all irgs reachable in call graph*/
2138 for (i = 0; i < get_irp_n_irgs(); i++)
2139 ird_set_irg_link(get_irp_irg(i), NULL);
2141 cg_walk(clear_link, collect_node, NULL);
2143 /* dump all graphs */
2144 for (i = 0; i < get_irp_n_irgs(); i++) {
2145 current_ir_graph = get_irp_irg(i);
2146 assert(ird_get_irg_link(current_ir_graph));
2147 dump_graph_from_list(f, current_ir_graph);
2148 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2152 set_interprocedural_view(rem_view);
2155 /*---------------------------------------------------------------------*/
2156 /* the following routines dumps type information without any ir nodes. */
2157 /*---------------------------------------------------------------------*/
2160 dump_type_graph (ir_graph *irg, const char *suffix)
2164 rem = current_ir_graph;
2166 /* if a filter is set, dump only the irg's that match the filter */
2167 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2169 current_ir_graph = irg;
2171 f = vcg_open(irg, suffix, "-type");
2172 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2174 /* walk over the blocks in the graph */
2175 type_walk_irg(irg, dump_type_info, NULL, f);
2176 /* The walker for the const code can be called several times for the
2177 same (sub) experssion. So that no nodes are dumped several times
2178 we decrease the visited flag of the corresponding graph after each
2179 walk. So now increase it finally. */
2180 inc_irg_visited(get_const_code_irg());
2183 current_ir_graph = rem;
2187 dump_all_types (const char *suffix)
2189 FILE *f = vcg_open_name("All_types", suffix);
2190 dump_vcg_header(f, "All_types", NULL);
2191 type_walk(dump_type_info, NULL, f);
2192 inc_irg_visited(get_const_code_irg());
2197 dump_class_hierarchy (bool entities, const char *suffix)
2199 FILE *f = vcg_open_name("class_hierarchy", suffix);
2203 dump_vcg_header(f, "class_hierarchy", NULL);
2208 type_walk(dump_class_hierarchy_node, NULL, &env);
2212 /*---------------------------------------------------------------------*/
2213 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2215 /* dump_ir_block_graph */
2217 /* dump_type_graph */
2218 /* dump_ir_graph_w_types */
2219 /*---------------------------------------------------------------------*/
2221 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2222 int i, n_irgs = get_irp_n_irgs();
2223 for (i = 0; i < n_irgs; ++i) {
2224 dmp_grph(get_irp_irg(i), suffix);
2229 /*--------------------------------------------------------------------------------*
2230 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2231 * packed together in one subgraph/box *
2232 *--------------------------------------------------------------------------------*/
2234 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2235 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2237 ir_loop *son = NULL;
2239 /* Dump a new loop node. */
2240 dump_loop_node(F, loop);
2242 /* Dump the loop elements. */
2244 for(i = 0; i < get_loop_n_elements(loop); i++) {
2245 le = get_loop_element(loop, i);
2247 if (get_kind(son) == k_ir_loop) {
2249 /* We are a loop son -> Recurse */
2251 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2252 fprintf(F, "\" }\n");
2253 fprintf (F, "edge: {sourcename: \"");
2255 fprintf (F, "\" targetname: \"");
2257 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2258 loop_node_started = 0;
2260 dump_loop_son_edge(F, loop, son_number++);
2261 dump_loops_standalone(F, son);
2262 } else if (get_kind(son) == k_ir_node) {
2263 /* We are a loop node -> Collect firm nodes */
2265 ir_node *n = le.node;
2268 if (!loop_node_started) {
2269 /* Start a new node which contains all firm nodes of the current loop */
2270 fprintf (F, "node: { title: \"");
2272 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2273 loop_node_started = 1;
2279 bad |= dump_node_opcode(F, n);
2280 bad |= dump_node_mode(F, n);
2281 bad |= dump_node_typeinfo(F, n);
2283 bad |= dump_node_nodeattr(F, n);
2284 fprintf (F, " %ld", get_irn_node_nr(n));
2285 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2286 if (has_backedges(n)) fprintf(F, "\t loop head!");
2287 } else { /* for callgraph loop tree */
2289 assert(get_kind(son) == k_ir_graph);
2291 /* We are a loop node -> Collect firm graphs */
2292 n = (ir_graph *)le.node;
2293 if (!loop_node_started) {
2294 /* Start a new node which contains all firm nodes of the current loop */
2295 fprintf (F, "node: { title: \"");
2297 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2298 loop_node_started = 1;
2303 fprintf (F, " %s", get_irg_dump_name(n));
2304 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2308 if (loop_node_started) {
2309 fprintf(F, "\" }\n");
2310 fprintf (F, "edge: {sourcename: \"");
2312 fprintf (F, "\" targetname: \"");
2314 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2315 loop_node_started = 0;
2319 void dump_loop_tree(ir_graph *irg, const char *suffix)
2322 ir_graph *rem = current_ir_graph;
2323 int el_rem = edge_label;
2326 /* if a filter is set, dump only the irg's that match the filter */
2327 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2330 current_ir_graph = irg;
2332 f = vcg_open(irg, suffix, "-looptree");
2333 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2335 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2339 edge_label = el_rem;
2340 current_ir_graph = rem;
2343 void dump_callgraph_loop_tree(const char *suffix) {
2345 F = vcg_open_name("Callgraph_looptree", suffix);
2346 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2347 dump_loops_standalone(F, irp->outermost_cg_loop);
2352 /*-----------------------------------------------------------------------------*/
2353 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2354 /*-----------------------------------------------------------------------------*/
2356 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2357 int i, son_number = 0, node_number = 0;
2359 if (dump_loop_information_flag) dump_loop_node(F, loop);
2361 for (i = 0; i < get_loop_n_elements(loop); i++) {
2362 loop_element le = get_loop_element(loop, i);
2363 if (*(le.kind) == k_ir_loop) {
2364 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2366 collect_nodeloop(F, le.son, loopnodes);
2368 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2369 eset_insert(loopnodes, le.node);
2374 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2377 for(i = 0; i < get_loop_n_elements(loop); i++) {
2378 loop_element le = get_loop_element(loop, i);
2379 if (*(le.kind) == k_ir_loop) {
2381 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2383 if (is_Block(le.node)) start = 0; else start = -1;
2384 for (j = start; j < get_irn_arity(le.node); j++) {
2385 ir_node *pred = get_irn_n(le.node, j);
2386 if (!eset_contains(loopnodes, pred)) {
2387 eset_insert(extnodes, pred);
2388 if (!is_Block(pred)) {
2389 pred = get_nodes_block(pred);
2390 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2398 void dump_loop(ir_loop *l, const char *suffix) {
2401 eset *loopnodes = eset_create();
2402 eset *extnodes = eset_create();
2405 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2406 F = vcg_open_name (name, suffix);
2407 dump_vcg_header(F, name, NULL);
2409 /* collect all nodes to dump */
2410 collect_nodeloop(F, l, loopnodes);
2411 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2413 /* build block lists */
2414 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2415 set_irn_link(n, NULL);
2416 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2417 set_irn_link(n, NULL);
2418 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2420 b = get_nodes_block(n);
2421 set_irn_link(n, get_irn_link(b));
2424 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2426 b = get_nodes_block(n);
2427 set_irn_link(n, get_irn_link(b));
2431 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2433 fprintf(F, "graph: { title: \"");
2435 fprintf(F, "\" label: \"");
2436 dump_node_opcode(F, b);
2437 fprintf (F, " %ld", get_irn_node_nr(b));
2438 fprintf(F, "\" status:clustered color:yellow\n");
2440 /* dump the blocks edges */
2441 dump_ir_data_edges(F, b);
2443 /* dump the nodes that go into the block */
2444 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2445 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2447 overrule_nodecolor = NULL;
2448 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2451 /* Close the vcg information for the block */
2453 dump_const_node_local(F, b);
2456 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2458 fprintf(F, "graph: { title: \"");
2460 fprintf(F, "\" label: \"");
2461 dump_node_opcode(F, b);
2462 fprintf (F, " %ld", get_irn_node_nr(b));
2463 fprintf(F, "\" status:clustered color:lightblue\n");
2465 /* dump the nodes that go into the block */
2466 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2467 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2469 overrule_nodecolor = NULL;
2470 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2473 /* Close the vcg information for the block */
2475 dump_const_node_local(F, b);
2479 eset_destroy(loopnodes);
2480 eset_destroy(extnodes);