backend_marked was a buggy/wrong concept, removed it
[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));
136         assert(is_compound_graph_path(path));
137         if (ent->attr.cmpd_attr.values == NULL) {
138                 ent->attr.cmpd_attr.values = NEW_ARR_F(ir_node*, 0);
139                 assert(ent->attr.cmpd_attr.val_paths == NULL);
140                 ent->attr.cmpd_attr.val_paths = NEW_ARR_F(compound_graph_path*, 0);
141         }
142         ARR_APP1(ir_node *, ent->attr.cmpd_attr.values, val);
143         ARR_APP1(compound_graph_path *, ent->attr.cmpd_attr.val_paths, path);
144 }
145
146 void set_compound_ent_value_w_path(ir_entity *ent, ir_node *val,
147                                    compound_graph_path *path, int pos)
148 {
149         assert(is_compound_entity(ent));
150         assert(is_compound_graph_path(path));
151         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.values));
152         ent->attr.cmpd_attr.values[pos]    = val;
153         ent->attr.cmpd_attr.val_paths[pos] = path;
154 }
155
156 compound_graph_path *get_compound_ent_value_path(const ir_entity *ent, int pos)
157 {
158         assert(is_compound_entity(ent));
159         assert(ent->initializer == NULL);
160         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.val_paths));
161         return ent->attr.cmpd_attr.val_paths[pos];
162 }
163
164 /**
165  * Returns non-zero, if two compound_graph_pathes are equal
166  *
167  * @param path1            the first path
168  * @param path2            the second path
169  */
170 static int equal_paths(compound_graph_path *path1, compound_graph_path *path2)
171 {
172         int i;
173         int len1 = get_compound_graph_path_length(path1);
174         int len2 = get_compound_graph_path_length(path2);
175
176         if (len2 != len1) return 0;
177
178         for (i = 0; i < len1; i++) {
179                 ir_type *tp;
180                 ir_entity *node1 = get_compound_graph_path_node(path1, i);
181                 ir_entity *node2 = get_compound_graph_path_node(path2, i);
182
183                 if (node1 != node2) return 0;
184
185                 tp = get_entity_owner(node1);
186                 if (is_Array_type(tp)) {
187                         int index1 = get_compound_graph_path_array_index(path1, i);
188                         int index2 = get_compound_graph_path_array_index(path2, i);
189                         if (index1 != index2)
190                                 return 0;
191                 }
192         }
193         return 1;
194 }
195
196 /**
197  * Returns the position of a value with the given path.
198  * The path must contain array indices for all array element entities.
199  *
200  * @todo  This implementation is very slow (O(number of initializers * |path|)
201  *        and should be replaced when the new tree oriented
202  *        value representation is finally implemented.
203  */
204 static int get_compound_ent_pos_by_path(const ir_entity *ent,
205                                         compound_graph_path *path)
206 {
207         int i, n_paths = get_compound_ent_n_values(ent);
208
209         for (i = 0; i < n_paths; i ++) {
210                 compound_graph_path *gr = get_compound_ent_value_path(ent, i);
211                 if (equal_paths(gr, path))
212                         return i;
213         }
214         return -1;
215 }
216
217 ir_node *get_compound_ent_value_by_path(const ir_entity *ent,
218                                         compound_graph_path *path)
219 {
220         int pos = get_compound_ent_pos_by_path(ent, path);
221         if (pos >= 0)
222                 return get_compound_ent_value(ent, pos);
223         return NULL;
224 }
225
226 void remove_compound_ent_value(ir_entity *ent, ir_entity *value_ent)
227 {
228         int i, n;
229         assert(is_compound_entity(ent));
230
231         n = ARR_LEN(ent->attr.cmpd_attr.val_paths);
232         for (i = 0; i < n; ++i) {
233                 compound_graph_path *path = ent->attr.cmpd_attr.val_paths[i];
234                 if (path->list[path->len-1].node == value_ent) {
235                         for (; i < n - 1; ++i) {
236                                 ent->attr.cmpd_attr.val_paths[i] = ent->attr.cmpd_attr.val_paths[i+1];
237                                 ent->attr.cmpd_attr.values[i]    = ent->attr.cmpd_attr.values[i+1];
238                         }
239                         ARR_SETLEN(ir_entity*, ent->attr.cmpd_attr.val_paths, n - 1);
240                         ARR_SETLEN(ir_node*,   ent->attr.cmpd_attr.values,    n - 1);
241                         break;
242                 }
243         }
244 }
245
246 void add_compound_ent_value(ir_entity *ent, ir_node *val, ir_entity *member)
247 {
248         compound_graph_path *path;
249         ir_type *owner_tp = get_entity_owner(member);
250         assert(is_compound_entity(ent));
251         path = new_compound_graph_path(get_entity_type(ent), 1);
252         path->list[0].node = member;
253         if (is_Array_type(owner_tp)) {
254                 int max;
255                 int i, n;
256
257                 assert(get_array_n_dimensions(owner_tp) == 1 && has_array_lower_bound(owner_tp, 0));
258                 max = get_array_lower_bound_int(owner_tp, 0) -1;
259                 for (i = 0, n = get_compound_ent_n_values(ent); i < n; ++i) {
260                         int index = get_compound_graph_path_array_index(get_compound_ent_value_path(ent, i), 0);
261                         if (index > max) {
262                                 max = index;
263                         }
264                 }
265                 path->list[0].index = max + 1;
266         }
267         add_compound_ent_value_w_path(ent, val, path);
268 }
269
270 ir_entity *get_compound_ent_value_member(const ir_entity *ent, int pos)
271 {
272         compound_graph_path *path;
273         assert(is_compound_entity(ent));
274         path = get_compound_ent_value_path(ent, pos);
275
276         return get_compound_graph_path_node(path, get_compound_graph_path_length(path)-1);
277 }
278
279 void set_compound_ent_value(ir_entity *ent, ir_node *val, ir_entity *member,
280                             int pos)
281 {
282         compound_graph_path *path;
283         assert(is_compound_entity(ent));
284         path = get_compound_ent_value_path(ent, pos);
285         set_compound_graph_path_node(path, 0, member);
286         set_compound_ent_value_w_path(ent, val, path, pos);
287 }
288
289 void set_array_entity_values(ir_entity *ent, tarval **values, int num_vals)
290 {
291         int i;
292         ir_graph *rem = current_ir_graph;
293         ir_type *arrtp = get_entity_type(ent);
294         ir_node *val;
295         ir_type *elttp = get_array_element_type(arrtp);
296
297         assert(is_Array_type(arrtp));
298         assert(get_array_n_dimensions(arrtp) == 1);
299         /* One bound is sufficient, the number of constant fields makes the
300            size. */
301         assert(get_array_lower_bound (arrtp, 0) || get_array_upper_bound (arrtp, 0));
302         current_ir_graph = get_const_code_irg();
303
304         for (i = 0; i < num_vals; i++) {
305                 val = new_Const_type(values[i], elttp);
306                 add_compound_ent_value(ent, val, get_array_element_entity(arrtp));
307                 set_compound_graph_path_array_index(get_compound_ent_value_path(ent, i), 0, i);
308         }
309         current_ir_graph = rem;
310 }
311
312 unsigned get_compound_ent_value_offset_bytes(const ir_entity *ent, int pos)
313 {
314         compound_graph_path *path;
315         int path_len, i;
316         unsigned offset = 0;
317         ir_type *curr_tp;
318
319         assert(get_type_state(get_entity_type(ent)) == layout_fixed);
320
321         path     = get_compound_ent_value_path(ent, pos);
322         path_len = get_compound_graph_path_length(path);
323         curr_tp  = path->tp;
324
325         for (i = 0; i < path_len; ++i) {
326                 if (is_Array_type(curr_tp)) {
327                         ir_type *elem_type = get_array_element_type(curr_tp);
328                         unsigned size      = get_type_size_bytes(elem_type);
329                         unsigned align     = get_type_alignment_bytes(elem_type);
330                         int      idx;
331
332                         assert(size > 0);
333                         if(size % align > 0) {
334                                 size += align - (size % align);
335                         }
336                         idx = get_compound_graph_path_array_index(path, i);
337                         assert(idx >= 0);
338                         offset += size * idx;
339                         curr_tp = elem_type;
340                 } else {
341                         ir_entity *node = get_compound_graph_path_node(path, i);
342                         offset += get_entity_offset(node);
343                         curr_tp = get_entity_type(node);
344                 }
345         }
346
347         return offset;
348 }
349
350 unsigned get_compound_ent_value_offset_bit_remainder(const ir_entity *ent,
351                                                      int pos)
352 {
353         compound_graph_path *path;
354         int path_len;
355         ir_entity *last_node;
356
357         assert(get_type_state(get_entity_type(ent)) == layout_fixed);
358
359         path      = get_compound_ent_value_path(ent, pos);
360         path_len  = get_compound_graph_path_length(path);
361         last_node = get_compound_graph_path_node(path, path_len - 1);
362
363         if(last_node == NULL)
364                 return 0;
365
366         return get_entity_offset_bits_remainder(last_node);
367 }
368
369 int get_compound_ent_n_values(const ir_entity *ent)
370 {
371         assert(ent->initializer == NULL);
372         assert(is_compound_entity(ent));
373         return ARR_LEN(ent->attr.cmpd_attr.values);
374 }
375
376 ir_node *get_compound_ent_value(const ir_entity *ent, int pos)
377 {
378         assert(is_compound_entity(ent));
379         assert(ent->initializer == NULL);
380         assert(0 <= pos && pos < ARR_LEN(ent->attr.cmpd_attr.values));
381         return skip_Id(ent->attr.cmpd_attr.values[pos]);
382 }
383
384 int entity_has_compound_ent_values(const ir_entity *entity)
385 {
386         if (!is_compound_entity(entity))
387                 return 0;
388
389         return entity->attr.cmpd_attr.values != NULL;
390 }