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 static 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 static 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 static const char *get_ent_dump_name(entity *ent) {
291 return "<NULL entity>";
292 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
293 if (ent->ld_name) return get_id_str(ent->ld_name);
294 return get_id_str(ent->name);
297 /* Returns the name of an IRG. */
298 const char *get_irg_dump_name(ir_graph *irg) {
299 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
300 entity *ent = get_irg_entity(irg);
301 return get_ent_dump_name(ent);
305 * Returns non-zero if a node is in floating state.
307 static int node_floats(ir_node *n) {
308 return ((get_irn_pinned(n) == op_pin_state_floats) &&
309 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
313 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
315 static void collect_node(ir_node * node, void *env) {
318 || get_irn_op(node) == op_Bad
319 || get_irn_op(node) == op_Unknown
320 || get_irn_op(node) == op_NoMem) {
321 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
322 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
323 ARR_APP1(ir_node *, arr, node);
324 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
326 ir_node * block = get_nodes_block(node);
329 /* this node is in a Bad block, so we must place it into the graph's list */
330 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
331 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
332 ARR_APP1(ir_node *, arr, node);
333 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
336 ird_set_irn_link(node, ird_get_irn_link(block));
337 ird_set_irn_link(block, node);
342 /** Construct lists to walk ir block-wise.
344 * Collects all blocks, nodes not op_pin_state_pinned,
345 * Bad, NoMem and Unknown into a flexible array in link field of
346 * irg they belong to. Sets the irg link field to NULL in all
347 * graphs not visited.
348 * Free the list with DEL_ARR_F().
350 static ir_node ** construct_block_lists(ir_graph *irg) {
351 int i, rem_view = get_interprocedural_view();
352 ir_graph *rem = current_ir_graph;
353 current_ir_graph = irg;
355 for (i = 0; i < get_irp_n_irgs(); i++)
356 ird_set_irg_link(get_irp_irg(i), NULL);
358 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
360 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
361 set_interprocedural_view(false);
363 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
364 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
365 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
366 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
368 set_interprocedural_view(rem_view);
370 current_ir_graph = rem;
371 return ird_get_irg_link(irg);
374 /*******************************************************************/
375 /* flags to steer output */
376 /*******************************************************************/
378 /** Dump only irgs with names start with this string */
379 const char *dump_file_filter = "";
381 /** A compiler option to turn off edge labels */
382 static int edge_label = 1;
383 /** A compiler option to turn off dumping values of constant entities */
384 static int const_entities = 1;
385 /** A compiler option to dump the keep alive edges */
386 static int dump_keepalive = 0;
387 /** Compiler options to dump analysis information in dump_ir_graph */
388 int dump_out_edge_flag = 0;
389 int dump_dominator_information_flag = 0;
390 int dump_loop_information_flag = 0;
391 int dump_backedge_information_flag = 1;
392 int dump_const_local = 0;
393 bool opt_dump_analysed_type_info = 1;
394 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
396 static const char *overrule_nodecolor = NULL;
398 /** The vcg attribute hook. */
399 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
402 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
404 dump_node_vcgattr_hook = hook;
407 INLINE bool get_opt_dump_const_local(void) {
408 if (!dump_out_edge_flag && !dump_loop_information_flag)
409 return dump_const_local;
414 void only_dump_method_with_name(ident *name) {
415 dump_file_filter = get_id_str(name);
419 /* To turn off display of edge labels. Edge labels offen cause xvcg to
420 abort with a segmentation fault. */
421 void turn_off_edge_labels(void) {
425 void dump_consts_local(bool b) {
426 dump_const_local = b;
429 void turn_off_constant_entity_values(void) {
433 void dump_keepalive_edges(bool b) {
437 bool get_opt_dump_keepalive_edges(void) {
438 return dump_keepalive;
441 void dump_out_edges(void) {
442 dump_out_edge_flag = 1;
445 void dump_dominator_information(void) {
446 dump_dominator_information_flag = 1;
449 void dump_loop_information(void) {
450 dump_loop_information_flag = 1;
453 void dont_dump_loop_information(void) {
454 dump_loop_information_flag = 0;
457 void dump_backedge_information(bool b) {
458 dump_backedge_information_flag = b;
461 /* Dump the information of type field specified in ana/irtypeinfo.h.
462 * If the flag is set, the type name is output in [] in the node label,
463 * else it is output as info.
465 void dump_analysed_type_info(bool b) {
466 opt_dump_analysed_type_info = b;
469 void dump_pointer_values_to_info(bool b) {
470 opt_dump_pointer_values_to_info = b;
473 /*-----------------------------------------------------------------*/
474 /* Routines to dump information about a single ir node. */
475 /*-----------------------------------------------------------------*/
478 * dump the name of a node n to the File F.
481 dump_node_opcode(FILE *F, ir_node *n)
485 switch(get_irn_opcode(n)) {
490 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
491 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
496 if (get_SymConst_kind(n) == symconst_addr_name) {
497 /* don't use get_SymConst_ptr_info as it mangles the name. */
498 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
499 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
500 assert(get_SymConst_entity(n));
501 assert(is_entity(get_SymConst_entity(n)));
502 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
504 assert(get_kind(get_SymConst_type(n)) == k_type);
505 assert(get_type_ident(get_SymConst_type(n)));
506 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
507 if (get_SymConst_kind(n) == symconst_type_tag)
515 if (!get_interprocedural_view())
522 ir_node *pred = get_Proj_pred(n);
524 if (get_irn_opcode(pred) == iro_Cond
525 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
526 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
527 fprintf (F, "defProj");
529 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
530 * fprintf (F, "Arg");
539 if (get_interprocedural_view()) {
540 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
545 case iro_CallBegin: {
546 ir_node *addr = get_CallBegin_ptr(n);
548 if (get_irn_op(addr) == op_Sel)
549 ent = get_Sel_entity(addr);
550 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
551 ent = get_SymConst_entity(addr);
552 fprintf (F, "%s", get_irn_opname(n));
553 if (ent) fprintf (F, " %s", get_entity_name(ent));
557 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
562 fprintf (F, "%s", get_irn_opname(n));
570 * Dump the mode of a node n to a file F.
571 * Ignore modes that are "always known".
574 dump_node_mode(FILE *F, ir_node *n)
577 opcode iro = get_irn_opcode(n);
590 ir_mode *mode = get_irn_mode(n);
592 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
593 (mode != mode_T || iro == iro_Proj))
594 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
602 * Dump the tpe of a node n to a file F if it's known.
604 static int dump_node_typeinfo(FILE *F, ir_node *n) {
607 if (opt_dump_analysed_type_info) {
608 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
609 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
610 type *tp = get_irn_typeinfo_type(n);
612 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
621 * Dump addinional node attributes of some nodes to a file F.
624 dump_node_nodeattr(FILE *F, ir_node *n)
628 switch (get_irn_opcode(n)) {
630 if (false && get_interprocedural_view()) {
631 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
635 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
636 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
638 fprintf (F, "%ld", get_Proj_proj(n));
642 fprintf (F, "%ld", get_Filter_proj(n));
645 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
648 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
651 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
662 * dumps the attributes of a node n into the file F.
663 * Currently this is only the color of a node.
665 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
668 fprintf(F, "color: red");
672 if (dump_node_vcgattr_hook)
673 if (dump_node_vcgattr_hook(F, n))
676 switch (get_irn_opcode(n)) {
683 fprintf (F, "color: blue");
686 fprintf (F, "color: lightyellow");
689 fprintf (F, "color: green");
695 fprintf (F, "color: yellow");
698 PRINT_DEFAULT_NODE_ATTR;
701 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
705 * Dump the node information of a node n to a file F.
707 static INLINE int dump_node_info(FILE *F, ir_node *n)
713 fprintf (F, " info1: \"");
714 if (opt_dump_pointer_values_to_info)
715 fprintf (F, "addr: %p\n", (void *)n);
716 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
717 fprintf (F, "visited: %ld\n", get_irn_visited(n));
718 irg = get_irn_irg(n);
719 if (irg != get_const_code_irg())
720 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
722 if (get_irn_pinned(n) == op_pin_state_floats &&
723 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
724 fprintf(F, "node was pinned in ");
725 dump_node_opcode(F, get_nodes_block(n));
726 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
730 /* show all predecessor nodes */
731 fprintf(F, "pred nodes: \n");
734 dump_node_opcode(F, get_nodes_block(n));
735 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
737 for ( i = 0; i < get_irn_arity(n); ++i) {
738 fprintf(F, " %d: ", i);
739 dump_node_opcode(F, get_irn_n(n, i));
740 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
744 fprintf(F, "arity: %d", get_irn_arity(n));
745 if ((get_irn_op(n) == op_Block) ||
746 (get_irn_op(n) == op_Phi) ||
747 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
748 fprintf(F, " backedges:");
750 for (i = 0; i < get_irn_arity(n); i++)
751 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
755 /* Loop node Someone else please tell me what's wrong ...
756 if (get_irn_loop(n)) {
757 ir_loop *loop = get_irn_loop(n);
759 fprintf(F, " in loop %d with depth %d\n",
760 get_loop_loop_nr(loop), get_loop_depth(loop));
765 switch (get_irn_opcode(n)) {
767 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
768 fprintf(F, "start of method of type %s\n", get_type_name_ex(tp, &bad));
769 for (i = 0; i < get_method_n_params(tp); ++i)
770 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
771 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
772 ir_node *sbl = get_nodes_block(n);
773 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
774 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
775 for (i = 0; i < n_cfgpreds; ++i) {
776 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
777 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
778 get_irg_dump_name(get_irn_irg(cfgpred)));
783 fprintf(F, "allocating entity of type %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
786 fprintf(F, "freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
789 entity *ent = get_Sel_entity(n);
792 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
793 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
796 fprintf(F, "<NULL entity>\n");
801 type *tp = get_Call_type(n);
802 fprintf(F, "calling method of type %s\n", get_type_name_ex(tp, &bad));
803 if(get_unknown_type() != tp) {
804 for (i = 0; i < get_method_n_params(tp); ++i)
805 fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
806 for (i = 0; i < get_method_n_ress(tp); ++i)
807 fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
809 if (Call_has_callees(n)) {
810 fprintf(F, "possible callees:\n");
811 for (i = 0; i < get_Call_n_callees(n); i++) {
812 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
816 case iro_CallBegin: {
817 ir_node *call = get_CallBegin_call(n);
818 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
819 if (Call_has_callees(call)) {
820 fprintf(F, "possible callees: \n");
821 for (i = 0; i < get_Call_n_callees(call); i++) {
822 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
827 if (!get_interprocedural_view()) {
828 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
829 fprintf(F, "return in method of type %s\n", get_type_name_ex(tp, &bad));
830 for (i = 0; i < get_method_n_ress(tp); ++i)
831 fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
835 type *tp = get_Const_type(n);
836 assert(tp != none_type);
837 fprintf(F, "Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
840 switch(get_SymConst_kind(n)) {
841 case symconst_addr_name:
842 fprintf(F, "kind: addr_name\n");
844 case symconst_addr_ent:
845 fprintf(F, "kind: addr_ent\n");
846 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
848 case symconst_type_tag:
849 fprintf(F, "kind: type_tag\n");
852 fprintf(F, "kind: size\n");
855 fprintf(F, "SymConst of type: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
859 if (get_interprocedural_view()) {
860 fprintf(F, "intra predecessor nodes:\n");
861 for (i = 0; i < get_irn_intra_arity(n); i++) {
862 ir_node *pred = get_irn_intra_n(n, i);
863 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
866 fprintf(F, "inter predecessor nodes:\n");
867 for (i = 0; i < get_irn_inter_arity(n); i++) {
868 ir_node *pred = get_irn_inter_n(n, i);
869 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
870 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
875 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
878 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
884 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
885 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
886 if (get_irn_typeinfo_type(n) != none_type)
887 fprintf (F, "Analysed type: %s\n", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
895 * checks wheater a node is "constant-like", ie can be treated "block-less"
898 bool is_constlike_node(ir_node *n) {
899 ir_op *op = get_irn_op(n);
900 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
904 /** outputs the predecessors of n, that are constants, local. I.e.,
905 generates a copy of the constant predecessors for each node called with. */
906 static void dump_const_node_local(FILE *F, ir_node *n) {
908 if (!get_opt_dump_const_local()) return;
910 /* Use visited flag to avoid outputting nodes twice.
911 initialize it first. */
912 for (i = 0; i < get_irn_arity(n); i++) {
913 ir_node *con = get_irn_n(n, i);
914 if (is_constlike_node(con)) {
915 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
919 for (i = 0; i < get_irn_arity(n); i++) {
920 ir_node *con = get_irn_n(n, i);
921 if (is_constlike_node(con) && irn_not_visited(con)) {
924 mark_irn_visited(con);
925 /* Generate a new name for the node by appending the names of
927 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
928 fprintf(F, " label: \"");
929 bad |= dump_node_opcode(F, con);
930 bad |= dump_node_mode(F, con);
931 bad |= dump_node_typeinfo(F, con);
933 bad |= dump_node_nodeattr(F, con);
934 fprintf(F, " %ld", get_irn_node_nr(con));
936 bad |= dump_node_info(F, con);
937 dump_node_vcgattr(F, con, bad);
943 /** If the block of an edge is a const_like node, dump it local with an edge */
944 static void dump_const_block_local(FILE *F, ir_node *n) {
945 if (!get_opt_dump_const_local()) return;
947 ir_node *blk = get_nodes_block(n);
948 if (is_constlike_node(blk)) {
951 /* Generate a new name for the node by appending the names of
953 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
954 fprintf(F, "\" label: \"");
955 bad |= dump_node_opcode(F, blk);
956 bad |= dump_node_mode(F, blk);
957 bad |= dump_node_typeinfo(F, blk);
959 bad |= dump_node_nodeattr(F, blk);
960 fprintf(F, " %ld", get_irn_node_nr(blk));
962 bad |= dump_node_info(F, blk);
963 dump_node_vcgattr(F, blk, bad);
966 fprintf (F, "edge: { sourcename: \"");
968 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
969 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
974 * prints the error message of a node to a file F as info2.
976 static void INLINE print_node_error(FILE *F, const char *err_msg)
981 fprintf (F, " info2: \"%s\"", err_msg);
987 static void dump_node(FILE *F, ir_node *n)
992 if (get_opt_dump_const_local() && is_constlike_node(n))
996 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
998 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
999 bad |= dump_node_opcode(F, n);
1000 bad |= dump_node_mode(F, n);
1001 bad |= dump_node_typeinfo(F, n);
1003 bad |= dump_node_nodeattr(F, n);
1004 fprintf(F, " %ld", get_irn_node_nr(n));
1006 bad |= dump_node_info(F, n);
1007 print_node_error(F, p);
1008 dump_node_vcgattr(F, n, bad);
1010 dump_const_node_local(F, n);
1012 dump_chi_term(F, n);
1017 /** dump the edge to the block this node belongs to */
1019 dump_ir_block_edge(FILE *F, ir_node *n) {
1020 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1021 if (is_no_Block(n)) {
1022 ir_node *block = get_nodes_block(n);
1024 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1025 dump_const_block_local(F, n);
1028 fprintf (F, "edge: { sourcename: \"");
1030 fprintf (F, "\" targetname: ");
1031 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1032 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1038 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1039 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1040 fprintf (F, INTRA_DATA_EDGE_ATTR);
1042 fprintf (F, INTER_DATA_EDGE_ATTR);
1046 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1047 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1048 fprintf (F, INTRA_MEM_EDGE_ATTR);
1050 fprintf (F, INTER_MEM_EDGE_ATTR);
1054 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1057 if (dump_backedge_information_flag && is_backedge(from, to))
1058 fprintf (F, BACK_EDGE_ATTR);
1060 switch (get_irn_opcode(from)) {
1062 fprintf (F, CF_EDGE_ATTR);
1064 case iro_Start: break;
1067 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1068 fprintf (F, CF_EDGE_ATTR);
1069 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1070 fprintf (F, INTER_MEM_EDGE_ATTR);
1078 print_data_edge_vcgattr(F, from, to);
1083 print_mem_edge_vcgattr(F, from, to);
1085 print_data_edge_vcgattr(F, from, to);
1089 print_data_edge_vcgattr(F, from, to);
1094 print_mem_edge_vcgattr(F, from, to);
1096 print_data_edge_vcgattr(F, from, to);
1103 print_data_edge_vcgattr(F, from, to);
1110 print_mem_edge_vcgattr(F, from, to);
1112 print_data_edge_vcgattr(F, from, to);
1124 print_data_edge_vcgattr(F, from, to);
1127 if (get_irn_modecode(from) == irm_M)
1128 fprintf (F, INTER_MEM_EDGE_ATTR);
1130 print_data_edge_vcgattr(F, from, to);
1137 print_mem_edge_vcgattr(F, from, to);
1139 print_data_edge_vcgattr(F, from, to);
1142 print_mem_edge_vcgattr(F, from, to);
1144 case iro_Tuple: break;
1147 switch (get_irn_modecode(from)) {
1149 fprintf (F, CF_EDGE_ATTR);
1152 fprintf (F, INTER_MEM_EDGE_ATTR);
1155 print_data_edge_vcgattr(F, from, to);
1159 case iro_Bad: break;
1160 case iro_Unknown: break;
1162 switch (get_irn_modecode(from)) {
1164 fprintf (F, INTRA_MEM_EDGE_ATTR);
1167 fprintf (F, CF_EDGE_ATTR);
1170 print_data_edge_vcgattr(F, from, to);
1178 /* dump edges to our inputs */
1180 dump_ir_data_edges(FILE *F, ir_node *n) {
1181 int i, visited = get_irn_visited(n);
1183 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1186 for (i = 0; i < get_irn_arity(n); i++) {
1187 ir_node * pred = get_irn_n(n, i);
1190 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1191 continue; /* pred not dumped */
1193 if (dump_backedge_information_flag && is_backedge(n, i))
1194 fprintf (F, "backedge: {sourcename: \"");
1196 fprintf (F, "edge: {sourcename: \"");
1198 fprintf (F, "\" targetname: ");
1199 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1200 PRINT_CONSTID(n, pred);
1202 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1204 fprintf (F, " label: \"%d\" ", i);
1205 print_edge_vcgattr(F, n, i);
1210 /** Dumps a node and its edges but not the block edge
1213 dump_node_wo_blockedge (ir_node *n, void *env) {
1216 dump_ir_data_edges(F, n);
1219 /** Dumps a node and its edges.
1222 dump_whole_node (ir_node *n, void *env) {
1224 dump_node_wo_blockedge(n, env);
1225 if (!node_floats(n)) dump_ir_block_edge(F, n);
1229 dump_const_node(ir_node *n, void *env) {
1230 if (is_Block(n)) return;
1231 dump_node_wo_blockedge(n, env);
1234 /***********************************************************************/
1235 /* the following routines dump the nodes/irgs bracketed to graphs. */
1236 /***********************************************************************/
1238 /** Dumps a constant expression as entity initializer, array bound ...
1240 static void dump_const_expression(FILE *F, ir_node *value) {
1241 ir_graph *rem = current_ir_graph;
1242 int rem_dump_const_local = dump_const_local;
1243 dump_const_local = 0;
1244 current_ir_graph = get_const_code_irg();
1245 irg_walk(value, dump_const_node, NULL, F);
1246 /* Decrease visited flag so that we walk with the same flag for the next
1247 expresssion. This guarantees that we don't dump the same node twice,
1248 as for const expressions cse is performed to save memory. */
1249 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1250 current_ir_graph = rem;
1251 dump_const_local = rem_dump_const_local;
1254 /** Dump a block as graph containing its nodes.
1256 * Expects to find nodes belonging to the block as list in its
1258 * Dumps the edges of all nodes including itself. */
1260 dump_whole_block(FILE *F, ir_node *block) {
1262 assert(is_Block(block));
1264 fprintf(F, "graph: { title: \"");
1265 PRINT_NODEID(block);
1266 fprintf(F, "\" label: \"");
1267 dump_node_opcode(F, block);
1268 fprintf (F, " %ld", get_irn_node_nr(block));
1270 if (get_opt_dump_abstvals())
1271 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1273 fprintf(F, "\" status:clustered color:%s \n",
1274 get_Block_matured(block) ? "yellow" : "red");
1276 /* dump the blocks edges */
1277 dump_ir_data_edges(F, block);
1279 /* dump the nodes that go into the block */
1280 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1282 dump_ir_data_edges(F, node);
1285 /* Close the vcg information for the block */
1287 dump_const_node_local(F, block);
1289 dump_chi_term(F, block);
1294 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1295 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1297 dump_block_graph(FILE *F, ir_graph *irg) {
1299 ir_graph *rem = current_ir_graph;
1300 ir_node **arr = ird_get_irg_link(irg);
1301 current_ir_graph = irg;
1303 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1304 ir_node * node = arr[i];
1305 if (is_Block(node)) {
1306 /* Dumps the block and all the nodes in the block, which are to
1307 be found in Block->link. */
1308 dump_whole_block(F, node);
1310 /* Nodes that are not in a Block. */
1312 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1313 dump_const_block_local(F, node);
1315 dump_ir_data_edges(F, node);
1319 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1320 dump_loop_nodes_into_graph(F, irg);
1322 current_ir_graph = rem;
1325 /** Dumps an irg as a graph.
1326 * If interprocedural view edges can point to nodes out of this graph.
1328 static void dump_graph(FILE *F, ir_graph *irg) {
1330 fprintf(F, "graph: { title: \"");
1332 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1333 get_ent_dump_name(get_irg_entity(irg)));
1335 dump_block_graph(F, irg);
1337 /* Close the vcg information for the irg */
1338 fprintf(F, "}\n\n");
1341 /*******************************************************************/
1342 /* Basic type and entity nodes and edges. */
1343 /*******************************************************************/
1345 /** dumps the edges between nodes and their type or entity attributes. */
1346 static void dump_node2type_edges(ir_node *n, void *env)
1351 switch (get_irn_opcode(n)) {
1353 /* @@@ some consts have an entity */
1356 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1357 || (get_SymConst_kind(n) ==symconst_size))
1359 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1363 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1366 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1369 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1372 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1375 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1383 static int print_type_info(FILE *F, type *tp) {
1386 if (get_type_state(tp) == layout_undefined) {
1387 fprintf(F, "state: layout_undefined\n");
1389 fprintf(F, "state: layout_fixed,\n");
1391 if (get_type_mode(tp))
1392 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1393 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1398 static void print_typespecific_info(FILE *F, type *tp) {
1399 switch (get_type_tpop_code(tp)) {
1402 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1409 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1410 fprintf(F, "params: %d\n", get_method_n_params(tp));
1411 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1419 case tpo_enumeration:
1433 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1434 switch (get_type_tpop_code(tp)) {
1437 if (peculiarity_existent == get_class_peculiarity(tp))
1438 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1440 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1444 fprintf (F, " " TYPE_METH_NODE_ATTR);
1455 case tpo_enumeration:
1468 static int print_type_node(FILE *F, type *tp)
1472 fprintf (F, "node: {title: ");
1474 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1475 fprintf (F, " info1: \"");
1476 bad |= print_type_info(F, tp);
1477 print_typespecific_info(F, tp);
1479 print_typespecific_vcgattr(F, tp);
1485 #define X(a) case a: fprintf(F, #a); break
1486 void dump_entity_node(FILE *F, entity *ent, int color)
1488 fprintf (F, "node: {title: \"");
1489 PRINT_ENTID(ent); fprintf(F, "\"");
1490 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1491 fprintf (F, "label: ");
1492 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1494 fprintf(F, "color: %d", color);
1496 fprintf (F, ENTITY_NODE_ATTR);
1497 fprintf (F, "\n info1: \"");
1499 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1501 fprintf(F, "\"\n}\n");
1505 static void dump_enum_item(FILE *F, type *tp, int pos)
1508 ident *id = get_enumeration_nameid(tp, pos);
1509 tarval *tv = get_enumeration_enum(tp, pos);
1511 tarval_snprintf(buf, sizeof(buf), tv);
1512 fprintf (F, "node: {title: \"");
1513 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1514 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1515 fprintf (F, "label: ");
1516 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1517 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1520 /* dumps a type or entity and it's edges. */
1522 dump_type_info(type_or_ent *tore, void *env) {
1524 int i = 0; /* to shutup gcc */
1526 /* dump this type or entity */
1528 switch (get_kind(tore)) {
1531 entity *ent = (entity *)tore;
1534 dump_entity_node(F, ent, 0);
1536 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1537 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1538 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1539 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1540 if(is_class_type(get_entity_owner(ent))) {
1541 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1542 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1544 /* attached subgraphs */
1545 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1546 if (is_atomic_entity(ent)) {
1547 value = get_atomic_ent_value(ent);
1549 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1550 /* DDMN(value); $$$ */
1551 dump_const_expression(F, value);
1554 if (is_compound_entity(ent)) {
1555 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1556 value = get_compound_ent_value(ent, i);
1558 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1559 dump_const_expression(F, value);
1560 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1562 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1563 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1564 get_compound_ent_value_member(ent, i), i);
1573 type *tp = (type *)tore;
1574 print_type_node(F, tp);
1575 /* and now the edges */
1576 switch (get_type_tpop_code(tp)) {
1579 for (i=0; i < get_class_n_supertypes(tp); i++)
1580 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1581 for (i=0; i < get_class_n_members(tp); i++)
1582 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1586 for (i=0; i < get_struct_n_members(tp); i++)
1587 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1591 for (i = 0; i < get_method_n_params(tp); i++)
1592 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1593 for (i = 0; i < get_method_n_ress(tp); i++)
1594 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1598 for (i = 0; i < get_union_n_members(tp); i++)
1599 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1603 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1604 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1605 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1606 ir_node *upper = get_array_upper_bound(tp, i);
1607 ir_node *lower = get_array_lower_bound(tp, i);
1608 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1609 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1610 dump_const_expression(F, upper);
1611 dump_const_expression(F, lower);
1615 case tpo_enumeration:
1617 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1618 dump_enum_item(F, tp, i);
1619 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1624 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1632 break; /* case k_type */
1635 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1637 } /* switch kind_or_entity */
1640 typedef struct _h_env {
1645 /** For dumping class hierarchies.
1646 * Dumps a class type node and a superclass edge.
1647 * If env->dump_ent dumps entities of classes and overwrites edges.
1650 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1653 int i = 0; /* to shutup gcc */
1655 /* dump this type or entity */
1656 switch (get_kind(tore)) {
1658 entity *ent = (entity *)tore;
1659 if (get_entity_owner(ent) == get_glob_type()) break;
1660 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1661 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1663 dump_entity_node(F, ent, 0);
1665 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1666 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1667 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1669 } break; /* case k_entity */
1672 type *tp = (type *)tore;
1673 if (tp == get_glob_type()) break;
1674 switch (get_type_tpop_code(tp)) {
1676 print_type_node(F, tp);
1677 /* and now the edges */
1678 for (i=0; i < get_class_n_supertypes(tp); i++)
1680 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1686 break; /* case k_type */
1689 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1691 } /* switch kind_or_entity */
1694 /*******************************************************************/
1695 /* dump analysis information that is expressed in graph terms. */
1696 /*******************************************************************/
1698 /* dump out edges */
1700 dump_out_edge(ir_node *n, void *env) {
1703 for (i = 0; i < get_irn_n_outs(n); i++) {
1704 assert(get_irn_out(n, i));
1705 fprintf (F, "edge: {sourcename: \"");
1707 fprintf (F, "\" targetname: \"");
1708 PRINT_NODEID(get_irn_out(n, i));
1709 fprintf (F, "\" color: red linestyle: dashed");
1715 dump_loop_label(FILE *F, ir_loop *loop) {
1716 fprintf (F, "loop %d, %d sons, %d nodes",
1717 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1720 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1721 fprintf (F, " info1: \"");
1722 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1723 #if DEBUG_libfirm /* GL @@@ debug analyses */
1724 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1730 dump_loop_node(FILE *F, ir_loop *loop) {
1731 fprintf (F, "node: {title: \"");
1733 fprintf (F, "\" label: \"");
1734 dump_loop_label(F, loop);
1736 dump_loop_info(F, loop);
1742 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1744 fprintf (F, "edge: {sourcename: \"");
1746 fprintf (F, "\" targetname: \"");
1747 PRINT_NODEID(get_loop_node(loop, i));
1748 fprintf (F, "\" color: green");
1753 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1755 fprintf (F, "edge: {sourcename: \"");
1757 fprintf (F, "\" targetname: \"");
1758 PRINT_LOOPID(get_loop_son(loop, i));
1759 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1760 get_loop_element_pos(loop, get_loop_son(loop, i)));
1764 void dump_loops(FILE *F, ir_loop *loop) {
1766 /* dump this loop node */
1767 dump_loop_node(F, loop);
1769 /* dump edges to nodes in loop -- only if it is a real loop */
1770 if (get_loop_depth(loop) != 0) {
1771 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1772 dump_loop_node_edge(F, loop, i);
1775 for (i = 0; i < get_loop_n_sons(loop); i++) {
1776 dump_loops(F, get_loop_son(loop, i));
1777 dump_loop_son_edge(F, loop, i);
1782 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1783 ir_graph *rem = current_ir_graph;
1784 current_ir_graph = irg;
1786 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1788 current_ir_graph = rem;
1793 * dumps the VCG header
1795 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1804 if (!orientation) orientation = "bottom_to_top";
1808 "graph: { title: \"ir graph of %s\"\n"
1809 "display_edge_labels: %s\n"
1810 "layoutalgorithm: mindepth\n"
1811 "manhattan_edges: yes\n"
1812 "port_sharing: no\n"
1814 "classname 1: \"intrablock Data\"\n"
1815 "classname 16: \"interblock Data\"\n"
1816 "classname 2: \"Block\"\n"
1817 "classname 13: \"Control Flow\"\n"
1818 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1819 "classname 14: \"intrablock Memory\"\n"
1820 "classname 17: \"interblock Memory\"\n"
1821 "classname 15: \"Dominators\"\n"
1822 "classname 3: \"Entity type\"\n"
1823 "classname 4: \"Entity owner\"\n"
1824 "classname 5: \"Method Param\"\n"
1825 "classname 6: \"Method Res\"\n"
1826 "classname 7: \"Super\"\n"
1827 "classname 8: \"Union\"\n"
1828 "classname 9: \"Points-to\"\n"
1829 "classname 10: \"Array Element Type\"\n"
1830 "classname 11: \"Overwrites\"\n"
1831 "classname 12: \"Member\"\n"
1832 "infoname 1: \"Attribute\"\n"
1833 "infoname 2: \"Verification errors\"\n",
1834 name, label, orientation);
1836 /* don't use all, the range is too whith/black. */
1840 "colorentry 100: 0 0 0\n"
1841 "colorentry 101: 20 0 0\n"
1842 "colorentry 102: 40 0 0\n"
1843 "colorentry 103: 60 0 0\n"
1844 "colorentry 104: 80 0 0\n"
1845 "colorentry 105: 100 0 0\n"
1846 "colorentry 106: 120 0 0\n"
1847 "colorentry 107: 140 0 0\n"
1848 "colorentry 108: 150 0 0\n"
1849 "colorentry 109: 180 0 0\n"
1850 "colorentry 110: 200 0 0\n"
1851 "colorentry 111: 220 0 0\n"
1852 "colorentry 112: 240 0 0\n"
1853 "colorentry 113: 255 0 0\n"
1854 "colorentry 113: 255 20 20\n"
1855 "colorentry 114: 255 40 40\n"
1856 "colorentry 115: 255 60 60\n"
1857 "colorentry 116: 255 80 80\n"
1858 "colorentry 117: 255 100 100\n"
1859 "colorentry 118: 255 120 120\n"
1860 "colorentry 119: 255 140 140\n"
1861 "colorentry 120: 255 150 150\n"
1862 "colorentry 121: 255 180 180\n"
1863 "colorentry 122: 255 200 200\n"
1864 "colorentry 123: 255 220 220\n"
1865 "colorentry 124: 255 240 240\n"
1866 "colorentry 125: 255 250 250\n"
1869 fprintf (F, "\n"); /* a separator */
1875 * @param irg The graph to be dumped
1876 * @param suffix1 first filename suffix
1877 * @param suffix2 second filename suffix
1879 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1881 const char *nm = get_irg_dump_name(irg);
1882 int len = strlen(nm), i, j;
1883 char *fname; /* filename to put the vcg information in */
1885 if (!suffix1) suffix1 = "";
1886 if (!suffix2) suffix2 = "";
1888 /* open file for vcg graph */
1889 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1891 /* strncpy (fname, nm, len); */ /* copy the filename */
1893 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1895 fname[j] = '@'; j++; fname[j] = '1'; j++;
1896 } else if (nm[i] == '@') {
1897 fname[j] = '@'; j++; fname[j] = '2'; j++;
1899 fname[j] = nm[i]; j++;
1903 strcat (fname, suffix1); /* append file suffix */
1904 strcat (fname, suffix2); /* append file suffix */
1905 strcat (fname, ".vcg"); /* append the .vcg suffix */
1906 F = fopen (fname, "w"); /* open file for writing */
1908 panic("cannot open %s for writing (%m)", fname); /* not reached */
1918 * @param irg The graph to be dumped
1919 * @param suffix filename suffix
1921 static FILE *vcg_open_name (const char *name, const char *suffix) {
1923 char *fname; /* filename to put the vcg information in */
1924 int i, j, len = strlen(name);
1926 if (!suffix) suffix = "";
1928 /** open file for vcg graph */
1929 fname = malloc (len * 2 + 5 + strlen(suffix));
1930 /* strcpy (fname, name);*/ /* copy the filename */
1932 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1933 if (name[i] == '/') {
1934 fname[j] = '@'; j++; fname[j] = '1'; j++;
1935 } else if (name[i] == '@') {
1936 fname[j] = '@'; j++; fname[j] = '2'; j++;
1938 fname[j] = name[i]; j++;
1942 strcat (fname, suffix);
1943 strcat (fname, ".vcg"); /* append the .vcg suffix */
1944 F = fopen (fname, "w"); /* open file for writing */
1946 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1954 * Dumps the vcg file footer
1956 static INLINE void dump_vcg_footer (FILE *F) {
1961 * close the vcg file
1963 void vcg_close (FILE *F) {
1964 dump_vcg_footer(F); /* print footer */
1965 fclose (F); /* close vcg file */
1968 /************************************************************************/
1969 /************************************************************************/
1970 /* Routines that dump all or parts of the firm representation to a file */
1971 /************************************************************************/
1972 /************************************************************************/
1974 /************************************************************************/
1975 /* Dump ir graphs, differnt formats and additional information. */
1976 /************************************************************************/
1978 /** Routine to dump a graph, blocks as conventional nodes. */
1980 dump_ir_graph (ir_graph *irg, const char *suffix )
1985 rem = current_ir_graph;
1987 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1988 current_ir_graph = irg;
1989 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1990 else suffix1 = "-pure";
1991 f = vcg_open(irg, suffix, suffix1);
1992 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1994 /* walk over the graph */
1995 /* dump_whole_node must be called in post visiting predecessors */
1996 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1998 /* dump the out edges in a separate walk */
1999 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2000 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2005 current_ir_graph = rem;
2010 dump_ir_block_graph (ir_graph *irg, const char *suffix)
2016 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2019 if (get_interprocedural_view()) suffix1 = "-ip";
2021 f = vcg_open(irg, suffix, suffix1);
2022 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2024 construct_block_lists(irg);
2026 for (i = 0; i < get_irp_n_irgs(); i++) {
2027 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2029 dump_graph(f, get_irp_irg(i));
2037 /** dumps a graph with type information */
2039 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2042 ir_graph *rem = current_ir_graph;
2045 /* if a filter is set, dump only the irg's that match the filter */
2046 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2049 current_ir_graph = irg;
2051 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2052 else suffix1 = "-pure-wtypes";
2053 f = vcg_open(irg,suffix, suffix1);
2054 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2056 /* dump common ir graph */
2057 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2058 /* dump type info */
2059 type_walk_irg(irg, dump_type_info, NULL, f);
2060 inc_irg_visited(get_const_code_irg());
2061 /* dump edges from graph to type info */
2062 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2065 current_ir_graph = rem;
2069 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2074 ir_graph *rem = current_ir_graph;
2076 /* if a filter is set, dump only the irg's that match the filter */
2077 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2080 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2081 else suffix1 = "-wtypes";
2082 f = vcg_open(irg, suffix, suffix1);
2083 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2085 /* dump common blocked ir graph */
2086 construct_block_lists(irg);
2088 for (i = 0; i < get_irp_n_irgs(); i++) {
2089 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2091 dump_graph(f, get_irp_irg(i));
2096 /* dump type info */
2097 current_ir_graph = irg;
2098 type_walk_irg(irg, dump_type_info, NULL, f);
2099 inc_irg_visited(get_const_code_irg());
2101 /* dump edges from graph to type info */
2102 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2104 current_ir_graph = rem;
2108 /*---------------------------------------------------------------------*/
2109 /* The following routines dump a control flow graph. */
2110 /*---------------------------------------------------------------------*/
2113 dump_block_to_cfg(ir_node *block, void *env) {
2118 if (is_Block(block)) {
2119 /* This is a block. Dump a node for the block. */
2120 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2121 fprintf (F, "\" label: \"");
2122 if (block == get_irg_start_block(get_irn_irg(block)))
2123 fprintf(F, "Start ");
2124 if (block == get_irg_end_block(get_irn_irg(block)))
2127 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2128 PRINT_NODEID(block);
2130 fprintf(F, "info1:\"");
2131 if (dump_dominator_information_flag)
2132 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2134 /* show arity and possible Bad predecessors of the block */
2135 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2136 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2137 ir_node *pred = get_Block_cfgpred(block, i);
2140 fprintf(F, "Bad pred at pos: ");
2141 fprintf(F, "%d ", i);
2148 fprintf (F, "\""); /* closing quote of info */
2150 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2151 (block == get_irg_end_block(get_irn_irg(block))) )
2152 fprintf(F, " color:blue ");
2154 fprintf(F, " color:yellow ");
2157 /* Dump the edges */
2158 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2159 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2160 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2161 fprintf (F, "edge: { sourcename: \"");
2162 PRINT_NODEID(block);
2163 fprintf (F, "\" targetname: \"");
2165 fprintf (F, "\"}\n");
2168 /* Dump dominator edge */
2169 if (dump_dominator_information_flag && get_Block_idom(block)) {
2170 pred = get_Block_idom(block);
2171 fprintf (F, "edge: { sourcename: \"");
2172 PRINT_NODEID(block);
2173 fprintf (F, "\" targetname: \"");
2175 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2181 dump_cfg (ir_graph *irg, const char *suffix)
2184 ir_graph *rem = current_ir_graph;
2185 int ddif = dump_dominator_information_flag;
2186 int ipv = get_interprocedural_view();
2188 /* if a filter is set, dump only the irg's that match the filter */
2189 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2192 current_ir_graph = irg;
2194 f = vcg_open(irg, suffix, "-cfg");
2195 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2198 printf("Warning: dumping cfg not in interprocedural view!\n");
2199 set_interprocedural_view(false);
2202 if (get_irg_dom_state(irg) != dom_consistent)
2203 dump_dominator_information_flag = 0;
2205 /* walk over the blocks in the graph */
2206 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2207 dump_node(f, get_irg_bad(irg));
2209 dump_dominator_information_flag = ddif;
2210 set_interprocedural_view(ipv);
2212 current_ir_graph = rem;
2215 static int weight_overall(int rec, int loop) {
2216 return 2*rec + loop;
2219 static int compute_color (int my, int max) {
2224 /* if small, scale to the full color range. */
2226 my = my * (n_colors/max);
2228 int step = 1 + (max / n_colors);
2232 return base_color + n_colors - color;
2235 static int get_entity_color(entity *ent) {
2236 assert(get_entity_irg(ent));
2237 ir_graph *irg = get_entity_irg(ent);
2239 int rec_depth = get_irg_recursion_depth(irg);
2240 int loop_depth = get_irg_loop_depth(irg);
2241 int overall_depth = weight_overall(rec_depth, loop_depth);
2243 int max_rec_depth = irp->max_callgraph_recursion_depth;
2244 int max_loop_depth = irp->max_callgraph_loop_depth;
2245 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2247 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2248 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2249 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2251 return my_overall_color;
2254 void dump_callgraph(const char *suffix) {
2256 int i, n_irgs = get_irp_n_irgs();
2257 int rem = edge_label;
2259 //ident *prefix = new_id_from_str("java/");
2261 F = vcg_open_name("Callgraph", suffix);
2262 dump_vcg_header(F, "Callgraph", NULL);
2264 for (i = 0; i < n_irgs; ++i) {
2265 ir_graph *irg = get_irp_irg(i);
2266 entity *ent = get_irg_entity(irg);
2267 int j, n_callees = get_irg_n_callees(irg);
2269 /* Do not dump runtime system. */
2270 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2272 dump_entity_node(F, ent, get_entity_color(ent));
2273 for (j = 0; j < n_callees; ++j) {
2274 entity *c = get_irg_entity(get_irg_callee(irg, j));
2275 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2276 int be = is_irg_callee_backedge(irg, j);
2279 "label:\"recursion %d\" color: %d" :
2280 "label:\"calls %d\" color: %d";
2281 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2289 /* Dump all irgs in interprocedural view to a single file. */
2290 void dump_all_cg_block_graph(const char *suffix) {
2293 int rem_view = get_interprocedural_view();
2294 set_interprocedural_view(true);
2296 f = vcg_open_name("All_graphs", suffix);
2297 dump_vcg_header(f, "All_graphs", NULL);
2299 /* collect nodes in all irgs reachable in call graph*/
2300 for (i = 0; i < get_irp_n_irgs(); i++)
2301 ird_set_irg_link(get_irp_irg(i), NULL);
2303 cg_walk(clear_link, collect_node, NULL);
2305 /* dump all graphs */
2306 for (i = 0; i < get_irp_n_irgs(); i++) {
2307 current_ir_graph = get_irp_irg(i);
2308 assert(ird_get_irg_link(current_ir_graph));
2309 dump_graph(f, current_ir_graph);
2310 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2314 set_interprocedural_view(rem_view);
2317 /*---------------------------------------------------------------------*/
2318 /* the following routines dumps type information without any ir nodes. */
2319 /*---------------------------------------------------------------------*/
2322 dump_type_graph (ir_graph *irg, const char *suffix)
2326 rem = current_ir_graph;
2328 /* if a filter is set, dump only the irg's that match the filter */
2329 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2331 current_ir_graph = irg;
2333 f = vcg_open(irg, suffix, "-type");
2334 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2336 /* walk over the blocks in the graph */
2337 type_walk_irg(irg, dump_type_info, NULL, f);
2338 /* The walker for the const code can be called several times for the
2339 same (sub) experssion. So that no nodes are dumped several times
2340 we decrease the visited flag of the corresponding graph after each
2341 walk. So now increase it finally. */
2342 inc_irg_visited(get_const_code_irg());
2345 current_ir_graph = rem;
2349 dump_all_types (const char *suffix)
2351 FILE *f = vcg_open_name("All_types", suffix);
2352 dump_vcg_header(f, "All_types", NULL);
2353 type_walk(dump_type_info, NULL, f);
2354 inc_irg_visited(get_const_code_irg());
2359 dump_class_hierarchy (bool entities, const char *suffix)
2361 FILE *f = vcg_open_name("class_hierarchy", suffix);
2365 dump_vcg_header(f, "class_hierarchy", NULL);
2370 type_walk(dump_class_hierarchy_node, NULL, &env);
2374 /*---------------------------------------------------------------------*/
2375 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2377 /* dump_ir_block_graph */
2379 /* dump_type_graph */
2380 /* dump_ir_graph_w_types */
2381 /*---------------------------------------------------------------------*/
2383 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2384 int i, n_irgs = get_irp_n_irgs();
2385 for (i = 0; i < n_irgs; ++i) {
2386 dmp_grph(get_irp_irg(i), suffix);
2391 /*--------------------------------------------------------------------------------*
2392 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2393 * packed together in one subgraph/box *
2394 *--------------------------------------------------------------------------------*/
2396 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2397 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2399 ir_loop *son = NULL;
2401 /* Dump a new loop node. */
2402 dump_loop_node(F, loop);
2404 /* Dump the loop elements. */
2406 for(i = 0; i < get_loop_n_elements(loop); i++) {
2407 le = get_loop_element(loop, i);
2409 if (get_kind(son) == k_ir_loop) {
2411 /* We are a loop son -> Recurse */
2413 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2414 fprintf(F, "\" }\n");
2415 fprintf (F, "edge: {sourcename: \"");
2417 fprintf (F, "\" targetname: \"");
2419 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2420 loop_node_started = 0;
2422 dump_loop_son_edge(F, loop, son_number++);
2423 dump_loops_standalone(F, son);
2424 } else if (get_kind(son) == k_ir_node) {
2425 /* We are a loop node -> Collect firm nodes */
2427 ir_node *n = le.node;
2430 if (!loop_node_started) {
2431 /* Start a new node which contains all firm nodes of the current loop */
2432 fprintf (F, "node: { title: \"");
2434 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2435 loop_node_started = 1;
2441 bad |= dump_node_opcode(F, n);
2442 bad |= dump_node_mode(F, n);
2443 bad |= dump_node_typeinfo(F, n);
2445 bad |= dump_node_nodeattr(F, n);
2446 fprintf (F, " %ld", get_irn_node_nr(n));
2447 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2448 if (has_backedges(n)) fprintf(F, "\t loop head!");
2449 } else { /* for callgraph loop tree */
2450 assert(get_kind(son) == k_ir_graph);
2451 /* We are a loop node -> Collect firm graphs */
2452 ir_graph *n = (ir_graph *)le.node;
2453 if (!loop_node_started) {
2454 /* Start a new node which contains all firm nodes of the current loop */
2455 fprintf (F, "node: { title: \"");
2457 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2458 loop_node_started = 1;
2463 fprintf (F, " %s", get_irg_dump_name(n));
2464 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2468 if (loop_node_started) {
2469 fprintf(F, "\" }\n");
2470 fprintf (F, "edge: {sourcename: \"");
2472 fprintf (F, "\" targetname: \"");
2474 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2475 loop_node_started = 0;
2479 void dump_loop_tree(ir_graph *irg, const char *suffix)
2482 ir_graph *rem = current_ir_graph;
2483 int el_rem = edge_label;
2486 /* if a filter is set, dump only the irg's that match the filter */
2487 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2490 current_ir_graph = irg;
2492 f = vcg_open(irg, suffix, "-looptree");
2493 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2495 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2499 edge_label = el_rem;
2500 current_ir_graph = rem;
2503 void dump_callgraph_loop_tree(const char *suffix) {
2505 F = vcg_open_name("Callgraph_looptree", suffix);
2506 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2507 dump_loops_standalone(F, irp->outermost_cg_loop);
2512 /*-----------------------------------------------------------------------------*/
2513 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2514 /*-----------------------------------------------------------------------------*/
2516 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2517 int i, son_number = 0, node_number = 0;
2519 if (dump_loop_information_flag) dump_loop_node(F, loop);
2521 for (i = 0; i < get_loop_n_elements(loop); i++) {
2522 loop_element le = get_loop_element(loop, i);
2523 if (*(le.kind) == k_ir_loop) {
2524 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2526 collect_nodeloop(F, le.son, loopnodes);
2528 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2529 eset_insert(loopnodes, le.node);
2534 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2537 for(i = 0; i < get_loop_n_elements(loop); i++) {
2538 loop_element le = get_loop_element(loop, i);
2539 if (*(le.kind) == k_ir_loop) {
2541 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2543 if (is_Block(le.node)) start = 0; else start = -1;
2544 for (j = start; j < get_irn_arity(le.node); j++) {
2545 ir_node *pred = get_irn_n(le.node, j);
2546 if (!eset_contains(loopnodes, pred)) {
2547 eset_insert(extnodes, pred);
2548 if (!is_Block(pred)) {
2549 pred = get_nodes_block(pred);
2550 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2558 void dump_loop(ir_loop *l, const char *suffix) {
2561 eset *loopnodes = eset_create();
2562 eset *extnodes = eset_create();
2565 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2566 F = vcg_open_name (name, suffix);
2567 dump_vcg_header(F, name, NULL);
2569 /* collect all nodes to dump */
2570 collect_nodeloop(F, l, loopnodes);
2571 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2573 /* build block lists */
2574 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2575 set_irn_link(n, NULL);
2576 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2577 set_irn_link(n, NULL);
2578 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2580 b = get_nodes_block(n);
2581 set_irn_link(n, get_irn_link(b));
2584 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2586 b = get_nodes_block(n);
2587 set_irn_link(n, get_irn_link(b));
2591 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2593 fprintf(F, "graph: { title: \"");
2595 fprintf(F, "\" label: \"");
2596 dump_node_opcode(F, b);
2597 fprintf (F, " %ld", get_irn_node_nr(b));
2598 fprintf(F, "\" status:clustered color:yellow\n");
2600 /* dump the blocks edges */
2601 dump_ir_data_edges(F, b);
2603 /* dump the nodes that go into the block */
2604 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2605 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2607 overrule_nodecolor = NULL;
2608 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2611 /* Close the vcg information for the block */
2613 dump_const_node_local(F, b);
2616 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2618 fprintf(F, "graph: { title: \"");
2620 fprintf(F, "\" label: \"");
2621 dump_node_opcode(F, b);
2622 fprintf (F, " %ld", get_irn_node_nr(b));
2623 fprintf(F, "\" status:clustered color:lightblue\n");
2625 /* dump the nodes that go into the block */
2626 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2627 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2629 overrule_nodecolor = NULL;
2630 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2633 /* Close the vcg information for the block */
2635 dump_const_node_local(F, b);
2639 eset_destroy(loopnodes);
2640 eset_destroy(extnodes);