fix a few errors and warnings in the new pass code; improve some comments
[libfirm] / ir / common / irtools.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     Some often needed tool-functions
23  * @author    Michael Beck
24  * @version   $Id$
25  */
26 #include "config.h"
27
28 #include "pset.h"
29
30 #include <stdlib.h>
31 #include "irnode_t.h"
32 #include "irbackedge_t.h"
33 #include "irtools.h"
34 #include "irprintf.h"
35 #include "irpass_t.h"
36
37 /* the famous clear_link implementation. */
38 void firm_clear_link(ir_node *n, void *env) {
39         (void) env;
40         set_irn_link(n, NULL);
41 }
42
43 /* the famous clear_node_and_phi_links() implementation. */
44 void firm_clear_node_and_phi_links(ir_node *n, void *env) {
45         (void) env;
46         set_irn_link(n, NULL);
47         if (is_Block(n))
48                 set_Block_phis(n, NULL);
49         else if (is_Phi(n))
50                 set_Phi_next(n, NULL);
51 }
52
53 /*
54  * Copies a node to a new irg. The Ins of the new node point to
55  * the predecessors on the old irg.  n->link points to the new node.
56  *
57  * Does NOT copy standard nodes like Start, End etc that are fixed
58  * in an irg. Instead, the corresponding nodes of the new irg are returned.
59  * Note further, that the new nodes have no block.
60  */
61 void
62 copy_irn_to_irg(ir_node *n, ir_graph *irg) {
63         ir_op *op = get_irn_op(n);
64         ir_graph *old_irg;
65         ir_node *nn = NULL;
66
67         /* do not copy standard nodes */
68         if (op == op_Bad)
69                 nn = get_irg_bad(irg);
70         else if (op == op_NoMem)
71                 n = get_irg_no_mem(irg);
72         else if (op == op_Block) {
73                 old_irg = get_irn_irg(n);
74
75                 if (n == get_irg_start_block(old_irg))
76                         nn = get_irg_start_block(irg);
77                 else if (n == get_irg_end_block(old_irg))
78                         nn = get_irg_end_block(irg);
79         }
80         else if (op == op_Start)
81                 nn = get_irg_start(irg);
82         else if (op == op_End)
83                 nn = get_irg_end(irg);
84         else if (op == op_Proj) {
85                 old_irg = get_irn_irg(n);
86
87                 if (n == get_irg_initial_exec(old_irg))
88                         nn = get_irg_initial_exec(irg);
89                 else if (n == get_irg_frame(old_irg))
90                         nn = get_irg_frame(irg);
91                 else if (n == get_irg_initial_mem(old_irg))
92                         nn = get_irg_initial_mem(irg);
93                 else if (n == get_irg_args(old_irg))
94                         nn = get_irg_args(irg);
95         }
96
97         if (nn) {
98                 set_irn_link(n, nn);
99                 return;
100         }
101
102         nn = new_ir_node(get_irn_dbg_info(n),
103                          irg,
104                          NULL,            /* no block yet, will be set later */
105                          op,
106                          get_irn_mode(n),
107                          get_irn_arity(n),
108                          get_irn_in(n) + 1);
109
110
111         /* Copy the attributes.  These might point to additional data.  If this
112            was allocated on the old obstack the pointers now are dangling.  This
113            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
114         copy_node_attr(n, nn);
115         new_backedge_info(nn);
116         set_irn_link(n, nn);
117
118         /* fix the irg for blocks */
119         if (is_Block(nn)) {
120                 nn->attr.block.irg.irg = irg;
121
122                 /* we cannot allow blocks WITHOUT macroblock input */
123                 set_Block_MacroBlock(nn, get_Block_MacroBlock(n));
124         }
125 }
126
127 /*
128  * Creates an exact copy of a node.
129  * The copy resides in the same graph in the same block.
130  */
131 ir_node *exact_copy(const ir_node *n) {
132         ir_graph *irg = get_irn_irg(n);
133         ir_node *res, *block = NULL;
134
135         if (is_no_Block(n))
136                 block = get_nodes_block(n);
137
138         res = new_ir_node(get_irn_dbg_info(n),
139                 irg,
140                 block,
141                 get_irn_op(n),
142                 get_irn_mode(n),
143                 get_irn_arity(n),
144                 get_irn_in(n) + 1);
145
146
147         /* Copy the attributes.  These might point to additional data.  If this
148            was allocated on the old obstack the pointers now are dangling.  This
149            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
150         copy_node_attr(n, res);
151         new_backedge_info(res);
152
153         if (is_Block(n)) {
154                 set_Block_MacroBlock(res, get_Block_MacroBlock(n));
155         }
156         return res;
157 }
158
159 /*
160  * Dump a pset containing Firm objects.
161  */
162 void firm_pset_dump(pset *set) {
163         void *obj;
164
165         foreach_pset(set, obj) {
166                 ir_fprintf(stderr, "%+F\n", obj);
167         }
168 }
169
170 /**
171  * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
172  */
173 static int void_graph_wrapper(ir_graph *irg, void *context) {
174         void (*function)(ir_graph *irg) = context;
175         function(irg);
176         return 0;
177 }  /* void_graph_wrapper */
178
179 /* Creates an ir_graph pass for running void function(ir_graph *irg). */
180 ir_graph_pass_t *def_graph_pass(
181         const char *name, void (*function)(ir_graph *irg))
182 {
183         struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
184
185         pass->kind       = k_ir_graph_pass;
186         pass->run_on_irg = void_graph_wrapper;
187         pass->context    = function;
188         pass->name       = name;
189
190         INIT_LIST_HEAD(&pass->list);
191
192         return pass;
193 }  /* def_graph_pass */
194
195 /**
196  * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
197  */
198 static int int_graph_wrapper(ir_graph *irg, void *context) {
199         int (*function)(ir_graph *irg) = context;
200         return function(irg);
201 }  /* int_graph_wrapper */
202
203 /* Creates an ir_graph pass for running void function(ir_graph *irg). */
204 ir_graph_pass_t *def_graph_pass_ret(
205                 const char *name, int (*function)(ir_graph *irg))
206 {
207         struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
208
209         pass->kind       = k_ir_graph_pass;
210         pass->run_on_irg = int_graph_wrapper;
211         pass->context    = function;
212         pass->name       = name;
213
214         INIT_LIST_HEAD(&pass->list);
215
216         return pass;
217 }  /* def_graph_pass_ret */
218
219 /**
220  * Wrapper for running void function(void) as an ir_prog pass.
221  */
222 static int void_prog_wrapper(ir_prog *irp, void *context) {
223         void (*function)(void) = context;
224
225         (void)irp;
226         function();
227         return 0;
228 }  /* void_graph_wrapper */
229
230 /* Creates an ir_prog pass for running void function(void). */
231 ir_prog_pass_t *def_prog_pass(
232         const char *name,
233         void (*function)(void))
234 {
235         struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
236
237         pass->kind          = k_ir_prog_pass;
238         pass->run_on_irprog = void_prog_wrapper;
239         pass->context       = function;
240         pass->name          = name;
241
242         INIT_LIST_HEAD(&pass->list);
243
244         return pass;
245 }  /* def_prog_pass */