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"
32 #include "type_or_entity.h"
36 #include "callgraph.h"
46 void dump_chi_term(FILE *FL, ir_node *n);
47 void dump_state(FILE *FL, ir_node *n);
48 int get_opt_dump_abstvals(void);
49 typedef unsigned long SeqNo;
50 SeqNo get_Block_seqno(ir_node *n);
53 /* basis for a color range for vcg */
54 static int n_colors = 0;
55 static int base_color = 0;
57 #define ERROR_TXT "<ERROR>"
60 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
61 * in the later case, sets bad
63 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
66 return get_mode_name(mode);
72 * returns the name of a type or <ERROR> if mode is NOT a mode object.
73 * in the later case, sets bad
75 static const char *get_type_name_ex(type *tp, int *bad)
78 return get_type_name(tp);
84 * prints the edge from a type S to a type T with additional info fmt, ...
87 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
92 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
93 fprintf(F, " targetname: "); PRINT_TYPEID(T);
100 * prints the edge from a type T to an entity E with additional info fmt, ...
103 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
108 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
109 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
110 vfprintf(F, fmt, ap);
116 * prints the edge from an entity E to an entity T with additional info fmt, ...
119 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
125 fprintf(F, "backedge: { sourcename: \"");
127 fprintf(F, "edge: { sourcename: \"");
129 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
130 vfprintf(F, fmt, ap);
136 * prints the edge from an entity E to a type T with additional info fmt, ...
139 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
144 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
145 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
146 vfprintf(F, fmt, ap);
152 * prints the edge from a node N to a type T with additional info fmt, ...
155 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
160 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
161 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
162 vfprintf(F, fmt, ap);
168 * prints the edge from a node N to an entity E with additional info fmt, ...
171 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
176 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
177 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
179 vfprintf(F, fmt, ap);
185 * prints the edge from an entity E to a node N with additional info fmt, ...
188 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
193 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
194 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
195 vfprintf(F, fmt, ap);
201 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
204 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
209 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
210 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
211 vfprintf(F, fmt, ap);
216 /*-----------------------------------------------------------------*/
217 /* global and ahead declarations */
218 /*-----------------------------------------------------------------*/
220 static void dump_whole_node(ir_node *n, void *env);
221 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
223 /*-----------------------------------------------------------------*/
224 /* Helper functions. */
225 /*-----------------------------------------------------------------*/
228 * This map is used as a private link attr to be able to call dumper
229 * anywhere without destroying link fields.
231 static pmap *irdump_link_map = NULL;
233 /** Creates the link attribut map. */
234 static void init_irdump(void) {
235 /* We need a new, empty map. */
236 if (irdump_link_map) pmap_destroy(irdump_link_map);
237 irdump_link_map = pmap_create();
241 * Returns the private link field.
243 static void *ird_get_irn_link(ir_node *n) {
245 if (!irdump_link_map) return NULL;
247 if (pmap_contains(irdump_link_map, (void *)n))
248 res = pmap_get(irdump_link_map, (void *)n);
253 * Sets the private link field.
255 static void ird_set_irn_link(ir_node *n, void *x) {
256 if (!irdump_link_map) init_irdump();
257 pmap_insert(irdump_link_map, (void *)n, x);
261 * Gets the private link field of an irg.
263 static void *ird_get_irg_link(ir_graph *irg) {
265 if (!irdump_link_map) return NULL;
267 if (pmap_contains(irdump_link_map, (void *)irg))
268 res = pmap_get(irdump_link_map, (void *)irg);
273 * Sets the private link field of an irg.
275 static void ird_set_irg_link(ir_graph *irg, void *x) {
276 if (!irdump_link_map) init_irdump();
277 pmap_insert(irdump_link_map, (void *)irg, x);
281 * Walker, clears tzhe private link field
283 static void clear_link(ir_node * node, void * env) {
284 ird_set_irn_link(node, NULL);
288 * Returns non-zero if a node is in floating state.
290 static int node_floats(ir_node *n) {
291 return ((get_irn_pinned(n) == op_pin_state_floats) &&
292 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
296 * If the entity has a ld_name, returns it, else returns the name of the entity.
298 static const char *get_ent_dump_name(entity *ent) {
300 return "<NULL entity>";
301 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
302 if (ent->ld_name) return get_id_str(ent->ld_name);
303 return get_id_str(ent->name);
306 /* Returns the name of an IRG. */
307 const char *get_irg_dump_name(ir_graph *irg) {
308 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
309 entity *ent = get_irg_entity(irg);
310 return get_ent_dump_name(ent);
314 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
316 static void collect_node(ir_node * node, void *env) {
319 || get_irn_op(node) == op_Bad
320 || get_irn_op(node) == op_Unknown
321 || get_irn_op(node) == op_NoMem) {
322 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
323 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
324 ARR_APP1(ir_node *, arr, node);
325 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
327 ir_node * block = get_nodes_block(node);
328 ird_set_irn_link(node, ird_get_irn_link(block));
329 ird_set_irn_link(block, node);
333 /** Construct lists to walk ir block-wise.
335 * Collects all blocks, nodes not op_pin_state_pinned,
336 * Bad, NoMem and Unknown into a flexible array in link field of
337 * irg they belong to. Sets the irg link field to NULL in all
338 * graphs not visited.
339 * Free the list with DEL_ARR_F().
341 static ir_node ** construct_block_lists(ir_graph *irg) {
342 int i, rem_view = get_interprocedural_view();
343 ir_graph *rem = current_ir_graph;
344 current_ir_graph = irg;
346 for (i = 0; i < get_irp_n_irgs(); i++)
347 ird_set_irg_link(get_irp_irg(i), NULL);
349 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
351 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
352 set_interprocedural_view(false);
353 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
354 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
355 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
356 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
357 set_interprocedural_view(rem_view);
359 current_ir_graph = rem;
360 return ird_get_irg_link(irg);
363 /*******************************************************************/
364 /* flags to steer output */
365 /*******************************************************************/
367 /** Dump only irgs with names start with this string */
368 const char *dump_file_filter = "";
370 /** A compiler option to turn off edge labels */
371 static int edge_label = 1;
372 /** A compiler option to turn off dumping values of constant entities */
373 static int const_entities = 1;
374 /** A compiler option to dump the keep alive edges */
375 static int dump_keepalive = 0;
376 /** Compiler options to dump analysis information in dump_ir_graph */
377 int dump_out_edge_flag = 0;
378 int dump_dominator_information_flag = 0;
379 int dump_loop_information_flag = 0;
380 int dump_backedge_information_flag = 1;
381 int dump_const_local = 0;
382 bool opt_dump_analysed_type_info = 1;
383 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
385 static const char *overrule_nodecolor = NULL;
387 /** The vcg attribute hook. */
388 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
391 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook)
393 dump_node_vcgattr_hook = hook;
396 INLINE bool get_opt_dump_const_local(void) {
397 if (!dump_out_edge_flag && !dump_loop_information_flag)
398 return dump_const_local;
403 void only_dump_method_with_name(ident *name) {
404 dump_file_filter = get_id_str(name);
408 /* To turn off display of edge labels. Edge labels offen cause xvcg to
409 abort with a segmentation fault. */
410 void turn_off_edge_labels(void) {
414 void dump_consts_local(bool b) {
415 dump_const_local = b;
418 void turn_off_constant_entity_values(void) {
422 void dump_keepalive_edges(bool b) {
426 bool get_opt_dump_keepalive_edges(void) {
427 return dump_keepalive;
430 void dump_out_edges(void) {
431 dump_out_edge_flag = 1;
434 void dump_dominator_information(void) {
435 dump_dominator_information_flag = 1;
438 void dump_loop_information(void) {
439 dump_loop_information_flag = 1;
442 void dont_dump_loop_information(void) {
443 dump_loop_information_flag = 0;
446 void dump_backedge_information(bool b) {
447 dump_backedge_information_flag = b;
450 /* Dump the information of type field specified in ana/irtypeinfo.h.
451 * If the flag is set, the type name is output in [] in the node label,
452 * else it is output as info.
454 void dump_analysed_type_info(bool b) {
455 opt_dump_analysed_type_info = b;
458 void dump_pointer_values_to_info(bool b) {
459 opt_dump_pointer_values_to_info = b;
462 /*-----------------------------------------------------------------*/
463 /* Routines to dump information about a single ir node. */
464 /*-----------------------------------------------------------------*/
467 * dump the name of a node n to the File F.
470 dump_node_opcode(FILE *F, ir_node *n)
474 switch(get_irn_opcode(n)) {
479 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
480 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
485 if (get_SymConst_kind(n) == symconst_addr_name) {
486 /* don't use get_SymConst_ptr_info as it mangles the name. */
487 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
488 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
489 assert(get_SymConst_entity(n));
490 assert(is_entity(get_SymConst_entity(n)));
491 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
493 assert(get_kind(get_SymConst_type(n)) == k_type);
494 assert(get_type_ident(get_SymConst_type(n)));
495 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
496 if (get_SymConst_kind(n) == symconst_type_tag)
504 if (!get_interprocedural_view())
511 ir_node *pred = get_Proj_pred(n);
513 if (get_irn_opcode(pred) == iro_Cond
514 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
515 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
516 fprintf (F, "defProj");
518 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
519 * fprintf (F, "Arg");
528 if (get_interprocedural_view()) {
529 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
534 case iro_CallBegin: {
535 ir_node *addr = get_CallBegin_ptr(n);
537 if (get_irn_op(addr) == op_Sel)
538 ent = get_Sel_entity(addr);
539 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
540 ent = get_SymConst_entity(addr);
541 fprintf (F, "%s", get_irn_opname(n));
542 if (ent) fprintf (F, " %s", get_entity_name(ent));
546 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
551 fprintf (F, "%s", get_irn_opname(n));
559 * Dump the mode of a node n to a file F.
560 * Ignore modes that are "always known".
563 dump_node_mode(FILE *F, ir_node *n)
566 opcode iro = get_irn_opcode(n);
579 ir_mode *mode = get_irn_mode(n);
581 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
582 (mode != mode_T || iro == iro_Proj))
583 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
591 * Dump the tpe of a node n to a file F if it's known.
593 static int dump_node_typeinfo(FILE *F, ir_node *n) {
596 if (opt_dump_analysed_type_info) {
597 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
598 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
599 type *tp = get_irn_typeinfo_type(n);
601 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
610 * Dump addinional node attributes of some nodes to a file F.
613 dump_node_nodeattr(FILE *F, ir_node *n)
617 switch (get_irn_opcode(n)) {
619 if (false && get_interprocedural_view()) {
620 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
624 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
625 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
627 fprintf (F, "%ld", get_Proj_proj(n));
631 fprintf (F, "%ld", get_Filter_proj(n));
634 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
637 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
640 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
651 * dumps the attributes of a node n into the file F.
652 * Currently this is only the color of a node.
654 static void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
657 fprintf(F, "color: red");
661 if (dump_node_vcgattr_hook)
662 if (dump_node_vcgattr_hook(F, n));
665 switch (get_irn_opcode(n)) {
672 fprintf (F, "color: blue");
675 fprintf (F, "color: lightyellow");
678 fprintf (F, "color: green");
684 fprintf (F, "color: yellow");
687 PRINT_DEFAULT_NODE_ATTR;
690 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
694 * Dump the node information of a node n to a file F.
696 static INLINE int dump_node_info(FILE *F, ir_node *n)
702 fprintf (F, " info1: \"");
703 if (opt_dump_pointer_values_to_info)
704 fprintf (F, "addr: %p \n", (void *)n);
705 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
706 fprintf (F, "visited: %ld \n", get_irn_visited(n));
707 irg = get_irn_irg(n);
708 if (irg != get_const_code_irg())
709 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
711 if (get_irn_pinned(n) == op_pin_state_floats &&
712 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
713 fprintf(F, "node was pinned in ");
714 dump_node_opcode(F, get_nodes_block(n));
715 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
719 /* show all predecessor nodes */
720 fprintf(F, "pred nodes: \n");
723 dump_node_opcode(F, get_nodes_block(n));
724 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
726 for ( i = 0; i < get_irn_arity(n); ++i) {
727 fprintf(F, " %d: ", i);
728 dump_node_opcode(F, get_irn_n(n, i));
729 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
733 fprintf(F, "arity: %d", get_irn_arity(n));
734 if ((get_irn_op(n) == op_Block) ||
735 (get_irn_op(n) == op_Phi) ||
736 ((get_irn_op(n) == op_Filter) && get_interprocedural_view())) {
737 fprintf(F, " backedges:");
739 for (i = 0; i < get_irn_arity(n); i++)
740 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
744 /* Loop node Someone else please tell me what's wrong ...
745 if (get_irn_loop(n)) {
746 ir_loop *loop = get_irn_loop(n);
748 fprintf(F, " in loop %d with depth %d\n",
749 get_loop_loop_nr(loop), get_loop_depth(loop));
754 switch (get_irn_opcode(n)) {
756 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
757 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
758 for (i = 0; i < get_method_n_params(tp); ++i)
759 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
760 if ((get_irp_ip_view_state() == ip_view_valid) && !get_interprocedural_view()) {
761 ir_node *sbl = get_nodes_block(n);
762 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
763 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
764 for (i = 0; i < n_cfgpreds; ++i) {
765 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
766 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
767 get_irg_dump_name(get_irn_irg(cfgpred)));
772 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
775 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
778 entity *ent = get_Sel_entity(n);
781 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
782 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
785 fprintf(F, "<NULL entity>\n");
790 type *tp = get_Call_type(n);
791 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
792 if(get_unknown_type() != tp) {
793 for (i = 0; i < get_method_n_params(tp); ++i)
794 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
795 for (i = 0; i < get_method_n_ress(tp); ++i)
796 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
798 if (Call_has_callees(n)) {
799 fprintf(F, "possible callees: \n");
800 for (i = 0; i < get_Call_n_callees(n); i++) {
801 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
805 case iro_CallBegin: {
806 ir_node *call = get_CallBegin_call(n);
807 fprintf(F, "Call: %ld\n", get_irn_node_nr(call));
808 if (Call_has_callees(call)) {
809 fprintf(F, "possible callees: \n");
810 for (i = 0; i < get_Call_n_callees(call); i++) {
811 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
816 if (!get_interprocedural_view()) {
817 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
818 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
819 for (i = 0; i < get_method_n_ress(tp); ++i)
820 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
824 type *tp = get_Const_type(n);
825 assert(tp != none_type);
826 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
829 switch(get_SymConst_kind(n)) {
830 case symconst_addr_name:
831 fprintf(F, "kind addr_name\n");
833 case symconst_addr_ent:
834 fprintf(F, "kind addr_ent\n");
835 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
837 case symconst_type_tag:
838 fprintf(F, "kind type_tag\n");
841 fprintf(F, "kind size\n");
844 fprintf(F, "SymConst of type %s \n", get_type_name_ex(get_SymConst_value_type(n), &bad));
848 if (get_interprocedural_view()) {
849 fprintf(F, "intra predecessor nodes:\n");
850 for (i = 0; i < get_irn_intra_arity(n); i++) {
851 ir_node *pred = get_irn_intra_n(n, i);
852 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
855 fprintf(F, "inter predecessor nodes:\n");
856 for (i = 0; i < get_irn_inter_arity(n); i++) {
857 ir_node *pred = get_irn_inter_n(n, i);
858 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
859 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
864 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
867 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
873 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
874 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
875 if (get_irn_typeinfo_type(n) != none_type)
876 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
884 * checks wheater a node is "constant-like", ie can be treated "block-less"
887 bool is_constlike_node(ir_node *n) {
888 ir_op *op = get_irn_op(n);
889 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
893 /** outputs the predecessors of n, that are constants, local. I.e.,
894 generates a copy of the constant predecessors for each node called with. */
895 static void dump_const_node_local(FILE *F, ir_node *n) {
897 if (!get_opt_dump_const_local()) return;
899 /* Use visited flag to avoid outputting nodes twice.
900 initialize it first. */
901 for (i = 0; i < get_irn_arity(n); i++) {
902 ir_node *con = get_irn_n(n, i);
903 if (is_constlike_node(con)) {
904 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
908 for (i = 0; i < get_irn_arity(n); i++) {
909 ir_node *con = get_irn_n(n, i);
910 if (is_constlike_node(con) && irn_not_visited(con)) {
913 mark_irn_visited(con);
914 /* Generate a new name for the node by appending the names of
916 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
917 fprintf(F, " label: \"");
918 bad |= dump_node_opcode(F, con);
919 bad |= dump_node_mode(F, con);
920 bad |= dump_node_typeinfo(F, con);
922 bad |= dump_node_nodeattr(F, con);
923 fprintf(F, " %ld", get_irn_node_nr(con));
925 bad |= dump_node_info(F, con);
926 dump_node_vcgattr(F, con, bad);
933 * prints the error message of a node to a file F as info2.
935 static void INLINE print_node_error(FILE *F, const char *err_msg)
940 fprintf (F, " info2: \"%s\"", err_msg);
946 static void dump_node(FILE *F, ir_node *n)
951 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
953 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
955 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
956 bad |= dump_node_opcode(F, n);
957 bad |= dump_node_mode(F, n);
958 bad |= dump_node_typeinfo(F, n);
960 bad |= dump_node_nodeattr(F, n);
961 fprintf(F, " %ld", get_irn_node_nr(n));
963 bad |= dump_node_info(F, n);
964 print_node_error(F, p);
965 dump_node_vcgattr(F, n, bad);
967 dump_const_node_local(F, n);
974 /** dump the edge to the block this node belongs to */
976 dump_ir_block_edge(FILE *F, ir_node *n) {
977 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
978 if (is_no_Block(n)) {
979 ir_node *block = get_nodes_block(n);
981 fprintf (F, "edge: { sourcename: \"");
983 fprintf (F, "\" targetname: ");
984 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
985 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
990 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
991 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
992 fprintf (F, INTRA_DATA_EDGE_ATTR);
994 fprintf (F, INTER_DATA_EDGE_ATTR);
998 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
999 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
1000 fprintf (F, INTRA_MEM_EDGE_ATTR);
1002 fprintf (F, INTER_MEM_EDGE_ATTR);
1006 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1009 if (dump_backedge_information_flag && is_backedge(from, to))
1010 fprintf (F, BACK_EDGE_ATTR);
1012 switch (get_irn_opcode(from)) {
1014 fprintf (F, CF_EDGE_ATTR);
1016 case iro_Start: break;
1019 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1020 fprintf (F, CF_EDGE_ATTR);
1021 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1022 fprintf (F, INTER_MEM_EDGE_ATTR);
1030 print_data_edge_vcgattr(F, from, to);
1035 print_mem_edge_vcgattr(F, from, to);
1037 print_data_edge_vcgattr(F, from, to);
1041 print_data_edge_vcgattr(F, from, to);
1046 print_mem_edge_vcgattr(F, from, to);
1048 print_data_edge_vcgattr(F, from, to);
1055 print_data_edge_vcgattr(F, from, to);
1062 print_mem_edge_vcgattr(F, from, to);
1064 print_data_edge_vcgattr(F, from, to);
1076 print_data_edge_vcgattr(F, from, to);
1079 if (get_irn_modecode(from) == irm_M)
1080 fprintf (F, INTER_MEM_EDGE_ATTR);
1082 print_data_edge_vcgattr(F, from, to);
1089 print_mem_edge_vcgattr(F, from, to);
1091 print_data_edge_vcgattr(F, from, to);
1094 print_mem_edge_vcgattr(F, from, to);
1096 case iro_Tuple: break;
1099 switch (get_irn_modecode(from)) {
1101 fprintf (F, CF_EDGE_ATTR);
1104 fprintf (F, INTER_MEM_EDGE_ATTR);
1107 print_data_edge_vcgattr(F, from, to);
1111 case iro_Bad: break;
1112 case iro_Unknown: break;
1114 switch (get_irn_modecode(from)) {
1116 fprintf (F, INTRA_MEM_EDGE_ATTR);
1119 fprintf (F, CF_EDGE_ATTR);
1122 print_data_edge_vcgattr(F, from, to);
1130 /* dump edges to our inputs */
1132 dump_ir_data_edges(FILE *F, ir_node *n) {
1133 int i, visited = get_irn_visited(n);
1135 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1138 for (i = 0; i < get_irn_arity(n); i++) {
1139 ir_node * pred = get_irn_n(n, i);
1142 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1143 continue; /* pred not dumped */
1145 if (dump_backedge_information_flag && is_backedge(n, i))
1146 fprintf (F, "backedge: {sourcename: \"");
1148 fprintf (F, "edge: {sourcename: \"");
1150 fprintf (F, "\" targetname: ");
1151 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1152 PRINT_CONSTID(n, pred);
1154 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1156 fprintf (F, " label: \"%d\" ", i);
1157 print_edge_vcgattr(F, n, i);
1162 /** Dumps a node and its edges but not the block edge
1165 dump_node_wo_blockedge (ir_node *n, void *env) {
1168 dump_ir_data_edges(F, n);
1171 /** Dumps a node and its edges.
1174 dump_whole_node (ir_node *n, void *env) {
1176 dump_node_wo_blockedge(n, env);
1177 if (!node_floats(n)) dump_ir_block_edge(F, n);
1181 dump_const_node(ir_node *n, void *env) {
1182 if (is_Block(n)) return;
1183 dump_node_wo_blockedge(n, env);
1186 /***********************************************************************/
1187 /* the following routines dump the nodes/irgs bracketed to graphs. */
1188 /***********************************************************************/
1190 /** Dumps a constant expression as entity initializer, array bound ...
1192 static void dump_const_expression(FILE *F, ir_node *value) {
1193 ir_graph *rem = current_ir_graph;
1194 int rem_dump_const_local = dump_const_local;
1195 dump_const_local = 0;
1196 current_ir_graph = get_const_code_irg();
1197 irg_walk(value, dump_const_node, NULL, F);
1198 /* Decrease visited flag so that we walk with the same flag for the next
1199 expresssion. This guarantees that we don't dump the same node twice,
1200 as for const expressions cse is performed to save memory. */
1201 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1202 current_ir_graph = rem;
1203 dump_const_local = rem_dump_const_local;
1206 /** Dump a block as graph containing its nodes.
1208 * Expects to find nodes belonging to the block as list in its
1210 * Dumps the edges of all nodes including itself. */
1212 dump_whole_block(FILE *F, ir_node *block) {
1214 assert(is_Block(block));
1216 fprintf(F, "graph: { title: \"");
1217 PRINT_NODEID(block);
1218 fprintf(F, "\" label: \"");
1219 dump_node_opcode(F, block);
1220 fprintf (F, " %ld", get_irn_node_nr(block));
1222 if (get_opt_dump_abstvals())
1223 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1225 fprintf(F, "\" status:clustered color:%s \n",
1226 get_Block_matured(block) ? "yellow" : "red");
1228 /* dump the blocks edges */
1229 dump_ir_data_edges(F, block);
1231 /* dump the nodes that go into the block */
1232 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1234 dump_ir_data_edges(F, node);
1237 /* Close the vcg information for the block */
1239 dump_const_node_local(F, block);
1241 dump_chi_term(F, block);
1246 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1247 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1249 dump_block_graph(FILE *F, ir_graph *irg) {
1251 ir_graph *rem = current_ir_graph;
1252 ir_node **arr = ird_get_irg_link(irg);
1253 current_ir_graph = irg;
1255 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1256 ir_node * node = arr[i];
1257 if (is_Block(node)) {
1258 /* Dumps the block and all the nodes in the block, which are to
1259 be found in Block->link. */
1260 dump_whole_block(F, node);
1262 /* Nodes that are not in a Block. */
1264 dump_ir_data_edges(F, node);
1268 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1269 dump_loop_nodes_into_graph(F, irg);
1271 current_ir_graph = rem;
1274 /** Dumps an irg as a graph.
1275 * If interprocedural view edges can point to nodes out of this graph.
1277 static void dump_graph(FILE *F, ir_graph *irg) {
1279 fprintf(F, "graph: { title: \"");
1281 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1282 get_ent_dump_name(get_irg_entity(irg)));
1284 dump_block_graph(F, irg);
1286 /* Close the vcg information for the irg */
1287 fprintf(F, "}\n\n");
1290 /*******************************************************************/
1291 /* Basic type and entity nodes and edges. */
1292 /*******************************************************************/
1294 /** dumps the edges between nodes and their type or entity attributes. */
1295 static void dump_node2type_edges(ir_node *n, void *env)
1300 switch (get_irn_opcode(n)) {
1302 /* @@@ some consts have an entity */
1305 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1306 || (get_SymConst_kind(n) ==symconst_size))
1308 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1312 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1315 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1318 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1321 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1324 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1332 static int print_type_info(FILE *F, type *tp) {
1335 if (get_type_state(tp) == layout_undefined) {
1336 fprintf(F, "state: layout_undefined\n");
1338 fprintf(F, "state: layout_fixed,\n");
1340 if (get_type_mode(tp))
1341 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1342 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1347 static void print_typespecific_info(FILE *F, type *tp) {
1348 switch (get_type_tpop_code(tp)) {
1351 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1358 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1359 fprintf(F, "params: %d\n", get_method_n_params(tp));
1360 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1368 case tpo_enumeration:
1382 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1383 switch (get_type_tpop_code(tp)) {
1386 if (peculiarity_existent == get_class_peculiarity(tp))
1387 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1389 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1393 fprintf (F, " " TYPE_METH_NODE_ATTR);
1404 case tpo_enumeration:
1417 static int print_type_node(FILE *F, type *tp)
1421 fprintf (F, "node: {title: ");
1423 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1424 fprintf (F, " info1: \"");
1425 bad |= print_type_info(F, tp);
1426 print_typespecific_info(F, tp);
1428 print_typespecific_vcgattr(F, tp);
1434 #define X(a) case a: fprintf(F, #a); break
1435 void dump_entity_node(FILE *F, entity *ent, int color)
1437 fprintf (F, "node: {title: \"");
1438 PRINT_ENTID(ent); fprintf(F, "\"");
1439 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1440 fprintf (F, "label: ");
1441 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1443 fprintf(F, "color: %d", color);
1445 fprintf (F, ENTITY_NODE_ATTR);
1446 fprintf (F, "\n info1: \"");
1448 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1450 fprintf(F, "\"\n}\n");
1454 static void dump_enum_item(FILE *F, type *tp, int pos)
1457 ident *id = get_enumeration_nameid(tp, pos);
1458 tarval *tv = get_enumeration_enum(tp, pos);
1460 tarval_snprintf(buf, sizeof(buf), tv);
1461 fprintf (F, "node: {title: \"");
1462 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1463 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1464 fprintf (F, "label: ");
1465 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1466 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1469 /* dumps a type or entity and it's edges. */
1471 dump_type_info(type_or_ent *tore, void *env) {
1473 int i = 0; /* to shutup gcc */
1475 /* dump this type or entity */
1477 switch (get_kind(tore)) {
1480 entity *ent = (entity *)tore;
1483 dump_entity_node(F, ent, 0);
1485 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1486 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1487 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1488 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1489 if(is_class_type(get_entity_owner(ent))) {
1490 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1491 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1493 /* attached subgraphs */
1494 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1495 if (is_atomic_entity(ent)) {
1496 value = get_atomic_ent_value(ent);
1498 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1499 /* DDMN(value); $$$ */
1500 dump_const_expression(F, value);
1503 if (is_compound_entity(ent)) {
1504 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1505 value = get_compound_ent_value(ent, i);
1507 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1508 dump_const_expression(F, value);
1509 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1511 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1512 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1513 get_compound_ent_value_member(ent, i), i);
1522 type *tp = (type *)tore;
1523 print_type_node(F, tp);
1524 /* and now the edges */
1525 switch (get_type_tpop_code(tp)) {
1528 for (i=0; i < get_class_n_supertypes(tp); i++)
1529 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1530 for (i=0; i < get_class_n_members(tp); i++)
1531 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1535 for (i=0; i < get_struct_n_members(tp); i++)
1536 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1540 for (i = 0; i < get_method_n_params(tp); i++)
1541 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1542 for (i = 0; i < get_method_n_ress(tp); i++)
1543 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1547 for (i = 0; i < get_union_n_members(tp); i++)
1548 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1552 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1553 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1554 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1555 ir_node *upper = get_array_upper_bound(tp, i);
1556 ir_node *lower = get_array_lower_bound(tp, i);
1557 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1558 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1559 dump_const_expression(F, upper);
1560 dump_const_expression(F, lower);
1564 case tpo_enumeration:
1566 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1567 dump_enum_item(F, tp, i);
1568 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1573 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1581 break; /* case k_type */
1584 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1586 } /* switch kind_or_entity */
1589 typedef struct _h_env {
1594 /** For dumping class hierarchies.
1595 * Dumps a class type node and a superclass edge.
1596 * If env->dump_ent dumps entities of classes and overwrites edges.
1599 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1602 int i = 0; /* to shutup gcc */
1604 /* dump this type or entity */
1605 switch (get_kind(tore)) {
1607 entity *ent = (entity *)tore;
1608 if (get_entity_owner(ent) == get_glob_type()) break;
1609 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1610 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1612 dump_entity_node(F, ent, 0);
1614 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1615 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1616 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1618 } break; /* case k_entity */
1621 type *tp = (type *)tore;
1622 if (tp == get_glob_type()) break;
1623 switch (get_type_tpop_code(tp)) {
1625 print_type_node(F, tp);
1626 /* and now the edges */
1627 for (i=0; i < get_class_n_supertypes(tp); i++)
1629 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1635 break; /* case k_type */
1638 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1640 } /* switch kind_or_entity */
1643 /*******************************************************************/
1644 /* dump analysis information that is expressed in graph terms. */
1645 /*******************************************************************/
1647 /* dump out edges */
1649 dump_out_edge(ir_node *n, void *env) {
1652 for (i = 0; i < get_irn_n_outs(n); i++) {
1653 assert(get_irn_out(n, i));
1654 fprintf (F, "edge: {sourcename: \"");
1656 fprintf (F, "\" targetname: \"");
1657 PRINT_NODEID(get_irn_out(n, i));
1658 fprintf (F, "\" color: red linestyle: dashed");
1664 dump_loop_label(FILE *F, ir_loop *loop) {
1665 fprintf (F, "loop %d, %d sons, %d nodes",
1666 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1669 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1670 fprintf (F, " info1: \"");
1671 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1672 #if DEBUG_libfirm /* GL @@@ debug analyses */
1673 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1679 dump_loop_node(FILE *F, ir_loop *loop) {
1680 fprintf (F, "node: {title: \"");
1682 fprintf (F, "\" label: \"");
1683 dump_loop_label(F, loop);
1685 dump_loop_info(F, loop);
1691 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1693 fprintf (F, "edge: {sourcename: \"");
1695 fprintf (F, "\" targetname: \"");
1696 PRINT_NODEID(get_loop_node(loop, i));
1697 fprintf (F, "\" color: green");
1702 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1704 fprintf (F, "edge: {sourcename: \"");
1706 fprintf (F, "\" targetname: \"");
1707 PRINT_LOOPID(get_loop_son(loop, i));
1708 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1709 get_loop_element_pos(loop, get_loop_son(loop, i)));
1713 void dump_loops(FILE *F, ir_loop *loop) {
1715 /* dump this loop node */
1716 dump_loop_node(F, loop);
1718 /* dump edges to nodes in loop -- only if it is a real loop */
1719 if (get_loop_depth(loop) != 0) {
1720 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1721 dump_loop_node_edge(F, loop, i);
1724 for (i = 0; i < get_loop_n_sons(loop); i++) {
1725 dump_loops(F, get_loop_son(loop, i));
1726 dump_loop_son_edge(F, loop, i);
1731 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1732 ir_graph *rem = current_ir_graph;
1733 current_ir_graph = irg;
1735 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1737 current_ir_graph = rem;
1742 * dumps the VCG header
1744 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1753 if (!orientation) orientation = "bottom_to_top";
1757 "graph: { title: \"ir graph of %s\"\n"
1758 "display_edge_labels: %s\n"
1759 "layoutalgorithm: mindepth\n"
1760 "manhattan_edges: yes\n"
1761 "port_sharing: no\n"
1763 "classname 1: \"intrablock Data\"\n"
1764 "classname 16: \"interblock Data\"\n"
1765 "classname 2: \"Block\"\n"
1766 "classname 13: \"Control Flow\"\n"
1767 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1768 "classname 14: \"intrablock Memory\"\n"
1769 "classname 17: \"interblock Memory\"\n"
1770 "classname 15: \"Dominators\"\n"
1771 "classname 3: \"Entity type\"\n"
1772 "classname 4: \"Entity owner\"\n"
1773 "classname 5: \"Method Param\"\n"
1774 "classname 6: \"Method Res\"\n"
1775 "classname 7: \"Super\"\n"
1776 "classname 8: \"Union\"\n"
1777 "classname 9: \"Points-to\"\n"
1778 "classname 10: \"Array Element Type\"\n"
1779 "classname 11: \"Overwrites\"\n"
1780 "classname 12: \"Member\"\n"
1781 "infoname 1: \"Attribute\"\n"
1782 "infoname 2: \"Verification errors\"\n",
1783 name, label, orientation);
1785 /* don't use all, the range is too whith/black. */
1789 "colorentry 100: 0 0 0\n"
1790 "colorentry 101: 20 0 0\n"
1791 "colorentry 102: 40 0 0\n"
1792 "colorentry 103: 60 0 0\n"
1793 "colorentry 104: 80 0 0\n"
1794 "colorentry 105: 100 0 0\n"
1795 "colorentry 106: 120 0 0\n"
1796 "colorentry 107: 140 0 0\n"
1797 "colorentry 108: 150 0 0\n"
1798 "colorentry 109: 180 0 0\n"
1799 "colorentry 110: 200 0 0\n"
1800 "colorentry 111: 220 0 0\n"
1801 "colorentry 112: 240 0 0\n"
1802 "colorentry 113: 255 0 0\n"
1803 "colorentry 113: 255 20 20\n"
1804 "colorentry 114: 255 40 40\n"
1805 "colorentry 115: 255 60 60\n"
1806 "colorentry 116: 255 80 80\n"
1807 "colorentry 117: 255 100 100\n"
1808 "colorentry 118: 255 120 120\n"
1809 "colorentry 119: 255 140 140\n"
1810 "colorentry 120: 255 150 150\n"
1811 "colorentry 121: 255 180 180\n"
1812 "colorentry 122: 255 200 200\n"
1813 "colorentry 123: 255 220 220\n"
1814 "colorentry 124: 255 240 240\n"
1815 "colorentry 125: 255 250 250\n"
1818 fprintf (F, "\n"); /* a separator */
1824 * @param irg The graph to be dumped
1825 * @param suffix1 first filename suffix
1826 * @param suffix2 second filename suffix
1828 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1830 const char *nm = get_irg_dump_name(irg);
1831 int len = strlen(nm), i, j;
1832 char *fname; /* filename to put the vcg information in */
1834 if (!suffix1) suffix1 = "";
1835 if (!suffix2) suffix2 = "";
1837 /* open file for vcg graph */
1838 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1840 /* strncpy (fname, nm, len); */ /* copy the filename */
1842 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1844 fname[j] = '@'; j++; fname[j] = '1'; j++;
1845 } else if (nm[i] == '@') {
1846 fname[j] = '@'; j++; fname[j] = '2'; j++;
1848 fname[j] = nm[i]; j++;
1852 strcat (fname, suffix1); /* append file suffix */
1853 strcat (fname, suffix2); /* append file suffix */
1854 strcat (fname, ".vcg"); /* append the .vcg suffix */
1855 F = fopen (fname, "w"); /* open file for writing */
1857 panic("cannot open %s for writing (%m)", fname); /* not reached */
1867 * @param irg The graph to be dumped
1868 * @param suffix filename suffix
1870 static FILE *vcg_open_name (const char *name, const char *suffix) {
1872 char *fname; /* filename to put the vcg information in */
1873 int i, j, len = strlen(name);
1875 if (!suffix) suffix = "";
1877 /** open file for vcg graph */
1878 fname = malloc (len * 2 + 5 + strlen(suffix));
1879 /* strcpy (fname, name);*/ /* copy the filename */
1881 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1882 if (name[i] == '/') {
1883 fname[j] = '@'; j++; fname[j] = '1'; j++;
1884 } else if (name[i] == '@') {
1885 fname[j] = '@'; j++; fname[j] = '2'; j++;
1887 fname[j] = name[i]; j++;
1891 strcat (fname, suffix);
1892 strcat (fname, ".vcg"); /* append the .vcg suffix */
1893 F = fopen (fname, "w"); /* open file for writing */
1895 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1903 * Dumps the vcg file footer
1905 static INLINE void dump_vcg_footer (FILE *F) {
1910 * close the vcg file
1912 void vcg_close (FILE *F) {
1913 dump_vcg_footer(F); /* print footer */
1914 fclose (F); /* close vcg file */
1917 /************************************************************************/
1918 /************************************************************************/
1919 /* Routines that dump all or parts of the firm representation to a file */
1920 /************************************************************************/
1921 /************************************************************************/
1923 /************************************************************************/
1924 /* Dump ir graphs, differnt formats and additional information. */
1925 /************************************************************************/
1927 /** Routine to dump a graph, blocks as conventional nodes.
1930 dump_ir_graph (ir_graph *irg, const char *suffix )
1935 rem = current_ir_graph;
1937 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1938 current_ir_graph = irg;
1939 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1940 else suffix1 = "-pure";
1941 f = vcg_open(irg, suffix, suffix1);
1942 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1944 /* walk over the graph */
1945 /* dump_whole_node must be called in post visiting predecessors */
1946 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1948 /* dump the out edges in a separate walk */
1949 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1950 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1955 current_ir_graph = rem;
1960 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1966 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1969 if (get_interprocedural_view()) suffix1 = "-ip";
1971 f = vcg_open(irg, suffix, suffix1);
1972 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1974 construct_block_lists(irg);
1976 for (i = 0; i < get_irp_n_irgs(); i++) {
1977 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1979 dump_graph(f, get_irp_irg(i));
1987 /** dumps a graph with type information
1990 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1993 ir_graph *rem = current_ir_graph;
1996 /* if a filter is set, dump only the irg's that match the filter */
1997 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2000 current_ir_graph = irg;
2002 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2003 else suffix1 = "-pure-wtypes";
2004 f = vcg_open(irg,suffix, suffix1);
2005 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2007 /* dump common ir graph */
2008 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2009 /* dump type info */
2010 type_walk_irg(irg, dump_type_info, NULL, f);
2011 inc_irg_visited(get_const_code_irg());
2012 /* dump edges from graph to type info */
2013 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2016 current_ir_graph = rem;
2020 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2025 ir_graph *rem = current_ir_graph;
2027 /* if a filter is set, dump only the irg's that match the filter */
2028 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2031 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2032 else suffix1 = "-wtypes";
2033 f = vcg_open(irg, suffix, suffix1);
2034 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2036 /* dump common blocked ir graph */
2037 construct_block_lists(irg);
2039 for (i = 0; i < get_irp_n_irgs(); i++) {
2040 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2042 dump_graph(f, get_irp_irg(i));
2047 /* dump type info */
2048 current_ir_graph = irg;
2049 type_walk_irg(irg, dump_type_info, NULL, f);
2050 inc_irg_visited(get_const_code_irg());
2052 /* dump edges from graph to type info */
2053 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2055 current_ir_graph = rem;
2059 /*---------------------------------------------------------------------*/
2060 /* The following routines dump a control flow graph. */
2061 /*---------------------------------------------------------------------*/
2064 dump_block_to_cfg(ir_node *block, void *env) {
2069 if (is_Block(block)) {
2070 /* This is a block. Dump a node for the block. */
2071 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2072 fprintf (F, "\" label: \"");
2073 if (block == get_irg_start_block(get_irn_irg(block)))
2074 fprintf(F, "Start ");
2075 if (block == get_irg_end_block(get_irn_irg(block)))
2078 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2079 PRINT_NODEID(block);
2081 fprintf(F, "info1:\"");
2082 if (dump_dominator_information_flag)
2083 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2085 /* show arity and possible Bad predecessors of the block */
2086 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2087 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2088 ir_node *pred = get_Block_cfgpred(block, i);
2091 fprintf(F, "Bad pred at pos: ");
2092 fprintf(F, "%d ", i);
2099 fprintf (F, "\""); /* closing quote of info */
2101 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2102 (block == get_irg_end_block(get_irn_irg(block))) )
2103 fprintf(F, " color:blue ");
2105 fprintf(F, " color:yellow ");
2108 /* Dump the edges */
2109 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2110 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2111 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2112 fprintf (F, "edge: { sourcename: \"");
2113 PRINT_NODEID(block);
2114 fprintf (F, "\" targetname: \"");
2116 fprintf (F, "\"}\n");
2119 /* Dump dominator edge */
2120 if (dump_dominator_information_flag && get_Block_idom(block)) {
2121 pred = get_Block_idom(block);
2122 fprintf (F, "edge: { sourcename: \"");
2123 PRINT_NODEID(block);
2124 fprintf (F, "\" targetname: \"");
2126 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2132 dump_cfg (ir_graph *irg, const char *suffix)
2135 ir_graph *rem = current_ir_graph;
2136 int ddif = dump_dominator_information_flag;
2137 int ipv = get_interprocedural_view();
2139 /* if a filter is set, dump only the irg's that match the filter */
2140 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2143 current_ir_graph = irg;
2145 f = vcg_open(irg, suffix, "-cfg");
2146 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2149 printf("Warning: dumping cfg not in interprocedural view!\n");
2150 set_interprocedural_view(false);
2153 if (get_irg_dom_state(irg) != dom_consistent)
2154 dump_dominator_information_flag = 0;
2156 /* walk over the blocks in the graph */
2157 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2158 dump_node(f, get_irg_bad(irg));
2160 dump_dominator_information_flag = ddif;
2161 set_interprocedural_view(ipv);
2163 current_ir_graph = rem;
2166 static int weight_overall(int rec, int loop) {
2167 return 2*rec + loop;
2170 static int compute_color (int my, int max) {
2175 /* if small, scale to the full color range. */
2177 my = my * (n_colors/max);
2179 int step = 1 + (max / n_colors);
2183 return base_color + n_colors - color;
2186 static int get_entity_color(entity *ent) {
2187 assert(get_entity_irg(ent));
2188 ir_graph *irg = get_entity_irg(ent);
2190 int rec_depth = get_irg_recursion_depth(irg);
2191 int loop_depth = get_irg_loop_depth(irg);
2192 int overall_depth = weight_overall(rec_depth, loop_depth);
2194 int max_rec_depth = irp->max_callgraph_recursion_depth;
2195 int max_loop_depth = irp->max_callgraph_loop_depth;
2196 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2198 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2199 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2200 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2202 return my_overall_color;
2205 void dump_callgraph(const char *suffix) {
2207 int i, n_irgs = get_irp_n_irgs();
2208 int rem = edge_label;
2210 //ident *prefix = new_id_from_str("java/");
2212 F = vcg_open_name("Callgraph", suffix);
2213 dump_vcg_header(F, "Callgraph", NULL);
2215 for (i = 0; i < n_irgs; ++i) {
2216 ir_graph *irg = get_irp_irg(i);
2217 entity *ent = get_irg_entity(irg);
2218 int j, n_callees = get_irg_n_callees(irg);
2220 /* Do not dump runtime system. */
2221 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2223 dump_entity_node(F, ent, get_entity_color(ent));
2224 for (j = 0; j < n_callees; ++j) {
2225 entity *c = get_irg_entity(get_irg_callee(irg, j));
2226 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2227 int be = is_irg_callee_backedge(irg, j);
2230 "label:\"recursion %d\" color: %d" :
2231 "label:\"calls %d\" color: %d";
2232 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2240 /* Dump all irgs in interprocedural view to a single file. */
2241 void dump_all_cg_block_graph(const char *suffix) {
2244 int rem_view = get_interprocedural_view();
2245 set_interprocedural_view(true);
2247 f = vcg_open_name("All_graphs", suffix);
2248 dump_vcg_header(f, "All_graphs", NULL);
2250 /* collect nodes in all irgs reachable in call graph*/
2251 for (i = 0; i < get_irp_n_irgs(); i++)
2252 ird_set_irg_link(get_irp_irg(i), NULL);
2254 cg_walk(clear_link, collect_node, NULL);
2256 /* dump all graphs */
2257 for (i = 0; i < get_irp_n_irgs(); i++) {
2258 current_ir_graph = get_irp_irg(i);
2259 assert(ird_get_irg_link(current_ir_graph));
2260 dump_graph(f, current_ir_graph);
2261 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2265 set_interprocedural_view(rem_view);
2268 /*---------------------------------------------------------------------*/
2269 /* the following routines dumps type information without any ir nodes. */
2270 /*---------------------------------------------------------------------*/
2273 dump_type_graph (ir_graph *irg, const char *suffix)
2277 rem = current_ir_graph;
2279 /* if a filter is set, dump only the irg's that match the filter */
2280 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2282 current_ir_graph = irg;
2284 f = vcg_open(irg, suffix, "-type");
2285 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2287 /* walk over the blocks in the graph */
2288 type_walk_irg(irg, dump_type_info, NULL, f);
2289 /* The walker for the const code can be called several times for the
2290 same (sub) experssion. So that no nodes are dumped several times
2291 we decrease the visited flag of the corresponding graph after each
2292 walk. So now increase it finally. */
2293 inc_irg_visited(get_const_code_irg());
2296 current_ir_graph = rem;
2300 dump_all_types (const char *suffix)
2302 FILE *f = vcg_open_name("All_types", suffix);
2303 dump_vcg_header(f, "All_types", NULL);
2304 type_walk(dump_type_info, NULL, f);
2305 inc_irg_visited(get_const_code_irg());
2310 dump_class_hierarchy (bool entities, const char *suffix)
2312 FILE *f = vcg_open_name("class_hierarchy", suffix);
2316 dump_vcg_header(f, "class_hierarchy", NULL);
2321 type_walk(dump_class_hierarchy_node, NULL, &env);
2325 /*---------------------------------------------------------------------*/
2326 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2328 /* dump_ir_block_graph */
2330 /* dump_type_graph */
2331 /* dump_ir_graph_w_types */
2332 /*---------------------------------------------------------------------*/
2334 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2335 int i, n_irgs = get_irp_n_irgs();
2336 for (i = 0; i < n_irgs; ++i) {
2337 dmp_grph(get_irp_irg(i), suffix);
2342 /*--------------------------------------------------------------------------------*
2343 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2344 * packed together in one subgraph/box *
2345 *--------------------------------------------------------------------------------*/
2347 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2348 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2350 ir_loop *son = NULL;
2352 /* Dump a new loop node. */
2353 dump_loop_node(F, loop);
2355 /* Dump the loop elements. */
2357 for(i = 0; i < get_loop_n_elements(loop); i++) {
2358 le = get_loop_element(loop, i);
2360 if (get_kind(son) == k_ir_loop) {
2362 /* We are a loop son -> Recurse */
2364 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2365 fprintf(F, "\" }\n");
2366 fprintf (F, "edge: {sourcename: \"");
2368 fprintf (F, "\" targetname: \"");
2370 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2371 loop_node_started = 0;
2373 dump_loop_son_edge(F, loop, son_number++);
2374 dump_loops_standalone(F, son);
2375 } else if (get_kind(son) == k_ir_node) {
2376 /* We are a loop node -> Collect firm nodes */
2378 ir_node *n = le.node;
2381 if (!loop_node_started) {
2382 /* Start a new node which contains all firm nodes of the current loop */
2383 fprintf (F, "node: { title: \"");
2385 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2386 loop_node_started = 1;
2392 bad |= dump_node_opcode(F, n);
2393 bad |= dump_node_mode(F, n);
2394 bad |= dump_node_typeinfo(F, n);
2396 bad |= dump_node_nodeattr(F, n);
2397 fprintf (F, " %ld", get_irn_node_nr(n));
2398 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2399 if (has_backedges(n)) fprintf(F, "\t loop head!");
2400 } else { /* for callgraph loop tree */
2401 assert(get_kind(son) == k_ir_graph);
2402 /* We are a loop node -> Collect firm graphs */
2403 ir_graph *n = (ir_graph *)le.node;
2404 if (!loop_node_started) {
2405 /* Start a new node which contains all firm nodes of the current loop */
2406 fprintf (F, "node: { title: \"");
2408 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2409 loop_node_started = 1;
2414 fprintf (F, " %s", get_irg_dump_name(n));
2415 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2419 if (loop_node_started) {
2420 fprintf(F, "\" }\n");
2421 fprintf (F, "edge: {sourcename: \"");
2423 fprintf (F, "\" targetname: \"");
2425 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2426 loop_node_started = 0;
2430 void dump_loop_tree(ir_graph *irg, const char *suffix)
2433 ir_graph *rem = current_ir_graph;
2434 int el_rem = edge_label;
2437 /* if a filter is set, dump only the irg's that match the filter */
2438 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2441 current_ir_graph = irg;
2443 f = vcg_open(irg, suffix, "-looptree");
2444 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2446 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2450 edge_label = el_rem;
2451 current_ir_graph = rem;
2454 void dump_callgraph_loop_tree(const char *suffix) {
2456 F = vcg_open_name("Callgraph_looptree", suffix);
2457 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2458 dump_loops_standalone(F, irp->outermost_cg_loop);
2463 /*-----------------------------------------------------------------------------*/
2464 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2465 /*-----------------------------------------------------------------------------*/
2467 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2468 int i, son_number = 0, node_number = 0;
2470 if (dump_loop_information_flag) dump_loop_node(F, loop);
2472 for (i = 0; i < get_loop_n_elements(loop); i++) {
2473 loop_element le = get_loop_element(loop, i);
2474 if (*(le.kind) == k_ir_loop) {
2475 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2477 collect_nodeloop(F, le.son, loopnodes);
2479 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2480 eset_insert(loopnodes, le.node);
2485 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2488 for(i = 0; i < get_loop_n_elements(loop); i++) {
2489 loop_element le = get_loop_element(loop, i);
2490 if (*(le.kind) == k_ir_loop) {
2492 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2494 if (is_Block(le.node)) start = 0; else start = -1;
2495 for (j = start; j < get_irn_arity(le.node); j++) {
2496 ir_node *pred = get_irn_n(le.node, j);
2497 if (!eset_contains(loopnodes, pred)) {
2498 eset_insert(extnodes, pred);
2499 if (!is_Block(pred)) {
2500 pred = get_nodes_block(pred);
2501 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2509 void dump_loop(ir_loop *l, const char *suffix) {
2512 eset *loopnodes = eset_create();
2513 eset *extnodes = eset_create();
2516 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2517 F = vcg_open_name (name, suffix);
2518 dump_vcg_header(F, name, NULL);
2520 /* collect all nodes to dump */
2521 collect_nodeloop(F, l, loopnodes);
2522 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2524 /* build block lists */
2525 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2526 set_irn_link(n, NULL);
2527 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2528 set_irn_link(n, NULL);
2529 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2531 b = get_nodes_block(n);
2532 set_irn_link(n, get_irn_link(b));
2535 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2537 b = get_nodes_block(n);
2538 set_irn_link(n, get_irn_link(b));
2542 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2544 fprintf(F, "graph: { title: \"");
2546 fprintf(F, "\" label: \"");
2547 dump_node_opcode(F, b);
2548 fprintf (F, " %ld", get_irn_node_nr(b));
2549 fprintf(F, "\" status:clustered color:yellow\n");
2551 /* dump the blocks edges */
2552 dump_ir_data_edges(F, b);
2554 /* dump the nodes that go into the block */
2555 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2556 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2558 overrule_nodecolor = NULL;
2559 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2562 /* Close the vcg information for the block */
2564 dump_const_node_local(F, b);
2567 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2569 fprintf(F, "graph: { title: \"");
2571 fprintf(F, "\" label: \"");
2572 dump_node_opcode(F, b);
2573 fprintf (F, " %ld", get_irn_node_nr(b));
2574 fprintf(F, "\" status:clustered color:lightblue\n");
2576 /* dump the nodes that go into the block */
2577 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2578 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2580 overrule_nodecolor = NULL;
2581 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2584 /* Close the vcg information for the block */
2586 dump_const_node_local(F, b);
2590 eset_destroy(loopnodes);
2591 eset_destroy(extnodes);