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"
52 void dump_irn_chi_term(FILE *FL, ir_node *n);
53 void dump_irn_state(FILE *FL, ir_node *n);
54 int get_opt_dump_abstvals(void);
55 typedef unsigned long SeqNo;
56 SeqNo get_Block_seqno(ir_node *n);
59 /* basis for a color range for vcg */
60 static int n_colors = 0;
61 static int base_color = 0;
63 #define ERROR_TXT "<ERROR>"
66 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
67 * in the later case, sets bad
69 const char *get_mode_name_ex(ir_mode *mode, int *bad)
72 return get_mode_name(mode);
78 * returns the name of a type or <ERROR> if mode is NOT a mode object.
79 * in the later case, sets bad
81 const char *get_type_name_ex(type *tp, int *bad)
84 return get_type_name(tp);
90 * prints the edge from a type S to a type T with additional info fmt, ...
93 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
98 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
99 fprintf(F, " targetname: "); PRINT_TYPEID(T);
100 vfprintf(F, fmt, ap);
106 * prints the edge from a type T to an entity E with additional info fmt, ...
109 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
114 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
115 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
116 vfprintf(F, fmt, ap);
122 * prints the edge from an entity E to an entity T with additional info fmt, ...
125 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
131 fprintf(F, "backedge: { sourcename: \"");
133 fprintf(F, "edge: { sourcename: \"");
135 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
136 vfprintf(F, fmt, ap);
142 * prints the edge from an entity E to a type T with additional info fmt, ...
145 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
150 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
151 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
152 vfprintf(F, fmt, ap);
158 * prints the edge from a node N to a type T with additional info fmt, ...
161 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
166 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
167 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
168 vfprintf(F, fmt, ap);
174 * prints the edge from a node N to an entity E with additional info fmt, ...
177 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
182 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
183 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
185 vfprintf(F, fmt, ap);
191 * prints the edge from an entity E to a node N with additional info fmt, ...
194 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
199 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
200 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
201 vfprintf(F, fmt, ap);
207 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
210 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
215 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
216 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
217 vfprintf(F, fmt, ap);
222 /*-----------------------------------------------------------------*/
223 /* global and ahead declarations */
224 /*-----------------------------------------------------------------*/
226 static void dump_whole_node(ir_node *n, void *env);
227 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
229 /*-----------------------------------------------------------------*/
230 /* Helper functions. */
231 /*-----------------------------------------------------------------*/
234 * This map is used as a private link attr to be able to call dumper
235 * anywhere without destroying link fields.
237 static pmap *irdump_link_map = NULL;
239 /** Creates the link attribut map. */
240 static void init_irdump(void) {
241 /* We need a new, empty map. */
242 if (irdump_link_map) pmap_destroy(irdump_link_map);
243 irdump_link_map = pmap_create();
247 * Returns the private link field.
249 static void *ird_get_irn_link(ir_node *n) {
251 if (!irdump_link_map) return NULL;
253 if (pmap_contains(irdump_link_map, (void *)n))
254 res = pmap_get(irdump_link_map, (void *)n);
259 * Sets the private link field.
261 static void ird_set_irn_link(ir_node *n, void *x) {
262 if (!irdump_link_map) init_irdump();
263 pmap_insert(irdump_link_map, (void *)n, x);
267 * Gets the private link field of an irg.
269 static void *ird_get_irg_link(ir_graph *irg) {
271 if (!irdump_link_map) return NULL;
273 if (pmap_contains(irdump_link_map, (void *)irg))
274 res = pmap_get(irdump_link_map, (void *)irg);
279 * Sets the private link field of an irg.
281 static void ird_set_irg_link(ir_graph *irg, void *x) {
282 if (!irdump_link_map) init_irdump();
283 pmap_insert(irdump_link_map, (void *)irg, x);
287 * Walker, clears tzhe private link field
289 static void clear_link(ir_node * node, void * env) {
290 ird_set_irn_link(node, NULL);
294 * If the entity has a ld_name, returns it, else returns the name of the entity.
296 const char *get_ent_dump_name(entity *ent) {
298 return "<NULL entity>";
299 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
300 if (ent->ld_name) return get_id_str(ent->ld_name);
301 return get_id_str(ent->name);
304 /* Returns the name of an IRG. */
305 const char *get_irg_dump_name(ir_graph *irg) {
306 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
307 entity *ent = get_irg_entity(irg);
308 return get_ent_dump_name(ent);
312 * Returns non-zero if a node is in floating state.
314 static int node_floats(ir_node *n) {
315 return ((get_irn_pinned(n) == op_pin_state_floats) &&
316 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
320 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
322 static void collect_node(ir_node * node, void *env) {
325 || get_irn_op(node) == op_Bad
326 || get_irn_op(node) == op_Unknown
327 || get_irn_op(node) == op_NoMem) {
328 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
329 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
330 ARR_APP1(ir_node *, arr, node);
331 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
333 ir_node * block = get_nodes_block(node);
336 /* this node is in a Bad block, so we must place it into the graph's list */
337 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
338 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
339 ARR_APP1(ir_node *, arr, node);
340 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
343 ird_set_irn_link(node, ird_get_irn_link(block));
344 ird_set_irn_link(block, node);
349 /** Construct lists to walk ir block-wise.
351 * Collects all blocks, nodes not op_pin_state_pinned,
352 * Bad, NoMem and Unknown into a flexible array in link field of
353 * irg they belong to. Sets the irg link field to NULL in all
354 * graphs not visited.
355 * Free the list with DEL_ARR_F().
357 static ir_node ** construct_block_lists(ir_graph *irg) {
358 int i, rem_view = get_interprocedural_view();
359 ir_graph *rem = current_ir_graph;
360 current_ir_graph = irg;
362 for (i = 0; i < get_irp_n_irgs(); i++)
363 ird_set_irg_link(get_irp_irg(i), NULL);
365 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
367 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
368 set_interprocedural_view(false);
370 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
371 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
372 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
373 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
375 set_interprocedural_view(rem_view);
377 current_ir_graph = rem;
378 return ird_get_irg_link(irg);
381 /*******************************************************************/
382 /* flags to steer output */
383 /*******************************************************************/
385 /** Dump only irgs with names start with this string */
386 const char *dump_file_filter = "";
388 /** A compiler option to turn off edge labels */
389 static int edge_label = 1;
390 /** A compiler option to turn off dumping values of constant entities */
391 static int const_entities = 1;
392 /** A compiler option to dump the keep alive edges */
393 static int dump_keepalive = 0;
394 /** Compiler options to dump analysis information in dump_ir_graph */
395 int dump_out_edge_flag = 0;
396 int dump_dominator_information_flag = 0;
397 int dump_loop_information_flag = 0;
398 int dump_backedge_information_flag = 1;
399 int dump_const_local = 0;
400 bool opt_dump_analysed_type_info = 1;
401 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
403 static const char *overrule_nodecolor = NULL;
405 /** The vcg attribute hook. */
406 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
409 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
411 dump_node_vcgattr_hook = hook;
414 INLINE bool get_opt_dump_const_local(void) {
415 if (!dump_out_edge_flag && !dump_loop_information_flag)
416 return dump_const_local;
421 void only_dump_method_with_name(ident *name) {
422 dump_file_filter = get_id_str(name);
426 /* To turn off display of edge labels. Edge labels offen cause xvcg to
427 abort with a segmentation fault. */
428 void turn_off_edge_labels(void) {
432 void dump_consts_local(bool b) {
433 dump_const_local = b;
436 void dump_constant_entity_values(bool b) {
440 void dump_keepalive_edges(bool b) {
444 bool get_opt_dump_keepalive_edges(void) {
445 return dump_keepalive;
448 void dump_out_edges(bool b) {
449 dump_out_edge_flag = b;
452 void dump_dominator_information(bool b) {
453 dump_dominator_information_flag = b;
456 void dump_loop_information(bool b) {
457 dump_loop_information_flag = b;
460 void dump_backedge_information(bool b) {
461 dump_backedge_information_flag = b;
464 /* Dump the information of type field specified in ana/irtypeinfo.h.
465 * If the flag is set, the type name is output in [] in the node label,
466 * else it is output as info.
468 void dump_analysed_type_info(bool b) {
469 opt_dump_analysed_type_info = b;
472 void dump_pointer_values_to_info(bool b) {
473 opt_dump_pointer_values_to_info = b;
476 /*-----------------------------------------------------------------*/
477 /* Routines to dump information about a single ir node. */
478 /*-----------------------------------------------------------------*/
481 * dump the name of a node n to the File F.
484 dump_node_opcode(FILE *F, ir_node *n)
488 switch(get_irn_opcode(n)) {
493 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
494 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
499 if (get_SymConst_kind(n) == symconst_addr_name) {
500 /* don't use get_SymConst_ptr_info as it mangles the name. */
501 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
502 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
503 assert(get_SymConst_entity(n));
504 assert(is_entity(get_SymConst_entity(n)));
505 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
507 assert(get_kind(get_SymConst_type(n)) == k_type);
508 assert(get_type_ident(get_SymConst_type(n)));
509 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
510 if (get_SymConst_kind(n) == symconst_type_tag)
518 if (!get_interprocedural_view())
525 ir_node *pred = get_Proj_pred(n);
527 if (get_irn_opcode(pred) == iro_Cond
528 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
529 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
530 fprintf (F, "defProj");
532 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
533 * fprintf (F, "Arg");
542 if (get_interprocedural_view()) {
543 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
548 case iro_CallBegin: {
549 ir_node *addr = get_CallBegin_ptr(n);
551 if (get_irn_op(addr) == op_Sel)
552 ent = get_Sel_entity(addr);
553 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
554 ent = get_SymConst_entity(addr);
555 fprintf (F, "%s", get_irn_opname(n));
556 if (ent) fprintf (F, " %s", get_entity_name(ent));
560 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
565 fprintf (F, "%s", get_irn_opname(n));
573 * Dump the mode of a node n to a file F.
574 * Ignore modes that are "always known".
577 dump_node_mode(FILE *F, ir_node *n)
580 opcode iro = get_irn_opcode(n);
593 ir_mode *mode = get_irn_mode(n);
595 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
596 (mode != mode_T || iro == iro_Proj))
597 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
605 * Dump the tpe of a node n to a file F if it's known.
607 static int dump_node_typeinfo(FILE *F, ir_node *n) {
610 if (opt_dump_analysed_type_info) {
611 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
612 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
613 type *tp = get_irn_typeinfo_type(n);
615 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
624 * Dump addinional node attributes of some nodes to a file F.
627 dump_node_nodeattr(FILE *F, ir_node *n)
631 switch (get_irn_opcode(n)) {
633 if (false && get_interprocedural_view()) {
634 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
638 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
639 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
641 fprintf (F, "%ld", get_Proj_proj(n));
645 fprintf (F, "%ld", get_Filter_proj(n));
648 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
651 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
654 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
665 * dumps the attributes of a node n into the file F.
666 * Currently this is only the color of a node.
668 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
673 fprintf(F, "color: red");
677 if (dump_node_vcgattr_hook)
678 if (dump_node_vcgattr_hook(F, node, local))
681 n = local ? local : node;
683 switch (get_irn_opcode(n)) {
690 fprintf (F, "color: blue");
693 if (is_Block_dead(n))
694 fprintf (F, "color: lightred");
696 fprintf (F, "color: lightyellow");
699 fprintf (F, "color: green");
705 fprintf (F, "color: yellow");
708 PRINT_DEFAULT_NODE_ATTR;
711 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
716 * Dump the node information of a node n to a file F.
718 static INLINE int dump_node_info(FILE *F, ir_node *n)
720 fprintf (F, " info1: \"");
721 bad = dump_irnode_to_file(F, n);
727 * checks wheater a node is "constant-like", ie can be treated "block-less"
730 bool is_constlike_node(ir_node *n) {
731 ir_op *op = get_irn_op(n);
732 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
736 /** outputs the predecessors of n, that are constants, local. I.e.,
737 generates a copy of the constant predecessors for each node called with. */
738 static void dump_const_node_local(FILE *F, ir_node *n) {
740 if (!get_opt_dump_const_local()) return;
742 /* Use visited flag to avoid outputting nodes twice.
743 initialize it first. */
744 for (i = 0; i < get_irn_arity(n); i++) {
745 ir_node *con = get_irn_n(n, i);
746 if (is_constlike_node(con)) {
747 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
751 for (i = 0; i < get_irn_arity(n); i++) {
752 ir_node *con = get_irn_n(n, i);
753 if (is_constlike_node(con) && irn_not_visited(con)) {
756 mark_irn_visited(con);
757 /* Generate a new name for the node by appending the names of
759 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
760 fprintf(F, " label: \"");
761 bad |= dump_node_opcode(F, con);
762 bad |= dump_node_mode(F, con);
763 bad |= dump_node_typeinfo(F, con);
765 bad |= dump_node_nodeattr(F, con);
766 fprintf(F, " %ld", get_irn_node_nr(con));
768 bad |= dump_node_info(F, con);
769 dump_node_vcgattr(F, n, con, bad);
775 /** If the block of an edge is a const_like node, dump it local with an edge */
776 static void dump_const_block_local(FILE *F, ir_node *n) {
779 if (!get_opt_dump_const_local()) return;
781 blk = get_nodes_block(n);
782 if (is_constlike_node(blk)) {
785 /* Generate a new name for the node by appending the names of
787 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
788 fprintf(F, "\" label: \"");
789 bad |= dump_node_opcode(F, blk);
790 bad |= dump_node_mode(F, blk);
791 bad |= dump_node_typeinfo(F, blk);
793 bad |= dump_node_nodeattr(F, blk);
794 fprintf(F, " %ld", get_irn_node_nr(blk));
796 bad |= dump_node_info(F, blk);
797 dump_node_vcgattr(F, n, blk, bad);
800 fprintf (F, "edge: { sourcename: \"");
802 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
803 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
808 * prints the error message of a node to a file F as info2.
810 static void INLINE print_node_error(FILE *F, const char *err_msg)
815 fprintf (F, " info2: \"%s\"", err_msg);
821 static void dump_node(FILE *F, ir_node *n)
826 if (get_opt_dump_const_local() && is_constlike_node(n))
830 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
832 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
833 bad |= dump_node_opcode(F, n);
834 bad |= dump_node_mode(F, n);
835 bad |= dump_node_typeinfo(F, n);
837 bad |= dump_node_nodeattr(F, n);
838 fprintf(F, " %ld", get_irn_node_nr(n));
840 bad |= dump_node_info(F, n);
841 print_node_error(F, p);
842 dump_node_vcgattr(F, n, NULL, bad);
844 dump_const_node_local(F, n);
846 dump_irn_chi_term(F, n);
847 dump_irn_state(F, n);
851 /** dump the edge to the block this node belongs to */
853 dump_ir_block_edge(FILE *F, ir_node *n) {
854 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
855 if (is_no_Block(n)) {
856 ir_node *block = get_nodes_block(n);
858 if (get_opt_dump_const_local() && is_constlike_node(block)) {
859 dump_const_block_local(F, n);
862 fprintf (F, "edge: { sourcename: \"");
864 fprintf (F, "\" targetname: ");
865 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
866 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
872 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
873 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
874 fprintf (F, INTRA_DATA_EDGE_ATTR);
876 fprintf (F, INTER_DATA_EDGE_ATTR);
880 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
881 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
882 fprintf (F, INTRA_MEM_EDGE_ATTR);
884 fprintf (F, INTER_MEM_EDGE_ATTR);
888 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
891 if (dump_backedge_information_flag && is_backedge(from, to))
892 fprintf (F, BACK_EDGE_ATTR);
894 switch (get_irn_opcode(from)) {
896 fprintf (F, CF_EDGE_ATTR);
898 case iro_Start: break;
901 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
902 fprintf (F, CF_EDGE_ATTR);
903 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
904 fprintf (F, INTER_MEM_EDGE_ATTR);
912 print_data_edge_vcgattr(F, from, to);
917 print_mem_edge_vcgattr(F, from, to);
919 print_data_edge_vcgattr(F, from, to);
923 print_data_edge_vcgattr(F, from, to);
928 print_mem_edge_vcgattr(F, from, to);
930 print_data_edge_vcgattr(F, from, to);
937 print_data_edge_vcgattr(F, from, to);
944 print_mem_edge_vcgattr(F, from, to);
946 print_data_edge_vcgattr(F, from, to);
958 print_data_edge_vcgattr(F, from, to);
961 if (get_irn_modecode(from) == irm_M)
962 fprintf (F, INTER_MEM_EDGE_ATTR);
964 print_data_edge_vcgattr(F, from, to);
971 print_mem_edge_vcgattr(F, from, to);
973 print_data_edge_vcgattr(F, from, to);
976 print_mem_edge_vcgattr(F, from, to);
978 case iro_Tuple: break;
981 switch (get_irn_modecode(from)) {
983 fprintf (F, CF_EDGE_ATTR);
986 fprintf (F, INTER_MEM_EDGE_ATTR);
989 print_data_edge_vcgattr(F, from, to);
994 case iro_Unknown: break;
996 switch (get_irn_modecode(from)) {
998 fprintf (F, INTRA_MEM_EDGE_ATTR);
1001 fprintf (F, CF_EDGE_ATTR);
1004 print_data_edge_vcgattr(F, from, to);
1012 /* dump edges to our inputs */
1014 dump_ir_data_edges(FILE *F, ir_node *n) {
1016 unsigned long 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_irn_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 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)),
1823 dump_file_filter, strlen(dump_file_filter)) != 0) return;
1825 current_ir_graph = irg;
1826 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1827 else suffix1 = "-pure";
1828 f = vcg_open(irg, suffix, suffix1);
1829 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1831 /* walk over the graph */
1832 /* dump_whole_node must be called in post visiting predecessors */
1833 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1835 /* dump the out edges in a separate walk */
1836 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1837 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1842 current_ir_graph = rem;
1847 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1853 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1856 if (get_interprocedural_view()) suffix1 = "-ip";
1858 f = vcg_open(irg, suffix, suffix1);
1859 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1861 construct_block_lists(irg);
1863 for (i = 0; i < get_irp_n_irgs(); i++) {
1864 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1866 dump_graph_from_list(f, get_irp_irg(i));
1874 /** dumps a graph with type information */
1876 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1879 ir_graph *rem = current_ir_graph;
1882 /* if a filter is set, dump only the irg's that match the filter */
1883 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1886 current_ir_graph = irg;
1888 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1889 else suffix1 = "-pure-wtypes";
1890 f = vcg_open(irg,suffix, suffix1);
1891 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1893 /* dump common ir graph */
1894 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1895 /* dump type info */
1896 type_walk_irg(irg, dump_type_info, NULL, f);
1897 inc_irg_visited(get_const_code_irg());
1898 /* dump edges from graph to type info */
1899 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1902 current_ir_graph = rem;
1906 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1911 ir_graph *rem = current_ir_graph;
1913 /* if a filter is set, dump only the irg's that match the filter */
1914 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1917 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1918 else suffix1 = "-wtypes";
1919 f = vcg_open(irg, suffix, suffix1);
1920 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1922 /* dump common blocked ir graph */
1923 construct_block_lists(irg);
1925 for (i = 0; i < get_irp_n_irgs(); i++) {
1926 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1928 dump_graph_from_list(f, get_irp_irg(i));
1933 /* dump type info */
1934 current_ir_graph = irg;
1935 type_walk_irg(irg, dump_type_info, NULL, f);
1936 inc_irg_visited(get_const_code_irg());
1938 /* dump edges from graph to type info */
1939 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1941 current_ir_graph = rem;
1945 /*---------------------------------------------------------------------*/
1946 /* The following routines dump a control flow graph. */
1947 /*---------------------------------------------------------------------*/
1950 dump_block_to_cfg(ir_node *block, void *env) {
1955 if (is_Block(block)) {
1956 /* This is a block. Dump a node for the block. */
1957 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1958 fprintf (F, "\" label: \"");
1959 if (block == get_irg_start_block(get_irn_irg(block)))
1960 fprintf(F, "Start ");
1961 if (block == get_irg_end_block(get_irn_irg(block)))
1964 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1965 PRINT_NODEID(block);
1967 fprintf(F, "info1:\"");
1968 if (dump_dominator_information_flag)
1969 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1971 /* show arity and possible Bad predecessors of the block */
1972 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1973 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1974 ir_node *pred = get_Block_cfgpred(block, i);
1977 fprintf(F, "Bad pred at pos: ");
1978 fprintf(F, "%d ", i);
1985 fprintf (F, "\""); /* closing quote of info */
1987 if ((block == get_irg_start_block(get_irn_irg(block))) ||
1988 (block == get_irg_end_block(get_irn_irg(block))) )
1989 fprintf(F, " color:blue ");
1991 fprintf(F, " color:yellow ");
1994 /* Dump the edges */
1995 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1996 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1997 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1998 fprintf (F, "edge: { sourcename: \"");
1999 PRINT_NODEID(block);
2000 fprintf (F, "\" targetname: \"");
2002 fprintf (F, "\"}\n");
2005 /* Dump dominator edge */
2006 if (dump_dominator_information_flag && get_Block_idom(block)) {
2007 pred = get_Block_idom(block);
2008 fprintf (F, "edge: { sourcename: \"");
2009 PRINT_NODEID(block);
2010 fprintf (F, "\" targetname: \"");
2012 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2018 dump_cfg (ir_graph *irg, const char *suffix)
2021 ir_graph *rem = current_ir_graph;
2022 int ddif = dump_dominator_information_flag;
2023 int ipv = get_interprocedural_view();
2025 /* if a filter is set, dump only the irg's that match the filter */
2026 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2029 current_ir_graph = irg;
2031 f = vcg_open(irg, suffix, "-cfg");
2032 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2035 printf("Warning: dumping cfg not in interprocedural view!\n");
2036 set_interprocedural_view(false);
2039 if (get_irg_dom_state(irg) != dom_consistent)
2040 dump_dominator_information_flag = 0;
2042 /* walk over the blocks in the graph */
2043 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2044 dump_node(f, get_irg_bad(irg));
2046 dump_dominator_information_flag = ddif;
2047 set_interprocedural_view(ipv);
2049 current_ir_graph = rem;
2053 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2054 if (pset_find_ptr(mark_set, n)) return;
2056 pset_insert_ptr(mark_set, n);
2059 int i, start = is_Block(n) ? 0 : -1;
2060 dump_whole_node(n, F);
2061 for (i = start; i < get_irn_arity(n); ++i)
2062 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2065 /* Don't dump edges to nodes further out. These might be edges to
2066 nodes we already dumped, if there is a shorter path to these. */
2070 static int subgraph_counter = 0;
2071 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2074 pset *mark_set = pset_new_ptr(1);
2075 sprintf(buf, "-subg_%03d", subgraph_counter++);
2076 F = vcg_open(get_irn_irg(root), suffix, buf);
2077 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2078 descend_and_dump(F, root, depth, mark_set);
2084 static int weight_overall(int rec, int loop) {
2085 return 2*rec + loop;
2088 static int compute_color (int my, int max) {
2095 /* if small, scale to the full color range. */
2097 my = my * (n_colors/max);
2099 step = 1 + (max / n_colors);
2103 return base_color + n_colors - color;
2106 static int get_entity_color(entity *ent) {
2107 ir_graph *irg = get_entity_irg(ent);
2111 int rec_depth = get_irg_recursion_depth(irg);
2112 int loop_depth = get_irg_loop_depth(irg);
2113 int overall_depth = weight_overall(rec_depth, loop_depth);
2115 int max_rec_depth = irp->max_callgraph_recursion_depth;
2116 int max_loop_depth = irp->max_callgraph_loop_depth;
2117 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2119 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2120 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2121 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2123 return my_overall_color;
2127 void dump_callgraph(const char *suffix) {
2129 int i, n_irgs = get_irp_n_irgs();
2130 int rem = edge_label;
2132 //ident *prefix = new_id_from_str("java/");
2134 F = vcg_open_name("Callgraph", suffix);
2135 dump_vcg_header(F, "Callgraph", NULL);
2137 for (i = 0; i < n_irgs; ++i) {
2138 ir_graph *irg = get_irp_irg(i);
2139 entity *ent = get_irg_entity(irg);
2140 int j, n_callees = get_irg_n_callees(irg);
2142 /* Do not dump runtime system. */
2143 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2145 dump_entity_node(F, ent, get_entity_color(ent));
2146 for (j = 0; j < n_callees; ++j) {
2147 entity *c = get_irg_entity(get_irg_callee(irg, j));
2148 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2149 int be = is_irg_callee_backedge(irg, j);
2152 "label:\"recursion %d\" color: %d" :
2153 "label:\"calls %d\" color: %d";
2154 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2162 /* Dump all irgs in interprocedural view to a single file. */
2163 void dump_all_cg_block_graph(const char *suffix) {
2166 int rem_view = get_interprocedural_view();
2167 set_interprocedural_view(true);
2169 f = vcg_open_name("All_graphs", suffix);
2170 dump_vcg_header(f, "All_graphs", NULL);
2172 /* collect nodes in all irgs reachable in call graph*/
2173 for (i = 0; i < get_irp_n_irgs(); i++)
2174 ird_set_irg_link(get_irp_irg(i), NULL);
2176 cg_walk(clear_link, collect_node, NULL);
2178 /* dump all graphs */
2179 for (i = 0; i < get_irp_n_irgs(); i++) {
2180 current_ir_graph = get_irp_irg(i);
2181 assert(ird_get_irg_link(current_ir_graph));
2182 dump_graph_from_list(f, current_ir_graph);
2183 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2187 set_interprocedural_view(rem_view);
2190 /*---------------------------------------------------------------------*/
2191 /* the following routines dumps type information without any ir nodes. */
2192 /*---------------------------------------------------------------------*/
2195 dump_type_graph (ir_graph *irg, const char *suffix)
2199 rem = current_ir_graph;
2201 /* if a filter is set, dump only the irg's that match the filter */
2202 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2204 current_ir_graph = irg;
2206 f = vcg_open(irg, suffix, "-type");
2207 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2209 /* walk over the blocks in the graph */
2210 type_walk_irg(irg, dump_type_info, NULL, f);
2211 /* The walker for the const code can be called several times for the
2212 same (sub) experssion. So that no nodes are dumped several times
2213 we decrease the visited flag of the corresponding graph after each
2214 walk. So now increase it finally. */
2215 inc_irg_visited(get_const_code_irg());
2218 current_ir_graph = rem;
2222 dump_all_types (const char *suffix)
2224 FILE *f = vcg_open_name("All_types", suffix);
2225 dump_vcg_header(f, "All_types", NULL);
2226 type_walk(dump_type_info, NULL, f);
2227 inc_irg_visited(get_const_code_irg());
2232 dump_class_hierarchy (bool entities, const char *suffix)
2234 FILE *f = vcg_open_name("class_hierarchy", suffix);
2238 dump_vcg_header(f, "class_hierarchy", NULL);
2243 type_walk(dump_class_hierarchy_node, NULL, &env);
2247 /*---------------------------------------------------------------------*/
2248 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2250 /* dump_ir_block_graph */
2252 /* dump_type_graph */
2253 /* dump_ir_graph_w_types */
2254 /*---------------------------------------------------------------------*/
2256 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2257 int i, n_irgs = get_irp_n_irgs();
2258 for (i = 0; i < n_irgs; ++i) {
2259 dmp_grph(get_irp_irg(i), suffix);
2264 /*--------------------------------------------------------------------------------*
2265 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2266 * packed together in one subgraph/box *
2267 *--------------------------------------------------------------------------------*/
2269 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2270 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2272 ir_loop *son = NULL;
2274 /* Dump a new loop node. */
2275 dump_loop_node(F, loop);
2277 /* Dump the loop elements. */
2279 for(i = 0; i < get_loop_n_elements(loop); i++) {
2280 le = get_loop_element(loop, i);
2282 if (get_kind(son) == k_ir_loop) {
2284 /* We are a loop son -> Recurse */
2286 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2287 fprintf(F, "\" }\n");
2288 fprintf (F, "edge: {sourcename: \"");
2290 fprintf (F, "\" targetname: \"");
2292 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2293 loop_node_started = 0;
2295 dump_loop_son_edge(F, loop, son_number++);
2296 dump_loops_standalone(F, son);
2297 } else if (get_kind(son) == k_ir_node) {
2298 /* We are a loop node -> Collect firm nodes */
2300 ir_node *n = le.node;
2303 if (!loop_node_started) {
2304 /* Start a new node which contains all firm nodes of the current loop */
2305 fprintf (F, "node: { title: \"");
2307 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2308 loop_node_started = 1;
2314 bad |= dump_node_opcode(F, n);
2315 bad |= dump_node_mode(F, n);
2316 bad |= dump_node_typeinfo(F, n);
2318 bad |= dump_node_nodeattr(F, n);
2319 fprintf (F, " %ld", get_irn_node_nr(n));
2320 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2321 if (has_backedges(n)) fprintf(F, "\t loop head!");
2322 } else { /* for callgraph loop tree */
2324 assert(get_kind(son) == k_ir_graph);
2326 /* We are a loop node -> Collect firm graphs */
2327 n = (ir_graph *)le.node;
2328 if (!loop_node_started) {
2329 /* Start a new node which contains all firm nodes of the current loop */
2330 fprintf (F, "node: { title: \"");
2332 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2333 loop_node_started = 1;
2338 fprintf (F, " %s", get_irg_dump_name(n));
2339 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2343 if (loop_node_started) {
2344 fprintf(F, "\" }\n");
2345 fprintf (F, "edge: {sourcename: \"");
2347 fprintf (F, "\" targetname: \"");
2349 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2350 loop_node_started = 0;
2354 void dump_loop_tree(ir_graph *irg, const char *suffix)
2357 ir_graph *rem = current_ir_graph;
2358 int el_rem = edge_label;
2361 /* if a filter is set, dump only the irg's that match the filter */
2362 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2365 current_ir_graph = irg;
2367 f = vcg_open(irg, suffix, "-looptree");
2368 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2370 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2374 edge_label = el_rem;
2375 current_ir_graph = rem;
2378 void dump_callgraph_loop_tree(const char *suffix) {
2380 F = vcg_open_name("Callgraph_looptree", suffix);
2381 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2382 dump_loops_standalone(F, irp->outermost_cg_loop);
2387 /*-----------------------------------------------------------------------------*/
2388 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2389 /*-----------------------------------------------------------------------------*/
2391 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2392 int i, son_number = 0, node_number = 0;
2394 if (dump_loop_information_flag) dump_loop_node(F, loop);
2396 for (i = 0; i < get_loop_n_elements(loop); i++) {
2397 loop_element le = get_loop_element(loop, i);
2398 if (*(le.kind) == k_ir_loop) {
2399 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2401 collect_nodeloop(F, le.son, loopnodes);
2403 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2404 eset_insert(loopnodes, le.node);
2409 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2412 for(i = 0; i < get_loop_n_elements(loop); i++) {
2413 loop_element le = get_loop_element(loop, i);
2414 if (*(le.kind) == k_ir_loop) {
2416 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2418 if (is_Block(le.node)) start = 0; else start = -1;
2419 for (j = start; j < get_irn_arity(le.node); j++) {
2420 ir_node *pred = get_irn_n(le.node, j);
2421 if (!eset_contains(loopnodes, pred)) {
2422 eset_insert(extnodes, pred);
2423 if (!is_Block(pred)) {
2424 pred = get_nodes_block(pred);
2425 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2433 void dump_loop(ir_loop *l, const char *suffix) {
2436 eset *loopnodes = eset_create();
2437 eset *extnodes = eset_create();
2440 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2441 F = vcg_open_name (name, suffix);
2442 dump_vcg_header(F, name, NULL);
2444 /* collect all nodes to dump */
2445 collect_nodeloop(F, l, loopnodes);
2446 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2448 /* build block lists */
2449 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2450 set_irn_link(n, NULL);
2451 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2452 set_irn_link(n, NULL);
2453 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2455 b = get_nodes_block(n);
2456 set_irn_link(n, get_irn_link(b));
2459 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2461 b = get_nodes_block(n);
2462 set_irn_link(n, get_irn_link(b));
2466 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2468 fprintf(F, "graph: { title: \"");
2470 fprintf(F, "\" label: \"");
2471 dump_node_opcode(F, b);
2472 fprintf (F, " %ld", get_irn_node_nr(b));
2473 fprintf(F, "\" status:clustered color:yellow\n");
2475 /* dump the blocks edges */
2476 dump_ir_data_edges(F, b);
2478 /* dump the nodes that go into the block */
2479 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2480 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2482 overrule_nodecolor = NULL;
2483 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2486 /* Close the vcg information for the block */
2488 dump_const_node_local(F, b);
2491 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2493 fprintf(F, "graph: { title: \"");
2495 fprintf(F, "\" label: \"");
2496 dump_node_opcode(F, b);
2497 fprintf (F, " %ld", get_irn_node_nr(b));
2498 fprintf(F, "\" status:clustered color:lightblue\n");
2500 /* dump the nodes that go into the block */
2501 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2502 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2504 overrule_nodecolor = NULL;
2505 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2508 /* Close the vcg information for the block */
2510 dump_const_node_local(F, b);
2514 eset_destroy(loopnodes);
2515 eset_destroy(extnodes);