struct types still require names.
[libfirm] / ir / tr / compound_path.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  * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
23  * @version $Id$
24  */
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <assert.h>
29
30 #include "firm_types.h"
31 #include "typerep.h"
32 #include "compound_path_t.h"
33 #include "xmalloc.h"
34 #include "type_t.h"
35 #include "entity_t.h"
36 #include "irgraph_t.h"
37 #include "ircons.h"
38
39 compound_graph_path *new_compound_graph_path(ir_type *tp, int length)
40 {
41         compound_graph_path *res;
42
43         assert(is_compound_type(tp));
44         assert(length > 0);
45
46         res = xmalloc(sizeof(*res) + (length-1) * sizeof(res->list[0]));
47         memset(res, 0, sizeof(*res) + (length-1) * sizeof(res->list[0]));
48         res->kind = k_ir_compound_graph_path;
49         res->tp   = tp;
50         res->len  = length;
51
52         return res;
53 }
54
55 void free_compound_graph_path(compound_graph_path *gr)
56 {
57         assert(gr && is_compound_graph_path(gr));
58         gr->kind = k_BAD;
59         free(gr);
60 }
61
62 int is_compound_graph_path(const void *thing)
63 {
64         return get_kind(thing) == k_ir_compound_graph_path;
65 }
66
67 int is_proper_compound_graph_path(compound_graph_path *gr, int pos)
68 {
69         int i;
70         ir_entity *node;
71         ir_type *owner = gr->tp;
72
73         for (i = 0; i <= pos; i++) {
74                 node = get_compound_graph_path_node(gr, i);
75                 if (node == NULL)
76                         /* Path not yet complete. */
77                         return 1;
78                 if (get_entity_owner(node) != owner)
79                         return 0;
80                 owner = get_entity_type(node);
81         }
82         if (pos == get_compound_graph_path_length(gr))
83                 if (!is_atomic_type(owner))
84                         return 0;
85                 return 1;
86 }
87
88 int get_compound_graph_path_length(const compound_graph_path *gr)
89 {
90         assert(gr && is_compound_graph_path(gr));
91         return gr->len;
92 }
93
94 ir_entity *get_compound_graph_path_node(const compound_graph_path *gr, int pos)
95 {
96         assert(gr && is_compound_graph_path(gr));
97         assert(pos >= 0 && pos < gr->len);
98         return gr->list[pos].node;
99 }
100
101 void set_compound_graph_path_node(compound_graph_path *gr, int pos,
102                                   ir_entity *node)
103 {
104         assert(gr && is_compound_graph_path(gr));
105         assert(pos >= 0 && pos < gr->len);
106         assert(is_entity(node));
107         gr->list[pos].node = node;
108         assert(is_proper_compound_graph_path(gr, pos));
109 }
110
111 int get_compound_graph_path_array_index(const compound_graph_path *gr, int pos)
112 {
113         assert(gr && is_compound_graph_path(gr));
114         assert(pos >= 0 && pos < gr->len);
115         return gr->list[pos].index;
116 }
117
118 void set_compound_graph_path_array_index(compound_graph_path *gr, int pos,
119                                          int index)
120 {
121         assert(gr && is_compound_graph_path(gr));
122         assert(pos >= 0 && pos < gr->len);
123         gr->list[pos].index = index;
124 }
125
126 ir_type *get_compound_graph_path_type(const compound_graph_path *gr)
127 {
128         assert(gr && is_compound_graph_path(gr));
129         return gr->tp;
130 }
131
132 void add_compound_ent_value_w_path(ir_entity *ent, ir_node *val,
133                                    compound_graph_path *path)
134 {
135         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
136         assert(is_compound_graph_path(path));
137         ARR_APP1(ir_node *, ent->attr.cmpd_attr.values, val);
138         ARR_APP1(compound_graph_path *, ent->attr.cmpd_attr.val_paths, path);
139 }
140
141 void set_compound_ent_value_w_path(ir_entity *ent, ir_node *val,
142                                    compound_graph_path *path, int pos)
143 {
144         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
145         assert(is_compound_graph_path(path));
146         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.values));
147         ent->attr.cmpd_attr.values[pos]    = val;
148         ent->attr.cmpd_attr.val_paths[pos] = path;
149 }
150
151 compound_graph_path *get_compound_ent_value_path(ir_entity *ent, int pos)
152 {
153         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
154         assert(!ent->has_initializer);
155         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.val_paths));
156         return ent->attr.cmpd_attr.val_paths[pos];
157 }
158
159 /**
160  * Returns non-zero, if two compound_graph_pathes are equal
161  *
162  * @param path1            the first path
163  * @param path2            the second path
164  */
165 static int equal_paths(compound_graph_path *path1, compound_graph_path *path2)
166 {
167         int i;
168         int len1 = get_compound_graph_path_length(path1);
169         int len2 = get_compound_graph_path_length(path2);
170
171         if (len2 != len1) return 0;
172
173         for (i = 0; i < len1; i++) {
174                 ir_type *tp;
175                 ir_entity *node1 = get_compound_graph_path_node(path1, i);
176                 ir_entity *node2 = get_compound_graph_path_node(path2, i);
177
178                 if (node1 != node2) return 0;
179
180                 tp = get_entity_owner(node1);
181                 if (is_Array_type(tp)) {
182                         int index1 = get_compound_graph_path_array_index(path1, i);
183                         int index2 = get_compound_graph_path_array_index(path2, i);
184                         if (index1 != index2)
185                                 return 0;
186                 }
187         }
188         return 1;
189 }
190
191 /**
192  * Returns the position of a value with the given path.
193  * The path must contain array indices for all array element entities.
194  *
195  * @todo  This implementation is very slow (O(number of initializers * |path|)
196  *        and should be replaced when the new tree oriented
197  *        value representation is finally implemented.
198  */
199 static int get_compound_ent_pos_by_path(ir_entity *ent,
200                                         compound_graph_path *path)
201 {
202         int i, n_paths = get_compound_ent_n_values(ent);
203
204         for (i = 0; i < n_paths; i ++) {
205                 compound_graph_path *gr = get_compound_ent_value_path(ent, i);
206                 if (equal_paths(gr, path))
207                         return i;
208         }
209         return -1;
210 }
211
212 ir_node *get_compound_ent_value_by_path(ir_entity *ent,
213                                         compound_graph_path *path)
214 {
215         int pos = get_compound_ent_pos_by_path(ent, path);
216         if (pos >= 0)
217                 return get_compound_ent_value(ent, pos);
218         return NULL;
219 }
220
221 void remove_compound_ent_value(ir_entity *ent, ir_entity *value_ent)
222 {
223         int i, n;
224         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
225
226         n = ARR_LEN(ent->attr.cmpd_attr.val_paths);
227         for (i = 0; i < n; ++i) {
228                 compound_graph_path *path = ent->attr.cmpd_attr.val_paths[i];
229                 if (path->list[path->len-1].node == value_ent) {
230                         for (; i < n - 1; ++i) {
231                                 ent->attr.cmpd_attr.val_paths[i] = ent->attr.cmpd_attr.val_paths[i+1];
232                                 ent->attr.cmpd_attr.values[i]    = ent->attr.cmpd_attr.values[i+1];
233                         }
234                         ARR_SETLEN(ir_entity*, ent->attr.cmpd_attr.val_paths, n - 1);
235                         ARR_SETLEN(ir_node*,   ent->attr.cmpd_attr.values,    n - 1);
236                         break;
237                 }
238         }
239 }
240
241 void add_compound_ent_value(ir_entity *ent, ir_node *val, ir_entity *member)
242 {
243         compound_graph_path *path;
244         ir_type *owner_tp = get_entity_owner(member);
245         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
246         path = new_compound_graph_path(get_entity_type(ent), 1);
247         path->list[0].node = member;
248         if (is_Array_type(owner_tp)) {
249                 int max;
250                 int i, n;
251
252                 assert(get_array_n_dimensions(owner_tp) == 1 && has_array_lower_bound(owner_tp, 0));
253                 max = get_array_lower_bound_int(owner_tp, 0) -1;
254                 for (i = 0, n = get_compound_ent_n_values(ent); i < n; ++i) {
255                         int index = get_compound_graph_path_array_index(get_compound_ent_value_path(ent, i), 0);
256                         if (index > max) {
257                                 max = index;
258                         }
259                 }
260                 path->list[0].index = max + 1;
261         }
262         add_compound_ent_value_w_path(ent, val, path);
263 }
264
265 ir_entity *get_compound_ent_value_member(ir_entity *ent, int pos)
266 {
267         compound_graph_path *path;
268         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
269         path = get_compound_ent_value_path(ent, pos);
270
271         return get_compound_graph_path_node(path, get_compound_graph_path_length(path)-1);
272 }
273
274 void set_compound_ent_value(ir_entity *ent, ir_node *val, ir_entity *member,
275                             int pos)
276 {
277         compound_graph_path *path;
278         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
279         path = get_compound_ent_value_path(ent, pos);
280         set_compound_graph_path_node(path, 0, member);
281         set_compound_ent_value_w_path(ent, val, path, pos);
282 }
283
284 void set_array_entity_values(ir_entity *ent, tarval **values, int num_vals)
285 {
286         int i;
287         ir_graph *rem = current_ir_graph;
288         ir_type *arrtp = get_entity_type(ent);
289         ir_node *val;
290         ir_type *elttp = get_array_element_type(arrtp);
291
292         assert(is_Array_type(arrtp));
293         assert(get_array_n_dimensions(arrtp) == 1);
294         /* One bound is sufficient, the number of constant fields makes the
295            size. */
296         assert(get_array_lower_bound (arrtp, 0) || get_array_upper_bound (arrtp, 0));
297         assert(get_entity_variability(ent) != variability_uninitialized);
298         current_ir_graph = get_const_code_irg();
299
300         for (i = 0; i < num_vals; i++) {
301                 val = new_Const_type(values[i], elttp);
302                 add_compound_ent_value(ent, val, get_array_element_entity(arrtp));
303                 set_compound_graph_path_array_index(get_compound_ent_value_path(ent, i), 0, i);
304         }
305         current_ir_graph = rem;
306 }
307
308 unsigned get_compound_ent_value_offset_bytes(ir_entity *ent, int pos)
309 {
310         compound_graph_path *path;
311         int path_len, i;
312         unsigned offset = 0;
313         ir_type *curr_tp;
314
315         assert(get_type_state(get_entity_type(ent)) == layout_fixed);
316
317         path     = get_compound_ent_value_path(ent, pos);
318         path_len = get_compound_graph_path_length(path);
319         curr_tp  = path->tp;
320
321         for (i = 0; i < path_len; ++i) {
322                 if (is_Array_type(curr_tp)) {
323                         ir_type *elem_type = get_array_element_type(curr_tp);
324                         unsigned size      = get_type_size_bytes(elem_type);
325                         unsigned align     = get_type_alignment_bytes(elem_type);
326                         int      idx;
327
328                         assert(size > 0);
329                         if(size % align > 0) {
330                                 size += align - (size % align);
331                         }
332                         idx = get_compound_graph_path_array_index(path, i);
333                         assert(idx >= 0);
334                         offset += size * idx;
335                         curr_tp = elem_type;
336                 } else {
337                         ir_entity *node = get_compound_graph_path_node(path, i);
338                         offset += get_entity_offset(node);
339                         curr_tp = get_entity_type(node);
340                 }
341         }
342
343         return offset;
344 }
345
346 unsigned get_compound_ent_value_offset_bit_remainder(ir_entity *ent, int pos)
347 {
348         compound_graph_path *path;
349         int path_len;
350         ir_entity *last_node;
351
352         assert(get_type_state(get_entity_type(ent)) == layout_fixed);
353
354         path      = get_compound_ent_value_path(ent, pos);
355         path_len  = get_compound_graph_path_length(path);
356         last_node = get_compound_graph_path_node(path, path_len - 1);
357
358         if(last_node == NULL)
359                 return 0;
360
361         return get_entity_offset_bits_remainder(last_node);
362 }
363
364 int get_compound_ent_n_values(ir_entity *ent)
365 {
366         assert(!ent->has_initializer);
367         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
368         return ARR_LEN(ent->attr.cmpd_attr.values);
369 }
370
371 ir_node *get_compound_ent_value(ir_entity *ent, int pos)
372 {
373         assert(is_compound_entity(ent) && (ent->variability != variability_uninitialized));
374         assert(!ent->has_initializer);
375         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.values));
376         return skip_Id(ent->attr.cmpd_attr.values[pos]);
377 }