automatically generate most getter/setter functions of firm nodes
[libfirm] / ir / ir / irphase_t.h
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   Phase information handling using node indexes.
23  * @author  Sebastian Hack
24  * @version $Id$
25  */
26 #ifndef FIRM_IR_PHASE_T_H
27 #define FIRM_IR_PHASE_T_H
28
29 #include "firm_types.h"
30 #include "obst.h"
31 #include "irgraph_t.h"
32 #include "irtools.h"
33 #include "irphase.h"
34
35 /**
36  * A phase object.
37  */
38 struct ir_phase {
39         void           **data_ptr;      /**< Map node indexes to irn data on the obstack. */
40         ir_graph        *irg;           /**< The irg this phase will we applied to. */
41         phase_irn_init  *data_init;     /**< A callback that is called to initialize newly created node data. */
42         size_t           n_data_ptr;    /**< The length of the data_ptr array. */
43         struct obstack   obst;          /**< The obstack where the irn phase data will be stored on. */
44         void            *priv;          /**< Some pointer private to the user of the phase. */
45 };
46
47 /**
48  * For statistics: A type containing statistic data of a phase object.
49  */
50 typedef struct {
51         unsigned node_slots;       /**< The number of allocated node slots. */
52         unsigned node_slots_used;  /**< The number of used node slots, i.e. nodes that have node data. */
53         unsigned node_map_bytes;   /**< Number of used bytes for the node map. */
54         unsigned overall_bytes;    /**< Overall number of used bytes for the phase. */
55 } phase_stat_t;
56
57 /**
58  * Collect Phase statistics.
59  *
60  * @param phase  The phase.
61  * @param stat   Will be filled with the statistical data.
62  */
63 phase_stat_t *phase_stat(const ir_phase *phase, phase_stat_t *stat);
64
65
66 /**
67  * Re-initialize the irn data for the given node.
68  *
69  * @param phase  The phase.
70  * @param irn    The irn.
71  */
72 static inline void phase_reinit_single_irn_data(ir_phase *phase, ir_node *irn)
73 {
74         int idx;
75
76         if (! phase->data_init)
77                 return;
78
79         idx = get_irn_idx(irn);
80         if (phase->data_ptr[idx])
81                 phase->data_init(phase, irn, phase->data_ptr[idx]);
82 }
83
84 /**
85  * Returns the first node of the phase having some data assigned.
86  *
87  * @param phase  The phase.
88  *
89  * @return The first irn having some data assigned, NULL otherwise
90  */
91 ir_node *phase_get_first_node(const ir_phase *phase);
92
93 /**
94  * Returns the next node after @p start having some data assigned.
95  *
96  * @param phase  The phase.
97  * @param start  The node to start from
98  *
99  * @return The next node after start having some data assigned, NULL otherwise
100  */
101 ir_node *phase_get_next_node(const ir_phase *phase, ir_node *start);
102
103 /**
104  * Convenience macro to iterate over all nodes of a phase
105  * having some data assigned.
106  *
107  * @param phase  The phase.
108  * @param irn    A local variable that will hold the current node inside the loop.
109  */
110 #define foreach_phase_irn(phase, irn) \
111         for (irn = phase_get_first_node(phase); irn; irn = phase_get_next_node(phase, irn))
112
113 /**
114  * Get the irg the phase runs on.
115  *
116  * @param phase  The phase.
117  */
118 static inline ir_graph *phase_get_irg(const ir_phase *phase)
119 {
120         return phase->irg;
121 }
122
123 /**
124  * Get private data pointer as passed on creating the phase.
125  *
126  * @param phase  The phase.
127  */
128 static inline void *phase_get_private(const ir_phase *phase)
129 {
130         return phase->priv;
131 }
132
133 /**
134  * Attach pointer with private data to phase
135  */
136 static inline void phase_set_private(ir_phase *phase, void *priv)
137 {
138         phase->priv = priv;
139 }
140
141 static inline void *phase_alloc(ir_phase *phase, size_t size)
142 {
143         return obstack_alloc(&phase->obst, size);
144 }
145
146 /**
147  * Get the obstack of a phase.
148  *
149  * @param phase  The phase.
150  */
151 static inline struct obstack *phase_obst(ir_phase *phase)
152 {
153         return &phase->obst;
154 }
155
156 /**
157  * Get the phase node data for an irn.
158  *
159  * @param phase   The phase.
160  * @param irn     The irn to get data for.
161  *
162  * @return A pointer to the node data or NULL if the irn has no phase data allocated yet.
163  */
164 static inline void *phase_get_irn_data(const ir_phase *ph, const ir_node *irn)
165 {
166         unsigned idx = get_irn_idx(irn);
167         return idx < ph->n_data_ptr ? ph->data_ptr[idx] : NULL;
168 }
169
170 /**
171  * This is private and just here for performance reasons.
172  */
173 static inline void private_phase_enlarge(ir_phase *phase, unsigned max_idx)
174 {
175         unsigned last_irg_idx = get_irg_last_idx(phase->irg);
176         size_t old_cap        = phase->n_data_ptr;
177         size_t new_cap;
178
179         /* make the maximum index at least as big as the largest index in the graph. */
180         max_idx = MAX(max_idx, last_irg_idx);
181         new_cap = (size_t) (max_idx + 256);
182
183         phase->data_ptr = XREALLOC(phase->data_ptr, void*, new_cap);
184
185         /* initialize the newly allocated memory. */
186         memset(phase->data_ptr + old_cap, 0, (new_cap - old_cap) * sizeof(phase->data_ptr[0]));
187         phase->n_data_ptr = new_cap;
188 }
189
190 /*
191  * This is private and only here for performance reasons.
192  */
193 static inline void private_phase_assure_capacity(ir_phase *ph, unsigned max_idx)
194 {
195         if (max_idx >= ph->n_data_ptr)
196                 private_phase_enlarge(ph, max_idx);
197 }
198
199
200 /**
201  * Get or set phase data for an irn.
202  *
203  * @param phase  The phase.
204  * @param irn    The irn to get (or set) node data for.
205  *
206  * @return A (non-NULL) pointer to phase data for the irn. Either existent one or newly allocated one.
207  */
208 static inline void *phase_get_or_set_irn_data(ir_phase *ph, const ir_node *irn)
209 {
210         unsigned idx = get_irn_idx(irn);
211         void *res;
212
213         /* Assure that there's a sufficient amount of slots. */
214         private_phase_assure_capacity(ph, idx + 1);
215
216         res = ph->data_ptr[idx];
217
218         /* If there has no irn data allocated yet, do that now. */
219         if(!res) {
220                 phase_irn_init *data_init = ph->data_init;
221
222                 /* call the node data structure allocator/constructor. */
223                 res = ph->data_ptr[idx] = data_init(ph, irn, NULL);
224
225         }
226         return res;
227 }
228
229 /**
230  * Set the node data for an irn.
231  *
232  * @param phase  The phase.
233  * @param irn    The node.
234  * @param data   The node data.
235  *
236  * @return The old data or NULL if there was none.
237  */
238 static inline void *phase_set_irn_data(ir_phase *ph, const ir_node *irn,
239                                        void *data)
240 {
241         unsigned idx = get_irn_idx(irn);
242         void *res;
243
244         /* Assure that there's a sufficient amount of slots. */
245         private_phase_assure_capacity(ph, idx + 1);
246
247         res = ph->data_ptr[idx];
248         ph->data_ptr[idx] = data;
249
250         return res;
251 }
252
253
254 /**
255  * convenience function that returns phase information attached to a node
256  */
257 static inline void *get_irn_phase_info(const ir_node *irn, ir_phase_id id)
258 {
259         const ir_graph *irg = get_irn_irg(irn);
260         const ir_phase *ph  = irg_get_phase(irg, id);
261         return phase_get_irn_data(ph, irn);
262 }
263
264 /**
265  * Get or set information a phase holds about a node.
266  * If the given phase does not hold information of the node,
267  * the information structure will be created, initialized (see the data_init function of ir_phase), and returned.
268  * @param irn The node.
269  * @param id  The ID of the phase.
270  */
271 static inline void *get_or_set_irn_phase_info(const ir_node *irn, ir_phase_id id)
272 {
273         const ir_graph *irg = get_irn_irg(irn);
274         ir_phase *ph  = irg_get_phase(irg, id);
275         return phase_get_or_set_irn_data(ph, irn);
276 }
277
278 static inline void *set_irn_phase_info(const ir_node *irn, ir_phase_id id, void *data)
279 {
280         const ir_graph *irg = get_irn_irg(irn);
281         ir_phase *ph  = irg_get_phase(irg, id);
282         return phase_set_irn_data(ph, irn, data);
283 }
284
285
286
287
288 #endif