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