3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
51 void dump_chi_term(FILE *FL, ir_node *n);
52 void dump_state(FILE *FL, ir_node *n);
53 int get_opt_dump_abstvals(void);
54 typedef unsigned long SeqNo;
55 SeqNo get_Block_seqno(ir_node *n);
58 /* basis for a color range for vcg */
59 static int n_colors = 0;
60 static int base_color = 0;
62 #define ERROR_TXT "<ERROR>"
65 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
66 * in the later case, sets bad
68 const char *get_mode_name_ex(ir_mode *mode, int *bad)
71 return get_mode_name(mode);
77 * returns the name of a type or <ERROR> if mode is NOT a mode object.
78 * in the later case, sets bad
80 const char *get_type_name_ex(type *tp, int *bad)
83 return get_type_name(tp);
89 * prints the edge from a type S to a type T with additional info fmt, ...
92 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
97 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
98 fprintf(F, " targetname: "); PRINT_TYPEID(T);
105 * prints the edge from a type T to an entity E with additional info fmt, ...
108 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
113 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
114 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
115 vfprintf(F, fmt, ap);
121 * prints the edge from an entity E to an entity T with additional info fmt, ...
124 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
130 fprintf(F, "backedge: { sourcename: \"");
132 fprintf(F, "edge: { sourcename: \"");
134 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
135 vfprintf(F, fmt, ap);
141 * prints the edge from an entity E to a type T with additional info fmt, ...
144 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
149 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
150 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
151 vfprintf(F, fmt, ap);
157 * prints the edge from a node N to a type T with additional info fmt, ...
160 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
165 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
166 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
167 vfprintf(F, fmt, ap);
173 * prints the edge from a node N to an entity E with additional info fmt, ...
176 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
181 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
182 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
184 vfprintf(F, fmt, ap);
190 * prints the edge from an entity E to a node N with additional info fmt, ...
193 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
198 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
199 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
200 vfprintf(F, fmt, ap);
206 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
209 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
214 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
215 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
216 vfprintf(F, fmt, ap);
221 /*-----------------------------------------------------------------*/
222 /* global and ahead declarations */
223 /*-----------------------------------------------------------------*/
225 static void dump_whole_node(ir_node *n, void *env);
226 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
228 /*-----------------------------------------------------------------*/
229 /* Helper functions. */
230 /*-----------------------------------------------------------------*/
233 * This map is used as a private link attr to be able to call dumper
234 * anywhere without destroying link fields.
236 static pmap *irdump_link_map = NULL;
238 /** Creates the link attribut map. */
239 static void init_irdump(void) {
240 /* We need a new, empty map. */
241 if (irdump_link_map) pmap_destroy(irdump_link_map);
242 irdump_link_map = pmap_create();
246 * Returns the private link field.
248 static void *ird_get_irn_link(ir_node *n) {
250 if (!irdump_link_map) return NULL;
252 if (pmap_contains(irdump_link_map, (void *)n))
253 res = pmap_get(irdump_link_map, (void *)n);
258 * Sets the private link field.
260 static void ird_set_irn_link(ir_node *n, void *x) {
261 if (!irdump_link_map) init_irdump();
262 pmap_insert(irdump_link_map, (void *)n, x);
266 * Gets the private link field of an irg.
268 static void *ird_get_irg_link(ir_graph *irg) {
270 if (!irdump_link_map) return NULL;
272 if (pmap_contains(irdump_link_map, (void *)irg))
273 res = pmap_get(irdump_link_map, (void *)irg);
278 * Sets the private link field of an irg.
280 static void ird_set_irg_link(ir_graph *irg, void *x) {
281 if (!irdump_link_map) init_irdump();
282 pmap_insert(irdump_link_map, (void *)irg, x);
286 * Walker, clears tzhe private link field
288 static void clear_link(ir_node * node, void * env) {
289 ird_set_irn_link(node, NULL);
293 * If the entity has a ld_name, returns it, else returns the name of the entity.
295 const char *get_ent_dump_name(entity *ent) {
297 return "<NULL entity>";
298 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
299 if (ent->ld_name) return get_id_str(ent->ld_name);
300 return get_id_str(ent->name);
303 /* Returns the name of an IRG. */
304 const char *get_irg_dump_name(ir_graph *irg) {
305 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
306 entity *ent = get_irg_entity(irg);
307 return get_ent_dump_name(ent);
311 * Returns non-zero if a node is in floating state.
313 static int node_floats(ir_node *n) {
314 return ((get_irn_pinned(n) == op_pin_state_floats) &&
315 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
319 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
321 static void collect_node(ir_node * node, void *env) {
324 || get_irn_op(node) == op_Bad
325 || get_irn_op(node) == op_Unknown
326 || get_irn_op(node) == op_NoMem) {
327 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
328 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
329 ARR_APP1(ir_node *, arr, node);
330 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
332 ir_node * block = get_nodes_block(node);
335 /* this node is in a Bad block, so we must place it into the graph's list */
336 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
337 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
338 ARR_APP1(ir_node *, arr, node);
339 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
342 ird_set_irn_link(node, ird_get_irn_link(block));
343 ird_set_irn_link(block, node);
348 /** Construct lists to walk ir block-wise.
350 * Collects all blocks, nodes not op_pin_state_pinned,
351 * Bad, NoMem and Unknown into a flexible array in link field of
352 * irg they belong to. Sets the irg link field to NULL in all
353 * graphs not visited.
354 * Free the list with DEL_ARR_F().
356 static ir_node ** construct_block_lists(ir_graph *irg) {
357 int i, rem_view = get_interprocedural_view();
358 ir_graph *rem = current_ir_graph;
359 current_ir_graph = irg;
361 for (i = 0; i < get_irp_n_irgs(); i++)
362 ird_set_irg_link(get_irp_irg(i), NULL);
364 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
366 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
367 set_interprocedural_view(false);
369 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
370 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
371 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
372 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
374 set_interprocedural_view(rem_view);
376 current_ir_graph = rem;
377 return ird_get_irg_link(irg);
380 /*******************************************************************/
381 /* flags to steer output */
382 /*******************************************************************/
384 /** Dump only irgs with names start with this string */
385 const char *dump_file_filter = "";
387 /** A compiler option to turn off edge labels */
388 static int edge_label = 1;
389 /** A compiler option to turn off dumping values of constant entities */
390 static int const_entities = 1;
391 /** A compiler option to dump the keep alive edges */
392 static int dump_keepalive = 0;
393 /** Compiler options to dump analysis information in dump_ir_graph */
394 int dump_out_edge_flag = 0;
395 int dump_dominator_information_flag = 0;
396 int dump_loop_information_flag = 0;
397 int dump_backedge_information_flag = 1;
398 int dump_const_local = 0;
399 bool opt_dump_analysed_type_info = 1;
400 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
402 static const char *overrule_nodecolor = NULL;
404 /** The vcg attribute hook. */
405 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
408 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
410 dump_node_vcgattr_hook = hook;
413 INLINE bool get_opt_dump_const_local(void) {
414 if (!dump_out_edge_flag && !dump_loop_information_flag)
415 return dump_const_local;
420 void only_dump_method_with_name(ident *name) {
421 dump_file_filter = get_id_str(name);
425 /* To turn off display of edge labels. Edge labels offen cause xvcg to
426 abort with a segmentation fault. */
427 void turn_off_edge_labels(void) {
431 void dump_consts_local(bool b) {
432 dump_const_local = b;
435 void turn_off_constant_entity_values(void) {
439 void dump_keepalive_edges(bool b) {
443 bool get_opt_dump_keepalive_edges(void) {
444 return dump_keepalive;
447 void dump_out_edges(void) {
448 dump_out_edge_flag = 1;
451 void dump_dominator_information(void) {
452 dump_dominator_information_flag = 1;
455 void dump_loop_information(void) {
456 dump_loop_information_flag = 1;
459 void dont_dump_loop_information(void) {
460 dump_loop_information_flag = 0;
463 void dump_backedge_information(bool b) {
464 dump_backedge_information_flag = b;
467 /* Dump the information of type field specified in ana/irtypeinfo.h.
468 * If the flag is set, the type name is output in [] in the node label,
469 * else it is output as info.
471 void dump_analysed_type_info(bool b) {
472 opt_dump_analysed_type_info = b;
475 void dump_pointer_values_to_info(bool b) {
476 opt_dump_pointer_values_to_info = b;
479 /*-----------------------------------------------------------------*/
480 /* Routines to dump information about a single ir node. */
481 /*-----------------------------------------------------------------*/
484 * dump the name of a node n to the File F.
487 dump_node_opcode(FILE *F, ir_node *n)
491 switch(get_irn_opcode(n)) {
496 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
497 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
502 if (get_SymConst_kind(n) == symconst_addr_name) {
503 /* don't use get_SymConst_ptr_info as it mangles the name. */
504 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
505 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
506 assert(get_SymConst_entity(n));
507 assert(is_entity(get_SymConst_entity(n)));
508 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
510 assert(get_kind(get_SymConst_type(n)) == k_type);
511 assert(get_type_ident(get_SymConst_type(n)));
512 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
513 if (get_SymConst_kind(n) == symconst_type_tag)
521 if (!get_interprocedural_view())
528 ir_node *pred = get_Proj_pred(n);
530 if (get_irn_opcode(pred) == iro_Cond
531 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
532 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
533 fprintf (F, "defProj");
535 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
536 * fprintf (F, "Arg");
545 if (get_interprocedural_view()) {
546 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
551 case iro_CallBegin: {
552 ir_node *addr = get_CallBegin_ptr(n);
554 if (get_irn_op(addr) == op_Sel)
555 ent = get_Sel_entity(addr);
556 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
557 ent = get_SymConst_entity(addr);
558 fprintf (F, "%s", get_irn_opname(n));
559 if (ent) fprintf (F, " %s", get_entity_name(ent));
563 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
568 fprintf (F, "%s", get_irn_opname(n));
576 * Dump the mode of a node n to a file F.
577 * Ignore modes that are "always known".
580 dump_node_mode(FILE *F, ir_node *n)
583 opcode iro = get_irn_opcode(n);
596 ir_mode *mode = get_irn_mode(n);
598 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
599 (mode != mode_T || iro == iro_Proj))
600 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
608 * Dump the tpe of a node n to a file F if it's known.
610 static int dump_node_typeinfo(FILE *F, ir_node *n) {
613 if (opt_dump_analysed_type_info) {
614 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
615 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
616 type *tp = get_irn_typeinfo_type(n);
618 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
627 * Dump addinional node attributes of some nodes to a file F.
630 dump_node_nodeattr(FILE *F, ir_node *n)
634 switch (get_irn_opcode(n)) {
636 if (false && get_interprocedural_view()) {
637 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
641 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
642 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
644 fprintf (F, "%ld", get_Proj_proj(n));
648 fprintf (F, "%ld", get_Filter_proj(n));
651 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
654 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
657 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
668 * dumps the attributes of a node n into the file F.
669 * Currently this is only the color of a node.
671 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
674 fprintf(F, "color: red");
678 if (dump_node_vcgattr_hook)
679 if (dump_node_vcgattr_hook(F, n))
682 switch (get_irn_opcode(n)) {
689 fprintf (F, "color: blue");
692 if (is_Block_dead(n))
693 fprintf (F, "color: lightred");
695 fprintf (F, "color: lightyellow");
698 fprintf (F, "color: green");
704 fprintf (F, "color: yellow");
707 PRINT_DEFAULT_NODE_ATTR;
710 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
715 * Dump the node information of a node n to a file F.
717 static INLINE int dump_node_info(FILE *F, ir_node *n)
719 fprintf (F, " info1: \"");
720 bad = dump_irnode_to_file(F, n);
726 * checks wheater a node is "constant-like", ie can be treated "block-less"
729 bool is_constlike_node(ir_node *n) {
730 ir_op *op = get_irn_op(n);
731 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
735 /** outputs the predecessors of n, that are constants, local. I.e.,
736 generates a copy of the constant predecessors for each node called with. */
737 static void dump_const_node_local(FILE *F, ir_node *n) {
739 if (!get_opt_dump_const_local()) return;
741 /* Use visited flag to avoid outputting nodes twice.
742 initialize it first. */
743 for (i = 0; i < get_irn_arity(n); i++) {
744 ir_node *con = get_irn_n(n, i);
745 if (is_constlike_node(con)) {
746 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
750 for (i = 0; i < get_irn_arity(n); i++) {
751 ir_node *con = get_irn_n(n, i);
752 if (is_constlike_node(con) && irn_not_visited(con)) {
755 mark_irn_visited(con);
756 /* Generate a new name for the node by appending the names of
758 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
759 fprintf(F, " label: \"");
760 bad |= dump_node_opcode(F, con);
761 bad |= dump_node_mode(F, con);
762 bad |= dump_node_typeinfo(F, con);
764 bad |= dump_node_nodeattr(F, con);
765 fprintf(F, " %ld", get_irn_node_nr(con));
767 bad |= dump_node_info(F, con);
768 dump_node_vcgattr(F, con, bad);
774 /** If the block of an edge is a const_like node, dump it local with an edge */
775 static void dump_const_block_local(FILE *F, ir_node *n) {
776 if (!get_opt_dump_const_local()) return;
778 ir_node *blk = get_nodes_block(n);
779 if (is_constlike_node(blk)) {
782 /* Generate a new name for the node by appending the names of
784 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
785 fprintf(F, "\" label: \"");
786 bad |= dump_node_opcode(F, blk);
787 bad |= dump_node_mode(F, blk);
788 bad |= dump_node_typeinfo(F, blk);
790 bad |= dump_node_nodeattr(F, blk);
791 fprintf(F, " %ld", get_irn_node_nr(blk));
793 bad |= dump_node_info(F, blk);
794 dump_node_vcgattr(F, blk, bad);
797 fprintf (F, "edge: { sourcename: \"");
799 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
800 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
805 * prints the error message of a node to a file F as info2.
807 static void INLINE print_node_error(FILE *F, const char *err_msg)
812 fprintf (F, " info2: \"%s\"", err_msg);
818 static void dump_node(FILE *F, ir_node *n)
823 if (get_opt_dump_const_local() && is_constlike_node(n))
827 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
829 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
830 bad |= dump_node_opcode(F, n);
831 bad |= dump_node_mode(F, n);
832 bad |= dump_node_typeinfo(F, n);
834 bad |= dump_node_nodeattr(F, n);
835 fprintf(F, " %ld", get_irn_node_nr(n));
837 bad |= dump_node_info(F, n);
838 print_node_error(F, p);
839 dump_node_vcgattr(F, n, bad);
841 dump_const_node_local(F, n);
848 /** dump the edge to the block this node belongs to */
850 dump_ir_block_edge(FILE *F, ir_node *n) {
851 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
852 if (is_no_Block(n)) {
853 ir_node *block = get_nodes_block(n);
855 if (get_opt_dump_const_local() && is_constlike_node(block)) {
856 dump_const_block_local(F, n);
859 fprintf (F, "edge: { sourcename: \"");
861 fprintf (F, "\" targetname: ");
862 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
863 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
869 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
870 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
871 fprintf (F, INTRA_DATA_EDGE_ATTR);
873 fprintf (F, INTER_DATA_EDGE_ATTR);
877 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
878 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
879 fprintf (F, INTRA_MEM_EDGE_ATTR);
881 fprintf (F, INTER_MEM_EDGE_ATTR);
885 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
888 if (dump_backedge_information_flag && is_backedge(from, to))
889 fprintf (F, BACK_EDGE_ATTR);
891 switch (get_irn_opcode(from)) {
893 fprintf (F, CF_EDGE_ATTR);
895 case iro_Start: break;
898 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
899 fprintf (F, CF_EDGE_ATTR);
900 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
901 fprintf (F, INTER_MEM_EDGE_ATTR);
909 print_data_edge_vcgattr(F, from, to);
914 print_mem_edge_vcgattr(F, from, to);
916 print_data_edge_vcgattr(F, from, to);
920 print_data_edge_vcgattr(F, from, to);
925 print_mem_edge_vcgattr(F, from, to);
927 print_data_edge_vcgattr(F, from, to);
934 print_data_edge_vcgattr(F, from, to);
941 print_mem_edge_vcgattr(F, from, to);
943 print_data_edge_vcgattr(F, from, to);
955 print_data_edge_vcgattr(F, from, to);
958 if (get_irn_modecode(from) == irm_M)
959 fprintf (F, INTER_MEM_EDGE_ATTR);
961 print_data_edge_vcgattr(F, from, to);
968 print_mem_edge_vcgattr(F, from, to);
970 print_data_edge_vcgattr(F, from, to);
973 print_mem_edge_vcgattr(F, from, to);
975 case iro_Tuple: break;
978 switch (get_irn_modecode(from)) {
980 fprintf (F, CF_EDGE_ATTR);
983 fprintf (F, INTER_MEM_EDGE_ATTR);
986 print_data_edge_vcgattr(F, from, to);
991 case iro_Unknown: break;
993 switch (get_irn_modecode(from)) {
995 fprintf (F, INTRA_MEM_EDGE_ATTR);
998 fprintf (F, CF_EDGE_ATTR);
1001 print_data_edge_vcgattr(F, from, to);
1009 /* dump edges to our inputs */
1011 dump_ir_data_edges(FILE *F, ir_node *n) {
1012 int i, visited = get_irn_visited(n);
1014 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1017 for (i = 0; i < get_irn_arity(n); i++) {
1018 ir_node * pred = get_irn_n(n, i);
1021 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1022 continue; /* pred not dumped */
1024 if (dump_backedge_information_flag && is_backedge(n, i))
1025 fprintf (F, "backedge: {sourcename: \"");
1027 fprintf (F, "edge: {sourcename: \"");
1029 fprintf (F, "\" targetname: ");
1030 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1031 PRINT_CONSTID(n, pred);
1033 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1035 fprintf (F, " label: \"%d\" ", i);
1036 print_edge_vcgattr(F, n, i);
1041 /** Dumps a node and its edges but not the block edge
1044 dump_node_wo_blockedge (ir_node *n, void *env) {
1047 dump_ir_data_edges(F, n);
1050 /** Dumps a node and its edges.
1053 dump_whole_node (ir_node *n, void *env) {
1055 dump_node_wo_blockedge(n, env);
1056 if (!node_floats(n)) dump_ir_block_edge(F, n);
1060 dump_const_node(ir_node *n, void *env) {
1061 if (is_Block(n)) return;
1062 dump_node_wo_blockedge(n, env);
1065 /***********************************************************************/
1066 /* the following routines dump the nodes/irgs bracketed to graphs. */
1067 /***********************************************************************/
1069 /** Dumps a constant expression as entity initializer, array bound ...
1071 static void dump_const_expression(FILE *F, ir_node *value) {
1072 ir_graph *rem = current_ir_graph;
1073 int rem_dump_const_local = dump_const_local;
1074 dump_const_local = 0;
1075 current_ir_graph = get_const_code_irg();
1076 irg_walk(value, dump_const_node, NULL, F);
1077 /* Decrease visited flag so that we walk with the same flag for the next
1078 expresssion. This guarantees that we don't dump the same node twice,
1079 as for const expressions cse is performed to save memory. */
1080 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1081 current_ir_graph = rem;
1082 dump_const_local = rem_dump_const_local;
1085 /** Dump a block as graph containing its nodes.
1087 * Expects to find nodes belonging to the block as list in its
1089 * Dumps the edges of all nodes including itself. */
1091 dump_whole_block(FILE *F, ir_node *block) {
1093 assert(is_Block(block));
1095 fprintf(F, "graph: { title: \"");
1096 PRINT_NODEID(block);
1097 fprintf(F, "\" label: \"");
1098 dump_node_opcode(F, block);
1099 fprintf (F, " %ld", get_irn_node_nr(block));
1101 if (get_opt_dump_abstvals())
1102 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1104 fprintf(F, "\" status:clustered color:%s \n",
1105 get_Block_matured(block) ? "yellow" : "red");
1107 /* dump the blocks edges */
1108 dump_ir_data_edges(F, block);
1110 /* dump the nodes that go into the block */
1111 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1113 dump_ir_data_edges(F, node);
1116 /* Close the vcg information for the block */
1118 dump_const_node_local(F, block);
1120 dump_chi_term(F, block);
1125 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1126 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1128 dump_block_graph(FILE *F, ir_graph *irg) {
1130 ir_graph *rem = current_ir_graph;
1131 ir_node **arr = ird_get_irg_link(irg);
1132 current_ir_graph = irg;
1134 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1135 ir_node * node = arr[i];
1136 if (is_Block(node)) {
1137 /* Dumps the block and all the nodes in the block, which are to
1138 be found in Block->link. */
1139 dump_whole_block(F, node);
1141 /* Nodes that are not in a Block. */
1143 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1144 dump_const_block_local(F, node);
1146 dump_ir_data_edges(F, node);
1150 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1151 dump_loop_nodes_into_graph(F, irg);
1153 current_ir_graph = rem;
1156 /** Dumps an irg as a graph.
1157 * If interprocedural view edges can point to nodes out of this graph.
1159 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1161 fprintf(F, "graph: { title: \"");
1163 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1164 get_ent_dump_name(get_irg_entity(irg)));
1166 dump_block_graph(F, irg);
1168 /* Close the vcg information for the irg */
1169 fprintf(F, "}\n\n");
1172 /*******************************************************************/
1173 /* Basic type and entity nodes and edges. */
1174 /*******************************************************************/
1176 /** dumps the edges between nodes and their type or entity attributes. */
1177 static void dump_node2type_edges(ir_node *n, void *env)
1182 switch (get_irn_opcode(n)) {
1184 /* @@@ some consts have an entity */
1187 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1188 || (get_SymConst_kind(n) ==symconst_size))
1190 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1194 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1197 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1200 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1203 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1206 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1214 static int print_type_info(FILE *F, type *tp) {
1217 if (get_type_state(tp) == layout_undefined) {
1218 fprintf(F, "state: layout_undefined\n");
1220 fprintf(F, "state: layout_fixed,\n");
1222 if (get_type_mode(tp))
1223 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1224 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1229 static void print_typespecific_info(FILE *F, type *tp) {
1230 switch (get_type_tpop_code(tp)) {
1233 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1240 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1241 fprintf(F, "params: %d\n", get_method_n_params(tp));
1242 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1250 case tpo_enumeration:
1264 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1265 switch (get_type_tpop_code(tp)) {
1268 if (peculiarity_existent == get_class_peculiarity(tp))
1269 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1271 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1275 fprintf (F, " " TYPE_METH_NODE_ATTR);
1286 case tpo_enumeration:
1299 static int print_type_node(FILE *F, type *tp)
1303 fprintf (F, "node: {title: ");
1305 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1306 fprintf (F, " info1: \"");
1307 bad |= print_type_info(F, tp);
1308 print_typespecific_info(F, tp);
1310 print_typespecific_vcgattr(F, tp);
1316 #define X(a) case a: fprintf(F, #a); break
1317 void dump_entity_node(FILE *F, entity *ent, int color)
1319 fprintf (F, "node: {title: \"");
1320 PRINT_ENTID(ent); fprintf(F, "\"");
1321 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1322 fprintf (F, "label: ");
1323 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1325 fprintf(F, "color: %d", color);
1327 fprintf (F, ENTITY_NODE_ATTR);
1328 fprintf (F, "\n info1: \"");
1330 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1332 fprintf(F, "\"\n}\n");
1336 static void dump_enum_item(FILE *F, type *tp, int pos)
1339 ident *id = get_enumeration_nameid(tp, pos);
1340 tarval *tv = get_enumeration_enum(tp, pos);
1342 tarval_snprintf(buf, sizeof(buf), tv);
1343 fprintf (F, "node: {title: \"");
1344 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1345 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1346 fprintf (F, "label: ");
1347 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1348 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1351 /* dumps a type or entity and it's edges. */
1353 dump_type_info(type_or_ent *tore, void *env) {
1355 int i = 0; /* to shutup gcc */
1357 /* dump this type or entity */
1359 switch (get_kind(tore)) {
1362 entity *ent = (entity *)tore;
1365 dump_entity_node(F, ent, 0);
1367 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1368 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1369 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1370 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1371 if(is_class_type(get_entity_owner(ent))) {
1372 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1373 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1375 /* attached subgraphs */
1376 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1377 if (is_atomic_entity(ent)) {
1378 value = get_atomic_ent_value(ent);
1380 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1381 /* DDMN(value); $$$ */
1382 dump_const_expression(F, value);
1385 if (is_compound_entity(ent)) {
1386 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1387 value = get_compound_ent_value(ent, i);
1389 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1390 dump_const_expression(F, value);
1391 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1393 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1394 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1395 get_compound_ent_value_member(ent, i), i);
1404 type *tp = (type *)tore;
1405 print_type_node(F, tp);
1406 /* and now the edges */
1407 switch (get_type_tpop_code(tp)) {
1410 for (i=0; i < get_class_n_supertypes(tp); i++)
1411 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1412 for (i=0; i < get_class_n_members(tp); i++)
1413 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1417 for (i=0; i < get_struct_n_members(tp); i++)
1418 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1422 for (i = 0; i < get_method_n_params(tp); i++)
1423 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1424 for (i = 0; i < get_method_n_ress(tp); i++)
1425 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1429 for (i = 0; i < get_union_n_members(tp); i++)
1430 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1434 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1435 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1436 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1437 ir_node *upper = get_array_upper_bound(tp, i);
1438 ir_node *lower = get_array_lower_bound(tp, i);
1439 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1440 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1441 dump_const_expression(F, upper);
1442 dump_const_expression(F, lower);
1446 case tpo_enumeration:
1448 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1449 dump_enum_item(F, tp, i);
1450 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1455 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1463 break; /* case k_type */
1466 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1468 } /* switch kind_or_entity */
1471 typedef struct _h_env {
1476 /** For dumping class hierarchies.
1477 * Dumps a class type node and a superclass edge.
1478 * If env->dump_ent dumps entities of classes and overwrites edges.
1481 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1484 int i = 0; /* to shutup gcc */
1486 /* dump this type or entity */
1487 switch (get_kind(tore)) {
1489 entity *ent = (entity *)tore;
1490 if (get_entity_owner(ent) == get_glob_type()) break;
1491 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1492 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1494 dump_entity_node(F, ent, 0);
1496 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1497 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1498 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1500 } break; /* case k_entity */
1503 type *tp = (type *)tore;
1504 if (tp == get_glob_type()) break;
1505 switch (get_type_tpop_code(tp)) {
1507 print_type_node(F, tp);
1508 /* and now the edges */
1509 for (i=0; i < get_class_n_supertypes(tp); i++)
1511 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1517 break; /* case k_type */
1520 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1522 } /* switch kind_or_entity */
1525 /*******************************************************************/
1526 /* dump analysis information that is expressed in graph terms. */
1527 /*******************************************************************/
1529 /* dump out edges */
1531 dump_out_edge(ir_node *n, void *env) {
1534 for (i = 0; i < get_irn_n_outs(n); i++) {
1535 assert(get_irn_out(n, i));
1536 fprintf (F, "edge: {sourcename: \"");
1538 fprintf (F, "\" targetname: \"");
1539 PRINT_NODEID(get_irn_out(n, i));
1540 fprintf (F, "\" color: red linestyle: dashed");
1546 dump_loop_label(FILE *F, ir_loop *loop) {
1547 fprintf (F, "loop %d, %d sons, %d nodes",
1548 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1551 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1552 fprintf (F, " info1: \"");
1553 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1554 #if DEBUG_libfirm /* GL @@@ debug analyses */
1555 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1561 dump_loop_node(FILE *F, ir_loop *loop) {
1562 fprintf (F, "node: {title: \"");
1564 fprintf (F, "\" label: \"");
1565 dump_loop_label(F, loop);
1567 dump_loop_info(F, loop);
1573 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1575 fprintf (F, "edge: {sourcename: \"");
1577 fprintf (F, "\" targetname: \"");
1578 PRINT_NODEID(get_loop_node(loop, i));
1579 fprintf (F, "\" color: green");
1584 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1586 fprintf (F, "edge: {sourcename: \"");
1588 fprintf (F, "\" targetname: \"");
1589 PRINT_LOOPID(get_loop_son(loop, i));
1590 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1591 get_loop_element_pos(loop, get_loop_son(loop, i)));
1595 void dump_loops(FILE *F, ir_loop *loop) {
1597 /* dump this loop node */
1598 dump_loop_node(F, loop);
1600 /* dump edges to nodes in loop -- only if it is a real loop */
1601 if (get_loop_depth(loop) != 0) {
1602 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1603 dump_loop_node_edge(F, loop, i);
1606 for (i = 0; i < get_loop_n_sons(loop); i++) {
1607 dump_loops(F, get_loop_son(loop, i));
1608 dump_loop_son_edge(F, loop, i);
1613 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1614 ir_graph *rem = current_ir_graph;
1615 current_ir_graph = irg;
1617 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1619 current_ir_graph = rem;
1624 * dumps the VCG header
1626 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1635 if (!orientation) orientation = "bottom_to_top";
1639 "graph: { title: \"ir graph of %s\"\n"
1640 "display_edge_labels: %s\n"
1641 "layoutalgorithm: mindepth\n"
1642 "manhattan_edges: yes\n"
1643 "port_sharing: no\n"
1645 "classname 1: \"intrablock Data\"\n"
1646 "classname 16: \"interblock Data\"\n"
1647 "classname 2: \"Block\"\n"
1648 "classname 13: \"Control Flow\"\n"
1649 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1650 "classname 14: \"intrablock Memory\"\n"
1651 "classname 17: \"interblock Memory\"\n"
1652 "classname 15: \"Dominators\"\n"
1653 "classname 3: \"Entity type\"\n"
1654 "classname 4: \"Entity owner\"\n"
1655 "classname 5: \"Method Param\"\n"
1656 "classname 6: \"Method Res\"\n"
1657 "classname 7: \"Super\"\n"
1658 "classname 8: \"Union\"\n"
1659 "classname 9: \"Points-to\"\n"
1660 "classname 10: \"Array Element Type\"\n"
1661 "classname 11: \"Overwrites\"\n"
1662 "classname 12: \"Member\"\n"
1663 "infoname 1: \"Attribute\"\n"
1664 "infoname 2: \"Verification errors\"\n",
1665 name, label, orientation);
1667 /* don't use all, the range is too whith/black. */
1671 "colorentry 100: 0 0 0\n"
1672 "colorentry 101: 20 0 0\n"
1673 "colorentry 102: 40 0 0\n"
1674 "colorentry 103: 60 0 0\n"
1675 "colorentry 104: 80 0 0\n"
1676 "colorentry 105: 100 0 0\n"
1677 "colorentry 106: 120 0 0\n"
1678 "colorentry 107: 140 0 0\n"
1679 "colorentry 108: 150 0 0\n"
1680 "colorentry 109: 180 0 0\n"
1681 "colorentry 110: 200 0 0\n"
1682 "colorentry 111: 220 0 0\n"
1683 "colorentry 112: 240 0 0\n"
1684 "colorentry 113: 255 0 0\n"
1685 "colorentry 113: 255 20 20\n"
1686 "colorentry 114: 255 40 40\n"
1687 "colorentry 115: 255 60 60\n"
1688 "colorentry 116: 255 80 80\n"
1689 "colorentry 117: 255 100 100\n"
1690 "colorentry 118: 255 120 120\n"
1691 "colorentry 119: 255 140 140\n"
1692 "colorentry 120: 255 150 150\n"
1693 "colorentry 121: 255 180 180\n"
1694 "colorentry 122: 255 200 200\n"
1695 "colorentry 123: 255 220 220\n"
1696 "colorentry 124: 255 240 240\n"
1697 "colorentry 125: 255 250 250\n"
1700 fprintf (F, "\n"); /* a separator */
1706 * @param irg The graph to be dumped
1707 * @param suffix1 first filename suffix
1708 * @param suffix2 second filename suffix
1710 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1712 const char *nm = get_irg_dump_name(irg);
1713 int len = strlen(nm), i, j;
1714 char *fname; /* filename to put the vcg information in */
1716 if (!suffix1) suffix1 = "";
1717 if (!suffix2) suffix2 = "";
1719 /* open file for vcg graph */
1720 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1722 /* strncpy (fname, nm, len); */ /* copy the filename */
1724 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1726 fname[j] = '@'; j++; fname[j] = '1'; j++;
1727 } else if (nm[i] == '@') {
1728 fname[j] = '@'; j++; fname[j] = '2'; j++;
1730 fname[j] = nm[i]; j++;
1734 strcat (fname, suffix1); /* append file suffix */
1735 strcat (fname, suffix2); /* append file suffix */
1736 strcat (fname, ".vcg"); /* append the .vcg suffix */
1737 F = fopen (fname, "w"); /* open file for writing */
1739 panic("cannot open %s for writing (%m)", fname); /* not reached */
1749 * @param irg The graph to be dumped
1750 * @param suffix filename suffix
1752 static FILE *vcg_open_name (const char *name, const char *suffix) {
1754 char *fname; /* filename to put the vcg information in */
1755 int i, j, len = strlen(name);
1757 if (!suffix) suffix = "";
1759 /** open file for vcg graph */
1760 fname = malloc (len * 2 + 5 + strlen(suffix));
1761 /* strcpy (fname, name);*/ /* copy the filename */
1763 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1764 if (name[i] == '/') {
1765 fname[j] = '@'; j++; fname[j] = '1'; j++;
1766 } else if (name[i] == '@') {
1767 fname[j] = '@'; j++; fname[j] = '2'; j++;
1769 fname[j] = name[i]; j++;
1773 strcat (fname, suffix);
1774 strcat (fname, ".vcg"); /* append the .vcg suffix */
1775 F = fopen (fname, "w"); /* open file for writing */
1777 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1785 * Dumps the vcg file footer
1787 static INLINE void dump_vcg_footer (FILE *F) {
1792 * close the vcg file
1794 void vcg_close (FILE *F) {
1795 dump_vcg_footer(F); /* print footer */
1796 fclose (F); /* close vcg file */
1799 /************************************************************************/
1800 /************************************************************************/
1801 /* Routines that dump all or parts of the firm representation to a file */
1802 /************************************************************************/
1803 /************************************************************************/
1805 /************************************************************************/
1806 /* Dump ir graphs, differnt formats and additional information. */
1807 /************************************************************************/
1809 /** Routine to dump a graph, blocks as conventional nodes. */
1811 dump_ir_graph (ir_graph *irg, const char *suffix )
1816 rem = current_ir_graph;
1818 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1819 current_ir_graph = irg;
1820 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1821 else suffix1 = "-pure";
1822 f = vcg_open(irg, suffix, suffix1);
1823 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1825 /* walk over the graph */
1826 /* dump_whole_node must be called in post visiting predecessors */
1827 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1829 /* dump the out edges in a separate walk */
1830 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1831 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1836 current_ir_graph = rem;
1841 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1847 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1850 if (get_interprocedural_view()) suffix1 = "-ip";
1852 f = vcg_open(irg, suffix, suffix1);
1853 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1855 construct_block_lists(irg);
1857 for (i = 0; i < get_irp_n_irgs(); i++) {
1858 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1860 dump_graph_from_list(f, get_irp_irg(i));
1868 /** dumps a graph with type information */
1870 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1873 ir_graph *rem = current_ir_graph;
1876 /* if a filter is set, dump only the irg's that match the filter */
1877 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1880 current_ir_graph = irg;
1882 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
1883 else suffix1 = "-pure-wtypes";
1884 f = vcg_open(irg,suffix, suffix1);
1885 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1887 /* dump common ir graph */
1888 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1889 /* dump type info */
1890 type_walk_irg(irg, dump_type_info, NULL, f);
1891 inc_irg_visited(get_const_code_irg());
1892 /* dump edges from graph to type info */
1893 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1896 current_ir_graph = rem;
1900 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1905 ir_graph *rem = current_ir_graph;
1907 /* if a filter is set, dump only the irg's that match the filter */
1908 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1911 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
1912 else suffix1 = "-wtypes";
1913 f = vcg_open(irg, suffix, suffix1);
1914 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1916 /* dump common blocked ir graph */
1917 construct_block_lists(irg);
1919 for (i = 0; i < get_irp_n_irgs(); i++) {
1920 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1922 dump_graph_from_list(f, get_irp_irg(i));
1927 /* dump type info */
1928 current_ir_graph = irg;
1929 type_walk_irg(irg, dump_type_info, NULL, f);
1930 inc_irg_visited(get_const_code_irg());
1932 /* dump edges from graph to type info */
1933 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1935 current_ir_graph = rem;
1939 /*---------------------------------------------------------------------*/
1940 /* The following routines dump a control flow graph. */
1941 /*---------------------------------------------------------------------*/
1944 dump_block_to_cfg(ir_node *block, void *env) {
1949 if (is_Block(block)) {
1950 /* This is a block. Dump a node for the block. */
1951 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1952 fprintf (F, "\" label: \"");
1953 if (block == get_irg_start_block(get_irn_irg(block)))
1954 fprintf(F, "Start ");
1955 if (block == get_irg_end_block(get_irn_irg(block)))
1958 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1959 PRINT_NODEID(block);
1961 fprintf(F, "info1:\"");
1962 if (dump_dominator_information_flag)
1963 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
1965 /* show arity and possible Bad predecessors of the block */
1966 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
1967 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
1968 ir_node *pred = get_Block_cfgpred(block, i);
1971 fprintf(F, "Bad pred at pos: ");
1972 fprintf(F, "%d ", i);
1979 fprintf (F, "\""); /* closing quote of info */
1981 if ((block == get_irg_start_block(get_irn_irg(block))) ||
1982 (block == get_irg_end_block(get_irn_irg(block))) )
1983 fprintf(F, " color:blue ");
1985 fprintf(F, " color:yellow ");
1988 /* Dump the edges */
1989 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1990 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1991 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1992 fprintf (F, "edge: { sourcename: \"");
1993 PRINT_NODEID(block);
1994 fprintf (F, "\" targetname: \"");
1996 fprintf (F, "\"}\n");
1999 /* Dump dominator edge */
2000 if (dump_dominator_information_flag && get_Block_idom(block)) {
2001 pred = get_Block_idom(block);
2002 fprintf (F, "edge: { sourcename: \"");
2003 PRINT_NODEID(block);
2004 fprintf (F, "\" targetname: \"");
2006 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2012 dump_cfg (ir_graph *irg, const char *suffix)
2015 ir_graph *rem = current_ir_graph;
2016 int ddif = dump_dominator_information_flag;
2017 int ipv = get_interprocedural_view();
2019 /* if a filter is set, dump only the irg's that match the filter */
2020 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2023 current_ir_graph = irg;
2025 f = vcg_open(irg, suffix, "-cfg");
2026 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2029 printf("Warning: dumping cfg not in interprocedural view!\n");
2030 set_interprocedural_view(false);
2033 if (get_irg_dom_state(irg) != dom_consistent)
2034 dump_dominator_information_flag = 0;
2036 /* walk over the blocks in the graph */
2037 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2038 dump_node(f, get_irg_bad(irg));
2040 dump_dominator_information_flag = ddif;
2041 set_interprocedural_view(ipv);
2043 current_ir_graph = rem;
2046 static int weight_overall(int rec, int loop) {
2047 return 2*rec + loop;
2050 static int compute_color (int my, int max) {
2055 /* if small, scale to the full color range. */
2057 my = my * (n_colors/max);
2059 int step = 1 + (max / n_colors);
2063 return base_color + n_colors - color;
2066 static int get_entity_color(entity *ent) {
2067 assert(get_entity_irg(ent));
2068 ir_graph *irg = get_entity_irg(ent);
2070 int rec_depth = get_irg_recursion_depth(irg);
2071 int loop_depth = get_irg_loop_depth(irg);
2072 int overall_depth = weight_overall(rec_depth, loop_depth);
2074 int max_rec_depth = irp->max_callgraph_recursion_depth;
2075 int max_loop_depth = irp->max_callgraph_loop_depth;
2076 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2078 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2079 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2080 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2082 return my_overall_color;
2085 void dump_callgraph(const char *suffix) {
2087 int i, n_irgs = get_irp_n_irgs();
2088 int rem = edge_label;
2090 //ident *prefix = new_id_from_str("java/");
2092 F = vcg_open_name("Callgraph", suffix);
2093 dump_vcg_header(F, "Callgraph", NULL);
2095 for (i = 0; i < n_irgs; ++i) {
2096 ir_graph *irg = get_irp_irg(i);
2097 entity *ent = get_irg_entity(irg);
2098 int j, n_callees = get_irg_n_callees(irg);
2100 /* Do not dump runtime system. */
2101 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2103 dump_entity_node(F, ent, get_entity_color(ent));
2104 for (j = 0; j < n_callees; ++j) {
2105 entity *c = get_irg_entity(get_irg_callee(irg, j));
2106 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2107 int be = is_irg_callee_backedge(irg, j);
2110 "label:\"recursion %d\" color: %d" :
2111 "label:\"calls %d\" color: %d";
2112 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2120 /* Dump all irgs in interprocedural view to a single file. */
2121 void dump_all_cg_block_graph(const char *suffix) {
2124 int rem_view = get_interprocedural_view();
2125 set_interprocedural_view(true);
2127 f = vcg_open_name("All_graphs", suffix);
2128 dump_vcg_header(f, "All_graphs", NULL);
2130 /* collect nodes in all irgs reachable in call graph*/
2131 for (i = 0; i < get_irp_n_irgs(); i++)
2132 ird_set_irg_link(get_irp_irg(i), NULL);
2134 cg_walk(clear_link, collect_node, NULL);
2136 /* dump all graphs */
2137 for (i = 0; i < get_irp_n_irgs(); i++) {
2138 current_ir_graph = get_irp_irg(i);
2139 assert(ird_get_irg_link(current_ir_graph));
2140 dump_graph_from_list(f, current_ir_graph);
2141 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2145 set_interprocedural_view(rem_view);
2148 /*---------------------------------------------------------------------*/
2149 /* the following routines dumps type information without any ir nodes. */
2150 /*---------------------------------------------------------------------*/
2153 dump_type_graph (ir_graph *irg, const char *suffix)
2157 rem = current_ir_graph;
2159 /* if a filter is set, dump only the irg's that match the filter */
2160 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2162 current_ir_graph = irg;
2164 f = vcg_open(irg, suffix, "-type");
2165 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2167 /* walk over the blocks in the graph */
2168 type_walk_irg(irg, dump_type_info, NULL, f);
2169 /* The walker for the const code can be called several times for the
2170 same (sub) experssion. So that no nodes are dumped several times
2171 we decrease the visited flag of the corresponding graph after each
2172 walk. So now increase it finally. */
2173 inc_irg_visited(get_const_code_irg());
2176 current_ir_graph = rem;
2180 dump_all_types (const char *suffix)
2182 FILE *f = vcg_open_name("All_types", suffix);
2183 dump_vcg_header(f, "All_types", NULL);
2184 type_walk(dump_type_info, NULL, f);
2185 inc_irg_visited(get_const_code_irg());
2190 dump_class_hierarchy (bool entities, const char *suffix)
2192 FILE *f = vcg_open_name("class_hierarchy", suffix);
2196 dump_vcg_header(f, "class_hierarchy", NULL);
2201 type_walk(dump_class_hierarchy_node, NULL, &env);
2205 /*---------------------------------------------------------------------*/
2206 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2208 /* dump_ir_block_graph */
2210 /* dump_type_graph */
2211 /* dump_ir_graph_w_types */
2212 /*---------------------------------------------------------------------*/
2214 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2215 int i, n_irgs = get_irp_n_irgs();
2216 for (i = 0; i < n_irgs; ++i) {
2217 dmp_grph(get_irp_irg(i), suffix);
2222 /*--------------------------------------------------------------------------------*
2223 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2224 * packed together in one subgraph/box *
2225 *--------------------------------------------------------------------------------*/
2227 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2228 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2230 ir_loop *son = NULL;
2232 /* Dump a new loop node. */
2233 dump_loop_node(F, loop);
2235 /* Dump the loop elements. */
2237 for(i = 0; i < get_loop_n_elements(loop); i++) {
2238 le = get_loop_element(loop, i);
2240 if (get_kind(son) == k_ir_loop) {
2242 /* We are a loop son -> Recurse */
2244 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2245 fprintf(F, "\" }\n");
2246 fprintf (F, "edge: {sourcename: \"");
2248 fprintf (F, "\" targetname: \"");
2250 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2251 loop_node_started = 0;
2253 dump_loop_son_edge(F, loop, son_number++);
2254 dump_loops_standalone(F, son);
2255 } else if (get_kind(son) == k_ir_node) {
2256 /* We are a loop node -> Collect firm nodes */
2258 ir_node *n = le.node;
2261 if (!loop_node_started) {
2262 /* Start a new node which contains all firm nodes of the current loop */
2263 fprintf (F, "node: { title: \"");
2265 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2266 loop_node_started = 1;
2272 bad |= dump_node_opcode(F, n);
2273 bad |= dump_node_mode(F, n);
2274 bad |= dump_node_typeinfo(F, n);
2276 bad |= dump_node_nodeattr(F, n);
2277 fprintf (F, " %ld", get_irn_node_nr(n));
2278 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2279 if (has_backedges(n)) fprintf(F, "\t loop head!");
2280 } else { /* for callgraph loop tree */
2281 assert(get_kind(son) == k_ir_graph);
2282 /* We are a loop node -> Collect firm graphs */
2283 ir_graph *n = (ir_graph *)le.node;
2284 if (!loop_node_started) {
2285 /* Start a new node which contains all firm nodes of the current loop */
2286 fprintf (F, "node: { title: \"");
2288 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2289 loop_node_started = 1;
2294 fprintf (F, " %s", get_irg_dump_name(n));
2295 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2299 if (loop_node_started) {
2300 fprintf(F, "\" }\n");
2301 fprintf (F, "edge: {sourcename: \"");
2303 fprintf (F, "\" targetname: \"");
2305 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2306 loop_node_started = 0;
2310 void dump_loop_tree(ir_graph *irg, const char *suffix)
2313 ir_graph *rem = current_ir_graph;
2314 int el_rem = edge_label;
2317 /* if a filter is set, dump only the irg's that match the filter */
2318 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2321 current_ir_graph = irg;
2323 f = vcg_open(irg, suffix, "-looptree");
2324 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2326 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2330 edge_label = el_rem;
2331 current_ir_graph = rem;
2334 void dump_callgraph_loop_tree(const char *suffix) {
2336 F = vcg_open_name("Callgraph_looptree", suffix);
2337 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2338 dump_loops_standalone(F, irp->outermost_cg_loop);
2343 /*-----------------------------------------------------------------------------*/
2344 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2345 /*-----------------------------------------------------------------------------*/
2347 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2348 int i, son_number = 0, node_number = 0;
2350 if (dump_loop_information_flag) dump_loop_node(F, loop);
2352 for (i = 0; i < get_loop_n_elements(loop); i++) {
2353 loop_element le = get_loop_element(loop, i);
2354 if (*(le.kind) == k_ir_loop) {
2355 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2357 collect_nodeloop(F, le.son, loopnodes);
2359 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2360 eset_insert(loopnodes, le.node);
2365 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2368 for(i = 0; i < get_loop_n_elements(loop); i++) {
2369 loop_element le = get_loop_element(loop, i);
2370 if (*(le.kind) == k_ir_loop) {
2372 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2374 if (is_Block(le.node)) start = 0; else start = -1;
2375 for (j = start; j < get_irn_arity(le.node); j++) {
2376 ir_node *pred = get_irn_n(le.node, j);
2377 if (!eset_contains(loopnodes, pred)) {
2378 eset_insert(extnodes, pred);
2379 if (!is_Block(pred)) {
2380 pred = get_nodes_block(pred);
2381 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2389 void dump_loop(ir_loop *l, const char *suffix) {
2392 eset *loopnodes = eset_create();
2393 eset *extnodes = eset_create();
2396 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2397 F = vcg_open_name (name, suffix);
2398 dump_vcg_header(F, name, NULL);
2400 /* collect all nodes to dump */
2401 collect_nodeloop(F, l, loopnodes);
2402 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2404 /* build block lists */
2405 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2406 set_irn_link(n, NULL);
2407 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2408 set_irn_link(n, NULL);
2409 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2411 b = get_nodes_block(n);
2412 set_irn_link(n, get_irn_link(b));
2415 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2417 b = get_nodes_block(n);
2418 set_irn_link(n, get_irn_link(b));
2422 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2424 fprintf(F, "graph: { title: \"");
2426 fprintf(F, "\" label: \"");
2427 dump_node_opcode(F, b);
2428 fprintf (F, " %ld", get_irn_node_nr(b));
2429 fprintf(F, "\" status:clustered color:yellow\n");
2431 /* dump the blocks edges */
2432 dump_ir_data_edges(F, b);
2434 /* dump the nodes that go into the block */
2435 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2436 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2438 overrule_nodecolor = NULL;
2439 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2442 /* Close the vcg information for the block */
2444 dump_const_node_local(F, b);
2447 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2449 fprintf(F, "graph: { title: \"");
2451 fprintf(F, "\" label: \"");
2452 dump_node_opcode(F, b);
2453 fprintf (F, " %ld", get_irn_node_nr(b));
2454 fprintf(F, "\" status:clustered color:lightblue\n");
2456 /* dump the nodes that go into the block */
2457 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2458 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2460 overrule_nodecolor = NULL;
2461 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2464 /* Close the vcg information for the block */
2466 dump_const_node_local(F, b);
2470 eset_destroy(loopnodes);
2471 eset_destroy(extnodes);