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 BLOCK_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
61 #define CF_EDGE_ATTR "class:13 color:red"
62 #define MEM_EDGE_ATTR "class:14 color:blue"
63 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
65 #define BACK_EDGE_ATTR "linestyle:dashed "
67 /* Attributes of edges between Firm nodes and type/entity nodes */
68 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
70 /* Attributes of edges in type/entity graphs. */
71 #define TYPE_METH_NODE_ATTR "color: lightyellow"
72 #define TYPE_CLASS_NODE_ATTR "color: green"
73 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
74 #define ENTITY_NODE_ATTR "color: yellow"
75 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
76 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
77 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
78 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
79 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
80 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
81 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
82 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
83 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
84 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
85 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
86 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
87 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
88 #define ENUM_ITEM_NODE_ATTR "color: green"
90 #if DEBUG_libfirm && NODEID_AS_LABEL
91 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
92 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
93 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
94 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
95 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
96 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
97 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
100 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
101 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
102 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
103 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
104 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
105 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
106 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
109 static const char *get_type_name_ex(type *tp, int *bad)
112 return get_type_name(tp);
117 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
122 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
123 fprintf(F, " targetname: "); PRINT_TYPEID(T);
124 vfprintf(F, fmt, ap);
129 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
134 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
135 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
136 vfprintf(F, fmt, ap);
141 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
146 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
147 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
148 vfprintf(F, fmt, ap);
153 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
158 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
159 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
160 vfprintf(F, fmt, ap);
165 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
170 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
171 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
172 vfprintf(F, fmt, ap);
177 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
182 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
183 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
185 vfprintf(F, fmt, ap);
190 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
195 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
196 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
197 vfprintf(F, fmt, ap);
202 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
207 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
208 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
209 vfprintf(F, fmt, ap);
214 /*******************************************************************/
215 /* global and ahead declarations */
216 /*******************************************************************/
218 /* A suffix to manipulate the file name. */
219 char *dump_file_suffix = "";
221 char *dump_file_filter = "";
223 /* file to dump to */
226 static void dump_whole_node(ir_node *n, void* env);
227 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
229 /*******************************************************************/
230 /* Helper functions. */
231 /*******************************************************************/
233 /* Use private link attr to be able to call dumper anywhere without
234 destroying link fields. */
236 static pmap *irdump_link_map = NULL;
238 static void init_irdump(void) {
239 /* We need a new, empty map. */
240 if (irdump_link_map) pmap_destroy(irdump_link_map);
241 irdump_link_map = pmap_create();
245 void *ird_get_irn_link(ir_node *n) {
247 if (!irdump_link_map) return NULL;
249 if (pmap_contains(irdump_link_map, (void *)n))
250 res = pmap_get(irdump_link_map, (void *)n);
254 void ird_set_irn_link(ir_node *n, void *x) {
255 if (!irdump_link_map) init_irdump();
256 pmap_insert(irdump_link_map, (void *)n, x);
259 void *ird_get_irg_link(ir_graph *irg) {
261 if (!irdump_link_map) return NULL;
263 if (pmap_contains(irdump_link_map, (void *)irg))
264 res = pmap_get(irdump_link_map, (void *)irg);
268 void ird_set_irg_link(ir_graph *irg, void *x) {
269 if (!irdump_link_map) init_irdump();
270 pmap_insert(irdump_link_map, (void *)irg, x);
273 static void clear_link(ir_node * node, void * env) {
274 ird_set_irn_link(node, NULL);
278 static int node_floats(ir_node *n) {
279 return ((get_op_pinned(get_irn_op(n)) == floats) &&
280 (get_irg_pinned(current_ir_graph) == floats));
283 static const char *get_ent_dump_name(entity *ent) {
285 return "<NULL entity>";
286 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
287 if (ent->ld_name) return get_id_str(ent->ld_name);
288 return get_id_str(ent->name);
291 static const char *get_irg_dump_name(ir_graph *irg) {
292 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
293 entity *ent = get_irg_ent(irg);
294 return get_ent_dump_name(ent);
297 static void collect_node(ir_node * node, void *env) {
300 || get_irn_op(node) == op_Bad
301 || get_irn_op(node) == op_Unknown) {
302 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
303 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
304 ARR_APP1(ir_node *, arr, node);
305 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
307 ir_node * block = get_nodes_block(node);
308 ird_set_irn_link(node, ird_get_irn_link(block));
309 ird_set_irn_link(block, node);
313 /** Construct lists to walk ir block-wise.
315 * Collects all blocks, nodes not pinned,
316 * Bad and Unknown into a flexible array in link field of
317 * irg they belong to. Sets the irg link field to NULL in all
318 * graphs not visited.
319 * Free the list with DEL_ARR_F. */
320 static ir_node ** construct_block_lists(ir_graph *irg) {
322 ir_graph *rem = current_ir_graph;
323 current_ir_graph = irg;
325 for (i = 0; i < get_irp_n_irgs(); i++)
326 ird_set_irg_link(get_irp_irg(i), NULL);
328 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
330 current_ir_graph = rem;
331 return ird_get_irg_link(irg);
334 /*******************************************************************/
335 /* flags to steer output */
336 /*******************************************************************/
338 /* A compiler option to turn off edge labels */
340 /* A compiler option to turn off dumping values of constant entities */
341 int const_entities = 1;
342 /* A compiler option to dump the keep alive edges */
343 int dump_keepalive = 0;
344 /* Compiler options to dump analysis information in dump_ir_graph */
345 int dump_out_edge_flag = 0;
346 int dump_dominator_information_flag = 0;
347 int dump_loop_information_flag = 0;
348 int dump_backedge_information_flag = 1;
349 int dump_const_local = 0;
350 bool opt_dump_analysed_type_info = 1;
351 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
353 char* overrule_nodecolor = NULL;
355 INLINE bool get_opt_dump_const_local(void) {
356 if (!dump_out_edge_flag && !dump_loop_information_flag)
357 return dump_const_local;
362 /* To turn off display of edge labels. Edge labels offen cause xvcg to
363 abort with a segmentation fault. */
364 void turn_off_edge_labels(void) {
368 void dump_consts_local(bool b) {
369 dump_const_local = b;
372 void turn_off_constant_entity_values(void) {
376 void dump_keepalive_edges(bool b) {
380 bool get_opt_dump_keepalive_edges(void) {
381 return dump_keepalive;
384 void dump_out_edges(void) {
385 dump_out_edge_flag = 1;
388 void dump_dominator_information(void) {
389 dump_dominator_information_flag = 1;
392 void dump_loop_information(void) {
393 dump_loop_information_flag = 1;
396 void dont_dump_loop_information(void) {
397 dump_loop_information_flag = 0;
400 void dump_backedge_information(bool b) {
401 dump_backedge_information_flag = b;
404 /* Dump the information of type field specified in ana/irtypeinfo.h.
405 * If the flag is set, the type name is output in [] in the node label,
406 * else it is output as info.
408 void dump_analysed_type_info(bool b) {
409 opt_dump_analysed_type_info = b;
412 void dump_pointer_values_to_info(bool b) {
413 opt_dump_pointer_values_to_info = b;
416 /*******************************************************************/
417 /* Routines to dump information about a single ir node. */
418 /*******************************************************************/
421 dump_node_opcode(FILE *F, ir_node *n)
425 switch(get_irn_opcode(n)) {
430 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
431 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
436 if (get_SymConst_kind(n) == linkage_ptr_info) {
437 /* don't use get_SymConst_ptr_info as it mangles the name. */
438 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
440 assert(get_kind(get_SymConst_type(n)) == k_type);
441 assert(get_type_ident(get_SymConst_type(n)));
442 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
443 if (get_SymConst_kind(n) == type_tag)
451 if (!interprocedural_view) fprintf(F, "Proj'");
452 else fprintf(F, "%s", get_irn_opname(n));
456 if (interprocedural_view) {
457 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
463 fprintf (F, "%s", get_irn_opname(n));
471 dump_node_mode (ir_node *n)
473 switch (get_irn_opcode(n)) {
492 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
499 static int dump_node_typeinfo(ir_node *n) {
502 if (opt_dump_analysed_type_info) {
503 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
504 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
505 type *tp = get_irn_type(n);
507 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
516 dump_node_nodeattr (ir_node *n)
520 switch (get_irn_opcode(n)) {
522 if (false && interprocedural_view) {
523 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
527 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
528 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
530 fprintf (F, "%ld", get_Proj_proj(n));
534 fprintf (F, "%ld", get_Filter_proj(n));
537 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
540 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
543 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
553 static INLINE void dump_node_vcgattr(ir_node *n, int bad)
556 fprintf(F, "color: red");
559 switch (get_irn_opcode(n)) {
566 fprintf (F, "color: blue");
569 fprintf (F, "color: lightyellow");
572 fprintf (F, "color: green");
578 fprintf (F, "color: yellow");
581 PRINT_DEFAULT_NODE_ATTR;
584 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
587 static INLINE int dump_node_info(ir_node *n)
593 fprintf (F, " info1: \"");
594 if (opt_dump_pointer_values_to_info)
595 fprintf (F, "addr: %p \n", (void *)n);
596 fprintf (F, "visited: %ld \n", get_irn_visited(n));
597 irg = get_irn_irg(n);
598 if (irg != get_const_code_irg())
599 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
601 fprintf(F, "arity: %d", get_irn_arity(n));
602 if ((get_irn_op(n) == op_Block) ||
603 (get_irn_op(n) == op_Phi) ||
604 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
605 fprintf(F, " backedges:");
607 for (i = 0; i < get_irn_arity(n); i++)
608 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
612 /* Loop node Someone else please tell me what's wrong ...
613 if (get_irn_loop(n)) {
614 ir_loop *loop = get_irn_loop(n);
616 fprintf(F, " in loop %d with depth %d\n",
617 get_loop_loop_nr(loop), get_loop_depth(loop));
622 switch (get_irn_opcode(n)) {
624 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
625 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
626 for (i = 0; i < get_method_n_params(tp); ++i)
627 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
630 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
633 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
636 entity *ent = get_Sel_entity(n);
639 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
640 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
643 fprintf(F, "<NULL entity>\n");
648 type *tp = get_Call_type(n);
649 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
650 for (i = 0; i < get_method_n_params(tp); ++i)
651 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
652 for (i = 0; i < get_method_n_ress(tp); ++i)
653 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
654 if (Call_has_callees(n)) {
655 fprintf(F, "possible callees: \n");
656 for (i = 0; i < get_Call_n_callees(n); i++) {
657 if (!get_Call_callee(n, i)) {
658 fprintf(F, " %d external method\n", i);
660 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
665 case iro_CallBegin: {
666 ir_node *call = get_CallBegin_call(n);
667 if (Call_has_callees(call)) {
668 fprintf(F, "possible callees: \n");
669 for (i = 0; i < get_Call_n_callees(call); i++) {
670 if (!get_Call_callee(call, i)) {
671 fprintf(F, " %d external method\n", i);
673 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
679 if (!interprocedural_view) {
680 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
681 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
682 for (i = 0; i < get_method_n_ress(tp); ++i)
683 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
687 type *tp = get_Const_type(n);
688 assert(tp != none_type);
689 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
693 if (interprocedural_view) {
694 fprintf(F, "intra predecessor nodes:\n");
695 for (i = 0; i < get_irn_intra_arity(n); i++) {
696 ir_node *pred = get_irn_intra_n(n, i);
697 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
700 fprintf(F, "inter predecessor nodes:\n");
701 for (i = 0; i < get_irn_inter_arity(n); i++) {
702 ir_node *pred = get_irn_inter_n(n, i);
703 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
704 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
711 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
712 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
713 if (get_irn_type(n) != none_type)
714 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
723 bool is_constlike_node(ir_node *n) {
724 ir_op *op = get_irn_op(n);
725 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
729 /* outputs the predecessors of n, that are constants, local. I.e.,
730 generates a copy of the constant predecessors for each node called with. */
731 static void dump_const_node_local(ir_node *n) {
733 if (!get_opt_dump_const_local()) return;
735 /* Use visited flag to avoid outputting nodes twice.
736 initialize it first. */
737 for (i = 0; i < get_irn_arity(n); i++) {
738 ir_node *con = get_irn_n(n, i);
739 if (is_constlike_node(con)) {
740 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
744 for (i = 0; i < get_irn_arity(n); i++) {
745 ir_node *con = get_irn_n(n, i);
746 if (is_constlike_node(con) && irn_not_visited(con)) {
749 mark_irn_visited(con);
750 /* Generate a new name for the node by appending the names of
752 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
753 fprintf(F, " label: \"");
754 bad |= dump_node_opcode(F, con);
755 dump_node_mode (con);
756 bad |= dump_node_typeinfo(con);
758 bad |= dump_node_nodeattr(con);
759 fprintf(F, " %ld", get_irn_node_nr(con));
761 bad |= dump_node_info(con);
762 dump_node_vcgattr(con, bad);
768 static void print_node_error(const char *p)
773 fprintf (F, " info2: \"%s\"", p);
776 static void dump_node(ir_node *n)
781 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
783 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
785 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
786 bad |= dump_node_opcode(F, n);
788 bad |= dump_node_typeinfo(n);
790 bad |= dump_node_nodeattr(n);
791 fprintf(F, " %ld", get_irn_node_nr(n));
793 bad |= dump_node_info(n);
795 dump_node_vcgattr(n, bad);
797 dump_const_node_local(n);
804 /* dump the edge to the block this node belongs to */
806 dump_ir_block_edge(ir_node *n) {
807 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
808 if (is_no_Block(n)) {
809 fprintf (F, "edge: { sourcename: \"");
811 fprintf (F, "\" targetname: \"");
812 PRINT_NODEID(get_nodes_block(n));
813 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
817 static void print_edge_vcgattr(ir_node *from, int to) {
820 if (dump_backedge_information_flag && is_backedge(from, to))
821 fprintf (F, BACK_EDGE_ATTR);
823 switch (get_irn_opcode(from)) {
825 fprintf (F, CF_EDGE_ATTR);
827 case iro_Start: break;
830 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
831 fprintf (F, CF_EDGE_ATTR);
832 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
833 fprintf (F, MEM_EDGE_ATTR);
836 case iro_EndReg: break;
837 case iro_EndExcept: break;
839 case iro_Break: break;
840 case iro_Cond: break;
843 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
845 case iro_Const: break;
846 case iro_SymConst:break;
849 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
851 case iro_CallBegin: break;
854 case iro_Minus: break;
860 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
868 case iro_Shrs: break;
871 case iro_Conv: break;
873 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
879 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
882 fprintf (F, MEM_EDGE_ATTR);
884 case iro_Tuple: break;
887 switch (get_irn_modecode(from)) {
889 fprintf (F, CF_EDGE_ATTR);
892 fprintf (F, MEM_EDGE_ATTR);
898 case iro_Unknown: break;
905 /* dump edges to our inputs */
907 dump_ir_data_edges(ir_node *n) {
908 int i, visited = get_irn_visited(n);
910 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
913 for (i = 0; i < get_irn_arity(n); i++) {
914 ir_node * pred = get_irn_n(n, i);
917 if ((interprocedural_view && get_irn_visited(pred) < visited))
918 continue; /* pred not dumped */
920 if (dump_backedge_information_flag && is_backedge(n, i))
921 fprintf (F, "backedge: {sourcename: \"");
923 fprintf (F, "edge: {sourcename: \"");
925 fprintf (F, "\" targetname: ");
926 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
927 PRINT_CONSTID(n, pred);
929 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
931 fprintf (F, " label: \"%d\" ", i);
932 print_edge_vcgattr(n, i);
937 /** Dumps a node and its edges but not the block edge
940 dump_node_wo_blockedge (ir_node *n, void* env) {
942 dump_ir_data_edges(n);
945 /** Dumps a node and its edges.
948 dump_whole_node (ir_node *n, void* env) {
949 dump_node_wo_blockedge(n, env);
950 if (!node_floats(n)) dump_ir_block_edge(n);
954 dump_const_node(ir_node *n, void *env) {
955 if (is_Block(n)) return;
956 dump_node_wo_blockedge(n, env);
959 /***********************************************************************/
960 /* the following routines dump the nodes/irgs bracketed to graphs. */
961 /***********************************************************************/
963 /** Dumps a constant expression as entity initializer, array bound ...
965 static void dump_const_expression(ir_node *value) {
966 ir_graph *rem = current_ir_graph;
967 int rem_dump_const_local = dump_const_local;
968 dump_const_local = 0;
969 current_ir_graph = get_const_code_irg();
970 irg_walk(value, dump_const_node, NULL, NULL);
971 /* Decrease visited flag so that we walk with the same flag for the next
972 expresssion. This guarantees that we don't dump the same node twice,
973 as for const expressions cse is performed to save memory. */
974 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
975 current_ir_graph = rem;
976 dump_const_local = rem_dump_const_local;
979 /** Dump a block as graph containing its nodes.
981 * Expects to find nodes belonging to the block as list in its
983 * Dumps the edges of all nodes including itself. */
985 dump_whole_block(ir_node *block) {
987 assert(is_Block(block));
989 fprintf(F, "graph: { title: \"");
991 fprintf(F, "\" label: \"");
992 dump_node_opcode(F, block);
993 fprintf (F, " %ld", get_irn_node_nr(block));
995 if (get_opt_dump_abstvals())
996 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
998 fprintf(F, "\" status:clustered color:%s \n",
999 get_Block_matured(block) ? "yellow" : "red");
1001 /* dump the blocks edges */
1002 dump_ir_data_edges(block);
1004 /* dump the nodes that go into the block */
1005 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1007 dump_ir_data_edges(node);
1010 /* Close the vcg information for the block */
1012 dump_const_node_local(block);
1014 dump_chi_term(F, block);
1019 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1020 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
1022 dump_block_graph(ir_graph *irg) {
1024 ir_graph *rem = current_ir_graph;
1025 ir_node **arr = ird_get_irg_link(irg);
1026 current_ir_graph = irg;
1028 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1029 ir_node * node = arr[i];
1030 if (is_Block(node)) {
1031 /* Dumps the block and all the nodes in the block, which are to
1032 be found in Block->link. */
1033 dump_whole_block(node);
1035 /* Nodes that are not in a Block. */
1037 dump_ir_data_edges(node);
1041 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
1043 current_ir_graph = rem;
1046 /** Dumps an irg as a graph.
1047 * If interprocedural view edges can point to nodes out of this graph.
1049 static void dump_graph(ir_graph *irg) {
1051 fprintf(F, "graph: { title: \"");
1053 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1054 get_ent_dump_name(get_irg_ent(irg)));
1056 dump_block_graph (irg);
1058 /* Close the vcg information for the irg */
1059 fprintf(F, "}\n\n");
1062 /*******************************************************************/
1063 /* Basic type and entity nodes and edges. */
1064 /*******************************************************************/
1066 /* dumps the edges between nodes and their type or entity attributes. */
1067 static void dump_node2type_edges (ir_node *n, void *env)
1071 switch (get_irn_opcode(n)) {
1073 /* @@@ some consts have an entity */
1076 if ( (get_SymConst_kind(n) == type_tag)
1077 || (get_SymConst_kind(n) == size))
1079 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1083 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1086 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1089 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1092 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1095 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1103 static void print_type_info(type *tp) {
1104 if (get_type_state(tp) == layout_undefined) {
1105 fprintf(F, "state: layout_undefined\n");
1107 fprintf(F, "state: layout_fixed,\n");
1109 if (get_type_mode(tp))
1110 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1111 fprintf(F, "size: %dB,\n", get_type_size(tp));
1114 static void print_typespecific_info(type *tp) {
1115 switch (get_type_tpop_code(tp)) {
1118 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1125 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1126 fprintf(F, "params: %d\n", get_method_n_params(tp));
1127 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1135 case tpo_enumeration:
1149 static void print_typespecific_vcgattr(type *tp) {
1150 switch (get_type_tpop_code(tp)) {
1153 if (peculiarity_existent == get_class_peculiarity(tp))
1154 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1156 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1160 fprintf (F, " " TYPE_METH_NODE_ATTR);
1171 case tpo_enumeration:
1184 static int print_type_node(type *tp)
1188 fprintf (F, "node: {title: ");
1190 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1191 fprintf (F, " info1: \"");
1192 print_type_info(tp);
1193 print_typespecific_info(tp);
1195 print_typespecific_vcgattr(tp);
1201 #define X(a) case a: fprintf(F, #a); break
1202 void dump_entity_node(entity *ent)
1204 fprintf (F, "node: {title: \"");
1205 PRINT_ENTID(ent); fprintf(F, "\"");
1206 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1207 fprintf (F, "label: ");
1208 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1209 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1211 fprintf (F, "\nallocation: ");
1212 switch (get_entity_allocation(ent)) {
1213 X(allocation_dynamic);
1214 X(allocation_automatic);
1215 X(allocation_static);
1216 X(allocation_parameter);
1219 fprintf (F, "\nvisibility: ");
1220 switch (get_entity_visibility(ent)) {
1221 X(visibility_local);
1222 X(visibility_external_visible);
1223 X(visibility_external_allocated);
1226 fprintf (F, "\nvariability: ");
1227 switch (get_entity_variability(ent)) {
1228 X(variability_uninitialized);
1229 X(variability_initialized);
1230 X(variability_part_constant);
1231 X(variability_constant);
1234 fprintf (F, "\nvolatility: ");
1235 switch (get_entity_volatility(ent)) {
1236 X(volatility_non_volatile);
1237 X(volatility_is_volatile);
1240 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1241 fprintf(F, "\nname: %s\nld_name: %s",
1242 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1243 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1244 if (is_method_type(get_entity_type(ent))) {
1245 if (get_entity_irg(ent)) /* can be null */
1246 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1248 { fprintf (F, "\nirg = NULL"); }
1250 fprintf(F, "\"\n}\n");
1254 static void dump_enum_item(type *tp, int pos)
1257 ident *id = get_enumeration_nameid(tp, pos);
1258 tarval *tv = get_enumeration_enum(tp, pos);
1260 tarval_snprintf(buf, sizeof(buf), tv);
1261 fprintf (F, "node: {title: \"");
1262 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1263 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1264 fprintf (F, "label: ");
1265 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, id_to_str(id));
1266 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1269 /* dumps a type or entity and it's edges. */
1271 dump_type_info (type_or_ent *tore, void *env) {
1272 int i = 0; /* to shutup gcc */
1274 /* dump this type or entity */
1276 switch (get_kind(tore)) {
1279 entity *ent = (entity *)tore;
1282 dump_entity_node(ent);
1284 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1285 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1286 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1287 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1288 if(is_class_type(get_entity_owner(ent))) {
1289 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1290 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1293 /* attached subgraphs */
1294 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1295 if (is_atomic_entity(ent)) {
1296 value = get_atomic_ent_value(ent);
1298 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1299 /* DDMN(value); $$$ */
1300 dump_const_expression(value);
1303 if (is_compound_entity(ent)) {
1304 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1305 value = get_compound_ent_value(ent, i);
1307 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1308 dump_const_expression(value);
1309 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1311 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1312 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1313 get_compound_ent_value_member(ent, i), i);
1322 type *tp = (type *)tore;
1323 print_type_node(tp);
1324 /* and now the edges */
1325 switch (get_type_tpop_code(tp)) {
1328 for (i=0; i < get_class_n_supertypes(tp); i++) {
1329 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1332 for (i=0; i < get_class_n_members(tp); i++) {
1333 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1338 for (i=0; i < get_struct_n_members(tp); i++) {
1339 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1344 for (i = 0; i < get_method_n_params(tp); i++)
1346 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1348 for (i = 0; i < get_method_n_ress(tp); i++)
1350 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1355 for (i = 0; i < get_union_n_members(tp); i++)
1357 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1362 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1363 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1364 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1365 ir_node *upper = get_array_upper_bound(tp, i);
1366 ir_node *lower = get_array_lower_bound(tp, i);
1367 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1368 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1369 dump_const_expression(upper);
1370 dump_const_expression(lower);
1374 case tpo_enumeration:
1376 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1377 dump_enum_item(tp, i);
1378 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1383 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1391 break; /* case k_type */
1394 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1396 } /* switch kind_or_entity */
1399 /** For dumping class hierarchies.
1400 * Dumps a class type node and a superclass edge.
1401 * If env != null dumps entities of classes and overwrites edges.
1404 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1405 int i = 0; /* to shutup gcc */
1407 /* dump this type or entity */
1408 switch (get_kind(tore)) {
1410 entity *ent = (entity *)tore;
1411 if (get_entity_owner(ent) == get_glob_type()) break;
1412 if ((env) && is_class_type(get_entity_owner(ent))) {
1414 dump_entity_node(ent);
1416 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1417 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1419 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1422 } break; /* case k_entity */
1425 type *tp = (type *)tore;
1426 if (tp == get_glob_type()) break;
1427 switch (get_type_tpop_code(tp)) {
1429 print_type_node(tp);
1430 /* and now the edges */
1431 for (i=0; i < get_class_n_supertypes(tp); i++)
1433 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1439 break; /* case k_type */
1442 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1444 } /* switch kind_or_entity */
1447 /*******************************************************************/
1448 /* dump analysis information that is expressed in graph terms. */
1449 /*******************************************************************/
1451 /* dump out edges */
1453 dump_out_edge (ir_node *n, void* env) {
1455 for (i = 0; i < get_irn_n_outs(n); i++) {
1456 assert(get_irn_out(n, i));
1457 fprintf (F, "edge: {sourcename: \"");
1459 fprintf (F, "\" targetname: \"");
1460 PRINT_NODEID(get_irn_out(n, i));
1461 fprintf (F, "\" color: red linestyle: dashed");
1467 dump_loop_label(ir_loop *loop) {
1468 fprintf (F, "loop %d, %d sons, %d nodes",
1469 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1472 static INLINE void dump_loop_info(ir_loop *loop) {
1473 fprintf (F, " info1: \"");
1474 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1475 #if DEBUG_libfirm /* GL @@@ debug analyses */
1476 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1482 dump_loop_node(ir_loop *loop) {
1483 fprintf (F, "node: {title: \"");
1485 fprintf (F, "\" label: \"");
1486 dump_loop_label(loop);
1488 dump_loop_info(loop);
1494 dump_loop_node_edge (ir_loop *loop, int i) {
1496 fprintf (F, "edge: {sourcename: \"");
1498 fprintf (F, "\" targetname: \"");
1499 PRINT_NODEID(get_loop_node(loop, i));
1500 fprintf (F, "\" color: green");
1505 dump_loop_son_edge (ir_loop *loop, int i) {
1507 fprintf (F, "edge: {sourcename: \"");
1509 fprintf (F, "\" targetname: \"");
1510 PRINT_LOOPID(get_loop_son(loop, i));
1511 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1512 get_loop_element_pos(loop, get_loop_son(loop, i)));
1516 void dump_loops (ir_loop *loop) {
1518 /* dump this loop node */
1519 dump_loop_node(loop);
1521 /* dump edges to nodes in loop -- only if it is a real loop */
1522 if (get_loop_depth(loop) != 0) {
1523 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1524 dump_loop_node_edge(loop, i);
1527 for (i = 0; i < get_loop_n_sons(loop); i++) {
1528 dump_loops(get_loop_son(loop, i));
1529 dump_loop_son_edge(loop, i);
1534 void dump_loop_nodes_into_graph(ir_graph *irg) {
1535 ir_graph *rem = current_ir_graph;
1536 current_ir_graph = irg;
1538 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1540 current_ir_graph = rem;
1544 /************************************************************************/
1545 /* open and close vcg file */
1546 /************************************************************************/
1549 dump_vcg_header(const char *name, const char *orientation) {
1558 if (!orientation) orientation = "bottom_to_top";
1562 "graph: { title: \"ir graph of %s\"\n"
1563 "display_edge_labels: %s\n"
1564 "layoutalgorithm: mindepth\n"
1565 "manhattan_edges: yes\n"
1566 "port_sharing: no\n"
1568 "classname 1: \"Data\"\n"
1569 "classname 2: \"Block\"\n"
1570 "classname 13:\"Control Flow\"\n"
1571 "classname 14:\"Memory\"\n"
1572 "classname 15:\"Dominators\"\n"
1573 "classname 3: \"Entity type\"\n"
1574 "classname 4: \"Entity owner\"\n"
1575 "classname 5: \"Method Param\"\n"
1576 "classname 6: \"Method Res\"\n"
1577 "classname 7: \"Super\"\n"
1578 "classname 8: \"Union\"\n"
1579 "classname 9: \"Points-to\"\n"
1580 "classname 10: \"Array Element Type\"\n"
1581 "classname 11: \"Overwrites\"\n"
1582 "classname 12: \"Member\"\n"
1583 "infoname 1: \"Attribute\"\n"
1584 "infoname 2: \"Verification errors\"\n",
1585 name, label, orientation);
1587 fprintf (F, "\n"); /* a separator */
1590 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1591 const char *nm = get_irg_dump_name(irg);
1592 int len = strlen(nm), i, j;
1593 char *fname; /* filename to put the vcg information in */
1595 if (!suffix1) suffix1 = "";
1596 if (!suffix2) suffix2 = "";
1598 /** open file for vcg graph */
1599 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1601 /* strncpy (fname, nm, len); */ /* copy the filename */
1603 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1605 fname[j] = '@'; j++; fname[j] = '1'; j++;
1606 } else if (nm[i] == '@') {
1607 fname[j] = '@'; j++; fname[j] = '2'; j++;
1609 fname[j] = nm[i]; j++;
1613 strcat (fname, suffix1); /* append file suffix */
1614 strcat (fname, suffix2); /* append file suffix */
1615 strcat (fname, ".vcg"); /* append the .vcg suffix */
1616 F = fopen (fname, "w"); /* open file for writing */
1618 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1623 static void vcg_open_name (const char *name, char *suffix) {
1624 char *fname; /* filename to put the vcg information in */
1625 int i, j, len = strlen(name);
1627 if (!suffix) suffix = "";
1629 /** open file for vcg graph */
1630 fname = malloc (len * 2 + 5 + strlen(suffix));
1631 /* strcpy (fname, name);*/ /* copy the filename */
1633 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1634 if (name[i] == '/') {
1635 fname[j] = '@'; j++; fname[j] = '1'; j++;
1636 } else if (name[i] == '@') {
1637 fname[j] = '@'; j++; fname[j] = '2'; j++;
1639 fname[j] = name[i]; j++;
1643 strcat (fname, suffix);
1644 strcat (fname, ".vcg"); /* append the .vcg suffix */
1645 F = fopen (fname, "w"); /* open file for writing */
1647 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1652 static INLINE void dump_vcg_footer (void) {
1658 dump_vcg_footer(); /* print footer */
1659 fclose (F); /* close vcg file */
1662 /************************************************************************/
1663 /************************************************************************/
1664 /* Routines that dump all or parts of the firm representation to a file */
1665 /************************************************************************/
1666 /************************************************************************/
1668 /************************************************************************/
1669 /* Dump ir graphs, differnt formats and additional information. */
1670 /************************************************************************/
1672 /** Routine to dump a graph, blocks as conventional nodes.
1675 dump_ir_graph (ir_graph *irg)
1679 rem = current_ir_graph;
1681 /* printf("comparing %s %s\n", get_irg_dump_name(irg), dump_file_filter); */
1683 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1685 current_ir_graph = irg;
1686 if (interprocedural_view) suffix = "-pure-ip";
1687 else suffix = "-pure";
1688 vcg_open (irg, dump_file_suffix, suffix);
1689 dump_vcg_header(get_irg_dump_name(irg), NULL);
1691 /* walk over the graph */
1692 /* dump_whole_node must be called in post visiting predecessors */
1693 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1695 /* dump the out edges in a separate walk */
1696 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1697 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1702 current_ir_graph = rem;
1707 dump_ir_block_graph (ir_graph *irg)
1712 /* printf("comparing %s %s\n", get_irg_dump_name(irg), dump_file_filter); */
1713 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1715 if (interprocedural_view) suffix = "-ip";
1717 vcg_open (irg, dump_file_suffix, suffix);
1718 dump_vcg_header(get_irg_dump_name(irg), NULL);
1720 construct_block_lists(irg);
1722 for (i = 0; i < get_irp_n_irgs(); i++) {
1723 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1725 dump_graph(get_irp_irg(i));
1733 /** dumps a graph with type information
1736 dump_ir_graph_w_types (ir_graph *irg)
1738 ir_graph *rem = current_ir_graph;
1741 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1743 current_ir_graph = irg;
1745 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1746 else suffix = "-pure-wtypes";
1747 vcg_open (irg, dump_file_suffix, suffix);
1748 dump_vcg_header(get_irg_dump_name(irg), NULL);
1750 /* dump common ir graph */
1751 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1752 /* dump type info */
1753 type_walk_irg(irg, dump_type_info, NULL, NULL);
1754 inc_irg_visited(get_const_code_irg());
1755 /* dump edges from graph to type info */
1756 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1759 current_ir_graph = rem;
1763 dump_ir_block_graph_w_types (ir_graph *irg)
1767 ir_graph *rem = current_ir_graph;
1769 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1771 if (interprocedural_view) suffix = "-wtypes-ip";
1772 else suffix = "-wtypes";
1773 vcg_open (irg, dump_file_suffix, suffix);
1774 dump_vcg_header(get_irg_dump_name(irg), NULL);
1776 /* dump common blocked ir graph */
1777 construct_block_lists(irg);
1779 for (i = 0; i < get_irp_n_irgs(); i++) {
1780 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1782 dump_graph(get_irp_irg(i));
1787 /* dump type info */
1788 current_ir_graph = irg;
1789 type_walk_irg(irg, dump_type_info, NULL, NULL);
1790 inc_irg_visited(get_const_code_irg());
1792 /* dump edges from graph to type info */
1793 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1795 current_ir_graph = rem;
1799 /***********************************************************************/
1800 /* The following routines dump a control flow graph. */
1801 /***********************************************************************/
1804 dump_block_to_cfg (ir_node *block, void *env) {
1808 if (is_Block(block)) {
1809 /* This is a block. Dump a node for the block. */
1810 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1811 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1812 PRINT_NODEID(block);
1814 if (dump_dominator_information_flag)
1815 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1817 /* Dump the edges */
1818 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1819 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1820 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1821 fprintf (F, "edge: { sourcename: \"");
1822 PRINT_NODEID(block);
1823 fprintf (F, "\" targetname: \"");
1825 fprintf (F, "\"}\n");
1828 /* Dump dominator edge */
1829 if (dump_dominator_information_flag && get_Block_idom(block)) {
1830 pred = get_Block_idom(block);
1831 fprintf (F, "edge: { sourcename: \"");
1832 PRINT_NODEID(block);
1833 fprintf (F, "\" targetname: \"");
1835 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1841 dump_cfg (ir_graph *irg)
1843 ir_graph *rem = current_ir_graph;
1844 int ddif = dump_dominator_information_flag;
1845 int ipv = interprocedural_view;
1847 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1849 current_ir_graph = irg;
1851 vcg_open (irg, dump_file_suffix, "-cfg");
1852 dump_vcg_header(get_irg_dump_name(irg), NULL);
1854 if (interprocedural_view) {
1855 printf("Warning: dumping cfg not in interprocedural view!\n");
1856 interprocedural_view = 0;
1859 if (get_irg_dom_state(irg) != dom_consistent)
1860 dump_dominator_information_flag = 0;
1862 /* walk over the blocks in the graph */
1863 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1864 dump_node (get_irg_bad(irg));
1866 dump_dominator_information_flag = ddif;
1867 interprocedural_view = ipv;
1869 current_ir_graph = rem;
1874 /* Dump all irgs in interprocedural view to a single file. */
1875 void dump_all_cg_block_graph(void) {
1877 int rem_view = interprocedural_view;
1878 interprocedural_view = 1;
1880 vcg_open_name ("All_graphs", dump_file_suffix);
1881 dump_vcg_header("All_graphs", NULL);
1883 /* collect nodes in all irgs reachable in call graph*/
1884 for (i = 0; i < get_irp_n_irgs(); i++)
1885 ird_set_irg_link(get_irp_irg(i), NULL);
1887 cg_walk(clear_link, collect_node, NULL);
1889 /* dump all graphs */
1890 for (i = 0; i < get_irp_n_irgs(); i++) {
1891 current_ir_graph = get_irp_irg(i);
1892 assert(ird_get_irg_link(current_ir_graph));
1893 dump_graph(current_ir_graph);
1894 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1898 interprocedural_view = rem_view;
1901 /***********************************************************************/
1902 /* the following routines dumps type information without any ir nodes. */
1903 /***********************************************************************/
1906 dump_type_graph (ir_graph *irg)
1909 rem = current_ir_graph;
1911 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1913 current_ir_graph = irg;
1915 vcg_open (irg, dump_file_suffix, "-type");
1916 dump_vcg_header(get_irg_dump_name(irg), NULL);
1918 /* walk over the blocks in the graph */
1919 type_walk_irg(irg, dump_type_info, NULL, NULL);
1920 /* The walker for the const code can be called several times for the
1921 same (sub) experssion. So that no nodes are dumped several times
1922 we decrease the visited flag of the corresponding graph after each
1923 walk. So now increase it finally. */
1924 inc_irg_visited(get_const_code_irg());
1927 current_ir_graph = rem;
1931 dump_all_types (void)
1933 vcg_open_name ("All_types", dump_file_suffix);
1934 dump_vcg_header("All_types", NULL);
1935 type_walk(dump_type_info, NULL, NULL);
1936 inc_irg_visited(get_const_code_irg());
1941 dump_class_hierarchy (bool entities)
1943 vcg_open_name ("class_hierarchy", dump_file_suffix);
1944 dump_vcg_header("class_hierarchy", NULL);
1946 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1948 type_walk(dump_class_hierarchy_node, NULL, NULL);
1952 /***********************************************************************/
1953 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1955 /* dump_ir_block_graph */
1957 /* dump_type_graph */
1958 /* dump_ir_graph_w_types */
1959 /***********************************************************************/
1961 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1963 for (i=0; i < get_irp_n_irgs(); i++) {
1964 dmp_grph(get_irp_irg(i));
1969 /**********************************************************************************
1970 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1971 * packed together in one subgraph *
1972 **********************************************************************************/
1976 void dump_loops_standalone (ir_loop *loop) {
1977 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
1979 ir_loop *son = NULL;
1981 /* Dump a new loop node. */
1982 dump_loop_node(loop);
1984 /* Dump the loop elements. */
1986 for(i = 0; i < get_loop_n_elements(loop); i++)
1988 le = get_loop_element(loop, i);
1990 if (get_kind(son) == k_ir_loop) {
1992 /* We are a loop son -> Recurse */
1994 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
1995 fprintf(F, "\" }\n");
1996 fprintf (F, "edge: {sourcename: \"");
1998 fprintf (F, "\" targetname: \"");
2000 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2001 loop_node_started = 0;
2003 dump_loop_son_edge(loop, son_number++);
2004 dump_loops_standalone(son);
2007 /* We are a loop node -> Collect firm nodes */
2009 ir_node *n = le.node;
2011 if (!loop_node_started) {
2012 /* Start a new node which contains all firm nodes of the current loop */
2013 fprintf (F, "node: { title: \"");
2015 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2016 loop_node_started = 1;
2022 dump_node_opcode(F, n);
2024 dump_node_typeinfo(n);
2026 dump_node_nodeattr(n);
2027 fprintf (F, " %ld", get_irn_node_nr(n));
2031 if (loop_node_started) {
2032 fprintf(F, "\" }\n");
2033 fprintf (F, "edge: {sourcename: \"");
2035 fprintf (F, "\" targetname: \"");
2037 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2038 loop_node_started = 0;
2042 void dump_loop_tree(ir_graph *irg, char *suffix)
2044 ir_graph *rem = current_ir_graph;
2045 int el_rem = edge_label;
2048 /* @@@ AS: What does that do? */
2049 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
2051 current_ir_graph = irg;
2053 vcg_open(irg, suffix, "-looptree");
2054 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
2056 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
2060 edge_label = el_rem;
2061 current_ir_graph = rem;
2065 /*******************************************************************************/
2066 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2067 /*******************************************************************************/
2069 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
2070 int i, son_number = 0, node_number = 0;
2072 if (dump_loop_information_flag) dump_loop_node(loop);
2074 for (i = 0; i < get_loop_n_elements(loop); i++) {
2075 loop_element le = get_loop_element(loop, i);
2076 if (*(le.kind) == k_ir_loop) {
2077 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
2079 collect_nodeloop(le.son, loopnodes);
2081 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
2082 eset_insert(loopnodes, le.node);
2087 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2090 for(i = 0; i < get_loop_n_elements(loop); i++) {
2091 loop_element le = get_loop_element(loop, i);
2092 if (*(le.kind) == k_ir_loop) {
2094 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2096 if (is_Block(le.node)) start = 0; else start = -1;
2097 for (j = start; j < get_irn_arity(le.node); j++) {
2098 ir_node *pred = get_irn_n(le.node, j);
2099 if (!eset_contains(loopnodes, pred)) {
2100 eset_insert(extnodes, pred);
2101 if (!is_Block(pred)) {
2102 pred = get_nodes_block(pred);
2103 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2111 void dump_loop (ir_loop *l, char *suffix) {
2113 eset *loopnodes = eset_create();
2114 eset *extnodes = eset_create();
2117 sprintf(name, "loop_%d", get_loop_loop_nr(l));
2118 vcg_open_name (name, suffix);
2119 dump_vcg_header(name, NULL);
2121 /* collect all nodes to dump */
2122 collect_nodeloop(l, loopnodes);
2123 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2125 /* build block lists */
2126 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2127 set_irn_link(n, NULL);
2128 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2129 set_irn_link(n, NULL);
2130 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2132 b = get_nodes_block(n);
2133 set_irn_link(n, get_irn_link(b));
2136 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2138 b = get_nodes_block(n);
2139 set_irn_link(n, get_irn_link(b));
2143 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2145 fprintf(F, "graph: { title: \"");
2147 fprintf(F, "\" label: \"");
2148 dump_node_opcode(F, b);
2149 fprintf (F, " %ld", get_irn_node_nr(b));
2150 fprintf(F, "\" status:clustered color:yellow\n");
2152 /* dump the blocks edges */
2153 dump_ir_data_edges(b);
2155 /* dump the nodes that go into the block */
2156 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2157 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2159 overrule_nodecolor = NULL;
2160 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2163 /* Close the vcg information for the block */
2165 dump_const_node_local(b);
2168 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2170 fprintf(F, "graph: { title: \"");
2172 fprintf(F, "\" label: \"");
2173 dump_node_opcode(F, b);
2174 fprintf (F, " %ld", get_irn_node_nr(b));
2175 fprintf(F, "\" status:clustered color:lightblue\n");
2177 /* dump the nodes that go into the block */
2178 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2179 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2181 overrule_nodecolor = NULL;
2182 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2185 /* Close the vcg information for the block */
2187 dump_const_node_local(b);
2191 eset_destroy(loopnodes);
2192 eset_destroy(extnodes);