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.
22 # include "irnode_t.h"
23 # include "irgraph_t.h"
24 # include "entity_t.h"
26 # include "firm_common_t.h"
31 # include "typewalk.h"
34 # include "type_or_entity.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 /* Attributes of nodes */
54 #define PRINT_DEFAULT_NODE_ATTR
55 #define DEFAULT_NODE_ATTR " "
56 #define DEFAULT_TYPE_ATTRIBUTE " "
57 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
59 /* Attributes of edges between Firm nodes */
60 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
61 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
62 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
63 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
64 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
65 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
66 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
68 #define BACK_EDGE_ATTR "linestyle:dashed "
70 /* Attributes of edges between Firm nodes and type/entity nodes */
71 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
73 /* Attributes of edges in type/entity graphs. */
74 #define TYPE_METH_NODE_ATTR "color: lightyellow"
75 #define TYPE_CLASS_NODE_ATTR "color: green"
76 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
77 #define ENTITY_NODE_ATTR "color: yellow"
78 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
79 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
80 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
81 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
82 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
83 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
84 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
85 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
86 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
87 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
88 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
89 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
90 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
91 #define ENUM_ITEM_NODE_ATTR "color: green"
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))
112 static const char *get_type_name_ex(type *tp, int *bad)
115 return get_type_name(tp);
120 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
125 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
126 fprintf(F, " targetname: "); PRINT_TYPEID(T);
127 vfprintf(F, fmt, ap);
132 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
137 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
138 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
139 vfprintf(F, fmt, ap);
144 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
149 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
150 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
151 vfprintf(F, fmt, ap);
156 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
161 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
162 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
163 vfprintf(F, fmt, ap);
168 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
173 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
174 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
175 vfprintf(F, fmt, ap);
180 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
185 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
186 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
188 vfprintf(F, fmt, ap);
193 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
198 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
199 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
200 vfprintf(F, fmt, ap);
205 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
210 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
211 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
212 vfprintf(F, fmt, ap);
217 /*******************************************************************/
218 /* global and ahead declarations */
219 /*******************************************************************/
221 /* A suffix to manipulate the file name. */
222 char *dump_file_suffix = "";
224 char *dump_file_filter = "";
226 /* file to dump to */
229 static void dump_whole_node(ir_node *n, void* env);
230 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
232 /*******************************************************************/
233 /* Helper functions. */
234 /*******************************************************************/
236 /* Use private link attr to be able to call dumper anywhere without
237 destroying link fields. */
239 static pmap *irdump_link_map = NULL;
241 static void init_irdump(void) {
242 /* We need a new, empty map. */
243 if (irdump_link_map) pmap_destroy(irdump_link_map);
244 irdump_link_map = pmap_create();
248 void *ird_get_irn_link(ir_node *n) {
250 if (!irdump_link_map) return NULL;
252 if (pmap_contains(irdump_link_map, (void *)n))
253 res = pmap_get(irdump_link_map, (void *)n);
257 void ird_set_irn_link(ir_node *n, void *x) {
258 if (!irdump_link_map) init_irdump();
259 pmap_insert(irdump_link_map, (void *)n, x);
262 void *ird_get_irg_link(ir_graph *irg) {
264 if (!irdump_link_map) return NULL;
266 if (pmap_contains(irdump_link_map, (void *)irg))
267 res = pmap_get(irdump_link_map, (void *)irg);
271 void ird_set_irg_link(ir_graph *irg, void *x) {
272 if (!irdump_link_map) init_irdump();
273 pmap_insert(irdump_link_map, (void *)irg, x);
276 static void clear_link(ir_node * node, void * env) {
277 ird_set_irn_link(node, NULL);
281 static int node_floats(ir_node *n) {
282 return ((get_op_pinned(get_irn_op(n)) == floats) &&
283 (get_irg_pinned(current_ir_graph) == floats));
286 static const char *get_ent_dump_name(entity *ent) {
288 return "<NULL entity>";
289 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
290 if (ent->ld_name) return get_id_str(ent->ld_name);
291 return get_id_str(ent->name);
294 static const char *get_irg_dump_name(ir_graph *irg) {
295 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
296 entity *ent = get_irg_ent(irg);
297 return get_ent_dump_name(ent);
300 static void collect_node(ir_node * node, void *env) {
303 || get_irn_op(node) == op_Bad
304 || get_irn_op(node) == op_Unknown) {
305 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
306 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
307 ARR_APP1(ir_node *, arr, node);
308 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
310 ir_node * block = get_nodes_block(node);
311 ird_set_irn_link(node, ird_get_irn_link(block));
312 ird_set_irn_link(block, node);
316 /** Construct lists to walk ir block-wise.
318 * Collects all blocks, nodes not pinned,
319 * Bad and Unknown into a flexible array in link field of
320 * irg they belong to. Sets the irg link field to NULL in all
321 * graphs not visited.
322 * Free the list with DEL_ARR_F. */
323 static ir_node ** construct_block_lists(ir_graph *irg) {
324 int i, rem_view = interprocedural_view;
325 ir_graph *rem = current_ir_graph;
326 current_ir_graph = irg;
328 for (i = 0; i < get_irp_n_irgs(); i++)
329 ird_set_irg_link(get_irp_irg(i), NULL);
331 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
333 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
334 interprocedural_view = 0;
335 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
336 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
337 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
338 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
339 interprocedural_view = rem_view;
341 current_ir_graph = rem;
342 return ird_get_irg_link(irg);
345 /*******************************************************************/
346 /* flags to steer output */
347 /*******************************************************************/
349 /* A compiler option to turn off edge labels */
351 /* A compiler option to turn off dumping values of constant entities */
352 int const_entities = 1;
353 /* A compiler option to dump the keep alive edges */
354 int dump_keepalive = 0;
355 /* Compiler options to dump analysis information in dump_ir_graph */
356 int dump_out_edge_flag = 0;
357 int dump_dominator_information_flag = 0;
358 int dump_loop_information_flag = 0;
359 int dump_backedge_information_flag = 1;
360 int dump_const_local = 0;
361 bool opt_dump_analysed_type_info = 1;
362 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
364 char* overrule_nodecolor = NULL;
366 INLINE bool get_opt_dump_const_local(void) {
367 if (!dump_out_edge_flag && !dump_loop_information_flag)
368 return dump_const_local;
373 /* To turn off display of edge labels. Edge labels offen cause xvcg to
374 abort with a segmentation fault. */
375 void turn_off_edge_labels(void) {
379 void dump_consts_local(bool b) {
380 dump_const_local = b;
383 void turn_off_constant_entity_values(void) {
387 void dump_keepalive_edges(bool b) {
391 bool get_opt_dump_keepalive_edges(void) {
392 return dump_keepalive;
395 void dump_out_edges(void) {
396 dump_out_edge_flag = 1;
399 void dump_dominator_information(void) {
400 dump_dominator_information_flag = 1;
403 void dump_loop_information(void) {
404 dump_loop_information_flag = 1;
407 void dont_dump_loop_information(void) {
408 dump_loop_information_flag = 0;
411 void dump_backedge_information(bool b) {
412 dump_backedge_information_flag = b;
415 /* Dump the information of type field specified in ana/irtypeinfo.h.
416 * If the flag is set, the type name is output in [] in the node label,
417 * else it is output as info.
419 void dump_analysed_type_info(bool b) {
420 opt_dump_analysed_type_info = b;
423 void dump_pointer_values_to_info(bool b) {
424 opt_dump_pointer_values_to_info = b;
427 /*******************************************************************/
428 /* Routines to dump information about a single ir node. */
429 /*******************************************************************/
432 dump_node_opcode(FILE *F, ir_node *n)
436 switch(get_irn_opcode(n)) {
441 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
442 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
447 if (get_SymConst_kind(n) == linkage_ptr_info) {
448 /* don't use get_SymConst_ptr_info as it mangles the name. */
449 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
451 assert(get_kind(get_SymConst_type(n)) == k_type);
452 assert(get_type_ident(get_SymConst_type(n)));
453 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
454 if (get_SymConst_kind(n) == type_tag)
462 if (!interprocedural_view) fprintf(F, "Proj'");
463 else fprintf(F, "%s", get_irn_opname(n));
467 ir_node *cond = get_Proj_pred(n);
469 if (get_irn_opcode(cond) == iro_Cond
470 && get_Proj_proj(n) == get_Cond_defaultProj(cond)
471 && get_irn_mode(get_Cond_selector(cond)) != mode_b)
472 fprintf (F, "defProj");
474 fprintf (F, "%s", get_irn_opname(n));
478 if (interprocedural_view) {
479 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
485 fprintf (F, "%s", get_irn_opname(n));
493 dump_node_mode (ir_node *n)
495 switch (get_irn_opcode(n)) {
514 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
521 static int dump_node_typeinfo(ir_node *n) {
524 if (opt_dump_analysed_type_info) {
525 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
526 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
527 type *tp = get_irn_type(n);
529 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
538 dump_node_nodeattr (ir_node *n)
542 switch (get_irn_opcode(n)) {
544 if (false && interprocedural_view) {
545 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
549 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
550 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
552 fprintf (F, "%ld", get_Proj_proj(n));
556 fprintf (F, "%ld", get_Filter_proj(n));
559 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
562 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
565 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
575 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
578 fprintf(F, "color: red");
581 switch (get_irn_opcode(n)) {
588 fprintf (F, "color: blue");
591 fprintf (F, "color: lightyellow");
594 fprintf (F, "color: green");
600 fprintf (F, "color: yellow");
603 PRINT_DEFAULT_NODE_ATTR;
606 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
609 static INLINE int dump_node_info(ir_node *n)
615 fprintf (F, " info1: \"");
616 if (opt_dump_pointer_values_to_info)
617 fprintf (F, "addr: %p \n", (void *)n);
618 fprintf (F, "visited: %ld \n", get_irn_visited(n));
619 irg = get_irn_irg(n);
620 if (irg != get_const_code_irg())
621 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
623 fprintf(F, "arity: %d", get_irn_arity(n));
624 if ((get_irn_op(n) == op_Block) ||
625 (get_irn_op(n) == op_Phi) ||
626 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
627 fprintf(F, " backedges:");
629 for (i = 0; i < get_irn_arity(n); i++)
630 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
634 /* Loop node Someone else please tell me what's wrong ...
635 if (get_irn_loop(n)) {
636 ir_loop *loop = get_irn_loop(n);
638 fprintf(F, " in loop %d with depth %d\n",
639 get_loop_loop_nr(loop), get_loop_depth(loop));
644 switch (get_irn_opcode(n)) {
646 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
647 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
648 for (i = 0; i < get_method_n_params(tp); ++i)
649 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
652 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
655 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
658 entity *ent = get_Sel_entity(n);
661 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
662 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
665 fprintf(F, "<NULL entity>\n");
670 type *tp = get_Call_type(n);
671 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
672 for (i = 0; i < get_method_n_params(tp); ++i)
673 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
674 for (i = 0; i < get_method_n_ress(tp); ++i)
675 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
676 if (Call_has_callees(n)) {
677 fprintf(F, "possible callees: \n");
678 for (i = 0; i < get_Call_n_callees(n); i++) {
679 if (!get_Call_callee(n, i)) {
680 fprintf(F, " %d external method\n", i);
682 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
687 case iro_CallBegin: {
688 ir_node *call = get_CallBegin_call(n);
689 if (Call_has_callees(call)) {
690 fprintf(F, "possible callees: \n");
691 for (i = 0; i < get_Call_n_callees(call); i++) {
692 if (!get_Call_callee(call, i)) {
693 fprintf(F, " %d external method\n", i);
695 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
701 if (!interprocedural_view) {
702 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
703 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
704 for (i = 0; i < get_method_n_ress(tp); ++i)
705 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
709 type *tp = get_Const_type(n);
710 assert(tp != none_type);
711 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
715 if (interprocedural_view) {
716 fprintf(F, "intra predecessor nodes:\n");
717 for (i = 0; i < get_irn_intra_arity(n); i++) {
718 ir_node *pred = get_irn_intra_n(n, i);
719 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
722 fprintf(F, "inter predecessor nodes:\n");
723 for (i = 0; i < get_irn_inter_arity(n); i++) {
724 ir_node *pred = get_irn_inter_n(n, i);
725 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
726 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
733 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
734 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
735 if (get_irn_type(n) != none_type)
736 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
745 bool is_constlike_node(ir_node *n) {
746 ir_op *op = get_irn_op(n);
747 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
751 /* outputs the predecessors of n, that are constants, local. I.e.,
752 generates a copy of the constant predecessors for each node called with. */
753 static void dump_const_node_local(ir_node *n) {
755 if (!get_opt_dump_const_local()) return;
757 /* Use visited flag to avoid outputting nodes twice.
758 initialize it first. */
759 for (i = 0; i < get_irn_arity(n); i++) {
760 ir_node *con = get_irn_n(n, i);
761 if (is_constlike_node(con)) {
762 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
766 for (i = 0; i < get_irn_arity(n); i++) {
767 ir_node *con = get_irn_n(n, i);
768 if (is_constlike_node(con) && irn_not_visited(con)) {
771 mark_irn_visited(con);
772 /* Generate a new name for the node by appending the names of
774 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
775 fprintf(F, " label: \"");
776 bad |= dump_node_opcode(F, con);
777 dump_node_mode (con);
778 bad |= dump_node_typeinfo(con);
780 bad |= dump_node_nodeattr(con);
781 fprintf(F, " %ld", get_irn_node_nr(con));
783 bad |= dump_node_info(con);
784 dump_node_vcgattr(con, bad);
790 static void print_node_error(const char *p)
795 fprintf (F, " info2: \"%s\"", p);
798 static void dump_node(ir_node *n)
803 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
805 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
807 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
808 bad |= dump_node_opcode(F, n);
810 bad |= dump_node_typeinfo(n);
812 bad |= dump_node_nodeattr(n);
813 fprintf(F, " %ld", get_irn_node_nr(n));
815 bad |= dump_node_info(n);
817 dump_node_vcgattr(n, bad);
819 dump_const_node_local(n);
826 /* dump the edge to the block this node belongs to */
828 dump_ir_block_edge(ir_node *n) {
829 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
830 if (is_no_Block(n)) {
831 fprintf (F, "edge: { sourcename: \"");
833 fprintf (F, "\" targetname: \"");
834 PRINT_NODEID(get_nodes_block(n));
835 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
840 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
841 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
842 fprintf (F, INTRA_DATA_EDGE_ATTR);
844 fprintf (F, INTER_DATA_EDGE_ATTR);
848 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
849 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
850 fprintf (F, INTRA_MEM_EDGE_ATTR);
852 fprintf (F, INTER_MEM_EDGE_ATTR);
856 print_edge_vcgattr(ir_node *from, int to) {
859 if (dump_backedge_information_flag && is_backedge(from, to))
860 fprintf (F, BACK_EDGE_ATTR);
862 switch (get_irn_opcode(from)) {
864 fprintf (F, CF_EDGE_ATTR);
866 case iro_Start: break;
869 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
870 fprintf (F, CF_EDGE_ATTR);
871 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
872 fprintf (F, INTER_MEM_EDGE_ATTR);
880 print_data_edge_vcgattr(F, from, to);
885 print_mem_edge_vcgattr(F, from, to);
887 print_data_edge_vcgattr(F, from, to);
891 print_data_edge_vcgattr(F, from, to);
896 print_mem_edge_vcgattr(F, from, to);
898 print_data_edge_vcgattr(F, from, to);
905 print_data_edge_vcgattr(F, from, to);
912 print_mem_edge_vcgattr(F, from, to);
914 print_data_edge_vcgattr(F, from, to);
926 print_data_edge_vcgattr(F, from, to);
929 if (get_irn_modecode(from) == irm_M)
930 fprintf (F, INTER_MEM_EDGE_ATTR);
932 print_data_edge_vcgattr(F, from, to);
939 print_mem_edge_vcgattr(F, from, to);
941 print_data_edge_vcgattr(F, from, to);
944 print_mem_edge_vcgattr(F, from, to);
946 case iro_Tuple: break;
949 switch (get_irn_modecode(from)) {
951 fprintf (F, CF_EDGE_ATTR);
954 fprintf (F, INTER_MEM_EDGE_ATTR);
957 print_data_edge_vcgattr(F, from, to);
962 case iro_Unknown: break;
964 switch (get_irn_modecode(from)) {
966 fprintf (F, INTRA_MEM_EDGE_ATTR);
969 fprintf (F, CF_EDGE_ATTR);
972 print_data_edge_vcgattr(F, from, to);
980 /* dump edges to our inputs */
982 dump_ir_data_edges(ir_node *n) {
983 int i, visited = get_irn_visited(n);
985 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
988 for (i = 0; i < get_irn_arity(n); i++) {
989 ir_node * pred = get_irn_n(n, i);
992 if ((interprocedural_view && get_irn_visited(pred) < visited))
993 continue; /* pred not dumped */
995 if (dump_backedge_information_flag && is_backedge(n, i))
996 fprintf (F, "backedge: {sourcename: \"");
998 fprintf (F, "edge: {sourcename: \"");
1000 fprintf (F, "\" targetname: ");
1001 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1002 PRINT_CONSTID(n, pred);
1004 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1006 fprintf (F, " label: \"%d\" ", i);
1007 print_edge_vcgattr(n, i);
1012 /** Dumps a node and its edges but not the block edge
1015 dump_node_wo_blockedge (ir_node *n, void* env) {
1017 dump_ir_data_edges(n);
1020 /** Dumps a node and its edges.
1023 dump_whole_node (ir_node *n, void* env) {
1024 dump_node_wo_blockedge(n, env);
1025 if (!node_floats(n)) dump_ir_block_edge(n);
1029 dump_const_node(ir_node *n, void *env) {
1030 if (is_Block(n)) return;
1031 dump_node_wo_blockedge(n, env);
1034 /***********************************************************************/
1035 /* the following routines dump the nodes/irgs bracketed to graphs. */
1036 /***********************************************************************/
1038 /** Dumps a constant expression as entity initializer, array bound ...
1040 static void dump_const_expression(ir_node *value) {
1041 ir_graph *rem = current_ir_graph;
1042 int rem_dump_const_local = dump_const_local;
1043 dump_const_local = 0;
1044 current_ir_graph = get_const_code_irg();
1045 irg_walk(value, dump_const_node, NULL, NULL);
1046 /* Decrease visited flag so that we walk with the same flag for the next
1047 expresssion. This guarantees that we don't dump the same node twice,
1048 as for const expressions cse is performed to save memory. */
1049 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1050 current_ir_graph = rem;
1051 dump_const_local = rem_dump_const_local;
1054 /** Dump a block as graph containing its nodes.
1056 * Expects to find nodes belonging to the block as list in its
1058 * Dumps the edges of all nodes including itself. */
1060 dump_whole_block(ir_node *block) {
1062 assert(is_Block(block));
1064 fprintf(F, "graph: { title: \"");
1065 PRINT_NODEID(block);
1066 fprintf(F, "\" label: \"");
1067 dump_node_opcode(F, block);
1068 fprintf (F, " %ld", get_irn_node_nr(block));
1070 if (get_opt_dump_abstvals())
1071 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1073 fprintf(F, "\" status:clustered color:%s \n",
1074 get_Block_matured(block) ? "yellow" : "red");
1076 /* dump the blocks edges */
1077 dump_ir_data_edges(block);
1079 /* dump the nodes that go into the block */
1080 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1082 dump_ir_data_edges(node);
1085 /* Close the vcg information for the block */
1087 dump_const_node_local(block);
1089 dump_chi_term(F, block);
1094 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1095 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1097 dump_block_graph(ir_graph *irg) {
1099 ir_graph *rem = current_ir_graph;
1100 ir_node **arr = ird_get_irg_link(irg);
1101 current_ir_graph = irg;
1103 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1104 ir_node * node = arr[i];
1105 if (is_Block(node)) {
1106 /* Dumps the block and all the nodes in the block, which are to
1107 be found in Block->link. */
1108 dump_whole_block(node);
1110 /* Nodes that are not in a Block. */
1112 dump_ir_data_edges(node);
1116 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1118 current_ir_graph = rem;
1121 /** Dumps an irg as a graph.
1122 * If interprocedural view edges can point to nodes out of this graph.
1124 static void dump_graph(ir_graph *irg) {
1126 fprintf(F, "graph: { title: \"");
1128 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1129 get_ent_dump_name(get_irg_ent(irg)));
1131 dump_block_graph (irg);
1133 /* Close the vcg information for the irg */
1134 fprintf(F, "}\n\n");
1137 /*******************************************************************/
1138 /* Basic type and entity nodes and edges. */
1139 /*******************************************************************/
1141 /* dumps the edges between nodes and their type or entity attributes. */
1142 static void dump_node2type_edges (ir_node *n, void *env)
1146 switch (get_irn_opcode(n)) {
1148 /* @@@ some consts have an entity */
1151 if ( (get_SymConst_kind(n) == type_tag)
1152 || (get_SymConst_kind(n) == size))
1154 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1158 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1161 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1164 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1167 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1170 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1178 static void print_type_info(type *tp) {
1179 if (get_type_state(tp) == layout_undefined) {
1180 fprintf(F, "state: layout_undefined\n");
1182 fprintf(F, "state: layout_fixed,\n");
1184 if (get_type_mode(tp))
1185 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1186 fprintf(F, "size: %dB,\n", get_type_size(tp));
1189 static void print_typespecific_info(type *tp) {
1190 switch (get_type_tpop_code(tp)) {
1193 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1200 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1201 fprintf(F, "params: %d\n", get_method_n_params(tp));
1202 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1210 case tpo_enumeration:
1224 static void print_typespecific_vcgattr(type *tp) {
1225 switch (get_type_tpop_code(tp)) {
1228 if (peculiarity_existent == get_class_peculiarity(tp))
1229 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1231 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1235 fprintf (F, " " TYPE_METH_NODE_ATTR);
1246 case tpo_enumeration:
1259 static int print_type_node(type *tp)
1263 fprintf (F, "node: {title: ");
1265 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1266 fprintf (F, " info1: \"");
1267 print_type_info(tp);
1268 print_typespecific_info(tp);
1270 print_typespecific_vcgattr(tp);
1276 #define X(a) case a: fprintf(F, #a); break
1277 void dump_entity_node(entity *ent)
1279 fprintf (F, "node: {title: \"");
1280 PRINT_ENTID(ent); fprintf(F, "\"");
1281 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1282 fprintf (F, "label: ");
1283 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1284 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1286 fprintf (F, "\nallocation: ");
1287 switch (get_entity_allocation(ent)) {
1288 X(allocation_dynamic);
1289 X(allocation_automatic);
1290 X(allocation_static);
1291 X(allocation_parameter);
1294 fprintf (F, "\nvisibility: ");
1295 switch (get_entity_visibility(ent)) {
1296 X(visibility_local);
1297 X(visibility_external_visible);
1298 X(visibility_external_allocated);
1301 fprintf (F, "\nvariability: ");
1302 switch (get_entity_variability(ent)) {
1303 X(variability_uninitialized);
1304 X(variability_initialized);
1305 X(variability_part_constant);
1306 X(variability_constant);
1309 fprintf (F, "\nvolatility: ");
1310 switch (get_entity_volatility(ent)) {
1311 X(volatility_non_volatile);
1312 X(volatility_is_volatile);
1315 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1316 fprintf(F, "\nname: %s\nld_name: %s",
1317 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1318 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1319 if (is_method_type(get_entity_type(ent))) {
1320 if (get_entity_irg(ent)) /* can be null */
1321 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1323 { fprintf (F, "\nirg = NULL"); }
1325 fprintf(F, "\"\n}\n");
1329 static void dump_enum_item(type *tp, int pos)
1332 ident *id = get_enumeration_nameid(tp, pos);
1333 tarval *tv = get_enumeration_enum(tp, pos);
1335 tarval_snprintf(buf, sizeof(buf), tv);
1336 fprintf (F, "node: {title: \"");
1337 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1338 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1339 fprintf (F, "label: ");
1340 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1341 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1344 /* dumps a type or entity and it's edges. */
1346 dump_type_info (type_or_ent *tore, void *env) {
1347 int i = 0; /* to shutup gcc */
1349 /* dump this type or entity */
1351 switch (get_kind(tore)) {
1354 entity *ent = (entity *)tore;
1357 dump_entity_node(ent);
1359 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1360 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1361 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1362 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1363 if(is_class_type(get_entity_owner(ent))) {
1364 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1365 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1368 /* attached subgraphs */
1369 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1370 if (is_atomic_entity(ent)) {
1371 value = get_atomic_ent_value(ent);
1373 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1374 /* DDMN(value); $$$ */
1375 dump_const_expression(value);
1378 if (is_compound_entity(ent)) {
1379 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1380 value = get_compound_ent_value(ent, i);
1382 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1383 dump_const_expression(value);
1384 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1386 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1387 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1388 get_compound_ent_value_member(ent, i), i);
1397 type *tp = (type *)tore;
1398 print_type_node(tp);
1399 /* and now the edges */
1400 switch (get_type_tpop_code(tp)) {
1403 for (i=0; i < get_class_n_supertypes(tp); i++) {
1404 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1407 for (i=0; i < get_class_n_members(tp); i++) {
1408 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1413 for (i=0; i < get_struct_n_members(tp); i++) {
1414 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1419 for (i = 0; i < get_method_n_params(tp); i++)
1421 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1423 for (i = 0; i < get_method_n_ress(tp); i++)
1425 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1430 for (i = 0; i < get_union_n_members(tp); i++)
1432 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1437 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1438 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1439 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1440 ir_node *upper = get_array_upper_bound(tp, i);
1441 ir_node *lower = get_array_lower_bound(tp, i);
1442 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1443 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1444 dump_const_expression(upper);
1445 dump_const_expression(lower);
1449 case tpo_enumeration:
1451 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1452 dump_enum_item(tp, i);
1453 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1458 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1466 break; /* case k_type */
1469 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1471 } /* switch kind_or_entity */
1474 /** For dumping class hierarchies.
1475 * Dumps a class type node and a superclass edge.
1476 * If env != null dumps entities of classes and overwrites edges.
1479 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1480 int i = 0; /* to shutup gcc */
1482 /* dump this type or entity */
1483 switch (get_kind(tore)) {
1485 entity *ent = (entity *)tore;
1486 if (get_entity_owner(ent) == get_glob_type()) break;
1487 if ((env) && is_class_type(get_entity_owner(ent))) {
1489 dump_entity_node(ent);
1491 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1492 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1494 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1497 } break; /* case k_entity */
1500 type *tp = (type *)tore;
1501 if (tp == get_glob_type()) break;
1502 switch (get_type_tpop_code(tp)) {
1504 print_type_node(tp);
1505 /* and now the edges */
1506 for (i=0; i < get_class_n_supertypes(tp); i++)
1508 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1514 break; /* case k_type */
1517 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1519 } /* switch kind_or_entity */
1522 /*******************************************************************/
1523 /* dump analysis information that is expressed in graph terms. */
1524 /*******************************************************************/
1526 /* dump out edges */
1528 dump_out_edge (ir_node *n, void* env) {
1530 for (i = 0; i < get_irn_n_outs(n); i++) {
1531 assert(get_irn_out(n, i));
1532 fprintf (F, "edge: {sourcename: \"");
1534 fprintf (F, "\" targetname: \"");
1535 PRINT_NODEID(get_irn_out(n, i));
1536 fprintf (F, "\" color: red linestyle: dashed");
1542 dump_loop_label(ir_loop *loop) {
1543 fprintf (F, "loop %d, %d sons, %d nodes",
1544 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1547 static INLINE void dump_loop_info(ir_loop *loop) {
1548 fprintf (F, " info1: \"");
1549 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1550 #if DEBUG_libfirm /* GL @@@ debug analyses */
1551 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1557 dump_loop_node(ir_loop *loop) {
1558 fprintf (F, "node: {title: \"");
1560 fprintf (F, "\" label: \"");
1561 dump_loop_label(loop);
1563 dump_loop_info(loop);
1569 dump_loop_node_edge (ir_loop *loop, int i) {
1571 fprintf (F, "edge: {sourcename: \"");
1573 fprintf (F, "\" targetname: \"");
1574 PRINT_NODEID(get_loop_node(loop, i));
1575 fprintf (F, "\" color: green");
1580 dump_loop_son_edge (ir_loop *loop, int i) {
1582 fprintf (F, "edge: {sourcename: \"");
1584 fprintf (F, "\" targetname: \"");
1585 PRINT_LOOPID(get_loop_son(loop, i));
1586 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1587 get_loop_element_pos(loop, get_loop_son(loop, i)));
1591 void dump_loops (ir_loop *loop) {
1593 /* dump this loop node */
1594 dump_loop_node(loop);
1596 /* dump edges to nodes in loop -- only if it is a real loop */
1597 if (get_loop_depth(loop) != 0) {
1598 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1599 dump_loop_node_edge(loop, i);
1602 for (i = 0; i < get_loop_n_sons(loop); i++) {
1603 dump_loops(get_loop_son(loop, i));
1604 dump_loop_son_edge(loop, i);
1609 void dump_loop_nodes_into_graph(ir_graph *irg) {
1610 ir_graph *rem = current_ir_graph;
1611 current_ir_graph = irg;
1613 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1615 current_ir_graph = rem;
1619 /************************************************************************/
1620 /* open and close vcg file */
1621 /************************************************************************/
1624 dump_vcg_header(const char *name, const char *orientation) {
1633 if (!orientation) orientation = "bottom_to_top";
1637 "graph: { title: \"ir graph of %s\"\n"
1638 "display_edge_labels: %s\n"
1639 "layoutalgorithm: mindepth\n"
1640 "manhattan_edges: yes\n"
1641 "port_sharing: no\n"
1643 "classname 1: \"intrablock Data\"\n"
1644 "classname 16: \"interblock Data\"\n"
1645 "classname 2: \"Block\"\n"
1646 "classname 13: \"Control Flow\"\n"
1647 "classname 14: \"intrablock Memory\"\n"
1648 "classname 17: \"interblock Memory\"\n"
1649 "classname 15: \"Dominators\"\n"
1650 "classname 3: \"Entity type\"\n"
1651 "classname 4: \"Entity owner\"\n"
1652 "classname 5: \"Method Param\"\n"
1653 "classname 6: \"Method Res\"\n"
1654 "classname 7: \"Super\"\n"
1655 "classname 8: \"Union\"\n"
1656 "classname 9: \"Points-to\"\n"
1657 "classname 10: \"Array Element Type\"\n"
1658 "classname 11: \"Overwrites\"\n"
1659 "classname 12: \"Member\"\n"
1660 "infoname 1: \"Attribute\"\n"
1661 "infoname 2: \"Verification errors\"\n",
1662 name, label, orientation);
1664 fprintf (F, "\n"); /* a separator */
1667 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1668 const char *nm = get_irg_dump_name(irg);
1669 int len = strlen(nm), i, j;
1670 char *fname; /* filename to put the vcg information in */
1672 if (!suffix1) suffix1 = "";
1673 if (!suffix2) suffix2 = "";
1675 /** open file for vcg graph */
1676 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1678 /* strncpy (fname, nm, len); */ /* copy the filename */
1680 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1682 fname[j] = '@'; j++; fname[j] = '1'; j++;
1683 } else if (nm[i] == '@') {
1684 fname[j] = '@'; j++; fname[j] = '2'; j++;
1686 fname[j] = nm[i]; j++;
1690 strcat (fname, suffix1); /* append file suffix */
1691 strcat (fname, suffix2); /* append file suffix */
1692 strcat (fname, ".vcg"); /* append the .vcg suffix */
1693 F = fopen (fname, "w"); /* open file for writing */
1695 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1700 static void vcg_open_name (const char *name, char *suffix) {
1701 char *fname; /* filename to put the vcg information in */
1702 int i, j, len = strlen(name);
1704 if (!suffix) suffix = "";
1706 /** open file for vcg graph */
1707 fname = malloc (len * 2 + 5 + strlen(suffix));
1708 /* strcpy (fname, name);*/ /* copy the filename */
1710 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1711 if (name[i] == '/') {
1712 fname[j] = '@'; j++; fname[j] = '1'; j++;
1713 } else if (name[i] == '@') {
1714 fname[j] = '@'; j++; fname[j] = '2'; j++;
1716 fname[j] = name[i]; j++;
1720 strcat (fname, suffix);
1721 strcat (fname, ".vcg"); /* append the .vcg suffix */
1722 F = fopen (fname, "w"); /* open file for writing */
1724 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1729 static INLINE void dump_vcg_footer (void) {
1735 dump_vcg_footer(); /* print footer */
1736 fclose (F); /* close vcg file */
1739 /************************************************************************/
1740 /************************************************************************/
1741 /* Routines that dump all or parts of the firm representation to a file */
1742 /************************************************************************/
1743 /************************************************************************/
1745 /************************************************************************/
1746 /* Dump ir graphs, differnt formats and additional information. */
1747 /************************************************************************/
1749 /** Routine to dump a graph, blocks as conventional nodes.
1752 dump_ir_graph (ir_graph *irg)
1756 rem = current_ir_graph;
1758 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1760 current_ir_graph = irg;
1761 if (interprocedural_view) suffix = "-pure-ip";
1762 else suffix = "-pure";
1763 vcg_open (irg, dump_file_suffix, suffix);
1764 dump_vcg_header(get_irg_dump_name(irg), NULL);
1766 /* walk over the graph */
1767 /* dump_whole_node must be called in post visiting predecessors */
1768 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1770 /* dump the out edges in a separate walk */
1771 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1772 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1777 current_ir_graph = rem;
1782 dump_ir_block_graph (ir_graph *irg)
1787 if(strncmp(get_entity_name(get_irg_ent(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1789 if (interprocedural_view) suffix = "-ip";
1791 vcg_open (irg, dump_file_suffix, suffix);
1792 dump_vcg_header(get_irg_dump_name(irg), NULL);
1794 construct_block_lists(irg);
1796 for (i = 0; i < get_irp_n_irgs(); i++) {
1797 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1799 dump_graph(get_irp_irg(i));
1807 /** dumps a graph with type information
1810 dump_ir_graph_w_types (ir_graph *irg)
1812 ir_graph *rem = current_ir_graph;
1815 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1817 current_ir_graph = irg;
1819 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1820 else suffix = "-pure-wtypes";
1821 vcg_open (irg, dump_file_suffix, suffix);
1822 dump_vcg_header(get_irg_dump_name(irg), NULL);
1824 /* dump common ir graph */
1825 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1826 /* dump type info */
1827 type_walk_irg(irg, dump_type_info, NULL, NULL);
1828 inc_irg_visited(get_const_code_irg());
1829 /* dump edges from graph to type info */
1830 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1833 current_ir_graph = rem;
1837 dump_ir_block_graph_w_types (ir_graph *irg)
1841 ir_graph *rem = current_ir_graph;
1843 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1845 if (interprocedural_view) suffix = "-wtypes-ip";
1846 else suffix = "-wtypes";
1847 vcg_open (irg, dump_file_suffix, suffix);
1848 dump_vcg_header(get_irg_dump_name(irg), NULL);
1850 /* dump common blocked ir graph */
1851 construct_block_lists(irg);
1853 for (i = 0; i < get_irp_n_irgs(); i++) {
1854 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1856 dump_graph(get_irp_irg(i));
1861 /* dump type info */
1862 current_ir_graph = irg;
1863 type_walk_irg(irg, dump_type_info, NULL, NULL);
1864 inc_irg_visited(get_const_code_irg());
1866 /* dump edges from graph to type info */
1867 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1869 current_ir_graph = rem;
1873 /***********************************************************************/
1874 /* The following routines dump a control flow graph. */
1875 /***********************************************************************/
1878 dump_block_to_cfg (ir_node *block, void *env) {
1882 if (is_Block(block)) {
1883 /* This is a block. Dump a node for the block. */
1884 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1885 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1886 PRINT_NODEID(block);
1888 if (dump_dominator_information_flag)
1889 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1891 /* Dump the edges */
1892 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1893 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1894 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1895 fprintf (F, "edge: { sourcename: \"");
1896 PRINT_NODEID(block);
1897 fprintf (F, "\" targetname: \"");
1899 fprintf (F, "\"}\n");
1902 /* Dump dominator edge */
1903 if (dump_dominator_information_flag && get_Block_idom(block)) {
1904 pred = get_Block_idom(block);
1905 fprintf (F, "edge: { sourcename: \"");
1906 PRINT_NODEID(block);
1907 fprintf (F, "\" targetname: \"");
1909 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1915 dump_cfg (ir_graph *irg)
1917 ir_graph *rem = current_ir_graph;
1918 int ddif = dump_dominator_information_flag;
1919 int ipv = interprocedural_view;
1921 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1923 current_ir_graph = irg;
1925 vcg_open (irg, dump_file_suffix, "-cfg");
1926 dump_vcg_header(get_irg_dump_name(irg), NULL);
1928 if (interprocedural_view) {
1929 printf("Warning: dumping cfg not in interprocedural view!\n");
1930 interprocedural_view = 0;
1933 if (get_irg_dom_state(irg) != dom_consistent)
1934 dump_dominator_information_flag = 0;
1936 /* walk over the blocks in the graph */
1937 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1938 dump_node (get_irg_bad(irg));
1940 dump_dominator_information_flag = ddif;
1941 interprocedural_view = ipv;
1943 current_ir_graph = rem;
1948 /* Dump all irgs in interprocedural view to a single file. */
1949 void dump_all_cg_block_graph(void) {
1951 int rem_view = interprocedural_view;
1952 interprocedural_view = 1;
1954 vcg_open_name ("All_graphs", dump_file_suffix);
1955 dump_vcg_header("All_graphs", NULL);
1957 /* collect nodes in all irgs reachable in call graph*/
1958 for (i = 0; i < get_irp_n_irgs(); i++)
1959 ird_set_irg_link(get_irp_irg(i), NULL);
1961 cg_walk(clear_link, collect_node, NULL);
1963 /* dump all graphs */
1964 for (i = 0; i < get_irp_n_irgs(); i++) {
1965 current_ir_graph = get_irp_irg(i);
1966 assert(ird_get_irg_link(current_ir_graph));
1967 dump_graph(current_ir_graph);
1968 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1972 interprocedural_view = rem_view;
1975 /***********************************************************************/
1976 /* the following routines dumps type information without any ir nodes. */
1977 /***********************************************************************/
1980 dump_type_graph (ir_graph *irg)
1983 rem = current_ir_graph;
1985 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1987 current_ir_graph = irg;
1989 vcg_open (irg, dump_file_suffix, "-type");
1990 dump_vcg_header(get_irg_dump_name(irg), NULL);
1992 /* walk over the blocks in the graph */
1993 type_walk_irg(irg, dump_type_info, NULL, NULL);
1994 /* The walker for the const code can be called several times for the
1995 same (sub) experssion. So that no nodes are dumped several times
1996 we decrease the visited flag of the corresponding graph after each
1997 walk. So now increase it finally. */
1998 inc_irg_visited(get_const_code_irg());
2001 current_ir_graph = rem;
2005 dump_all_types (void)
2007 vcg_open_name ("All_types", dump_file_suffix);
2008 dump_vcg_header("All_types", NULL);
2009 type_walk(dump_type_info, NULL, NULL);
2010 inc_irg_visited(get_const_code_irg());
2015 dump_class_hierarchy (bool entities)
2017 vcg_open_name ("class_hierarchy", dump_file_suffix);
2018 dump_vcg_header("class_hierarchy", NULL);
2020 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
2022 type_walk(dump_class_hierarchy_node, NULL, NULL);
2026 /***********************************************************************/
2027 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2029 /* dump_ir_block_graph */
2031 /* dump_type_graph */
2032 /* dump_ir_graph_w_types */
2033 /***********************************************************************/
2035 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
2037 for (i=0; i < get_irp_n_irgs(); i++) {
2038 dmp_grph(get_irp_irg(i));
2043 /**********************************************************************************
2044 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2045 * packed together in one subgraph *
2046 **********************************************************************************/
2050 void dump_loops_standalone (ir_loop *loop) {
2051 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2053 ir_loop *son = NULL;
2055 /* Dump a new loop node. */
2056 dump_loop_node(loop);
2058 /* Dump the loop elements. */
2060 for(i = 0; i < get_loop_n_elements(loop); i++)
2062 le = get_loop_element(loop, i);
2064 if (get_kind(son) == k_ir_loop) {
2066 /* We are a loop son -> Recurse */
2068 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2069 fprintf(F, "\" }\n");
2070 fprintf (F, "edge: {sourcename: \"");
2072 fprintf (F, "\" targetname: \"");
2074 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2075 loop_node_started = 0;
2077 dump_loop_son_edge(loop, son_number++);
2078 dump_loops_standalone(son);
2081 /* We are a loop node -> Collect firm nodes */
2083 ir_node *n = le.node;
2085 if (!loop_node_started) {
2086 /* Start a new node which contains all firm nodes of the current loop */
2087 fprintf (F, "node: { title: \"");
2089 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2090 loop_node_started = 1;
2096 dump_node_opcode(F, n);
2098 dump_node_typeinfo(n);
2100 dump_node_nodeattr(n);
2101 fprintf (F, " %ld", get_irn_node_nr(n));
2105 if (loop_node_started) {
2106 fprintf(F, "\" }\n");
2107 fprintf (F, "edge: {sourcename: \"");
2109 fprintf (F, "\" targetname: \"");
2111 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2112 loop_node_started = 0;
2116 void dump_loop_tree(ir_graph *irg, char *suffix)
2118 ir_graph *rem = current_ir_graph;
2119 int el_rem = edge_label;
2122 /* @@@ AS: What does that do? */
2123 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2125 current_ir_graph = irg;
2127 vcg_open(irg, suffix, "-looptree");
2128 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2130 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2134 edge_label = el_rem;
2135 current_ir_graph = rem;
2139 /*******************************************************************************/
2140 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2141 /*******************************************************************************/
2143 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2144 int i, son_number = 0, node_number = 0;
2146 if (dump_loop_information_flag) dump_loop_node(loop);
2148 for (i = 0; i < get_loop_n_elements(loop); i++) {
2149 loop_element le = get_loop_element(loop, i);
2150 if (*(le.kind) == k_ir_loop) {
2151 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2153 collect_nodeloop(le.son, loopnodes);
2155 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2156 eset_insert(loopnodes, le.node);
2161 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2164 for(i = 0; i < get_loop_n_elements(loop); i++) {
2165 loop_element le = get_loop_element(loop, i);
2166 if (*(le.kind) == k_ir_loop) {
2168 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2170 if (is_Block(le.node)) start = 0; else start = -1;
2171 for (j = start; j < get_irn_arity(le.node); j++) {
2172 ir_node *pred = get_irn_n(le.node, j);
2173 if (!eset_contains(loopnodes, pred)) {
2174 eset_insert(extnodes, pred);
2175 if (!is_Block(pred)) {
2176 pred = get_nodes_block(pred);
2177 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2185 void dump_loop (ir_loop *l, char *suffix) {
2187 eset *loopnodes = eset_create();
2188 eset *extnodes = eset_create();
2191 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2192 vcg_open_name (name, suffix);
2193 dump_vcg_header(name, NULL);
2195 /* collect all nodes to dump */
2196 collect_nodeloop(l, loopnodes);
2197 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2199 /* build block lists */
2200 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2201 set_irn_link(n, NULL);
2202 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2203 set_irn_link(n, NULL);
2204 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2206 b = get_nodes_block(n);
2207 set_irn_link(n, get_irn_link(b));
2210 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2212 b = get_nodes_block(n);
2213 set_irn_link(n, get_irn_link(b));
2217 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2219 fprintf(F, "graph: { title: \"");
2221 fprintf(F, "\" label: \"");
2222 dump_node_opcode(F, b);
2223 fprintf (F, " %ld", get_irn_node_nr(b));
2224 fprintf(F, "\" status:clustered color:yellow\n");
2226 /* dump the blocks edges */
2227 dump_ir_data_edges(b);
2229 /* dump the nodes that go into the block */
2230 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2231 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2233 overrule_nodecolor = NULL;
2234 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2237 /* Close the vcg information for the block */
2239 dump_const_node_local(b);
2242 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2244 fprintf(F, "graph: { title: \"");
2246 fprintf(F, "\" label: \"");
2247 dump_node_opcode(F, b);
2248 fprintf (F, " %ld", get_irn_node_nr(b));
2249 fprintf(F, "\" status:clustered color:lightblue\n");
2251 /* dump the nodes that go into the block */
2252 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2253 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2255 overrule_nodecolor = NULL;
2256 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2259 /* Close the vcg information for the block */
2261 dump_const_node_local(b);
2265 eset_destroy(loopnodes);
2266 eset_destroy(extnodes);