Bugfix: restructured so memory disambiguator can switched off
[libfirm] / ir / ana / irloop.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  * @brief    Loop datastructure and access functions -- private stuff.
23  * @author   Goetz Lindenmaier
24  * @date     7.2002
25  * @version  $Id: irloop_t.h 17143 2008-01-02 20:56:33Z beck $
26  */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STDLIB_H
35 # include <stdlib.h>
36 #endif
37
38 #include "irloop_t.h"
39 #include "irprog_t.h"
40
41 void add_loop_son(ir_loop *loop, ir_loop *son) {
42         loop_element lson;
43         assert(loop && loop->kind == k_ir_loop);
44         assert(get_kind(son) == k_ir_loop);
45         lson.son = son;
46         ARR_APP1(loop_element, loop->children, lson);
47         ++loop->n_sons;
48 }
49
50 void add_loop_node(ir_loop *loop, ir_node *n) {
51         loop_element ln;
52         ln.node = n;
53         assert(loop && loop->kind == k_ir_loop);
54         ARR_APP1(loop_element, loop->children, ln);
55         loop->n_nodes++;
56 }
57
58 void add_loop_irg(ir_loop *loop, ir_graph *irg) {
59         loop_element ln;
60         ln.irg = irg;
61         assert(loop && loop->kind == k_ir_loop);
62         ARR_APP1(loop_element, loop->children, ln);
63         loop->n_nodes++;
64 }
65
66 /**
67  * Mature all loops by removing the flexible arrays of a loop.
68  */
69 void mature_loops(ir_loop *loop, struct obstack *obst) {
70         loop_element *new_children = DUP_ARR_D(loop_element, obst, loop->children);
71         DEL_ARR_F(loop->children);
72         loop->children = new_children;
73
74         if (loop->n_sons > 0) {
75                 /* we have child loops, mature them */
76                 int i;
77
78                 for (i = ARR_LEN(new_children) - 1; i >= 0; --i) {
79                         loop_element child = new_children[i];
80
81                         if (*child.kind == k_ir_loop) {
82                                 mature_loops(child.son, obst);
83                         }
84                 }
85         }
86 }
87
88 /* Returns outer loop, itself if outermost. */
89 ir_loop *(get_loop_outer_loop)(const ir_loop *loop) {
90         return _get_loop_outer_loop(loop);
91 }
92
93 /* Returns nesting depth of this loop */
94 int (get_loop_depth)(const ir_loop *loop) {
95         return _get_loop_depth(loop);
96 }
97
98 /* Returns the number of inner loops */
99 int (get_loop_n_sons)(const ir_loop *loop) {
100         return _get_loop_n_sons(loop);
101 }
102
103 /* Returns the pos`th loop_node-child              *
104  * TODO: This method isn`t very efficient !        *
105  * Returns NULL if there isn`t a pos`th loop_node */
106 ir_loop *get_loop_son(ir_loop *loop, int pos) {
107         int child_nr = 0, loop_nr = -1;
108
109         assert(loop && loop->kind == k_ir_loop);
110         while (child_nr < ARR_LEN(loop->children)) {
111                 if (*(loop->children[child_nr].kind) == k_ir_loop)
112                         loop_nr++;
113                 if (loop_nr == pos)
114                         return loop->children[child_nr].son;
115                 child_nr++;
116         }
117         return NULL;
118 }
119
120 /* Returns the number of nodes in the loop */
121 int get_loop_n_nodes(ir_loop *loop) {
122         assert(loop); assert(loop->kind == k_ir_loop);
123         return loop->n_nodes;
124 }
125
126 /* Returns the pos'th ir_node-child                *
127  * TODO: This method isn't very efficient !        *
128  * Returns NULL if there isn't a pos'th ir_node   */
129 ir_node *get_loop_node(ir_loop *loop, int pos) {
130         int child_nr, node_nr = -1;
131
132         assert(loop && loop->kind == k_ir_loop);
133         assert(pos < get_loop_n_nodes(loop));
134
135         for (child_nr = 0; child_nr < ARR_LEN(loop->children); child_nr++) {
136                 if (*(loop->children[child_nr].kind) == k_ir_node)
137                         node_nr++;
138                 if (node_nr == pos)
139                         return loop -> children[child_nr].node;
140         }
141
142         assert(0 && "no child at pos found");
143         return NULL;
144 }
145
146 /* Returns the number of elements contained in loop.  */
147 int get_loop_n_elements(const ir_loop *loop) {
148         assert(loop && loop->kind == k_ir_loop);
149         return(ARR_LEN(loop->children));
150 }
151
152 /*
153 Returns the pos`th loop element.
154 This may be a loop_node or a ir_node. The caller of this function has
155 to check the *(loop_element.kind) field for "k_ir_node" or "k_ir_loop"
156 and then select the appropriate "loop_element.node" or "loop_element.son".
157 */
158 loop_element get_loop_element(const ir_loop *loop, int pos) {
159         assert(loop && loop->kind == k_ir_loop && pos < ARR_LEN(loop->children));
160         return(loop -> children[pos]);
161 }
162
163 int get_loop_element_pos(const ir_loop *loop, void *le) {
164         int i, n;
165         assert(loop && loop->kind == k_ir_loop);
166
167         n = get_loop_n_elements(loop);
168         for (i = 0; i < n; i++)
169                 if (get_loop_element(loop, i).node == le)
170                         return i;
171         return -1;
172 }
173
174
175 /**
176  * Sets the loop for a node.
177  */
178 void set_irn_loop(ir_node *n, ir_loop *loop) {
179         n->loop = loop;
180 }
181
182 /* Uses temporary information to get the loop */
183 ir_loop *(get_irn_loop)(const ir_node *n) {
184         return _get_irn_loop(n);
185 }
186
187 int get_loop_loop_nr(const ir_loop *loop) {
188         assert(loop && loop->kind == k_ir_loop);
189 #ifdef DEBUG_libfirm
190         return loop->loop_nr;
191 #else
192         return (int)loop;
193 #endif
194 }
195
196 /** A field to connect additional information to a loop.  Only valid
197     if libfirm_debug is set. */
198 void set_loop_link(ir_loop *loop, void *link) {
199         assert(loop && loop->kind == k_ir_loop);
200         loop->link = link;
201 }
202 void *get_loop_link(const ir_loop *loop) {
203         assert(loop && loop->kind == k_ir_loop);
204         return loop->link;
205 }
206
207 int (is_ir_loop)(const void *thing) {
208         return _is_ir_loop(thing);
209 }
210
211 /* The outermost loop is remarked in the surrounding graph. */
212 void (set_irg_loop)(ir_graph *irg, ir_loop *loop) {
213         _set_irg_loop(irg, loop);
214 }
215
216 /* Returns the root loop info (if exists) for an irg. */
217 ir_loop *(get_irg_loop)(ir_graph *irg) {
218         return _get_irg_loop(irg);
219 }
220
221 /*
222  * Allocates a new loop as son of father on the given obstack.
223  * If father is equal NULL, a new root loop is created.
224  */
225 ir_loop *alloc_loop(ir_loop *father, struct obstack *obst) {
226         ir_loop *son;
227
228         son = obstack_alloc(obst, sizeof(*son));
229         memset(son, 0, sizeof(*son));
230         son->kind     = k_ir_loop;
231         son->children = NEW_ARR_F(loop_element, 0);
232         son->n_nodes  = 0;
233         son->n_sons   = 0;
234         son->link     = NULL;
235         if (father) {
236                 son->outer_loop = father;
237                 add_loop_son(father, son);
238                 son->depth = father->depth + 1;
239         } else {  /* The root loop */
240                 son->outer_loop = son;
241                 son->depth      = 0;
242         }
243
244 #ifdef DEBUG_libfirm
245         son->loop_nr = get_irp_new_node_nr();
246 #endif
247
248         return son;
249 }