for i in *.[ch]; do sed -e 's/Copyrigth/Copyright/g' -i modeconv.h; done
[libfirm] / ir / adt / array.h
1 /*
2  * Copyright (C) 1995-2007 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     Dynamic and flexible arrays for C.
23  * @author    Markus Armbruster
24  * @version   $Id$
25  */
26 #ifndef FIRM_ADT_ARRAY_H
27 #define FIRM_ADT_ARRAY_H
28
29 #include <assert.h>
30 #include <stddef.h>
31 #include <obstack.h>
32
33 #include "fourcc.h"
34 #include "align.h"
35 #include "xmalloc.h"
36
37 #define ARR_D_MAGIC     FOURCC('A','R','R','D')
38 #define ARR_A_MAGIC     FOURCC('A','R','R','A')
39 #define ARR_F_MAGIC     FOURCC('A','R','R','F')
40
41 /**
42  * Creates a flexible array.
43  *
44  * @param type     The element type of the new array.
45  * @param nelts    a size_t expression evaluating to the number of elements
46  *
47  * This macro creates a flexible array of a given type at runtime.
48  * The size of the array can be changed later.
49  *
50  * @return A pointer to the flexible array (can be used as a pointer to the
51  *         first element of this array).
52  */
53 #define NEW_ARR_F(type, nelts)                                          \
54   ((type *)_new_arr_f ((nelts), sizeof(type) * (nelts)))
55
56 /**
57  * Creates a new flxible array with the same number of elements as a
58  * given one.
59  *
60  * @param type     The element type of the new array.
61  * @param arr      An array from which the number of elements will be taken
62  *
63  * This macro creates a flexible array of a given type at runtime.
64  * The size of the array can be changed later.
65  *
66  * @return A pointer to the flexible array (can be used as a pointer to the
67  *         first element of this array).
68  */
69 #define CLONE_ARR_F(type, arr)                  \
70   NEW_ARR_F (type, ARR_LEN ((arr)))
71
72 /**
73  * Duplicates an array and returns the new flexible one.
74  *
75  * @param type     The element type of the new array.
76  * @param arr      An array from which the elements will be duplicated
77  *
78  * This macro creates a flexible array of a given type at runtime.
79  * The size of the array can be changed later.
80  *
81  * @return A pointer to the flexible array (can be used as a pointer to the
82  *         first element of this array).
83  */
84 #define DUP_ARR_F(type, arr)                                                    \
85   memcpy (CLONE_ARR_F (type, (arr)), (arr), sizeof(type) * ARR_LEN((arr)))
86
87 /**
88  * Delete a flexible array.
89  *
90  * @param arr    The flexible array.
91  */
92 #define DEL_ARR_F(arr) (_del_arr_f ((arr)))
93
94 /**
95  * Creates a dynamic array on an obstack.
96  *
97  * @param type     The element type of the new array.
98  * @param obstack  A struct obstack * were the data will be allocated
99  * @param nelts    A size_t expression evaluating to the number of elements
100  *
101  * This macro creates a dynamic array of a given type at runtime.
102  * The size of the array cannot be changed later.
103  *
104  * @return A pointer to the dynamic array (can be used as a pointer to the
105  *         first element of this array).
106  */
107 #define NEW_ARR_D(type, obstack, nelts)                                 \
108   (  nelts                                                              \
109    ? (type *)_new_arr_d ((obstack), (nelts), sizeof(type) * (nelts))    \
110    : (type *)arr_mt_descr.v.elts)
111
112 /**
113  * Creates a new dynamic array with the same number of elements as a
114  * given one.
115  *
116  * @param type     The element type of the new array.
117  * @param obstack  An struct obstack * were the data will be allocated
118  * @param arr      An array from which the number of elements will be taken
119  *
120  * This macro creates a dynamic array of a given type at runtime.
121  * The size of the array cannot be changed later.
122  *
123  * @return A pointer to the dynamic array (can be used as a pointer to the
124  *         first element of this array).
125  */
126 #define CLONE_ARR_D(type, obstack, arr)         \
127   NEW_ARR_D (type, (obstack), ARR_LEN ((arr)))
128
129 /**
130  * Duplicates an array and returns the new dynamic one.
131  *
132  * @param type     The element type of the new array.
133  * @param obstack  An struct obstack * were the data will be allocated
134  * @param arr      An array from which the elements will be duplicated
135  *
136  * This macro creates a dynamic array of a given type at runtime.
137  * The size of the array cannot be changed later.
138  *
139  * @return A pointer to the dynamic array (can be used as a pointer to the
140  *         first element of this array).
141  */
142 #define DUP_ARR_D(type, obstack, arr)                                                   \
143   memcpy (CLONE_ARR_D (type, (obstack), (arr)), (arr), sizeof(type) * ARR_LEN ((arr)))
144
145 /**
146  * Create an automatic array which will be deleted at return from function.
147  * Beware, the data will be allocated on the function stack!
148  *
149  * @param type     The element type of the new array.
150  * @param var      A lvalue of type (type *) which will hold the new array.
151  * @param n        number of elements in this array.
152  *
153  * This macro creates a dynamic array on the functions stack of a given type at runtime.
154  * The size of the array cannot be changed later.
155  */
156 #define NEW_ARR_A(type, var, n)                                                                 \
157   do {                                                                                          \
158     int _nelts = (n);                                                                           \
159     assert (_nelts >= 0);                                                                       \
160     (var) = (void *)((_arr_descr *)alloca (_ARR_ELTS_OFFS + sizeof(type) * _nelts))->v.elts;    \
161     _ARR_SET_DBGINF (_ARR_DESCR ((var)), ARR_A_MAGIC, sizeof (type));                           \
162     (void)(_ARR_DESCR ((var))->nelts = _nelts);                                                 \
163   } while (0)
164
165 /**
166  * Creates a new automatic array with the same number of elements as a
167  * given one.
168  *
169  * @param type     The element type of the new array.
170  * @param var      A lvalue of type (type *) which will hold the new array.
171  * @param arr      An array from which the elements will be duplicated
172  *
173  * This macro creates a dynamic array of a given type at runtime.
174  * The size of the array cannot be changed later.
175  *
176  * @return A pointer to the dynamic array (can be used as a pointer to the
177  *         first element of this array).
178  */
179 #define CLONE_ARR_A(type, var, arr)             \
180   NEW_ARR_A (type, (var), ARR_LEN ((arr)))
181
182 /**
183  * Duplicates an array and returns a new automatic one.
184  *
185  * @param type     The element type of the new array.
186  * @param var      A lvalue of type (type *) which will hold the new array.
187  * @param arr      An array from with the number of elements will be taken
188  *
189  * This macro creates a dynamic array of a given type at runtime.
190  * The size of the array cannot be changed later.
191  *
192  * @return A pointer to the dynamic array (can be used as a pointer to the
193  *         first element of this array).
194  */
195 #define DUP_ARR_A(type, var, arr)                                       \
196   do { CLONE_ARR_A(type, (var), (arr));                                 \
197        memcpy ((var), (arr), sizeof (type) * ARR_LEN ((arr))); }        \
198   while (0)
199
200 /**
201  * Declare an initialized (zero'ed) array of fixed size.
202  * This macro should be used at file scope only.
203  *
204  * @param type     The element type of the new array.
205  * @param var      A lvalue of type (type *) which will hold the new array.
206  * @param _nelts   Number of elements in this new array.
207  */
208 #define DECL_ARR_S(type, var, _nelts)                                   \
209   ARR_STRUCT(type, (_nelts) ? (_nelts) : 1) _##var;                     \
210   type *var = (_ARR_SET_DBGINF (&_##var, ARR_A_MAGIC, sizeof (type)),   \
211                _##var.nelts = _nelts,                                   \
212                _##var.v.elts)
213
214 /**
215  * Returns the length of an array
216  *
217  * @param arr  a flexible, dynamic, automatic or static array.
218  */
219 #define ARR_LEN(arr) (ARR_VRFY ((arr)), _ARR_DESCR((arr))->nelts)
220
221 /**
222  * Resize a flexible array, allocate more data if needed but do NOT
223  * reduce.
224  *
225  * @param type     The element type of the array.
226  * @param arr      The array, which must be an lvalue.
227  * @param n        The new size of the array.
228  *
229  * @remark  This macro may change arr, so update all references!
230  */
231 #define ARR_RESIZE(type, arr, n)                                        \
232   ((arr) = _arr_resize ((arr), (n), sizeof(type)))
233
234 /**
235  * Resize a flexible array, always reallocate data.
236  *
237  * @param type     The element type of the array.
238  * @param arr      The array, which must be an lvalue.
239  * @param n        The new size of the array.
240  *
241  * @remark  This macro may change arr, so update all references!
242  */
243 #define ARR_SETLEN(type, arr, n)                                        \
244   ((arr) = _arr_setlen ((arr), (n), sizeof(type) * (n)))
245
246 /** Set a length smaller than the current length of the array.  Do not
247  *  resize. len must be <= ARR_LEN(arr). */
248 #define ARR_SHRINKLEN(arr,len)                                          \
249    (ARR_VRFY ((arr)), assert(_ARR_DESCR((arr))->nelts >= len),             \
250     _ARR_DESCR((arr))->nelts = len)
251
252 /**
253  * Resize a flexible array by growing it by delta elements.
254  *
255  * @param type     The element type of the array.
256  * @param arr      The array, which must be an lvalue.
257  * @param delta    The delta number of elements.
258  *
259  * @remark  This macro may change arr, so update all references!
260  */
261 #define ARR_EXTEND(type, arr, delta)                    \
262   ARR_RESIZE (type, (arr), ARR_LEN ((arr)) + (delta))
263
264 /**
265  * Resize a flexible array to hold n elements only if it is currently shorter
266  * than n.
267  *
268  * @param type     The element type of the array.
269  * @param arr      The array, which must be an lvalue.
270  * @param n        The new size of the array.
271  *
272  * @remark  This macro may change arr, so update all references!
273  */
274 #define ARR_EXTO(type, arr, n)                                          \
275   ((n) >= ARR_LEN ((arr)) ? ARR_RESIZE (type, (arr), (n)+1) : (arr))
276
277 /**
278  * Append one element to a flexible array.
279  *
280  * @param type     The element type of the array.
281  * @param arr      The array, which must be an lvalue.
282  * @param elt      The new element, must be of type (type).
283  */
284 #define ARR_APP1(type, arr, elt)                                        \
285   (ARR_EXTEND (type, (arr), 1), (arr)[ARR_LEN ((arr))-1] = (elt))
286
287
288 #ifdef NDEBUG
289 # define ARR_VRFY(arr) ((void)0)
290 # define ARR_IDX_VRFY(arr, idx) ((void)0)
291 #else
292 # define ARR_VRFY(arr)                                                                  \
293     assert (   (   (_ARR_DESCR((arr))->magic == ARR_D_MAGIC)                            \
294                 || (_ARR_DESCR((arr))->magic == ARR_A_MAGIC)                            \
295                 || (_ARR_DESCR((arr))->magic == ARR_F_MAGIC))                           \
296             && (   (_ARR_DESCR((arr))->magic != ARR_F_MAGIC)                            \
297                 || (_ARR_DESCR((arr))->u.allocated >= _ARR_DESCR((arr))->nelts))        \
298             && (_ARR_DESCR((arr))->nelts >= 0))
299 # define ARR_IDX_VRFY(arr, idx)                         \
300     assert ((0 <= (idx)) && ((idx) < ARR_LEN ((arr))))
301 #endif
302
303
304 /* Private !!!
305    Don't try this at home, kids, we're trained professionals ;->
306    ... or at the IPD, either. */
307 #ifdef NDEBUG
308 # define _ARR_DBGINF_DECL
309 # define _ARR_SET_DBGINF(descr, co, es)
310 #else
311 # define _ARR_DBGINF_DECL int magic; size_t eltsize;
312 # define _ARR_SET_DBGINF(descr, co, es)                                 \
313     ( (descr)->magic = (co), (descr)->eltsize = (es) )
314 #endif
315
316 /**
317  * Construct an array header.
318  */
319 #define ARR_STRUCT(type, _nelts)                                                \
320   struct {                                                                      \
321     _ARR_DBGINF_DECL                                                            \
322     union {                                                                     \
323       struct obstack *obstack;  /* dynamic: allocated on this obstack */        \
324       int allocated;                    /* flexible: #slots allocated */        \
325     } u;                                                                        \
326     int nelts;                                                                  \
327     union {                                                                     \
328       type elts[(_nelts)];                                                      \
329       aligned_type align[1];                                                    \
330     } v;                                                                        \
331   }
332
333 /**
334  * The array descriptor header type.
335  */
336 typedef ARR_STRUCT (aligned_type, 1) _arr_descr;
337
338 extern _arr_descr arr_mt_descr;
339
340 void *_new_arr_f (int, size_t);
341 void _del_arr_f (void *);
342 void *_new_arr_d (struct obstack *obstack, int nelts, size_t elts_size);
343 void *_arr_resize (void *, int, size_t);
344 void *_arr_setlen (void *, int, size_t);
345
346 #define _ARR_ELTS_OFFS offsetof (_arr_descr, v.elts)
347 #define _ARR_DESCR(elts) ((_arr_descr *)(void *)((char *)(elts) - _ARR_ELTS_OFFS))
348
349 #endif