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.
18 #include "firm_common_t.h"
21 #include "irgraph_t.h"
31 #include "type_or_entity.h"
35 #include "callgraph.h"
45 void dump_chi_term(FILE *FL, ir_node *n);
46 void dump_state(FILE *FL, ir_node *n);
47 int get_opt_dump_abstvals(void);
48 typedef unsigned long SeqNo;
49 SeqNo get_Block_seqno(ir_node *n);
52 /* basis for a color range for vcg */
53 static int n_colors = 0;
54 static int base_color = 0;
56 #define ERROR_TXT "<ERROR>"
59 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
60 * in the later case, sets bad
62 const char *get_mode_name_ex(ir_mode *mode, int *bad)
65 return get_mode_name(mode);
71 * returns the name of a type or <ERROR> if mode is NOT a mode object.
72 * in the later case, sets bad
74 const char *get_type_name_ex(type *tp, int *bad)
77 return get_type_name(tp);
83 * prints the edge from a type S to a type T with additional info fmt, ...
86 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
91 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
92 fprintf(F, " targetname: "); PRINT_TYPEID(T);
99 * prints the edge from a type T to an entity E with additional info fmt, ...
102 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
107 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
108 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
109 vfprintf(F, fmt, ap);
115 * prints the edge from an entity E to an entity T with additional info fmt, ...
118 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
124 fprintf(F, "backedge: { sourcename: \"");
126 fprintf(F, "edge: { sourcename: \"");
128 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
129 vfprintf(F, fmt, ap);
135 * prints the edge from an entity E to a type T with additional info fmt, ...
138 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
143 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
144 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
145 vfprintf(F, fmt, ap);
151 * prints the edge from a node N to a type T with additional info fmt, ...
154 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
159 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
160 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
161 vfprintf(F, fmt, ap);
167 * prints the edge from a node N to an entity E with additional info fmt, ...
170 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
175 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
176 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
178 vfprintf(F, fmt, ap);
184 * prints the edge from an entity E to a node N with additional info fmt, ...
187 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
192 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
193 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
194 vfprintf(F, fmt, ap);
200 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
203 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
208 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
209 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
210 vfprintf(F, fmt, ap);
215 /*-----------------------------------------------------------------*/
216 /* global and ahead declarations */
217 /*-----------------------------------------------------------------*/
219 static void dump_whole_node(ir_node *n, void *env);
220 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
222 /*-----------------------------------------------------------------*/
223 /* Helper functions. */
224 /*-----------------------------------------------------------------*/
227 * This map is used as a private link attr to be able to call dumper
228 * anywhere without destroying link fields.
230 static pmap *irdump_link_map = NULL;
232 /** Creates the link attribut map. */
233 static void init_irdump(void) {
234 /* We need a new, empty map. */
235 if (irdump_link_map) pmap_destroy(irdump_link_map);
236 irdump_link_map = pmap_create();
240 * Returns the private link field.
242 static void *ird_get_irn_link(ir_node *n) {
244 if (!irdump_link_map) return NULL;
246 if (pmap_contains(irdump_link_map, (void *)n))
247 res = pmap_get(irdump_link_map, (void *)n);
252 * Sets the private link field.
254 static void ird_set_irn_link(ir_node *n, void *x) {
255 if (!irdump_link_map) init_irdump();
256 pmap_insert(irdump_link_map, (void *)n, x);
260 * Gets the private link field of an irg.
262 static void *ird_get_irg_link(ir_graph *irg) {
264 if (!irdump_link_map) return NULL;
266 if (pmap_contains(irdump_link_map, (void *)irg))
267 res = pmap_get(irdump_link_map, (void *)irg);
272 * Sets the private link field of an irg.
274 static void ird_set_irg_link(ir_graph *irg, void *x) {
275 if (!irdump_link_map) init_irdump();
276 pmap_insert(irdump_link_map, (void *)irg, x);
280 * Walker, clears tzhe private link field
282 static void clear_link(ir_node * node, void * env) {
283 ird_set_irn_link(node, NULL);
287 * If the entity has a ld_name, returns it, else returns the name of the entity.
289 const char *get_ent_dump_name(entity *ent) {
291 return "<NULL entity>";
292 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
293 if (ent->ld_name) return get_id_str(ent->ld_name);
294 return get_id_str(ent->name);
297 /* Returns the name of an IRG. */
298 const char *get_irg_dump_name(ir_graph *irg) {
299 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
300 entity *ent = get_irg_entity(irg);
301 return get_ent_dump_name(ent);
305 * Returns non-zero if a node is in floating state.
307 static int node_floats(ir_node *n) {
308 return ((get_irn_pinned(n) == op_pin_state_floats) &&
309 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
313 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
315 static void collect_node(ir_node * node, void *env) {
318 || get_irn_op(node) == op_Bad
319 || get_irn_op(node) == op_Unknown
320 || get_irn_op(node) == op_NoMem) {
321 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
322 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
323 ARR_APP1(ir_node *, arr, node);
324 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
326 ir_node * block = get_nodes_block(node);
329 /* this node is in a Bad block, so we must place it into the graph's list */
330 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
331 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
332 ARR_APP1(ir_node *, arr, node);
333 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
336 ird_set_irn_link(node, ird_get_irn_link(block));
337 ird_set_irn_link(block, node);
342 /** Construct lists to walk ir block-wise.
344 * Collects all blocks, nodes not op_pin_state_pinned,
345 * Bad, NoMem and Unknown into a flexible array in link field of
346 * irg they belong to. Sets the irg link field to NULL in all
347 * graphs not visited.
348 * Free the list with DEL_ARR_F().
350 static ir_node ** construct_block_lists(ir_graph *irg) {
351 int i, rem_view = get_interprocedural_view();
352 ir_graph *rem = current_ir_graph;
353 current_ir_graph = irg;
355 for (i = 0; i < get_irp_n_irgs(); i++)
356 ird_set_irg_link(get_irp_irg(i), NULL);
358 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
360 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
361 set_interprocedural_view(false);
363 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
364 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
365 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
366 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
368 set_interprocedural_view(rem_view);
370 current_ir_graph = rem;
371 return ird_get_irg_link(irg);
374 /*******************************************************************/
375 /* flags to steer output */
376 /*******************************************************************/
378 /** Dump only irgs with names start with this string */
379 const char *dump_file_filter = "";
381 /** A compiler option to turn off edge labels */
382 static int edge_label = 1;
383 /** A compiler option to turn off dumping values of constant entities */
384 static int const_entities = 1;
385 /** A compiler option to dump the keep alive edges */
386 static int dump_keepalive = 0;
387 /** Compiler options to dump analysis information in dump_ir_graph */
388 int dump_out_edge_flag = 0;
389 int dump_dominator_information_flag = 0;
390 int dump_loop_information_flag = 0;
391 int dump_backedge_information_flag = 1;
392 int dump_const_local = 0;
393 bool opt_dump_analysed_type_info = 1;
394 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
396 static const char *overrule_nodecolor = NULL;
398 /** The vcg attribute hook. */
399 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
402 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
404 dump_node_vcgattr_hook = hook;
407 INLINE bool get_opt_dump_const_local(void) {
408 if (!dump_out_edge_flag && !dump_loop_information_flag)
409 return dump_const_local;
414 void only_dump_method_with_name(ident *name) {
415 dump_file_filter = get_id_str(name);
419 /* To turn off display of edge labels. Edge labels offen cause xvcg to
420 abort with a segmentation fault. */
421 void turn_off_edge_labels(void) {
425 void dump_consts_local(bool b) {
426 dump_const_local = b;
429 void turn_off_constant_entity_values(void) {
433 void dump_keepalive_edges(bool b) {
437 bool get_opt_dump_keepalive_edges(void) {
438 return dump_keepalive;
441 void dump_out_edges(void) {
442 dump_out_edge_flag = 1;
445 void dump_dominator_information(void) {
446 dump_dominator_information_flag = 1;
449 void dump_loop_information(void) {
450 dump_loop_information_flag = 1;
453 void dont_dump_loop_information(void) {
454 dump_loop_information_flag = 0;
457 void dump_backedge_information(bool b) {
458 dump_backedge_information_flag = b;
461 /* Dump the information of type field specified in ana/irtypeinfo.h.
462 * If the flag is set, the type name is output in [] in the node label,
463 * else it is output as info.
465 void dump_analysed_type_info(bool b) {
466 opt_dump_analysed_type_info = b;
469 void dump_pointer_values_to_info(bool b) {
470 opt_dump_pointer_values_to_info = b;
473 /*-----------------------------------------------------------------*/
474 /* Routines to dump information about a single ir node. */
475 /*-----------------------------------------------------------------*/
478 * dump the name of a node n to the File F.
481 dump_node_opcode(FILE *F, ir_node *n)
485 switch(get_irn_opcode(n)) {
490 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
491 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
496 if (get_SymConst_kind(n) == symconst_addr_name) {
497 /* don't use get_SymConst_ptr_info as it mangles the name. */
498 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
499 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
500 assert(get_SymConst_entity(n));
501 assert(is_entity(get_SymConst_entity(n)));
502 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
504 assert(get_kind(get_SymConst_type(n)) == k_type);
505 assert(get_type_ident(get_SymConst_type(n)));
506 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
507 if (get_SymConst_kind(n) == symconst_type_tag)
515 if (!get_interprocedural_view())
522 ir_node *pred = get_Proj_pred(n);
524 if (get_irn_opcode(pred) == iro_Cond
525 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
526 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
527 fprintf (F, "defProj");
529 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
530 * fprintf (F, "Arg");
539 if (get_interprocedural_view()) {
540 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
545 case iro_CallBegin: {
546 ir_node *addr = get_CallBegin_ptr(n);
548 if (get_irn_op(addr) == op_Sel)
549 ent = get_Sel_entity(addr);
550 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
551 ent = get_SymConst_entity(addr);
552 fprintf (F, "%s", get_irn_opname(n));
553 if (ent) fprintf (F, " %s", get_entity_name(ent));
557 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
562 fprintf (F, "%s", get_irn_opname(n));
570 * Dump the mode of a node n to a file F.
571 * Ignore modes that are "always known".
574 dump_node_mode(FILE *F, ir_node *n)
577 opcode iro = get_irn_opcode(n);
590 ir_mode *mode = get_irn_mode(n);
592 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
593 (mode != mode_T || iro == iro_Proj))
594 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
602 * Dump the tpe of a node n to a file F if it's known.
604 static int dump_node_typeinfo(FILE *F, ir_node *n) {
607 if (opt_dump_analysed_type_info) {
608 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
609 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
610 type *tp = get_irn_typeinfo_type(n);
612 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
621 * Dump addinional node attributes of some nodes to a file F.
624 dump_node_nodeattr(FILE *F, ir_node *n)
628 switch (get_irn_opcode(n)) {
630 if (false && get_interprocedural_view()) {
631 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
635 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
636 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
638 fprintf (F, "%ld", get_Proj_proj(n));
642 fprintf (F, "%ld", get_Filter_proj(n));
645 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
648 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
651 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
662 * dumps the attributes of a node n into the file F.
663 * Currently this is only the color of a node.
665 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
668 fprintf(F, "color: red");
672 if (dump_node_vcgattr_hook)
673 if (dump_node_vcgattr_hook(F, n))
676 switch (get_irn_opcode(n)) {
683 fprintf (F, "color: blue");
686 fprintf (F, "color: lightyellow");
689 fprintf (F, "color: green");
695 fprintf (F, "color: yellow");
698 PRINT_DEFAULT_NODE_ATTR;
701 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
705 /* Replace this once I can do a reference. */
708 * Dump the node information of a node n to a file F.
710 static INLINE int dump_node_info(FILE *F, ir_node *n)
712 fprintf (F, " info1: \"");
713 bad = dump_irnode_to_file(F, n);
719 * Dump the node information of a node n to a file F.
721 static INLINE int dump_node_info(FILE *F, ir_node *n)
727 fprintf (F, " info1: \"");
728 if (opt_dump_pointer_values_to_info)
729 fprintf (F, "addr: %p\n", (void *)n);
730 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
731 fprintf (F, "visited: %ld\n", get_irn_visited(n));
732 irg = get_irn_irg(n);
733 if (irg != get_const_code_irg())
734 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
736 if (get_irn_pinned(n) == op_pin_state_floats &&
737 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
738 fprintf(F, "node was pinned in ");
739 dump_node_opcode(F, get_nodes_block(n));
740 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
744 /* show all predecessor nodes */
745 fprintf(F, "pred nodes: \n");
748 dump_node_opcode(F, get_nodes_block(n));
749 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
751 for ( i = 0; i < get_irn_arity(n); ++i) {
752 fprintf(F, " %d: ", i);
753 dump_node_opcode(F, get_irn_n(n, i));
754 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
758 fprintf(F, "arity: %d", get_irn_arity(n));
759 if ((get_irn_op(n) == op_Block) ||
760 (get_irn_op(n) == op_Phi) ||
761 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
762 fprintf(F, " backedges:");
764 for (i = 0; i < get_irn_arity(n); i++)
765 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
769 /* Loop node Someone else please tell me what's wrong ...
770 if (get_irn_loop(n)) {
771 ir_loop *loop = get_irn_loop(n);
773 fprintf(F, " in loop %d with depth %d\n",
774 get_loop_loop_nr(loop), get_loop_depth(loop));
779 switch (get_irn_opcode(n)) {
781 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
782 fprintf(F, "start of method of type %s\n", get_type_name_ex(tp, &bad));
783 for (i = 0; i < get_method_n_params(tp); ++i)
784 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
785 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
786 ir_node *sbl = get_nodes_block(n);
787 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
788 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
789 for (i = 0; i < n_cfgpreds; ++i) {
790 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
791 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
792 get_irg_dump_name(get_irn_irg(cfgpred)));
797 fprintf(F, "allocating entity of type %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
800 fprintf(F, "freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
803 entity *ent = get_Sel_entity(n);
806 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
807 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
810 fprintf(F, "<NULL entity>\n");
815 type *tp = get_Call_type(n);
816 fprintf(F, "calling method of type %s\n", get_type_name_ex(tp, &bad));
817 if(get_unknown_type() != tp) {
818 for (i = 0; i < get_method_n_params(tp); ++i)
819 fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
820 for (i = 0; i < get_method_n_ress(tp); ++i)
821 fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
823 if (Call_has_callees(n)) {
824 fprintf(F, "possible callees:\n");
825 for (i = 0; i < get_Call_n_callees(n); i++) {
826 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
830 case iro_CallBegin: {
831 ir_node *call = get_CallBegin_call(n);
832 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
833 if (Call_has_callees(call)) {
834 fprintf(F, "possible callees: \n");
835 for (i = 0; i < get_Call_n_callees(call); i++) {
836 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
841 if (!get_interprocedural_view()) {
842 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
843 fprintf(F, "return in method of type %s\n", get_type_name_ex(tp, &bad));
844 for (i = 0; i < get_method_n_ress(tp); ++i)
845 fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
849 type *tp = get_Const_type(n);
850 assert(tp != none_type);
851 fprintf(F, "Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
854 switch(get_SymConst_kind(n)) {
855 case symconst_addr_name:
856 fprintf(F, "kind: addr_name\n");
858 case symconst_addr_ent:
859 fprintf(F, "kind: addr_ent\n");
860 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
862 case symconst_type_tag:
863 fprintf(F, "kind: type_tag\n");
866 fprintf(F, "kind: size\n");
869 fprintf(F, "SymConst of type: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
873 if (get_interprocedural_view()) {
874 fprintf(F, "intra predecessor nodes:\n");
875 for (i = 0; i < get_irn_intra_arity(n); i++) {
876 ir_node *pred = get_irn_intra_n(n, i);
877 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
880 fprintf(F, "inter predecessor nodes:\n");
881 for (i = 0; i < get_irn_inter_arity(n); i++) {
882 ir_node *pred = get_irn_inter_n(n, i);
883 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
884 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
889 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
892 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
898 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
899 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
900 if (get_irn_typeinfo_type(n) != none_type)
901 fprintf (F, "Analysed type: %s\n", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
910 * checks wheater a node is "constant-like", ie can be treated "block-less"
913 bool is_constlike_node(ir_node *n) {
914 ir_op *op = get_irn_op(n);
915 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
919 /** outputs the predecessors of n, that are constants, local. I.e.,
920 generates a copy of the constant predecessors for each node called with. */
921 static void dump_const_node_local(FILE *F, ir_node *n) {
923 if (!get_opt_dump_const_local()) return;
925 /* Use visited flag to avoid outputting nodes twice.
926 initialize it first. */
927 for (i = 0; i < get_irn_arity(n); i++) {
928 ir_node *con = get_irn_n(n, i);
929 if (is_constlike_node(con)) {
930 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
934 for (i = 0; i < get_irn_arity(n); i++) {
935 ir_node *con = get_irn_n(n, i);
936 if (is_constlike_node(con) && irn_not_visited(con)) {
939 mark_irn_visited(con);
940 /* Generate a new name for the node by appending the names of
942 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
943 fprintf(F, " label: \"");
944 bad |= dump_node_opcode(F, con);
945 bad |= dump_node_mode(F, con);
946 bad |= dump_node_typeinfo(F, con);
948 bad |= dump_node_nodeattr(F, con);
949 fprintf(F, " %ld", get_irn_node_nr(con));
951 bad |= dump_node_info(F, con);
952 dump_node_vcgattr(F, con, bad);
958 /** If the block of an edge is a const_like node, dump it local with an edge */
959 static void dump_const_block_local(FILE *F, ir_node *n) {
960 if (!get_opt_dump_const_local()) return;
962 ir_node *blk = get_nodes_block(n);
963 if (is_constlike_node(blk)) {
966 /* Generate a new name for the node by appending the names of
968 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
969 fprintf(F, "\" label: \"");
970 bad |= dump_node_opcode(F, blk);
971 bad |= dump_node_mode(F, blk);
972 bad |= dump_node_typeinfo(F, blk);
974 bad |= dump_node_nodeattr(F, blk);
975 fprintf(F, " %ld", get_irn_node_nr(blk));
977 bad |= dump_node_info(F, blk);
978 dump_node_vcgattr(F, blk, bad);
981 fprintf (F, "edge: { sourcename: \"");
983 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
984 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
989 * prints the error message of a node to a file F as info2.
991 static void INLINE print_node_error(FILE *F, const char *err_msg)
996 fprintf (F, " info2: \"%s\"", err_msg);
1002 static void dump_node(FILE *F, ir_node *n)
1007 if (get_opt_dump_const_local() && is_constlike_node(n))
1010 /* dump this node */
1011 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1013 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1014 bad |= dump_node_opcode(F, n);
1015 bad |= dump_node_mode(F, n);
1016 bad |= dump_node_typeinfo(F, n);
1018 bad |= dump_node_nodeattr(F, n);
1019 fprintf(F, " %ld", get_irn_node_nr(n));
1021 bad |= dump_node_info(F, n);
1022 print_node_error(F, p);
1023 dump_node_vcgattr(F, n, bad);
1025 dump_const_node_local(F, n);
1027 dump_chi_term(F, n);
1032 /** dump the edge to the block this node belongs to */
1034 dump_ir_block_edge(FILE *F, ir_node *n) {
1035 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1036 if (is_no_Block(n)) {
1037 ir_node *block = get_nodes_block(n);
1039 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1040 dump_const_block_local(F, n);
1043 fprintf (F, "edge: { sourcename: \"");
1045 fprintf (F, "\" targetname: ");
1046 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1047 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1053 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1054 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1055 fprintf (F, INTRA_DATA_EDGE_ATTR);
1057 fprintf (F, INTER_DATA_EDGE_ATTR);
1061 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1062 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1063 fprintf (F, INTRA_MEM_EDGE_ATTR);
1065 fprintf (F, INTER_MEM_EDGE_ATTR);
1069 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1072 if (dump_backedge_information_flag && is_backedge(from, to))
1073 fprintf (F, BACK_EDGE_ATTR);
1075 switch (get_irn_opcode(from)) {
1077 fprintf (F, CF_EDGE_ATTR);
1079 case iro_Start: break;
1082 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1083 fprintf (F, CF_EDGE_ATTR);
1084 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1085 fprintf (F, INTER_MEM_EDGE_ATTR);
1093 print_data_edge_vcgattr(F, from, to);
1098 print_mem_edge_vcgattr(F, from, to);
1100 print_data_edge_vcgattr(F, from, to);
1104 print_data_edge_vcgattr(F, from, to);
1109 print_mem_edge_vcgattr(F, from, to);
1111 print_data_edge_vcgattr(F, from, to);
1118 print_data_edge_vcgattr(F, from, to);
1125 print_mem_edge_vcgattr(F, from, to);
1127 print_data_edge_vcgattr(F, from, to);
1139 print_data_edge_vcgattr(F, from, to);
1142 if (get_irn_modecode(from) == irm_M)
1143 fprintf (F, INTER_MEM_EDGE_ATTR);
1145 print_data_edge_vcgattr(F, from, to);
1152 print_mem_edge_vcgattr(F, from, to);
1154 print_data_edge_vcgattr(F, from, to);
1157 print_mem_edge_vcgattr(F, from, to);
1159 case iro_Tuple: break;
1162 switch (get_irn_modecode(from)) {
1164 fprintf (F, CF_EDGE_ATTR);
1167 fprintf (F, INTER_MEM_EDGE_ATTR);
1170 print_data_edge_vcgattr(F, from, to);
1174 case iro_Bad: break;
1175 case iro_Unknown: break;
1177 switch (get_irn_modecode(from)) {
1179 fprintf (F, INTRA_MEM_EDGE_ATTR);
1182 fprintf (F, CF_EDGE_ATTR);
1185 print_data_edge_vcgattr(F, from, to);
1193 /* dump edges to our inputs */
1195 dump_ir_data_edges(FILE *F, ir_node *n) {
1196 int i, visited = get_irn_visited(n);
1198 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1201 for (i = 0; i < get_irn_arity(n); i++) {
1202 ir_node * pred = get_irn_n(n, i);
1205 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1206 continue; /* pred not dumped */
1208 if (dump_backedge_information_flag && is_backedge(n, i))
1209 fprintf (F, "backedge: {sourcename: \"");
1211 fprintf (F, "edge: {sourcename: \"");
1213 fprintf (F, "\" targetname: ");
1214 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1215 PRINT_CONSTID(n, pred);
1217 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1219 fprintf (F, " label: \"%d\" ", i);
1220 print_edge_vcgattr(F, n, i);
1225 /** Dumps a node and its edges but not the block edge
1228 dump_node_wo_blockedge (ir_node *n, void *env) {
1231 dump_ir_data_edges(F, n);
1234 /** Dumps a node and its edges.
1237 dump_whole_node (ir_node *n, void *env) {
1239 dump_node_wo_blockedge(n, env);
1240 if (!node_floats(n)) dump_ir_block_edge(F, n);
1244 dump_const_node(ir_node *n, void *env) {
1245 if (is_Block(n)) return;
1246 dump_node_wo_blockedge(n, env);
1249 /***********************************************************************/
1250 /* the following routines dump the nodes/irgs bracketed to graphs. */
1251 /***********************************************************************/
1253 /** Dumps a constant expression as entity initializer, array bound ...
1255 static void dump_const_expression(FILE *F, ir_node *value) {
1256 ir_graph *rem = current_ir_graph;
1257 int rem_dump_const_local = dump_const_local;
1258 dump_const_local = 0;
1259 current_ir_graph = get_const_code_irg();
1260 irg_walk(value, dump_const_node, NULL, F);
1261 /* Decrease visited flag so that we walk with the same flag for the next
1262 expresssion. This guarantees that we don't dump the same node twice,
1263 as for const expressions cse is performed to save memory. */
1264 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1265 current_ir_graph = rem;
1266 dump_const_local = rem_dump_const_local;
1269 /** Dump a block as graph containing its nodes.
1271 * Expects to find nodes belonging to the block as list in its
1273 * Dumps the edges of all nodes including itself. */
1275 dump_whole_block(FILE *F, ir_node *block) {
1277 assert(is_Block(block));
1279 fprintf(F, "graph: { title: \"");
1280 PRINT_NODEID(block);
1281 fprintf(F, "\" label: \"");
1282 dump_node_opcode(F, block);
1283 fprintf (F, " %ld", get_irn_node_nr(block));
1285 if (get_opt_dump_abstvals())
1286 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1288 fprintf(F, "\" status:clustered color:%s \n",
1289 get_Block_matured(block) ? "yellow" : "red");
1291 /* dump the blocks edges */
1292 dump_ir_data_edges(F, block);
1294 /* dump the nodes that go into the block */
1295 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1297 dump_ir_data_edges(F, node);
1300 /* Close the vcg information for the block */
1302 dump_const_node_local(F, block);
1304 dump_chi_term(F, block);
1309 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1310 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1312 dump_block_graph(FILE *F, ir_graph *irg) {
1314 ir_graph *rem = current_ir_graph;
1315 ir_node **arr = ird_get_irg_link(irg);
1316 current_ir_graph = irg;
1318 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1319 ir_node * node = arr[i];
1320 if (is_Block(node)) {
1321 /* Dumps the block and all the nodes in the block, which are to
1322 be found in Block->link. */
1323 dump_whole_block(F, node);
1325 /* Nodes that are not in a Block. */
1327 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1328 dump_const_block_local(F, node);
1330 dump_ir_data_edges(F, node);
1334 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1335 dump_loop_nodes_into_graph(F, irg);
1337 current_ir_graph = rem;
1340 /** Dumps an irg as a graph.
1341 * If interprocedural view edges can point to nodes out of this graph.
1343 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1345 fprintf(F, "graph: { title: \"");
1347 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1348 get_ent_dump_name(get_irg_entity(irg)));
1350 dump_block_graph(F, irg);
1352 /* Close the vcg information for the irg */
1353 fprintf(F, "}\n\n");
1356 /*******************************************************************/
1357 /* Basic type and entity nodes and edges. */
1358 /*******************************************************************/
1360 /** dumps the edges between nodes and their type or entity attributes. */
1361 static void dump_node2type_edges(ir_node *n, void *env)
1366 switch (get_irn_opcode(n)) {
1368 /* @@@ some consts have an entity */
1371 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1372 || (get_SymConst_kind(n) ==symconst_size))
1374 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1378 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1381 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1384 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1387 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1390 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1398 static int print_type_info(FILE *F, type *tp) {
1401 if (get_type_state(tp) == layout_undefined) {
1402 fprintf(F, "state: layout_undefined\n");
1404 fprintf(F, "state: layout_fixed,\n");
1406 if (get_type_mode(tp))
1407 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1408 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1413 static void print_typespecific_info(FILE *F, type *tp) {
1414 switch (get_type_tpop_code(tp)) {
1417 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1424 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1425 fprintf(F, "params: %d\n", get_method_n_params(tp));
1426 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1434 case tpo_enumeration:
1448 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1449 switch (get_type_tpop_code(tp)) {
1452 if (peculiarity_existent == get_class_peculiarity(tp))
1453 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1455 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1459 fprintf (F, " " TYPE_METH_NODE_ATTR);
1470 case tpo_enumeration:
1483 static int print_type_node(FILE *F, type *tp)
1487 fprintf (F, "node: {title: ");
1489 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1490 fprintf (F, " info1: \"");
1491 bad |= print_type_info(F, tp);
1492 print_typespecific_info(F, tp);
1494 print_typespecific_vcgattr(F, tp);
1500 #define X(a) case a: fprintf(F, #a); break
1501 void dump_entity_node(FILE *F, entity *ent, int color)
1503 fprintf (F, "node: {title: \"");
1504 PRINT_ENTID(ent); fprintf(F, "\"");
1505 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1506 fprintf (F, "label: ");
1507 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1509 fprintf(F, "color: %d", color);
1511 fprintf (F, ENTITY_NODE_ATTR);
1512 fprintf (F, "\n info1: \"");
1514 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1516 fprintf(F, "\"\n}\n");
1520 static void dump_enum_item(FILE *F, type *tp, int pos)
1523 ident *id = get_enumeration_nameid(tp, pos);
1524 tarval *tv = get_enumeration_enum(tp, pos);
1526 tarval_snprintf(buf, sizeof(buf), tv);
1527 fprintf (F, "node: {title: \"");
1528 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1529 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1530 fprintf (F, "label: ");
1531 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1532 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1535 /* dumps a type or entity and it's edges. */
1537 dump_type_info(type_or_ent *tore, void *env) {
1539 int i = 0; /* to shutup gcc */
1541 /* dump this type or entity */
1543 switch (get_kind(tore)) {
1546 entity *ent = (entity *)tore;
1549 dump_entity_node(F, ent, 0);
1551 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1552 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1553 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1554 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1555 if(is_class_type(get_entity_owner(ent))) {
1556 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1557 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1559 /* attached subgraphs */
1560 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1561 if (is_atomic_entity(ent)) {
1562 value = get_atomic_ent_value(ent);
1564 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1565 /* DDMN(value); $$$ */
1566 dump_const_expression(F, value);
1569 if (is_compound_entity(ent)) {
1570 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1571 value = get_compound_ent_value(ent, i);
1573 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1574 dump_const_expression(F, value);
1575 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1577 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1578 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1579 get_compound_ent_value_member(ent, i), i);
1588 type *tp = (type *)tore;
1589 print_type_node(F, tp);
1590 /* and now the edges */
1591 switch (get_type_tpop_code(tp)) {
1594 for (i=0; i < get_class_n_supertypes(tp); i++)
1595 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1596 for (i=0; i < get_class_n_members(tp); i++)
1597 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1601 for (i=0; i < get_struct_n_members(tp); i++)
1602 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1606 for (i = 0; i < get_method_n_params(tp); i++)
1607 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1608 for (i = 0; i < get_method_n_ress(tp); i++)
1609 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1613 for (i = 0; i < get_union_n_members(tp); i++)
1614 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1618 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1619 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1620 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1621 ir_node *upper = get_array_upper_bound(tp, i);
1622 ir_node *lower = get_array_lower_bound(tp, i);
1623 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1624 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1625 dump_const_expression(F, upper);
1626 dump_const_expression(F, lower);
1630 case tpo_enumeration:
1632 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1633 dump_enum_item(F, tp, i);
1634 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1639 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1647 break; /* case k_type */
1650 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1652 } /* switch kind_or_entity */
1655 typedef struct _h_env {
1660 /** For dumping class hierarchies.
1661 * Dumps a class type node and a superclass edge.
1662 * If env->dump_ent dumps entities of classes and overwrites edges.
1665 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1668 int i = 0; /* to shutup gcc */
1670 /* dump this type or entity */
1671 switch (get_kind(tore)) {
1673 entity *ent = (entity *)tore;
1674 if (get_entity_owner(ent) == get_glob_type()) break;
1675 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1676 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1678 dump_entity_node(F, ent, 0);
1680 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1681 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1682 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1684 } break; /* case k_entity */
1687 type *tp = (type *)tore;
1688 if (tp == get_glob_type()) break;
1689 switch (get_type_tpop_code(tp)) {
1691 print_type_node(F, tp);
1692 /* and now the edges */
1693 for (i=0; i < get_class_n_supertypes(tp); i++)
1695 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1701 break; /* case k_type */
1704 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1706 } /* switch kind_or_entity */
1709 /*******************************************************************/
1710 /* dump analysis information that is expressed in graph terms. */
1711 /*******************************************************************/
1713 /* dump out edges */
1715 dump_out_edge(ir_node *n, void *env) {
1718 for (i = 0; i < get_irn_n_outs(n); i++) {
1719 assert(get_irn_out(n, i));
1720 fprintf (F, "edge: {sourcename: \"");
1722 fprintf (F, "\" targetname: \"");
1723 PRINT_NODEID(get_irn_out(n, i));
1724 fprintf (F, "\" color: red linestyle: dashed");
1730 dump_loop_label(FILE *F, ir_loop *loop) {
1731 fprintf (F, "loop %d, %d sons, %d nodes",
1732 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1735 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1736 fprintf (F, " info1: \"");
1737 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1738 #if DEBUG_libfirm /* GL @@@ debug analyses */
1739 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1745 dump_loop_node(FILE *F, ir_loop *loop) {
1746 fprintf (F, "node: {title: \"");
1748 fprintf (F, "\" label: \"");
1749 dump_loop_label(F, loop);
1751 dump_loop_info(F, loop);
1757 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1759 fprintf (F, "edge: {sourcename: \"");
1761 fprintf (F, "\" targetname: \"");
1762 PRINT_NODEID(get_loop_node(loop, i));
1763 fprintf (F, "\" color: green");
1768 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1770 fprintf (F, "edge: {sourcename: \"");
1772 fprintf (F, "\" targetname: \"");
1773 PRINT_LOOPID(get_loop_son(loop, i));
1774 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1775 get_loop_element_pos(loop, get_loop_son(loop, i)));
1779 void dump_loops(FILE *F, ir_loop *loop) {
1781 /* dump this loop node */
1782 dump_loop_node(F, loop);
1784 /* dump edges to nodes in loop -- only if it is a real loop */
1785 if (get_loop_depth(loop) != 0) {
1786 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1787 dump_loop_node_edge(F, loop, i);
1790 for (i = 0; i < get_loop_n_sons(loop); i++) {
1791 dump_loops(F, get_loop_son(loop, i));
1792 dump_loop_son_edge(F, loop, i);
1797 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1798 ir_graph *rem = current_ir_graph;
1799 current_ir_graph = irg;
1801 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1803 current_ir_graph = rem;
1808 * dumps the VCG header
1810 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1819 if (!orientation) orientation = "bottom_to_top";
1823 "graph: { title: \"ir graph of %s\"\n"
1824 "display_edge_labels: %s\n"
1825 "layoutalgorithm: mindepth\n"
1826 "manhattan_edges: yes\n"
1827 "port_sharing: no\n"
1829 "classname 1: \"intrablock Data\"\n"
1830 "classname 16: \"interblock Data\"\n"
1831 "classname 2: \"Block\"\n"
1832 "classname 13: \"Control Flow\"\n"
1833 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1834 "classname 14: \"intrablock Memory\"\n"
1835 "classname 17: \"interblock Memory\"\n"
1836 "classname 15: \"Dominators\"\n"
1837 "classname 3: \"Entity type\"\n"
1838 "classname 4: \"Entity owner\"\n"
1839 "classname 5: \"Method Param\"\n"
1840 "classname 6: \"Method Res\"\n"
1841 "classname 7: \"Super\"\n"
1842 "classname 8: \"Union\"\n"
1843 "classname 9: \"Points-to\"\n"
1844 "classname 10: \"Array Element Type\"\n"
1845 "classname 11: \"Overwrites\"\n"
1846 "classname 12: \"Member\"\n"
1847 "infoname 1: \"Attribute\"\n"
1848 "infoname 2: \"Verification errors\"\n",
1849 name, label, orientation);
1851 /* don't use all, the range is too whith/black. */
1855 "colorentry 100: 0 0 0\n"
1856 "colorentry 101: 20 0 0\n"
1857 "colorentry 102: 40 0 0\n"
1858 "colorentry 103: 60 0 0\n"
1859 "colorentry 104: 80 0 0\n"
1860 "colorentry 105: 100 0 0\n"
1861 "colorentry 106: 120 0 0\n"
1862 "colorentry 107: 140 0 0\n"
1863 "colorentry 108: 150 0 0\n"
1864 "colorentry 109: 180 0 0\n"
1865 "colorentry 110: 200 0 0\n"
1866 "colorentry 111: 220 0 0\n"
1867 "colorentry 112: 240 0 0\n"
1868 "colorentry 113: 255 0 0\n"
1869 "colorentry 113: 255 20 20\n"
1870 "colorentry 114: 255 40 40\n"
1871 "colorentry 115: 255 60 60\n"
1872 "colorentry 116: 255 80 80\n"
1873 "colorentry 117: 255 100 100\n"
1874 "colorentry 118: 255 120 120\n"
1875 "colorentry 119: 255 140 140\n"
1876 "colorentry 120: 255 150 150\n"
1877 "colorentry 121: 255 180 180\n"
1878 "colorentry 122: 255 200 200\n"
1879 "colorentry 123: 255 220 220\n"
1880 "colorentry 124: 255 240 240\n"
1881 "colorentry 125: 255 250 250\n"
1884 fprintf (F, "\n"); /* a separator */
1890 * @param irg The graph to be dumped
1891 * @param suffix1 first filename suffix
1892 * @param suffix2 second filename suffix
1894 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1896 const char *nm = get_irg_dump_name(irg);
1897 int len = strlen(nm), i, j;
1898 char *fname; /* filename to put the vcg information in */
1900 if (!suffix1) suffix1 = "";
1901 if (!suffix2) suffix2 = "";
1903 /* open file for vcg graph */
1904 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1906 /* strncpy (fname, nm, len); */ /* copy the filename */
1908 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1910 fname[j] = '@'; j++; fname[j] = '1'; j++;
1911 } else if (nm[i] == '@') {
1912 fname[j] = '@'; j++; fname[j] = '2'; j++;
1914 fname[j] = nm[i]; j++;
1918 strcat (fname, suffix1); /* append file suffix */
1919 strcat (fname, suffix2); /* append file suffix */
1920 strcat (fname, ".vcg"); /* append the .vcg suffix */
1921 F = fopen (fname, "w"); /* open file for writing */
1923 panic("cannot open %s for writing (%m)", fname); /* not reached */
1933 * @param irg The graph to be dumped
1934 * @param suffix filename suffix
1936 static FILE *vcg_open_name (const char *name, const char *suffix) {
1938 char *fname; /* filename to put the vcg information in */
1939 int i, j, len = strlen(name);
1941 if (!suffix) suffix = "";
1943 /** open file for vcg graph */
1944 fname = malloc (len * 2 + 5 + strlen(suffix));
1945 /* strcpy (fname, name);*/ /* copy the filename */
1947 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1948 if (name[i] == '/') {
1949 fname[j] = '@'; j++; fname[j] = '1'; j++;
1950 } else if (name[i] == '@') {
1951 fname[j] = '@'; j++; fname[j] = '2'; j++;
1953 fname[j] = name[i]; j++;
1957 strcat (fname, suffix);
1958 strcat (fname, ".vcg"); /* append the .vcg suffix */
1959 F = fopen (fname, "w"); /* open file for writing */
1961 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1969 * Dumps the vcg file footer
1971 static INLINE void dump_vcg_footer (FILE *F) {
1976 * close the vcg file
1978 void vcg_close (FILE *F) {
1979 dump_vcg_footer(F); /* print footer */
1980 fclose (F); /* close vcg file */
1983 /************************************************************************/
1984 /************************************************************************/
1985 /* Routines that dump all or parts of the firm representation to a file */
1986 /************************************************************************/
1987 /************************************************************************/
1989 /************************************************************************/
1990 /* Dump ir graphs, differnt formats and additional information. */
1991 /************************************************************************/
1993 /** Routine to dump a graph, blocks as conventional nodes. */
1995 dump_ir_graph (ir_graph *irg, const char *suffix )
2000 rem = current_ir_graph;
2002 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2003 current_ir_graph = irg;
2004 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2005 else suffix1 = "-pure";
2006 f = vcg_open(irg, suffix, suffix1);
2007 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2009 /* walk over the graph */
2010 /* dump_whole_node must be called in post visiting predecessors */
2011 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2013 /* dump the out edges in a separate walk */
2014 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2015 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2020 current_ir_graph = rem;
2025 dump_ir_block_graph (ir_graph *irg, const char *suffix)
2031 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2034 if (get_interprocedural_view()) suffix1 = "-ip";
2036 f = vcg_open(irg, suffix, suffix1);
2037 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2039 construct_block_lists(irg);
2041 for (i = 0; i < get_irp_n_irgs(); i++) {
2042 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2044 dump_graph_from_list(f, get_irp_irg(i));
2052 /** dumps a graph with type information */
2054 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2057 ir_graph *rem = current_ir_graph;
2060 /* if a filter is set, dump only the irg's that match the filter */
2061 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2064 current_ir_graph = irg;
2066 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2067 else suffix1 = "-pure-wtypes";
2068 f = vcg_open(irg,suffix, suffix1);
2069 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2071 /* dump common ir graph */
2072 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2073 /* dump type info */
2074 type_walk_irg(irg, dump_type_info, NULL, f);
2075 inc_irg_visited(get_const_code_irg());
2076 /* dump edges from graph to type info */
2077 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2080 current_ir_graph = rem;
2084 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2089 ir_graph *rem = current_ir_graph;
2091 /* if a filter is set, dump only the irg's that match the filter */
2092 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2095 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2096 else suffix1 = "-wtypes";
2097 f = vcg_open(irg, suffix, suffix1);
2098 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2100 /* dump common blocked ir graph */
2101 construct_block_lists(irg);
2103 for (i = 0; i < get_irp_n_irgs(); i++) {
2104 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2106 dump_graph_from_list(f, get_irp_irg(i));
2111 /* dump type info */
2112 current_ir_graph = irg;
2113 type_walk_irg(irg, dump_type_info, NULL, f);
2114 inc_irg_visited(get_const_code_irg());
2116 /* dump edges from graph to type info */
2117 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2119 current_ir_graph = rem;
2123 /*---------------------------------------------------------------------*/
2124 /* The following routines dump a control flow graph. */
2125 /*---------------------------------------------------------------------*/
2128 dump_block_to_cfg(ir_node *block, void *env) {
2133 if (is_Block(block)) {
2134 /* This is a block. Dump a node for the block. */
2135 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2136 fprintf (F, "\" label: \"");
2137 if (block == get_irg_start_block(get_irn_irg(block)))
2138 fprintf(F, "Start ");
2139 if (block == get_irg_end_block(get_irn_irg(block)))
2142 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2143 PRINT_NODEID(block);
2145 fprintf(F, "info1:\"");
2146 if (dump_dominator_information_flag)
2147 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2149 /* show arity and possible Bad predecessors of the block */
2150 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2151 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2152 ir_node *pred = get_Block_cfgpred(block, i);
2155 fprintf(F, "Bad pred at pos: ");
2156 fprintf(F, "%d ", i);
2163 fprintf (F, "\""); /* closing quote of info */
2165 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2166 (block == get_irg_end_block(get_irn_irg(block))) )
2167 fprintf(F, " color:blue ");
2169 fprintf(F, " color:yellow ");
2172 /* Dump the edges */
2173 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2174 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2175 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2176 fprintf (F, "edge: { sourcename: \"");
2177 PRINT_NODEID(block);
2178 fprintf (F, "\" targetname: \"");
2180 fprintf (F, "\"}\n");
2183 /* Dump dominator edge */
2184 if (dump_dominator_information_flag && get_Block_idom(block)) {
2185 pred = get_Block_idom(block);
2186 fprintf (F, "edge: { sourcename: \"");
2187 PRINT_NODEID(block);
2188 fprintf (F, "\" targetname: \"");
2190 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2196 dump_cfg (ir_graph *irg, const char *suffix)
2199 ir_graph *rem = current_ir_graph;
2200 int ddif = dump_dominator_information_flag;
2201 int ipv = get_interprocedural_view();
2203 /* if a filter is set, dump only the irg's that match the filter */
2204 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2207 current_ir_graph = irg;
2209 f = vcg_open(irg, suffix, "-cfg");
2210 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2213 printf("Warning: dumping cfg not in interprocedural view!\n");
2214 set_interprocedural_view(false);
2217 if (get_irg_dom_state(irg) != dom_consistent)
2218 dump_dominator_information_flag = 0;
2220 /* walk over the blocks in the graph */
2221 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2222 dump_node(f, get_irg_bad(irg));
2224 dump_dominator_information_flag = ddif;
2225 set_interprocedural_view(ipv);
2227 current_ir_graph = rem;
2230 static int weight_overall(int rec, int loop) {
2231 return 2*rec + loop;
2234 static int compute_color (int my, int max) {
2239 /* if small, scale to the full color range. */
2241 my = my * (n_colors/max);
2243 int step = 1 + (max / n_colors);
2247 return base_color + n_colors - color;
2250 static int get_entity_color(entity *ent) {
2251 assert(get_entity_irg(ent));
2252 ir_graph *irg = get_entity_irg(ent);
2254 int rec_depth = get_irg_recursion_depth(irg);
2255 int loop_depth = get_irg_loop_depth(irg);
2256 int overall_depth = weight_overall(rec_depth, loop_depth);
2258 int max_rec_depth = irp->max_callgraph_recursion_depth;
2259 int max_loop_depth = irp->max_callgraph_loop_depth;
2260 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2262 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2263 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2264 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2266 return my_overall_color;
2269 void dump_callgraph(const char *suffix) {
2271 int i, n_irgs = get_irp_n_irgs();
2272 int rem = edge_label;
2274 //ident *prefix = new_id_from_str("java/");
2276 F = vcg_open_name("Callgraph", suffix);
2277 dump_vcg_header(F, "Callgraph", NULL);
2279 for (i = 0; i < n_irgs; ++i) {
2280 ir_graph *irg = get_irp_irg(i);
2281 entity *ent = get_irg_entity(irg);
2282 int j, n_callees = get_irg_n_callees(irg);
2284 /* Do not dump runtime system. */
2285 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2287 dump_entity_node(F, ent, get_entity_color(ent));
2288 for (j = 0; j < n_callees; ++j) {
2289 entity *c = get_irg_entity(get_irg_callee(irg, j));
2290 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2291 int be = is_irg_callee_backedge(irg, j);
2294 "label:\"recursion %d\" color: %d" :
2295 "label:\"calls %d\" color: %d";
2296 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2304 /* Dump all irgs in interprocedural view to a single file. */
2305 void dump_all_cg_block_graph(const char *suffix) {
2308 int rem_view = get_interprocedural_view();
2309 set_interprocedural_view(true);
2311 f = vcg_open_name("All_graphs", suffix);
2312 dump_vcg_header(f, "All_graphs", NULL);
2314 /* collect nodes in all irgs reachable in call graph*/
2315 for (i = 0; i < get_irp_n_irgs(); i++)
2316 ird_set_irg_link(get_irp_irg(i), NULL);
2318 cg_walk(clear_link, collect_node, NULL);
2320 /* dump all graphs */
2321 for (i = 0; i < get_irp_n_irgs(); i++) {
2322 current_ir_graph = get_irp_irg(i);
2323 assert(ird_get_irg_link(current_ir_graph));
2324 dump_graph_from_list(f, current_ir_graph);
2325 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2329 set_interprocedural_view(rem_view);
2332 /*---------------------------------------------------------------------*/
2333 /* the following routines dumps type information without any ir nodes. */
2334 /*---------------------------------------------------------------------*/
2337 dump_type_graph (ir_graph *irg, const char *suffix)
2341 rem = current_ir_graph;
2343 /* if a filter is set, dump only the irg's that match the filter */
2344 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2346 current_ir_graph = irg;
2348 f = vcg_open(irg, suffix, "-type");
2349 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2351 /* walk over the blocks in the graph */
2352 type_walk_irg(irg, dump_type_info, NULL, f);
2353 /* The walker for the const code can be called several times for the
2354 same (sub) experssion. So that no nodes are dumped several times
2355 we decrease the visited flag of the corresponding graph after each
2356 walk. So now increase it finally. */
2357 inc_irg_visited(get_const_code_irg());
2360 current_ir_graph = rem;
2364 dump_all_types (const char *suffix)
2366 FILE *f = vcg_open_name("All_types", suffix);
2367 dump_vcg_header(f, "All_types", NULL);
2368 type_walk(dump_type_info, NULL, f);
2369 inc_irg_visited(get_const_code_irg());
2374 dump_class_hierarchy (bool entities, const char *suffix)
2376 FILE *f = vcg_open_name("class_hierarchy", suffix);
2380 dump_vcg_header(f, "class_hierarchy", NULL);
2385 type_walk(dump_class_hierarchy_node, NULL, &env);
2389 /*---------------------------------------------------------------------*/
2390 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2392 /* dump_ir_block_graph */
2394 /* dump_type_graph */
2395 /* dump_ir_graph_w_types */
2396 /*---------------------------------------------------------------------*/
2398 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2399 int i, n_irgs = get_irp_n_irgs();
2400 for (i = 0; i < n_irgs; ++i) {
2401 dmp_grph(get_irp_irg(i), suffix);
2406 /*--------------------------------------------------------------------------------*
2407 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2408 * packed together in one subgraph/box *
2409 *--------------------------------------------------------------------------------*/
2411 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2412 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2414 ir_loop *son = NULL;
2416 /* Dump a new loop node. */
2417 dump_loop_node(F, loop);
2419 /* Dump the loop elements. */
2421 for(i = 0; i < get_loop_n_elements(loop); i++) {
2422 le = get_loop_element(loop, i);
2424 if (get_kind(son) == k_ir_loop) {
2426 /* We are a loop son -> Recurse */
2428 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2429 fprintf(F, "\" }\n");
2430 fprintf (F, "edge: {sourcename: \"");
2432 fprintf (F, "\" targetname: \"");
2434 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2435 loop_node_started = 0;
2437 dump_loop_son_edge(F, loop, son_number++);
2438 dump_loops_standalone(F, son);
2439 } else if (get_kind(son) == k_ir_node) {
2440 /* We are a loop node -> Collect firm nodes */
2442 ir_node *n = le.node;
2445 if (!loop_node_started) {
2446 /* Start a new node which contains all firm nodes of the current loop */
2447 fprintf (F, "node: { title: \"");
2449 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2450 loop_node_started = 1;
2456 bad |= dump_node_opcode(F, n);
2457 bad |= dump_node_mode(F, n);
2458 bad |= dump_node_typeinfo(F, n);
2460 bad |= dump_node_nodeattr(F, n);
2461 fprintf (F, " %ld", get_irn_node_nr(n));
2462 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2463 if (has_backedges(n)) fprintf(F, "\t loop head!");
2464 } else { /* for callgraph loop tree */
2465 assert(get_kind(son) == k_ir_graph);
2466 /* We are a loop node -> Collect firm graphs */
2467 ir_graph *n = (ir_graph *)le.node;
2468 if (!loop_node_started) {
2469 /* Start a new node which contains all firm nodes of the current loop */
2470 fprintf (F, "node: { title: \"");
2472 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2473 loop_node_started = 1;
2478 fprintf (F, " %s", get_irg_dump_name(n));
2479 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2483 if (loop_node_started) {
2484 fprintf(F, "\" }\n");
2485 fprintf (F, "edge: {sourcename: \"");
2487 fprintf (F, "\" targetname: \"");
2489 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2490 loop_node_started = 0;
2494 void dump_loop_tree(ir_graph *irg, const char *suffix)
2497 ir_graph *rem = current_ir_graph;
2498 int el_rem = edge_label;
2501 /* if a filter is set, dump only the irg's that match the filter */
2502 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2505 current_ir_graph = irg;
2507 f = vcg_open(irg, suffix, "-looptree");
2508 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2510 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2514 edge_label = el_rem;
2515 current_ir_graph = rem;
2518 void dump_callgraph_loop_tree(const char *suffix) {
2520 F = vcg_open_name("Callgraph_looptree", suffix);
2521 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2522 dump_loops_standalone(F, irp->outermost_cg_loop);
2527 /*-----------------------------------------------------------------------------*/
2528 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2529 /*-----------------------------------------------------------------------------*/
2531 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2532 int i, son_number = 0, node_number = 0;
2534 if (dump_loop_information_flag) dump_loop_node(F, loop);
2536 for (i = 0; i < get_loop_n_elements(loop); i++) {
2537 loop_element le = get_loop_element(loop, i);
2538 if (*(le.kind) == k_ir_loop) {
2539 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2541 collect_nodeloop(F, le.son, loopnodes);
2543 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2544 eset_insert(loopnodes, le.node);
2549 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2552 for(i = 0; i < get_loop_n_elements(loop); i++) {
2553 loop_element le = get_loop_element(loop, i);
2554 if (*(le.kind) == k_ir_loop) {
2556 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2558 if (is_Block(le.node)) start = 0; else start = -1;
2559 for (j = start; j < get_irn_arity(le.node); j++) {
2560 ir_node *pred = get_irn_n(le.node, j);
2561 if (!eset_contains(loopnodes, pred)) {
2562 eset_insert(extnodes, pred);
2563 if (!is_Block(pred)) {
2564 pred = get_nodes_block(pred);
2565 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2573 void dump_loop(ir_loop *l, const char *suffix) {
2576 eset *loopnodes = eset_create();
2577 eset *extnodes = eset_create();
2580 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2581 F = vcg_open_name (name, suffix);
2582 dump_vcg_header(F, name, NULL);
2584 /* collect all nodes to dump */
2585 collect_nodeloop(F, l, loopnodes);
2586 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2588 /* build block lists */
2589 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2590 set_irn_link(n, NULL);
2591 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2592 set_irn_link(n, NULL);
2593 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2595 b = get_nodes_block(n);
2596 set_irn_link(n, get_irn_link(b));
2599 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2601 b = get_nodes_block(n);
2602 set_irn_link(n, get_irn_link(b));
2606 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2608 fprintf(F, "graph: { title: \"");
2610 fprintf(F, "\" label: \"");
2611 dump_node_opcode(F, b);
2612 fprintf (F, " %ld", get_irn_node_nr(b));
2613 fprintf(F, "\" status:clustered color:yellow\n");
2615 /* dump the blocks edges */
2616 dump_ir_data_edges(F, b);
2618 /* dump the nodes that go into the block */
2619 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2620 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2622 overrule_nodecolor = NULL;
2623 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2626 /* Close the vcg information for the block */
2628 dump_const_node_local(F, b);
2631 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2633 fprintf(F, "graph: { title: \"");
2635 fprintf(F, "\" label: \"");
2636 dump_node_opcode(F, b);
2637 fprintf (F, " %ld", get_irn_node_nr(b));
2638 fprintf(F, "\" status:clustered color:lightblue\n");
2640 /* dump the nodes that go into the block */
2641 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2642 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2644 overrule_nodecolor = NULL;
2645 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2648 /* Close the vcg information for the block */
2650 dump_const_node_local(F, b);
2654 eset_destroy(loopnodes);
2655 eset_destroy(extnodes);