3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
51 void dump_chi_term(FILE *FL, ir_node *n);
52 void dump_state(FILE *FL, ir_node *n);
53 int get_opt_dump_abstvals(void);
54 typedef unsigned long SeqNo;
55 SeqNo get_Block_seqno(ir_node *n);
58 /* basis for a color range for vcg */
59 static int n_colors = 0;
60 static int base_color = 0;
62 #define ERROR_TXT "<ERROR>"
65 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
66 * in the later case, sets bad
68 const char *get_mode_name_ex(ir_mode *mode, int *bad)
71 return get_mode_name(mode);
77 * returns the name of a type or <ERROR> if mode is NOT a mode object.
78 * in the later case, sets bad
80 const char *get_type_name_ex(type *tp, int *bad)
83 return get_type_name(tp);
89 * prints the edge from a type S to a type T with additional info fmt, ...
92 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
97 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
98 fprintf(F, " targetname: "); PRINT_TYPEID(T);
105 * prints the edge from a type T to an entity E with additional info fmt, ...
108 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
113 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
114 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
115 vfprintf(F, fmt, ap);
121 * prints the edge from an entity E to an entity T with additional info fmt, ...
124 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
130 fprintf(F, "backedge: { sourcename: \"");
132 fprintf(F, "edge: { sourcename: \"");
134 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
135 vfprintf(F, fmt, ap);
141 * prints the edge from an entity E to a type T with additional info fmt, ...
144 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
149 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
150 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
151 vfprintf(F, fmt, ap);
157 * prints the edge from a node N to a type T with additional info fmt, ...
160 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
165 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
166 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
167 vfprintf(F, fmt, ap);
173 * prints the edge from a node N to an entity E with additional info fmt, ...
176 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
181 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
182 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
184 vfprintf(F, fmt, ap);
190 * prints the edge from an entity E to a node N with additional info fmt, ...
193 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
198 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
199 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
200 vfprintf(F, fmt, ap);
206 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
209 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
214 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
215 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
216 vfprintf(F, fmt, ap);
221 /*-----------------------------------------------------------------*/
222 /* global and ahead declarations */
223 /*-----------------------------------------------------------------*/
225 static void dump_whole_node(ir_node *n, void *env);
226 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
228 /*-----------------------------------------------------------------*/
229 /* Helper functions. */
230 /*-----------------------------------------------------------------*/
233 * This map is used as a private link attr to be able to call dumper
234 * anywhere without destroying link fields.
236 static pmap *irdump_link_map = NULL;
238 /** Creates the link attribut map. */
239 static void init_irdump(void) {
240 /* We need a new, empty map. */
241 if (irdump_link_map) pmap_destroy(irdump_link_map);
242 irdump_link_map = pmap_create();
246 * Returns the private link field.
248 static void *ird_get_irn_link(ir_node *n) {
250 if (!irdump_link_map) return NULL;
252 if (pmap_contains(irdump_link_map, (void *)n))
253 res = pmap_get(irdump_link_map, (void *)n);
258 * Sets the private link field.
260 static void ird_set_irn_link(ir_node *n, void *x) {
261 if (!irdump_link_map) init_irdump();
262 pmap_insert(irdump_link_map, (void *)n, x);
266 * Gets the private link field of an irg.
268 static void *ird_get_irg_link(ir_graph *irg) {
270 if (!irdump_link_map) return NULL;
272 if (pmap_contains(irdump_link_map, (void *)irg))
273 res = pmap_get(irdump_link_map, (void *)irg);
278 * Sets the private link field of an irg.
280 static void ird_set_irg_link(ir_graph *irg, void *x) {
281 if (!irdump_link_map) init_irdump();
282 pmap_insert(irdump_link_map, (void *)irg, x);
286 * Walker, clears tzhe private link field
288 static void clear_link(ir_node * node, void * env) {
289 ird_set_irn_link(node, NULL);
293 * If the entity has a ld_name, returns it, else returns the name of the entity.
295 const char *get_ent_dump_name(entity *ent) {
297 return "<NULL entity>";
298 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
299 if (ent->ld_name) return get_id_str(ent->ld_name);
300 return get_id_str(ent->name);
303 /* Returns the name of an IRG. */
304 const char *get_irg_dump_name(ir_graph *irg) {
305 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
306 entity *ent = get_irg_entity(irg);
307 return get_ent_dump_name(ent);
311 * Returns non-zero if a node is in floating state.
313 static int node_floats(ir_node *n) {
314 return ((get_irn_pinned(n) == op_pin_state_floats) &&
315 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
319 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
321 static void collect_node(ir_node * node, void *env) {
324 || get_irn_op(node) == op_Bad
325 || get_irn_op(node) == op_Unknown
326 || get_irn_op(node) == op_NoMem) {
327 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
328 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
329 ARR_APP1(ir_node *, arr, node);
330 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
332 ir_node * block = get_nodes_block(node);
335 /* this node is in a Bad block, so we must place it into the graph's list */
336 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
337 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
338 ARR_APP1(ir_node *, arr, node);
339 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
342 ird_set_irn_link(node, ird_get_irn_link(block));
343 ird_set_irn_link(block, node);
348 /** Construct lists to walk ir block-wise.
350 * Collects all blocks, nodes not op_pin_state_pinned,
351 * Bad, NoMem and Unknown into a flexible array in link field of
352 * irg they belong to. Sets the irg link field to NULL in all
353 * graphs not visited.
354 * Free the list with DEL_ARR_F().
356 static ir_node ** construct_block_lists(ir_graph *irg) {
357 int i, rem_view = get_interprocedural_view();
358 ir_graph *rem = current_ir_graph;
359 current_ir_graph = irg;
361 for (i = 0; i < get_irp_n_irgs(); i++)
362 ird_set_irg_link(get_irp_irg(i), NULL);
364 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
366 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
367 set_interprocedural_view(false);
369 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
370 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
371 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
372 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
374 set_interprocedural_view(rem_view);
376 current_ir_graph = rem;
377 return ird_get_irg_link(irg);
380 /*******************************************************************/
381 /* flags to steer output */
382 /*******************************************************************/
384 /** Dump only irgs with names start with this string */
385 const char *dump_file_filter = "";
387 /** A compiler option to turn off edge labels */
388 static int edge_label = 1;
389 /** A compiler option to turn off dumping values of constant entities */
390 static int const_entities = 1;
391 /** A compiler option to dump the keep alive edges */
392 static int dump_keepalive = 0;
393 /** Compiler options to dump analysis information in dump_ir_graph */
394 int dump_out_edge_flag = 0;
395 int dump_dominator_information_flag = 0;
396 int dump_loop_information_flag = 0;
397 int dump_backedge_information_flag = 1;
398 int dump_const_local = 0;
399 bool opt_dump_analysed_type_info = 1;
400 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
402 static const char *overrule_nodecolor = NULL;
404 /** The vcg attribute hook. */
405 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
408 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
410 dump_node_vcgattr_hook = hook;
413 INLINE bool get_opt_dump_const_local(void) {
414 if (!dump_out_edge_flag && !dump_loop_information_flag)
415 return dump_const_local;
420 void only_dump_method_with_name(ident *name) {
421 dump_file_filter = get_id_str(name);
425 /* To turn off display of edge labels. Edge labels offen cause xvcg to
426 abort with a segmentation fault. */
427 void turn_off_edge_labels(void) {
431 void dump_consts_local(bool b) {
432 dump_const_local = b;
435 void turn_off_constant_entity_values(void) {
439 void dump_keepalive_edges(bool b) {
443 bool get_opt_dump_keepalive_edges(void) {
444 return dump_keepalive;
447 void dump_out_edges(void) {
448 dump_out_edge_flag = 1;
451 void dump_dominator_information(void) {
452 dump_dominator_information_flag = 1;
455 void dump_loop_information(void) {
456 dump_loop_information_flag = 1;
459 void dont_dump_loop_information(void) {
460 dump_loop_information_flag = 0;
463 void dump_backedge_information(bool b) {
464 dump_backedge_information_flag = b;
467 /* Dump the information of type field specified in ana/irtypeinfo.h.
468 * If the flag is set, the type name is output in [] in the node label,
469 * else it is output as info.
471 void dump_analysed_type_info(bool b) {
472 opt_dump_analysed_type_info = b;
475 void dump_pointer_values_to_info(bool b) {
476 opt_dump_pointer_values_to_info = b;
479 /*-----------------------------------------------------------------*/
480 /* Routines to dump information about a single ir node. */
481 /*-----------------------------------------------------------------*/
484 * dump the name of a node n to the File F.
487 dump_node_opcode(FILE *F, ir_node *n)
491 switch(get_irn_opcode(n)) {
496 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
497 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
502 if (get_SymConst_kind(n) == symconst_addr_name) {
503 /* don't use get_SymConst_ptr_info as it mangles the name. */
504 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
505 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
506 assert(get_SymConst_entity(n));
507 assert(is_entity(get_SymConst_entity(n)));
508 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
510 assert(get_kind(get_SymConst_type(n)) == k_type);
511 assert(get_type_ident(get_SymConst_type(n)));
512 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
513 if (get_SymConst_kind(n) == symconst_type_tag)
521 if (!get_interprocedural_view())
528 ir_node *pred = get_Proj_pred(n);
530 if (get_irn_opcode(pred) == iro_Cond
531 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
532 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
533 fprintf (F, "defProj");
535 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
536 * fprintf (F, "Arg");
545 if (get_interprocedural_view()) {
546 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
551 case iro_CallBegin: {
552 ir_node *addr = get_CallBegin_ptr(n);
554 if (get_irn_op(addr) == op_Sel)
555 ent = get_Sel_entity(addr);
556 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
557 ent = get_SymConst_entity(addr);
558 fprintf (F, "%s", get_irn_opname(n));
559 if (ent) fprintf (F, " %s", get_entity_name(ent));
563 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
568 fprintf (F, "%s", get_irn_opname(n));
576 * Dump the mode of a node n to a file F.
577 * Ignore modes that are "always known".
580 dump_node_mode(FILE *F, ir_node *n)
583 opcode iro = get_irn_opcode(n);
596 ir_mode *mode = get_irn_mode(n);
598 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
599 (mode != mode_T || iro == iro_Proj))
600 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
608 * Dump the tpe of a node n to a file F if it's known.
610 static int dump_node_typeinfo(FILE *F, ir_node *n) {
613 if (opt_dump_analysed_type_info) {
614 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
615 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
616 type *tp = get_irn_typeinfo_type(n);
618 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
627 * Dump addinional node attributes of some nodes to a file F.
630 dump_node_nodeattr(FILE *F, ir_node *n)
634 switch (get_irn_opcode(n)) {
636 if (false && get_interprocedural_view()) {
637 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
641 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
642 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
644 fprintf (F, "%ld", get_Proj_proj(n));
648 fprintf (F, "%ld", get_Filter_proj(n));
651 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
654 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
657 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
668 * dumps the attributes of a node n into the file F.
669 * Currently this is only the color of a node.
671 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
674 fprintf(F, "color: red");
678 if (dump_node_vcgattr_hook)
679 if (dump_node_vcgattr_hook(F, n))
682 switch (get_irn_opcode(n)) {
689 fprintf (F, "color: blue");
692 if (is_Block_dead(n))
693 fprintf (F, "color: lightred");
695 fprintf (F, "color: lightyellow");
698 fprintf (F, "color: green");
704 fprintf (F, "color: yellow");
707 PRINT_DEFAULT_NODE_ATTR;
710 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
714 /* Replace this once I can do a reference. */
717 * Dump the node information of a node n to a file F.
719 static INLINE int dump_node_info(FILE *F, ir_node *n)
721 fprintf (F, " info1: \"");
722 bad = dump_irnode_to_file(F, n);
728 * Dump the node information of a node n to a file F.
730 static INLINE int dump_node_info(FILE *F, ir_node *n)
736 fprintf (F, " info1: \"");
737 if (opt_dump_pointer_values_to_info)
738 fprintf (F, "addr: %p\n", (void *)n);
739 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
740 fprintf (F, "visited: %ld\n", get_irn_visited(n));
741 irg = get_irn_irg(n);
742 if (irg != get_const_code_irg())
743 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
745 if (get_irn_pinned(n) == op_pin_state_floats &&
746 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
747 fprintf(F, "node was pinned in ");
748 dump_node_opcode(F, get_nodes_block(n));
749 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
753 /* show all predecessor nodes */
754 fprintf(F, "pred nodes: \n");
757 dump_node_opcode(F, get_nodes_block(n));
758 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
760 for ( i = 0; i < get_irn_arity(n); ++i) {
761 fprintf(F, " %d: ", i);
762 dump_node_opcode(F, get_irn_n(n, i));
763 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
767 fprintf(F, "arity: %d", get_irn_arity(n));
768 if ((get_irn_op(n) == op_Block) ||
769 (get_irn_op(n) == op_Phi) ||
770 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
771 fprintf(F, " backedges:");
773 for (i = 0; i < get_irn_arity(n); i++)
774 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
778 /* Loop node Someone else please tell me what's wrong ...
779 if (get_irn_loop(n)) {
780 ir_loop *loop = get_irn_loop(n);
782 fprintf(F, " in loop %d with depth %d\n",
783 get_loop_loop_nr(loop), get_loop_depth(loop));
788 switch (get_irn_opcode(n)) {
790 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
791 fprintf(F, "start of method of type %s\n", get_type_name_ex(tp, &bad));
792 for (i = 0; i < get_method_n_params(tp); ++i)
793 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
794 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
795 ir_node *sbl = get_nodes_block(n);
796 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
797 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
798 for (i = 0; i < n_cfgpreds; ++i) {
799 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
800 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
801 get_irg_dump_name(get_irn_irg(cfgpred)));
806 fprintf(F, "allocating entity of type %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
809 fprintf(F, "freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
812 entity *ent = get_Sel_entity(n);
815 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
816 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
819 fprintf(F, "<NULL entity>\n");
824 type *tp = get_Call_type(n);
825 fprintf(F, "calling method of type %s\n", get_type_name_ex(tp, &bad));
826 if(get_unknown_type() != tp) {
827 for (i = 0; i < get_method_n_params(tp); ++i)
828 fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
829 for (i = 0; i < get_method_n_ress(tp); ++i)
830 fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
832 if (Call_has_callees(n)) {
833 fprintf(F, "possible callees:\n");
834 for (i = 0; i < get_Call_n_callees(n); i++) {
835 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
839 case iro_CallBegin: {
840 ir_node *call = get_CallBegin_call(n);
841 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
842 if (Call_has_callees(call)) {
843 fprintf(F, "possible callees: \n");
844 for (i = 0; i < get_Call_n_callees(call); i++) {
845 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
850 if (!get_interprocedural_view()) {
851 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
852 fprintf(F, "return in method of type %s\n", get_type_name_ex(tp, &bad));
853 for (i = 0; i < get_method_n_ress(tp); ++i)
854 fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
858 type *tp = get_Const_type(n);
859 assert(tp != none_type);
860 fprintf(F, "Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
863 switch(get_SymConst_kind(n)) {
864 case symconst_addr_name:
865 fprintf(F, "kind: addr_name\n");
867 case symconst_addr_ent:
868 fprintf(F, "kind: addr_ent\n");
869 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
871 case symconst_type_tag:
872 fprintf(F, "kind: type_tag\n");
875 fprintf(F, "kind: size\n");
878 fprintf(F, "SymConst of type: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
882 if (get_interprocedural_view()) {
883 fprintf(F, "intra predecessor nodes:\n");
884 for (i = 0; i < get_irn_intra_arity(n); i++) {
885 ir_node *pred = get_irn_intra_n(n, i);
886 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
889 fprintf(F, "inter predecessor nodes:\n");
890 for (i = 0; i < get_irn_inter_arity(n); i++) {
891 ir_node *pred = get_irn_inter_n(n, i);
892 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
893 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
898 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
901 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
907 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
908 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
909 if (get_irn_typeinfo_type(n) != none_type)
910 fprintf (F, "Analysed type: %s\n", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
919 * checks wheater a node is "constant-like", ie can be treated "block-less"
922 bool is_constlike_node(ir_node *n) {
923 ir_op *op = get_irn_op(n);
924 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
928 /** outputs the predecessors of n, that are constants, local. I.e.,
929 generates a copy of the constant predecessors for each node called with. */
930 static void dump_const_node_local(FILE *F, ir_node *n) {
932 if (!get_opt_dump_const_local()) return;
934 /* Use visited flag to avoid outputting nodes twice.
935 initialize it first. */
936 for (i = 0; i < get_irn_arity(n); i++) {
937 ir_node *con = get_irn_n(n, i);
938 if (is_constlike_node(con)) {
939 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
943 for (i = 0; i < get_irn_arity(n); i++) {
944 ir_node *con = get_irn_n(n, i);
945 if (is_constlike_node(con) && irn_not_visited(con)) {
948 mark_irn_visited(con);
949 /* Generate a new name for the node by appending the names of
951 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
952 fprintf(F, " label: \"");
953 bad |= dump_node_opcode(F, con);
954 bad |= dump_node_mode(F, con);
955 bad |= dump_node_typeinfo(F, con);
957 bad |= dump_node_nodeattr(F, con);
958 fprintf(F, " %ld", get_irn_node_nr(con));
960 bad |= dump_node_info(F, con);
961 dump_node_vcgattr(F, con, bad);
967 /** If the block of an edge is a const_like node, dump it local with an edge */
968 static void dump_const_block_local(FILE *F, ir_node *n) {
969 if (!get_opt_dump_const_local()) return;
971 ir_node *blk = get_nodes_block(n);
972 if (is_constlike_node(blk)) {
975 /* Generate a new name for the node by appending the names of
977 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
978 fprintf(F, "\" label: \"");
979 bad |= dump_node_opcode(F, blk);
980 bad |= dump_node_mode(F, blk);
981 bad |= dump_node_typeinfo(F, blk);
983 bad |= dump_node_nodeattr(F, blk);
984 fprintf(F, " %ld", get_irn_node_nr(blk));
986 bad |= dump_node_info(F, blk);
987 dump_node_vcgattr(F, blk, bad);
990 fprintf (F, "edge: { sourcename: \"");
992 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
993 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
998 * prints the error message of a node to a file F as info2.
1000 static void INLINE print_node_error(FILE *F, const char *err_msg)
1005 fprintf (F, " info2: \"%s\"", err_msg);
1011 static void dump_node(FILE *F, ir_node *n)
1016 if (get_opt_dump_const_local() && is_constlike_node(n))
1019 /* dump this node */
1020 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1022 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1023 bad |= dump_node_opcode(F, n);
1024 bad |= dump_node_mode(F, n);
1025 bad |= dump_node_typeinfo(F, n);
1027 bad |= dump_node_nodeattr(F, n);
1028 fprintf(F, " %ld", get_irn_node_nr(n));
1030 bad |= dump_node_info(F, n);
1031 print_node_error(F, p);
1032 dump_node_vcgattr(F, n, bad);
1034 dump_const_node_local(F, n);
1036 dump_chi_term(F, n);
1041 /** dump the edge to the block this node belongs to */
1043 dump_ir_block_edge(FILE *F, ir_node *n) {
1044 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1045 if (is_no_Block(n)) {
1046 ir_node *block = get_nodes_block(n);
1048 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1049 dump_const_block_local(F, n);
1052 fprintf (F, "edge: { sourcename: \"");
1054 fprintf (F, "\" targetname: ");
1055 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1056 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1062 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1063 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1064 fprintf (F, INTRA_DATA_EDGE_ATTR);
1066 fprintf (F, INTER_DATA_EDGE_ATTR);
1070 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1071 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1072 fprintf (F, INTRA_MEM_EDGE_ATTR);
1074 fprintf (F, INTER_MEM_EDGE_ATTR);
1078 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1081 if (dump_backedge_information_flag && is_backedge(from, to))
1082 fprintf (F, BACK_EDGE_ATTR);
1084 switch (get_irn_opcode(from)) {
1086 fprintf (F, CF_EDGE_ATTR);
1088 case iro_Start: break;
1091 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1092 fprintf (F, CF_EDGE_ATTR);
1093 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1094 fprintf (F, INTER_MEM_EDGE_ATTR);
1102 print_data_edge_vcgattr(F, from, to);
1107 print_mem_edge_vcgattr(F, from, to);
1109 print_data_edge_vcgattr(F, from, to);
1113 print_data_edge_vcgattr(F, from, to);
1118 print_mem_edge_vcgattr(F, from, to);
1120 print_data_edge_vcgattr(F, from, to);
1127 print_data_edge_vcgattr(F, from, to);
1134 print_mem_edge_vcgattr(F, from, to);
1136 print_data_edge_vcgattr(F, from, to);
1148 print_data_edge_vcgattr(F, from, to);
1151 if (get_irn_modecode(from) == irm_M)
1152 fprintf (F, INTER_MEM_EDGE_ATTR);
1154 print_data_edge_vcgattr(F, from, to);
1161 print_mem_edge_vcgattr(F, from, to);
1163 print_data_edge_vcgattr(F, from, to);
1166 print_mem_edge_vcgattr(F, from, to);
1168 case iro_Tuple: break;
1171 switch (get_irn_modecode(from)) {
1173 fprintf (F, CF_EDGE_ATTR);
1176 fprintf (F, INTER_MEM_EDGE_ATTR);
1179 print_data_edge_vcgattr(F, from, to);
1183 case iro_Bad: break;
1184 case iro_Unknown: break;
1186 switch (get_irn_modecode(from)) {
1188 fprintf (F, INTRA_MEM_EDGE_ATTR);
1191 fprintf (F, CF_EDGE_ATTR);
1194 print_data_edge_vcgattr(F, from, to);
1202 /* dump edges to our inputs */
1204 dump_ir_data_edges(FILE *F, ir_node *n) {
1205 int i, visited = get_irn_visited(n);
1207 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1210 for (i = 0; i < get_irn_arity(n); i++) {
1211 ir_node * pred = get_irn_n(n, i);
1214 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1215 continue; /* pred not dumped */
1217 if (dump_backedge_information_flag && is_backedge(n, i))
1218 fprintf (F, "backedge: {sourcename: \"");
1220 fprintf (F, "edge: {sourcename: \"");
1222 fprintf (F, "\" targetname: ");
1223 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1224 PRINT_CONSTID(n, pred);
1226 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1228 fprintf (F, " label: \"%d\" ", i);
1229 print_edge_vcgattr(F, n, i);
1234 /** Dumps a node and its edges but not the block edge
1237 dump_node_wo_blockedge (ir_node *n, void *env) {
1240 dump_ir_data_edges(F, n);
1243 /** Dumps a node and its edges.
1246 dump_whole_node (ir_node *n, void *env) {
1248 dump_node_wo_blockedge(n, env);
1249 if (!node_floats(n)) dump_ir_block_edge(F, n);
1253 dump_const_node(ir_node *n, void *env) {
1254 if (is_Block(n)) return;
1255 dump_node_wo_blockedge(n, env);
1258 /***********************************************************************/
1259 /* the following routines dump the nodes/irgs bracketed to graphs. */
1260 /***********************************************************************/
1262 /** Dumps a constant expression as entity initializer, array bound ...
1264 static void dump_const_expression(FILE *F, ir_node *value) {
1265 ir_graph *rem = current_ir_graph;
1266 int rem_dump_const_local = dump_const_local;
1267 dump_const_local = 0;
1268 current_ir_graph = get_const_code_irg();
1269 irg_walk(value, dump_const_node, NULL, F);
1270 /* Decrease visited flag so that we walk with the same flag for the next
1271 expresssion. This guarantees that we don't dump the same node twice,
1272 as for const expressions cse is performed to save memory. */
1273 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1274 current_ir_graph = rem;
1275 dump_const_local = rem_dump_const_local;
1278 /** Dump a block as graph containing its nodes.
1280 * Expects to find nodes belonging to the block as list in its
1282 * Dumps the edges of all nodes including itself. */
1284 dump_whole_block(FILE *F, ir_node *block) {
1286 assert(is_Block(block));
1288 fprintf(F, "graph: { title: \"");
1289 PRINT_NODEID(block);
1290 fprintf(F, "\" label: \"");
1291 dump_node_opcode(F, block);
1292 fprintf (F, " %ld", get_irn_node_nr(block));
1294 if (get_opt_dump_abstvals())
1295 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1297 fprintf(F, "\" status:clustered color:%s \n",
1298 get_Block_matured(block) ? "yellow" : "red");
1300 /* dump the blocks edges */
1301 dump_ir_data_edges(F, block);
1303 /* dump the nodes that go into the block */
1304 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1306 dump_ir_data_edges(F, node);
1309 /* Close the vcg information for the block */
1311 dump_const_node_local(F, block);
1313 dump_chi_term(F, block);
1318 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1319 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1321 dump_block_graph(FILE *F, ir_graph *irg) {
1323 ir_graph *rem = current_ir_graph;
1324 ir_node **arr = ird_get_irg_link(irg);
1325 current_ir_graph = irg;
1327 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1328 ir_node * node = arr[i];
1329 if (is_Block(node)) {
1330 /* Dumps the block and all the nodes in the block, which are to
1331 be found in Block->link. */
1332 dump_whole_block(F, node);
1334 /* Nodes that are not in a Block. */
1336 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1337 dump_const_block_local(F, node);
1339 dump_ir_data_edges(F, node);
1343 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1344 dump_loop_nodes_into_graph(F, irg);
1346 current_ir_graph = rem;
1349 /** Dumps an irg as a graph.
1350 * If interprocedural view edges can point to nodes out of this graph.
1352 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1354 fprintf(F, "graph: { title: \"");
1356 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1357 get_ent_dump_name(get_irg_entity(irg)));
1359 dump_block_graph(F, irg);
1361 /* Close the vcg information for the irg */
1362 fprintf(F, "}\n\n");
1365 /*******************************************************************/
1366 /* Basic type and entity nodes and edges. */
1367 /*******************************************************************/
1369 /** dumps the edges between nodes and their type or entity attributes. */
1370 static void dump_node2type_edges(ir_node *n, void *env)
1375 switch (get_irn_opcode(n)) {
1377 /* @@@ some consts have an entity */
1380 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1381 || (get_SymConst_kind(n) ==symconst_size))
1383 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1387 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1390 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1393 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1396 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1399 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1407 static int print_type_info(FILE *F, type *tp) {
1410 if (get_type_state(tp) == layout_undefined) {
1411 fprintf(F, "state: layout_undefined\n");
1413 fprintf(F, "state: layout_fixed,\n");
1415 if (get_type_mode(tp))
1416 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1417 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1422 static void print_typespecific_info(FILE *F, type *tp) {
1423 switch (get_type_tpop_code(tp)) {
1426 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1433 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1434 fprintf(F, "params: %d\n", get_method_n_params(tp));
1435 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1443 case tpo_enumeration:
1457 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1458 switch (get_type_tpop_code(tp)) {
1461 if (peculiarity_existent == get_class_peculiarity(tp))
1462 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1464 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1468 fprintf (F, " " TYPE_METH_NODE_ATTR);
1479 case tpo_enumeration:
1492 static int print_type_node(FILE *F, type *tp)
1496 fprintf (F, "node: {title: ");
1498 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1499 fprintf (F, " info1: \"");
1500 bad |= print_type_info(F, tp);
1501 print_typespecific_info(F, tp);
1503 print_typespecific_vcgattr(F, tp);
1509 #define X(a) case a: fprintf(F, #a); break
1510 void dump_entity_node(FILE *F, entity *ent, int color)
1512 fprintf (F, "node: {title: \"");
1513 PRINT_ENTID(ent); fprintf(F, "\"");
1514 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1515 fprintf (F, "label: ");
1516 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1518 fprintf(F, "color: %d", color);
1520 fprintf (F, ENTITY_NODE_ATTR);
1521 fprintf (F, "\n info1: \"");
1523 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1525 fprintf(F, "\"\n}\n");
1529 static void dump_enum_item(FILE *F, type *tp, int pos)
1532 ident *id = get_enumeration_nameid(tp, pos);
1533 tarval *tv = get_enumeration_enum(tp, pos);
1535 tarval_snprintf(buf, sizeof(buf), tv);
1536 fprintf (F, "node: {title: \"");
1537 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1538 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1539 fprintf (F, "label: ");
1540 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1541 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1544 /* dumps a type or entity and it's edges. */
1546 dump_type_info(type_or_ent *tore, void *env) {
1548 int i = 0; /* to shutup gcc */
1550 /* dump this type or entity */
1552 switch (get_kind(tore)) {
1555 entity *ent = (entity *)tore;
1558 dump_entity_node(F, ent, 0);
1560 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1561 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1562 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1563 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1564 if(is_class_type(get_entity_owner(ent))) {
1565 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1566 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1568 /* attached subgraphs */
1569 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1570 if (is_atomic_entity(ent)) {
1571 value = get_atomic_ent_value(ent);
1573 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1574 /* DDMN(value); $$$ */
1575 dump_const_expression(F, value);
1578 if (is_compound_entity(ent)) {
1579 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1580 value = get_compound_ent_value(ent, i);
1582 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1583 dump_const_expression(F, value);
1584 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1586 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1587 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1588 get_compound_ent_value_member(ent, i), i);
1597 type *tp = (type *)tore;
1598 print_type_node(F, tp);
1599 /* and now the edges */
1600 switch (get_type_tpop_code(tp)) {
1603 for (i=0; i < get_class_n_supertypes(tp); i++)
1604 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1605 for (i=0; i < get_class_n_members(tp); i++)
1606 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1610 for (i=0; i < get_struct_n_members(tp); i++)
1611 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1615 for (i = 0; i < get_method_n_params(tp); i++)
1616 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1617 for (i = 0; i < get_method_n_ress(tp); i++)
1618 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1622 for (i = 0; i < get_union_n_members(tp); i++)
1623 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1627 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1628 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1629 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1630 ir_node *upper = get_array_upper_bound(tp, i);
1631 ir_node *lower = get_array_lower_bound(tp, i);
1632 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1633 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1634 dump_const_expression(F, upper);
1635 dump_const_expression(F, lower);
1639 case tpo_enumeration:
1641 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1642 dump_enum_item(F, tp, i);
1643 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1648 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1656 break; /* case k_type */
1659 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1661 } /* switch kind_or_entity */
1664 typedef struct _h_env {
1669 /** For dumping class hierarchies.
1670 * Dumps a class type node and a superclass edge.
1671 * If env->dump_ent dumps entities of classes and overwrites edges.
1674 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1677 int i = 0; /* to shutup gcc */
1679 /* dump this type or entity */
1680 switch (get_kind(tore)) {
1682 entity *ent = (entity *)tore;
1683 if (get_entity_owner(ent) == get_glob_type()) break;
1684 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1685 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1687 dump_entity_node(F, ent, 0);
1689 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1690 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1691 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1693 } break; /* case k_entity */
1696 type *tp = (type *)tore;
1697 if (tp == get_glob_type()) break;
1698 switch (get_type_tpop_code(tp)) {
1700 print_type_node(F, tp);
1701 /* and now the edges */
1702 for (i=0; i < get_class_n_supertypes(tp); i++)
1704 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1710 break; /* case k_type */
1713 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1715 } /* switch kind_or_entity */
1718 /*******************************************************************/
1719 /* dump analysis information that is expressed in graph terms. */
1720 /*******************************************************************/
1722 /* dump out edges */
1724 dump_out_edge(ir_node *n, void *env) {
1727 for (i = 0; i < get_irn_n_outs(n); i++) {
1728 assert(get_irn_out(n, i));
1729 fprintf (F, "edge: {sourcename: \"");
1731 fprintf (F, "\" targetname: \"");
1732 PRINT_NODEID(get_irn_out(n, i));
1733 fprintf (F, "\" color: red linestyle: dashed");
1739 dump_loop_label(FILE *F, ir_loop *loop) {
1740 fprintf (F, "loop %d, %d sons, %d nodes",
1741 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1744 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1745 fprintf (F, " info1: \"");
1746 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1747 #if DEBUG_libfirm /* GL @@@ debug analyses */
1748 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1754 dump_loop_node(FILE *F, ir_loop *loop) {
1755 fprintf (F, "node: {title: \"");
1757 fprintf (F, "\" label: \"");
1758 dump_loop_label(F, loop);
1760 dump_loop_info(F, loop);
1766 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1768 fprintf (F, "edge: {sourcename: \"");
1770 fprintf (F, "\" targetname: \"");
1771 PRINT_NODEID(get_loop_node(loop, i));
1772 fprintf (F, "\" color: green");
1777 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1779 fprintf (F, "edge: {sourcename: \"");
1781 fprintf (F, "\" targetname: \"");
1782 PRINT_LOOPID(get_loop_son(loop, i));
1783 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1784 get_loop_element_pos(loop, get_loop_son(loop, i)));
1788 void dump_loops(FILE *F, ir_loop *loop) {
1790 /* dump this loop node */
1791 dump_loop_node(F, loop);
1793 /* dump edges to nodes in loop -- only if it is a real loop */
1794 if (get_loop_depth(loop) != 0) {
1795 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1796 dump_loop_node_edge(F, loop, i);
1799 for (i = 0; i < get_loop_n_sons(loop); i++) {
1800 dump_loops(F, get_loop_son(loop, i));
1801 dump_loop_son_edge(F, loop, i);
1806 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1807 ir_graph *rem = current_ir_graph;
1808 current_ir_graph = irg;
1810 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1812 current_ir_graph = rem;
1817 * dumps the VCG header
1819 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1828 if (!orientation) orientation = "bottom_to_top";
1832 "graph: { title: \"ir graph of %s\"\n"
1833 "display_edge_labels: %s\n"
1834 "layoutalgorithm: mindepth\n"
1835 "manhattan_edges: yes\n"
1836 "port_sharing: no\n"
1838 "classname 1: \"intrablock Data\"\n"
1839 "classname 16: \"interblock Data\"\n"
1840 "classname 2: \"Block\"\n"
1841 "classname 13: \"Control Flow\"\n"
1842 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1843 "classname 14: \"intrablock Memory\"\n"
1844 "classname 17: \"interblock Memory\"\n"
1845 "classname 15: \"Dominators\"\n"
1846 "classname 3: \"Entity type\"\n"
1847 "classname 4: \"Entity owner\"\n"
1848 "classname 5: \"Method Param\"\n"
1849 "classname 6: \"Method Res\"\n"
1850 "classname 7: \"Super\"\n"
1851 "classname 8: \"Union\"\n"
1852 "classname 9: \"Points-to\"\n"
1853 "classname 10: \"Array Element Type\"\n"
1854 "classname 11: \"Overwrites\"\n"
1855 "classname 12: \"Member\"\n"
1856 "infoname 1: \"Attribute\"\n"
1857 "infoname 2: \"Verification errors\"\n",
1858 name, label, orientation);
1860 /* don't use all, the range is too whith/black. */
1864 "colorentry 100: 0 0 0\n"
1865 "colorentry 101: 20 0 0\n"
1866 "colorentry 102: 40 0 0\n"
1867 "colorentry 103: 60 0 0\n"
1868 "colorentry 104: 80 0 0\n"
1869 "colorentry 105: 100 0 0\n"
1870 "colorentry 106: 120 0 0\n"
1871 "colorentry 107: 140 0 0\n"
1872 "colorentry 108: 150 0 0\n"
1873 "colorentry 109: 180 0 0\n"
1874 "colorentry 110: 200 0 0\n"
1875 "colorentry 111: 220 0 0\n"
1876 "colorentry 112: 240 0 0\n"
1877 "colorentry 113: 255 0 0\n"
1878 "colorentry 113: 255 20 20\n"
1879 "colorentry 114: 255 40 40\n"
1880 "colorentry 115: 255 60 60\n"
1881 "colorentry 116: 255 80 80\n"
1882 "colorentry 117: 255 100 100\n"
1883 "colorentry 118: 255 120 120\n"
1884 "colorentry 119: 255 140 140\n"
1885 "colorentry 120: 255 150 150\n"
1886 "colorentry 121: 255 180 180\n"
1887 "colorentry 122: 255 200 200\n"
1888 "colorentry 123: 255 220 220\n"
1889 "colorentry 124: 255 240 240\n"
1890 "colorentry 125: 255 250 250\n"
1893 fprintf (F, "\n"); /* a separator */
1899 * @param irg The graph to be dumped
1900 * @param suffix1 first filename suffix
1901 * @param suffix2 second filename suffix
1903 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1905 const char *nm = get_irg_dump_name(irg);
1906 int len = strlen(nm), i, j;
1907 char *fname; /* filename to put the vcg information in */
1909 if (!suffix1) suffix1 = "";
1910 if (!suffix2) suffix2 = "";
1912 /* open file for vcg graph */
1913 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1915 /* strncpy (fname, nm, len); */ /* copy the filename */
1917 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1919 fname[j] = '@'; j++; fname[j] = '1'; j++;
1920 } else if (nm[i] == '@') {
1921 fname[j] = '@'; j++; fname[j] = '2'; j++;
1923 fname[j] = nm[i]; j++;
1927 strcat (fname, suffix1); /* append file suffix */
1928 strcat (fname, suffix2); /* append file suffix */
1929 strcat (fname, ".vcg"); /* append the .vcg suffix */
1930 F = fopen (fname, "w"); /* open file for writing */
1932 panic("cannot open %s for writing (%m)", fname); /* not reached */
1942 * @param irg The graph to be dumped
1943 * @param suffix filename suffix
1945 static FILE *vcg_open_name (const char *name, const char *suffix) {
1947 char *fname; /* filename to put the vcg information in */
1948 int i, j, len = strlen(name);
1950 if (!suffix) suffix = "";
1952 /** open file for vcg graph */
1953 fname = malloc (len * 2 + 5 + strlen(suffix));
1954 /* strcpy (fname, name);*/ /* copy the filename */
1956 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1957 if (name[i] == '/') {
1958 fname[j] = '@'; j++; fname[j] = '1'; j++;
1959 } else if (name[i] == '@') {
1960 fname[j] = '@'; j++; fname[j] = '2'; j++;
1962 fname[j] = name[i]; j++;
1966 strcat (fname, suffix);
1967 strcat (fname, ".vcg"); /* append the .vcg suffix */
1968 F = fopen (fname, "w"); /* open file for writing */
1970 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1978 * Dumps the vcg file footer
1980 static INLINE void dump_vcg_footer (FILE *F) {
1985 * close the vcg file
1987 void vcg_close (FILE *F) {
1988 dump_vcg_footer(F); /* print footer */
1989 fclose (F); /* close vcg file */
1992 /************************************************************************/
1993 /************************************************************************/
1994 /* Routines that dump all or parts of the firm representation to a file */
1995 /************************************************************************/
1996 /************************************************************************/
1998 /************************************************************************/
1999 /* Dump ir graphs, differnt formats and additional information. */
2000 /************************************************************************/
2002 /** Routine to dump a graph, blocks as conventional nodes. */
2004 dump_ir_graph (ir_graph *irg, const char *suffix )
2009 rem = current_ir_graph;
2011 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2012 current_ir_graph = irg;
2013 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2014 else suffix1 = "-pure";
2015 f = vcg_open(irg, suffix, suffix1);
2016 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2018 /* walk over the graph */
2019 /* dump_whole_node must be called in post visiting predecessors */
2020 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2022 /* dump the out edges in a separate walk */
2023 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2024 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2029 current_ir_graph = rem;
2034 dump_ir_block_graph (ir_graph *irg, const char *suffix)
2040 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2043 if (get_interprocedural_view()) suffix1 = "-ip";
2045 f = vcg_open(irg, suffix, suffix1);
2046 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2048 construct_block_lists(irg);
2050 for (i = 0; i < get_irp_n_irgs(); i++) {
2051 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2053 dump_graph_from_list(f, get_irp_irg(i));
2061 /** dumps a graph with type information */
2063 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2066 ir_graph *rem = current_ir_graph;
2069 /* if a filter is set, dump only the irg's that match the filter */
2070 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2073 current_ir_graph = irg;
2075 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2076 else suffix1 = "-pure-wtypes";
2077 f = vcg_open(irg,suffix, suffix1);
2078 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2080 /* dump common ir graph */
2081 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2082 /* dump type info */
2083 type_walk_irg(irg, dump_type_info, NULL, f);
2084 inc_irg_visited(get_const_code_irg());
2085 /* dump edges from graph to type info */
2086 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2089 current_ir_graph = rem;
2093 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2098 ir_graph *rem = current_ir_graph;
2100 /* if a filter is set, dump only the irg's that match the filter */
2101 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2104 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2105 else suffix1 = "-wtypes";
2106 f = vcg_open(irg, suffix, suffix1);
2107 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2109 /* dump common blocked ir graph */
2110 construct_block_lists(irg);
2112 for (i = 0; i < get_irp_n_irgs(); i++) {
2113 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2115 dump_graph_from_list(f, get_irp_irg(i));
2120 /* dump type info */
2121 current_ir_graph = irg;
2122 type_walk_irg(irg, dump_type_info, NULL, f);
2123 inc_irg_visited(get_const_code_irg());
2125 /* dump edges from graph to type info */
2126 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2128 current_ir_graph = rem;
2132 /*---------------------------------------------------------------------*/
2133 /* The following routines dump a control flow graph. */
2134 /*---------------------------------------------------------------------*/
2137 dump_block_to_cfg(ir_node *block, void *env) {
2142 if (is_Block(block)) {
2143 /* This is a block. Dump a node for the block. */
2144 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2145 fprintf (F, "\" label: \"");
2146 if (block == get_irg_start_block(get_irn_irg(block)))
2147 fprintf(F, "Start ");
2148 if (block == get_irg_end_block(get_irn_irg(block)))
2151 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2152 PRINT_NODEID(block);
2154 fprintf(F, "info1:\"");
2155 if (dump_dominator_information_flag)
2156 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2158 /* show arity and possible Bad predecessors of the block */
2159 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2160 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2161 ir_node *pred = get_Block_cfgpred(block, i);
2164 fprintf(F, "Bad pred at pos: ");
2165 fprintf(F, "%d ", i);
2172 fprintf (F, "\""); /* closing quote of info */
2174 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2175 (block == get_irg_end_block(get_irn_irg(block))) )
2176 fprintf(F, " color:blue ");
2178 fprintf(F, " color:yellow ");
2181 /* Dump the edges */
2182 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2183 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2184 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2185 fprintf (F, "edge: { sourcename: \"");
2186 PRINT_NODEID(block);
2187 fprintf (F, "\" targetname: \"");
2189 fprintf (F, "\"}\n");
2192 /* Dump dominator edge */
2193 if (dump_dominator_information_flag && get_Block_idom(block)) {
2194 pred = get_Block_idom(block);
2195 fprintf (F, "edge: { sourcename: \"");
2196 PRINT_NODEID(block);
2197 fprintf (F, "\" targetname: \"");
2199 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2205 dump_cfg (ir_graph *irg, const char *suffix)
2208 ir_graph *rem = current_ir_graph;
2209 int ddif = dump_dominator_information_flag;
2210 int ipv = get_interprocedural_view();
2212 /* if a filter is set, dump only the irg's that match the filter */
2213 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2216 current_ir_graph = irg;
2218 f = vcg_open(irg, suffix, "-cfg");
2219 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2222 printf("Warning: dumping cfg not in interprocedural view!\n");
2223 set_interprocedural_view(false);
2226 if (get_irg_dom_state(irg) != dom_consistent)
2227 dump_dominator_information_flag = 0;
2229 /* walk over the blocks in the graph */
2230 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2231 dump_node(f, get_irg_bad(irg));
2233 dump_dominator_information_flag = ddif;
2234 set_interprocedural_view(ipv);
2236 current_ir_graph = rem;
2239 static int weight_overall(int rec, int loop) {
2240 return 2*rec + loop;
2243 static int compute_color (int my, int max) {
2248 /* if small, scale to the full color range. */
2250 my = my * (n_colors/max);
2252 int step = 1 + (max / n_colors);
2256 return base_color + n_colors - color;
2259 static int get_entity_color(entity *ent) {
2260 assert(get_entity_irg(ent));
2261 ir_graph *irg = get_entity_irg(ent);
2263 int rec_depth = get_irg_recursion_depth(irg);
2264 int loop_depth = get_irg_loop_depth(irg);
2265 int overall_depth = weight_overall(rec_depth, loop_depth);
2267 int max_rec_depth = irp->max_callgraph_recursion_depth;
2268 int max_loop_depth = irp->max_callgraph_loop_depth;
2269 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2271 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2272 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2273 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2275 return my_overall_color;
2278 void dump_callgraph(const char *suffix) {
2280 int i, n_irgs = get_irp_n_irgs();
2281 int rem = edge_label;
2283 //ident *prefix = new_id_from_str("java/");
2285 F = vcg_open_name("Callgraph", suffix);
2286 dump_vcg_header(F, "Callgraph", NULL);
2288 for (i = 0; i < n_irgs; ++i) {
2289 ir_graph *irg = get_irp_irg(i);
2290 entity *ent = get_irg_entity(irg);
2291 int j, n_callees = get_irg_n_callees(irg);
2293 /* Do not dump runtime system. */
2294 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2296 dump_entity_node(F, ent, get_entity_color(ent));
2297 for (j = 0; j < n_callees; ++j) {
2298 entity *c = get_irg_entity(get_irg_callee(irg, j));
2299 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2300 int be = is_irg_callee_backedge(irg, j);
2303 "label:\"recursion %d\" color: %d" :
2304 "label:\"calls %d\" color: %d";
2305 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2313 /* Dump all irgs in interprocedural view to a single file. */
2314 void dump_all_cg_block_graph(const char *suffix) {
2317 int rem_view = get_interprocedural_view();
2318 set_interprocedural_view(true);
2320 f = vcg_open_name("All_graphs", suffix);
2321 dump_vcg_header(f, "All_graphs", NULL);
2323 /* collect nodes in all irgs reachable in call graph*/
2324 for (i = 0; i < get_irp_n_irgs(); i++)
2325 ird_set_irg_link(get_irp_irg(i), NULL);
2327 cg_walk(clear_link, collect_node, NULL);
2329 /* dump all graphs */
2330 for (i = 0; i < get_irp_n_irgs(); i++) {
2331 current_ir_graph = get_irp_irg(i);
2332 assert(ird_get_irg_link(current_ir_graph));
2333 dump_graph_from_list(f, current_ir_graph);
2334 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2338 set_interprocedural_view(rem_view);
2341 /*---------------------------------------------------------------------*/
2342 /* the following routines dumps type information without any ir nodes. */
2343 /*---------------------------------------------------------------------*/
2346 dump_type_graph (ir_graph *irg, const char *suffix)
2350 rem = current_ir_graph;
2352 /* if a filter is set, dump only the irg's that match the filter */
2353 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2355 current_ir_graph = irg;
2357 f = vcg_open(irg, suffix, "-type");
2358 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2360 /* walk over the blocks in the graph */
2361 type_walk_irg(irg, dump_type_info, NULL, f);
2362 /* The walker for the const code can be called several times for the
2363 same (sub) experssion. So that no nodes are dumped several times
2364 we decrease the visited flag of the corresponding graph after each
2365 walk. So now increase it finally. */
2366 inc_irg_visited(get_const_code_irg());
2369 current_ir_graph = rem;
2373 dump_all_types (const char *suffix)
2375 FILE *f = vcg_open_name("All_types", suffix);
2376 dump_vcg_header(f, "All_types", NULL);
2377 type_walk(dump_type_info, NULL, f);
2378 inc_irg_visited(get_const_code_irg());
2383 dump_class_hierarchy (bool entities, const char *suffix)
2385 FILE *f = vcg_open_name("class_hierarchy", suffix);
2389 dump_vcg_header(f, "class_hierarchy", NULL);
2394 type_walk(dump_class_hierarchy_node, NULL, &env);
2398 /*---------------------------------------------------------------------*/
2399 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2401 /* dump_ir_block_graph */
2403 /* dump_type_graph */
2404 /* dump_ir_graph_w_types */
2405 /*---------------------------------------------------------------------*/
2407 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2408 int i, n_irgs = get_irp_n_irgs();
2409 for (i = 0; i < n_irgs; ++i) {
2410 dmp_grph(get_irp_irg(i), suffix);
2415 /*--------------------------------------------------------------------------------*
2416 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2417 * packed together in one subgraph/box *
2418 *--------------------------------------------------------------------------------*/
2420 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2421 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2423 ir_loop *son = NULL;
2425 /* Dump a new loop node. */
2426 dump_loop_node(F, loop);
2428 /* Dump the loop elements. */
2430 for(i = 0; i < get_loop_n_elements(loop); i++) {
2431 le = get_loop_element(loop, i);
2433 if (get_kind(son) == k_ir_loop) {
2435 /* We are a loop son -> Recurse */
2437 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2438 fprintf(F, "\" }\n");
2439 fprintf (F, "edge: {sourcename: \"");
2441 fprintf (F, "\" targetname: \"");
2443 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2444 loop_node_started = 0;
2446 dump_loop_son_edge(F, loop, son_number++);
2447 dump_loops_standalone(F, son);
2448 } else if (get_kind(son) == k_ir_node) {
2449 /* We are a loop node -> Collect firm nodes */
2451 ir_node *n = le.node;
2454 if (!loop_node_started) {
2455 /* Start a new node which contains all firm nodes of the current loop */
2456 fprintf (F, "node: { title: \"");
2458 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2459 loop_node_started = 1;
2465 bad |= dump_node_opcode(F, n);
2466 bad |= dump_node_mode(F, n);
2467 bad |= dump_node_typeinfo(F, n);
2469 bad |= dump_node_nodeattr(F, n);
2470 fprintf (F, " %ld", get_irn_node_nr(n));
2471 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2472 if (has_backedges(n)) fprintf(F, "\t loop head!");
2473 } else { /* for callgraph loop tree */
2474 assert(get_kind(son) == k_ir_graph);
2475 /* We are a loop node -> Collect firm graphs */
2476 ir_graph *n = (ir_graph *)le.node;
2477 if (!loop_node_started) {
2478 /* Start a new node which contains all firm nodes of the current loop */
2479 fprintf (F, "node: { title: \"");
2481 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2482 loop_node_started = 1;
2487 fprintf (F, " %s", get_irg_dump_name(n));
2488 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2492 if (loop_node_started) {
2493 fprintf(F, "\" }\n");
2494 fprintf (F, "edge: {sourcename: \"");
2496 fprintf (F, "\" targetname: \"");
2498 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2499 loop_node_started = 0;
2503 void dump_loop_tree(ir_graph *irg, const char *suffix)
2506 ir_graph *rem = current_ir_graph;
2507 int el_rem = edge_label;
2510 /* if a filter is set, dump only the irg's that match the filter */
2511 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2514 current_ir_graph = irg;
2516 f = vcg_open(irg, suffix, "-looptree");
2517 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2519 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2523 edge_label = el_rem;
2524 current_ir_graph = rem;
2527 void dump_callgraph_loop_tree(const char *suffix) {
2529 F = vcg_open_name("Callgraph_looptree", suffix);
2530 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2531 dump_loops_standalone(F, irp->outermost_cg_loop);
2536 /*-----------------------------------------------------------------------------*/
2537 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2538 /*-----------------------------------------------------------------------------*/
2540 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2541 int i, son_number = 0, node_number = 0;
2543 if (dump_loop_information_flag) dump_loop_node(F, loop);
2545 for (i = 0; i < get_loop_n_elements(loop); i++) {
2546 loop_element le = get_loop_element(loop, i);
2547 if (*(le.kind) == k_ir_loop) {
2548 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2550 collect_nodeloop(F, le.son, loopnodes);
2552 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2553 eset_insert(loopnodes, le.node);
2558 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2561 for(i = 0; i < get_loop_n_elements(loop); i++) {
2562 loop_element le = get_loop_element(loop, i);
2563 if (*(le.kind) == k_ir_loop) {
2565 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2567 if (is_Block(le.node)) start = 0; else start = -1;
2568 for (j = start; j < get_irn_arity(le.node); j++) {
2569 ir_node *pred = get_irn_n(le.node, j);
2570 if (!eset_contains(loopnodes, pred)) {
2571 eset_insert(extnodes, pred);
2572 if (!is_Block(pred)) {
2573 pred = get_nodes_block(pred);
2574 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2582 void dump_loop(ir_loop *l, const char *suffix) {
2585 eset *loopnodes = eset_create();
2586 eset *extnodes = eset_create();
2589 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2590 F = vcg_open_name (name, suffix);
2591 dump_vcg_header(F, name, NULL);
2593 /* collect all nodes to dump */
2594 collect_nodeloop(F, l, loopnodes);
2595 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2597 /* build block lists */
2598 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2599 set_irn_link(n, NULL);
2600 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2601 set_irn_link(n, NULL);
2602 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2604 b = get_nodes_block(n);
2605 set_irn_link(n, get_irn_link(b));
2608 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2610 b = get_nodes_block(n);
2611 set_irn_link(n, get_irn_link(b));
2615 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2617 fprintf(F, "graph: { title: \"");
2619 fprintf(F, "\" label: \"");
2620 dump_node_opcode(F, b);
2621 fprintf (F, " %ld", get_irn_node_nr(b));
2622 fprintf(F, "\" status:clustered color:yellow\n");
2624 /* dump the blocks edges */
2625 dump_ir_data_edges(F, b);
2627 /* dump the nodes that go into the block */
2628 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2629 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2631 overrule_nodecolor = NULL;
2632 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2635 /* Close the vcg information for the block */
2637 dump_const_node_local(F, b);
2640 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2642 fprintf(F, "graph: { title: \"");
2644 fprintf(F, "\" label: \"");
2645 dump_node_opcode(F, b);
2646 fprintf (F, " %ld", get_irn_node_nr(b));
2647 fprintf(F, "\" status:clustered color:lightblue\n");
2649 /* dump the nodes that go into the block */
2650 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2651 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2653 overrule_nodecolor = NULL;
2654 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2657 /* Close the vcg information for the block */
2659 dump_const_node_local(F, b);
2663 eset_destroy(loopnodes);
2664 eset_destroy(extnodes);