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 * Returns non-zero if a node is in floating state.
289 static int node_floats(ir_node *n) {
290 return ((get_irn_pinned(n) == op_pin_state_floats) &&
291 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
295 * If the entity has a ld_name, returns it, else returns the name of the entity.
297 static const char *get_ent_dump_name(entity *ent) {
299 return "<NULL entity>";
300 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
301 if (ent->ld_name) return get_id_str(ent->ld_name);
302 return get_id_str(ent->name);
305 /* Returns the name of an IRG. */
306 const char *get_irg_dump_name(ir_graph *irg) {
307 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
308 entity *ent = get_irg_entity(irg);
309 return get_ent_dump_name(ent);
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);
327 ird_set_irn_link(node, ird_get_irn_link(block));
328 ird_set_irn_link(block, node);
332 /** Construct lists to walk ir block-wise.
334 * Collects all blocks, nodes not op_pin_state_pinned,
335 * Bad, NoMem and Unknown into a flexible array in link field of
336 * irg they belong to. Sets the irg link field to NULL in all
337 * graphs not visited.
338 * Free the list with DEL_ARR_F().
340 static ir_node ** construct_block_lists(ir_graph *irg) {
341 int i, rem_view = get_interprocedural_view();
342 ir_graph *rem = current_ir_graph;
343 current_ir_graph = irg;
345 for (i = 0; i < get_irp_n_irgs(); i++)
346 ird_set_irg_link(get_irp_irg(i), NULL);
348 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
350 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
351 set_interprocedural_view(false);
352 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
353 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
354 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
355 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
356 set_interprocedural_view(rem_view);
358 current_ir_graph = rem;
359 return ird_get_irg_link(irg);
362 /*******************************************************************/
363 /* flags to steer output */
364 /*******************************************************************/
366 /** Dump only irgs with names start with this string */
367 const char *dump_file_filter = "";
369 /** A compiler option to turn off edge labels */
370 static int edge_label = 1;
371 /** A compiler option to turn off dumping values of constant entities */
372 static int const_entities = 1;
373 /** A compiler option to dump the keep alive edges */
374 static int dump_keepalive = 0;
375 /** Compiler options to dump analysis information in dump_ir_graph */
376 int dump_out_edge_flag = 0;
377 int dump_dominator_information_flag = 0;
378 int dump_loop_information_flag = 0;
379 int dump_backedge_information_flag = 1;
380 int dump_const_local = 0;
381 bool opt_dump_analysed_type_info = 1;
382 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
384 static const char *overrule_nodecolor = NULL;
386 /** The vcg attribute hook. */
387 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
390 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
392 dump_node_vcgattr_hook = hook;
395 INLINE bool get_opt_dump_const_local(void) {
396 if (!dump_out_edge_flag && !dump_loop_information_flag)
397 return dump_const_local;
402 void only_dump_method_with_name(ident *name) {
403 dump_file_filter = get_id_str(name);
407 /* To turn off display of edge labels. Edge labels offen cause xvcg to
408 abort with a segmentation fault. */
409 void turn_off_edge_labels(void) {
413 void dump_consts_local(bool b) {
414 dump_const_local = b;
417 void turn_off_constant_entity_values(void) {
421 void dump_keepalive_edges(bool b) {
425 bool get_opt_dump_keepalive_edges(void) {
426 return dump_keepalive;
429 void dump_out_edges(void) {
430 dump_out_edge_flag = 1;
433 void dump_dominator_information(void) {
434 dump_dominator_information_flag = 1;
437 void dump_loop_information(void) {
438 dump_loop_information_flag = 1;
441 void dont_dump_loop_information(void) {
442 dump_loop_information_flag = 0;
445 void dump_backedge_information(bool b) {
446 dump_backedge_information_flag = b;
449 /* Dump the information of type field specified in ana/irtypeinfo.h.
450 * If the flag is set, the type name is output in [] in the node label,
451 * else it is output as info.
453 void dump_analysed_type_info(bool b) {
454 opt_dump_analysed_type_info = b;
457 void dump_pointer_values_to_info(bool b) {
458 opt_dump_pointer_values_to_info = b;
461 /*-----------------------------------------------------------------*/
462 /* Routines to dump information about a single ir node. */
463 /*-----------------------------------------------------------------*/
466 * dump the name of a node n to the File F.
469 dump_node_opcode(FILE *F, ir_node *n)
473 switch(get_irn_opcode(n)) {
478 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
479 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
484 if (get_SymConst_kind(n) == symconst_addr_name) {
485 /* don't use get_SymConst_ptr_info as it mangles the name. */
486 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
487 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
488 assert(get_SymConst_entity(n));
489 assert(is_entity(get_SymConst_entity(n)));
490 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
492 assert(get_kind(get_SymConst_type(n)) == k_type);
493 assert(get_type_ident(get_SymConst_type(n)));
494 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
495 if (get_SymConst_kind(n) == symconst_type_tag)
503 if (!get_interprocedural_view())
510 ir_node *pred = get_Proj_pred(n);
512 if (get_irn_opcode(pred) == iro_Cond
513 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
514 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
515 fprintf (F, "defProj");
517 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
518 * fprintf (F, "Arg");
527 if (get_interprocedural_view()) {
528 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
533 case iro_CallBegin: {
534 ir_node *addr = get_CallBegin_ptr(n);
536 if (get_irn_op(addr) == op_Sel)
537 ent = get_Sel_entity(addr);
538 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
539 ent = get_SymConst_entity(addr);
540 fprintf (F, "%s", get_irn_opname(n));
541 if (ent) fprintf (F, " %s", get_entity_name(ent));
545 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
550 fprintf (F, "%s", get_irn_opname(n));
558 * Dump the mode of a node n to a file F.
559 * Ignore modes that are "always known".
562 dump_node_mode(FILE *F, ir_node *n)
565 opcode iro = get_irn_opcode(n);
578 ir_mode *mode = get_irn_mode(n);
580 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
581 (mode != mode_T || iro == iro_Proj))
582 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
590 * Dump the tpe of a node n to a file F if it's known.
592 static int dump_node_typeinfo(FILE *F, ir_node *n) {
595 if (opt_dump_analysed_type_info) {
596 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
597 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
598 type *tp = get_irn_typeinfo_type(n);
600 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
609 * Dump addinional node attributes of some nodes to a file F.
612 dump_node_nodeattr(FILE *F, ir_node *n)
616 switch (get_irn_opcode(n)) {
618 if (false && get_interprocedural_view()) {
619 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
623 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
624 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
626 fprintf (F, "%ld", get_Proj_proj(n));
630 fprintf (F, "%ld", get_Filter_proj(n));
633 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
636 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
639 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
650 * dumps the attributes of a node n into the file F.
651 * Currently this is only the color of a node.
653 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
656 fprintf(F, "color: red");
660 if (dump_node_vcgattr_hook)
661 if (dump_node_vcgattr_hook(F, n))
664 switch (get_irn_opcode(n)) {
671 fprintf (F, "color: blue");
674 fprintf (F, "color: lightyellow");
677 fprintf (F, "color: green");
683 fprintf (F, "color: yellow");
686 PRINT_DEFAULT_NODE_ATTR;
689 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
693 * Dump the node information of a node n to a file F.
695 static INLINE int dump_node_info(FILE *F, ir_node *n)
701 fprintf (F, " info1: \"");
702 if (opt_dump_pointer_values_to_info)
703 fprintf (F, "addr: %p\n", (void *)n);
704 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
705 fprintf (F, "visited: %ld\n", get_irn_visited(n));
706 irg = get_irn_irg(n);
707 if (irg != get_const_code_irg())
708 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
710 if (get_irn_pinned(n) == op_pin_state_floats &&
711 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
712 fprintf(F, "node was pinned in ");
713 dump_node_opcode(F, get_nodes_block(n));
714 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
718 /* show all predecessor nodes */
719 fprintf(F, "pred nodes: \n");
722 dump_node_opcode(F, get_nodes_block(n));
723 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
725 for ( i = 0; i < get_irn_arity(n); ++i) {
726 fprintf(F, " %d: ", i);
727 dump_node_opcode(F, get_irn_n(n, i));
728 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
732 fprintf(F, "arity: %d", get_irn_arity(n));
733 if ((get_irn_op(n) == op_Block) ||
734 (get_irn_op(n) == op_Phi) ||
735 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
736 fprintf(F, " backedges:");
738 for (i = 0; i < get_irn_arity(n); i++)
739 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
743 /* Loop node Someone else please tell me what's wrong ...
744 if (get_irn_loop(n)) {
745 ir_loop *loop = get_irn_loop(n);
747 fprintf(F, " in loop %d with depth %d\n",
748 get_loop_loop_nr(loop), get_loop_depth(loop));
753 switch (get_irn_opcode(n)) {
755 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
756 fprintf(F, "start of method of type %s\n", get_type_name_ex(tp, &bad));
757 for (i = 0; i < get_method_n_params(tp); ++i)
758 fprintf(F, " param %d type: %s n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
759 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
760 ir_node *sbl = get_nodes_block(n);
761 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
762 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
763 for (i = 0; i < n_cfgpreds; ++i) {
764 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
765 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
766 get_irg_dump_name(get_irn_irg(cfgpred)));
771 fprintf(F, "allocating entity of type %s\n", get_type_name_ex(get_Alloc_type(n), &bad));
774 fprintf(F, "freeing entity of type %s\n", get_type_name_ex(get_Free_type(n), &bad));
777 entity *ent = get_Sel_entity(n);
780 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
781 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
784 fprintf(F, "<NULL entity>\n");
789 type *tp = get_Call_type(n);
790 fprintf(F, "calling method of type %s\n", get_type_name_ex(tp, &bad));
791 if(get_unknown_type() != tp) {
792 for (i = 0; i < get_method_n_params(tp); ++i)
793 fprintf(F, " param %d type: %s\n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
794 for (i = 0; i < get_method_n_ress(tp); ++i)
795 fprintf(F, " resul %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
797 if (Call_has_callees(n)) {
798 fprintf(F, "possible callees:\n");
799 for (i = 0; i < get_Call_n_callees(n); i++) {
800 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
804 case iro_CallBegin: {
805 ir_node *call = get_CallBegin_call(n);
806 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
807 if (Call_has_callees(call)) {
808 fprintf(F, "possible callees: \n");
809 for (i = 0; i < get_Call_n_callees(call); i++) {
810 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
815 if (!get_interprocedural_view()) {
816 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
817 fprintf(F, "return in method of type %s\n", get_type_name_ex(tp, &bad));
818 for (i = 0; i < get_method_n_ress(tp); ++i)
819 fprintf(F, " res %d type: %s\n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
823 type *tp = get_Const_type(n);
824 assert(tp != none_type);
825 fprintf(F, "Const of type %s\n", get_type_name_ex(get_Const_type(n), &bad));
828 switch(get_SymConst_kind(n)) {
829 case symconst_addr_name:
830 fprintf(F, "kind: addr_name\n");
832 case symconst_addr_ent:
833 fprintf(F, "kind: addr_ent\n");
834 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
836 case symconst_type_tag:
837 fprintf(F, "kind: type_tag\n");
840 fprintf(F, "kind: size\n");
843 fprintf(F, "SymConst of type: %s\n", get_type_name_ex(get_SymConst_value_type(n), &bad));
847 if (get_interprocedural_view()) {
848 fprintf(F, "intra predecessor nodes:\n");
849 for (i = 0; i < get_irn_intra_arity(n); i++) {
850 ir_node *pred = get_irn_intra_n(n, i);
851 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
854 fprintf(F, "inter predecessor nodes:\n");
855 for (i = 0; i < get_irn_inter_arity(n); i++) {
856 ir_node *pred = get_irn_inter_n(n, i);
857 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
858 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
863 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
866 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
872 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
873 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
874 if (get_irn_typeinfo_type(n) != none_type)
875 fprintf (F, "Analysed type: %s\n", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
883 * checks wheater a node is "constant-like", ie can be treated "block-less"
886 bool is_constlike_node(ir_node *n) {
887 ir_op *op = get_irn_op(n);
888 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
892 /** outputs the predecessors of n, that are constants, local. I.e.,
893 generates a copy of the constant predecessors for each node called with. */
894 static void dump_const_node_local(FILE *F, ir_node *n) {
896 if (!get_opt_dump_const_local()) return;
898 /* Use visited flag to avoid outputting nodes twice.
899 initialize it first. */
900 for (i = 0; i < get_irn_arity(n); i++) {
901 ir_node *con = get_irn_n(n, i);
902 if (is_constlike_node(con)) {
903 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
907 for (i = 0; i < get_irn_arity(n); i++) {
908 ir_node *con = get_irn_n(n, i);
909 if (is_constlike_node(con) && irn_not_visited(con)) {
912 mark_irn_visited(con);
913 /* Generate a new name for the node by appending the names of
915 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
916 fprintf(F, " label: \"");
917 bad |= dump_node_opcode(F, con);
918 bad |= dump_node_mode(F, con);
919 bad |= dump_node_typeinfo(F, con);
921 bad |= dump_node_nodeattr(F, con);
922 fprintf(F, " %ld", get_irn_node_nr(con));
924 bad |= dump_node_info(F, con);
925 dump_node_vcgattr(F, con, bad);
932 * prints the error message of a node to a file F as info2.
934 static void INLINE print_node_error(FILE *F, const char *err_msg)
939 fprintf (F, " info2: \"%s\"", err_msg);
945 static void dump_node(FILE *F, ir_node *n)
950 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
952 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
954 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
955 bad |= dump_node_opcode(F, n);
956 bad |= dump_node_mode(F, n);
957 bad |= dump_node_typeinfo(F, n);
959 bad |= dump_node_nodeattr(F, n);
960 fprintf(F, " %ld", get_irn_node_nr(n));
962 bad |= dump_node_info(F, n);
963 print_node_error(F, p);
964 dump_node_vcgattr(F, n, bad);
966 dump_const_node_local(F, n);
973 /** dump the edge to the block this node belongs to */
975 dump_ir_block_edge(FILE *F, ir_node *n) {
976 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
977 if (is_no_Block(n)) {
978 ir_node *block = get_nodes_block(n);
980 fprintf (F, "edge: { sourcename: \"");
982 fprintf (F, "\" targetname: ");
983 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
984 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
989 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
990 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
991 fprintf (F, INTRA_DATA_EDGE_ATTR);
993 fprintf (F, INTER_DATA_EDGE_ATTR);
997 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
998 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
999 fprintf (F, INTRA_MEM_EDGE_ATTR);
1001 fprintf (F, INTER_MEM_EDGE_ATTR);
1005 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1008 if (dump_backedge_information_flag && is_backedge(from, to))
1009 fprintf (F, BACK_EDGE_ATTR);
1011 switch (get_irn_opcode(from)) {
1013 fprintf (F, CF_EDGE_ATTR);
1015 case iro_Start: break;
1018 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1019 fprintf (F, CF_EDGE_ATTR);
1020 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1021 fprintf (F, INTER_MEM_EDGE_ATTR);
1029 print_data_edge_vcgattr(F, from, to);
1034 print_mem_edge_vcgattr(F, from, to);
1036 print_data_edge_vcgattr(F, from, to);
1040 print_data_edge_vcgattr(F, from, to);
1045 print_mem_edge_vcgattr(F, from, to);
1047 print_data_edge_vcgattr(F, from, to);
1054 print_data_edge_vcgattr(F, from, to);
1061 print_mem_edge_vcgattr(F, from, to);
1063 print_data_edge_vcgattr(F, from, to);
1075 print_data_edge_vcgattr(F, from, to);
1078 if (get_irn_modecode(from) == irm_M)
1079 fprintf (F, INTER_MEM_EDGE_ATTR);
1081 print_data_edge_vcgattr(F, from, to);
1088 print_mem_edge_vcgattr(F, from, to);
1090 print_data_edge_vcgattr(F, from, to);
1093 print_mem_edge_vcgattr(F, from, to);
1095 case iro_Tuple: break;
1098 switch (get_irn_modecode(from)) {
1100 fprintf (F, CF_EDGE_ATTR);
1103 fprintf (F, INTER_MEM_EDGE_ATTR);
1106 print_data_edge_vcgattr(F, from, to);
1110 case iro_Bad: break;
1111 case iro_Unknown: break;
1113 switch (get_irn_modecode(from)) {
1115 fprintf (F, INTRA_MEM_EDGE_ATTR);
1118 fprintf (F, CF_EDGE_ATTR);
1121 print_data_edge_vcgattr(F, from, to);
1129 /* dump edges to our inputs */
1131 dump_ir_data_edges(FILE *F, ir_node *n) {
1132 int i, visited = get_irn_visited(n);
1134 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1137 for (i = 0; i < get_irn_arity(n); i++) {
1138 ir_node * pred = get_irn_n(n, i);
1141 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1142 continue; /* pred not dumped */
1144 if (dump_backedge_information_flag && is_backedge(n, i))
1145 fprintf (F, "backedge: {sourcename: \"");
1147 fprintf (F, "edge: {sourcename: \"");
1149 fprintf (F, "\" targetname: ");
1150 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1151 PRINT_CONSTID(n, pred);
1153 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1155 fprintf (F, " label: \"%d\" ", i);
1156 print_edge_vcgattr(F, n, i);
1161 /** Dumps a node and its edges but not the block edge
1164 dump_node_wo_blockedge (ir_node *n, void *env) {
1167 dump_ir_data_edges(F, n);
1170 /** Dumps a node and its edges.
1173 dump_whole_node (ir_node *n, void *env) {
1175 dump_node_wo_blockedge(n, env);
1176 if (!node_floats(n)) dump_ir_block_edge(F, n);
1180 dump_const_node(ir_node *n, void *env) {
1181 if (is_Block(n)) return;
1182 dump_node_wo_blockedge(n, env);
1185 /***********************************************************************/
1186 /* the following routines dump the nodes/irgs bracketed to graphs. */
1187 /***********************************************************************/
1189 /** Dumps a constant expression as entity initializer, array bound ...
1191 static void dump_const_expression(FILE *F, ir_node *value) {
1192 ir_graph *rem = current_ir_graph;
1193 int rem_dump_const_local = dump_const_local;
1194 dump_const_local = 0;
1195 current_ir_graph = get_const_code_irg();
1196 irg_walk(value, dump_const_node, NULL, F);
1197 /* Decrease visited flag so that we walk with the same flag for the next
1198 expresssion. This guarantees that we don't dump the same node twice,
1199 as for const expressions cse is performed to save memory. */
1200 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1201 current_ir_graph = rem;
1202 dump_const_local = rem_dump_const_local;
1205 /** Dump a block as graph containing its nodes.
1207 * Expects to find nodes belonging to the block as list in its
1209 * Dumps the edges of all nodes including itself. */
1211 dump_whole_block(FILE *F, ir_node *block) {
1213 assert(is_Block(block));
1215 fprintf(F, "graph: { title: \"");
1216 PRINT_NODEID(block);
1217 fprintf(F, "\" label: \"");
1218 dump_node_opcode(F, block);
1219 fprintf (F, " %ld", get_irn_node_nr(block));
1221 if (get_opt_dump_abstvals())
1222 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1224 fprintf(F, "\" status:clustered color:%s \n",
1225 get_Block_matured(block) ? "yellow" : "red");
1227 /* dump the blocks edges */
1228 dump_ir_data_edges(F, block);
1230 /* dump the nodes that go into the block */
1231 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1233 dump_ir_data_edges(F, node);
1236 /* Close the vcg information for the block */
1238 dump_const_node_local(F, block);
1240 dump_chi_term(F, block);
1245 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1246 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1248 dump_block_graph(FILE *F, ir_graph *irg) {
1250 ir_graph *rem = current_ir_graph;
1251 ir_node **arr = ird_get_irg_link(irg);
1252 current_ir_graph = irg;
1254 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1255 ir_node * node = arr[i];
1256 if (is_Block(node)) {
1257 /* Dumps the block and all the nodes in the block, which are to
1258 be found in Block->link. */
1259 dump_whole_block(F, node);
1261 /* Nodes that are not in a Block. */
1263 dump_ir_data_edges(F, node);
1267 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1268 dump_loop_nodes_into_graph(F, irg);
1270 current_ir_graph = rem;
1273 /** Dumps an irg as a graph.
1274 * If interprocedural view edges can point to nodes out of this graph.
1276 static void dump_graph(FILE *F, ir_graph *irg) {
1278 fprintf(F, "graph: { title: \"");
1280 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1281 get_ent_dump_name(get_irg_entity(irg)));
1283 dump_block_graph(F, irg);
1285 /* Close the vcg information for the irg */
1286 fprintf(F, "}\n\n");
1289 /*******************************************************************/
1290 /* Basic type and entity nodes and edges. */
1291 /*******************************************************************/
1293 /** dumps the edges between nodes and their type or entity attributes. */
1294 static void dump_node2type_edges(ir_node *n, void *env)
1299 switch (get_irn_opcode(n)) {
1301 /* @@@ some consts have an entity */
1304 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1305 || (get_SymConst_kind(n) ==symconst_size))
1307 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1311 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1314 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1317 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1320 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1323 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1331 static int print_type_info(FILE *F, type *tp) {
1334 if (get_type_state(tp) == layout_undefined) {
1335 fprintf(F, "state: layout_undefined\n");
1337 fprintf(F, "state: layout_fixed,\n");
1339 if (get_type_mode(tp))
1340 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1341 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1346 static void print_typespecific_info(FILE *F, type *tp) {
1347 switch (get_type_tpop_code(tp)) {
1350 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1357 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1358 fprintf(F, "params: %d\n", get_method_n_params(tp));
1359 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1367 case tpo_enumeration:
1381 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1382 switch (get_type_tpop_code(tp)) {
1385 if (peculiarity_existent == get_class_peculiarity(tp))
1386 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1388 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1392 fprintf (F, " " TYPE_METH_NODE_ATTR);
1403 case tpo_enumeration:
1416 static int print_type_node(FILE *F, type *tp)
1420 fprintf (F, "node: {title: ");
1422 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1423 fprintf (F, " info1: \"");
1424 bad |= print_type_info(F, tp);
1425 print_typespecific_info(F, tp);
1427 print_typespecific_vcgattr(F, tp);
1433 #define X(a) case a: fprintf(F, #a); break
1434 void dump_entity_node(FILE *F, entity *ent, int color)
1436 fprintf (F, "node: {title: \"");
1437 PRINT_ENTID(ent); fprintf(F, "\"");
1438 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1439 fprintf (F, "label: ");
1440 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1442 fprintf(F, "color: %d", color);
1444 fprintf (F, ENTITY_NODE_ATTR);
1445 fprintf (F, "\n info1: \"");
1447 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1449 fprintf(F, "\"\n}\n");
1453 static void dump_enum_item(FILE *F, type *tp, int pos)
1456 ident *id = get_enumeration_nameid(tp, pos);
1457 tarval *tv = get_enumeration_enum(tp, pos);
1459 tarval_snprintf(buf, sizeof(buf), tv);
1460 fprintf (F, "node: {title: \"");
1461 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1462 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1463 fprintf (F, "label: ");
1464 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1465 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1468 /* dumps a type or entity and it's edges. */
1470 dump_type_info(type_or_ent *tore, void *env) {
1472 int i = 0; /* to shutup gcc */
1474 /* dump this type or entity */
1476 switch (get_kind(tore)) {
1479 entity *ent = (entity *)tore;
1482 dump_entity_node(F, ent, 0);
1484 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1485 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1486 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1487 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1488 if(is_class_type(get_entity_owner(ent))) {
1489 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1490 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1492 /* attached subgraphs */
1493 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1494 if (is_atomic_entity(ent)) {
1495 value = get_atomic_ent_value(ent);
1497 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1498 /* DDMN(value); $$$ */
1499 dump_const_expression(F, value);
1502 if (is_compound_entity(ent)) {
1503 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1504 value = get_compound_ent_value(ent, i);
1506 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1507 dump_const_expression(F, value);
1508 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1510 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1511 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1512 get_compound_ent_value_member(ent, i), i);
1521 type *tp = (type *)tore;
1522 print_type_node(F, tp);
1523 /* and now the edges */
1524 switch (get_type_tpop_code(tp)) {
1527 for (i=0; i < get_class_n_supertypes(tp); i++)
1528 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1529 for (i=0; i < get_class_n_members(tp); i++)
1530 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1534 for (i=0; i < get_struct_n_members(tp); i++)
1535 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1539 for (i = 0; i < get_method_n_params(tp); i++)
1540 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1541 for (i = 0; i < get_method_n_ress(tp); i++)
1542 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1546 for (i = 0; i < get_union_n_members(tp); i++)
1547 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1551 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1552 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1553 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1554 ir_node *upper = get_array_upper_bound(tp, i);
1555 ir_node *lower = get_array_lower_bound(tp, i);
1556 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1557 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1558 dump_const_expression(F, upper);
1559 dump_const_expression(F, lower);
1563 case tpo_enumeration:
1565 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1566 dump_enum_item(F, tp, i);
1567 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1572 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1580 break; /* case k_type */
1583 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1585 } /* switch kind_or_entity */
1588 typedef struct _h_env {
1593 /** For dumping class hierarchies.
1594 * Dumps a class type node and a superclass edge.
1595 * If env->dump_ent dumps entities of classes and overwrites edges.
1598 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1601 int i = 0; /* to shutup gcc */
1603 /* dump this type or entity */
1604 switch (get_kind(tore)) {
1606 entity *ent = (entity *)tore;
1607 if (get_entity_owner(ent) == get_glob_type()) break;
1608 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1609 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1611 dump_entity_node(F, ent, 0);
1613 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1614 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1615 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1617 } break; /* case k_entity */
1620 type *tp = (type *)tore;
1621 if (tp == get_glob_type()) break;
1622 switch (get_type_tpop_code(tp)) {
1624 print_type_node(F, tp);
1625 /* and now the edges */
1626 for (i=0; i < get_class_n_supertypes(tp); i++)
1628 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1634 break; /* case k_type */
1637 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1639 } /* switch kind_or_entity */
1642 /*******************************************************************/
1643 /* dump analysis information that is expressed in graph terms. */
1644 /*******************************************************************/
1646 /* dump out edges */
1648 dump_out_edge(ir_node *n, void *env) {
1651 for (i = 0; i < get_irn_n_outs(n); i++) {
1652 assert(get_irn_out(n, i));
1653 fprintf (F, "edge: {sourcename: \"");
1655 fprintf (F, "\" targetname: \"");
1656 PRINT_NODEID(get_irn_out(n, i));
1657 fprintf (F, "\" color: red linestyle: dashed");
1663 dump_loop_label(FILE *F, ir_loop *loop) {
1664 fprintf (F, "loop %d, %d sons, %d nodes",
1665 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1668 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1669 fprintf (F, " info1: \"");
1670 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1671 #if DEBUG_libfirm /* GL @@@ debug analyses */
1672 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1678 dump_loop_node(FILE *F, ir_loop *loop) {
1679 fprintf (F, "node: {title: \"");
1681 fprintf (F, "\" label: \"");
1682 dump_loop_label(F, loop);
1684 dump_loop_info(F, loop);
1690 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1692 fprintf (F, "edge: {sourcename: \"");
1694 fprintf (F, "\" targetname: \"");
1695 PRINT_NODEID(get_loop_node(loop, i));
1696 fprintf (F, "\" color: green");
1701 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1703 fprintf (F, "edge: {sourcename: \"");
1705 fprintf (F, "\" targetname: \"");
1706 PRINT_LOOPID(get_loop_son(loop, i));
1707 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1708 get_loop_element_pos(loop, get_loop_son(loop, i)));
1712 void dump_loops(FILE *F, ir_loop *loop) {
1714 /* dump this loop node */
1715 dump_loop_node(F, loop);
1717 /* dump edges to nodes in loop -- only if it is a real loop */
1718 if (get_loop_depth(loop) != 0) {
1719 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1720 dump_loop_node_edge(F, loop, i);
1723 for (i = 0; i < get_loop_n_sons(loop); i++) {
1724 dump_loops(F, get_loop_son(loop, i));
1725 dump_loop_son_edge(F, loop, i);
1730 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1731 ir_graph *rem = current_ir_graph;
1732 current_ir_graph = irg;
1734 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1736 current_ir_graph = rem;
1741 * dumps the VCG header
1743 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1752 if (!orientation) orientation = "bottom_to_top";
1756 "graph: { title: \"ir graph of %s\"\n"
1757 "display_edge_labels: %s\n"
1758 "layoutalgorithm: mindepth\n"
1759 "manhattan_edges: yes\n"
1760 "port_sharing: no\n"
1762 "classname 1: \"intrablock Data\"\n"
1763 "classname 16: \"interblock Data\"\n"
1764 "classname 2: \"Block\"\n"
1765 "classname 13: \"Control Flow\"\n"
1766 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1767 "classname 14: \"intrablock Memory\"\n"
1768 "classname 17: \"interblock Memory\"\n"
1769 "classname 15: \"Dominators\"\n"
1770 "classname 3: \"Entity type\"\n"
1771 "classname 4: \"Entity owner\"\n"
1772 "classname 5: \"Method Param\"\n"
1773 "classname 6: \"Method Res\"\n"
1774 "classname 7: \"Super\"\n"
1775 "classname 8: \"Union\"\n"
1776 "classname 9: \"Points-to\"\n"
1777 "classname 10: \"Array Element Type\"\n"
1778 "classname 11: \"Overwrites\"\n"
1779 "classname 12: \"Member\"\n"
1780 "infoname 1: \"Attribute\"\n"
1781 "infoname 2: \"Verification errors\"\n",
1782 name, label, orientation);
1784 /* don't use all, the range is too whith/black. */
1788 "colorentry 100: 0 0 0\n"
1789 "colorentry 101: 20 0 0\n"
1790 "colorentry 102: 40 0 0\n"
1791 "colorentry 103: 60 0 0\n"
1792 "colorentry 104: 80 0 0\n"
1793 "colorentry 105: 100 0 0\n"
1794 "colorentry 106: 120 0 0\n"
1795 "colorentry 107: 140 0 0\n"
1796 "colorentry 108: 150 0 0\n"
1797 "colorentry 109: 180 0 0\n"
1798 "colorentry 110: 200 0 0\n"
1799 "colorentry 111: 220 0 0\n"
1800 "colorentry 112: 240 0 0\n"
1801 "colorentry 113: 255 0 0\n"
1802 "colorentry 113: 255 20 20\n"
1803 "colorentry 114: 255 40 40\n"
1804 "colorentry 115: 255 60 60\n"
1805 "colorentry 116: 255 80 80\n"
1806 "colorentry 117: 255 100 100\n"
1807 "colorentry 118: 255 120 120\n"
1808 "colorentry 119: 255 140 140\n"
1809 "colorentry 120: 255 150 150\n"
1810 "colorentry 121: 255 180 180\n"
1811 "colorentry 122: 255 200 200\n"
1812 "colorentry 123: 255 220 220\n"
1813 "colorentry 124: 255 240 240\n"
1814 "colorentry 125: 255 250 250\n"
1817 fprintf (F, "\n"); /* a separator */
1823 * @param irg The graph to be dumped
1824 * @param suffix1 first filename suffix
1825 * @param suffix2 second filename suffix
1827 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1829 const char *nm = get_irg_dump_name(irg);
1830 int len = strlen(nm), i, j;
1831 char *fname; /* filename to put the vcg information in */
1833 if (!suffix1) suffix1 = "";
1834 if (!suffix2) suffix2 = "";
1836 /* open file for vcg graph */
1837 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1839 /* strncpy (fname, nm, len); */ /* copy the filename */
1841 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1843 fname[j] = '@'; j++; fname[j] = '1'; j++;
1844 } else if (nm[i] == '@') {
1845 fname[j] = '@'; j++; fname[j] = '2'; j++;
1847 fname[j] = nm[i]; j++;
1851 strcat (fname, suffix1); /* append file suffix */
1852 strcat (fname, suffix2); /* append file suffix */
1853 strcat (fname, ".vcg"); /* append the .vcg suffix */
1854 F = fopen (fname, "w"); /* open file for writing */
1856 panic("cannot open %s for writing (%m)", fname); /* not reached */
1866 * @param irg The graph to be dumped
1867 * @param suffix filename suffix
1869 static FILE *vcg_open_name (const char *name, const char *suffix) {
1871 char *fname; /* filename to put the vcg information in */
1872 int i, j, len = strlen(name);
1874 if (!suffix) suffix = "";
1876 /** open file for vcg graph */
1877 fname = malloc (len * 2 + 5 + strlen(suffix));
1878 /* strcpy (fname, name);*/ /* copy the filename */
1880 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1881 if (name[i] == '/') {
1882 fname[j] = '@'; j++; fname[j] = '1'; j++;
1883 } else if (name[i] == '@') {
1884 fname[j] = '@'; j++; fname[j] = '2'; j++;
1886 fname[j] = name[i]; j++;
1890 strcat (fname, suffix);
1891 strcat (fname, ".vcg"); /* append the .vcg suffix */
1892 F = fopen (fname, "w"); /* open file for writing */
1894 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1902 * Dumps the vcg file footer
1904 static INLINE void dump_vcg_footer (FILE *F) {
1909 * close the vcg file
1911 void vcg_close (FILE *F) {
1912 dump_vcg_footer(F); /* print footer */
1913 fclose (F); /* close vcg file */
1916 /************************************************************************/
1917 /************************************************************************/
1918 /* Routines that dump all or parts of the firm representation to a file */
1919 /************************************************************************/
1920 /************************************************************************/
1922 /************************************************************************/
1923 /* Dump ir graphs, differnt formats and additional information. */
1924 /************************************************************************/
1926 /** Routine to dump a graph, blocks as conventional nodes. */
1928 dump_ir_graph (ir_graph *irg, const char *suffix )
1933 rem = current_ir_graph;
1935 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1936 current_ir_graph = irg;
1937 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1938 else suffix1 = "-pure";
1939 f = vcg_open(irg, suffix, suffix1);
1940 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1942 /* walk over the graph */
1943 /* dump_whole_node must be called in post visiting predecessors */
1944 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1946 /* dump the out edges in a separate walk */
1947 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1948 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1953 current_ir_graph = rem;
1958 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1964 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1967 if (get_interprocedural_view()) suffix1 = "-ip";
1969 f = vcg_open(irg, suffix, suffix1);
1970 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1972 construct_block_lists(irg);
1974 for (i = 0; i < get_irp_n_irgs(); i++) {
1975 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1977 dump_graph(f, get_irp_irg(i));
1985 /** dumps a graph with type information */
1987 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1990 ir_graph *rem = current_ir_graph;
1993 /* if a filter is set, dump only the irg's that match the filter */
1994 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1997 current_ir_graph = irg;
1999 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2000 else suffix1 = "-pure-wtypes";
2001 f = vcg_open(irg,suffix, suffix1);
2002 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2004 /* dump common ir graph */
2005 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2006 /* dump type info */
2007 type_walk_irg(irg, dump_type_info, NULL, f);
2008 inc_irg_visited(get_const_code_irg());
2009 /* dump edges from graph to type info */
2010 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2013 current_ir_graph = rem;
2017 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2022 ir_graph *rem = current_ir_graph;
2024 /* if a filter is set, dump only the irg's that match the filter */
2025 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2028 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2029 else suffix1 = "-wtypes";
2030 f = vcg_open(irg, suffix, suffix1);
2031 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2033 /* dump common blocked ir graph */
2034 construct_block_lists(irg);
2036 for (i = 0; i < get_irp_n_irgs(); i++) {
2037 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2039 dump_graph(f, get_irp_irg(i));
2044 /* dump type info */
2045 current_ir_graph = irg;
2046 type_walk_irg(irg, dump_type_info, NULL, f);
2047 inc_irg_visited(get_const_code_irg());
2049 /* dump edges from graph to type info */
2050 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2052 current_ir_graph = rem;
2056 /*---------------------------------------------------------------------*/
2057 /* The following routines dump a control flow graph. */
2058 /*---------------------------------------------------------------------*/
2061 dump_block_to_cfg(ir_node *block, void *env) {
2066 if (is_Block(block)) {
2067 /* This is a block. Dump a node for the block. */
2068 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2069 fprintf (F, "\" label: \"");
2070 if (block == get_irg_start_block(get_irn_irg(block)))
2071 fprintf(F, "Start ");
2072 if (block == get_irg_end_block(get_irn_irg(block)))
2075 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2076 PRINT_NODEID(block);
2078 fprintf(F, "info1:\"");
2079 if (dump_dominator_information_flag)
2080 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2082 /* show arity and possible Bad predecessors of the block */
2083 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2084 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2085 ir_node *pred = get_Block_cfgpred(block, i);
2088 fprintf(F, "Bad pred at pos: ");
2089 fprintf(F, "%d ", i);
2096 fprintf (F, "\""); /* closing quote of info */
2098 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2099 (block == get_irg_end_block(get_irn_irg(block))) )
2100 fprintf(F, " color:blue ");
2102 fprintf(F, " color:yellow ");
2105 /* Dump the edges */
2106 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2107 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2108 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2109 fprintf (F, "edge: { sourcename: \"");
2110 PRINT_NODEID(block);
2111 fprintf (F, "\" targetname: \"");
2113 fprintf (F, "\"}\n");
2116 /* Dump dominator edge */
2117 if (dump_dominator_information_flag && get_Block_idom(block)) {
2118 pred = get_Block_idom(block);
2119 fprintf (F, "edge: { sourcename: \"");
2120 PRINT_NODEID(block);
2121 fprintf (F, "\" targetname: \"");
2123 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2129 dump_cfg (ir_graph *irg, const char *suffix)
2132 ir_graph *rem = current_ir_graph;
2133 int ddif = dump_dominator_information_flag;
2134 int ipv = get_interprocedural_view();
2136 /* if a filter is set, dump only the irg's that match the filter */
2137 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2140 current_ir_graph = irg;
2142 f = vcg_open(irg, suffix, "-cfg");
2143 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2146 printf("Warning: dumping cfg not in interprocedural view!\n");
2147 set_interprocedural_view(false);
2150 if (get_irg_dom_state(irg) != dom_consistent)
2151 dump_dominator_information_flag = 0;
2153 /* walk over the blocks in the graph */
2154 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2155 dump_node(f, get_irg_bad(irg));
2157 dump_dominator_information_flag = ddif;
2158 set_interprocedural_view(ipv);
2160 current_ir_graph = rem;
2163 static int weight_overall(int rec, int loop) {
2164 return 2*rec + loop;
2167 static int compute_color (int my, int max) {
2172 /* if small, scale to the full color range. */
2174 my = my * (n_colors/max);
2176 int step = 1 + (max / n_colors);
2180 return base_color + n_colors - color;
2183 static int get_entity_color(entity *ent) {
2184 assert(get_entity_irg(ent));
2185 ir_graph *irg = get_entity_irg(ent);
2187 int rec_depth = get_irg_recursion_depth(irg);
2188 int loop_depth = get_irg_loop_depth(irg);
2189 int overall_depth = weight_overall(rec_depth, loop_depth);
2191 int max_rec_depth = irp->max_callgraph_recursion_depth;
2192 int max_loop_depth = irp->max_callgraph_loop_depth;
2193 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2195 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2196 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2197 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2199 return my_overall_color;
2202 void dump_callgraph(const char *suffix) {
2204 int i, n_irgs = get_irp_n_irgs();
2205 int rem = edge_label;
2207 //ident *prefix = new_id_from_str("java/");
2209 F = vcg_open_name("Callgraph", suffix);
2210 dump_vcg_header(F, "Callgraph", NULL);
2212 for (i = 0; i < n_irgs; ++i) {
2213 ir_graph *irg = get_irp_irg(i);
2214 entity *ent = get_irg_entity(irg);
2215 int j, n_callees = get_irg_n_callees(irg);
2217 /* Do not dump runtime system. */
2218 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2220 dump_entity_node(F, ent, get_entity_color(ent));
2221 for (j = 0; j < n_callees; ++j) {
2222 entity *c = get_irg_entity(get_irg_callee(irg, j));
2223 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2224 int be = is_irg_callee_backedge(irg, j);
2227 "label:\"recursion %d\" color: %d" :
2228 "label:\"calls %d\" color: %d";
2229 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2237 /* Dump all irgs in interprocedural view to a single file. */
2238 void dump_all_cg_block_graph(const char *suffix) {
2241 int rem_view = get_interprocedural_view();
2242 set_interprocedural_view(true);
2244 f = vcg_open_name("All_graphs", suffix);
2245 dump_vcg_header(f, "All_graphs", NULL);
2247 /* collect nodes in all irgs reachable in call graph*/
2248 for (i = 0; i < get_irp_n_irgs(); i++)
2249 ird_set_irg_link(get_irp_irg(i), NULL);
2251 cg_walk(clear_link, collect_node, NULL);
2253 /* dump all graphs */
2254 for (i = 0; i < get_irp_n_irgs(); i++) {
2255 current_ir_graph = get_irp_irg(i);
2256 assert(ird_get_irg_link(current_ir_graph));
2257 dump_graph(f, current_ir_graph);
2258 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2262 set_interprocedural_view(rem_view);
2265 /*---------------------------------------------------------------------*/
2266 /* the following routines dumps type information without any ir nodes. */
2267 /*---------------------------------------------------------------------*/
2270 dump_type_graph (ir_graph *irg, const char *suffix)
2274 rem = current_ir_graph;
2276 /* if a filter is set, dump only the irg's that match the filter */
2277 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2279 current_ir_graph = irg;
2281 f = vcg_open(irg, suffix, "-type");
2282 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2284 /* walk over the blocks in the graph */
2285 type_walk_irg(irg, dump_type_info, NULL, f);
2286 /* The walker for the const code can be called several times for the
2287 same (sub) experssion. So that no nodes are dumped several times
2288 we decrease the visited flag of the corresponding graph after each
2289 walk. So now increase it finally. */
2290 inc_irg_visited(get_const_code_irg());
2293 current_ir_graph = rem;
2297 dump_all_types (const char *suffix)
2299 FILE *f = vcg_open_name("All_types", suffix);
2300 dump_vcg_header(f, "All_types", NULL);
2301 type_walk(dump_type_info, NULL, f);
2302 inc_irg_visited(get_const_code_irg());
2307 dump_class_hierarchy (bool entities, const char *suffix)
2309 FILE *f = vcg_open_name("class_hierarchy", suffix);
2313 dump_vcg_header(f, "class_hierarchy", NULL);
2318 type_walk(dump_class_hierarchy_node, NULL, &env);
2322 /*---------------------------------------------------------------------*/
2323 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2325 /* dump_ir_block_graph */
2327 /* dump_type_graph */
2328 /* dump_ir_graph_w_types */
2329 /*---------------------------------------------------------------------*/
2331 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2332 int i, n_irgs = get_irp_n_irgs();
2333 for (i = 0; i < n_irgs; ++i) {
2334 dmp_grph(get_irp_irg(i), suffix);
2339 /*--------------------------------------------------------------------------------*
2340 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2341 * packed together in one subgraph/box *
2342 *--------------------------------------------------------------------------------*/
2344 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2345 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2347 ir_loop *son = NULL;
2349 /* Dump a new loop node. */
2350 dump_loop_node(F, loop);
2352 /* Dump the loop elements. */
2354 for(i = 0; i < get_loop_n_elements(loop); i++) {
2355 le = get_loop_element(loop, i);
2357 if (get_kind(son) == k_ir_loop) {
2359 /* We are a loop son -> Recurse */
2361 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2362 fprintf(F, "\" }\n");
2363 fprintf (F, "edge: {sourcename: \"");
2365 fprintf (F, "\" targetname: \"");
2367 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2368 loop_node_started = 0;
2370 dump_loop_son_edge(F, loop, son_number++);
2371 dump_loops_standalone(F, son);
2372 } else if (get_kind(son) == k_ir_node) {
2373 /* We are a loop node -> Collect firm nodes */
2375 ir_node *n = le.node;
2378 if (!loop_node_started) {
2379 /* Start a new node which contains all firm nodes of the current loop */
2380 fprintf (F, "node: { title: \"");
2382 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2383 loop_node_started = 1;
2389 bad |= dump_node_opcode(F, n);
2390 bad |= dump_node_mode(F, n);
2391 bad |= dump_node_typeinfo(F, n);
2393 bad |= dump_node_nodeattr(F, n);
2394 fprintf (F, " %ld", get_irn_node_nr(n));
2395 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2396 if (has_backedges(n)) fprintf(F, "\t loop head!");
2397 } else { /* for callgraph loop tree */
2398 assert(get_kind(son) == k_ir_graph);
2399 /* We are a loop node -> Collect firm graphs */
2400 ir_graph *n = (ir_graph *)le.node;
2401 if (!loop_node_started) {
2402 /* Start a new node which contains all firm nodes of the current loop */
2403 fprintf (F, "node: { title: \"");
2405 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2406 loop_node_started = 1;
2411 fprintf (F, " %s", get_irg_dump_name(n));
2412 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2416 if (loop_node_started) {
2417 fprintf(F, "\" }\n");
2418 fprintf (F, "edge: {sourcename: \"");
2420 fprintf (F, "\" targetname: \"");
2422 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2423 loop_node_started = 0;
2427 void dump_loop_tree(ir_graph *irg, const char *suffix)
2430 ir_graph *rem = current_ir_graph;
2431 int el_rem = edge_label;
2434 /* if a filter is set, dump only the irg's that match the filter */
2435 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2438 current_ir_graph = irg;
2440 f = vcg_open(irg, suffix, "-looptree");
2441 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2443 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2447 edge_label = el_rem;
2448 current_ir_graph = rem;
2451 void dump_callgraph_loop_tree(const char *suffix) {
2453 F = vcg_open_name("Callgraph_looptree", suffix);
2454 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2455 dump_loops_standalone(F, irp->outermost_cg_loop);
2460 /*-----------------------------------------------------------------------------*/
2461 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2462 /*-----------------------------------------------------------------------------*/
2464 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2465 int i, son_number = 0, node_number = 0;
2467 if (dump_loop_information_flag) dump_loop_node(F, loop);
2469 for (i = 0; i < get_loop_n_elements(loop); i++) {
2470 loop_element le = get_loop_element(loop, i);
2471 if (*(le.kind) == k_ir_loop) {
2472 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2474 collect_nodeloop(F, le.son, loopnodes);
2476 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2477 eset_insert(loopnodes, le.node);
2482 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2485 for(i = 0; i < get_loop_n_elements(loop); i++) {
2486 loop_element le = get_loop_element(loop, i);
2487 if (*(le.kind) == k_ir_loop) {
2489 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2491 if (is_Block(le.node)) start = 0; else start = -1;
2492 for (j = start; j < get_irn_arity(le.node); j++) {
2493 ir_node *pred = get_irn_n(le.node, j);
2494 if (!eset_contains(loopnodes, pred)) {
2495 eset_insert(extnodes, pred);
2496 if (!is_Block(pred)) {
2497 pred = get_nodes_block(pred);
2498 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2506 void dump_loop(ir_loop *l, const char *suffix) {
2509 eset *loopnodes = eset_create();
2510 eset *extnodes = eset_create();
2513 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2514 F = vcg_open_name (name, suffix);
2515 dump_vcg_header(F, name, NULL);
2517 /* collect all nodes to dump */
2518 collect_nodeloop(F, l, loopnodes);
2519 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2521 /* build block lists */
2522 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2523 set_irn_link(n, NULL);
2524 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2525 set_irn_link(n, NULL);
2526 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2528 b = get_nodes_block(n);
2529 set_irn_link(n, get_irn_link(b));
2532 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2534 b = get_nodes_block(n);
2535 set_irn_link(n, get_irn_link(b));
2539 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2541 fprintf(F, "graph: { title: \"");
2543 fprintf(F, "\" label: \"");
2544 dump_node_opcode(F, b);
2545 fprintf (F, " %ld", get_irn_node_nr(b));
2546 fprintf(F, "\" status:clustered color:yellow\n");
2548 /* dump the blocks edges */
2549 dump_ir_data_edges(F, b);
2551 /* dump the nodes that go into the block */
2552 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2553 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2555 overrule_nodecolor = NULL;
2556 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2559 /* Close the vcg information for the block */
2561 dump_const_node_local(F, b);
2564 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2566 fprintf(F, "graph: { title: \"");
2568 fprintf(F, "\" label: \"");
2569 dump_node_opcode(F, b);
2570 fprintf (F, " %ld", get_irn_node_nr(b));
2571 fprintf(F, "\" status:clustered color:lightblue\n");
2573 /* dump the nodes that go into the block */
2574 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2575 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2577 overrule_nodecolor = NULL;
2578 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2581 /* Close the vcg information for the block */
2583 dump_const_node_local(F, b);
2587 eset_destroy(loopnodes);
2588 eset_destroy(extnodes);