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 if (is_Block_dead(n))
687 fprintf (F, "color: lightred");
689 fprintf (F, "color: lightyellow");
692 fprintf (F, "color: green");
698 fprintf (F, "color: yellow");
701 PRINT_DEFAULT_NODE_ATTR;
704 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
708 /* Replace this once I can do a reference. */
711 * Dump the node information of a node n to a file F.
713 static INLINE int dump_node_info(FILE *F, ir_node *n)
715 fprintf (F, " info1: \"");
716 bad = dump_irnode_to_file(F, n);
722 * Dump the node information of a node n to a file F.
724 static INLINE int dump_node_info(FILE *F, ir_node *n)
730 fprintf (F, " info1: \"");
731 if (opt_dump_pointer_values_to_info)
732 fprintf (F, "addr: %p\n", (void *)n);
733 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
734 fprintf (F, "visited: %ld\n", get_irn_visited(n));
735 irg = get_irn_irg(n);
736 if (irg != get_const_code_irg())
737 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
739 if (get_irn_pinned(n) == op_pin_state_floats &&
740 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
741 fprintf(F, "node was pinned in ");
742 dump_node_opcode(F, get_nodes_block(n));
743 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
747 /* show all predecessor nodes */
748 fprintf(F, "pred nodes: \n");
751 dump_node_opcode(F, get_nodes_block(n));
752 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
754 for ( i = 0; i < get_irn_arity(n); ++i) {
755 fprintf(F, " %d: ", i);
756 dump_node_opcode(F, get_irn_n(n, i));
757 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
761 fprintf(F, "arity: %d", get_irn_arity(n));
762 if ((get_irn_op(n) == op_Block) ||
763 (get_irn_op(n) == op_Phi) ||
764 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
765 fprintf(F, " backedges:");
767 for (i = 0; i < get_irn_arity(n); i++)
768 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
772 /* Loop node Someone else please tell me what's wrong ...
773 if (get_irn_loop(n)) {
774 ir_loop *loop = get_irn_loop(n);
776 fprintf(F, " in loop %d with depth %d\n",
777 get_loop_loop_nr(loop), get_loop_depth(loop));
782 switch (get_irn_opcode(n)) {
784 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
785 fprintf(F, "start of method of type %s\n", get_type_name_ex(tp, &bad));
786 for (i = 0; i < get_method_n_params(tp); ++i)
787 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
788 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
789 ir_node *sbl = get_nodes_block(n);
790 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
791 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
792 for (i = 0; i < n_cfgpreds; ++i) {
793 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
794 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
795 get_irg_dump_name(get_irn_irg(cfgpred)));
800 fprintf(F, "allocating entity of type %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
803 fprintf(F, "freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
806 entity *ent = get_Sel_entity(n);
809 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
810 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
813 fprintf(F, "<NULL entity>\n");
818 type *tp = get_Call_type(n);
819 fprintf(F, "calling method of type %s\n", get_type_name_ex(tp, &bad));
820 if(get_unknown_type() != tp) {
821 for (i = 0; i < get_method_n_params(tp); ++i)
822 fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
823 for (i = 0; i < get_method_n_ress(tp); ++i)
824 fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
826 if (Call_has_callees(n)) {
827 fprintf(F, "possible callees:\n");
828 for (i = 0; i < get_Call_n_callees(n); i++) {
829 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
833 case iro_CallBegin: {
834 ir_node *call = get_CallBegin_call(n);
835 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
836 if (Call_has_callees(call)) {
837 fprintf(F, "possible callees: \n");
838 for (i = 0; i < get_Call_n_callees(call); i++) {
839 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
844 if (!get_interprocedural_view()) {
845 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
846 fprintf(F, "return in method of type %s\n", get_type_name_ex(tp, &bad));
847 for (i = 0; i < get_method_n_ress(tp); ++i)
848 fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
852 type *tp = get_Const_type(n);
853 assert(tp != none_type);
854 fprintf(F, "Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
857 switch(get_SymConst_kind(n)) {
858 case symconst_addr_name:
859 fprintf(F, "kind: addr_name\n");
861 case symconst_addr_ent:
862 fprintf(F, "kind: addr_ent\n");
863 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
865 case symconst_type_tag:
866 fprintf(F, "kind: type_tag\n");
869 fprintf(F, "kind: size\n");
872 fprintf(F, "SymConst of type: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
876 if (get_interprocedural_view()) {
877 fprintf(F, "intra predecessor nodes:\n");
878 for (i = 0; i < get_irn_intra_arity(n); i++) {
879 ir_node *pred = get_irn_intra_n(n, i);
880 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
883 fprintf(F, "inter predecessor nodes:\n");
884 for (i = 0; i < get_irn_inter_arity(n); i++) {
885 ir_node *pred = get_irn_inter_n(n, i);
886 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
887 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
892 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
895 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
901 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
902 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
903 if (get_irn_typeinfo_type(n) != none_type)
904 fprintf (F, "Analysed type: %s\n", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
913 * checks wheater a node is "constant-like", ie can be treated "block-less"
916 bool is_constlike_node(ir_node *n) {
917 ir_op *op = get_irn_op(n);
918 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
922 /** outputs the predecessors of n, that are constants, local. I.e.,
923 generates a copy of the constant predecessors for each node called with. */
924 static void dump_const_node_local(FILE *F, ir_node *n) {
926 if (!get_opt_dump_const_local()) return;
928 /* Use visited flag to avoid outputting nodes twice.
929 initialize it first. */
930 for (i = 0; i < get_irn_arity(n); i++) {
931 ir_node *con = get_irn_n(n, i);
932 if (is_constlike_node(con)) {
933 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
937 for (i = 0; i < get_irn_arity(n); i++) {
938 ir_node *con = get_irn_n(n, i);
939 if (is_constlike_node(con) && irn_not_visited(con)) {
942 mark_irn_visited(con);
943 /* Generate a new name for the node by appending the names of
945 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
946 fprintf(F, " label: \"");
947 bad |= dump_node_opcode(F, con);
948 bad |= dump_node_mode(F, con);
949 bad |= dump_node_typeinfo(F, con);
951 bad |= dump_node_nodeattr(F, con);
952 fprintf(F, " %ld", get_irn_node_nr(con));
954 bad |= dump_node_info(F, con);
955 dump_node_vcgattr(F, con, bad);
961 /** If the block of an edge is a const_like node, dump it local with an edge */
962 static void dump_const_block_local(FILE *F, ir_node *n) {
963 if (!get_opt_dump_const_local()) return;
965 ir_node *blk = get_nodes_block(n);
966 if (is_constlike_node(blk)) {
969 /* Generate a new name for the node by appending the names of
971 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
972 fprintf(F, "\" label: \"");
973 bad |= dump_node_opcode(F, blk);
974 bad |= dump_node_mode(F, blk);
975 bad |= dump_node_typeinfo(F, blk);
977 bad |= dump_node_nodeattr(F, blk);
978 fprintf(F, " %ld", get_irn_node_nr(blk));
980 bad |= dump_node_info(F, blk);
981 dump_node_vcgattr(F, blk, bad);
984 fprintf (F, "edge: { sourcename: \"");
986 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
987 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
992 * prints the error message of a node to a file F as info2.
994 static void INLINE print_node_error(FILE *F, const char *err_msg)
999 fprintf (F, " info2: \"%s\"", err_msg);
1005 static void dump_node(FILE *F, ir_node *n)
1010 if (get_opt_dump_const_local() && is_constlike_node(n))
1013 /* dump this node */
1014 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1016 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1017 bad |= dump_node_opcode(F, n);
1018 bad |= dump_node_mode(F, n);
1019 bad |= dump_node_typeinfo(F, n);
1021 bad |= dump_node_nodeattr(F, n);
1022 fprintf(F, " %ld", get_irn_node_nr(n));
1024 bad |= dump_node_info(F, n);
1025 print_node_error(F, p);
1026 dump_node_vcgattr(F, n, bad);
1028 dump_const_node_local(F, n);
1030 dump_chi_term(F, n);
1035 /** dump the edge to the block this node belongs to */
1037 dump_ir_block_edge(FILE *F, ir_node *n) {
1038 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1039 if (is_no_Block(n)) {
1040 ir_node *block = get_nodes_block(n);
1042 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1043 dump_const_block_local(F, n);
1046 fprintf (F, "edge: { sourcename: \"");
1048 fprintf (F, "\" targetname: ");
1049 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1050 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1056 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1057 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1058 fprintf (F, INTRA_DATA_EDGE_ATTR);
1060 fprintf (F, INTER_DATA_EDGE_ATTR);
1064 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1065 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1066 fprintf (F, INTRA_MEM_EDGE_ATTR);
1068 fprintf (F, INTER_MEM_EDGE_ATTR);
1072 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1075 if (dump_backedge_information_flag && is_backedge(from, to))
1076 fprintf (F, BACK_EDGE_ATTR);
1078 switch (get_irn_opcode(from)) {
1080 fprintf (F, CF_EDGE_ATTR);
1082 case iro_Start: break;
1085 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1086 fprintf (F, CF_EDGE_ATTR);
1087 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1088 fprintf (F, INTER_MEM_EDGE_ATTR);
1096 print_data_edge_vcgattr(F, from, to);
1101 print_mem_edge_vcgattr(F, from, to);
1103 print_data_edge_vcgattr(F, from, to);
1107 print_data_edge_vcgattr(F, from, to);
1112 print_mem_edge_vcgattr(F, from, to);
1114 print_data_edge_vcgattr(F, from, to);
1121 print_data_edge_vcgattr(F, from, to);
1128 print_mem_edge_vcgattr(F, from, to);
1130 print_data_edge_vcgattr(F, from, to);
1142 print_data_edge_vcgattr(F, from, to);
1145 if (get_irn_modecode(from) == irm_M)
1146 fprintf (F, INTER_MEM_EDGE_ATTR);
1148 print_data_edge_vcgattr(F, from, to);
1155 print_mem_edge_vcgattr(F, from, to);
1157 print_data_edge_vcgattr(F, from, to);
1160 print_mem_edge_vcgattr(F, from, to);
1162 case iro_Tuple: break;
1165 switch (get_irn_modecode(from)) {
1167 fprintf (F, CF_EDGE_ATTR);
1170 fprintf (F, INTER_MEM_EDGE_ATTR);
1173 print_data_edge_vcgattr(F, from, to);
1177 case iro_Bad: break;
1178 case iro_Unknown: break;
1180 switch (get_irn_modecode(from)) {
1182 fprintf (F, INTRA_MEM_EDGE_ATTR);
1185 fprintf (F, CF_EDGE_ATTR);
1188 print_data_edge_vcgattr(F, from, to);
1196 /* dump edges to our inputs */
1198 dump_ir_data_edges(FILE *F, ir_node *n) {
1199 int i, visited = get_irn_visited(n);
1201 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1204 for (i = 0; i < get_irn_arity(n); i++) {
1205 ir_node * pred = get_irn_n(n, i);
1208 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1209 continue; /* pred not dumped */
1211 if (dump_backedge_information_flag && is_backedge(n, i))
1212 fprintf (F, "backedge: {sourcename: \"");
1214 fprintf (F, "edge: {sourcename: \"");
1216 fprintf (F, "\" targetname: ");
1217 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1218 PRINT_CONSTID(n, pred);
1220 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1222 fprintf (F, " label: \"%d\" ", i);
1223 print_edge_vcgattr(F, n, i);
1228 /** Dumps a node and its edges but not the block edge
1231 dump_node_wo_blockedge (ir_node *n, void *env) {
1234 dump_ir_data_edges(F, n);
1237 /** Dumps a node and its edges.
1240 dump_whole_node (ir_node *n, void *env) {
1242 dump_node_wo_blockedge(n, env);
1243 if (!node_floats(n)) dump_ir_block_edge(F, n);
1247 dump_const_node(ir_node *n, void *env) {
1248 if (is_Block(n)) return;
1249 dump_node_wo_blockedge(n, env);
1252 /***********************************************************************/
1253 /* the following routines dump the nodes/irgs bracketed to graphs. */
1254 /***********************************************************************/
1256 /** Dumps a constant expression as entity initializer, array bound ...
1258 static void dump_const_expression(FILE *F, ir_node *value) {
1259 ir_graph *rem = current_ir_graph;
1260 int rem_dump_const_local = dump_const_local;
1261 dump_const_local = 0;
1262 current_ir_graph = get_const_code_irg();
1263 irg_walk(value, dump_const_node, NULL, F);
1264 /* Decrease visited flag so that we walk with the same flag for the next
1265 expresssion. This guarantees that we don't dump the same node twice,
1266 as for const expressions cse is performed to save memory. */
1267 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1268 current_ir_graph = rem;
1269 dump_const_local = rem_dump_const_local;
1272 /** Dump a block as graph containing its nodes.
1274 * Expects to find nodes belonging to the block as list in its
1276 * Dumps the edges of all nodes including itself. */
1278 dump_whole_block(FILE *F, ir_node *block) {
1280 assert(is_Block(block));
1282 fprintf(F, "graph: { title: \"");
1283 PRINT_NODEID(block);
1284 fprintf(F, "\" label: \"");
1285 dump_node_opcode(F, block);
1286 fprintf (F, " %ld", get_irn_node_nr(block));
1288 if (get_opt_dump_abstvals())
1289 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1291 fprintf(F, "\" status:clustered color:%s \n",
1292 get_Block_matured(block) ? "yellow" : "red");
1294 /* dump the blocks edges */
1295 dump_ir_data_edges(F, block);
1297 /* dump the nodes that go into the block */
1298 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1300 dump_ir_data_edges(F, node);
1303 /* Close the vcg information for the block */
1305 dump_const_node_local(F, block);
1307 dump_chi_term(F, block);
1312 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1313 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1315 dump_block_graph(FILE *F, ir_graph *irg) {
1317 ir_graph *rem = current_ir_graph;
1318 ir_node **arr = ird_get_irg_link(irg);
1319 current_ir_graph = irg;
1321 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1322 ir_node * node = arr[i];
1323 if (is_Block(node)) {
1324 /* Dumps the block and all the nodes in the block, which are to
1325 be found in Block->link. */
1326 dump_whole_block(F, node);
1328 /* Nodes that are not in a Block. */
1330 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1331 dump_const_block_local(F, node);
1333 dump_ir_data_edges(F, node);
1337 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1338 dump_loop_nodes_into_graph(F, irg);
1340 current_ir_graph = rem;
1343 /** Dumps an irg as a graph.
1344 * If interprocedural view edges can point to nodes out of this graph.
1346 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1348 fprintf(F, "graph: { title: \"");
1350 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1351 get_ent_dump_name(get_irg_entity(irg)));
1353 dump_block_graph(F, irg);
1355 /* Close the vcg information for the irg */
1356 fprintf(F, "}\n\n");
1359 /*******************************************************************/
1360 /* Basic type and entity nodes and edges. */
1361 /*******************************************************************/
1363 /** dumps the edges between nodes and their type or entity attributes. */
1364 static void dump_node2type_edges(ir_node *n, void *env)
1369 switch (get_irn_opcode(n)) {
1371 /* @@@ some consts have an entity */
1374 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1375 || (get_SymConst_kind(n) ==symconst_size))
1377 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1381 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1384 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1387 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1390 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1393 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1401 static int print_type_info(FILE *F, type *tp) {
1404 if (get_type_state(tp) == layout_undefined) {
1405 fprintf(F, "state: layout_undefined\n");
1407 fprintf(F, "state: layout_fixed,\n");
1409 if (get_type_mode(tp))
1410 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1411 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1416 static void print_typespecific_info(FILE *F, type *tp) {
1417 switch (get_type_tpop_code(tp)) {
1420 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1427 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1428 fprintf(F, "params: %d\n", get_method_n_params(tp));
1429 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1437 case tpo_enumeration:
1451 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1452 switch (get_type_tpop_code(tp)) {
1455 if (peculiarity_existent == get_class_peculiarity(tp))
1456 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1458 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1462 fprintf (F, " " TYPE_METH_NODE_ATTR);
1473 case tpo_enumeration:
1486 static int print_type_node(FILE *F, type *tp)
1490 fprintf (F, "node: {title: ");
1492 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1493 fprintf (F, " info1: \"");
1494 bad |= print_type_info(F, tp);
1495 print_typespecific_info(F, tp);
1497 print_typespecific_vcgattr(F, tp);
1503 #define X(a) case a: fprintf(F, #a); break
1504 void dump_entity_node(FILE *F, entity *ent, int color)
1506 fprintf (F, "node: {title: \"");
1507 PRINT_ENTID(ent); fprintf(F, "\"");
1508 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1509 fprintf (F, "label: ");
1510 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1512 fprintf(F, "color: %d", color);
1514 fprintf (F, ENTITY_NODE_ATTR);
1515 fprintf (F, "\n info1: \"");
1517 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1519 fprintf(F, "\"\n}\n");
1523 static void dump_enum_item(FILE *F, type *tp, int pos)
1526 ident *id = get_enumeration_nameid(tp, pos);
1527 tarval *tv = get_enumeration_enum(tp, pos);
1529 tarval_snprintf(buf, sizeof(buf), tv);
1530 fprintf (F, "node: {title: \"");
1531 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1532 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1533 fprintf (F, "label: ");
1534 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1535 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1538 /* dumps a type or entity and it's edges. */
1540 dump_type_info(type_or_ent *tore, void *env) {
1542 int i = 0; /* to shutup gcc */
1544 /* dump this type or entity */
1546 switch (get_kind(tore)) {
1549 entity *ent = (entity *)tore;
1552 dump_entity_node(F, ent, 0);
1554 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1555 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1556 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1557 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1558 if(is_class_type(get_entity_owner(ent))) {
1559 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1560 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1562 /* attached subgraphs */
1563 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1564 if (is_atomic_entity(ent)) {
1565 value = get_atomic_ent_value(ent);
1567 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1568 /* DDMN(value); $$$ */
1569 dump_const_expression(F, value);
1572 if (is_compound_entity(ent)) {
1573 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1574 value = get_compound_ent_value(ent, i);
1576 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1577 dump_const_expression(F, value);
1578 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1580 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1581 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1582 get_compound_ent_value_member(ent, i), i);
1591 type *tp = (type *)tore;
1592 print_type_node(F, tp);
1593 /* and now the edges */
1594 switch (get_type_tpop_code(tp)) {
1597 for (i=0; i < get_class_n_supertypes(tp); i++)
1598 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1599 for (i=0; i < get_class_n_members(tp); i++)
1600 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1604 for (i=0; i < get_struct_n_members(tp); i++)
1605 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1609 for (i = 0; i < get_method_n_params(tp); i++)
1610 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1611 for (i = 0; i < get_method_n_ress(tp); i++)
1612 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1616 for (i = 0; i < get_union_n_members(tp); i++)
1617 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1621 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1622 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1623 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1624 ir_node *upper = get_array_upper_bound(tp, i);
1625 ir_node *lower = get_array_lower_bound(tp, i);
1626 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1627 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1628 dump_const_expression(F, upper);
1629 dump_const_expression(F, lower);
1633 case tpo_enumeration:
1635 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1636 dump_enum_item(F, tp, i);
1637 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1642 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1650 break; /* case k_type */
1653 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1655 } /* switch kind_or_entity */
1658 typedef struct _h_env {
1663 /** For dumping class hierarchies.
1664 * Dumps a class type node and a superclass edge.
1665 * If env->dump_ent dumps entities of classes and overwrites edges.
1668 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1671 int i = 0; /* to shutup gcc */
1673 /* dump this type or entity */
1674 switch (get_kind(tore)) {
1676 entity *ent = (entity *)tore;
1677 if (get_entity_owner(ent) == get_glob_type()) break;
1678 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1679 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1681 dump_entity_node(F, ent, 0);
1683 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1684 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1685 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1687 } break; /* case k_entity */
1690 type *tp = (type *)tore;
1691 if (tp == get_glob_type()) break;
1692 switch (get_type_tpop_code(tp)) {
1694 print_type_node(F, tp);
1695 /* and now the edges */
1696 for (i=0; i < get_class_n_supertypes(tp); i++)
1698 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1704 break; /* case k_type */
1707 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1709 } /* switch kind_or_entity */
1712 /*******************************************************************/
1713 /* dump analysis information that is expressed in graph terms. */
1714 /*******************************************************************/
1716 /* dump out edges */
1718 dump_out_edge(ir_node *n, void *env) {
1721 for (i = 0; i < get_irn_n_outs(n); i++) {
1722 assert(get_irn_out(n, i));
1723 fprintf (F, "edge: {sourcename: \"");
1725 fprintf (F, "\" targetname: \"");
1726 PRINT_NODEID(get_irn_out(n, i));
1727 fprintf (F, "\" color: red linestyle: dashed");
1733 dump_loop_label(FILE *F, ir_loop *loop) {
1734 fprintf (F, "loop %d, %d sons, %d nodes",
1735 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1738 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1739 fprintf (F, " info1: \"");
1740 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1741 #if DEBUG_libfirm /* GL @@@ debug analyses */
1742 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1748 dump_loop_node(FILE *F, ir_loop *loop) {
1749 fprintf (F, "node: {title: \"");
1751 fprintf (F, "\" label: \"");
1752 dump_loop_label(F, loop);
1754 dump_loop_info(F, loop);
1760 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1762 fprintf (F, "edge: {sourcename: \"");
1764 fprintf (F, "\" targetname: \"");
1765 PRINT_NODEID(get_loop_node(loop, i));
1766 fprintf (F, "\" color: green");
1771 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1773 fprintf (F, "edge: {sourcename: \"");
1775 fprintf (F, "\" targetname: \"");
1776 PRINT_LOOPID(get_loop_son(loop, i));
1777 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1778 get_loop_element_pos(loop, get_loop_son(loop, i)));
1782 void dump_loops(FILE *F, ir_loop *loop) {
1784 /* dump this loop node */
1785 dump_loop_node(F, loop);
1787 /* dump edges to nodes in loop -- only if it is a real loop */
1788 if (get_loop_depth(loop) != 0) {
1789 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1790 dump_loop_node_edge(F, loop, i);
1793 for (i = 0; i < get_loop_n_sons(loop); i++) {
1794 dump_loops(F, get_loop_son(loop, i));
1795 dump_loop_son_edge(F, loop, i);
1800 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1801 ir_graph *rem = current_ir_graph;
1802 current_ir_graph = irg;
1804 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1806 current_ir_graph = rem;
1811 * dumps the VCG header
1813 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1822 if (!orientation) orientation = "bottom_to_top";
1826 "graph: { title: \"ir graph of %s\"\n"
1827 "display_edge_labels: %s\n"
1828 "layoutalgorithm: mindepth\n"
1829 "manhattan_edges: yes\n"
1830 "port_sharing: no\n"
1832 "classname 1: \"intrablock Data\"\n"
1833 "classname 16: \"interblock Data\"\n"
1834 "classname 2: \"Block\"\n"
1835 "classname 13: \"Control Flow\"\n"
1836 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1837 "classname 14: \"intrablock Memory\"\n"
1838 "classname 17: \"interblock Memory\"\n"
1839 "classname 15: \"Dominators\"\n"
1840 "classname 3: \"Entity type\"\n"
1841 "classname 4: \"Entity owner\"\n"
1842 "classname 5: \"Method Param\"\n"
1843 "classname 6: \"Method Res\"\n"
1844 "classname 7: \"Super\"\n"
1845 "classname 8: \"Union\"\n"
1846 "classname 9: \"Points-to\"\n"
1847 "classname 10: \"Array Element Type\"\n"
1848 "classname 11: \"Overwrites\"\n"
1849 "classname 12: \"Member\"\n"
1850 "infoname 1: \"Attribute\"\n"
1851 "infoname 2: \"Verification errors\"\n",
1852 name, label, orientation);
1854 /* don't use all, the range is too whith/black. */
1858 "colorentry 100: 0 0 0\n"
1859 "colorentry 101: 20 0 0\n"
1860 "colorentry 102: 40 0 0\n"
1861 "colorentry 103: 60 0 0\n"
1862 "colorentry 104: 80 0 0\n"
1863 "colorentry 105: 100 0 0\n"
1864 "colorentry 106: 120 0 0\n"
1865 "colorentry 107: 140 0 0\n"
1866 "colorentry 108: 150 0 0\n"
1867 "colorentry 109: 180 0 0\n"
1868 "colorentry 110: 200 0 0\n"
1869 "colorentry 111: 220 0 0\n"
1870 "colorentry 112: 240 0 0\n"
1871 "colorentry 113: 255 0 0\n"
1872 "colorentry 113: 255 20 20\n"
1873 "colorentry 114: 255 40 40\n"
1874 "colorentry 115: 255 60 60\n"
1875 "colorentry 116: 255 80 80\n"
1876 "colorentry 117: 255 100 100\n"
1877 "colorentry 118: 255 120 120\n"
1878 "colorentry 119: 255 140 140\n"
1879 "colorentry 120: 255 150 150\n"
1880 "colorentry 121: 255 180 180\n"
1881 "colorentry 122: 255 200 200\n"
1882 "colorentry 123: 255 220 220\n"
1883 "colorentry 124: 255 240 240\n"
1884 "colorentry 125: 255 250 250\n"
1887 fprintf (F, "\n"); /* a separator */
1893 * @param irg The graph to be dumped
1894 * @param suffix1 first filename suffix
1895 * @param suffix2 second filename suffix
1897 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1899 const char *nm = get_irg_dump_name(irg);
1900 int len = strlen(nm), i, j;
1901 char *fname; /* filename to put the vcg information in */
1903 if (!suffix1) suffix1 = "";
1904 if (!suffix2) suffix2 = "";
1906 /* open file for vcg graph */
1907 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1909 /* strncpy (fname, nm, len); */ /* copy the filename */
1911 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1913 fname[j] = '@'; j++; fname[j] = '1'; j++;
1914 } else if (nm[i] == '@') {
1915 fname[j] = '@'; j++; fname[j] = '2'; j++;
1917 fname[j] = nm[i]; j++;
1921 strcat (fname, suffix1); /* append file suffix */
1922 strcat (fname, suffix2); /* append file suffix */
1923 strcat (fname, ".vcg"); /* append the .vcg suffix */
1924 F = fopen (fname, "w"); /* open file for writing */
1926 panic("cannot open %s for writing (%m)", fname); /* not reached */
1936 * @param irg The graph to be dumped
1937 * @param suffix filename suffix
1939 static FILE *vcg_open_name (const char *name, const char *suffix) {
1941 char *fname; /* filename to put the vcg information in */
1942 int i, j, len = strlen(name);
1944 if (!suffix) suffix = "";
1946 /** open file for vcg graph */
1947 fname = malloc (len * 2 + 5 + strlen(suffix));
1948 /* strcpy (fname, name);*/ /* copy the filename */
1950 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1951 if (name[i] == '/') {
1952 fname[j] = '@'; j++; fname[j] = '1'; j++;
1953 } else if (name[i] == '@') {
1954 fname[j] = '@'; j++; fname[j] = '2'; j++;
1956 fname[j] = name[i]; j++;
1960 strcat (fname, suffix);
1961 strcat (fname, ".vcg"); /* append the .vcg suffix */
1962 F = fopen (fname, "w"); /* open file for writing */
1964 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1972 * Dumps the vcg file footer
1974 static INLINE void dump_vcg_footer (FILE *F) {
1979 * close the vcg file
1981 void vcg_close (FILE *F) {
1982 dump_vcg_footer(F); /* print footer */
1983 fclose (F); /* close vcg file */
1986 /************************************************************************/
1987 /************************************************************************/
1988 /* Routines that dump all or parts of the firm representation to a file */
1989 /************************************************************************/
1990 /************************************************************************/
1992 /************************************************************************/
1993 /* Dump ir graphs, differnt formats and additional information. */
1994 /************************************************************************/
1996 /** Routine to dump a graph, blocks as conventional nodes. */
1998 dump_ir_graph (ir_graph *irg, const char *suffix )
2003 rem = current_ir_graph;
2005 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2006 current_ir_graph = irg;
2007 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2008 else suffix1 = "-pure";
2009 f = vcg_open(irg, suffix, suffix1);
2010 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2012 /* walk over the graph */
2013 /* dump_whole_node must be called in post visiting predecessors */
2014 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2016 /* dump the out edges in a separate walk */
2017 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2018 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2023 current_ir_graph = rem;
2028 dump_ir_block_graph (ir_graph *irg, const char *suffix)
2034 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2037 if (get_interprocedural_view()) suffix1 = "-ip";
2039 f = vcg_open(irg, suffix, suffix1);
2040 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2042 construct_block_lists(irg);
2044 for (i = 0; i < get_irp_n_irgs(); i++) {
2045 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2047 dump_graph_from_list(f, get_irp_irg(i));
2055 /** dumps a graph with type information */
2057 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2060 ir_graph *rem = current_ir_graph;
2063 /* if a filter is set, dump only the irg's that match the filter */
2064 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2067 current_ir_graph = irg;
2069 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2070 else suffix1 = "-pure-wtypes";
2071 f = vcg_open(irg,suffix, suffix1);
2072 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2074 /* dump common ir graph */
2075 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2076 /* dump type info */
2077 type_walk_irg(irg, dump_type_info, NULL, f);
2078 inc_irg_visited(get_const_code_irg());
2079 /* dump edges from graph to type info */
2080 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2083 current_ir_graph = rem;
2087 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2092 ir_graph *rem = current_ir_graph;
2094 /* if a filter is set, dump only the irg's that match the filter */
2095 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2098 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2099 else suffix1 = "-wtypes";
2100 f = vcg_open(irg, suffix, suffix1);
2101 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2103 /* dump common blocked ir graph */
2104 construct_block_lists(irg);
2106 for (i = 0; i < get_irp_n_irgs(); i++) {
2107 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2109 dump_graph_from_list(f, get_irp_irg(i));
2114 /* dump type info */
2115 current_ir_graph = irg;
2116 type_walk_irg(irg, dump_type_info, NULL, f);
2117 inc_irg_visited(get_const_code_irg());
2119 /* dump edges from graph to type info */
2120 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2122 current_ir_graph = rem;
2126 /*---------------------------------------------------------------------*/
2127 /* The following routines dump a control flow graph. */
2128 /*---------------------------------------------------------------------*/
2131 dump_block_to_cfg(ir_node *block, void *env) {
2136 if (is_Block(block)) {
2137 /* This is a block. Dump a node for the block. */
2138 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2139 fprintf (F, "\" label: \"");
2140 if (block == get_irg_start_block(get_irn_irg(block)))
2141 fprintf(F, "Start ");
2142 if (block == get_irg_end_block(get_irn_irg(block)))
2145 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2146 PRINT_NODEID(block);
2148 fprintf(F, "info1:\"");
2149 if (dump_dominator_information_flag)
2150 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2152 /* show arity and possible Bad predecessors of the block */
2153 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2154 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2155 ir_node *pred = get_Block_cfgpred(block, i);
2158 fprintf(F, "Bad pred at pos: ");
2159 fprintf(F, "%d ", i);
2166 fprintf (F, "\""); /* closing quote of info */
2168 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2169 (block == get_irg_end_block(get_irn_irg(block))) )
2170 fprintf(F, " color:blue ");
2172 fprintf(F, " color:yellow ");
2175 /* Dump the edges */
2176 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2177 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2178 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2179 fprintf (F, "edge: { sourcename: \"");
2180 PRINT_NODEID(block);
2181 fprintf (F, "\" targetname: \"");
2183 fprintf (F, "\"}\n");
2186 /* Dump dominator edge */
2187 if (dump_dominator_information_flag && get_Block_idom(block)) {
2188 pred = get_Block_idom(block);
2189 fprintf (F, "edge: { sourcename: \"");
2190 PRINT_NODEID(block);
2191 fprintf (F, "\" targetname: \"");
2193 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2199 dump_cfg (ir_graph *irg, const char *suffix)
2202 ir_graph *rem = current_ir_graph;
2203 int ddif = dump_dominator_information_flag;
2204 int ipv = get_interprocedural_view();
2206 /* if a filter is set, dump only the irg's that match the filter */
2207 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2210 current_ir_graph = irg;
2212 f = vcg_open(irg, suffix, "-cfg");
2213 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2216 printf("Warning: dumping cfg not in interprocedural view!\n");
2217 set_interprocedural_view(false);
2220 if (get_irg_dom_state(irg) != dom_consistent)
2221 dump_dominator_information_flag = 0;
2223 /* walk over the blocks in the graph */
2224 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2225 dump_node(f, get_irg_bad(irg));
2227 dump_dominator_information_flag = ddif;
2228 set_interprocedural_view(ipv);
2230 current_ir_graph = rem;
2233 static int weight_overall(int rec, int loop) {
2234 return 2*rec + loop;
2237 static int compute_color (int my, int max) {
2242 /* if small, scale to the full color range. */
2244 my = my * (n_colors/max);
2246 int step = 1 + (max / n_colors);
2250 return base_color + n_colors - color;
2253 static int get_entity_color(entity *ent) {
2254 assert(get_entity_irg(ent));
2255 ir_graph *irg = get_entity_irg(ent);
2257 int rec_depth = get_irg_recursion_depth(irg);
2258 int loop_depth = get_irg_loop_depth(irg);
2259 int overall_depth = weight_overall(rec_depth, loop_depth);
2261 int max_rec_depth = irp->max_callgraph_recursion_depth;
2262 int max_loop_depth = irp->max_callgraph_loop_depth;
2263 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2265 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2266 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2267 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2269 return my_overall_color;
2272 void dump_callgraph(const char *suffix) {
2274 int i, n_irgs = get_irp_n_irgs();
2275 int rem = edge_label;
2277 //ident *prefix = new_id_from_str("java/");
2279 F = vcg_open_name("Callgraph", suffix);
2280 dump_vcg_header(F, "Callgraph", NULL);
2282 for (i = 0; i < n_irgs; ++i) {
2283 ir_graph *irg = get_irp_irg(i);
2284 entity *ent = get_irg_entity(irg);
2285 int j, n_callees = get_irg_n_callees(irg);
2287 /* Do not dump runtime system. */
2288 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2290 dump_entity_node(F, ent, get_entity_color(ent));
2291 for (j = 0; j < n_callees; ++j) {
2292 entity *c = get_irg_entity(get_irg_callee(irg, j));
2293 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2294 int be = is_irg_callee_backedge(irg, j);
2297 "label:\"recursion %d\" color: %d" :
2298 "label:\"calls %d\" color: %d";
2299 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2307 /* Dump all irgs in interprocedural view to a single file. */
2308 void dump_all_cg_block_graph(const char *suffix) {
2311 int rem_view = get_interprocedural_view();
2312 set_interprocedural_view(true);
2314 f = vcg_open_name("All_graphs", suffix);
2315 dump_vcg_header(f, "All_graphs", NULL);
2317 /* collect nodes in all irgs reachable in call graph*/
2318 for (i = 0; i < get_irp_n_irgs(); i++)
2319 ird_set_irg_link(get_irp_irg(i), NULL);
2321 cg_walk(clear_link, collect_node, NULL);
2323 /* dump all graphs */
2324 for (i = 0; i < get_irp_n_irgs(); i++) {
2325 current_ir_graph = get_irp_irg(i);
2326 assert(ird_get_irg_link(current_ir_graph));
2327 dump_graph_from_list(f, current_ir_graph);
2328 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2332 set_interprocedural_view(rem_view);
2335 /*---------------------------------------------------------------------*/
2336 /* the following routines dumps type information without any ir nodes. */
2337 /*---------------------------------------------------------------------*/
2340 dump_type_graph (ir_graph *irg, const char *suffix)
2344 rem = current_ir_graph;
2346 /* if a filter is set, dump only the irg's that match the filter */
2347 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2349 current_ir_graph = irg;
2351 f = vcg_open(irg, suffix, "-type");
2352 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2354 /* walk over the blocks in the graph */
2355 type_walk_irg(irg, dump_type_info, NULL, f);
2356 /* The walker for the const code can be called several times for the
2357 same (sub) experssion. So that no nodes are dumped several times
2358 we decrease the visited flag of the corresponding graph after each
2359 walk. So now increase it finally. */
2360 inc_irg_visited(get_const_code_irg());
2363 current_ir_graph = rem;
2367 dump_all_types (const char *suffix)
2369 FILE *f = vcg_open_name("All_types", suffix);
2370 dump_vcg_header(f, "All_types", NULL);
2371 type_walk(dump_type_info, NULL, f);
2372 inc_irg_visited(get_const_code_irg());
2377 dump_class_hierarchy (bool entities, const char *suffix)
2379 FILE *f = vcg_open_name("class_hierarchy", suffix);
2383 dump_vcg_header(f, "class_hierarchy", NULL);
2388 type_walk(dump_class_hierarchy_node, NULL, &env);
2392 /*---------------------------------------------------------------------*/
2393 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2395 /* dump_ir_block_graph */
2397 /* dump_type_graph */
2398 /* dump_ir_graph_w_types */
2399 /*---------------------------------------------------------------------*/
2401 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2402 int i, n_irgs = get_irp_n_irgs();
2403 for (i = 0; i < n_irgs; ++i) {
2404 dmp_grph(get_irp_irg(i), suffix);
2409 /*--------------------------------------------------------------------------------*
2410 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2411 * packed together in one subgraph/box *
2412 *--------------------------------------------------------------------------------*/
2414 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2415 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2417 ir_loop *son = NULL;
2419 /* Dump a new loop node. */
2420 dump_loop_node(F, loop);
2422 /* Dump the loop elements. */
2424 for(i = 0; i < get_loop_n_elements(loop); i++) {
2425 le = get_loop_element(loop, i);
2427 if (get_kind(son) == k_ir_loop) {
2429 /* We are a loop son -> Recurse */
2431 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2432 fprintf(F, "\" }\n");
2433 fprintf (F, "edge: {sourcename: \"");
2435 fprintf (F, "\" targetname: \"");
2437 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2438 loop_node_started = 0;
2440 dump_loop_son_edge(F, loop, son_number++);
2441 dump_loops_standalone(F, son);
2442 } else if (get_kind(son) == k_ir_node) {
2443 /* We are a loop node -> Collect firm nodes */
2445 ir_node *n = le.node;
2448 if (!loop_node_started) {
2449 /* Start a new node which contains all firm nodes of the current loop */
2450 fprintf (F, "node: { title: \"");
2452 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2453 loop_node_started = 1;
2459 bad |= dump_node_opcode(F, n);
2460 bad |= dump_node_mode(F, n);
2461 bad |= dump_node_typeinfo(F, n);
2463 bad |= dump_node_nodeattr(F, n);
2464 fprintf (F, " %ld", get_irn_node_nr(n));
2465 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2466 if (has_backedges(n)) fprintf(F, "\t loop head!");
2467 } else { /* for callgraph loop tree */
2468 assert(get_kind(son) == k_ir_graph);
2469 /* We are a loop node -> Collect firm graphs */
2470 ir_graph *n = (ir_graph *)le.node;
2471 if (!loop_node_started) {
2472 /* Start a new node which contains all firm nodes of the current loop */
2473 fprintf (F, "node: { title: \"");
2475 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2476 loop_node_started = 1;
2481 fprintf (F, " %s", get_irg_dump_name(n));
2482 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2486 if (loop_node_started) {
2487 fprintf(F, "\" }\n");
2488 fprintf (F, "edge: {sourcename: \"");
2490 fprintf (F, "\" targetname: \"");
2492 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2493 loop_node_started = 0;
2497 void dump_loop_tree(ir_graph *irg, const char *suffix)
2500 ir_graph *rem = current_ir_graph;
2501 int el_rem = edge_label;
2504 /* if a filter is set, dump only the irg's that match the filter */
2505 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2508 current_ir_graph = irg;
2510 f = vcg_open(irg, suffix, "-looptree");
2511 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2513 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2517 edge_label = el_rem;
2518 current_ir_graph = rem;
2521 void dump_callgraph_loop_tree(const char *suffix) {
2523 F = vcg_open_name("Callgraph_looptree", suffix);
2524 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2525 dump_loops_standalone(F, irp->outermost_cg_loop);
2530 /*-----------------------------------------------------------------------------*/
2531 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2532 /*-----------------------------------------------------------------------------*/
2534 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2535 int i, son_number = 0, node_number = 0;
2537 if (dump_loop_information_flag) dump_loop_node(F, loop);
2539 for (i = 0; i < get_loop_n_elements(loop); i++) {
2540 loop_element le = get_loop_element(loop, i);
2541 if (*(le.kind) == k_ir_loop) {
2542 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2544 collect_nodeloop(F, le.son, loopnodes);
2546 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2547 eset_insert(loopnodes, le.node);
2552 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2555 for(i = 0; i < get_loop_n_elements(loop); i++) {
2556 loop_element le = get_loop_element(loop, i);
2557 if (*(le.kind) == k_ir_loop) {
2559 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2561 if (is_Block(le.node)) start = 0; else start = -1;
2562 for (j = start; j < get_irn_arity(le.node); j++) {
2563 ir_node *pred = get_irn_n(le.node, j);
2564 if (!eset_contains(loopnodes, pred)) {
2565 eset_insert(extnodes, pred);
2566 if (!is_Block(pred)) {
2567 pred = get_nodes_block(pred);
2568 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2576 void dump_loop(ir_loop *l, const char *suffix) {
2579 eset *loopnodes = eset_create();
2580 eset *extnodes = eset_create();
2583 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2584 F = vcg_open_name (name, suffix);
2585 dump_vcg_header(F, name, NULL);
2587 /* collect all nodes to dump */
2588 collect_nodeloop(F, l, loopnodes);
2589 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2591 /* build block lists */
2592 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2593 set_irn_link(n, NULL);
2594 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2595 set_irn_link(n, NULL);
2596 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2598 b = get_nodes_block(n);
2599 set_irn_link(n, get_irn_link(b));
2602 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2604 b = get_nodes_block(n);
2605 set_irn_link(n, get_irn_link(b));
2609 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2611 fprintf(F, "graph: { title: \"");
2613 fprintf(F, "\" label: \"");
2614 dump_node_opcode(F, b);
2615 fprintf (F, " %ld", get_irn_node_nr(b));
2616 fprintf(F, "\" status:clustered color:yellow\n");
2618 /* dump the blocks edges */
2619 dump_ir_data_edges(F, b);
2621 /* dump the nodes that go into the block */
2622 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2623 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2625 overrule_nodecolor = NULL;
2626 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2629 /* Close the vcg information for the block */
2631 dump_const_node_local(F, b);
2634 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2636 fprintf(F, "graph: { title: \"");
2638 fprintf(F, "\" label: \"");
2639 dump_node_opcode(F, b);
2640 fprintf (F, " %ld", get_irn_node_nr(b));
2641 fprintf(F, "\" status:clustered color:lightblue\n");
2643 /* dump the nodes that go into the block */
2644 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2645 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2647 overrule_nodecolor = NULL;
2648 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2651 /* Close the vcg information for the block */
2653 dump_const_node_local(F, b);
2657 eset_destroy(loopnodes);
2658 eset_destroy(extnodes);