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"
42 #include "irextbb_t.h"
53 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
54 extern void dump_irn_state(FILE *FL, ir_node *n);
55 extern int get_opt_dump_abstvals(void);
56 typedef unsigned long SeqNo;
57 extern SeqNo get_Block_seqno(ir_node *n);
60 /* basis for a color range for vcg */
61 static int n_colors = 0;
62 static int base_color = 0;
64 /** Dump only irgs with names that start with this string */
65 static ident *dump_file_filter_id = NULL;
67 #define ERROR_TXT "<ERROR>"
70 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
71 * in the later case, sets bad
73 const char *get_mode_name_ex(ir_mode *mode, int *bad)
76 return get_mode_name(mode);
82 * returns the name of a type or <ERROR> if mode is NOT a mode object.
83 * in the later case, sets bad
85 const char *get_type_name_ex(type *tp, int *bad)
88 return get_type_name(tp);
94 * prints the edge from a type S to a type T with additional info fmt, ...
97 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
102 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
103 fprintf(F, " targetname: "); PRINT_TYPEID(T);
104 vfprintf(F, fmt, ap);
110 * prints the edge from a type T to an entity E with additional info fmt, ...
113 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
118 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
119 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
120 vfprintf(F, fmt, ap);
126 * prints the edge from an entity E to an entity T with additional info fmt, ...
129 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
135 fprintf(F, "backedge: { sourcename: \"");
137 fprintf(F, "edge: { sourcename: \"");
139 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
140 vfprintf(F, fmt, ap);
146 * prints the edge from an entity E to a type T with additional info fmt, ...
149 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
154 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
155 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
156 vfprintf(F, fmt, ap);
162 * prints the edge from a node N to a type T with additional info fmt, ...
165 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
170 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
171 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
172 vfprintf(F, fmt, ap);
178 * prints the edge from a node N to an entity E with additional info fmt, ...
181 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
186 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
187 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
189 vfprintf(F, fmt, ap);
195 * prints the edge from an entity E to a node N with additional info fmt, ...
198 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
203 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
204 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
205 vfprintf(F, fmt, ap);
211 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
214 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
219 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
220 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
221 vfprintf(F, fmt, ap);
226 /*-----------------------------------------------------------------*/
227 /* global and ahead declarations */
228 /*-----------------------------------------------------------------*/
230 static void dump_whole_node(ir_node *n, void *env);
231 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
233 /*-----------------------------------------------------------------*/
234 /* Helper functions. */
235 /*-----------------------------------------------------------------*/
238 * This map is used as a private link attr to be able to call dumper
239 * anywhere without destroying link fields.
241 static pmap *irdump_link_map = NULL;
243 /** NOT A STANDARD LIBFIRM INIT METHOD
245 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
246 * are off, we want to have as few interferences as possible. Therefore the
247 * initialization is perfomed lazily and not called from within init_firm.
249 * Creates the link attribut map. */
250 static void init_irdump(void) {
251 /* We need a new, empty map. */
252 if (irdump_link_map) pmap_destroy(irdump_link_map);
253 irdump_link_map = pmap_create();
254 if (!dump_file_filter_id)
255 dump_file_filter_id = new_id_from_str("");
258 * Returns the private link field.
260 static void *ird_get_irn_link(ir_node *n) {
262 if (!irdump_link_map) return NULL;
264 if (pmap_contains(irdump_link_map, (void *)n))
265 res = pmap_get(irdump_link_map, (void *)n);
270 * Sets the private link field.
272 static void ird_set_irn_link(ir_node *n, void *x) {
273 if (!irdump_link_map) init_irdump();
274 pmap_insert(irdump_link_map, (void *)n, x);
278 * Gets the private link field of an irg.
280 static void *ird_get_irg_link(ir_graph *irg) {
282 if (!irdump_link_map) return NULL;
284 if (pmap_contains(irdump_link_map, (void *)irg))
285 res = pmap_get(irdump_link_map, (void *)irg);
290 * Sets the private link field of an irg.
292 static void ird_set_irg_link(ir_graph *irg, void *x) {
293 if (!irdump_link_map) init_irdump();
294 pmap_insert(irdump_link_map, (void *)irg, x);
298 * Walker, clears the private link field.
300 static void clear_link(ir_node * node, void * env) {
301 ird_set_irn_link(node, NULL);
305 * If the entity has a ld_name, returns it, else returns the name of the entity.
307 const char *get_ent_dump_name(entity *ent) {
309 return "<NULL entity>";
310 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
311 if (ent->ld_name) return get_id_str(ent->ld_name);
312 return get_id_str(ent->name);
315 /* Returns the name of an IRG. */
316 const char *get_irg_dump_name(ir_graph *irg) {
317 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
318 entity *ent = get_irg_entity(irg);
319 return get_ent_dump_name(ent);
323 * Returns non-zero if a node is in floating state.
325 static int node_floats(ir_node *n) {
326 return ((get_irn_pinned(n) == op_pin_state_floats) &&
327 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
331 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
333 static void collect_node(ir_node * node, void *env) {
336 || get_irn_op(node) == op_Bad
337 || get_irn_op(node) == op_Unknown
338 || get_irn_op(node) == op_NoMem) {
339 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
340 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
341 ARR_APP1(ir_node *, arr, node);
342 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
344 ir_node * block = get_nodes_block(node);
347 /* this node is in a Bad block, so we must place it into the graph's list */
348 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
349 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
350 ARR_APP1(ir_node *, arr, node);
351 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
354 ird_set_irn_link(node, ird_get_irn_link(block));
355 ird_set_irn_link(block, node);
360 /** Construct lists to walk ir block-wise.
362 * Collects all blocks, nodes not op_pin_state_pinned,
363 * Bad, NoMem and Unknown into a flexible array in link field of
364 * irg they belong to. Sets the irg link field to NULL in all
365 * graphs not visited.
366 * Free the list with DEL_ARR_F().
368 static ir_node **construct_block_lists(ir_graph *irg) {
369 int i, rem_view = get_interprocedural_view();
370 ir_graph *rem = current_ir_graph;
371 current_ir_graph = irg;
373 for (i = 0; i < get_irp_n_irgs(); i++)
374 ird_set_irg_link(get_irp_irg(i), NULL);
376 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
378 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
379 set_interprocedural_view(false);
381 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
382 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
383 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
384 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
386 set_interprocedural_view(rem_view);
388 current_ir_graph = rem;
389 return ird_get_irg_link(irg);
392 typedef struct _list_tuple {
394 ir_extblk **extbb_list;
397 /** Construct lists to walk ir extended block-wise.
398 * Free the lists in the tuple with DEL_ARR_F().
400 static list_tuple *construct_extblock_lists(ir_graph *irg) {
401 ir_node **blk_list = construct_block_lists(irg);
403 ir_graph *rem = current_ir_graph;
404 list_tuple *lists = xmalloc(sizeof(*lists));
406 current_ir_graph = irg;
408 lists->blk_list = NEW_ARR_F(ir_node *, 0);
409 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
411 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
414 if (is_Block(blk_list[i])) {
415 ext = get_Block_extbb(blk_list[i]);
417 if (extbb_not_visited(ext)) {
418 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
419 mark_extbb_visited(ext);
423 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
426 current_ir_graph = rem;
428 ird_set_irg_link(irg, lists);
432 /*******************************************************************/
433 /* flags to steer output */
434 /*******************************************************************/
436 /** A compiler option to turn off edge labels */
437 static int edge_label = 1;
438 /** A compiler option to turn off dumping values of constant entities */
439 static int const_entities = 1;
440 /** A compiler option to dump the keep alive edges */
441 static int dump_keepalive = 0;
442 /** Compiler options to dump analysis information in dump_ir_graph */
443 int dump_out_edge_flag = 0;
444 int dump_dominator_information_flag = 0;
445 int dump_loop_information_flag = 0;
446 int dump_backedge_information_flag = 1;
447 int dump_const_local = 0;
448 bool opt_dump_analysed_type_info = 1;
449 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
451 static const char *overrule_nodecolor = NULL;
453 /** An additional edge hook. */
454 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
456 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
458 dump_node_edge_hook = func;
461 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
463 return dump_node_edge_hook;
467 /** The vcg attribute hook. */
468 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
471 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
472 dump_node_vcgattr_hook = hook;
475 INLINE bool get_opt_dump_const_local(void) {
476 if (!dump_out_edge_flag && !dump_loop_information_flag)
477 return dump_const_local;
482 void only_dump_method_with_name(ident *name) {
483 dump_file_filter_id = name;
486 ident *get_dump_file_filter_ident(void) {
487 return dump_file_filter_id;
490 /** Returns true if dump file filter is not set, or if it is a
492 int is_filtered_dump_name(ident *name) {
493 if (!dump_file_filter_id) return 1;
494 return id_is_prefix(dump_file_filter_id, name);
497 /* To turn off display of edge labels. Edge labels offen cause xvcg to
498 abort with a segmentation fault. */
499 void turn_off_edge_labels(void) {
503 void dump_consts_local(bool b) {
504 dump_const_local = b;
507 void dump_constant_entity_values(bool b) {
511 void dump_keepalive_edges(bool b) {
515 bool get_opt_dump_keepalive_edges(void) {
516 return dump_keepalive;
519 void dump_out_edges(bool b) {
520 dump_out_edge_flag = b;
523 void dump_dominator_information(bool b) {
524 dump_dominator_information_flag = b;
527 void dump_loop_information(bool b) {
528 dump_loop_information_flag = b;
531 void dump_backedge_information(bool b) {
532 dump_backedge_information_flag = b;
535 /* Dump the information of type field specified in ana/irtypeinfo.h.
536 * If the flag is set, the type name is output in [] in the node label,
537 * else it is output as info.
539 void set_opt_dump_analysed_type_info(bool b) {
540 opt_dump_analysed_type_info = b;
543 void dump_pointer_values_to_info(bool b) {
544 opt_dump_pointer_values_to_info = b;
547 /*-----------------------------------------------------------------*/
548 /* Routines to dump information about a single ir node. */
549 /*-----------------------------------------------------------------*/
552 * dump the name of a node n to the File F.
555 dump_node_opcode(FILE *F, ir_node *n)
559 switch(get_irn_opcode(n)) {
564 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
565 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
570 if (get_SymConst_kind(n) == symconst_addr_name) {
571 /* don't use get_SymConst_ptr_info as it mangles the name. */
572 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
573 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
574 assert(get_SymConst_entity(n));
575 assert(is_entity(get_SymConst_entity(n)));
576 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
578 assert(get_kind(get_SymConst_type(n)) == k_type);
579 assert(get_type_ident(get_SymConst_type(n)));
580 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
581 if (get_SymConst_kind(n) == symconst_type_tag)
589 if (!get_interprocedural_view())
596 ir_node *pred = get_Proj_pred(n);
598 if (get_irn_opcode(pred) == iro_Cond
599 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
600 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
601 fprintf (F, "defProj");
603 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
604 * fprintf (F, "Arg");
613 if (get_interprocedural_view()) {
614 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
619 case iro_CallBegin: {
620 ir_node *addr = get_CallBegin_ptr(n);
622 if (get_irn_op(addr) == op_Sel)
623 ent = get_Sel_entity(addr);
624 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
625 ent = get_SymConst_entity(addr);
626 fprintf (F, "%s", get_irn_opname(n));
627 if (ent) fprintf (F, " %s", get_entity_name(ent));
631 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
636 fprintf (F, "%s", get_irn_opname(n));
644 * Dump the mode of a node n to a file F.
645 * Ignore modes that are "always known".
648 dump_node_mode(FILE *F, ir_node *n)
651 opcode iro = get_irn_opcode(n);
664 ir_mode *mode = get_irn_mode(n);
666 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
667 (mode != mode_T || iro == iro_Proj))
668 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
676 * Dump the type of a node n to a file F if it's known.
678 static int dump_node_typeinfo(FILE *F, ir_node *n) {
681 if (opt_dump_analysed_type_info) {
682 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
683 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
684 type *tp = get_irn_typeinfo_type(n);
685 if (tp != firm_none_type)
686 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
695 * Dump additional node attributes of some nodes to a file F.
698 dump_node_nodeattr(FILE *F, ir_node *n)
702 switch (get_irn_opcode(n)) {
704 if (false && get_interprocedural_view()) {
705 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
709 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
710 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
712 fprintf (F, "%ld ", get_Proj_proj(n));
716 fprintf (F, "%ld ", get_Filter_proj(n));
719 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
722 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
725 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
736 #include "execution_frequency.h"
737 #include "callgraph.h"
739 void dump_node_ana_vals(FILE *F, ir_node *n) {
741 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
742 get_irn_exec_freq(n),
743 get_irg_method_execution_frequency(get_irn_irg(n)),
744 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
745 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
750 /* Dumps a node label without the enclosing ". */
751 int dump_node_label(FILE *F, ir_node *n) {
754 bad |= dump_node_opcode(F, n);
755 bad |= dump_node_mode(F, n);
757 bad |= dump_node_typeinfo(F, n);
758 bad |= dump_node_nodeattr(F, n);
759 fprintf(F, "%ld", get_irn_node_nr(n));
766 * Dumps the attributes of a node n into the file F.
767 * Currently this is only the color of a node.
769 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
774 fprintf(F, "color: red");
778 if (dump_node_vcgattr_hook)
779 if (dump_node_vcgattr_hook(F, node, local))
782 n = local ? local : node;
784 switch (get_irn_opcode(n)) {
791 fprintf (F, "color: blue");
794 if (is_Block_dead(n))
795 fprintf (F, "color: lightred");
797 fprintf (F, "color: lightyellow");
800 fprintf (F, "color: green");
806 fprintf (F, "color: yellow");
809 PRINT_DEFAULT_NODE_ATTR;
812 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
817 * Dump the node information of a node n to a file F.
819 static INLINE int dump_node_info(FILE *F, ir_node *n)
821 fprintf (F, " info1: \"");
822 bad = dump_irnode_to_file(F, n);
828 * checks whether a node is "constant-like" ie can be treated "block-less"
831 bool is_constlike_node(ir_node *n) {
832 ir_op *op = get_irn_op(n);
833 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
837 /** outputs the predecessors of n, that are constants, local. I.e.,
838 generates a copy of the constant predecessors for each node called with. */
839 static void dump_const_node_local(FILE *F, ir_node *n) {
841 if (!get_opt_dump_const_local()) return;
843 /* Use visited flag to avoid outputting nodes twice.
844 initialize it first. */
845 for (i = 0; i < get_irn_arity(n); i++) {
846 ir_node *con = get_irn_n(n, i);
847 if (is_constlike_node(con)) {
848 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
852 for (i = 0; i < get_irn_arity(n); i++) {
853 ir_node *con = get_irn_n(n, i);
854 if (is_constlike_node(con) && irn_not_visited(con)) {
857 mark_irn_visited(con);
858 /* Generate a new name for the node by appending the names of
860 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
861 fprintf(F, " label: \"");
862 bad |= dump_node_label(F, con);
864 bad |= dump_node_info(F, con);
865 dump_node_vcgattr(F, n, con, bad);
871 /** If the block of an edge is a const_like node, dump it local with an edge */
872 static void dump_const_block_local(FILE *F, ir_node *n) {
875 if (!get_opt_dump_const_local()) return;
877 blk = get_nodes_block(n);
878 if (is_constlike_node(blk)) {
881 /* Generate a new name for the node by appending the names of
883 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
884 fprintf(F, "\" label: \"");
885 bad |= dump_node_label(F, blk);
887 bad |= dump_node_info(F, blk);
888 dump_node_vcgattr(F, n, blk, bad);
891 fprintf (F, "edge: { sourcename: \"");
893 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
894 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
899 * prints the error message of a node to a file F as info2.
901 static void INLINE print_node_error(FILE *F, const char *err_msg)
906 fprintf (F, " info2: \"%s\"", err_msg);
912 static void dump_node(FILE *F, ir_node *n)
917 if (get_opt_dump_const_local() && is_constlike_node(n))
921 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
923 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
924 bad |= dump_node_label(F, n);
925 dump_node_ana_vals(F, n);
926 //dump_node_ana_info(F, n);
928 bad |= dump_node_info(F, n);
929 print_node_error(F, p);
930 dump_node_vcgattr(F, n, NULL, bad);
932 dump_const_node_local(F, n);
934 if(dump_node_edge_hook)
935 dump_node_edge_hook(F, n);
937 dump_irn_chi_term(F, n);
938 dump_irn_state(F, n);
942 /** dump the edge to the block this node belongs to */
944 dump_ir_block_edge(FILE *F, ir_node *n) {
945 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
946 if (is_no_Block(n)) {
947 ir_node *block = get_nodes_block(n);
949 if (get_opt_dump_const_local() && is_constlike_node(block)) {
950 dump_const_block_local(F, n);
953 fprintf (F, "edge: { sourcename: \"");
955 fprintf (F, "\" targetname: ");
956 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
957 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
963 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
965 * do not use get_nodes_block() here, will fail
966 * if the irg is not pinned.
968 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
969 fprintf (F, INTRA_DATA_EDGE_ATTR);
971 fprintf (F, INTER_DATA_EDGE_ATTR);
975 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
977 * do not use get_nodes_block() here, will fail
978 * if the irg is not pinned.
980 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
981 fprintf (F, INTRA_MEM_EDGE_ATTR);
983 fprintf (F, INTER_MEM_EDGE_ATTR);
987 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
990 if (dump_backedge_information_flag && is_backedge(from, to))
991 fprintf (F, BACK_EDGE_ATTR);
993 switch (get_irn_opcode(from)) {
995 fprintf (F, CF_EDGE_ATTR);
997 case iro_Start: break;
1000 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1001 fprintf (F, CF_EDGE_ATTR);
1002 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1003 fprintf (F, INTER_MEM_EDGE_ATTR);
1011 print_data_edge_vcgattr(F, from, to);
1016 print_mem_edge_vcgattr(F, from, to);
1018 print_data_edge_vcgattr(F, from, to);
1022 print_data_edge_vcgattr(F, from, to);
1027 print_mem_edge_vcgattr(F, from, to);
1029 print_data_edge_vcgattr(F, from, to);
1036 print_data_edge_vcgattr(F, from, to);
1043 print_mem_edge_vcgattr(F, from, to);
1045 print_data_edge_vcgattr(F, from, to);
1057 print_data_edge_vcgattr(F, from, to);
1060 if (get_irn_modecode(from) == irm_M)
1061 fprintf (F, INTER_MEM_EDGE_ATTR);
1063 print_data_edge_vcgattr(F, from, to);
1070 print_mem_edge_vcgattr(F, from, to);
1072 print_data_edge_vcgattr(F, from, to);
1075 print_mem_edge_vcgattr(F, from, to);
1077 case iro_Tuple: break;
1080 switch (get_irn_modecode(from)) {
1082 fprintf (F, CF_EDGE_ATTR);
1085 fprintf (F, INTER_MEM_EDGE_ATTR);
1088 print_data_edge_vcgattr(F, from, to);
1092 case iro_Bad: break;
1093 case iro_Unknown: break;
1095 switch (get_irn_modecode(from)) {
1097 fprintf (F, INTRA_MEM_EDGE_ATTR);
1100 fprintf (F, CF_EDGE_ATTR);
1103 print_data_edge_vcgattr(F, from, to);
1111 /* dump edges to our inputs */
1113 dump_ir_data_edges(FILE *F, ir_node *n) {
1115 unsigned long visited = get_irn_visited(n);
1117 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1120 for (i = 0; i < get_irn_arity(n); i++) {
1121 ir_node * pred = get_irn_n(n, i);
1124 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1125 continue; /* pred not dumped */
1127 if (dump_backedge_information_flag && is_backedge(n, i))
1128 fprintf (F, "backedge: {sourcename: \"");
1130 fprintf (F, "edge: {sourcename: \"");
1132 fprintf (F, "\" targetname: ");
1133 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1134 PRINT_CONSTID(n, pred);
1136 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1138 fprintf (F, " label: \"%d\" ", i);
1139 print_edge_vcgattr(F, n, i);
1144 /** Dumps a node and its edges but not the block edge
1147 dump_node_wo_blockedge (ir_node *n, void *env) {
1150 dump_ir_data_edges(F, n);
1153 /** Dumps a node and its edges.
1156 dump_whole_node (ir_node *n, void *env) {
1158 dump_node_wo_blockedge(n, env);
1159 if (!node_floats(n)) dump_ir_block_edge(F, n);
1163 dump_const_node(ir_node *n, void *env) {
1164 if (is_Block(n)) return;
1165 dump_node_wo_blockedge(n, env);
1168 /***********************************************************************/
1169 /* the following routines dump the nodes/irgs bracketed to graphs. */
1170 /***********************************************************************/
1172 /** Dumps a constant expression as entity initializer, array bound ...
1174 static void dump_const_expression(FILE *F, ir_node *value) {
1175 ir_graph *rem = current_ir_graph;
1176 int rem_dump_const_local = dump_const_local;
1177 dump_const_local = 0;
1178 current_ir_graph = get_const_code_irg();
1179 irg_walk(value, dump_const_node, NULL, F);
1180 /* Decrease visited flag so that we walk with the same flag for the next
1181 expression. This guarantees that we don't dump the same node twice,
1182 as for const expressions cse is performed to save memory. */
1183 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1184 current_ir_graph = rem;
1185 dump_const_local = rem_dump_const_local;
1188 /** Dump a block as graph containing its nodes.
1190 * Expects to find nodes belonging to the block as list in its
1192 * Dumps the edges of all nodes including itself. */
1194 dump_whole_block(FILE *F, ir_node *block) {
1196 assert(is_Block(block));
1198 fprintf(F, "graph: { title: \"");
1199 PRINT_NODEID(block);
1200 fprintf(F, "\" label: \"");
1201 dump_node_label(F, block);
1203 if (get_opt_dump_abstvals())
1204 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1206 fprintf(F, "\" status:clustered color:%s \n",
1207 get_Block_matured(block) ? "yellow" : "red");
1209 /* dump the blocks edges */
1210 dump_ir_data_edges(F, block);
1212 /* dump the nodes that go into the block */
1213 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1215 dump_ir_data_edges(F, node);
1218 /* Close the vcg information for the block */
1220 dump_const_node_local(F, block);
1222 dump_irn_chi_term(F, block);
1227 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1228 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1230 dump_block_graph(FILE *F, ir_graph *irg) {
1232 ir_graph *rem = current_ir_graph;
1233 ir_node **arr = ird_get_irg_link(irg);
1234 current_ir_graph = irg;
1236 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1237 ir_node * node = arr[i];
1238 if (is_Block(node)) {
1239 /* Dumps the block and all the nodes in the block, which are to
1240 be found in Block->link. */
1241 dump_whole_block(F, node);
1243 /* Nodes that are not in a Block. */
1245 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1246 dump_const_block_local(F, node);
1248 dump_ir_data_edges(F, node);
1252 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1253 dump_loop_nodes_into_graph(F, irg);
1255 current_ir_graph = rem;
1258 /** Dumps an irg as a graph clustered by block nodes.
1259 * If interprocedural view edges can point to nodes out of this graph.
1261 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1263 fprintf(F, "graph: { title: \"");
1265 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1266 get_ent_dump_name(get_irg_entity(irg)));
1268 dump_block_graph(F, irg);
1270 /* Close the vcg information for the irg */
1271 fprintf(F, "}\n\n");
1274 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1275 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1277 dump_extblock_graph(FILE *F, ir_graph *irg) {
1279 ir_graph *rem = current_ir_graph;
1280 ir_extblk **arr = ird_get_irg_link(irg);
1281 current_ir_graph = irg;
1284 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1285 ir_extblk *extbb = arr[i];
1286 ir_node *leader = extbb->blks[0];
1289 fprintf(F, "graph: { title: \"");
1290 PRINT_EXTBBID(leader);
1291 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1292 get_irn_node_nr(leader));
1294 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1295 ir_node * node = extbb->blks[j];
1296 if (is_Block(node)) {
1297 /* Dumps the block and all the nodes in the block, which are to
1298 be found in Block->link. */
1299 dump_whole_block(F, node);
1301 /* Nodes that are not in a Block. */
1303 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1304 dump_const_block_local(F, node);
1306 dump_ir_data_edges(F, node);
1312 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1313 dump_loop_nodes_into_graph(F, irg);
1315 current_ir_graph = rem;
1320 /*******************************************************************/
1321 /* Basic type and entity nodes and edges. */
1322 /*******************************************************************/
1324 /** dumps the edges between nodes and their type or entity attributes. */
1325 static void dump_node2type_edges(ir_node *n, void *env)
1330 switch (get_irn_opcode(n)) {
1332 /* @@@ some consts have an entity */
1335 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1336 || (get_SymConst_kind(n) ==symconst_size))
1338 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1342 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1345 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1348 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1351 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1354 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1362 static int print_type_info(FILE *F, type *tp) {
1365 if (get_type_state(tp) == layout_undefined) {
1366 fprintf(F, "state: layout_undefined\n");
1368 fprintf(F, "state: layout_fixed,\n");
1370 if (get_type_mode(tp))
1371 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1372 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1377 static void print_typespecific_info(FILE *F, type *tp) {
1378 switch (get_type_tpop_code(tp)) {
1381 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1388 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1389 fprintf(F, "params: %d\n", get_method_n_params(tp));
1390 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1398 case tpo_enumeration:
1412 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1413 switch (get_type_tpop_code(tp)) {
1416 if (peculiarity_existent == get_class_peculiarity(tp))
1417 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1419 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1423 fprintf (F, " " TYPE_METH_NODE_ATTR);
1434 case tpo_enumeration:
1448 /* Why not dump_type_node as the others? */
1449 static int print_type_node(FILE *F, type *tp)
1453 fprintf (F, "node: {title: ");
1455 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1456 fprintf (F, " info1: \"");
1458 bad |= print_type_info(F, tp);
1459 print_typespecific_info(F, tp);
1461 dump_type_to_file(F, tp, dump_verbosity_max);
1464 print_typespecific_vcgattr(F, tp);
1470 int dump_type_node(FILE *F, type *tp) {
1471 return print_type_node(F, tp);
1475 #define X(a) case a: fprintf(F, #a); break
1476 void dump_entity_node(FILE *F, entity *ent, int color)
1478 fprintf (F, "node: {title: \"");
1479 PRINT_ENTID(ent); fprintf(F, "\"");
1480 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1481 fprintf (F, "label: ");
1482 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1484 fprintf(F, "color: %d", color);
1486 fprintf (F, ENTITY_NODE_ATTR);
1487 fprintf (F, "\n info1: \"");
1489 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1491 fprintf(F, "\"\n}\n");
1495 static void dump_enum_item(FILE *F, type *tp, int pos)
1498 ident *id = get_enumeration_nameid(tp, pos);
1499 tarval *tv = get_enumeration_enum(tp, pos);
1501 tarval_snprintf(buf, sizeof(buf), tv);
1502 fprintf (F, "node: {title: \"");
1503 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1504 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1505 fprintf (F, "label: ");
1506 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1507 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1510 /* dumps a type or entity and it's edges. */
1512 dump_type_info(type_or_ent *tore, void *env) {
1514 int i = 0; /* to shutup gcc */
1516 /* dump this type or entity */
1518 switch (get_kind(tore)) {
1521 entity *ent = (entity *)tore;
1524 dump_entity_node(F, ent, 0);
1526 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1527 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1528 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1529 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1530 if (is_Class_type(get_entity_owner(ent))) {
1531 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1532 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1534 /* attached subgraphs */
1535 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1536 if (is_atomic_entity(ent)) {
1537 value = get_atomic_ent_value(ent);
1539 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1540 /* DDMN(value); $$$ */
1541 dump_const_expression(F, value);
1544 if (is_compound_entity(ent)) {
1545 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1546 value = get_compound_ent_value(ent, i);
1548 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1549 dump_const_expression(F, value);
1550 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1552 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1553 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1554 get_compound_ent_value_member(ent, i), i);
1563 type *tp = (type *)tore;
1564 print_type_node(F, tp);
1565 /* and now the edges */
1566 switch (get_type_tpop_code(tp)) {
1569 for (i=0; i < get_class_n_supertypes(tp); i++)
1570 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1571 for (i=0; i < get_class_n_members(tp); i++)
1572 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1576 for (i=0; i < get_struct_n_members(tp); i++)
1577 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1581 for (i = 0; i < get_method_n_params(tp); i++)
1582 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1583 for (i = 0; i < get_method_n_ress(tp); i++)
1584 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1588 for (i = 0; i < get_union_n_members(tp); i++)
1589 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1593 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1594 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1595 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1596 ir_node *upper = get_array_upper_bound(tp, i);
1597 ir_node *lower = get_array_lower_bound(tp, i);
1598 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1599 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1600 dump_const_expression(F, upper);
1601 dump_const_expression(F, lower);
1605 case tpo_enumeration:
1607 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1608 dump_enum_item(F, tp, i);
1609 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1614 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1622 break; /* case k_type */
1625 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1627 } /* switch kind_or_entity */
1630 typedef struct _h_env {
1635 /** For dumping class hierarchies.
1636 * Dumps a class type node and a superclass edge.
1637 * If env->dump_ent dumps entities of classes and overwrites edges.
1640 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1643 int i = 0; /* to shutup gcc */
1645 /* dump this type or entity */
1646 switch (get_kind(tore)) {
1648 entity *ent = (entity *)tore;
1649 if (get_entity_owner(ent) == get_glob_type()) break;
1650 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1651 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1653 dump_entity_node(F, ent, 0);
1655 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1656 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1657 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1659 } break; /* case k_entity */
1662 type *tp = (type *)tore;
1663 if (tp == get_glob_type()) break;
1664 switch (get_type_tpop_code(tp)) {
1666 print_type_node(F, tp);
1667 /* and now the edges */
1668 for (i=0; i < get_class_n_supertypes(tp); i++)
1670 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1676 break; /* case k_type */
1679 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1681 } /* switch kind_or_entity */
1684 /*******************************************************************/
1685 /* dump analysis information that is expressed in graph terms. */
1686 /*******************************************************************/
1688 /* dump out edges */
1690 dump_out_edge(ir_node *n, void *env) {
1693 for (i = 0; i < get_irn_n_outs(n); i++) {
1694 assert(get_irn_out(n, i));
1695 fprintf (F, "edge: {sourcename: \"");
1697 fprintf (F, "\" targetname: \"");
1698 PRINT_NODEID(get_irn_out(n, i));
1699 fprintf (F, "\" color: red linestyle: dashed");
1705 dump_loop_label(FILE *F, ir_loop *loop) {
1706 fprintf (F, "loop %d, %d sons, %d nodes",
1707 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1710 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1711 fprintf (F, " info1: \"");
1712 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1713 #if DEBUG_libfirm /* GL @@@ debug analyses */
1714 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1720 dump_loop_node(FILE *F, ir_loop *loop) {
1721 fprintf (F, "node: {title: \"");
1723 fprintf (F, "\" label: \"");
1724 dump_loop_label(F, loop);
1726 dump_loop_info(F, loop);
1732 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1734 fprintf (F, "edge: {sourcename: \"");
1736 fprintf (F, "\" targetname: \"");
1737 PRINT_NODEID(get_loop_node(loop, i));
1738 fprintf (F, "\" color: green");
1743 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1745 fprintf (F, "edge: {sourcename: \"");
1747 fprintf (F, "\" targetname: \"");
1748 PRINT_LOOPID(get_loop_son(loop, i));
1749 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1750 get_loop_element_pos(loop, get_loop_son(loop, i)));
1754 void dump_loops(FILE *F, ir_loop *loop) {
1756 /* dump this loop node */
1757 dump_loop_node(F, loop);
1759 /* dump edges to nodes in loop -- only if it is a real loop */
1760 if (get_loop_depth(loop) != 0) {
1761 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1762 dump_loop_node_edge(F, loop, i);
1765 for (i = 0; i < get_loop_n_sons(loop); i++) {
1766 dump_loops(F, get_loop_son(loop, i));
1767 dump_loop_son_edge(F, loop, i);
1772 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1773 ir_graph *rem = current_ir_graph;
1774 current_ir_graph = irg;
1776 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1778 current_ir_graph = rem;
1783 * dumps the VCG header
1785 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1794 if (!orientation) orientation = "bottom_to_top";
1798 "graph: { title: \"ir graph of %s\"\n"
1799 "display_edge_labels: %s\n"
1800 "layoutalgorithm: mindepth\n"
1801 "manhattan_edges: yes\n"
1802 "port_sharing: no\n"
1804 "classname 1: \"intrablock Data\"\n"
1805 "classname 16: \"interblock Data\"\n"
1806 "classname 2: \"Block\"\n"
1807 "classname 13: \"Control Flow\"\n"
1808 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1809 "classname 14: \"intrablock Memory\"\n"
1810 "classname 17: \"interblock Memory\"\n"
1811 "classname 15: \"Dominators\"\n"
1812 "classname 3: \"Entity type\"\n"
1813 "classname 4: \"Entity owner\"\n"
1814 "classname 5: \"Method Param\"\n"
1815 "classname 6: \"Method Res\"\n"
1816 "classname 7: \"Super\"\n"
1817 "classname 8: \"Union\"\n"
1818 "classname 9: \"Points-to\"\n"
1819 "classname 10: \"Array Element Type\"\n"
1820 "classname 11: \"Overwrites\"\n"
1821 "classname 12: \"Member\"\n"
1822 "infoname 1: \"Attribute\"\n"
1823 "infoname 2: \"Verification errors\"\n",
1824 name, label, orientation);
1826 /* don't use all, the range is too whith/black. */
1830 "colorentry 100: 0 0 0\n"
1831 "colorentry 101: 20 0 0\n"
1832 "colorentry 102: 40 0 0\n"
1833 "colorentry 103: 60 0 0\n"
1834 "colorentry 104: 80 0 0\n"
1835 "colorentry 105: 100 0 0\n"
1836 "colorentry 106: 120 0 0\n"
1837 "colorentry 107: 140 0 0\n"
1838 "colorentry 108: 150 0 0\n"
1839 "colorentry 109: 180 0 0\n"
1840 "colorentry 110: 200 0 0\n"
1841 "colorentry 111: 220 0 0\n"
1842 "colorentry 112: 240 0 0\n"
1843 "colorentry 113: 255 0 0\n"
1844 "colorentry 113: 255 20 20\n"
1845 "colorentry 114: 255 40 40\n"
1846 "colorentry 115: 255 60 60\n"
1847 "colorentry 116: 255 80 80\n"
1848 "colorentry 117: 255 100 100\n"
1849 "colorentry 118: 255 120 120\n"
1850 "colorentry 119: 255 140 140\n"
1851 "colorentry 120: 255 150 150\n"
1852 "colorentry 121: 255 180 180\n"
1853 "colorentry 122: 255 200 200\n"
1854 "colorentry 123: 255 220 220\n"
1855 "colorentry 124: 255 240 240\n"
1856 "colorentry 125: 255 250 250\n"
1859 fprintf (F, "\n"); /* a separator */
1865 * @param irg The graph to be dumped
1866 * @param suffix1 first filename suffix
1867 * @param suffix2 second filename suffix
1869 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1871 const char *nm = get_irg_dump_name(irg);
1872 int len = strlen(nm), i, j;
1873 char *fname; /* filename to put the vcg information in */
1875 if (!suffix1) suffix1 = "";
1876 if (!suffix2) suffix2 = "";
1878 /* open file for vcg graph */
1879 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1881 /* strncpy (fname, nm, len); */ /* copy the filename */
1883 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1885 fname[j] = '@'; j++; fname[j] = '1'; j++;
1886 } else if (nm[i] == '@') {
1887 fname[j] = '@'; j++; fname[j] = '2'; j++;
1889 fname[j] = nm[i]; j++;
1893 strcat (fname, suffix1); /* append file suffix */
1894 strcat (fname, suffix2); /* append file suffix */
1895 strcat (fname, ".vcg"); /* append the .vcg suffix */
1897 /* vcg really expect only a <CR> at end of line, so
1898 * the "b"inary mode is what you mean (and even needed for Win32)
1900 F = fopen (fname, "wb"); /* open file for writing */
1902 panic("cannot open %s for writing (%m)", fname); /* not reached */
1912 * @param irg The graph to be dumped
1913 * @param suffix filename suffix
1915 FILE *vcg_open_name (const char *name, const char *suffix) {
1917 char *fname; /* filename to put the vcg information in */
1918 int i, j, len = strlen(name);
1920 if (!suffix) suffix = "";
1922 /** open file for vcg graph */
1923 fname = malloc (len * 2 + 5 + strlen(suffix));
1924 /* strcpy (fname, name);*/ /* copy the filename */
1926 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1927 if (name[i] == '/') {
1928 fname[j] = '@'; j++; fname[j] = '1'; j++;
1929 } else if (name[i] == '@') {
1930 fname[j] = '@'; j++; fname[j] = '2'; j++;
1932 fname[j] = name[i]; j++;
1936 strcat (fname, suffix);
1937 strcat (fname, ".vcg"); /* append the .vcg suffix */
1939 /* vcg really expect only a <CR> at end of line, so
1940 * the "b"inary mode is what you mean (and even needed for Win32)
1942 F = fopen (fname, "wb"); /* open file for writing */
1944 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1952 * Dumps the vcg file footer
1954 static INLINE void dump_vcg_footer (FILE *F) {
1959 * close the vcg file
1961 void vcg_close (FILE *F) {
1962 dump_vcg_footer(F); /* print footer */
1963 fclose (F); /* close vcg file */
1966 /************************************************************************/
1967 /************************************************************************/
1968 /* Routines that dump all or parts of the firm representation to a file */
1969 /************************************************************************/
1970 /************************************************************************/
1972 /************************************************************************/
1973 /* Dump ir graphs, different formats and additional information. */
1974 /************************************************************************/
1976 /** Routine to dump a graph, blocks as conventional nodes. */
1978 dump_ir_graph (ir_graph *irg, const char *suffix )
1983 rem = current_ir_graph;
1985 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
1987 current_ir_graph = irg;
1988 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1989 else suffix1 = "-pure";
1990 f = vcg_open(irg, suffix, suffix1);
1991 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1993 /* walk over the graph */
1994 /* dump_whole_node must be called in post visiting predecessors */
1995 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1997 /* dump the out edges in a separate walk */
1998 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1999 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2004 current_ir_graph = rem;
2007 /* Dump a firm graph without explicit block nodes. */
2008 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2014 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2017 if (get_interprocedural_view()) suffix1 = "-ip";
2019 f = vcg_open(irg, suffix, suffix1);
2020 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2022 construct_block_lists(irg);
2025 * If we are in the interprocedural view, we dump not
2026 * only the requested irg but also all irgs that can be reached
2029 for (i = 0; i < get_irp_n_irgs(); i++) {
2030 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2032 dump_graph_from_list(f, get_irp_irg(i));
2040 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2041 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2047 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2052 if (get_interprocedural_view()) suffix1 = "-ip";
2054 F = vcg_open(irg, suffix, suffix1);
2055 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2057 construct_extblock_lists(irg);
2059 fprintf(F, "graph: { title: \"");
2061 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2062 get_ent_dump_name(get_irg_entity(irg)));
2064 for (i = 0; i < get_irp_n_irgs(); i++) {
2065 ir_graph *irg = get_irp_irg(i);
2066 list_tuple *lists = ird_get_irg_link(irg);
2069 /* dump the extended blocks first */
2070 if (ARR_LEN(lists->extbb_list)) {
2071 ird_set_irg_link(irg, lists->extbb_list);
2072 dump_extblock_graph(F, irg);
2075 /* we may have blocks without extended blocks, bad for instance */
2076 if (ARR_LEN(lists->blk_list)) {
2077 ird_set_irg_link(irg, lists->blk_list);
2078 dump_block_graph(F, irg);
2081 DEL_ARR_F(lists->extbb_list);
2082 DEL_ARR_F(lists->blk_list);
2087 /* Close the vcg information for the irg */
2088 fprintf(F, "}\n\n");
2094 /* dumps a graph with type information */
2096 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2099 ir_graph *rem = current_ir_graph;
2102 /* if a filter is set, dump only the irg's that match the filter */
2103 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2106 current_ir_graph = irg;
2108 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2109 else suffix1 = "-pure-wtypes";
2110 f = vcg_open(irg,suffix, suffix1);
2111 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2113 /* dump common ir graph */
2114 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2115 /* dump type info */
2116 type_walk_irg(irg, dump_type_info, NULL, f);
2117 inc_irg_visited(get_const_code_irg());
2118 /* dump edges from graph to type info */
2119 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2122 current_ir_graph = rem;
2126 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2131 ir_graph *rem = current_ir_graph;
2133 /* if a filter is set, dump only the irg's that match the filter */
2134 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2137 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2138 else suffix1 = "-wtypes";
2139 f = vcg_open(irg, suffix, suffix1);
2140 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2142 /* dump common blocked ir graph */
2143 construct_block_lists(irg);
2145 for (i = 0; i < get_irp_n_irgs(); i++) {
2146 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2148 dump_graph_from_list(f, get_irp_irg(i));
2153 /* dump type info */
2154 current_ir_graph = irg;
2155 type_walk_irg(irg, dump_type_info, NULL, f);
2156 inc_irg_visited(get_const_code_irg());
2158 /* dump edges from graph to type info */
2159 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2161 current_ir_graph = rem;
2165 /*---------------------------------------------------------------------*/
2166 /* The following routines dump a control flow graph. */
2167 /*---------------------------------------------------------------------*/
2170 dump_block_to_cfg(ir_node *block, void *env) {
2175 if (is_Block(block)) {
2176 /* This is a block. Dump a node for the block. */
2177 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2178 fprintf (F, "\" label: \"");
2179 if (block == get_irg_start_block(get_irn_irg(block)))
2180 fprintf(F, "Start ");
2181 if (block == get_irg_end_block(get_irn_irg(block)))
2184 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2185 PRINT_NODEID(block);
2187 fprintf(F, "info1:\"");
2190 if (dump_dominator_information_flag) {
2191 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2192 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2193 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2196 /* show arity and possible Bad predecessors of the block */
2197 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2198 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2199 ir_node *pred = get_Block_cfgpred(block, i);
2202 fprintf(F, "Bad pred at pos: ");
2203 fprintf(F, "%d ", i);
2210 /* the generic version. */
2211 dump_irnode_to_file(F, block);
2213 /* Check whether we have bad predecessors to color the block. */
2214 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2215 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2219 fprintf (F, "\""); /* closing quote of info */
2221 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2222 (block == get_irg_end_block(get_irn_irg(block))) )
2223 fprintf(F, " color:blue ");
2225 fprintf(F, " color:yellow ");
2228 /* Dump the edges */
2229 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2230 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2231 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2232 fprintf (F, "edge: { sourcename: \"");
2233 PRINT_NODEID(block);
2234 fprintf (F, "\" targetname: \"");
2236 fprintf (F, "\"}\n");
2239 /* Dump dominator edge */
2240 if (dump_dominator_information_flag && get_Block_idom(block)) {
2241 pred = get_Block_idom(block);
2242 fprintf (F, "edge: { sourcename: \"");
2243 PRINT_NODEID(block);
2244 fprintf (F, "\" targetname: \"");
2246 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2252 dump_cfg (ir_graph *irg, const char *suffix)
2255 ir_graph *rem = current_ir_graph;
2256 int ddif = dump_dominator_information_flag;
2257 int ipv = get_interprocedural_view();
2259 /* if a filter is set, dump only the irg's that match the filter */
2260 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2263 current_ir_graph = irg;
2265 f = vcg_open(irg, suffix, "-cfg");
2266 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2269 printf("Warning: dumping cfg not in interprocedural view!\n");
2270 set_interprocedural_view(false);
2273 if (get_irg_dom_state(irg) != dom_consistent)
2274 dump_dominator_information_flag = 0;
2276 /* walk over the blocks in the graph */
2277 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2278 dump_node(f, get_irg_bad(irg));
2280 dump_dominator_information_flag = ddif;
2281 set_interprocedural_view(ipv);
2283 current_ir_graph = rem;
2287 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2288 if (pset_find_ptr(mark_set, n)) return;
2290 pset_insert_ptr(mark_set, n);
2293 int i, start = is_Block(n) ? 0 : -1;
2294 dump_whole_node(n, F);
2295 for (i = start; i < get_irn_arity(n); ++i)
2296 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2299 /* Don't dump edges to nodes further out. These might be edges to
2300 nodes we already dumped, if there is a shorter path to these. */
2304 static int subgraph_counter = 0;
2305 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2308 pset *mark_set = pset_new_ptr(1);
2309 sprintf(buf, "-subg_%03d", subgraph_counter++);
2310 F = vcg_open(get_irn_irg(root), suffix, buf);
2311 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2312 descend_and_dump(F, root, depth, mark_set);
2318 static int weight_overall(int rec, int loop) {
2319 return 2*rec + loop;
2322 static int compute_color (int my, int max) {
2329 /* if small, scale to the full color range. */
2331 my = my * (n_colors/max);
2333 step = 1 + (max / n_colors);
2337 return base_color + n_colors - color;
2340 static int get_entity_color(entity *ent) {
2341 ir_graph *irg = get_entity_irg(ent);
2345 int rec_depth = get_irg_recursion_depth(irg);
2346 int loop_depth = get_irg_loop_depth(irg);
2347 int overall_depth = weight_overall(rec_depth, loop_depth);
2349 int max_rec_depth = irp->max_callgraph_recursion_depth;
2350 int max_loop_depth = irp->max_callgraph_loop_depth;
2351 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2353 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2354 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2355 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2357 return my_overall_color;
2361 void dump_callgraph(const char *suffix) {
2363 int i, n_irgs = get_irp_n_irgs();
2364 int rem = edge_label;
2366 //ident *prefix = new_id_from_str("java/");
2368 F = vcg_open_name("Callgraph", suffix);
2369 dump_vcg_header(F, "Callgraph", NULL);
2371 for (i = 0; i < n_irgs; ++i) {
2372 ir_graph *irg = get_irp_irg(i);
2373 entity *ent = get_irg_entity(irg);
2374 int j, n_callees = get_irg_n_callees(irg);
2376 /* Do not dump runtime system. */
2377 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2379 dump_entity_node(F, ent, get_entity_color(ent));
2380 for (j = 0; j < n_callees; ++j) {
2381 entity *c = get_irg_entity(get_irg_callee(irg, j));
2382 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2383 int be = is_irg_callee_backedge(irg, j);
2386 "label:\"recursion %d\" color: %d" :
2387 "label:\"calls %d\" color: %d";
2388 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2396 /* Dump all irgs in interprocedural view to a single file. */
2397 void dump_all_cg_block_graph(const char *suffix) {
2400 int rem_view = get_interprocedural_view();
2401 set_interprocedural_view(true);
2403 f = vcg_open_name("All_graphs", suffix);
2404 dump_vcg_header(f, "All_graphs", NULL);
2406 /* collect nodes in all irgs reachable in call graph*/
2407 for (i = 0; i < get_irp_n_irgs(); i++)
2408 ird_set_irg_link(get_irp_irg(i), NULL);
2410 cg_walk(clear_link, collect_node, NULL);
2412 /* dump all graphs */
2413 for (i = 0; i < get_irp_n_irgs(); i++) {
2414 current_ir_graph = get_irp_irg(i);
2415 assert(ird_get_irg_link(current_ir_graph));
2416 dump_graph_from_list(f, current_ir_graph);
2417 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2421 set_interprocedural_view(rem_view);
2424 /*---------------------------------------------------------------------*/
2425 /* the following routines dumps type information without any ir nodes. */
2426 /*---------------------------------------------------------------------*/
2429 dump_type_graph (ir_graph *irg, const char *suffix)
2433 rem = current_ir_graph;
2435 /* if a filter is set, dump only the irg's that match the filter */
2436 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2438 current_ir_graph = irg;
2440 f = vcg_open(irg, suffix, "-type");
2441 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2443 /* walk over the blocks in the graph */
2444 type_walk_irg(irg, dump_type_info, NULL, f);
2445 /* The walker for the const code can be called several times for the
2446 same (sub) expression. So that no nodes are dumped several times
2447 we decrease the visited flag of the corresponding graph after each
2448 walk. So now increase it finally. */
2449 inc_irg_visited(get_const_code_irg());
2452 current_ir_graph = rem;
2456 dump_all_types (const char *suffix)
2458 FILE *f = vcg_open_name("All_types", suffix);
2459 dump_vcg_header(f, "All_types", NULL);
2460 type_walk(dump_type_info, NULL, f);
2461 inc_irg_visited(get_const_code_irg());
2466 dump_class_hierarchy (bool entities, const char *suffix)
2468 FILE *f = vcg_open_name("class_hierarchy", suffix);
2472 dump_vcg_header(f, "class_hierarchy", NULL);
2477 type_walk(dump_class_hierarchy_node, NULL, &env);
2481 /*---------------------------------------------------------------------*/
2482 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2484 /* dump_ir_block_graph */
2486 /* dump_type_graph */
2487 /* dump_ir_graph_w_types */
2488 /*---------------------------------------------------------------------*/
2490 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2491 int i, n_irgs = get_irp_n_irgs();
2492 for (i = 0; i < n_irgs; ++i) {
2493 dmp_grph(get_irp_irg(i), suffix);
2498 /*--------------------------------------------------------------------------------*
2499 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2500 * packed together in one subgraph/box *
2501 *--------------------------------------------------------------------------------*/
2503 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2504 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2506 ir_loop *son = NULL;
2508 /* Dump a new loop node. */
2509 dump_loop_node(F, loop);
2511 /* Dump the loop elements. */
2513 for(i = 0; i < get_loop_n_elements(loop); i++) {
2514 le = get_loop_element(loop, i);
2516 if (get_kind(son) == k_ir_loop) {
2518 /* We are a loop son -> Recurse */
2520 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2521 fprintf(F, "\" }\n");
2522 fprintf (F, "edge: {sourcename: \"");
2524 fprintf (F, "\" targetname: \"");
2526 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2527 loop_node_started = 0;
2529 dump_loop_son_edge(F, loop, son_number++);
2530 dump_loops_standalone(F, son);
2531 } else if (get_kind(son) == k_ir_node) {
2532 /* We are a loop node -> Collect firm nodes */
2534 ir_node *n = le.node;
2537 if (!loop_node_started) {
2538 /* Start a new node which contains all firm nodes of the current loop */
2539 fprintf (F, "node: { title: \"");
2541 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2542 loop_node_started = 1;
2548 bad |= dump_node_label(F, n);
2549 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2550 if (has_backedges(n)) fprintf(F, "\t loop head!");
2551 } else { /* for callgraph loop tree */
2553 assert(get_kind(son) == k_ir_graph);
2555 /* We are a loop node -> Collect firm graphs */
2556 n = (ir_graph *)le.node;
2557 if (!loop_node_started) {
2558 /* Start a new node which contains all firm nodes of the current loop */
2559 fprintf (F, "node: { title: \"");
2561 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2562 loop_node_started = 1;
2567 fprintf (F, " %s", get_irg_dump_name(n));
2568 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2572 if (loop_node_started) {
2573 fprintf(F, "\" }\n");
2574 fprintf (F, "edge: {sourcename: \"");
2576 fprintf (F, "\" targetname: \"");
2578 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2579 loop_node_started = 0;
2583 void dump_loop_tree(ir_graph *irg, const char *suffix)
2586 ir_graph *rem = current_ir_graph;
2587 int el_rem = edge_label;
2590 /* if a filter is set, dump only the irg's that match the filter */
2591 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2593 current_ir_graph = irg;
2595 f = vcg_open(irg, suffix, "-looptree");
2596 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2598 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2602 edge_label = el_rem;
2603 current_ir_graph = rem;
2606 void dump_callgraph_loop_tree(const char *suffix) {
2608 F = vcg_open_name("Callgraph_looptree", suffix);
2609 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2610 dump_loops_standalone(F, irp->outermost_cg_loop);
2615 /*-----------------------------------------------------------------------------*/
2616 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2617 /*-----------------------------------------------------------------------------*/
2619 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2620 int i, son_number = 0, node_number = 0;
2622 if (dump_loop_information_flag) dump_loop_node(F, loop);
2624 for (i = 0; i < get_loop_n_elements(loop); i++) {
2625 loop_element le = get_loop_element(loop, i);
2626 if (*(le.kind) == k_ir_loop) {
2627 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2629 collect_nodeloop(F, le.son, loopnodes);
2631 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2632 eset_insert(loopnodes, le.node);
2637 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2640 for(i = 0; i < get_loop_n_elements(loop); i++) {
2641 loop_element le = get_loop_element(loop, i);
2642 if (*(le.kind) == k_ir_loop) {
2644 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2646 if (is_Block(le.node)) start = 0; else start = -1;
2647 for (j = start; j < get_irn_arity(le.node); j++) {
2648 ir_node *pred = get_irn_n(le.node, j);
2649 if (!eset_contains(loopnodes, pred)) {
2650 eset_insert(extnodes, pred);
2651 if (!is_Block(pred)) {
2652 pred = get_nodes_block(pred);
2653 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2661 void dump_loop(ir_loop *l, const char *suffix) {
2664 eset *loopnodes = eset_create();
2665 eset *extnodes = eset_create();
2668 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2669 F = vcg_open_name (name, suffix);
2670 dump_vcg_header(F, name, NULL);
2672 /* collect all nodes to dump */
2673 collect_nodeloop(F, l, loopnodes);
2674 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2676 /* build block lists */
2677 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2678 set_irn_link(n, NULL);
2679 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2680 set_irn_link(n, NULL);
2681 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2683 b = get_nodes_block(n);
2684 set_irn_link(n, get_irn_link(b));
2687 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2689 b = get_nodes_block(n);
2690 set_irn_link(n, get_irn_link(b));
2694 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2696 fprintf(F, "graph: { title: \"");
2698 fprintf(F, "\" label: \"");
2699 dump_node_opcode(F, b);
2700 fprintf (F, " %ld", get_irn_node_nr(b));
2701 fprintf(F, "\" status:clustered color:yellow\n");
2703 /* dump the blocks edges */
2704 dump_ir_data_edges(F, b);
2706 /* dump the nodes that go into the block */
2707 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2708 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2710 overrule_nodecolor = NULL;
2711 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2714 /* Close the vcg information for the block */
2716 dump_const_node_local(F, b);
2719 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2721 fprintf(F, "graph: { title: \"");
2723 fprintf(F, "\" label: \"");
2724 dump_node_opcode(F, b);
2725 fprintf (F, " %ld", get_irn_node_nr(b));
2726 fprintf(F, "\" status:clustered color:lightblue\n");
2728 /* dump the nodes that go into the block */
2729 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2730 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2732 overrule_nodecolor = NULL;
2733 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2736 /* Close the vcg information for the block */
2738 dump_const_node_local(F, b);
2742 eset_destroy(loopnodes);
2743 eset_destroy(extnodes);