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 /* Attributes of nodes */
53 #define PRINT_DEFAULT_NODE_ATTR
54 #define DEFAULT_NODE_ATTR " "
55 #define DEFAULT_TYPE_ATTRIBUTE " "
56 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
58 /* Attributes of edges between Firm nodes */
59 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
60 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
61 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
62 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
63 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
64 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
65 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
67 #define BACK_EDGE_ATTR "linestyle:dashed "
69 /* Attributes of edges between Firm nodes and type/entity nodes */
70 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
72 /* Attributes of edges in type/entity graphs. */
73 #define TYPE_METH_NODE_ATTR "color: lightyellow"
74 #define TYPE_CLASS_NODE_ATTR "color: green"
75 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
76 #define ENTITY_NODE_ATTR "color: yellow"
77 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
78 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
79 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
80 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
81 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
82 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
83 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
84 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
85 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
86 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
87 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
88 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
89 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
90 #define ENUM_ITEM_NODE_ATTR "color: green"
91 #define CALLGRAPH_EDGE_ATTR "calls"
93 #if DEBUG_libfirm && NODEID_AS_LABEL
94 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
95 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
96 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
97 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
98 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
99 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
100 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
103 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
104 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
105 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
106 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
107 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
108 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
109 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
113 /* basis for a color range for vcg */
114 static int n_colors = 0;
115 static int base_color = 0;
117 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
120 return get_mode_name(mode);
125 static const char *get_type_name_ex(type *tp, int *bad)
128 return get_type_name(tp);
133 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
138 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
139 fprintf(F, " targetname: "); PRINT_TYPEID(T);
140 vfprintf(F, fmt, ap);
145 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
150 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
151 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
152 vfprintf(F, fmt, ap);
157 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
163 fprintf(F, "backedge: { sourcename: \"");
165 fprintf(F, "edge: { sourcename: \"");
167 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
168 vfprintf(F, fmt, ap);
173 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
178 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
179 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
180 vfprintf(F, fmt, ap);
185 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
190 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
191 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
192 vfprintf(F, fmt, ap);
197 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
202 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
203 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
205 vfprintf(F, fmt, ap);
210 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
215 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
216 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
217 vfprintf(F, fmt, ap);
222 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
227 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
228 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
229 vfprintf(F, fmt, ap);
234 /*******************************************************************/
235 /* global and ahead declarations */
236 /*******************************************************************/
238 static void dump_whole_node(ir_node *n, void *env);
239 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
241 /*******************************************************************/
242 /* Helper functions. */
243 /*******************************************************************/
245 /* Use private link attr to be able to call dumper anywhere without
246 destroying link fields. */
248 static pmap *irdump_link_map = NULL;
250 static void init_irdump(void) {
251 /* We need a new, empty map. */
252 if (irdump_link_map) pmap_destroy(irdump_link_map);
253 irdump_link_map = pmap_create();
257 void *ird_get_irn_link(ir_node *n) {
259 if (!irdump_link_map) return NULL;
261 if (pmap_contains(irdump_link_map, (void *)n))
262 res = pmap_get(irdump_link_map, (void *)n);
266 void ird_set_irn_link(ir_node *n, void *x) {
267 if (!irdump_link_map) init_irdump();
268 pmap_insert(irdump_link_map, (void *)n, x);
271 void *ird_get_irg_link(ir_graph *irg) {
273 if (!irdump_link_map) return NULL;
275 if (pmap_contains(irdump_link_map, (void *)irg))
276 res = pmap_get(irdump_link_map, (void *)irg);
280 void ird_set_irg_link(ir_graph *irg, void *x) {
281 if (!irdump_link_map) init_irdump();
282 pmap_insert(irdump_link_map, (void *)irg, x);
285 static void clear_link(ir_node * node, void * env) {
286 ird_set_irn_link(node, NULL);
290 static int node_floats(ir_node *n) {
291 return ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
292 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
295 static const char *get_ent_dump_name(entity *ent) {
297 return "<NULL entity>";
298 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
299 if (ent->ld_name) return get_id_str(ent->ld_name);
300 return get_id_str(ent->name);
303 static const char *get_irg_dump_name(ir_graph *irg) {
304 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
305 entity *ent = get_irg_entity(irg);
306 return get_ent_dump_name(ent);
309 static void collect_node(ir_node * node, void *env) {
312 || get_irn_op(node) == op_Bad
313 || get_irn_op(node) == op_Unknown) {
314 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
315 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
316 ARR_APP1(ir_node *, arr, node);
317 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
319 ir_node * block = get_nodes_block(node);
320 ird_set_irn_link(node, ird_get_irn_link(block));
321 ird_set_irn_link(block, node);
325 /** Construct lists to walk ir block-wise.
327 * Collects all blocks, nodes not op_pin_state_pinned,
328 * Bad and Unknown into a flexible array in link field of
329 * irg they belong to. Sets the irg link field to NULL in all
330 * graphs not visited.
331 * Free the list with DEL_ARR_F. */
332 static ir_node ** construct_block_lists(ir_graph *irg) {
333 int i, rem_view = interprocedural_view;
334 ir_graph *rem = current_ir_graph;
335 current_ir_graph = irg;
337 for (i = 0; i < get_irp_n_irgs(); i++)
338 ird_set_irg_link(get_irp_irg(i), NULL);
340 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
342 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
343 interprocedural_view = 0;
344 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
345 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
346 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
347 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
348 interprocedural_view = rem_view;
350 current_ir_graph = rem;
351 return ird_get_irg_link(irg);
354 /*******************************************************************/
355 /* flags to steer output */
356 /*******************************************************************/
358 const char *dump_file_filter = "";
360 /* A compiler option to turn off edge labels */
362 /* A compiler option to turn off dumping values of constant entities */
363 int const_entities = 1;
364 /* A compiler option to dump the keep alive edges */
365 int dump_keepalive = 0;
366 /* Compiler options to dump analysis information in dump_ir_graph */
367 int dump_out_edge_flag = 0;
368 int dump_dominator_information_flag = 0;
369 int dump_loop_information_flag = 0;
370 int dump_backedge_information_flag = 1;
371 int dump_const_local = 0;
372 bool opt_dump_analysed_type_info = 1;
373 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
375 char* overrule_nodecolor = NULL;
377 INLINE bool get_opt_dump_const_local(void) {
378 if (!dump_out_edge_flag && !dump_loop_information_flag)
379 return dump_const_local;
384 void only_dump_method_with_name(ident *name) {
385 dump_file_filter = get_id_str(name);
389 /* To turn off display of edge labels. Edge labels offen cause xvcg to
390 abort with a segmentation fault. */
391 void turn_off_edge_labels(void) {
395 void dump_consts_local(bool b) {
396 dump_const_local = b;
399 void turn_off_constant_entity_values(void) {
403 void dump_keepalive_edges(bool b) {
407 bool get_opt_dump_keepalive_edges(void) {
408 return dump_keepalive;
411 void dump_out_edges(void) {
412 dump_out_edge_flag = 1;
415 void dump_dominator_information(void) {
416 dump_dominator_information_flag = 1;
419 void dump_loop_information(void) {
420 dump_loop_information_flag = 1;
423 void dont_dump_loop_information(void) {
424 dump_loop_information_flag = 0;
427 void dump_backedge_information(bool b) {
428 dump_backedge_information_flag = b;
431 /* Dump the information of type field specified in ana/irtypeinfo.h.
432 * If the flag is set, the type name is output in [] in the node label,
433 * else it is output as info.
435 void dump_analysed_type_info(bool b) {
436 opt_dump_analysed_type_info = b;
439 void dump_pointer_values_to_info(bool b) {
440 opt_dump_pointer_values_to_info = b;
443 /*******************************************************************/
444 /* Routines to dump information about a single ir node. */
445 /*******************************************************************/
448 dump_node_opcode(FILE *F, ir_node *n)
452 switch(get_irn_opcode(n)) {
457 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
458 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
463 if (get_SymConst_kind(n) == symconst_addr_name) {
464 /* don't use get_SymConst_ptr_info as it mangles the name. */
465 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
466 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
467 assert(get_SymConst_entity(n));
468 assert(is_entity(get_SymConst_entity(n)));
469 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
471 assert(get_kind(get_SymConst_type(n)) == k_type);
472 assert(get_type_ident(get_SymConst_type(n)));
473 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
474 if (get_SymConst_kind(n) == symconst_type_tag)
482 if (!interprocedural_view) fprintf(F, "Proj'");
483 else goto default_case;
487 ir_node *pred = get_Proj_pred(n);
489 if (get_irn_opcode(pred) == iro_Cond
490 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
491 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
492 fprintf (F, "defProj");
494 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
495 * fprintf (F, "Arg");
504 if (interprocedural_view) {
505 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
510 case iro_CallBegin: {
511 ir_node *addr = get_CallBegin_ptr(n);
513 if (get_irn_op(addr) == op_Sel)
514 ent = get_Sel_entity(addr);
515 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
516 ent = get_SymConst_entity(addr);
517 fprintf (F, "%s", get_irn_opname(n));
518 if (ent) fprintf (F, " %s", get_entity_name(ent));
524 fprintf (F, "%s", get_irn_opname(n));
532 dump_node_mode(FILE *F, ir_node *n)
536 switch (get_irn_opcode(n)) {
555 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
563 static int dump_node_typeinfo(FILE *F, ir_node *n) {
566 if (opt_dump_analysed_type_info) {
567 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
568 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
569 type *tp = get_irn_type(n);
571 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
580 dump_node_nodeattr(FILE *F, ir_node *n)
584 switch (get_irn_opcode(n)) {
586 if (false && interprocedural_view) {
587 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
591 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
592 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
594 fprintf (F, "%ld", get_Proj_proj(n));
598 fprintf (F, "%ld", get_Filter_proj(n));
601 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
604 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
607 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
617 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
620 fprintf(F, "color: red");
623 switch (get_irn_opcode(n)) {
630 fprintf (F, "color: blue");
633 fprintf (F, "color: lightyellow");
636 fprintf (F, "color: green");
642 fprintf (F, "color: yellow");
645 PRINT_DEFAULT_NODE_ATTR;
648 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
651 static INLINE int dump_node_info(FILE *F, ir_node *n)
657 fprintf (F, " info1: \"");
658 if (opt_dump_pointer_values_to_info)
659 fprintf (F, "addr: %p \n", (void *)n);
660 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
661 fprintf (F, "visited: %ld \n", get_irn_visited(n));
662 irg = get_irn_irg(n);
663 if (irg != get_const_code_irg())
664 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
666 fprintf(F, "arity: %d", get_irn_arity(n));
667 if ((get_irn_op(n) == op_Block) ||
668 (get_irn_op(n) == op_Phi) ||
669 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
670 fprintf(F, " backedges:");
672 for (i = 0; i < get_irn_arity(n); i++)
673 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
677 /* Loop node Someone else please tell me what's wrong ...
678 if (get_irn_loop(n)) {
679 ir_loop *loop = get_irn_loop(n);
681 fprintf(F, " in loop %d with depth %d\n",
682 get_loop_loop_nr(loop), get_loop_depth(loop));
687 switch (get_irn_opcode(n)) {
689 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
690 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
691 for (i = 0; i < get_method_n_params(tp); ++i)
692 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
695 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
698 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
701 entity *ent = get_Sel_entity(n);
704 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
705 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
708 fprintf(F, "<NULL entity>\n");
713 type *tp = get_Call_type(n);
714 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
715 for (i = 0; i < get_method_n_params(tp); ++i)
716 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
717 for (i = 0; i < get_method_n_ress(tp); ++i)
718 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
719 if (0 && Call_has_callees(n)) {
720 fprintf(F, "possible callees: \n");
721 for (i = 0; i < get_Call_n_callees(n); i++) {
722 if (!get_Call_callee(n, i)) {
723 fprintf(F, " %d external method\n", i);
725 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
730 case iro_CallBegin: {
731 ir_node *call = get_CallBegin_call(n);
732 if (Call_has_callees(call)) {
733 fprintf(F, "possible callees: \n");
734 for (i = 0; i < get_Call_n_callees(call); i++) {
735 if (!get_Call_callee(call, i)) {
736 fprintf(F, " %d external method\n", i);
738 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
744 if (!interprocedural_view) {
745 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
746 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
747 for (i = 0; i < get_method_n_ress(tp); ++i)
748 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
752 type *tp = get_Const_type(n);
753 assert(tp != none_type);
754 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
757 switch(get_SymConst_kind(n)) {
758 case symconst_addr_name:
759 fprintf(F, "kind addr_name\n");
761 case symconst_addr_ent:
762 fprintf(F, "kind addr_ent\n");
764 case symconst_type_tag:
765 fprintf(F, "kind type_tag\n");
768 fprintf(F, "kind size\n");
774 if (interprocedural_view) {
775 fprintf(F, "intra predecessor nodes:\n");
776 for (i = 0; i < get_irn_intra_arity(n); i++) {
777 ir_node *pred = get_irn_intra_n(n, i);
778 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
781 fprintf(F, "inter predecessor nodes:\n");
782 for (i = 0; i < get_irn_inter_arity(n); i++) {
783 ir_node *pred = get_irn_inter_n(n, i);
784 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
785 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
792 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
793 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
794 if (get_irn_type(n) != none_type)
795 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
804 bool is_constlike_node(ir_node *n) {
805 ir_op *op = get_irn_op(n);
806 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
810 /* outputs the predecessors of n, that are constants, local. I.e.,
811 generates a copy of the constant predecessors for each node called with. */
812 static void dump_const_node_local(FILE *F, ir_node *n) {
814 if (!get_opt_dump_const_local()) return;
816 /* Use visited flag to avoid outputting nodes twice.
817 initialize it first. */
818 for (i = 0; i < get_irn_arity(n); i++) {
819 ir_node *con = get_irn_n(n, i);
820 if (is_constlike_node(con)) {
821 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
825 for (i = 0; i < get_irn_arity(n); i++) {
826 ir_node *con = get_irn_n(n, i);
827 if (is_constlike_node(con) && irn_not_visited(con)) {
830 mark_irn_visited(con);
831 /* Generate a new name for the node by appending the names of
833 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
834 fprintf(F, " label: \"");
835 bad |= dump_node_opcode(F, con);
836 bad |= dump_node_mode(F, con);
837 bad |= dump_node_typeinfo(F, con);
839 bad |= dump_node_nodeattr(F, con);
840 fprintf(F, " %ld", get_irn_node_nr(con));
842 bad |= dump_node_info(F, con);
843 dump_node_vcgattr(F, con, bad);
849 static void INLINE print_node_error(FILE *F, const char *p)
854 fprintf (F, " info2: \"%s\"", p);
857 static void dump_node(FILE *F, ir_node *n)
862 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
864 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
866 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
867 bad |= dump_node_opcode(F, n);
868 bad |= dump_node_mode(F, n);
869 bad |= dump_node_typeinfo(F, n);
871 bad |= dump_node_nodeattr(F, n);
872 fprintf(F, " %ld", get_irn_node_nr(n));
874 bad |= dump_node_info(F, n);
875 print_node_error(F, p);
876 dump_node_vcgattr(F, n, bad);
878 dump_const_node_local(F, n);
885 /* dump the edge to the block this node belongs to */
887 dump_ir_block_edge(FILE *F, ir_node *n) {
888 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
889 if (is_no_Block(n)) {
890 fprintf (F, "edge: { sourcename: \"");
892 fprintf (F, "\" targetname: \"");
893 PRINT_NODEID(get_nodes_block(n));
894 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
899 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
900 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
901 fprintf (F, INTRA_DATA_EDGE_ATTR);
903 fprintf (F, INTER_DATA_EDGE_ATTR);
907 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
908 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
909 fprintf (F, INTRA_MEM_EDGE_ATTR);
911 fprintf (F, INTER_MEM_EDGE_ATTR);
915 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
918 if (dump_backedge_information_flag && is_backedge(from, to))
919 fprintf (F, BACK_EDGE_ATTR);
921 switch (get_irn_opcode(from)) {
923 fprintf (F, CF_EDGE_ATTR);
925 case iro_Start: break;
928 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
929 fprintf (F, CF_EDGE_ATTR);
930 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
931 fprintf (F, INTER_MEM_EDGE_ATTR);
939 print_data_edge_vcgattr(F, from, to);
944 print_mem_edge_vcgattr(F, from, to);
946 print_data_edge_vcgattr(F, from, to);
950 print_data_edge_vcgattr(F, from, to);
955 print_mem_edge_vcgattr(F, from, to);
957 print_data_edge_vcgattr(F, from, to);
964 print_data_edge_vcgattr(F, from, to);
971 print_mem_edge_vcgattr(F, from, to);
973 print_data_edge_vcgattr(F, from, to);
985 print_data_edge_vcgattr(F, from, to);
988 if (get_irn_modecode(from) == irm_M)
989 fprintf (F, INTER_MEM_EDGE_ATTR);
991 print_data_edge_vcgattr(F, from, to);
998 print_mem_edge_vcgattr(F, from, to);
1000 print_data_edge_vcgattr(F, from, to);
1003 print_mem_edge_vcgattr(F, from, to);
1005 case iro_Tuple: break;
1008 switch (get_irn_modecode(from)) {
1010 fprintf (F, CF_EDGE_ATTR);
1013 fprintf (F, INTER_MEM_EDGE_ATTR);
1016 print_data_edge_vcgattr(F, from, to);
1020 case iro_Bad: break;
1021 case iro_Unknown: break;
1023 switch (get_irn_modecode(from)) {
1025 fprintf (F, INTRA_MEM_EDGE_ATTR);
1028 fprintf (F, CF_EDGE_ATTR);
1031 print_data_edge_vcgattr(F, from, to);
1039 /* dump edges to our inputs */
1041 dump_ir_data_edges(FILE *F, ir_node *n) {
1042 int i, visited = get_irn_visited(n);
1044 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1047 for (i = 0; i < get_irn_arity(n); i++) {
1048 ir_node * pred = get_irn_n(n, i);
1051 if ((interprocedural_view && get_irn_visited(pred) < visited))
1052 continue; /* pred not dumped */
1054 if (dump_backedge_information_flag && is_backedge(n, i))
1055 fprintf (F, "backedge: {sourcename: \"");
1057 fprintf (F, "edge: {sourcename: \"");
1059 fprintf (F, "\" targetname: ");
1060 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1061 PRINT_CONSTID(n, pred);
1063 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1065 fprintf (F, " label: \"%d\" ", i);
1066 print_edge_vcgattr(F, n, i);
1071 /** Dumps a node and its edges but not the block edge
1074 dump_node_wo_blockedge (ir_node *n, void *env) {
1077 dump_ir_data_edges(F, n);
1080 /** Dumps a node and its edges.
1083 dump_whole_node (ir_node *n, void *env) {
1085 dump_node_wo_blockedge(n, env);
1086 if (!node_floats(n)) dump_ir_block_edge(F, n);
1090 dump_const_node(ir_node *n, void *env) {
1091 if (is_Block(n)) return;
1092 dump_node_wo_blockedge(n, env);
1095 /***********************************************************************/
1096 /* the following routines dump the nodes/irgs bracketed to graphs. */
1097 /***********************************************************************/
1099 /** Dumps a constant expression as entity initializer, array bound ...
1101 static void dump_const_expression(FILE *F, ir_node *value) {
1102 ir_graph *rem = current_ir_graph;
1103 int rem_dump_const_local = dump_const_local;
1104 dump_const_local = 0;
1105 current_ir_graph = get_const_code_irg();
1106 irg_walk(value, dump_const_node, NULL, F);
1107 /* Decrease visited flag so that we walk with the same flag for the next
1108 expresssion. This guarantees that we don't dump the same node twice,
1109 as for const expressions cse is performed to save memory. */
1110 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1111 current_ir_graph = rem;
1112 dump_const_local = rem_dump_const_local;
1115 /** Dump a block as graph containing its nodes.
1117 * Expects to find nodes belonging to the block as list in its
1119 * Dumps the edges of all nodes including itself. */
1121 dump_whole_block(FILE *F, ir_node *block) {
1123 assert(is_Block(block));
1125 fprintf(F, "graph: { title: \"");
1126 PRINT_NODEID(block);
1127 fprintf(F, "\" label: \"");
1128 dump_node_opcode(F, block);
1129 fprintf (F, " %ld", get_irn_node_nr(block));
1131 if (get_opt_dump_abstvals())
1132 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1134 fprintf(F, "\" status:clustered color:%s \n",
1135 get_Block_matured(block) ? "yellow" : "red");
1137 /* dump the blocks edges */
1138 dump_ir_data_edges(F, block);
1140 /* dump the nodes that go into the block */
1141 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1143 dump_ir_data_edges(F, node);
1146 /* Close the vcg information for the block */
1148 dump_const_node_local(F, block);
1150 dump_chi_term(F, block);
1155 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1156 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1158 dump_block_graph(FILE *F, ir_graph *irg) {
1160 ir_graph *rem = current_ir_graph;
1161 ir_node **arr = ird_get_irg_link(irg);
1162 current_ir_graph = irg;
1164 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1165 ir_node * node = arr[i];
1166 if (is_Block(node)) {
1167 /* Dumps the block and all the nodes in the block, which are to
1168 be found in Block->link. */
1169 dump_whole_block(F, node);
1171 /* Nodes that are not in a Block. */
1173 dump_ir_data_edges(F, node);
1177 if (dump_loop_information_flag) dump_loop_nodes_into_graph(F, irg);
1179 current_ir_graph = rem;
1182 /** Dumps an irg as a graph.
1183 * If interprocedural view edges can point to nodes out of this graph.
1185 static void dump_graph(FILE *F, ir_graph *irg) {
1187 fprintf(F, "graph: { title: \"");
1189 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1190 get_ent_dump_name(get_irg_entity(irg)));
1192 dump_block_graph(F, irg);
1194 /* Close the vcg information for the irg */
1195 fprintf(F, "}\n\n");
1198 /*******************************************************************/
1199 /* Basic type and entity nodes and edges. */
1200 /*******************************************************************/
1202 /* dumps the edges between nodes and their type or entity attributes. */
1203 static void dump_node2type_edges(ir_node *n, void *env)
1208 switch (get_irn_opcode(n)) {
1210 /* @@@ some consts have an entity */
1213 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1214 || (get_SymConst_kind(n) ==symconst_size))
1216 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1220 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1223 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1226 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1229 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1232 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1240 static int print_type_info(FILE *F, type *tp) {
1243 if (get_type_state(tp) == layout_undefined) {
1244 fprintf(F, "state: layout_undefined\n");
1246 fprintf(F, "state: layout_fixed,\n");
1248 if (get_type_mode(tp))
1249 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1250 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1255 static void print_typespecific_info(FILE *F, type *tp) {
1256 switch (get_type_tpop_code(tp)) {
1259 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1266 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1267 fprintf(F, "params: %d\n", get_method_n_params(tp));
1268 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1276 case tpo_enumeration:
1290 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1291 switch (get_type_tpop_code(tp)) {
1294 if (peculiarity_existent == get_class_peculiarity(tp))
1295 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1297 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1301 fprintf (F, " " TYPE_METH_NODE_ATTR);
1312 case tpo_enumeration:
1325 static int print_type_node(FILE *F, type *tp)
1329 fprintf (F, "node: {title: ");
1331 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1332 fprintf (F, " info1: \"");
1333 bad |= print_type_info(F, tp);
1334 print_typespecific_info(F, tp);
1336 print_typespecific_vcgattr(F, tp);
1342 #define X(a) case a: fprintf(F, #a); break
1343 void dump_entity_node(FILE *F, entity *ent, int color)
1345 fprintf (F, "node: {title: \"");
1346 PRINT_ENTID(ent); fprintf(F, "\"");
1347 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1348 fprintf (F, "label: ");
1349 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1351 fprintf(F, "color: %d", color);
1353 fprintf (F, ENTITY_NODE_ATTR);
1354 fprintf (F, "\n info1: \"");
1356 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1358 fprintf(F, "\"\n}\n");
1362 static void dump_enum_item(FILE *F, type *tp, int pos)
1365 ident *id = get_enumeration_nameid(tp, pos);
1366 tarval *tv = get_enumeration_enum(tp, pos);
1368 tarval_snprintf(buf, sizeof(buf), tv);
1369 fprintf (F, "node: {title: \"");
1370 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1371 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1372 fprintf (F, "label: ");
1373 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1374 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1377 /* dumps a type or entity and it's edges. */
1379 dump_type_info(type_or_ent *tore, void *env) {
1381 int i = 0; /* to shutup gcc */
1383 /* dump this type or entity */
1385 switch (get_kind(tore)) {
1388 entity *ent = (entity *)tore;
1391 dump_entity_node(F, ent, 0);
1393 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1394 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1395 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1396 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1397 if(is_class_type(get_entity_owner(ent))) {
1398 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1399 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1401 /* attached subgraphs */
1402 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1403 if (is_atomic_entity(ent)) {
1404 value = get_atomic_ent_value(ent);
1406 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1407 /* DDMN(value); $$$ */
1408 dump_const_expression(F, value);
1411 if (is_compound_entity(ent)) {
1412 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1413 value = get_compound_ent_value(ent, i);
1415 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1416 dump_const_expression(F, value);
1417 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1419 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1420 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1421 get_compound_ent_value_member(ent, i), i);
1430 type *tp = (type *)tore;
1431 print_type_node(F, tp);
1432 /* and now the edges */
1433 switch (get_type_tpop_code(tp)) {
1436 for (i=0; i < get_class_n_supertypes(tp); i++)
1437 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1438 for (i=0; i < get_class_n_members(tp); i++)
1439 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1443 for (i=0; i < get_struct_n_members(tp); i++)
1444 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1448 for (i = 0; i < get_method_n_params(tp); i++)
1449 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1450 for (i = 0; i < get_method_n_ress(tp); i++)
1451 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1455 for (i = 0; i < get_union_n_members(tp); i++)
1456 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1460 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1461 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1462 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1463 ir_node *upper = get_array_upper_bound(tp, i);
1464 ir_node *lower = get_array_lower_bound(tp, i);
1465 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1466 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1467 dump_const_expression(F, upper);
1468 dump_const_expression(F, lower);
1472 case tpo_enumeration:
1474 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1475 dump_enum_item(F, tp, i);
1476 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1481 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1489 break; /* case k_type */
1492 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1494 } /* switch kind_or_entity */
1497 typedef struct _h_env {
1502 /** For dumping class hierarchies.
1503 * Dumps a class type node and a superclass edge.
1504 * If env->dump_ent dumps entities of classes and overwrites edges.
1507 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1510 int i = 0; /* to shutup gcc */
1512 /* dump this type or entity */
1513 switch (get_kind(tore)) {
1515 entity *ent = (entity *)tore;
1516 if (get_entity_owner(ent) == get_glob_type()) break;
1517 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1518 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1520 dump_entity_node(F, ent, 0);
1522 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1523 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1524 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1526 } break; /* case k_entity */
1529 type *tp = (type *)tore;
1530 if (tp == get_glob_type()) break;
1531 switch (get_type_tpop_code(tp)) {
1533 print_type_node(F, tp);
1534 /* and now the edges */
1535 for (i=0; i < get_class_n_supertypes(tp); i++)
1537 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1543 break; /* case k_type */
1546 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1548 } /* switch kind_or_entity */
1551 /*******************************************************************/
1552 /* dump analysis information that is expressed in graph terms. */
1553 /*******************************************************************/
1555 /* dump out edges */
1557 dump_out_edge(ir_node *n, void *env) {
1560 for (i = 0; i < get_irn_n_outs(n); i++) {
1561 assert(get_irn_out(n, i));
1562 fprintf (F, "edge: {sourcename: \"");
1564 fprintf (F, "\" targetname: \"");
1565 PRINT_NODEID(get_irn_out(n, i));
1566 fprintf (F, "\" color: red linestyle: dashed");
1572 dump_loop_label(FILE *F, ir_loop *loop) {
1573 fprintf (F, "loop %d, %d sons, %d nodes",
1574 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1577 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1578 fprintf (F, " info1: \"");
1579 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1580 #if DEBUG_libfirm /* GL @@@ debug analyses */
1581 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1587 dump_loop_node(FILE *F, ir_loop *loop) {
1588 fprintf (F, "node: {title: \"");
1590 fprintf (F, "\" label: \"");
1591 dump_loop_label(F, loop);
1593 dump_loop_info(F, loop);
1599 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1601 fprintf (F, "edge: {sourcename: \"");
1603 fprintf (F, "\" targetname: \"");
1604 PRINT_NODEID(get_loop_node(loop, i));
1605 fprintf (F, "\" color: green");
1610 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1612 fprintf (F, "edge: {sourcename: \"");
1614 fprintf (F, "\" targetname: \"");
1615 PRINT_LOOPID(get_loop_son(loop, i));
1616 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1617 get_loop_element_pos(loop, get_loop_son(loop, i)));
1621 void dump_loops(FILE *F, ir_loop *loop) {
1623 /* dump this loop node */
1624 dump_loop_node(F, loop);
1626 /* dump edges to nodes in loop -- only if it is a real loop */
1627 if (get_loop_depth(loop) != 0) {
1628 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1629 dump_loop_node_edge(F, loop, i);
1632 for (i = 0; i < get_loop_n_sons(loop); i++) {
1633 dump_loops(F, get_loop_son(loop, i));
1634 dump_loop_son_edge(F, loop, i);
1639 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1640 ir_graph *rem = current_ir_graph;
1641 current_ir_graph = irg;
1643 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1645 current_ir_graph = rem;
1650 * dumps the VCG header
1653 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1662 if (!orientation) orientation = "bottom_to_top";
1666 "graph: { title: \"ir graph of %s\"\n"
1667 "display_edge_labels: %s\n"
1668 "layoutalgorithm: mindepth\n"
1669 "manhattan_edges: yes\n"
1670 "port_sharing: no\n"
1672 "classname 1: \"intrablock Data\"\n"
1673 "classname 16: \"interblock Data\"\n"
1674 "classname 2: \"Block\"\n"
1675 "classname 13: \"Control Flow\"\n"
1676 "classname 14: \"intrablock Memory\"\n"
1677 "classname 17: \"interblock Memory\"\n"
1678 "classname 15: \"Dominators\"\n"
1679 "classname 3: \"Entity type\"\n"
1680 "classname 4: \"Entity owner\"\n"
1681 "classname 5: \"Method Param\"\n"
1682 "classname 6: \"Method Res\"\n"
1683 "classname 7: \"Super\"\n"
1684 "classname 8: \"Union\"\n"
1685 "classname 9: \"Points-to\"\n"
1686 "classname 10: \"Array Element Type\"\n"
1687 "classname 11: \"Overwrites\"\n"
1688 "classname 12: \"Member\"\n"
1689 "infoname 1: \"Attribute\"\n"
1690 "infoname 2: \"Verification errors\"\n",
1691 name, label, orientation);
1693 /* don't use all, the range is too whith/black. */
1697 "colorentry 100: 0 0 0\n"
1698 "colorentry 101: 20 0 0\n"
1699 "colorentry 102: 40 0 0\n"
1700 "colorentry 103: 60 0 0\n"
1701 "colorentry 104: 80 0 0\n"
1702 "colorentry 105: 100 0 0\n"
1703 "colorentry 106: 120 0 0\n"
1704 "colorentry 107: 140 0 0\n"
1705 "colorentry 108: 150 0 0\n"
1706 "colorentry 109: 180 0 0\n"
1707 "colorentry 110: 200 0 0\n"
1708 "colorentry 111: 220 0 0\n"
1709 "colorentry 112: 240 0 0\n"
1710 "colorentry 113: 255 0 0\n"
1711 "colorentry 113: 255 20 20\n"
1712 "colorentry 114: 255 40 40\n"
1713 "colorentry 115: 255 60 60\n"
1714 "colorentry 116: 255 80 80\n"
1715 "colorentry 117: 255 100 100\n"
1716 "colorentry 118: 255 120 120\n"
1717 "colorentry 119: 255 140 140\n"
1718 "colorentry 120: 255 150 150\n"
1719 "colorentry 121: 255 180 180\n"
1720 "colorentry 122: 255 200 200\n"
1721 "colorentry 123: 255 220 220\n"
1722 "colorentry 124: 255 240 240\n"
1723 "colorentry 125: 255 250 250\n"
1726 fprintf (F, "\n"); /* a separator */
1732 * @param irg The graph to be dumped
1733 * @param suffix1 first filename suffix
1734 * @param suffix2 second filename suffix
1736 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1738 const char *nm = get_irg_dump_name(irg);
1739 int len = strlen(nm), i, j;
1740 char *fname; /* filename to put the vcg information in */
1742 if (!suffix1) suffix1 = "";
1743 if (!suffix2) suffix2 = "";
1745 /* open file for vcg graph */
1746 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1748 /* strncpy (fname, nm, len); */ /* copy the filename */
1750 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1752 fname[j] = '@'; j++; fname[j] = '1'; j++;
1753 } else if (nm[i] == '@') {
1754 fname[j] = '@'; j++; fname[j] = '2'; j++;
1756 fname[j] = nm[i]; j++;
1760 strcat (fname, suffix1); /* append file suffix */
1761 strcat (fname, suffix2); /* append file suffix */
1762 strcat (fname, ".vcg"); /* append the .vcg suffix */
1763 F = fopen (fname, "w"); /* open file for writing */
1765 panic("cannot open %s for writing (%m)", fname); /* not reached */
1775 * @param irg The graph to be dumped
1776 * @param suffix filename suffix
1778 static FILE *vcg_open_name (const char *name, const char *suffix) {
1780 char *fname; /* filename to put the vcg information in */
1781 int i, j, len = strlen(name);
1783 if (!suffix) suffix = "";
1785 /** open file for vcg graph */
1786 fname = malloc (len * 2 + 5 + strlen(suffix));
1787 /* strcpy (fname, name);*/ /* copy the filename */
1789 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1790 if (name[i] == '/') {
1791 fname[j] = '@'; j++; fname[j] = '1'; j++;
1792 } else if (name[i] == '@') {
1793 fname[j] = '@'; j++; fname[j] = '2'; j++;
1795 fname[j] = name[i]; j++;
1799 strcat (fname, suffix);
1800 strcat (fname, ".vcg"); /* append the .vcg suffix */
1801 F = fopen (fname, "w"); /* open file for writing */
1803 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1811 * Dumps the vcg file footer
1813 static INLINE void dump_vcg_footer (FILE *F) {
1818 * close the vcg file
1821 vcg_close (FILE *F) {
1822 dump_vcg_footer(F); /* print footer */
1823 fclose (F); /* close vcg file */
1826 /************************************************************************/
1827 /************************************************************************/
1828 /* Routines that dump all or parts of the firm representation to a file */
1829 /************************************************************************/
1830 /************************************************************************/
1832 /************************************************************************/
1833 /* Dump ir graphs, differnt formats and additional information. */
1834 /************************************************************************/
1836 /** Routine to dump a graph, blocks as conventional nodes.
1839 dump_ir_graph (ir_graph *irg, const char *suffix )
1844 rem = current_ir_graph;
1846 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1847 current_ir_graph = irg;
1848 if (interprocedural_view) suffix1 = "-pure-ip";
1849 else suffix1 = "-pure";
1850 f = vcg_open(irg, suffix, suffix1);
1851 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1853 /* walk over the graph */
1854 /* dump_whole_node must be called in post visiting predecessors */
1855 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1857 /* dump the out edges in a separate walk */
1858 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1859 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1864 current_ir_graph = rem;
1869 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1875 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1876 if (interprocedural_view) suffix1 = "-ip";
1878 f = vcg_open(irg, suffix, suffix1);
1879 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1881 construct_block_lists(irg);
1883 for (i = 0; i < get_irp_n_irgs(); i++) {
1884 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1886 dump_graph(f, get_irp_irg(i));
1894 /** dumps a graph with type information
1897 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1900 ir_graph *rem = current_ir_graph;
1903 /* if a filter is set, dump only the irg's that match the filter */
1904 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1907 current_ir_graph = irg;
1909 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1910 else suffix1 = "-pure-wtypes";
1911 f = vcg_open(irg,suffix, suffix1);
1912 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1914 /* dump common ir graph */
1915 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1916 /* dump type info */
1917 type_walk_irg(irg, dump_type_info, NULL, f);
1918 inc_irg_visited(get_const_code_irg());
1919 /* dump edges from graph to type info */
1920 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1923 current_ir_graph = rem;
1927 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1932 ir_graph *rem = current_ir_graph;
1934 /* if a filter is set, dump only the irg's that match the filter */
1935 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1938 if (interprocedural_view) suffix1 = "-wtypes-ip";
1939 else suffix1 = "-wtypes";
1940 f = vcg_open(irg, suffix, suffix1);
1941 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1943 /* dump common blocked ir graph */
1944 construct_block_lists(irg);
1946 for (i = 0; i < get_irp_n_irgs(); i++) {
1947 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1949 dump_graph(f, get_irp_irg(i));
1954 /* dump type info */
1955 current_ir_graph = irg;
1956 type_walk_irg(irg, dump_type_info, NULL, f);
1957 inc_irg_visited(get_const_code_irg());
1959 /* dump edges from graph to type info */
1960 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1962 current_ir_graph = rem;
1966 /***********************************************************************/
1967 /* The following routines dump a control flow graph. */
1968 /***********************************************************************/
1971 dump_block_to_cfg(ir_node *block, void *env) {
1976 if (is_Block(block)) {
1977 /* This is a block. Dump a node for the block. */
1978 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1979 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1980 PRINT_NODEID(block);
1982 if (dump_dominator_information_flag)
1983 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1985 /* Dump the edges */
1986 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1987 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1988 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1989 fprintf (F, "edge: { sourcename: \"");
1990 PRINT_NODEID(block);
1991 fprintf (F, "\" targetname: \"");
1993 fprintf (F, "\"}\n");
1996 /* Dump dominator edge */
1997 if (dump_dominator_information_flag && get_Block_idom(block)) {
1998 pred = get_Block_idom(block);
1999 fprintf (F, "edge: { sourcename: \"");
2000 PRINT_NODEID(block);
2001 fprintf (F, "\" targetname: \"");
2003 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2009 dump_cfg (ir_graph *irg, const char *suffix)
2012 ir_graph *rem = current_ir_graph;
2013 int ddif = dump_dominator_information_flag;
2014 int ipv = interprocedural_view;
2016 /* if a filter is set, dump only the irg's that match the filter */
2017 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2020 current_ir_graph = irg;
2022 f = vcg_open(irg, suffix, "-cfg");
2023 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2025 if (interprocedural_view) {
2026 printf("Warning: dumping cfg not in interprocedural view!\n");
2027 interprocedural_view = 0;
2030 if (get_irg_dom_state(irg) != dom_consistent)
2031 dump_dominator_information_flag = 0;
2033 /* walk over the blocks in the graph */
2034 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2035 dump_node(f, get_irg_bad(irg));
2037 dump_dominator_information_flag = ddif;
2038 interprocedural_view = ipv;
2040 current_ir_graph = rem;
2043 static int weight_overall(int rec, int loop) {
2044 return 2*rec + loop;
2047 static int compute_color (int my, int max) {
2052 /* if small, scale to the full color range. */
2054 my = my * (n_colors/max);
2056 int step = 1 + (max / n_colors);
2060 return base_color + n_colors - color;
2063 static int get_entity_color(entity *ent) {
2064 assert(get_entity_irg(ent));
2065 ir_graph *irg = get_entity_irg(ent);
2067 int rec_depth = get_irg_recursion_depth(irg);
2068 int loop_depth = get_irg_loop_depth(irg);
2069 int overall_depth = weight_overall(rec_depth, loop_depth);
2071 int max_rec_depth = irp->max_callgraph_recursion_depth;
2072 int max_loop_depth = irp->max_callgraph_loop_depth;
2073 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2075 int my_rec_color = compute_color(rec_depth, max_rec_depth);
2076 int my_loop_color = compute_color(loop_depth, max_loop_depth);
2077 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2079 return my_overall_color;
2082 void dump_callgraph(const char *suffix) {
2084 int i, n_irgs = get_irp_n_irgs();
2085 int rem = edge_label;
2087 //ident *prefix = new_id_from_str("java/");
2089 F = vcg_open_name("Callgraph", suffix);
2090 dump_vcg_header(F, "Callgraph", NULL);
2092 for (i = 0; i < n_irgs; ++i) {
2093 ir_graph *irg = get_irp_irg(i);
2094 entity *ent = get_irg_entity(irg);
2095 int j, n_callees = get_irg_n_callees(irg);
2097 /* Do not dump runtime system. */
2098 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2100 dump_entity_node(F, ent, get_entity_color(ent));
2101 for (j = 0; j < n_callees; ++j) {
2102 entity *c = get_irg_entity(get_irg_callee(irg, j));
2103 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2104 int be = is_irg_callee_backedge(irg, j);
2107 "label:\"recursion %d\" color: %d" :
2108 "label:\"calls %d\" color: %d";
2109 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2117 /* Dump all irgs in interprocedural view to a single file. */
2118 void dump_all_cg_block_graph(const char *suffix) {
2121 int rem_view = interprocedural_view;
2122 interprocedural_view = 1;
2124 f = vcg_open_name("All_graphs", suffix);
2125 dump_vcg_header(f, "All_graphs", NULL);
2127 /* collect nodes in all irgs reachable in call graph*/
2128 for (i = 0; i < get_irp_n_irgs(); i++)
2129 ird_set_irg_link(get_irp_irg(i), NULL);
2131 cg_walk(clear_link, collect_node, NULL);
2133 /* dump all graphs */
2134 for (i = 0; i < get_irp_n_irgs(); i++) {
2135 current_ir_graph = get_irp_irg(i);
2136 assert(ird_get_irg_link(current_ir_graph));
2137 dump_graph(f, current_ir_graph);
2138 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2142 interprocedural_view = rem_view;
2145 /***********************************************************************/
2146 /* the following routines dumps type information without any ir nodes. */
2147 /***********************************************************************/
2150 dump_type_graph (ir_graph *irg, const char *suffix)
2154 rem = current_ir_graph;
2156 /* if a filter is set, dump only the irg's that match the filter */
2157 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2159 current_ir_graph = irg;
2161 f = vcg_open(irg, suffix, "-type");
2162 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2164 /* walk over the blocks in the graph */
2165 type_walk_irg(irg, dump_type_info, NULL, f);
2166 /* The walker for the const code can be called several times for the
2167 same (sub) experssion. So that no nodes are dumped several times
2168 we decrease the visited flag of the corresponding graph after each
2169 walk. So now increase it finally. */
2170 inc_irg_visited(get_const_code_irg());
2173 current_ir_graph = rem;
2177 dump_all_types (const char *suffix)
2179 FILE *f = vcg_open_name("All_types", suffix);
2180 dump_vcg_header(f, "All_types", NULL);
2181 type_walk(dump_type_info, NULL, f);
2182 inc_irg_visited(get_const_code_irg());
2187 dump_class_hierarchy (bool entities, const char *suffix)
2189 FILE *f = vcg_open_name("class_hierarchy", suffix);
2193 dump_vcg_header(f, "class_hierarchy", NULL);
2198 type_walk(dump_class_hierarchy_node, NULL, &env);
2202 /***********************************************************************/
2203 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2205 /* dump_ir_block_graph */
2207 /* dump_type_graph */
2208 /* dump_ir_graph_w_types */
2209 /***********************************************************************/
2211 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2213 for (i=0; i < get_irp_n_irgs(); i++) {
2214 dmp_grph(get_irp_irg(i), suffix);
2219 /**********************************************************************************
2220 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2221 * packed together in one subgraph/box *
2222 **********************************************************************************/
2224 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2225 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2227 ir_loop *son = NULL;
2229 /* Dump a new loop node. */
2230 dump_loop_node(F, loop);
2232 /* Dump the loop elements. */
2234 for(i = 0; i < get_loop_n_elements(loop); i++) {
2235 le = get_loop_element(loop, i);
2237 if (get_kind(son) == k_ir_loop) {
2239 /* We are a loop son -> Recurse */
2241 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2242 fprintf(F, "\" }\n");
2243 fprintf (F, "edge: {sourcename: \"");
2245 fprintf (F, "\" targetname: \"");
2247 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2248 loop_node_started = 0;
2250 dump_loop_son_edge(F, loop, son_number++);
2251 dump_loops_standalone(F, son);
2252 } else if (get_kind(son) == k_ir_node) {
2253 /* We are a loop node -> Collect firm nodes */
2255 ir_node *n = le.node;
2258 if (!loop_node_started) {
2259 /* Start a new node which contains all firm nodes of the current loop */
2260 fprintf (F, "node: { title: \"");
2262 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2263 loop_node_started = 1;
2269 bad |= dump_node_opcode(F, n);
2270 bad |= dump_node_mode(F, n);
2271 bad |= dump_node_typeinfo(F, n);
2273 bad |= dump_node_nodeattr(F, n);
2274 fprintf (F, " %ld", get_irn_node_nr(n));
2275 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2276 } else { /* for callgraph loop tree */
2277 assert(get_kind(son) == k_ir_graph);
2278 /* We are a loop node -> Collect firm graphs */
2279 ir_graph *n = (ir_graph *)le.node;
2280 if (!loop_node_started) {
2281 /* Start a new node which contains all firm nodes of the current loop */
2282 fprintf (F, "node: { title: \"");
2284 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2285 loop_node_started = 1;
2290 fprintf (F, " %s", get_irg_dump_name(n));
2291 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2295 if (loop_node_started) {
2296 fprintf(F, "\" }\n");
2297 fprintf (F, "edge: {sourcename: \"");
2299 fprintf (F, "\" targetname: \"");
2301 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2302 loop_node_started = 0;
2306 void dump_loop_tree(ir_graph *irg, const char *suffix)
2309 ir_graph *rem = current_ir_graph;
2310 int el_rem = edge_label;
2313 /* if a filter is set, dump only the irg's that match the filter */
2314 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2317 current_ir_graph = irg;
2319 f = vcg_open(irg, suffix, "-looptree");
2320 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2322 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2326 edge_label = el_rem;
2327 current_ir_graph = rem;
2330 void dump_callgraph_loop_tree(const char *suffix) {
2332 F = vcg_open_name("Callgraph_looptree", suffix);
2333 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2334 dump_loops_standalone(F, irp->outermost_cg_loop);
2339 /*******************************************************************************/
2340 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2341 /*******************************************************************************/
2343 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2344 int i, son_number = 0, node_number = 0;
2346 if (dump_loop_information_flag) dump_loop_node(F, loop);
2348 for (i = 0; i < get_loop_n_elements(loop); i++) {
2349 loop_element le = get_loop_element(loop, i);
2350 if (*(le.kind) == k_ir_loop) {
2351 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2353 collect_nodeloop(F, le.son, loopnodes);
2355 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2356 eset_insert(loopnodes, le.node);
2361 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2364 for(i = 0; i < get_loop_n_elements(loop); i++) {
2365 loop_element le = get_loop_element(loop, i);
2366 if (*(le.kind) == k_ir_loop) {
2368 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2370 if (is_Block(le.node)) start = 0; else start = -1;
2371 for (j = start; j < get_irn_arity(le.node); j++) {
2372 ir_node *pred = get_irn_n(le.node, j);
2373 if (!eset_contains(loopnodes, pred)) {
2374 eset_insert(extnodes, pred);
2375 if (!is_Block(pred)) {
2376 pred = get_nodes_block(pred);
2377 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2385 void dump_loop(ir_loop *l, const char *suffix) {
2388 eset *loopnodes = eset_create();
2389 eset *extnodes = eset_create();
2392 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2393 F = vcg_open_name (name, suffix);
2394 dump_vcg_header(F, name, NULL);
2396 /* collect all nodes to dump */
2397 collect_nodeloop(F, l, loopnodes);
2398 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2400 /* build block lists */
2401 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2402 set_irn_link(n, NULL);
2403 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2404 set_irn_link(n, NULL);
2405 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2407 b = get_nodes_block(n);
2408 set_irn_link(n, get_irn_link(b));
2411 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2413 b = get_nodes_block(n);
2414 set_irn_link(n, get_irn_link(b));
2418 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2420 fprintf(F, "graph: { title: \"");
2422 fprintf(F, "\" label: \"");
2423 dump_node_opcode(F, b);
2424 fprintf (F, " %ld", get_irn_node_nr(b));
2425 fprintf(F, "\" status:clustered color:yellow\n");
2427 /* dump the blocks edges */
2428 dump_ir_data_edges(F, b);
2430 /* dump the nodes that go into the block */
2431 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2432 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2434 overrule_nodecolor = NULL;
2435 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2438 /* Close the vcg information for the block */
2440 dump_const_node_local(F, b);
2443 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2445 fprintf(F, "graph: { title: \"");
2447 fprintf(F, "\" label: \"");
2448 dump_node_opcode(F, b);
2449 fprintf (F, " %ld", get_irn_node_nr(b));
2450 fprintf(F, "\" status:clustered color:lightblue\n");
2452 /* dump the nodes that go into the block */
2453 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2454 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2456 overrule_nodecolor = NULL;
2457 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2460 /* Close the vcg information for the block */
2462 dump_const_node_local(F, b);
2466 eset_destroy(loopnodes);
2467 eset_destroy(extnodes);