Simplify handling of unreachable code
[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         size_t node_slots;       /**< The number of allocated node slots. */
52         size_t node_slots_used;  /**< The number of used node slots, i.e. nodes that have node data. */
53         size_t node_map_bytes;   /**< Number of used bytes for the node map. */
54         size_t 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                                                 phase_irn_reinit *reinit)
74 {
75         int idx;
76
77         if (! phase->data_init)
78                 return;
79
80         idx = get_irn_idx(irn);
81         if (phase->data_ptr[idx])
82                 phase->data_ptr[idx] = reinit(phase, irn, phase->data_ptr[idx]);
83 }
84
85 /**
86  * Returns the first node of the phase having some data assigned.
87  *
88  * @param phase  The phase.
89  *
90  * @return The first irn having some data assigned, NULL otherwise
91  */
92 ir_node *phase_get_first_node(const ir_phase *phase);
93
94 /**
95  * Returns the next node after @p start having some data assigned.
96  *
97  * @param phase  The phase.
98  * @param start  The node to start from
99  *
100  * @return The next node after start having some data assigned, NULL otherwise
101  */
102 ir_node *phase_get_next_node(const ir_phase *phase, ir_node *start);
103
104 /**
105  * Convenience macro to iterate over all nodes of a phase
106  * having some data assigned.
107  *
108  * @param phase  The phase.
109  * @param irn    A local variable that will hold the current node inside the loop.
110  */
111 #define foreach_phase_irn(phase, irn) \
112         for (irn = phase_get_first_node(phase); irn; irn = phase_get_next_node(phase, irn))
113
114 /**
115  * Get the irg the phase runs on.
116  *
117  * @param phase  The phase.
118  */
119 static inline ir_graph *phase_get_irg(const ir_phase *phase)
120 {
121         return phase->irg;
122 }
123
124 /**
125  * Get private data pointer as passed on creating the phase.
126  *
127  * @param phase  The phase.
128  */
129 static inline void *phase_get_private(const ir_phase *phase)
130 {
131         return phase->priv;
132 }
133
134 /**
135  * Attach pointer with private data to phase
136  */
137 static inline void phase_set_private(ir_phase *phase, void *priv)
138 {
139         phase->priv = priv;
140 }
141
142 static inline void *phase_alloc(ir_phase *phase, size_t size)
143 {
144         return obstack_alloc(&phase->obst, size);
145 }
146
147 /**
148  * Get the obstack of a phase.
149  *
150  * @param phase  The phase.
151  */
152 static inline struct obstack *phase_obst(ir_phase *phase)
153 {
154         return &phase->obst;
155 }
156
157 /**
158  * Get the phase node data for an irn.
159  *
160  * @param phase   The phase.
161  * @param irn     The irn to get data for.
162  *
163  * @return A pointer to the node data or NULL if the irn has no phase data allocated yet.
164  */
165 static inline void *phase_get_irn_data(const ir_phase *ph, const ir_node *irn)
166 {
167         unsigned idx = get_irn_idx(irn);
168         return idx < ph->n_data_ptr ? ph->data_ptr[idx] : NULL;
169 }
170
171 /**
172  * This is private and just here for performance reasons.
173  */
174 static inline void private_phase_enlarge(ir_phase *phase, unsigned max_idx)
175 {
176         unsigned last_irg_idx = get_irg_last_idx(phase->irg);
177         size_t old_cap        = phase->n_data_ptr;
178         size_t new_cap;
179
180         /* make the maximum index at least as big as the largest index in the graph. */
181         max_idx = MAX(max_idx, last_irg_idx);
182         new_cap = (size_t) (max_idx + 256);
183
184         phase->data_ptr = XREALLOC(phase->data_ptr, void*, new_cap);
185
186         /* initialize the newly allocated memory. */
187         memset(phase->data_ptr + old_cap, 0, (new_cap - old_cap) * sizeof(phase->data_ptr[0]));
188         phase->n_data_ptr = new_cap;
189 }
190
191 /*
192  * This is private and only here for performance reasons.
193  */
194 static inline void private_phase_assure_capacity(ir_phase *ph, unsigned max_idx)
195 {
196         if (max_idx >= ph->n_data_ptr)
197                 private_phase_enlarge(ph, max_idx);
198 }
199
200
201 /**
202  * Get or set phase data for an irn.
203  *
204  * @param phase  The phase.
205  * @param irn    The irn to get (or set) node data for.
206  *
207  * @return A (non-NULL) pointer to phase data for the irn. Either existent one or newly allocated one.
208  */
209 static inline void *phase_get_or_set_irn_data(ir_phase *ph, const ir_node *irn)
210 {
211         unsigned idx = get_irn_idx(irn);
212         void *res;
213
214         /* Assure that there's a sufficient amount of slots. */
215         private_phase_assure_capacity(ph, idx + 1);
216
217         res = ph->data_ptr[idx];
218
219         /* If there has no irn data allocated yet, do that now. */
220         if(!res) {
221                 phase_irn_init *data_init = ph->data_init;
222
223                 /* call the node data structure allocator/constructor. */
224                 res = ph->data_ptr[idx] = data_init(ph, irn);
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  * convenience function that returns phase information attached to a node
255  */
256 static inline void *get_irn_phase_info(const ir_node *irn, ir_phase_id id)
257 {
258         const ir_graph *irg = get_irn_irg(irn);
259         const ir_phase *ph  = irg_get_phase(irg, id);
260         return phase_get_irn_data(ph, irn);
261 }
262
263 /**
264  * Get or set information a phase holds about a node.
265  * If the given phase does not hold information of the node,
266  * the information structure will be created, initialized (see the data_init
267  * 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,
279                                        void *data)
280 {
281         const ir_graph *irg = get_irn_irg(irn);
282         ir_phase *ph  = irg_get_phase(irg, id);
283         return phase_set_irn_data(ph, irn, data);
284 }
285
286 #endif