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) {
964 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
965 fprintf (F, INTRA_DATA_EDGE_ATTR);
967 fprintf (F, INTER_DATA_EDGE_ATTR);
971 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
972 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
973 fprintf (F, INTRA_MEM_EDGE_ATTR);
975 fprintf (F, INTER_MEM_EDGE_ATTR);
979 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
982 if (dump_backedge_information_flag && is_backedge(from, to))
983 fprintf (F, BACK_EDGE_ATTR);
985 switch (get_irn_opcode(from)) {
987 fprintf (F, CF_EDGE_ATTR);
989 case iro_Start: break;
992 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
993 fprintf (F, CF_EDGE_ATTR);
994 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
995 fprintf (F, INTER_MEM_EDGE_ATTR);
1003 print_data_edge_vcgattr(F, from, to);
1008 print_mem_edge_vcgattr(F, from, to);
1010 print_data_edge_vcgattr(F, from, to);
1014 print_data_edge_vcgattr(F, from, to);
1019 print_mem_edge_vcgattr(F, from, to);
1021 print_data_edge_vcgattr(F, from, to);
1028 print_data_edge_vcgattr(F, from, to);
1035 print_mem_edge_vcgattr(F, from, to);
1037 print_data_edge_vcgattr(F, from, to);
1049 print_data_edge_vcgattr(F, from, to);
1052 if (get_irn_modecode(from) == irm_M)
1053 fprintf (F, INTER_MEM_EDGE_ATTR);
1055 print_data_edge_vcgattr(F, from, to);
1062 print_mem_edge_vcgattr(F, from, to);
1064 print_data_edge_vcgattr(F, from, to);
1067 print_mem_edge_vcgattr(F, from, to);
1069 case iro_Tuple: break;
1072 switch (get_irn_modecode(from)) {
1074 fprintf (F, CF_EDGE_ATTR);
1077 fprintf (F, INTER_MEM_EDGE_ATTR);
1080 print_data_edge_vcgattr(F, from, to);
1084 case iro_Bad: break;
1085 case iro_Unknown: break;
1087 switch (get_irn_modecode(from)) {
1089 fprintf (F, INTRA_MEM_EDGE_ATTR);
1092 fprintf (F, CF_EDGE_ATTR);
1095 print_data_edge_vcgattr(F, from, to);
1103 /* dump edges to our inputs */
1105 dump_ir_data_edges(FILE *F, ir_node *n) {
1107 unsigned long visited = get_irn_visited(n);
1109 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1112 for (i = 0; i < get_irn_arity(n); i++) {
1113 ir_node * pred = get_irn_n(n, i);
1116 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1117 continue; /* pred not dumped */
1119 if (dump_backedge_information_flag && is_backedge(n, i))
1120 fprintf (F, "backedge: {sourcename: \"");
1122 fprintf (F, "edge: {sourcename: \"");
1124 fprintf (F, "\" targetname: ");
1125 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1126 PRINT_CONSTID(n, pred);
1128 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1130 fprintf (F, " label: \"%d\" ", i);
1131 print_edge_vcgattr(F, n, i);
1136 /** Dumps a node and its edges but not the block edge
1139 dump_node_wo_blockedge (ir_node *n, void *env) {
1142 dump_ir_data_edges(F, n);
1145 /** Dumps a node and its edges.
1148 dump_whole_node (ir_node *n, void *env) {
1150 dump_node_wo_blockedge(n, env);
1151 if (!node_floats(n)) dump_ir_block_edge(F, n);
1155 dump_const_node(ir_node *n, void *env) {
1156 if (is_Block(n)) return;
1157 dump_node_wo_blockedge(n, env);
1160 /***********************************************************************/
1161 /* the following routines dump the nodes/irgs bracketed to graphs. */
1162 /***********************************************************************/
1164 /** Dumps a constant expression as entity initializer, array bound ...
1166 static void dump_const_expression(FILE *F, ir_node *value) {
1167 ir_graph *rem = current_ir_graph;
1168 int rem_dump_const_local = dump_const_local;
1169 dump_const_local = 0;
1170 current_ir_graph = get_const_code_irg();
1171 irg_walk(value, dump_const_node, NULL, F);
1172 /* Decrease visited flag so that we walk with the same flag for the next
1173 expression. This guarantees that we don't dump the same node twice,
1174 as for const expressions cse is performed to save memory. */
1175 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1176 current_ir_graph = rem;
1177 dump_const_local = rem_dump_const_local;
1180 /** Dump a block as graph containing its nodes.
1182 * Expects to find nodes belonging to the block as list in its
1184 * Dumps the edges of all nodes including itself. */
1186 dump_whole_block(FILE *F, ir_node *block) {
1188 assert(is_Block(block));
1190 fprintf(F, "graph: { title: \"");
1191 PRINT_NODEID(block);
1192 fprintf(F, "\" label: \"");
1193 dump_node_label(F, block);
1195 if (get_opt_dump_abstvals())
1196 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1198 fprintf(F, "\" status:clustered color:%s \n",
1199 get_Block_matured(block) ? "yellow" : "red");
1201 /* dump the blocks edges */
1202 dump_ir_data_edges(F, block);
1204 /* dump the nodes that go into the block */
1205 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1207 dump_ir_data_edges(F, node);
1210 /* Close the vcg information for the block */
1212 dump_const_node_local(F, block);
1214 dump_irn_chi_term(F, block);
1219 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1220 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1222 dump_block_graph(FILE *F, ir_graph *irg) {
1224 ir_graph *rem = current_ir_graph;
1225 ir_node **arr = ird_get_irg_link(irg);
1226 current_ir_graph = irg;
1228 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1229 ir_node * node = arr[i];
1230 if (is_Block(node)) {
1231 /* Dumps the block and all the nodes in the block, which are to
1232 be found in Block->link. */
1233 dump_whole_block(F, node);
1235 /* Nodes that are not in a Block. */
1237 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1238 dump_const_block_local(F, node);
1240 dump_ir_data_edges(F, node);
1244 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1245 dump_loop_nodes_into_graph(F, irg);
1247 current_ir_graph = rem;
1250 /** Dumps an irg as a graph clustered by block nodes.
1251 * If interprocedural view edges can point to nodes out of this graph.
1253 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1255 fprintf(F, "graph: { title: \"");
1257 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1258 get_ent_dump_name(get_irg_entity(irg)));
1260 dump_block_graph(F, irg);
1262 /* Close the vcg information for the irg */
1263 fprintf(F, "}\n\n");
1266 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1267 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1269 dump_extblock_graph(FILE *F, ir_graph *irg) {
1271 ir_graph *rem = current_ir_graph;
1272 ir_extblk **arr = ird_get_irg_link(irg);
1273 current_ir_graph = irg;
1276 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1277 ir_extblk *extbb = arr[i];
1278 ir_node *leader = extbb->blks[0];
1281 fprintf(F, "graph: { title: \"");
1282 PRINT_EXTBBID(leader);
1283 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1284 get_irn_node_nr(leader));
1286 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1287 ir_node * node = extbb->blks[j];
1288 if (is_Block(node)) {
1289 /* Dumps the block and all the nodes in the block, which are to
1290 be found in Block->link. */
1291 dump_whole_block(F, node);
1293 /* Nodes that are not in a Block. */
1295 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1296 dump_const_block_local(F, node);
1298 dump_ir_data_edges(F, node);
1304 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1305 dump_loop_nodes_into_graph(F, irg);
1307 current_ir_graph = rem;
1312 /*******************************************************************/
1313 /* Basic type and entity nodes and edges. */
1314 /*******************************************************************/
1316 /** dumps the edges between nodes and their type or entity attributes. */
1317 static void dump_node2type_edges(ir_node *n, void *env)
1322 switch (get_irn_opcode(n)) {
1324 /* @@@ some consts have an entity */
1327 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1328 || (get_SymConst_kind(n) ==symconst_size))
1330 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1334 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1337 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1340 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1343 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1346 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1354 static int print_type_info(FILE *F, type *tp) {
1357 if (get_type_state(tp) == layout_undefined) {
1358 fprintf(F, "state: layout_undefined\n");
1360 fprintf(F, "state: layout_fixed,\n");
1362 if (get_type_mode(tp))
1363 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1364 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1369 static void print_typespecific_info(FILE *F, type *tp) {
1370 switch (get_type_tpop_code(tp)) {
1373 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1380 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1381 fprintf(F, "params: %d\n", get_method_n_params(tp));
1382 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1390 case tpo_enumeration:
1404 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1405 switch (get_type_tpop_code(tp)) {
1408 if (peculiarity_existent == get_class_peculiarity(tp))
1409 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1411 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1415 fprintf (F, " " TYPE_METH_NODE_ATTR);
1426 case tpo_enumeration:
1440 /* Why not dump_type_node as the others? */
1441 static int print_type_node(FILE *F, type *tp)
1445 fprintf (F, "node: {title: ");
1447 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1448 fprintf (F, " info1: \"");
1450 bad |= print_type_info(F, tp);
1451 print_typespecific_info(F, tp);
1453 dump_type_to_file(F, tp, dump_verbosity_max);
1456 print_typespecific_vcgattr(F, tp);
1462 int dump_type_node(FILE *F, type *tp) {
1463 return print_type_node(F, tp);
1467 #define X(a) case a: fprintf(F, #a); break
1468 void dump_entity_node(FILE *F, entity *ent, int color)
1470 fprintf (F, "node: {title: \"");
1471 PRINT_ENTID(ent); fprintf(F, "\"");
1472 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1473 fprintf (F, "label: ");
1474 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1476 fprintf(F, "color: %d", color);
1478 fprintf (F, ENTITY_NODE_ATTR);
1479 fprintf (F, "\n info1: \"");
1481 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1483 fprintf(F, "\"\n}\n");
1487 static void dump_enum_item(FILE *F, type *tp, int pos)
1490 ident *id = get_enumeration_nameid(tp, pos);
1491 tarval *tv = get_enumeration_enum(tp, pos);
1493 tarval_snprintf(buf, sizeof(buf), tv);
1494 fprintf (F, "node: {title: \"");
1495 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1496 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1497 fprintf (F, "label: ");
1498 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1499 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1502 /* dumps a type or entity and it's edges. */
1504 dump_type_info(type_or_ent *tore, void *env) {
1506 int i = 0; /* to shutup gcc */
1508 /* dump this type or entity */
1510 switch (get_kind(tore)) {
1513 entity *ent = (entity *)tore;
1516 dump_entity_node(F, ent, 0);
1518 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1519 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1520 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1521 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1522 if (is_Class_type(get_entity_owner(ent))) {
1523 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1524 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1526 /* attached subgraphs */
1527 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1528 if (is_atomic_entity(ent)) {
1529 value = get_atomic_ent_value(ent);
1531 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1532 /* DDMN(value); $$$ */
1533 dump_const_expression(F, value);
1536 if (is_compound_entity(ent)) {
1537 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1538 value = get_compound_ent_value(ent, i);
1540 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1541 dump_const_expression(F, value);
1542 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1544 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1545 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1546 get_compound_ent_value_member(ent, i), i);
1555 type *tp = (type *)tore;
1556 print_type_node(F, tp);
1557 /* and now the edges */
1558 switch (get_type_tpop_code(tp)) {
1561 for (i=0; i < get_class_n_supertypes(tp); i++)
1562 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1563 for (i=0; i < get_class_n_members(tp); i++)
1564 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1568 for (i=0; i < get_struct_n_members(tp); i++)
1569 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1573 for (i = 0; i < get_method_n_params(tp); i++)
1574 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1575 for (i = 0; i < get_method_n_ress(tp); i++)
1576 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1580 for (i = 0; i < get_union_n_members(tp); i++)
1581 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1585 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1586 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1587 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1588 ir_node *upper = get_array_upper_bound(tp, i);
1589 ir_node *lower = get_array_lower_bound(tp, i);
1590 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1591 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1592 dump_const_expression(F, upper);
1593 dump_const_expression(F, lower);
1597 case tpo_enumeration:
1599 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1600 dump_enum_item(F, tp, i);
1601 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1606 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1614 break; /* case k_type */
1617 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1619 } /* switch kind_or_entity */
1622 typedef struct _h_env {
1627 /** For dumping class hierarchies.
1628 * Dumps a class type node and a superclass edge.
1629 * If env->dump_ent dumps entities of classes and overwrites edges.
1632 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1635 int i = 0; /* to shutup gcc */
1637 /* dump this type or entity */
1638 switch (get_kind(tore)) {
1640 entity *ent = (entity *)tore;
1641 if (get_entity_owner(ent) == get_glob_type()) break;
1642 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1643 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1645 dump_entity_node(F, ent, 0);
1647 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1648 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1649 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1651 } break; /* case k_entity */
1654 type *tp = (type *)tore;
1655 if (tp == get_glob_type()) break;
1656 switch (get_type_tpop_code(tp)) {
1658 print_type_node(F, tp);
1659 /* and now the edges */
1660 for (i=0; i < get_class_n_supertypes(tp); i++)
1662 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1668 break; /* case k_type */
1671 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1673 } /* switch kind_or_entity */
1676 /*******************************************************************/
1677 /* dump analysis information that is expressed in graph terms. */
1678 /*******************************************************************/
1680 /* dump out edges */
1682 dump_out_edge(ir_node *n, void *env) {
1685 for (i = 0; i < get_irn_n_outs(n); i++) {
1686 assert(get_irn_out(n, i));
1687 fprintf (F, "edge: {sourcename: \"");
1689 fprintf (F, "\" targetname: \"");
1690 PRINT_NODEID(get_irn_out(n, i));
1691 fprintf (F, "\" color: red linestyle: dashed");
1697 dump_loop_label(FILE *F, ir_loop *loop) {
1698 fprintf (F, "loop %d, %d sons, %d nodes",
1699 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1702 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1703 fprintf (F, " info1: \"");
1704 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1705 #if DEBUG_libfirm /* GL @@@ debug analyses */
1706 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1712 dump_loop_node(FILE *F, ir_loop *loop) {
1713 fprintf (F, "node: {title: \"");
1715 fprintf (F, "\" label: \"");
1716 dump_loop_label(F, loop);
1718 dump_loop_info(F, loop);
1724 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1726 fprintf (F, "edge: {sourcename: \"");
1728 fprintf (F, "\" targetname: \"");
1729 PRINT_NODEID(get_loop_node(loop, i));
1730 fprintf (F, "\" color: green");
1735 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1737 fprintf (F, "edge: {sourcename: \"");
1739 fprintf (F, "\" targetname: \"");
1740 PRINT_LOOPID(get_loop_son(loop, i));
1741 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1742 get_loop_element_pos(loop, get_loop_son(loop, i)));
1746 void dump_loops(FILE *F, ir_loop *loop) {
1748 /* dump this loop node */
1749 dump_loop_node(F, loop);
1751 /* dump edges to nodes in loop -- only if it is a real loop */
1752 if (get_loop_depth(loop) != 0) {
1753 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1754 dump_loop_node_edge(F, loop, i);
1757 for (i = 0; i < get_loop_n_sons(loop); i++) {
1758 dump_loops(F, get_loop_son(loop, i));
1759 dump_loop_son_edge(F, loop, i);
1764 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1765 ir_graph *rem = current_ir_graph;
1766 current_ir_graph = irg;
1768 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1770 current_ir_graph = rem;
1775 * dumps the VCG header
1777 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1786 if (!orientation) orientation = "bottom_to_top";
1790 "graph: { title: \"ir graph of %s\"\n"
1791 "display_edge_labels: %s\n"
1792 "layoutalgorithm: mindepth\n"
1793 "manhattan_edges: yes\n"
1794 "port_sharing: no\n"
1796 "classname 1: \"intrablock Data\"\n"
1797 "classname 16: \"interblock Data\"\n"
1798 "classname 2: \"Block\"\n"
1799 "classname 13: \"Control Flow\"\n"
1800 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1801 "classname 14: \"intrablock Memory\"\n"
1802 "classname 17: \"interblock Memory\"\n"
1803 "classname 15: \"Dominators\"\n"
1804 "classname 3: \"Entity type\"\n"
1805 "classname 4: \"Entity owner\"\n"
1806 "classname 5: \"Method Param\"\n"
1807 "classname 6: \"Method Res\"\n"
1808 "classname 7: \"Super\"\n"
1809 "classname 8: \"Union\"\n"
1810 "classname 9: \"Points-to\"\n"
1811 "classname 10: \"Array Element Type\"\n"
1812 "classname 11: \"Overwrites\"\n"
1813 "classname 12: \"Member\"\n"
1814 "infoname 1: \"Attribute\"\n"
1815 "infoname 2: \"Verification errors\"\n",
1816 name, label, orientation);
1818 /* don't use all, the range is too whith/black. */
1822 "colorentry 100: 0 0 0\n"
1823 "colorentry 101: 20 0 0\n"
1824 "colorentry 102: 40 0 0\n"
1825 "colorentry 103: 60 0 0\n"
1826 "colorentry 104: 80 0 0\n"
1827 "colorentry 105: 100 0 0\n"
1828 "colorentry 106: 120 0 0\n"
1829 "colorentry 107: 140 0 0\n"
1830 "colorentry 108: 150 0 0\n"
1831 "colorentry 109: 180 0 0\n"
1832 "colorentry 110: 200 0 0\n"
1833 "colorentry 111: 220 0 0\n"
1834 "colorentry 112: 240 0 0\n"
1835 "colorentry 113: 255 0 0\n"
1836 "colorentry 113: 255 20 20\n"
1837 "colorentry 114: 255 40 40\n"
1838 "colorentry 115: 255 60 60\n"
1839 "colorentry 116: 255 80 80\n"
1840 "colorentry 117: 255 100 100\n"
1841 "colorentry 118: 255 120 120\n"
1842 "colorentry 119: 255 140 140\n"
1843 "colorentry 120: 255 150 150\n"
1844 "colorentry 121: 255 180 180\n"
1845 "colorentry 122: 255 200 200\n"
1846 "colorentry 123: 255 220 220\n"
1847 "colorentry 124: 255 240 240\n"
1848 "colorentry 125: 255 250 250\n"
1851 fprintf (F, "\n"); /* a separator */
1857 * @param irg The graph to be dumped
1858 * @param suffix1 first filename suffix
1859 * @param suffix2 second filename suffix
1861 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1863 const char *nm = get_irg_dump_name(irg);
1864 int len = strlen(nm), i, j;
1865 char *fname; /* filename to put the vcg information in */
1867 if (!suffix1) suffix1 = "";
1868 if (!suffix2) suffix2 = "";
1870 /* open file for vcg graph */
1871 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1873 /* strncpy (fname, nm, len); */ /* copy the filename */
1875 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1877 fname[j] = '@'; j++; fname[j] = '1'; j++;
1878 } else if (nm[i] == '@') {
1879 fname[j] = '@'; j++; fname[j] = '2'; j++;
1881 fname[j] = nm[i]; j++;
1885 strcat (fname, suffix1); /* append file suffix */
1886 strcat (fname, suffix2); /* append file suffix */
1887 strcat (fname, ".vcg"); /* append the .vcg suffix */
1889 /* vcg really expect only a <CR> at end of line, so
1890 * the "b"inary mode is what you mean (and even needed for Win32)
1892 F = fopen (fname, "wb"); /* open file for writing */
1894 panic("cannot open %s for writing (%m)", fname); /* not reached */
1904 * @param irg The graph to be dumped
1905 * @param suffix filename suffix
1907 FILE *vcg_open_name (const char *name, const char *suffix) {
1909 char *fname; /* filename to put the vcg information in */
1910 int i, j, len = strlen(name);
1912 if (!suffix) suffix = "";
1914 /** open file for vcg graph */
1915 fname = malloc (len * 2 + 5 + strlen(suffix));
1916 /* strcpy (fname, name);*/ /* copy the filename */
1918 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1919 if (name[i] == '/') {
1920 fname[j] = '@'; j++; fname[j] = '1'; j++;
1921 } else if (name[i] == '@') {
1922 fname[j] = '@'; j++; fname[j] = '2'; j++;
1924 fname[j] = name[i]; j++;
1928 strcat (fname, suffix);
1929 strcat (fname, ".vcg"); /* append the .vcg suffix */
1931 /* vcg really expect only a <CR> at end of line, so
1932 * the "b"inary mode is what you mean (and even needed for Win32)
1934 F = fopen (fname, "wb"); /* open file for writing */
1936 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1944 * Dumps the vcg file footer
1946 static INLINE void dump_vcg_footer (FILE *F) {
1951 * close the vcg file
1953 void vcg_close (FILE *F) {
1954 dump_vcg_footer(F); /* print footer */
1955 fclose (F); /* close vcg file */
1958 /************************************************************************/
1959 /************************************************************************/
1960 /* Routines that dump all or parts of the firm representation to a file */
1961 /************************************************************************/
1962 /************************************************************************/
1964 /************************************************************************/
1965 /* Dump ir graphs, different formats and additional information. */
1966 /************************************************************************/
1968 /** Routine to dump a graph, blocks as conventional nodes. */
1970 dump_ir_graph (ir_graph *irg, const char *suffix )
1975 rem = current_ir_graph;
1977 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
1979 current_ir_graph = irg;
1980 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1981 else suffix1 = "-pure";
1982 f = vcg_open(irg, suffix, suffix1);
1983 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1985 /* walk over the graph */
1986 /* dump_whole_node must be called in post visiting predecessors */
1987 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1989 /* dump the out edges in a separate walk */
1990 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1991 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1996 current_ir_graph = rem;
1999 /* Dump a firm graph without explicit block nodes. */
2000 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2006 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2009 if (get_interprocedural_view()) suffix1 = "-ip";
2011 f = vcg_open(irg, suffix, suffix1);
2012 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2014 construct_block_lists(irg);
2017 * If we are in the interprocedural view, we dump not
2018 * only the requested irg but also all irgs that can be reached
2021 for (i = 0; i < get_irp_n_irgs(); i++) {
2022 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2024 dump_graph_from_list(f, get_irp_irg(i));
2032 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2033 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2039 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2044 if (get_interprocedural_view()) suffix1 = "-ip";
2046 F = vcg_open(irg, suffix, suffix1);
2047 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2049 construct_extblock_lists(irg);
2051 fprintf(F, "graph: { title: \"");
2053 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2054 get_ent_dump_name(get_irg_entity(irg)));
2056 for (i = 0; i < get_irp_n_irgs(); i++) {
2057 ir_graph *irg = get_irp_irg(i);
2058 list_tuple *lists = ird_get_irg_link(irg);
2061 /* dump the extended blocks first */
2062 if (ARR_LEN(lists->extbb_list)) {
2063 ird_set_irg_link(irg, lists->extbb_list);
2064 dump_extblock_graph(F, irg);
2067 /* we may have blocks without extended blocks, bad for instance */
2068 if (ARR_LEN(lists->blk_list)) {
2069 ird_set_irg_link(irg, lists->blk_list);
2070 dump_block_graph(F, irg);
2073 DEL_ARR_F(lists->extbb_list);
2074 DEL_ARR_F(lists->blk_list);
2079 /* Close the vcg information for the irg */
2080 fprintf(F, "}\n\n");
2086 /* dumps a graph with type information */
2088 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2091 ir_graph *rem = current_ir_graph;
2094 /* if a filter is set, dump only the irg's that match the filter */
2095 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2098 current_ir_graph = irg;
2100 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2101 else suffix1 = "-pure-wtypes";
2102 f = vcg_open(irg,suffix, suffix1);
2103 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2105 /* dump common ir graph */
2106 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2107 /* dump type info */
2108 type_walk_irg(irg, dump_type_info, NULL, f);
2109 inc_irg_visited(get_const_code_irg());
2110 /* dump edges from graph to type info */
2111 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2114 current_ir_graph = rem;
2118 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2123 ir_graph *rem = current_ir_graph;
2125 /* if a filter is set, dump only the irg's that match the filter */
2126 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2129 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2130 else suffix1 = "-wtypes";
2131 f = vcg_open(irg, suffix, suffix1);
2132 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2134 /* dump common blocked ir graph */
2135 construct_block_lists(irg);
2137 for (i = 0; i < get_irp_n_irgs(); i++) {
2138 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2140 dump_graph_from_list(f, get_irp_irg(i));
2145 /* dump type info */
2146 current_ir_graph = irg;
2147 type_walk_irg(irg, dump_type_info, NULL, f);
2148 inc_irg_visited(get_const_code_irg());
2150 /* dump edges from graph to type info */
2151 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2153 current_ir_graph = rem;
2157 /*---------------------------------------------------------------------*/
2158 /* The following routines dump a control flow graph. */
2159 /*---------------------------------------------------------------------*/
2162 dump_block_to_cfg(ir_node *block, void *env) {
2167 if (is_Block(block)) {
2168 /* This is a block. Dump a node for the block. */
2169 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2170 fprintf (F, "\" label: \"");
2171 if (block == get_irg_start_block(get_irn_irg(block)))
2172 fprintf(F, "Start ");
2173 if (block == get_irg_end_block(get_irn_irg(block)))
2176 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2177 PRINT_NODEID(block);
2179 fprintf(F, "info1:\"");
2182 if (dump_dominator_information_flag) {
2183 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2184 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2185 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2188 /* show arity and possible Bad predecessors of the block */
2189 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2190 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2191 ir_node *pred = get_Block_cfgpred(block, i);
2194 fprintf(F, "Bad pred at pos: ");
2195 fprintf(F, "%d ", i);
2202 /* the generic version. */
2203 dump_irnode_to_file(F, block);
2205 /* Check whether we have bad predecessors to color the block. */
2206 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2207 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2211 fprintf (F, "\""); /* closing quote of info */
2213 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2214 (block == get_irg_end_block(get_irn_irg(block))) )
2215 fprintf(F, " color:blue ");
2217 fprintf(F, " color:yellow ");
2220 /* Dump the edges */
2221 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2222 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2223 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2224 fprintf (F, "edge: { sourcename: \"");
2225 PRINT_NODEID(block);
2226 fprintf (F, "\" targetname: \"");
2228 fprintf (F, "\"}\n");
2231 /* Dump dominator edge */
2232 if (dump_dominator_information_flag && get_Block_idom(block)) {
2233 pred = get_Block_idom(block);
2234 fprintf (F, "edge: { sourcename: \"");
2235 PRINT_NODEID(block);
2236 fprintf (F, "\" targetname: \"");
2238 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2244 dump_cfg (ir_graph *irg, const char *suffix)
2247 ir_graph *rem = current_ir_graph;
2248 int ddif = dump_dominator_information_flag;
2249 int ipv = get_interprocedural_view();
2251 /* if a filter is set, dump only the irg's that match the filter */
2252 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2255 current_ir_graph = irg;
2257 f = vcg_open(irg, suffix, "-cfg");
2258 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2261 printf("Warning: dumping cfg not in interprocedural view!\n");
2262 set_interprocedural_view(false);
2265 if (get_irg_dom_state(irg) != dom_consistent)
2266 dump_dominator_information_flag = 0;
2268 /* walk over the blocks in the graph */
2269 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2270 dump_node(f, get_irg_bad(irg));
2272 dump_dominator_information_flag = ddif;
2273 set_interprocedural_view(ipv);
2275 current_ir_graph = rem;
2279 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2280 if (pset_find_ptr(mark_set, n)) return;
2282 pset_insert_ptr(mark_set, n);
2285 int i, start = is_Block(n) ? 0 : -1;
2286 dump_whole_node(n, F);
2287 for (i = start; i < get_irn_arity(n); ++i)
2288 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2291 /* Don't dump edges to nodes further out. These might be edges to
2292 nodes we already dumped, if there is a shorter path to these. */
2296 static int subgraph_counter = 0;
2297 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2300 pset *mark_set = pset_new_ptr(1);
2301 sprintf(buf, "-subg_%03d", subgraph_counter++);
2302 F = vcg_open(get_irn_irg(root), suffix, buf);
2303 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2304 descend_and_dump(F, root, depth, mark_set);
2310 static int weight_overall(int rec, int loop) {
2311 return 2*rec + loop;
2314 static int compute_color (int my, int max) {
2321 /* if small, scale to the full color range. */
2323 my = my * (n_colors/max);
2325 step = 1 + (max / n_colors);
2329 return base_color + n_colors - color;
2332 static int get_entity_color(entity *ent) {
2333 ir_graph *irg = get_entity_irg(ent);
2337 int rec_depth = get_irg_recursion_depth(irg);
2338 int loop_depth = get_irg_loop_depth(irg);
2339 int overall_depth = weight_overall(rec_depth, loop_depth);
2341 int max_rec_depth = irp->max_callgraph_recursion_depth;
2342 int max_loop_depth = irp->max_callgraph_loop_depth;
2343 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2345 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2346 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2347 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2349 return my_overall_color;
2353 void dump_callgraph(const char *suffix) {
2355 int i, n_irgs = get_irp_n_irgs();
2356 int rem = edge_label;
2358 //ident *prefix = new_id_from_str("java/");
2360 F = vcg_open_name("Callgraph", suffix);
2361 dump_vcg_header(F, "Callgraph", NULL);
2363 for (i = 0; i < n_irgs; ++i) {
2364 ir_graph *irg = get_irp_irg(i);
2365 entity *ent = get_irg_entity(irg);
2366 int j, n_callees = get_irg_n_callees(irg);
2368 /* Do not dump runtime system. */
2369 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2371 dump_entity_node(F, ent, get_entity_color(ent));
2372 for (j = 0; j < n_callees; ++j) {
2373 entity *c = get_irg_entity(get_irg_callee(irg, j));
2374 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2375 int be = is_irg_callee_backedge(irg, j);
2378 "label:\"recursion %d\" color: %d" :
2379 "label:\"calls %d\" color: %d";
2380 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2388 /* Dump all irgs in interprocedural view to a single file. */
2389 void dump_all_cg_block_graph(const char *suffix) {
2392 int rem_view = get_interprocedural_view();
2393 set_interprocedural_view(true);
2395 f = vcg_open_name("All_graphs", suffix);
2396 dump_vcg_header(f, "All_graphs", NULL);
2398 /* collect nodes in all irgs reachable in call graph*/
2399 for (i = 0; i < get_irp_n_irgs(); i++)
2400 ird_set_irg_link(get_irp_irg(i), NULL);
2402 cg_walk(clear_link, collect_node, NULL);
2404 /* dump all graphs */
2405 for (i = 0; i < get_irp_n_irgs(); i++) {
2406 current_ir_graph = get_irp_irg(i);
2407 assert(ird_get_irg_link(current_ir_graph));
2408 dump_graph_from_list(f, current_ir_graph);
2409 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2413 set_interprocedural_view(rem_view);
2416 /*---------------------------------------------------------------------*/
2417 /* the following routines dumps type information without any ir nodes. */
2418 /*---------------------------------------------------------------------*/
2421 dump_type_graph (ir_graph *irg, const char *suffix)
2425 rem = current_ir_graph;
2427 /* if a filter is set, dump only the irg's that match the filter */
2428 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2430 current_ir_graph = irg;
2432 f = vcg_open(irg, suffix, "-type");
2433 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2435 /* walk over the blocks in the graph */
2436 type_walk_irg(irg, dump_type_info, NULL, f);
2437 /* The walker for the const code can be called several times for the
2438 same (sub) expression. So that no nodes are dumped several times
2439 we decrease the visited flag of the corresponding graph after each
2440 walk. So now increase it finally. */
2441 inc_irg_visited(get_const_code_irg());
2444 current_ir_graph = rem;
2448 dump_all_types (const char *suffix)
2450 FILE *f = vcg_open_name("All_types", suffix);
2451 dump_vcg_header(f, "All_types", NULL);
2452 type_walk(dump_type_info, NULL, f);
2453 inc_irg_visited(get_const_code_irg());
2458 dump_class_hierarchy (bool entities, const char *suffix)
2460 FILE *f = vcg_open_name("class_hierarchy", suffix);
2464 dump_vcg_header(f, "class_hierarchy", NULL);
2469 type_walk(dump_class_hierarchy_node, NULL, &env);
2473 /*---------------------------------------------------------------------*/
2474 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2476 /* dump_ir_block_graph */
2478 /* dump_type_graph */
2479 /* dump_ir_graph_w_types */
2480 /*---------------------------------------------------------------------*/
2482 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2483 int i, n_irgs = get_irp_n_irgs();
2484 for (i = 0; i < n_irgs; ++i) {
2485 dmp_grph(get_irp_irg(i), suffix);
2490 /*--------------------------------------------------------------------------------*
2491 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2492 * packed together in one subgraph/box *
2493 *--------------------------------------------------------------------------------*/
2495 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2496 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2498 ir_loop *son = NULL;
2500 /* Dump a new loop node. */
2501 dump_loop_node(F, loop);
2503 /* Dump the loop elements. */
2505 for(i = 0; i < get_loop_n_elements(loop); i++) {
2506 le = get_loop_element(loop, i);
2508 if (get_kind(son) == k_ir_loop) {
2510 /* We are a loop son -> Recurse */
2512 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2513 fprintf(F, "\" }\n");
2514 fprintf (F, "edge: {sourcename: \"");
2516 fprintf (F, "\" targetname: \"");
2518 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2519 loop_node_started = 0;
2521 dump_loop_son_edge(F, loop, son_number++);
2522 dump_loops_standalone(F, son);
2523 } else if (get_kind(son) == k_ir_node) {
2524 /* We are a loop node -> Collect firm nodes */
2526 ir_node *n = le.node;
2529 if (!loop_node_started) {
2530 /* Start a new node which contains all firm nodes of the current loop */
2531 fprintf (F, "node: { title: \"");
2533 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2534 loop_node_started = 1;
2540 bad |= dump_node_label(F, n);
2541 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2542 if (has_backedges(n)) fprintf(F, "\t loop head!");
2543 } else { /* for callgraph loop tree */
2545 assert(get_kind(son) == k_ir_graph);
2547 /* We are a loop node -> Collect firm graphs */
2548 n = (ir_graph *)le.node;
2549 if (!loop_node_started) {
2550 /* Start a new node which contains all firm nodes of the current loop */
2551 fprintf (F, "node: { title: \"");
2553 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2554 loop_node_started = 1;
2559 fprintf (F, " %s", get_irg_dump_name(n));
2560 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2564 if (loop_node_started) {
2565 fprintf(F, "\" }\n");
2566 fprintf (F, "edge: {sourcename: \"");
2568 fprintf (F, "\" targetname: \"");
2570 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2571 loop_node_started = 0;
2575 void dump_loop_tree(ir_graph *irg, const char *suffix)
2578 ir_graph *rem = current_ir_graph;
2579 int el_rem = edge_label;
2582 /* if a filter is set, dump only the irg's that match the filter */
2583 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2585 current_ir_graph = irg;
2587 f = vcg_open(irg, suffix, "-looptree");
2588 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2590 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2594 edge_label = el_rem;
2595 current_ir_graph = rem;
2598 void dump_callgraph_loop_tree(const char *suffix) {
2600 F = vcg_open_name("Callgraph_looptree", suffix);
2601 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2602 dump_loops_standalone(F, irp->outermost_cg_loop);
2607 /*-----------------------------------------------------------------------------*/
2608 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2609 /*-----------------------------------------------------------------------------*/
2611 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2612 int i, son_number = 0, node_number = 0;
2614 if (dump_loop_information_flag) dump_loop_node(F, loop);
2616 for (i = 0; i < get_loop_n_elements(loop); i++) {
2617 loop_element le = get_loop_element(loop, i);
2618 if (*(le.kind) == k_ir_loop) {
2619 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2621 collect_nodeloop(F, le.son, loopnodes);
2623 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2624 eset_insert(loopnodes, le.node);
2629 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2632 for(i = 0; i < get_loop_n_elements(loop); i++) {
2633 loop_element le = get_loop_element(loop, i);
2634 if (*(le.kind) == k_ir_loop) {
2636 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2638 if (is_Block(le.node)) start = 0; else start = -1;
2639 for (j = start; j < get_irn_arity(le.node); j++) {
2640 ir_node *pred = get_irn_n(le.node, j);
2641 if (!eset_contains(loopnodes, pred)) {
2642 eset_insert(extnodes, pred);
2643 if (!is_Block(pred)) {
2644 pred = get_nodes_block(pred);
2645 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2653 void dump_loop(ir_loop *l, const char *suffix) {
2656 eset *loopnodes = eset_create();
2657 eset *extnodes = eset_create();
2660 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2661 F = vcg_open_name (name, suffix);
2662 dump_vcg_header(F, name, NULL);
2664 /* collect all nodes to dump */
2665 collect_nodeloop(F, l, loopnodes);
2666 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2668 /* build block lists */
2669 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2670 set_irn_link(n, NULL);
2671 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2672 set_irn_link(n, NULL);
2673 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2675 b = get_nodes_block(n);
2676 set_irn_link(n, get_irn_link(b));
2679 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2681 b = get_nodes_block(n);
2682 set_irn_link(n, get_irn_link(b));
2686 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2688 fprintf(F, "graph: { title: \"");
2690 fprintf(F, "\" label: \"");
2691 dump_node_opcode(F, b);
2692 fprintf (F, " %ld", get_irn_node_nr(b));
2693 fprintf(F, "\" status:clustered color:yellow\n");
2695 /* dump the blocks edges */
2696 dump_ir_data_edges(F, b);
2698 /* dump the nodes that go into the block */
2699 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2700 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2702 overrule_nodecolor = NULL;
2703 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2706 /* Close the vcg information for the block */
2708 dump_const_node_local(F, b);
2711 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2713 fprintf(F, "graph: { title: \"");
2715 fprintf(F, "\" label: \"");
2716 dump_node_opcode(F, b);
2717 fprintf (F, " %ld", get_irn_node_nr(b));
2718 fprintf(F, "\" status:clustered color:lightblue\n");
2720 /* dump the nodes that go into the block */
2721 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2722 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2724 overrule_nodecolor = NULL;
2725 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2728 /* Close the vcg information for the block */
2730 dump_const_node_local(F, b);
2734 eset_destroy(loopnodes);
2735 eset_destroy(extnodes);