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 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
53 extern void dump_irn_state(FILE *FL, ir_node *n);
54 extern int get_opt_dump_abstvals(void);
55 typedef unsigned long SeqNo;
56 extern 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 set_opt_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) == ir_typeinfo_consistent ||
612 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
613 type *tp = get_irn_typeinfo_type(n);
614 if (tp != firm_none_type)
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 a node label without the enclosing ". */
666 static int dump_node_label(FILE *F, ir_node *n) {
669 bad |= dump_node_opcode(F, n);
670 bad |= dump_node_mode(F, n);
672 bad |= dump_node_typeinfo(F, n);
673 bad |= dump_node_nodeattr(F, n);
674 fprintf(F, "%ld", get_irn_node_nr(n));
681 * Dumps the attributes of a node n into the file F.
682 * Currently this is only the color of a node.
684 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
689 fprintf(F, "color: red");
693 if (dump_node_vcgattr_hook)
694 if (dump_node_vcgattr_hook(F, node, local))
697 n = local ? local : node;
699 switch (get_irn_opcode(n)) {
706 fprintf (F, "color: blue");
709 if (is_Block_dead(n))
710 fprintf (F, "color: lightred");
712 fprintf (F, "color: lightyellow");
715 fprintf (F, "color: green");
721 fprintf (F, "color: yellow");
724 PRINT_DEFAULT_NODE_ATTR;
727 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
732 * Dump the node information of a node n to a file F.
734 static INLINE int dump_node_info(FILE *F, ir_node *n)
736 fprintf (F, " info1: \"");
737 bad = dump_irnode_to_file(F, n);
743 * checks wheater a node is "constant-like", ie can be treated "block-less"
746 bool is_constlike_node(ir_node *n) {
747 ir_op *op = get_irn_op(n);
748 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
752 /** outputs the predecessors of n, that are constants, local. I.e.,
753 generates a copy of the constant predecessors for each node called with. */
754 static void dump_const_node_local(FILE *F, ir_node *n) {
756 if (!get_opt_dump_const_local()) return;
758 /* Use visited flag to avoid outputting nodes twice.
759 initialize it first. */
760 for (i = 0; i < get_irn_arity(n); i++) {
761 ir_node *con = get_irn_n(n, i);
762 if (is_constlike_node(con)) {
763 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
767 for (i = 0; i < get_irn_arity(n); i++) {
768 ir_node *con = get_irn_n(n, i);
769 if (is_constlike_node(con) && irn_not_visited(con)) {
772 mark_irn_visited(con);
773 /* Generate a new name for the node by appending the names of
775 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
776 fprintf(F, " label: \"");
777 bad |= dump_node_label(F, con);
779 bad |= dump_node_info(F, con);
780 dump_node_vcgattr(F, n, con, bad);
786 /** If the block of an edge is a const_like node, dump it local with an edge */
787 static void dump_const_block_local(FILE *F, ir_node *n) {
790 if (!get_opt_dump_const_local()) return;
792 blk = get_nodes_block(n);
793 if (is_constlike_node(blk)) {
796 /* Generate a new name for the node by appending the names of
798 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
799 fprintf(F, "\" label: \"");
800 bad |= dump_node_label(F, blk);
802 bad |= dump_node_info(F, blk);
803 dump_node_vcgattr(F, n, blk, bad);
806 fprintf (F, "edge: { sourcename: \"");
808 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
809 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
814 * prints the error message of a node to a file F as info2.
816 static void INLINE print_node_error(FILE *F, const char *err_msg)
821 fprintf (F, " info2: \"%s\"", err_msg);
827 static void dump_node(FILE *F, ir_node *n)
832 if (get_opt_dump_const_local() && is_constlike_node(n))
836 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
838 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
839 bad |= dump_node_label(F, n);
840 //dump_node_ana_info(F, n);
842 bad |= dump_node_info(F, n);
843 print_node_error(F, p);
844 dump_node_vcgattr(F, n, NULL, bad);
846 dump_const_node_local(F, n);
848 dump_irn_chi_term(F, n);
849 dump_irn_state(F, n);
853 /** dump the edge to the block this node belongs to */
855 dump_ir_block_edge(FILE *F, ir_node *n) {
856 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
857 if (is_no_Block(n)) {
858 ir_node *block = get_nodes_block(n);
860 if (get_opt_dump_const_local() && is_constlike_node(block)) {
861 dump_const_block_local(F, n);
864 fprintf (F, "edge: { sourcename: \"");
866 fprintf (F, "\" targetname: ");
867 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
868 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
874 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
875 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
876 fprintf (F, INTRA_DATA_EDGE_ATTR);
878 fprintf (F, INTER_DATA_EDGE_ATTR);
882 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
883 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
884 fprintf (F, INTRA_MEM_EDGE_ATTR);
886 fprintf (F, INTER_MEM_EDGE_ATTR);
890 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
893 if (dump_backedge_information_flag && is_backedge(from, to))
894 fprintf (F, BACK_EDGE_ATTR);
896 switch (get_irn_opcode(from)) {
898 fprintf (F, CF_EDGE_ATTR);
900 case iro_Start: break;
903 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
904 fprintf (F, CF_EDGE_ATTR);
905 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
906 fprintf (F, INTER_MEM_EDGE_ATTR);
914 print_data_edge_vcgattr(F, from, to);
919 print_mem_edge_vcgattr(F, from, to);
921 print_data_edge_vcgattr(F, from, to);
925 print_data_edge_vcgattr(F, from, to);
930 print_mem_edge_vcgattr(F, from, to);
932 print_data_edge_vcgattr(F, from, to);
939 print_data_edge_vcgattr(F, from, to);
946 print_mem_edge_vcgattr(F, from, to);
948 print_data_edge_vcgattr(F, from, to);
960 print_data_edge_vcgattr(F, from, to);
963 if (get_irn_modecode(from) == irm_M)
964 fprintf (F, INTER_MEM_EDGE_ATTR);
966 print_data_edge_vcgattr(F, from, to);
973 print_mem_edge_vcgattr(F, from, to);
975 print_data_edge_vcgattr(F, from, to);
978 print_mem_edge_vcgattr(F, from, to);
980 case iro_Tuple: break;
983 switch (get_irn_modecode(from)) {
985 fprintf (F, CF_EDGE_ATTR);
988 fprintf (F, INTER_MEM_EDGE_ATTR);
991 print_data_edge_vcgattr(F, from, to);
996 case iro_Unknown: break;
998 switch (get_irn_modecode(from)) {
1000 fprintf (F, INTRA_MEM_EDGE_ATTR);
1003 fprintf (F, CF_EDGE_ATTR);
1006 print_data_edge_vcgattr(F, from, to);
1014 /* dump edges to our inputs */
1016 dump_ir_data_edges(FILE *F, ir_node *n) {
1018 unsigned long visited = get_irn_visited(n);
1020 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1023 for (i = 0; i < get_irn_arity(n); i++) {
1024 ir_node * pred = get_irn_n(n, i);
1027 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1028 continue; /* pred not dumped */
1030 if (dump_backedge_information_flag && is_backedge(n, i))
1031 fprintf (F, "backedge: {sourcename: \"");
1033 fprintf (F, "edge: {sourcename: \"");
1035 fprintf (F, "\" targetname: ");
1036 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1037 PRINT_CONSTID(n, pred);
1039 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1041 fprintf (F, " label: \"%d\" ", i);
1042 print_edge_vcgattr(F, n, i);
1047 /** Dumps a node and its edges but not the block edge
1050 dump_node_wo_blockedge (ir_node *n, void *env) {
1053 dump_ir_data_edges(F, n);
1056 /** Dumps a node and its edges.
1059 dump_whole_node (ir_node *n, void *env) {
1061 dump_node_wo_blockedge(n, env);
1062 if (!node_floats(n)) dump_ir_block_edge(F, n);
1066 dump_const_node(ir_node *n, void *env) {
1067 if (is_Block(n)) return;
1068 dump_node_wo_blockedge(n, env);
1071 /***********************************************************************/
1072 /* the following routines dump the nodes/irgs bracketed to graphs. */
1073 /***********************************************************************/
1075 /** Dumps a constant expression as entity initializer, array bound ...
1077 static void dump_const_expression(FILE *F, ir_node *value) {
1078 ir_graph *rem = current_ir_graph;
1079 int rem_dump_const_local = dump_const_local;
1080 dump_const_local = 0;
1081 current_ir_graph = get_const_code_irg();
1082 irg_walk(value, dump_const_node, NULL, F);
1083 /* Decrease visited flag so that we walk with the same flag for the next
1084 expresssion. This guarantees that we don't dump the same node twice,
1085 as for const expressions cse is performed to save memory. */
1086 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1087 current_ir_graph = rem;
1088 dump_const_local = rem_dump_const_local;
1091 /** Dump a block as graph containing its nodes.
1093 * Expects to find nodes belonging to the block as list in its
1095 * Dumps the edges of all nodes including itself. */
1097 dump_whole_block(FILE *F, ir_node *block) {
1099 assert(is_Block(block));
1101 fprintf(F, "graph: { title: \"");
1102 PRINT_NODEID(block);
1103 fprintf(F, "\" label: \"");
1104 dump_node_label(F, block);
1106 if (get_opt_dump_abstvals())
1107 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1109 fprintf(F, "\" status:clustered color:%s \n",
1110 get_Block_matured(block) ? "yellow" : "red");
1112 /* dump the blocks edges */
1113 dump_ir_data_edges(F, block);
1115 /* dump the nodes that go into the block */
1116 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1118 dump_ir_data_edges(F, node);
1121 /* Close the vcg information for the block */
1123 dump_const_node_local(F, block);
1125 dump_irn_chi_term(F, block);
1130 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1131 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1133 dump_block_graph(FILE *F, ir_graph *irg) {
1135 ir_graph *rem = current_ir_graph;
1136 ir_node **arr = ird_get_irg_link(irg);
1137 current_ir_graph = irg;
1139 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1140 ir_node * node = arr[i];
1141 if (is_Block(node)) {
1142 /* Dumps the block and all the nodes in the block, which are to
1143 be found in Block->link. */
1144 dump_whole_block(F, node);
1146 /* Nodes that are not in a Block. */
1148 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1149 dump_const_block_local(F, node);
1151 dump_ir_data_edges(F, node);
1155 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1156 dump_loop_nodes_into_graph(F, irg);
1158 current_ir_graph = rem;
1161 /** Dumps an irg as a graph.
1162 * If interprocedural view edges can point to nodes out of this graph.
1164 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1166 fprintf(F, "graph: { title: \"");
1168 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1169 get_ent_dump_name(get_irg_entity(irg)));
1171 dump_block_graph(F, irg);
1173 /* Close the vcg information for the irg */
1174 fprintf(F, "}\n\n");
1177 /*******************************************************************/
1178 /* Basic type and entity nodes and edges. */
1179 /*******************************************************************/
1181 /** dumps the edges between nodes and their type or entity attributes. */
1182 static void dump_node2type_edges(ir_node *n, void *env)
1187 switch (get_irn_opcode(n)) {
1189 /* @@@ some consts have an entity */
1192 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1193 || (get_SymConst_kind(n) ==symconst_size))
1195 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1199 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1202 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1205 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1208 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1211 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1219 static int print_type_info(FILE *F, type *tp) {
1222 if (get_type_state(tp) == layout_undefined) {
1223 fprintf(F, "state: layout_undefined\n");
1225 fprintf(F, "state: layout_fixed,\n");
1227 if (get_type_mode(tp))
1228 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1229 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1234 static void print_typespecific_info(FILE *F, type *tp) {
1235 switch (get_type_tpop_code(tp)) {
1238 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1245 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1246 fprintf(F, "params: %d\n", get_method_n_params(tp));
1247 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1255 case tpo_enumeration:
1269 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1270 switch (get_type_tpop_code(tp)) {
1273 if (peculiarity_existent == get_class_peculiarity(tp))
1274 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1276 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1280 fprintf (F, " " TYPE_METH_NODE_ATTR);
1291 case tpo_enumeration:
1304 static int print_type_node(FILE *F, type *tp)
1308 fprintf (F, "node: {title: ");
1310 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1311 fprintf (F, " info1: \"");
1312 bad |= print_type_info(F, tp);
1313 print_typespecific_info(F, tp);
1315 print_typespecific_vcgattr(F, tp);
1321 #define X(a) case a: fprintf(F, #a); break
1322 void dump_entity_node(FILE *F, entity *ent, int color)
1324 fprintf (F, "node: {title: \"");
1325 PRINT_ENTID(ent); fprintf(F, "\"");
1326 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1327 fprintf (F, "label: ");
1328 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1330 fprintf(F, "color: %d", color);
1332 fprintf (F, ENTITY_NODE_ATTR);
1333 fprintf (F, "\n info1: \"");
1335 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1337 fprintf(F, "\"\n}\n");
1341 static void dump_enum_item(FILE *F, type *tp, int pos)
1344 ident *id = get_enumeration_nameid(tp, pos);
1345 tarval *tv = get_enumeration_enum(tp, pos);
1347 tarval_snprintf(buf, sizeof(buf), tv);
1348 fprintf (F, "node: {title: \"");
1349 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1350 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1351 fprintf (F, "label: ");
1352 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1353 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1356 /* dumps a type or entity and it's edges. */
1358 dump_type_info(type_or_ent *tore, void *env) {
1360 int i = 0; /* to shutup gcc */
1362 /* dump this type or entity */
1364 switch (get_kind(tore)) {
1367 entity *ent = (entity *)tore;
1370 dump_entity_node(F, ent, 0);
1372 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1373 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1374 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1375 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1376 if (is_Class_type(get_entity_owner(ent))) {
1377 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1378 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1380 /* attached subgraphs */
1381 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1382 if (is_atomic_entity(ent)) {
1383 value = get_atomic_ent_value(ent);
1385 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1386 /* DDMN(value); $$$ */
1387 dump_const_expression(F, value);
1390 if (is_compound_entity(ent)) {
1391 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1392 value = get_compound_ent_value(ent, i);
1394 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1395 dump_const_expression(F, value);
1396 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1398 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1399 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1400 get_compound_ent_value_member(ent, i), i);
1409 type *tp = (type *)tore;
1410 print_type_node(F, tp);
1411 /* and now the edges */
1412 switch (get_type_tpop_code(tp)) {
1415 for (i=0; i < get_class_n_supertypes(tp); i++)
1416 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1417 for (i=0; i < get_class_n_members(tp); i++)
1418 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1422 for (i=0; i < get_struct_n_members(tp); i++)
1423 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1427 for (i = 0; i < get_method_n_params(tp); i++)
1428 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1429 for (i = 0; i < get_method_n_ress(tp); i++)
1430 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1434 for (i = 0; i < get_union_n_members(tp); i++)
1435 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1439 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1440 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1441 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1442 ir_node *upper = get_array_upper_bound(tp, i);
1443 ir_node *lower = get_array_lower_bound(tp, i);
1444 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1445 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1446 dump_const_expression(F, upper);
1447 dump_const_expression(F, lower);
1451 case tpo_enumeration:
1453 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1454 dump_enum_item(F, tp, i);
1455 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1460 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1468 break; /* case k_type */
1471 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1473 } /* switch kind_or_entity */
1476 typedef struct _h_env {
1481 /** For dumping class hierarchies.
1482 * Dumps a class type node and a superclass edge.
1483 * If env->dump_ent dumps entities of classes and overwrites edges.
1486 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1489 int i = 0; /* to shutup gcc */
1491 /* dump this type or entity */
1492 switch (get_kind(tore)) {
1494 entity *ent = (entity *)tore;
1495 if (get_entity_owner(ent) == get_glob_type()) break;
1496 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1497 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1499 dump_entity_node(F, ent, 0);
1501 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1502 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1503 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1505 } break; /* case k_entity */
1508 type *tp = (type *)tore;
1509 if (tp == get_glob_type()) break;
1510 switch (get_type_tpop_code(tp)) {
1512 print_type_node(F, tp);
1513 /* and now the edges */
1514 for (i=0; i < get_class_n_supertypes(tp); i++)
1516 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1522 break; /* case k_type */
1525 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1527 } /* switch kind_or_entity */
1530 /*******************************************************************/
1531 /* dump analysis information that is expressed in graph terms. */
1532 /*******************************************************************/
1534 /* dump out edges */
1536 dump_out_edge(ir_node *n, void *env) {
1539 for (i = 0; i < get_irn_n_outs(n); i++) {
1540 assert(get_irn_out(n, i));
1541 fprintf (F, "edge: {sourcename: \"");
1543 fprintf (F, "\" targetname: \"");
1544 PRINT_NODEID(get_irn_out(n, i));
1545 fprintf (F, "\" color: red linestyle: dashed");
1551 dump_loop_label(FILE *F, ir_loop *loop) {
1552 fprintf (F, "loop %d, %d sons, %d nodes",
1553 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1556 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1557 fprintf (F, " info1: \"");
1558 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1559 #if DEBUG_libfirm /* GL @@@ debug analyses */
1560 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1566 dump_loop_node(FILE *F, ir_loop *loop) {
1567 fprintf (F, "node: {title: \"");
1569 fprintf (F, "\" label: \"");
1570 dump_loop_label(F, loop);
1572 dump_loop_info(F, loop);
1578 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1580 fprintf (F, "edge: {sourcename: \"");
1582 fprintf (F, "\" targetname: \"");
1583 PRINT_NODEID(get_loop_node(loop, i));
1584 fprintf (F, "\" color: green");
1589 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1591 fprintf (F, "edge: {sourcename: \"");
1593 fprintf (F, "\" targetname: \"");
1594 PRINT_LOOPID(get_loop_son(loop, i));
1595 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1596 get_loop_element_pos(loop, get_loop_son(loop, i)));
1600 void dump_loops(FILE *F, ir_loop *loop) {
1602 /* dump this loop node */
1603 dump_loop_node(F, loop);
1605 /* dump edges to nodes in loop -- only if it is a real loop */
1606 if (get_loop_depth(loop) != 0) {
1607 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1608 dump_loop_node_edge(F, loop, i);
1611 for (i = 0; i < get_loop_n_sons(loop); i++) {
1612 dump_loops(F, get_loop_son(loop, i));
1613 dump_loop_son_edge(F, loop, i);
1618 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1619 ir_graph *rem = current_ir_graph;
1620 current_ir_graph = irg;
1622 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1624 current_ir_graph = rem;
1629 * dumps the VCG header
1631 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1640 if (!orientation) orientation = "bottom_to_top";
1644 "graph: { title: \"ir graph of %s\"\n"
1645 "display_edge_labels: %s\n"
1646 "layoutalgorithm: mindepth\n"
1647 "manhattan_edges: yes\n"
1648 "port_sharing: no\n"
1650 "classname 1: \"intrablock Data\"\n"
1651 "classname 16: \"interblock Data\"\n"
1652 "classname 2: \"Block\"\n"
1653 "classname 13: \"Control Flow\"\n"
1654 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1655 "classname 14: \"intrablock Memory\"\n"
1656 "classname 17: \"interblock Memory\"\n"
1657 "classname 15: \"Dominators\"\n"
1658 "classname 3: \"Entity type\"\n"
1659 "classname 4: \"Entity owner\"\n"
1660 "classname 5: \"Method Param\"\n"
1661 "classname 6: \"Method Res\"\n"
1662 "classname 7: \"Super\"\n"
1663 "classname 8: \"Union\"\n"
1664 "classname 9: \"Points-to\"\n"
1665 "classname 10: \"Array Element Type\"\n"
1666 "classname 11: \"Overwrites\"\n"
1667 "classname 12: \"Member\"\n"
1668 "infoname 1: \"Attribute\"\n"
1669 "infoname 2: \"Verification errors\"\n",
1670 name, label, orientation);
1672 /* don't use all, the range is too whith/black. */
1676 "colorentry 100: 0 0 0\n"
1677 "colorentry 101: 20 0 0\n"
1678 "colorentry 102: 40 0 0\n"
1679 "colorentry 103: 60 0 0\n"
1680 "colorentry 104: 80 0 0\n"
1681 "colorentry 105: 100 0 0\n"
1682 "colorentry 106: 120 0 0\n"
1683 "colorentry 107: 140 0 0\n"
1684 "colorentry 108: 150 0 0\n"
1685 "colorentry 109: 180 0 0\n"
1686 "colorentry 110: 200 0 0\n"
1687 "colorentry 111: 220 0 0\n"
1688 "colorentry 112: 240 0 0\n"
1689 "colorentry 113: 255 0 0\n"
1690 "colorentry 113: 255 20 20\n"
1691 "colorentry 114: 255 40 40\n"
1692 "colorentry 115: 255 60 60\n"
1693 "colorentry 116: 255 80 80\n"
1694 "colorentry 117: 255 100 100\n"
1695 "colorentry 118: 255 120 120\n"
1696 "colorentry 119: 255 140 140\n"
1697 "colorentry 120: 255 150 150\n"
1698 "colorentry 121: 255 180 180\n"
1699 "colorentry 122: 255 200 200\n"
1700 "colorentry 123: 255 220 220\n"
1701 "colorentry 124: 255 240 240\n"
1702 "colorentry 125: 255 250 250\n"
1705 fprintf (F, "\n"); /* a separator */
1711 * @param irg The graph to be dumped
1712 * @param suffix1 first filename suffix
1713 * @param suffix2 second filename suffix
1715 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1717 const char *nm = get_irg_dump_name(irg);
1718 int len = strlen(nm), i, j;
1719 char *fname; /* filename to put the vcg information in */
1721 if (!suffix1) suffix1 = "";
1722 if (!suffix2) suffix2 = "";
1724 /* open file for vcg graph */
1725 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1727 /* strncpy (fname, nm, len); */ /* copy the filename */
1729 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1731 fname[j] = '@'; j++; fname[j] = '1'; j++;
1732 } else if (nm[i] == '@') {
1733 fname[j] = '@'; j++; fname[j] = '2'; j++;
1735 fname[j] = nm[i]; j++;
1739 strcat (fname, suffix1); /* append file suffix */
1740 strcat (fname, suffix2); /* append file suffix */
1741 strcat (fname, ".vcg"); /* append the .vcg suffix */
1743 /* vcg really expect only a <CR> at end of line, so
1744 * the "b"inary mode is what you mean (and even needed for Win32)
1746 F = fopen (fname, "wb"); /* open file for writing */
1748 panic("cannot open %s for writing (%m)", fname); /* not reached */
1758 * @param irg The graph to be dumped
1759 * @param suffix filename suffix
1761 FILE *vcg_open_name (const char *name, const char *suffix) {
1763 char *fname; /* filename to put the vcg information in */
1764 int i, j, len = strlen(name);
1766 if (!suffix) suffix = "";
1768 /** open file for vcg graph */
1769 fname = malloc (len * 2 + 5 + strlen(suffix));
1770 /* strcpy (fname, name);*/ /* copy the filename */
1772 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1773 if (name[i] == '/') {
1774 fname[j] = '@'; j++; fname[j] = '1'; j++;
1775 } else if (name[i] == '@') {
1776 fname[j] = '@'; j++; fname[j] = '2'; j++;
1778 fname[j] = name[i]; j++;
1782 strcat (fname, suffix);
1783 strcat (fname, ".vcg"); /* append the .vcg suffix */
1785 /* vcg really expect only a <CR> at end of line, so
1786 * the "b"inary mode is what you mean (and even needed for Win32)
1788 F = fopen (fname, "wb"); /* open file for writing */
1790 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1798 * Dumps the vcg file footer
1800 static INLINE void dump_vcg_footer (FILE *F) {
1805 * close the vcg file
1807 void vcg_close (FILE *F) {
1808 dump_vcg_footer(F); /* print footer */
1809 fclose (F); /* close vcg file */
1812 /************************************************************************/
1813 /************************************************************************/
1814 /* Routines that dump all or parts of the firm representation to a file */
1815 /************************************************************************/
1816 /************************************************************************/
1818 /************************************************************************/
1819 /* Dump ir graphs, different formats and additional information. */
1820 /************************************************************************/
1822 /** Routine to dump a graph, blocks as conventional nodes. */
1824 dump_ir_graph (ir_graph *irg, const char *suffix )
1829 rem = current_ir_graph;
1831 if (strncmp(get_entity_name(get_irg_entity(irg)),
1832 dump_file_filter, strlen(dump_file_filter)) != 0) return;
1834 current_ir_graph = irg;
1835 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1836 else suffix1 = "-pure";
1837 f = vcg_open(irg, suffix, suffix1);
1838 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1840 /* walk over the graph */
1841 /* dump_whole_node must be called in post visiting predecessors */
1842 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1844 /* dump the out edges in a separate walk */
1845 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1846 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1851 current_ir_graph = rem;
1856 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1862 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1865 if (get_interprocedural_view()) suffix1 = "-ip";
1867 f = vcg_open(irg, suffix, suffix1);
1868 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1870 construct_block_lists(irg);
1872 for (i = 0; i < get_irp_n_irgs(); i++) {
1873 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1875 dump_graph_from_list(f, get_irp_irg(i));
1883 /** dumps a graph with type information */
1885 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1888 ir_graph *rem = current_ir_graph;
1891 /* if a filter is set, dump only the irg's that match the filter */
1892 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1895 current_ir_graph = irg;
1897 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1898 else suffix1 = "-pure-wtypes";
1899 f = vcg_open(irg,suffix, suffix1);
1900 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1902 /* dump common ir graph */
1903 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1904 /* dump type info */
1905 type_walk_irg(irg, dump_type_info, NULL, f);
1906 inc_irg_visited(get_const_code_irg());
1907 /* dump edges from graph to type info */
1908 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1911 current_ir_graph = rem;
1915 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1920 ir_graph *rem = current_ir_graph;
1922 /* if a filter is set, dump only the irg's that match the filter */
1923 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1926 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1927 else suffix1 = "-wtypes";
1928 f = vcg_open(irg, suffix, suffix1);
1929 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1931 /* dump common blocked ir graph */
1932 construct_block_lists(irg);
1934 for (i = 0; i < get_irp_n_irgs(); i++) {
1935 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1937 dump_graph_from_list(f, get_irp_irg(i));
1942 /* dump type info */
1943 current_ir_graph = irg;
1944 type_walk_irg(irg, dump_type_info, NULL, f);
1945 inc_irg_visited(get_const_code_irg());
1947 /* dump edges from graph to type info */
1948 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1950 current_ir_graph = rem;
1954 /*---------------------------------------------------------------------*/
1955 /* The following routines dump a control flow graph. */
1956 /*---------------------------------------------------------------------*/
1959 dump_block_to_cfg(ir_node *block, void *env) {
1964 if (is_Block(block)) {
1965 /* This is a block. Dump a node for the block. */
1966 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1967 fprintf (F, "\" label: \"");
1968 if (block == get_irg_start_block(get_irn_irg(block)))
1969 fprintf(F, "Start ");
1970 if (block == get_irg_end_block(get_irn_irg(block)))
1973 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1974 PRINT_NODEID(block);
1976 fprintf(F, "info1:\"");
1977 if (dump_dominator_information_flag) {
1978 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1979 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
1980 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
1983 /* show arity and possible Bad predecessors of the block */
1984 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1985 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1986 ir_node *pred = get_Block_cfgpred(block, i);
1989 fprintf(F, "Bad pred at pos: ");
1990 fprintf(F, "%d ", i);
1997 fprintf (F, "\""); /* closing quote of info */
1999 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2000 (block == get_irg_end_block(get_irn_irg(block))) )
2001 fprintf(F, " color:blue ");
2003 fprintf(F, " color:yellow ");
2006 /* Dump the edges */
2007 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2008 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2009 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2010 fprintf (F, "edge: { sourcename: \"");
2011 PRINT_NODEID(block);
2012 fprintf (F, "\" targetname: \"");
2014 fprintf (F, "\"}\n");
2017 /* Dump dominator edge */
2018 if (dump_dominator_information_flag && get_Block_idom(block)) {
2019 pred = get_Block_idom(block);
2020 fprintf (F, "edge: { sourcename: \"");
2021 PRINT_NODEID(block);
2022 fprintf (F, "\" targetname: \"");
2024 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2030 dump_cfg (ir_graph *irg, const char *suffix)
2033 ir_graph *rem = current_ir_graph;
2034 int ddif = dump_dominator_information_flag;
2035 int ipv = get_interprocedural_view();
2037 /* if a filter is set, dump only the irg's that match the filter */
2038 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2041 current_ir_graph = irg;
2043 f = vcg_open(irg, suffix, "-cfg");
2044 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2047 printf("Warning: dumping cfg not in interprocedural view!\n");
2048 set_interprocedural_view(false);
2051 if (get_irg_dom_state(irg) != dom_consistent)
2052 dump_dominator_information_flag = 0;
2054 /* walk over the blocks in the graph */
2055 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2056 dump_node(f, get_irg_bad(irg));
2058 dump_dominator_information_flag = ddif;
2059 set_interprocedural_view(ipv);
2061 current_ir_graph = rem;
2065 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2066 if (pset_find_ptr(mark_set, n)) return;
2068 pset_insert_ptr(mark_set, n);
2071 int i, start = is_Block(n) ? 0 : -1;
2072 dump_whole_node(n, F);
2073 for (i = start; i < get_irn_arity(n); ++i)
2074 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2077 /* Don't dump edges to nodes further out. These might be edges to
2078 nodes we already dumped, if there is a shorter path to these. */
2082 static int subgraph_counter = 0;
2083 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2086 pset *mark_set = pset_new_ptr(1);
2087 sprintf(buf, "-subg_%03d", subgraph_counter++);
2088 F = vcg_open(get_irn_irg(root), suffix, buf);
2089 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2090 descend_and_dump(F, root, depth, mark_set);
2096 static int weight_overall(int rec, int loop) {
2097 return 2*rec + loop;
2100 static int compute_color (int my, int max) {
2107 /* if small, scale to the full color range. */
2109 my = my * (n_colors/max);
2111 step = 1 + (max / n_colors);
2115 return base_color + n_colors - color;
2118 static int get_entity_color(entity *ent) {
2119 ir_graph *irg = get_entity_irg(ent);
2123 int rec_depth = get_irg_recursion_depth(irg);
2124 int loop_depth = get_irg_loop_depth(irg);
2125 int overall_depth = weight_overall(rec_depth, loop_depth);
2127 int max_rec_depth = irp->max_callgraph_recursion_depth;
2128 int max_loop_depth = irp->max_callgraph_loop_depth;
2129 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2131 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2132 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2133 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2135 return my_overall_color;
2139 void dump_callgraph(const char *suffix) {
2141 int i, n_irgs = get_irp_n_irgs();
2142 int rem = edge_label;
2144 //ident *prefix = new_id_from_str("java/");
2146 F = vcg_open_name("Callgraph", suffix);
2147 dump_vcg_header(F, "Callgraph", NULL);
2149 for (i = 0; i < n_irgs; ++i) {
2150 ir_graph *irg = get_irp_irg(i);
2151 entity *ent = get_irg_entity(irg);
2152 int j, n_callees = get_irg_n_callees(irg);
2154 /* Do not dump runtime system. */
2155 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2157 dump_entity_node(F, ent, get_entity_color(ent));
2158 for (j = 0; j < n_callees; ++j) {
2159 entity *c = get_irg_entity(get_irg_callee(irg, j));
2160 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2161 int be = is_irg_callee_backedge(irg, j);
2164 "label:\"recursion %d\" color: %d" :
2165 "label:\"calls %d\" color: %d";
2166 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2174 /* Dump all irgs in interprocedural view to a single file. */
2175 void dump_all_cg_block_graph(const char *suffix) {
2178 int rem_view = get_interprocedural_view();
2179 set_interprocedural_view(true);
2181 f = vcg_open_name("All_graphs", suffix);
2182 dump_vcg_header(f, "All_graphs", NULL);
2184 /* collect nodes in all irgs reachable in call graph*/
2185 for (i = 0; i < get_irp_n_irgs(); i++)
2186 ird_set_irg_link(get_irp_irg(i), NULL);
2188 cg_walk(clear_link, collect_node, NULL);
2190 /* dump all graphs */
2191 for (i = 0; i < get_irp_n_irgs(); i++) {
2192 current_ir_graph = get_irp_irg(i);
2193 assert(ird_get_irg_link(current_ir_graph));
2194 dump_graph_from_list(f, current_ir_graph);
2195 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2199 set_interprocedural_view(rem_view);
2202 /*---------------------------------------------------------------------*/
2203 /* the following routines dumps type information without any ir nodes. */
2204 /*---------------------------------------------------------------------*/
2207 dump_type_graph (ir_graph *irg, const char *suffix)
2211 rem = current_ir_graph;
2213 /* if a filter is set, dump only the irg's that match the filter */
2214 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2216 current_ir_graph = irg;
2218 f = vcg_open(irg, suffix, "-type");
2219 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2221 /* walk over the blocks in the graph */
2222 type_walk_irg(irg, dump_type_info, NULL, f);
2223 /* The walker for the const code can be called several times for the
2224 same (sub) expression. So that no nodes are dumped several times
2225 we decrease the visited flag of the corresponding graph after each
2226 walk. So now increase it finally. */
2227 inc_irg_visited(get_const_code_irg());
2230 current_ir_graph = rem;
2234 dump_all_types (const char *suffix)
2236 FILE *f = vcg_open_name("All_types", suffix);
2237 dump_vcg_header(f, "All_types", NULL);
2238 type_walk(dump_type_info, NULL, f);
2239 inc_irg_visited(get_const_code_irg());
2244 dump_class_hierarchy (bool entities, const char *suffix)
2246 FILE *f = vcg_open_name("class_hierarchy", suffix);
2250 dump_vcg_header(f, "class_hierarchy", NULL);
2255 type_walk(dump_class_hierarchy_node, NULL, &env);
2259 /*---------------------------------------------------------------------*/
2260 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2262 /* dump_ir_block_graph */
2264 /* dump_type_graph */
2265 /* dump_ir_graph_w_types */
2266 /*---------------------------------------------------------------------*/
2268 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2269 int i, n_irgs = get_irp_n_irgs();
2270 for (i = 0; i < n_irgs; ++i) {
2271 dmp_grph(get_irp_irg(i), suffix);
2276 /*--------------------------------------------------------------------------------*
2277 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2278 * packed together in one subgraph/box *
2279 *--------------------------------------------------------------------------------*/
2281 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2282 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2284 ir_loop *son = NULL;
2286 /* Dump a new loop node. */
2287 dump_loop_node(F, loop);
2289 /* Dump the loop elements. */
2291 for(i = 0; i < get_loop_n_elements(loop); i++) {
2292 le = get_loop_element(loop, i);
2294 if (get_kind(son) == k_ir_loop) {
2296 /* We are a loop son -> Recurse */
2298 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2299 fprintf(F, "\" }\n");
2300 fprintf (F, "edge: {sourcename: \"");
2302 fprintf (F, "\" targetname: \"");
2304 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2305 loop_node_started = 0;
2307 dump_loop_son_edge(F, loop, son_number++);
2308 dump_loops_standalone(F, son);
2309 } else if (get_kind(son) == k_ir_node) {
2310 /* We are a loop node -> Collect firm nodes */
2312 ir_node *n = le.node;
2315 if (!loop_node_started) {
2316 /* Start a new node which contains all firm nodes of the current loop */
2317 fprintf (F, "node: { title: \"");
2319 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2320 loop_node_started = 1;
2326 bad |= dump_node_label(F, n);
2327 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2328 if (has_backedges(n)) fprintf(F, "\t loop head!");
2329 } else { /* for callgraph loop tree */
2331 assert(get_kind(son) == k_ir_graph);
2333 /* We are a loop node -> Collect firm graphs */
2334 n = (ir_graph *)le.node;
2335 if (!loop_node_started) {
2336 /* Start a new node which contains all firm nodes of the current loop */
2337 fprintf (F, "node: { title: \"");
2339 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2340 loop_node_started = 1;
2345 fprintf (F, " %s", get_irg_dump_name(n));
2346 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2350 if (loop_node_started) {
2351 fprintf(F, "\" }\n");
2352 fprintf (F, "edge: {sourcename: \"");
2354 fprintf (F, "\" targetname: \"");
2356 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2357 loop_node_started = 0;
2361 void dump_loop_tree(ir_graph *irg, const char *suffix)
2364 ir_graph *rem = current_ir_graph;
2365 int el_rem = edge_label;
2368 /* if a filter is set, dump only the irg's that match the filter */
2369 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2372 current_ir_graph = irg;
2374 f = vcg_open(irg, suffix, "-looptree");
2375 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2377 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2381 edge_label = el_rem;
2382 current_ir_graph = rem;
2385 void dump_callgraph_loop_tree(const char *suffix) {
2387 F = vcg_open_name("Callgraph_looptree", suffix);
2388 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2389 dump_loops_standalone(F, irp->outermost_cg_loop);
2394 /*-----------------------------------------------------------------------------*/
2395 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2396 /*-----------------------------------------------------------------------------*/
2398 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2399 int i, son_number = 0, node_number = 0;
2401 if (dump_loop_information_flag) dump_loop_node(F, loop);
2403 for (i = 0; i < get_loop_n_elements(loop); i++) {
2404 loop_element le = get_loop_element(loop, i);
2405 if (*(le.kind) == k_ir_loop) {
2406 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2408 collect_nodeloop(F, le.son, loopnodes);
2410 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2411 eset_insert(loopnodes, le.node);
2416 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2419 for(i = 0; i < get_loop_n_elements(loop); i++) {
2420 loop_element le = get_loop_element(loop, i);
2421 if (*(le.kind) == k_ir_loop) {
2423 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2425 if (is_Block(le.node)) start = 0; else start = -1;
2426 for (j = start; j < get_irn_arity(le.node); j++) {
2427 ir_node *pred = get_irn_n(le.node, j);
2428 if (!eset_contains(loopnodes, pred)) {
2429 eset_insert(extnodes, pred);
2430 if (!is_Block(pred)) {
2431 pred = get_nodes_block(pred);
2432 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2440 void dump_loop(ir_loop *l, const char *suffix) {
2443 eset *loopnodes = eset_create();
2444 eset *extnodes = eset_create();
2447 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2448 F = vcg_open_name (name, suffix);
2449 dump_vcg_header(F, name, NULL);
2451 /* collect all nodes to dump */
2452 collect_nodeloop(F, l, loopnodes);
2453 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2455 /* build block lists */
2456 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2457 set_irn_link(n, NULL);
2458 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2459 set_irn_link(n, NULL);
2460 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2462 b = get_nodes_block(n);
2463 set_irn_link(n, get_irn_link(b));
2466 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2468 b = get_nodes_block(n);
2469 set_irn_link(n, get_irn_link(b));
2473 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2475 fprintf(F, "graph: { title: \"");
2477 fprintf(F, "\" label: \"");
2478 dump_node_opcode(F, b);
2479 fprintf (F, " %ld", get_irn_node_nr(b));
2480 fprintf(F, "\" status:clustered color:yellow\n");
2482 /* dump the blocks edges */
2483 dump_ir_data_edges(F, b);
2485 /* dump the nodes that go into the block */
2486 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2487 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2489 overrule_nodecolor = NULL;
2490 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2493 /* Close the vcg information for the block */
2495 dump_const_node_local(F, b);
2498 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2500 fprintf(F, "graph: { title: \"");
2502 fprintf(F, "\" label: \"");
2503 dump_node_opcode(F, b);
2504 fprintf (F, " %ld", get_irn_node_nr(b));
2505 fprintf(F, "\" status:clustered color:lightblue\n");
2507 /* dump the nodes that go into the block */
2508 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2509 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2511 overrule_nodecolor = NULL;
2512 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2515 /* Close the vcg information for the block */
2517 dump_const_node_local(F, b);
2521 eset_destroy(loopnodes);
2522 eset_destroy(extnodes);