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 /** Creates the link attribut map. */
244 static void init_irdump(void) {
245 /* We need a new, empty map. */
246 if (irdump_link_map) pmap_destroy(irdump_link_map);
247 irdump_link_map = pmap_create();
248 dump_file_filter_id = new_id_from_str("");
251 * Returns the private link field.
253 static void *ird_get_irn_link(ir_node *n) {
255 if (!irdump_link_map) return NULL;
257 if (pmap_contains(irdump_link_map, (void *)n))
258 res = pmap_get(irdump_link_map, (void *)n);
263 * Sets the private link field.
265 static void ird_set_irn_link(ir_node *n, void *x) {
266 if (!irdump_link_map) init_irdump();
267 pmap_insert(irdump_link_map, (void *)n, x);
271 * Gets the private link field of an irg.
273 static void *ird_get_irg_link(ir_graph *irg) {
275 if (!irdump_link_map) return NULL;
277 if (pmap_contains(irdump_link_map, (void *)irg))
278 res = pmap_get(irdump_link_map, (void *)irg);
283 * Sets the private link field of an irg.
285 static void ird_set_irg_link(ir_graph *irg, void *x) {
286 if (!irdump_link_map) init_irdump();
287 pmap_insert(irdump_link_map, (void *)irg, x);
291 * Walker, clears the private link field.
293 static void clear_link(ir_node * node, void * env) {
294 ird_set_irn_link(node, NULL);
298 * If the entity has a ld_name, returns it, else returns the name of the entity.
300 const char *get_ent_dump_name(entity *ent) {
302 return "<NULL entity>";
303 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
304 if (ent->ld_name) return get_id_str(ent->ld_name);
305 return get_id_str(ent->name);
308 /* Returns the name of an IRG. */
309 const char *get_irg_dump_name(ir_graph *irg) {
310 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
311 entity *ent = get_irg_entity(irg);
312 return get_ent_dump_name(ent);
316 * Returns non-zero if a node is in floating state.
318 static int node_floats(ir_node *n) {
319 return ((get_irn_pinned(n) == op_pin_state_floats) &&
320 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
324 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
326 static void collect_node(ir_node * node, void *env) {
329 || get_irn_op(node) == op_Bad
330 || get_irn_op(node) == op_Unknown
331 || get_irn_op(node) == op_NoMem) {
332 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
333 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
334 ARR_APP1(ir_node *, arr, node);
335 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
337 ir_node * block = get_nodes_block(node);
340 /* this node is in a Bad block, so we must place it into the graph's list */
341 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
342 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
343 ARR_APP1(ir_node *, arr, node);
344 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
347 ird_set_irn_link(node, ird_get_irn_link(block));
348 ird_set_irn_link(block, node);
353 /** Construct lists to walk ir block-wise.
355 * Collects all blocks, nodes not op_pin_state_pinned,
356 * Bad, NoMem and Unknown into a flexible array in link field of
357 * irg they belong to. Sets the irg link field to NULL in all
358 * graphs not visited.
359 * Free the list with DEL_ARR_F().
361 static ir_node **construct_block_lists(ir_graph *irg) {
362 int i, rem_view = get_interprocedural_view();
363 ir_graph *rem = current_ir_graph;
364 current_ir_graph = irg;
366 for (i = 0; i < get_irp_n_irgs(); i++)
367 ird_set_irg_link(get_irp_irg(i), NULL);
369 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
371 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
372 set_interprocedural_view(false);
374 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
375 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
376 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
377 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
379 set_interprocedural_view(rem_view);
381 current_ir_graph = rem;
382 return ird_get_irg_link(irg);
385 typedef struct _list_tuple {
387 ir_extblk **extbb_list;
390 /** Construct lists to walk ir extended block-wise.
391 * Free the lists in the tuple with DEL_ARR_F().
393 static list_tuple *construct_extblock_lists(ir_graph *irg) {
394 ir_node **blk_list = construct_block_lists(irg);
396 ir_graph *rem = current_ir_graph;
397 list_tuple *lists = xmalloc(sizeof(*lists));
399 current_ir_graph = irg;
401 lists->blk_list = NEW_ARR_F(ir_node *, 0);
402 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
404 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
407 if (is_Block(blk_list[i])) {
408 ext = get_Block_extbb(blk_list[i]);
410 if (extbb_not_visited(ext)) {
411 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
412 mark_extbb_visited(ext);
416 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
419 current_ir_graph = rem;
421 ird_set_irg_link(irg, lists);
425 /*******************************************************************/
426 /* flags to steer output */
427 /*******************************************************************/
429 /** A compiler option to turn off edge labels */
430 static int edge_label = 1;
431 /** A compiler option to turn off dumping values of constant entities */
432 static int const_entities = 1;
433 /** A compiler option to dump the keep alive edges */
434 static int dump_keepalive = 0;
435 /** Compiler options to dump analysis information in dump_ir_graph */
436 int dump_out_edge_flag = 0;
437 int dump_dominator_information_flag = 0;
438 int dump_loop_information_flag = 0;
439 int dump_backedge_information_flag = 1;
440 int dump_const_local = 0;
441 bool opt_dump_analysed_type_info = 1;
442 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
444 static const char *overrule_nodecolor = NULL;
446 /** An additional edge hook. */
447 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
449 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
451 dump_node_edge_hook = func;
454 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
456 return dump_node_edge_hook;
460 /** The vcg attribute hook. */
461 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
464 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
465 dump_node_vcgattr_hook = hook;
468 INLINE bool get_opt_dump_const_local(void) {
469 if (!dump_out_edge_flag && !dump_loop_information_flag)
470 return dump_const_local;
475 void only_dump_method_with_name(ident *name) {
476 dump_file_filter_id = name;
479 ident *get_dump_file_filter_ident(void) {
480 return dump_file_filter_id;
483 /** Returns true if dump file filter is not set, or if it is a
485 int is_filtered_dump_name(ident *name) {
486 if (!dump_file_filter_id) return 1;
487 return id_is_prefix(dump_file_filter_id, name);
490 /* To turn off display of edge labels. Edge labels offen cause xvcg to
491 abort with a segmentation fault. */
492 void turn_off_edge_labels(void) {
496 void dump_consts_local(bool b) {
497 dump_const_local = b;
500 void dump_constant_entity_values(bool b) {
504 void dump_keepalive_edges(bool b) {
508 bool get_opt_dump_keepalive_edges(void) {
509 return dump_keepalive;
512 void dump_out_edges(bool b) {
513 dump_out_edge_flag = b;
516 void dump_dominator_information(bool b) {
517 dump_dominator_information_flag = b;
520 void dump_loop_information(bool b) {
521 dump_loop_information_flag = b;
524 void dump_backedge_information(bool b) {
525 dump_backedge_information_flag = b;
528 /* Dump the information of type field specified in ana/irtypeinfo.h.
529 * If the flag is set, the type name is output in [] in the node label,
530 * else it is output as info.
532 void set_opt_dump_analysed_type_info(bool b) {
533 opt_dump_analysed_type_info = b;
536 void dump_pointer_values_to_info(bool b) {
537 opt_dump_pointer_values_to_info = b;
540 /*-----------------------------------------------------------------*/
541 /* Routines to dump information about a single ir node. */
542 /*-----------------------------------------------------------------*/
545 * dump the name of a node n to the File F.
548 dump_node_opcode(FILE *F, ir_node *n)
552 switch(get_irn_opcode(n)) {
557 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
558 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
563 if (get_SymConst_kind(n) == symconst_addr_name) {
564 /* don't use get_SymConst_ptr_info as it mangles the name. */
565 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
566 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
567 assert(get_SymConst_entity(n));
568 assert(is_entity(get_SymConst_entity(n)));
569 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
571 assert(get_kind(get_SymConst_type(n)) == k_type);
572 assert(get_type_ident(get_SymConst_type(n)));
573 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
574 if (get_SymConst_kind(n) == symconst_type_tag)
582 if (!get_interprocedural_view())
589 ir_node *pred = get_Proj_pred(n);
591 if (get_irn_opcode(pred) == iro_Cond
592 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
593 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
594 fprintf (F, "defProj");
596 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
597 * fprintf (F, "Arg");
606 if (get_interprocedural_view()) {
607 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
612 case iro_CallBegin: {
613 ir_node *addr = get_CallBegin_ptr(n);
615 if (get_irn_op(addr) == op_Sel)
616 ent = get_Sel_entity(addr);
617 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
618 ent = get_SymConst_entity(addr);
619 fprintf (F, "%s", get_irn_opname(n));
620 if (ent) fprintf (F, " %s", get_entity_name(ent));
624 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
629 fprintf (F, "%s", get_irn_opname(n));
637 * Dump the mode of a node n to a file F.
638 * Ignore modes that are "always known".
641 dump_node_mode(FILE *F, ir_node *n)
644 opcode iro = get_irn_opcode(n);
657 ir_mode *mode = get_irn_mode(n);
659 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
660 (mode != mode_T || iro == iro_Proj))
661 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
669 * Dump the type of a node n to a file F if it's known.
671 static int dump_node_typeinfo(FILE *F, ir_node *n) {
674 if (opt_dump_analysed_type_info) {
675 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
676 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
677 type *tp = get_irn_typeinfo_type(n);
678 if (tp != firm_none_type)
679 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
688 * Dump additional node attributes of some nodes to a file F.
691 dump_node_nodeattr(FILE *F, ir_node *n)
695 switch (get_irn_opcode(n)) {
697 if (false && get_interprocedural_view()) {
698 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
702 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
703 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
705 fprintf (F, "%ld ", get_Proj_proj(n));
709 fprintf (F, "%ld ", get_Filter_proj(n));
712 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
715 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
718 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
729 #include "execution_frequency.h"
730 #include "callgraph.h"
732 void dump_node_ana_vals(FILE *F, ir_node *n) {
734 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
735 get_irn_exec_freq(n),
736 get_irg_method_execution_frequency(get_irn_irg(n)),
737 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
738 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
743 /* Dumps a node label without the enclosing ". */
744 int dump_node_label(FILE *F, ir_node *n) {
747 bad |= dump_node_opcode(F, n);
748 bad |= dump_node_mode(F, n);
750 bad |= dump_node_typeinfo(F, n);
751 bad |= dump_node_nodeattr(F, n);
752 fprintf(F, "%ld", get_irn_node_nr(n));
759 * Dumps the attributes of a node n into the file F.
760 * Currently this is only the color of a node.
762 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
767 fprintf(F, "color: red");
771 if (dump_node_vcgattr_hook)
772 if (dump_node_vcgattr_hook(F, node, local))
775 n = local ? local : node;
777 switch (get_irn_opcode(n)) {
784 fprintf (F, "color: blue");
787 if (is_Block_dead(n))
788 fprintf (F, "color: lightred");
790 fprintf (F, "color: lightyellow");
793 fprintf (F, "color: green");
799 fprintf (F, "color: yellow");
802 PRINT_DEFAULT_NODE_ATTR;
805 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
810 * Dump the node information of a node n to a file F.
812 static INLINE int dump_node_info(FILE *F, ir_node *n)
814 fprintf (F, " info1: \"");
815 bad = dump_irnode_to_file(F, n);
821 * checks whether a node is "constant-like" ie can be treated "block-less"
824 bool is_constlike_node(ir_node *n) {
825 ir_op *op = get_irn_op(n);
826 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
830 /** outputs the predecessors of n, that are constants, local. I.e.,
831 generates a copy of the constant predecessors for each node called with. */
832 static void dump_const_node_local(FILE *F, ir_node *n) {
834 if (!get_opt_dump_const_local()) return;
836 /* Use visited flag to avoid outputting nodes twice.
837 initialize it first. */
838 for (i = 0; i < get_irn_arity(n); i++) {
839 ir_node *con = get_irn_n(n, i);
840 if (is_constlike_node(con)) {
841 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
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) && irn_not_visited(con)) {
850 mark_irn_visited(con);
851 /* Generate a new name for the node by appending the names of
853 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
854 fprintf(F, " label: \"");
855 bad |= dump_node_label(F, con);
857 bad |= dump_node_info(F, con);
858 dump_node_vcgattr(F, n, con, bad);
864 /** If the block of an edge is a const_like node, dump it local with an edge */
865 static void dump_const_block_local(FILE *F, ir_node *n) {
868 if (!get_opt_dump_const_local()) return;
870 blk = get_nodes_block(n);
871 if (is_constlike_node(blk)) {
874 /* Generate a new name for the node by appending the names of
876 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
877 fprintf(F, "\" label: \"");
878 bad |= dump_node_label(F, blk);
880 bad |= dump_node_info(F, blk);
881 dump_node_vcgattr(F, n, blk, bad);
884 fprintf (F, "edge: { sourcename: \"");
886 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
887 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
892 * prints the error message of a node to a file F as info2.
894 static void INLINE print_node_error(FILE *F, const char *err_msg)
899 fprintf (F, " info2: \"%s\"", err_msg);
905 static void dump_node(FILE *F, ir_node *n)
910 if (get_opt_dump_const_local() && is_constlike_node(n))
914 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
916 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
917 bad |= dump_node_label(F, n);
918 dump_node_ana_vals(F, n);
919 //dump_node_ana_info(F, n);
921 bad |= dump_node_info(F, n);
922 print_node_error(F, p);
923 dump_node_vcgattr(F, n, NULL, bad);
925 dump_const_node_local(F, n);
927 if(dump_node_edge_hook)
928 dump_node_edge_hook(F, n);
930 dump_irn_chi_term(F, n);
931 dump_irn_state(F, n);
935 /** dump the edge to the block this node belongs to */
937 dump_ir_block_edge(FILE *F, ir_node *n) {
938 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
939 if (is_no_Block(n)) {
940 ir_node *block = get_nodes_block(n);
942 if (get_opt_dump_const_local() && is_constlike_node(block)) {
943 dump_const_block_local(F, n);
946 fprintf (F, "edge: { sourcename: \"");
948 fprintf (F, "\" targetname: ");
949 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
950 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
956 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
957 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
958 fprintf (F, INTRA_DATA_EDGE_ATTR);
960 fprintf (F, INTER_DATA_EDGE_ATTR);
964 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
965 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
966 fprintf (F, INTRA_MEM_EDGE_ATTR);
968 fprintf (F, INTER_MEM_EDGE_ATTR);
972 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
975 if (dump_backedge_information_flag && is_backedge(from, to))
976 fprintf (F, BACK_EDGE_ATTR);
978 switch (get_irn_opcode(from)) {
980 fprintf (F, CF_EDGE_ATTR);
982 case iro_Start: break;
985 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
986 fprintf (F, CF_EDGE_ATTR);
987 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
988 fprintf (F, INTER_MEM_EDGE_ATTR);
996 print_data_edge_vcgattr(F, from, to);
1001 print_mem_edge_vcgattr(F, from, to);
1003 print_data_edge_vcgattr(F, from, to);
1007 print_data_edge_vcgattr(F, from, to);
1012 print_mem_edge_vcgattr(F, from, to);
1014 print_data_edge_vcgattr(F, from, to);
1021 print_data_edge_vcgattr(F, from, to);
1028 print_mem_edge_vcgattr(F, from, to);
1030 print_data_edge_vcgattr(F, from, to);
1042 print_data_edge_vcgattr(F, from, to);
1045 if (get_irn_modecode(from) == irm_M)
1046 fprintf (F, INTER_MEM_EDGE_ATTR);
1048 print_data_edge_vcgattr(F, from, to);
1055 print_mem_edge_vcgattr(F, from, to);
1057 print_data_edge_vcgattr(F, from, to);
1060 print_mem_edge_vcgattr(F, from, to);
1062 case iro_Tuple: break;
1065 switch (get_irn_modecode(from)) {
1067 fprintf (F, CF_EDGE_ATTR);
1070 fprintf (F, INTER_MEM_EDGE_ATTR);
1073 print_data_edge_vcgattr(F, from, to);
1077 case iro_Bad: break;
1078 case iro_Unknown: break;
1080 switch (get_irn_modecode(from)) {
1082 fprintf (F, INTRA_MEM_EDGE_ATTR);
1085 fprintf (F, CF_EDGE_ATTR);
1088 print_data_edge_vcgattr(F, from, to);
1096 /* dump edges to our inputs */
1098 dump_ir_data_edges(FILE *F, ir_node *n) {
1100 unsigned long visited = get_irn_visited(n);
1102 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1105 for (i = 0; i < get_irn_arity(n); i++) {
1106 ir_node * pred = get_irn_n(n, i);
1109 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1110 continue; /* pred not dumped */
1112 if (dump_backedge_information_flag && is_backedge(n, i))
1113 fprintf (F, "backedge: {sourcename: \"");
1115 fprintf (F, "edge: {sourcename: \"");
1117 fprintf (F, "\" targetname: ");
1118 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1119 PRINT_CONSTID(n, pred);
1121 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1123 fprintf (F, " label: \"%d\" ", i);
1124 print_edge_vcgattr(F, n, i);
1129 /** Dumps a node and its edges but not the block edge
1132 dump_node_wo_blockedge (ir_node *n, void *env) {
1135 dump_ir_data_edges(F, n);
1138 /** Dumps a node and its edges.
1141 dump_whole_node (ir_node *n, void *env) {
1143 dump_node_wo_blockedge(n, env);
1144 if (!node_floats(n)) dump_ir_block_edge(F, n);
1148 dump_const_node(ir_node *n, void *env) {
1149 if (is_Block(n)) return;
1150 dump_node_wo_blockedge(n, env);
1153 /***********************************************************************/
1154 /* the following routines dump the nodes/irgs bracketed to graphs. */
1155 /***********************************************************************/
1157 /** Dumps a constant expression as entity initializer, array bound ...
1159 static void dump_const_expression(FILE *F, ir_node *value) {
1160 ir_graph *rem = current_ir_graph;
1161 int rem_dump_const_local = dump_const_local;
1162 dump_const_local = 0;
1163 current_ir_graph = get_const_code_irg();
1164 irg_walk(value, dump_const_node, NULL, F);
1165 /* Decrease visited flag so that we walk with the same flag for the next
1166 expression. This guarantees that we don't dump the same node twice,
1167 as for const expressions cse is performed to save memory. */
1168 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1169 current_ir_graph = rem;
1170 dump_const_local = rem_dump_const_local;
1173 /** Dump a block as graph containing its nodes.
1175 * Expects to find nodes belonging to the block as list in its
1177 * Dumps the edges of all nodes including itself. */
1179 dump_whole_block(FILE *F, ir_node *block) {
1181 assert(is_Block(block));
1183 fprintf(F, "graph: { title: \"");
1184 PRINT_NODEID(block);
1185 fprintf(F, "\" label: \"");
1186 dump_node_label(F, block);
1188 if (get_opt_dump_abstvals())
1189 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1191 fprintf(F, "\" status:clustered color:%s \n",
1192 get_Block_matured(block) ? "yellow" : "red");
1194 /* dump the blocks edges */
1195 dump_ir_data_edges(F, block);
1197 /* dump the nodes that go into the block */
1198 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1200 dump_ir_data_edges(F, node);
1203 /* Close the vcg information for the block */
1205 dump_const_node_local(F, block);
1207 dump_irn_chi_term(F, block);
1212 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1213 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1215 dump_block_graph(FILE *F, ir_graph *irg) {
1217 ir_graph *rem = current_ir_graph;
1218 ir_node **arr = ird_get_irg_link(irg);
1219 current_ir_graph = irg;
1221 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1222 ir_node * node = arr[i];
1223 if (is_Block(node)) {
1224 /* Dumps the block and all the nodes in the block, which are to
1225 be found in Block->link. */
1226 dump_whole_block(F, node);
1228 /* Nodes that are not in a Block. */
1230 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1231 dump_const_block_local(F, node);
1233 dump_ir_data_edges(F, node);
1237 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1238 dump_loop_nodes_into_graph(F, irg);
1240 current_ir_graph = rem;
1243 /** Dumps an irg as a graph clustered by block nodes.
1244 * If interprocedural view edges can point to nodes out of this graph.
1246 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1248 fprintf(F, "graph: { title: \"");
1250 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1251 get_ent_dump_name(get_irg_entity(irg)));
1253 dump_block_graph(F, irg);
1255 /* Close the vcg information for the irg */
1256 fprintf(F, "}\n\n");
1259 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1260 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1262 dump_extblock_graph(FILE *F, ir_graph *irg) {
1264 ir_graph *rem = current_ir_graph;
1265 ir_extblk **arr = ird_get_irg_link(irg);
1266 current_ir_graph = irg;
1269 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1270 ir_extblk *extbb = arr[i];
1271 ir_node *leader = extbb->blks[0];
1274 fprintf(F, "graph: { title: \"");
1275 PRINT_EXTBBID(leader);
1276 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1277 get_irn_node_nr(leader));
1279 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1280 ir_node * node = extbb->blks[j];
1281 if (is_Block(node)) {
1282 /* Dumps the block and all the nodes in the block, which are to
1283 be found in Block->link. */
1284 dump_whole_block(F, node);
1286 /* Nodes that are not in a Block. */
1288 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1289 dump_const_block_local(F, node);
1291 dump_ir_data_edges(F, node);
1297 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1298 dump_loop_nodes_into_graph(F, irg);
1300 current_ir_graph = rem;
1305 /*******************************************************************/
1306 /* Basic type and entity nodes and edges. */
1307 /*******************************************************************/
1309 /** dumps the edges between nodes and their type or entity attributes. */
1310 static void dump_node2type_edges(ir_node *n, void *env)
1315 switch (get_irn_opcode(n)) {
1317 /* @@@ some consts have an entity */
1320 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1321 || (get_SymConst_kind(n) ==symconst_size))
1323 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1327 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1330 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1333 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1336 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1339 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1347 static int print_type_info(FILE *F, type *tp) {
1350 if (get_type_state(tp) == layout_undefined) {
1351 fprintf(F, "state: layout_undefined\n");
1353 fprintf(F, "state: layout_fixed,\n");
1355 if (get_type_mode(tp))
1356 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1357 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1362 static void print_typespecific_info(FILE *F, type *tp) {
1363 switch (get_type_tpop_code(tp)) {
1366 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1373 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1374 fprintf(F, "params: %d\n", get_method_n_params(tp));
1375 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1383 case tpo_enumeration:
1397 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1398 switch (get_type_tpop_code(tp)) {
1401 if (peculiarity_existent == get_class_peculiarity(tp))
1402 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1404 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1408 fprintf (F, " " TYPE_METH_NODE_ATTR);
1419 case tpo_enumeration:
1433 /* Why not dump_type_node as the others? */
1434 static int print_type_node(FILE *F, type *tp)
1438 fprintf (F, "node: {title: ");
1440 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1441 fprintf (F, " info1: \"");
1443 bad |= print_type_info(F, tp);
1444 print_typespecific_info(F, tp);
1446 dump_type_to_file(F, tp, dump_verbosity_max);
1449 print_typespecific_vcgattr(F, tp);
1455 int dump_type_node(FILE *F, type *tp) {
1456 return print_type_node(F, tp);
1460 #define X(a) case a: fprintf(F, #a); break
1461 void dump_entity_node(FILE *F, entity *ent, int color)
1463 fprintf (F, "node: {title: \"");
1464 PRINT_ENTID(ent); fprintf(F, "\"");
1465 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1466 fprintf (F, "label: ");
1467 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1469 fprintf(F, "color: %d", color);
1471 fprintf (F, ENTITY_NODE_ATTR);
1472 fprintf (F, "\n info1: \"");
1474 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1476 fprintf(F, "\"\n}\n");
1480 static void dump_enum_item(FILE *F, type *tp, int pos)
1483 ident *id = get_enumeration_nameid(tp, pos);
1484 tarval *tv = get_enumeration_enum(tp, pos);
1486 tarval_snprintf(buf, sizeof(buf), tv);
1487 fprintf (F, "node: {title: \"");
1488 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1489 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1490 fprintf (F, "label: ");
1491 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1492 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1495 /* dumps a type or entity and it's edges. */
1497 dump_type_info(type_or_ent *tore, void *env) {
1499 int i = 0; /* to shutup gcc */
1501 /* dump this type or entity */
1503 switch (get_kind(tore)) {
1506 entity *ent = (entity *)tore;
1509 dump_entity_node(F, ent, 0);
1511 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1512 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1513 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1514 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1515 if (is_Class_type(get_entity_owner(ent))) {
1516 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1517 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1519 /* attached subgraphs */
1520 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1521 if (is_atomic_entity(ent)) {
1522 value = get_atomic_ent_value(ent);
1524 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1525 /* DDMN(value); $$$ */
1526 dump_const_expression(F, value);
1529 if (is_compound_entity(ent)) {
1530 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1531 value = get_compound_ent_value(ent, i);
1533 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1534 dump_const_expression(F, value);
1535 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1537 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1538 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1539 get_compound_ent_value_member(ent, i), i);
1548 type *tp = (type *)tore;
1549 print_type_node(F, tp);
1550 /* and now the edges */
1551 switch (get_type_tpop_code(tp)) {
1554 for (i=0; i < get_class_n_supertypes(tp); i++)
1555 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1556 for (i=0; i < get_class_n_members(tp); i++)
1557 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1561 for (i=0; i < get_struct_n_members(tp); i++)
1562 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1566 for (i = 0; i < get_method_n_params(tp); i++)
1567 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1568 for (i = 0; i < get_method_n_ress(tp); i++)
1569 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1573 for (i = 0; i < get_union_n_members(tp); i++)
1574 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1578 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1579 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1580 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1581 ir_node *upper = get_array_upper_bound(tp, i);
1582 ir_node *lower = get_array_lower_bound(tp, i);
1583 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1584 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1585 dump_const_expression(F, upper);
1586 dump_const_expression(F, lower);
1590 case tpo_enumeration:
1592 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1593 dump_enum_item(F, tp, i);
1594 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1599 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1607 break; /* case k_type */
1610 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1612 } /* switch kind_or_entity */
1615 typedef struct _h_env {
1620 /** For dumping class hierarchies.
1621 * Dumps a class type node and a superclass edge.
1622 * If env->dump_ent dumps entities of classes and overwrites edges.
1625 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1628 int i = 0; /* to shutup gcc */
1630 /* dump this type or entity */
1631 switch (get_kind(tore)) {
1633 entity *ent = (entity *)tore;
1634 if (get_entity_owner(ent) == get_glob_type()) break;
1635 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1636 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1638 dump_entity_node(F, ent, 0);
1640 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1641 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1642 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1644 } break; /* case k_entity */
1647 type *tp = (type *)tore;
1648 if (tp == get_glob_type()) break;
1649 switch (get_type_tpop_code(tp)) {
1651 print_type_node(F, tp);
1652 /* and now the edges */
1653 for (i=0; i < get_class_n_supertypes(tp); i++)
1655 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1661 break; /* case k_type */
1664 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1666 } /* switch kind_or_entity */
1669 /*******************************************************************/
1670 /* dump analysis information that is expressed in graph terms. */
1671 /*******************************************************************/
1673 /* dump out edges */
1675 dump_out_edge(ir_node *n, void *env) {
1678 for (i = 0; i < get_irn_n_outs(n); i++) {
1679 assert(get_irn_out(n, i));
1680 fprintf (F, "edge: {sourcename: \"");
1682 fprintf (F, "\" targetname: \"");
1683 PRINT_NODEID(get_irn_out(n, i));
1684 fprintf (F, "\" color: red linestyle: dashed");
1690 dump_loop_label(FILE *F, ir_loop *loop) {
1691 fprintf (F, "loop %d, %d sons, %d nodes",
1692 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1695 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1696 fprintf (F, " info1: \"");
1697 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1698 #if DEBUG_libfirm /* GL @@@ debug analyses */
1699 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1705 dump_loop_node(FILE *F, ir_loop *loop) {
1706 fprintf (F, "node: {title: \"");
1708 fprintf (F, "\" label: \"");
1709 dump_loop_label(F, loop);
1711 dump_loop_info(F, loop);
1717 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1719 fprintf (F, "edge: {sourcename: \"");
1721 fprintf (F, "\" targetname: \"");
1722 PRINT_NODEID(get_loop_node(loop, i));
1723 fprintf (F, "\" color: green");
1728 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1730 fprintf (F, "edge: {sourcename: \"");
1732 fprintf (F, "\" targetname: \"");
1733 PRINT_LOOPID(get_loop_son(loop, i));
1734 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1735 get_loop_element_pos(loop, get_loop_son(loop, i)));
1739 void dump_loops(FILE *F, ir_loop *loop) {
1741 /* dump this loop node */
1742 dump_loop_node(F, loop);
1744 /* dump edges to nodes in loop -- only if it is a real loop */
1745 if (get_loop_depth(loop) != 0) {
1746 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1747 dump_loop_node_edge(F, loop, i);
1750 for (i = 0; i < get_loop_n_sons(loop); i++) {
1751 dump_loops(F, get_loop_son(loop, i));
1752 dump_loop_son_edge(F, loop, i);
1757 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1758 ir_graph *rem = current_ir_graph;
1759 current_ir_graph = irg;
1761 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1763 current_ir_graph = rem;
1768 * dumps the VCG header
1770 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1779 if (!orientation) orientation = "bottom_to_top";
1783 "graph: { title: \"ir graph of %s\"\n"
1784 "display_edge_labels: %s\n"
1785 "layoutalgorithm: mindepth\n"
1786 "manhattan_edges: yes\n"
1787 "port_sharing: no\n"
1789 "classname 1: \"intrablock Data\"\n"
1790 "classname 16: \"interblock Data\"\n"
1791 "classname 2: \"Block\"\n"
1792 "classname 13: \"Control Flow\"\n"
1793 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1794 "classname 14: \"intrablock Memory\"\n"
1795 "classname 17: \"interblock Memory\"\n"
1796 "classname 15: \"Dominators\"\n"
1797 "classname 3: \"Entity type\"\n"
1798 "classname 4: \"Entity owner\"\n"
1799 "classname 5: \"Method Param\"\n"
1800 "classname 6: \"Method Res\"\n"
1801 "classname 7: \"Super\"\n"
1802 "classname 8: \"Union\"\n"
1803 "classname 9: \"Points-to\"\n"
1804 "classname 10: \"Array Element Type\"\n"
1805 "classname 11: \"Overwrites\"\n"
1806 "classname 12: \"Member\"\n"
1807 "infoname 1: \"Attribute\"\n"
1808 "infoname 2: \"Verification errors\"\n",
1809 name, label, orientation);
1811 /* don't use all, the range is too whith/black. */
1815 "colorentry 100: 0 0 0\n"
1816 "colorentry 101: 20 0 0\n"
1817 "colorentry 102: 40 0 0\n"
1818 "colorentry 103: 60 0 0\n"
1819 "colorentry 104: 80 0 0\n"
1820 "colorentry 105: 100 0 0\n"
1821 "colorentry 106: 120 0 0\n"
1822 "colorentry 107: 140 0 0\n"
1823 "colorentry 108: 150 0 0\n"
1824 "colorentry 109: 180 0 0\n"
1825 "colorentry 110: 200 0 0\n"
1826 "colorentry 111: 220 0 0\n"
1827 "colorentry 112: 240 0 0\n"
1828 "colorentry 113: 255 0 0\n"
1829 "colorentry 113: 255 20 20\n"
1830 "colorentry 114: 255 40 40\n"
1831 "colorentry 115: 255 60 60\n"
1832 "colorentry 116: 255 80 80\n"
1833 "colorentry 117: 255 100 100\n"
1834 "colorentry 118: 255 120 120\n"
1835 "colorentry 119: 255 140 140\n"
1836 "colorentry 120: 255 150 150\n"
1837 "colorentry 121: 255 180 180\n"
1838 "colorentry 122: 255 200 200\n"
1839 "colorentry 123: 255 220 220\n"
1840 "colorentry 124: 255 240 240\n"
1841 "colorentry 125: 255 250 250\n"
1844 fprintf (F, "\n"); /* a separator */
1850 * @param irg The graph to be dumped
1851 * @param suffix1 first filename suffix
1852 * @param suffix2 second filename suffix
1854 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1856 const char *nm = get_irg_dump_name(irg);
1857 int len = strlen(nm), i, j;
1858 char *fname; /* filename to put the vcg information in */
1860 if (!suffix1) suffix1 = "";
1861 if (!suffix2) suffix2 = "";
1863 /* open file for vcg graph */
1864 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1866 /* strncpy (fname, nm, len); */ /* copy the filename */
1868 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1870 fname[j] = '@'; j++; fname[j] = '1'; j++;
1871 } else if (nm[i] == '@') {
1872 fname[j] = '@'; j++; fname[j] = '2'; j++;
1874 fname[j] = nm[i]; j++;
1878 strcat (fname, suffix1); /* append file suffix */
1879 strcat (fname, suffix2); /* append file suffix */
1880 strcat (fname, ".vcg"); /* append the .vcg suffix */
1882 /* vcg really expect only a <CR> at end of line, so
1883 * the "b"inary mode is what you mean (and even needed for Win32)
1885 F = fopen (fname, "wb"); /* open file for writing */
1887 panic("cannot open %s for writing (%m)", fname); /* not reached */
1897 * @param irg The graph to be dumped
1898 * @param suffix filename suffix
1900 FILE *vcg_open_name (const char *name, const char *suffix) {
1902 char *fname; /* filename to put the vcg information in */
1903 int i, j, len = strlen(name);
1905 if (!suffix) suffix = "";
1907 /** open file for vcg graph */
1908 fname = malloc (len * 2 + 5 + strlen(suffix));
1909 /* strcpy (fname, name);*/ /* copy the filename */
1911 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1912 if (name[i] == '/') {
1913 fname[j] = '@'; j++; fname[j] = '1'; j++;
1914 } else if (name[i] == '@') {
1915 fname[j] = '@'; j++; fname[j] = '2'; j++;
1917 fname[j] = name[i]; j++;
1921 strcat (fname, suffix);
1922 strcat (fname, ".vcg"); /* append the .vcg suffix */
1924 /* vcg really expect only a <CR> at end of line, so
1925 * the "b"inary mode is what you mean (and even needed for Win32)
1927 F = fopen (fname, "wb"); /* open file for writing */
1929 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1937 * Dumps the vcg file footer
1939 static INLINE void dump_vcg_footer (FILE *F) {
1944 * close the vcg file
1946 void vcg_close (FILE *F) {
1947 dump_vcg_footer(F); /* print footer */
1948 fclose (F); /* close vcg file */
1951 /************************************************************************/
1952 /************************************************************************/
1953 /* Routines that dump all or parts of the firm representation to a file */
1954 /************************************************************************/
1955 /************************************************************************/
1957 /************************************************************************/
1958 /* Dump ir graphs, different formats and additional information. */
1959 /************************************************************************/
1961 /** Routine to dump a graph, blocks as conventional nodes. */
1963 dump_ir_graph (ir_graph *irg, const char *suffix )
1968 rem = current_ir_graph;
1970 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
1972 current_ir_graph = irg;
1973 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1974 else suffix1 = "-pure";
1975 f = vcg_open(irg, suffix, suffix1);
1976 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1978 /* walk over the graph */
1979 /* dump_whole_node must be called in post visiting predecessors */
1980 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1982 /* dump the out edges in a separate walk */
1983 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1984 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1989 current_ir_graph = rem;
1992 /* Dump a firm graph without explicit block nodes. */
1993 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
1999 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2002 if (get_interprocedural_view()) suffix1 = "-ip";
2004 f = vcg_open(irg, suffix, suffix1);
2005 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2007 construct_block_lists(irg);
2010 * If we are in the interprocedural view, we dump not
2011 * only the requested irg but also all irgs that can be reached
2014 for (i = 0; i < get_irp_n_irgs(); i++) {
2015 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2017 dump_graph_from_list(f, get_irp_irg(i));
2025 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2026 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2032 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2037 if (get_interprocedural_view()) suffix1 = "-ip";
2039 F = vcg_open(irg, suffix, suffix1);
2040 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2042 construct_extblock_lists(irg);
2044 fprintf(F, "graph: { title: \"");
2046 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2047 get_ent_dump_name(get_irg_entity(irg)));
2049 for (i = 0; i < get_irp_n_irgs(); i++) {
2050 ir_graph *irg = get_irp_irg(i);
2051 list_tuple *lists = ird_get_irg_link(irg);
2054 /* dump the extended blocks first */
2055 if (ARR_LEN(lists->extbb_list)) {
2056 ird_set_irg_link(irg, lists->extbb_list);
2057 dump_extblock_graph(F, irg);
2060 /* we may have blocks without extended blocks, bad for instance */
2061 if (ARR_LEN(lists->blk_list)) {
2062 ird_set_irg_link(irg, lists->blk_list);
2063 dump_block_graph(F, irg);
2066 DEL_ARR_F(lists->extbb_list);
2067 DEL_ARR_F(lists->blk_list);
2072 /* Close the vcg information for the irg */
2073 fprintf(F, "}\n\n");
2079 /* dumps a graph with type information */
2081 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2084 ir_graph *rem = current_ir_graph;
2087 /* if a filter is set, dump only the irg's that match the filter */
2088 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2091 current_ir_graph = irg;
2093 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2094 else suffix1 = "-pure-wtypes";
2095 f = vcg_open(irg,suffix, suffix1);
2096 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2098 /* dump common ir graph */
2099 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2100 /* dump type info */
2101 type_walk_irg(irg, dump_type_info, NULL, f);
2102 inc_irg_visited(get_const_code_irg());
2103 /* dump edges from graph to type info */
2104 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2107 current_ir_graph = rem;
2111 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2116 ir_graph *rem = current_ir_graph;
2118 /* if a filter is set, dump only the irg's that match the filter */
2119 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2122 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2123 else suffix1 = "-wtypes";
2124 f = vcg_open(irg, suffix, suffix1);
2125 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2127 /* dump common blocked ir graph */
2128 construct_block_lists(irg);
2130 for (i = 0; i < get_irp_n_irgs(); i++) {
2131 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2133 dump_graph_from_list(f, get_irp_irg(i));
2138 /* dump type info */
2139 current_ir_graph = irg;
2140 type_walk_irg(irg, dump_type_info, NULL, f);
2141 inc_irg_visited(get_const_code_irg());
2143 /* dump edges from graph to type info */
2144 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2146 current_ir_graph = rem;
2150 /*---------------------------------------------------------------------*/
2151 /* The following routines dump a control flow graph. */
2152 /*---------------------------------------------------------------------*/
2155 dump_block_to_cfg(ir_node *block, void *env) {
2160 if (is_Block(block)) {
2161 /* This is a block. Dump a node for the block. */
2162 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2163 fprintf (F, "\" label: \"");
2164 if (block == get_irg_start_block(get_irn_irg(block)))
2165 fprintf(F, "Start ");
2166 if (block == get_irg_end_block(get_irn_irg(block)))
2169 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2170 PRINT_NODEID(block);
2172 fprintf(F, "info1:\"");
2175 if (dump_dominator_information_flag) {
2176 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2177 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2178 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2181 /* show arity and possible Bad predecessors of the block */
2182 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2183 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2184 ir_node *pred = get_Block_cfgpred(block, i);
2187 fprintf(F, "Bad pred at pos: ");
2188 fprintf(F, "%d ", i);
2195 /* the generic version. */
2196 dump_irnode_to_file(F, block);
2198 /* Check whether we have bad predecessors to color the block. */
2199 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2200 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2204 fprintf (F, "\""); /* closing quote of info */
2206 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2207 (block == get_irg_end_block(get_irn_irg(block))) )
2208 fprintf(F, " color:blue ");
2210 fprintf(F, " color:yellow ");
2213 /* Dump the edges */
2214 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2215 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2216 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2217 fprintf (F, "edge: { sourcename: \"");
2218 PRINT_NODEID(block);
2219 fprintf (F, "\" targetname: \"");
2221 fprintf (F, "\"}\n");
2224 /* Dump dominator edge */
2225 if (dump_dominator_information_flag && get_Block_idom(block)) {
2226 pred = get_Block_idom(block);
2227 fprintf (F, "edge: { sourcename: \"");
2228 PRINT_NODEID(block);
2229 fprintf (F, "\" targetname: \"");
2231 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2237 dump_cfg (ir_graph *irg, const char *suffix)
2240 ir_graph *rem = current_ir_graph;
2241 int ddif = dump_dominator_information_flag;
2242 int ipv = get_interprocedural_view();
2244 /* if a filter is set, dump only the irg's that match the filter */
2245 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2248 current_ir_graph = irg;
2250 f = vcg_open(irg, suffix, "-cfg");
2251 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2254 printf("Warning: dumping cfg not in interprocedural view!\n");
2255 set_interprocedural_view(false);
2258 if (get_irg_dom_state(irg) != dom_consistent)
2259 dump_dominator_information_flag = 0;
2261 /* walk over the blocks in the graph */
2262 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2263 dump_node(f, get_irg_bad(irg));
2265 dump_dominator_information_flag = ddif;
2266 set_interprocedural_view(ipv);
2268 current_ir_graph = rem;
2272 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2273 if (pset_find_ptr(mark_set, n)) return;
2275 pset_insert_ptr(mark_set, n);
2278 int i, start = is_Block(n) ? 0 : -1;
2279 dump_whole_node(n, F);
2280 for (i = start; i < get_irn_arity(n); ++i)
2281 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2284 /* Don't dump edges to nodes further out. These might be edges to
2285 nodes we already dumped, if there is a shorter path to these. */
2289 static int subgraph_counter = 0;
2290 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2293 pset *mark_set = pset_new_ptr(1);
2294 sprintf(buf, "-subg_%03d", subgraph_counter++);
2295 F = vcg_open(get_irn_irg(root), suffix, buf);
2296 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2297 descend_and_dump(F, root, depth, mark_set);
2303 static int weight_overall(int rec, int loop) {
2304 return 2*rec + loop;
2307 static int compute_color (int my, int max) {
2314 /* if small, scale to the full color range. */
2316 my = my * (n_colors/max);
2318 step = 1 + (max / n_colors);
2322 return base_color + n_colors - color;
2325 static int get_entity_color(entity *ent) {
2326 ir_graph *irg = get_entity_irg(ent);
2330 int rec_depth = get_irg_recursion_depth(irg);
2331 int loop_depth = get_irg_loop_depth(irg);
2332 int overall_depth = weight_overall(rec_depth, loop_depth);
2334 int max_rec_depth = irp->max_callgraph_recursion_depth;
2335 int max_loop_depth = irp->max_callgraph_loop_depth;
2336 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2338 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2339 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2340 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2342 return my_overall_color;
2346 void dump_callgraph(const char *suffix) {
2348 int i, n_irgs = get_irp_n_irgs();
2349 int rem = edge_label;
2351 //ident *prefix = new_id_from_str("java/");
2353 F = vcg_open_name("Callgraph", suffix);
2354 dump_vcg_header(F, "Callgraph", NULL);
2356 for (i = 0; i < n_irgs; ++i) {
2357 ir_graph *irg = get_irp_irg(i);
2358 entity *ent = get_irg_entity(irg);
2359 int j, n_callees = get_irg_n_callees(irg);
2361 /* Do not dump runtime system. */
2362 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2364 dump_entity_node(F, ent, get_entity_color(ent));
2365 for (j = 0; j < n_callees; ++j) {
2366 entity *c = get_irg_entity(get_irg_callee(irg, j));
2367 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2368 int be = is_irg_callee_backedge(irg, j);
2371 "label:\"recursion %d\" color: %d" :
2372 "label:\"calls %d\" color: %d";
2373 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2381 /* Dump all irgs in interprocedural view to a single file. */
2382 void dump_all_cg_block_graph(const char *suffix) {
2385 int rem_view = get_interprocedural_view();
2386 set_interprocedural_view(true);
2388 f = vcg_open_name("All_graphs", suffix);
2389 dump_vcg_header(f, "All_graphs", NULL);
2391 /* collect nodes in all irgs reachable in call graph*/
2392 for (i = 0; i < get_irp_n_irgs(); i++)
2393 ird_set_irg_link(get_irp_irg(i), NULL);
2395 cg_walk(clear_link, collect_node, NULL);
2397 /* dump all graphs */
2398 for (i = 0; i < get_irp_n_irgs(); i++) {
2399 current_ir_graph = get_irp_irg(i);
2400 assert(ird_get_irg_link(current_ir_graph));
2401 dump_graph_from_list(f, current_ir_graph);
2402 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2406 set_interprocedural_view(rem_view);
2409 /*---------------------------------------------------------------------*/
2410 /* the following routines dumps type information without any ir nodes. */
2411 /*---------------------------------------------------------------------*/
2414 dump_type_graph (ir_graph *irg, const char *suffix)
2418 rem = current_ir_graph;
2420 /* if a filter is set, dump only the irg's that match the filter */
2421 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2423 current_ir_graph = irg;
2425 f = vcg_open(irg, suffix, "-type");
2426 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2428 /* walk over the blocks in the graph */
2429 type_walk_irg(irg, dump_type_info, NULL, f);
2430 /* The walker for the const code can be called several times for the
2431 same (sub) expression. So that no nodes are dumped several times
2432 we decrease the visited flag of the corresponding graph after each
2433 walk. So now increase it finally. */
2434 inc_irg_visited(get_const_code_irg());
2437 current_ir_graph = rem;
2441 dump_all_types (const char *suffix)
2443 FILE *f = vcg_open_name("All_types", suffix);
2444 dump_vcg_header(f, "All_types", NULL);
2445 type_walk(dump_type_info, NULL, f);
2446 inc_irg_visited(get_const_code_irg());
2451 dump_class_hierarchy (bool entities, const char *suffix)
2453 FILE *f = vcg_open_name("class_hierarchy", suffix);
2457 dump_vcg_header(f, "class_hierarchy", NULL);
2462 type_walk(dump_class_hierarchy_node, NULL, &env);
2466 /*---------------------------------------------------------------------*/
2467 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2469 /* dump_ir_block_graph */
2471 /* dump_type_graph */
2472 /* dump_ir_graph_w_types */
2473 /*---------------------------------------------------------------------*/
2475 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2476 int i, n_irgs = get_irp_n_irgs();
2477 for (i = 0; i < n_irgs; ++i) {
2478 dmp_grph(get_irp_irg(i), suffix);
2483 /*--------------------------------------------------------------------------------*
2484 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2485 * packed together in one subgraph/box *
2486 *--------------------------------------------------------------------------------*/
2488 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2489 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2491 ir_loop *son = NULL;
2493 /* Dump a new loop node. */
2494 dump_loop_node(F, loop);
2496 /* Dump the loop elements. */
2498 for(i = 0; i < get_loop_n_elements(loop); i++) {
2499 le = get_loop_element(loop, i);
2501 if (get_kind(son) == k_ir_loop) {
2503 /* We are a loop son -> Recurse */
2505 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2506 fprintf(F, "\" }\n");
2507 fprintf (F, "edge: {sourcename: \"");
2509 fprintf (F, "\" targetname: \"");
2511 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2512 loop_node_started = 0;
2514 dump_loop_son_edge(F, loop, son_number++);
2515 dump_loops_standalone(F, son);
2516 } else if (get_kind(son) == k_ir_node) {
2517 /* We are a loop node -> Collect firm nodes */
2519 ir_node *n = le.node;
2522 if (!loop_node_started) {
2523 /* Start a new node which contains all firm nodes of the current loop */
2524 fprintf (F, "node: { title: \"");
2526 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2527 loop_node_started = 1;
2533 bad |= dump_node_label(F, n);
2534 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2535 if (has_backedges(n)) fprintf(F, "\t loop head!");
2536 } else { /* for callgraph loop tree */
2538 assert(get_kind(son) == k_ir_graph);
2540 /* We are a loop node -> Collect firm graphs */
2541 n = (ir_graph *)le.node;
2542 if (!loop_node_started) {
2543 /* Start a new node which contains all firm nodes of the current loop */
2544 fprintf (F, "node: { title: \"");
2546 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2547 loop_node_started = 1;
2552 fprintf (F, " %s", get_irg_dump_name(n));
2553 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2557 if (loop_node_started) {
2558 fprintf(F, "\" }\n");
2559 fprintf (F, "edge: {sourcename: \"");
2561 fprintf (F, "\" targetname: \"");
2563 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2564 loop_node_started = 0;
2568 void dump_loop_tree(ir_graph *irg, const char *suffix)
2571 ir_graph *rem = current_ir_graph;
2572 int el_rem = edge_label;
2575 /* if a filter is set, dump only the irg's that match the filter */
2576 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2578 current_ir_graph = irg;
2580 f = vcg_open(irg, suffix, "-looptree");
2581 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2583 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2587 edge_label = el_rem;
2588 current_ir_graph = rem;
2591 void dump_callgraph_loop_tree(const char *suffix) {
2593 F = vcg_open_name("Callgraph_looptree", suffix);
2594 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2595 dump_loops_standalone(F, irp->outermost_cg_loop);
2600 /*-----------------------------------------------------------------------------*/
2601 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2602 /*-----------------------------------------------------------------------------*/
2604 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2605 int i, son_number = 0, node_number = 0;
2607 if (dump_loop_information_flag) dump_loop_node(F, loop);
2609 for (i = 0; i < get_loop_n_elements(loop); i++) {
2610 loop_element le = get_loop_element(loop, i);
2611 if (*(le.kind) == k_ir_loop) {
2612 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2614 collect_nodeloop(F, le.son, loopnodes);
2616 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2617 eset_insert(loopnodes, le.node);
2622 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2625 for(i = 0; i < get_loop_n_elements(loop); i++) {
2626 loop_element le = get_loop_element(loop, i);
2627 if (*(le.kind) == k_ir_loop) {
2629 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2631 if (is_Block(le.node)) start = 0; else start = -1;
2632 for (j = start; j < get_irn_arity(le.node); j++) {
2633 ir_node *pred = get_irn_n(le.node, j);
2634 if (!eset_contains(loopnodes, pred)) {
2635 eset_insert(extnodes, pred);
2636 if (!is_Block(pred)) {
2637 pred = get_nodes_block(pred);
2638 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2646 void dump_loop(ir_loop *l, const char *suffix) {
2649 eset *loopnodes = eset_create();
2650 eset *extnodes = eset_create();
2653 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2654 F = vcg_open_name (name, suffix);
2655 dump_vcg_header(F, name, NULL);
2657 /* collect all nodes to dump */
2658 collect_nodeloop(F, l, loopnodes);
2659 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2661 /* build block lists */
2662 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2663 set_irn_link(n, NULL);
2664 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2665 set_irn_link(n, NULL);
2666 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2668 b = get_nodes_block(n);
2669 set_irn_link(n, get_irn_link(b));
2672 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2674 b = get_nodes_block(n);
2675 set_irn_link(n, get_irn_link(b));
2679 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2681 fprintf(F, "graph: { title: \"");
2683 fprintf(F, "\" label: \"");
2684 dump_node_opcode(F, b);
2685 fprintf (F, " %ld", get_irn_node_nr(b));
2686 fprintf(F, "\" status:clustered color:yellow\n");
2688 /* dump the blocks edges */
2689 dump_ir_data_edges(F, b);
2691 /* dump the nodes that go into the block */
2692 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2693 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2695 overrule_nodecolor = NULL;
2696 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2699 /* Close the vcg information for the block */
2701 dump_const_node_local(F, b);
2704 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2706 fprintf(F, "graph: { title: \"");
2708 fprintf(F, "\" label: \"");
2709 dump_node_opcode(F, b);
2710 fprintf (F, " %ld", get_irn_node_nr(b));
2711 fprintf(F, "\" status:clustered color:lightblue\n");
2713 /* dump the nodes that go into the block */
2714 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2715 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2717 overrule_nodecolor = NULL;
2718 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2721 /* Close the vcg information for the block */
2723 dump_const_node_local(F, b);
2727 eset_destroy(loopnodes);
2728 eset_destroy(extnodes);