200faf28ae6b8239b10dd9f2339a9cf76f33aed0
[libfirm] / ir / be / beutil.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Contains some useful function for the backend.
23  * @author      Sebastian Hack
24  * @version     $Id$
25  */
26 #include "config.h"
27
28 #include <stdio.h>
29
30 #include "pset.h"
31
32 #include "irgraph.h"
33 #include "irgwalk.h"
34 #include "irdump_t.h"
35 #include "irdom_t.h"
36 #include "ircons.h"
37 #include "iropt.h"
38 #include "irgopt.h"
39 #include "irtools.h"
40 #include "irprintf.h"
41 #include "iredges_t.h"
42
43 #include "beutil.h"
44 #include "besched.h"
45 #include "bearch.h"
46
47 /**
48  * Edge hook to dump the schedule edges.
49  */
50 static int sched_edge_hook(FILE *F, ir_node *irn)
51 {
52         if (is_Proj(irn))
53                 return 1;
54         if (sched_is_scheduled(irn) && sched_has_prev(irn)) {
55                 ir_node *prev = sched_prev(irn);
56                 fprintf(F, "edge:{sourcename:\"");
57                 PRINT_NODEID(irn);
58                 fprintf(F, "\" targetname:\"");
59                 PRINT_NODEID(prev);
60                 fprintf(F, "\" color:magenta}\n");
61         }
62         return 1;
63 }
64
65 void dump_ir_block_graph_sched(ir_graph *irg, const char *suffix)
66 {
67         DUMP_NODE_EDGE_FUNC old = get_dump_node_edge_hook();
68
69         dump_consts_local(0);
70         if (have_sched_info(irg))
71                 set_dump_node_edge_hook(sched_edge_hook);
72         dump_ir_block_graph(irg, suffix);
73         set_dump_node_edge_hook(old);
74 }
75
76 void dump_ir_extblock_graph_sched(ir_graph *irg, const char *suffix)
77 {
78         DUMP_NODE_EDGE_FUNC old = get_dump_node_edge_hook();
79
80         dump_consts_local(0);
81         if (have_sched_info(irg))
82                 set_dump_node_edge_hook(sched_edge_hook);
83         dump_ir_extblock_graph(irg, suffix);
84         set_dump_node_edge_hook(old);
85 }
86
87 /**
88  * Dumps a graph and numbers all dumps.
89  * @param irg    The graph
90  * @param suffix A suffix to its file name.
91  * @param dumper The dump function
92  */
93 void be_dump(ir_graph *irg, const char *suffix, void (*dumper)(ir_graph *, const char *))
94 {
95         static ir_graph *last_irg = NULL;
96         static int       nr       = 0;
97         char             buf[128];
98
99         if (irg != last_irg) {
100                 last_irg = irg;
101                 nr       = strcmp(suffix, "-abi") ? 0 : 1;
102         }
103
104         snprintf(buf, sizeof(buf), "-%02d%s", nr++, suffix);
105         buf[sizeof(buf) - 1] = '\0';
106         dumper(irg, buf);
107 }
108
109 void be_clear_links(ir_graph *irg)
110 {
111         irg_walk_graph(irg, firm_clear_link, NULL, NULL);
112 }
113
114 static void count_num_reachable_nodes(ir_node *irn, void *env)
115 {
116         int *num = env;
117         (*num)++;
118         (void) irn;
119 }
120
121 unsigned get_num_reachable_nodes(ir_graph *irg)
122 {
123         int num = 0;
124         irg_walk_graph(irg, count_num_reachable_nodes, NULL, &num);
125         return num;
126 }
127
128 /**
129  * Gets the Proj with number pn from irn.
130  */
131 ir_node *be_get_Proj_for_pn(const ir_node *irn, long pn)
132 {
133         const ir_edge_t *edge;
134         ir_node         *proj;
135         assert(get_irn_mode(irn) == mode_T && "need mode_T");
136
137         foreach_out_edge(irn, edge) {
138                 proj = get_edge_src_irn(edge);
139
140                 if (is_Proj(proj) && get_Proj_proj(proj) == pn)
141                         return proj;
142         }
143
144         return NULL;
145 }
146
147 FILE *be_ffopen(const char *base, const char *ext, const char *mode)
148 {
149         FILE *out;
150         char buf[1024];
151
152         snprintf(buf, sizeof(buf), "%s.%s", base, ext);
153         buf[sizeof(buf) - 1] = '\0';
154         if (! (out = fopen(buf, mode))) {
155                 fprintf(stderr, "Cannot open file %s in mode %s\n", buf, mode);
156                 return NULL;
157         }
158         return out;
159 }
160
161 static void add_to_postorder(ir_node *block, void *data)
162 {
163         ir_node ***list = (ir_node***) data;
164         ARR_APP1(ir_node*, *list, block);
165 }
166
167 ir_node **be_get_cfgpostorder(ir_graph *irg)
168 {
169         ir_node **list      = NEW_ARR_F(ir_node*, 0);
170         ir_node  *end_block = get_irg_end_block(irg);
171
172         /* end block may be unreachable in case of endless loops */
173         if (get_Block_n_cfgpreds(end_block) == 0)
174                 ARR_APP1(ir_node*, list, end_block);
175
176         /* walk blocks */
177         irg_block_edges_walk(get_irg_start_block(irg), NULL, add_to_postorder,
178                              &list);
179
180         return list;
181 }
182
183 ir_node *get_first_block_succ(const ir_node *block)
184 {
185         const ir_edge_t *edge = get_irn_out_edge_first_kind(block, EDGE_KIND_BLOCK);
186         assert(edge != NULL);
187         return get_edge_src_irn(edge);
188 }