gen_docu: fix missing attributes, show generation time at the end
[libfirm] / ir / ana / irloop.c
1 /*
2  * Copyright (C) 1995-2011 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  */
26 #include "config.h"
27
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "irloop_t.h"
32 #include "irprog_t.h"
33 #include "error.h"
34
35 void add_loop_son(ir_loop *loop, ir_loop *son)
36 {
37         loop_element lson;
38         assert(loop && loop->kind == k_ir_loop);
39         assert(get_kind(son) == k_ir_loop);
40         lson.son = son;
41         ARR_APP1(loop_element, loop->children, lson);
42         loop->flags |= loop_outer_loop;
43 }
44
45 void add_loop_node(ir_loop *loop, ir_node *n)
46 {
47         loop_element ln;
48         ln.node = n;
49         assert(loop && loop->kind == k_ir_loop);
50         ARR_APP1(loop_element, loop->children, ln);
51 }
52
53 void add_loop_irg(ir_loop *loop, ir_graph *irg)
54 {
55         loop_element ln;
56         ln.irg = irg;
57         assert(loop && loop->kind == k_ir_loop);
58         ARR_APP1(loop_element, loop->children, ln);
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 {
69         size_t i;
70
71         loop_element *new_children = DUP_ARR_D(loop_element, obst, loop->children);
72         DEL_ARR_F(loop->children);
73         loop->children = new_children;
74
75         /* mature child loops */
76         for (i = ARR_LEN(new_children); i > 0;) {
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 /* Returns outer loop, itself if outermost. */
86 ir_loop *(get_loop_outer_loop)(const ir_loop *loop)
87 {
88         return _get_loop_outer_loop(loop);
89 }
90
91 /* Returns nesting depth of this loop */
92 unsigned (get_loop_depth)(const ir_loop *loop)
93 {
94         return _get_loop_depth(loop);
95 }
96
97 /* Returns the number of elements contained in loop.  */
98 size_t get_loop_n_elements(const ir_loop *loop)
99 {
100         assert(loop && loop->kind == k_ir_loop);
101         return(ARR_LEN(loop->children));
102 }
103
104 loop_element get_loop_element(const ir_loop *loop, size_t pos)
105 {
106         assert(loop && loop->kind == k_ir_loop && pos < ARR_LEN(loop->children));
107         return(loop -> children[pos]);
108 }
109
110 /**
111  * Sets the loop for a node.
112  */
113 void set_irn_loop(ir_node *n, ir_loop *loop)
114 {
115         n->loop = loop;
116 }
117
118 ir_loop *(get_irn_loop)(const ir_node *n)
119 {
120         return _get_irn_loop(n);
121 }
122
123 long get_loop_loop_nr(const ir_loop *loop)
124 {
125         assert(loop && loop->kind == k_ir_loop);
126 #ifdef DEBUG_libfirm
127         return loop->loop_nr;
128 #else
129         return (long)loop;
130 #endif
131 }
132
133 void set_loop_link(ir_loop *loop, void *link)
134 {
135         assert(loop && loop->kind == k_ir_loop);
136         loop->link = link;
137 }
138
139 void *get_loop_link(const ir_loop *loop)
140 {
141         assert(loop && loop->kind == k_ir_loop);
142         return loop->link;
143 }
144
145 int (is_ir_loop)(const void *thing)
146 {
147         return _is_ir_loop(thing);
148 }
149
150 /* The outermost loop is remarked in the surrounding graph. */
151 void (set_irg_loop)(ir_graph *irg, ir_loop *loop)
152 {
153         _set_irg_loop(irg, loop);
154 }
155
156 /* Returns the root loop info (if exists) for an irg. */
157 ir_loop *(get_irg_loop)(const ir_graph *irg)
158 {
159         return _get_irg_loop(irg);
160 }
161
162 /*
163  * Allocates a new loop as son of father on the given obstack.
164  * If father is equal NULL, a new root loop is created.
165  */
166 ir_loop *alloc_loop(ir_loop *father, struct obstack *obst)
167 {
168         ir_loop *son;
169
170         son = OALLOCZ(obst, ir_loop);
171         son->kind     = k_ir_loop;
172         son->children = NEW_ARR_F(loop_element, 0);
173         son->link     = NULL;
174         if (father) {
175                 son->outer_loop = father;
176                 add_loop_son(father, son);
177                 son->depth = father->depth + 1;
178         } else {  /* The root loop */
179                 son->outer_loop = son;
180                 son->depth      = 0;
181         }
182
183 #ifdef DEBUG_libfirm
184         son->loop_nr = get_irp_new_node_nr();
185 #endif
186
187         return son;
188 }