remove #ifdef HAVE_CONFIG_Hs
[libfirm] / ir / ir / irgwalk.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   Functions for traversing ir graphs
23  * @author  Boris Boesler, Goetz Lindenmaier, Michael Beck
24  * @version $Id$
25  * @summary
26  *  traverse an ir graph
27  *  - execute the pre function before recursion
28  *  - execute the post function after recursion
29  */
30 #include "config.h"
31
32 #ifdef HAVE_STDLIB_H
33 # include <stdlib.h>
34 #endif
35
36 #include "irnode_t.h"
37 #include "irgraph_t.h"
38 #include "irprog.h"
39 #include "irgwalk.h"
40 #include "irhooks.h"
41 #include "ircgcons.h"
42 #include "entity_t.h"
43
44 #include "error.h"
45 #include "pset_new.h"
46 #include "array.h"
47
48 /**
49  * Walk over an interprocedural graph (callgraph).
50  * Visits only graphs in irg_set.
51  */
52 static void irg_walk_cg(ir_node * node, ir_visited_t visited,
53                         pset_new_t *irg_set, irg_walk_func *pre,
54                         irg_walk_func *post, void * env) {
55         int i;
56         ir_graph * rem = current_ir_graph;
57         ir_node * pred;
58
59         assert(node && node->kind == k_ir_node);
60         if (get_irn_visited(node) >= visited) return;
61
62         set_irn_visited(node, visited);
63
64         if (pre) pre(node, env);
65
66         pred = skip_Proj(node);
67         if (is_CallBegin(pred)            ||
68             get_irn_op(pred) == op_EndReg ||
69             get_irn_op(pred) == op_EndExcept) {
70                 current_ir_graph = get_irn_irg(pred);
71         }
72
73         if (is_no_Block(node)) { /* not block */
74                 irg_walk_cg(get_nodes_block(node), visited, irg_set, pre, post, env);
75         }
76
77         if (is_Block(node)) { /* block */
78                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
79                         ir_node * exec = get_irn_n(node, i);
80                         ir_node * pred = skip_Proj(exec);
81                         if ((
82                               !is_CallBegin(pred)           &&
83                               get_irn_op(pred) != op_EndReg &&
84                               get_irn_op(pred) != op_EndExcept
85                             ) || pset_new_contains(irg_set, get_irn_irg(pred))) {
86                                 irg_walk_cg(exec, visited, irg_set, pre, post, env);
87                         }
88                 }
89         } else if (is_Filter(node)) { /* filter */
90                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
91                         ir_node * pred = get_irn_n(node, i);
92                         if (is_Unknown(pred) || is_Bad(pred)) {
93                                 irg_walk_cg(pred, visited, irg_set, pre, post, env);
94                         } else {
95                                 ir_node * exec;
96                                 exec = skip_Proj(get_Block_cfgpred(get_nodes_block(node), i));
97
98                                 if (is_Bad(exec)) {
99                                         continue;
100                                 }
101
102                                 assert(is_CallBegin(exec)            ||
103                                        get_irn_op(exec) == op_EndReg ||
104                                        get_irn_op(exec) == op_EndExcept);
105                                 if (pset_new_contains(irg_set, get_irn_irg(exec))) {
106                                         current_ir_graph = get_irn_irg(exec);
107                                         irg_walk_cg(pred, visited, irg_set, pre, post, env);
108                                         current_ir_graph = rem;
109                                 }
110                         }
111                 }
112         } else {                      /* everything else */
113                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
114                         irg_walk_cg(get_irn_n(node, i), visited, irg_set, pre, post, env);
115                 }
116         }
117
118         if (post) post(node, env);
119
120         current_ir_graph = rem;
121 }
122
123
124 /**
125  * Insert all ir_graphs in irg_set, that are (transitive) reachable.
126  */
127 static void collect_irgs(ir_node * node, pset_new_t *irg_set) {
128         if (is_Call(node)) {
129                 int i;
130                 for (i = get_Call_n_callees(node) - 1; i >= 0; --i) {
131                         ir_entity * ent = get_Call_callee(node, i);
132                         ir_graph * irg = get_entity_irg(ent);
133                         if (irg && !pset_new_contains(irg_set, irg)) {
134                                 pset_new_insert(irg_set, irg);
135                                 irg_walk_graph(irg, (irg_walk_func *) collect_irgs, NULL, irg_set);
136                         }
137                 }
138         }
139 }
140
141 /**
142  * specialized version of irg_walk_2, called if only pre callback exists
143  *
144  * @return number of visited nodes
145  */
146 static unsigned
147 irg_walk_2_pre(ir_node *node, irg_walk_func *pre, void * env) {
148         int i;
149         unsigned cnt = 1;
150         ir_graph *irg = current_ir_graph;
151
152         set_irn_visited(node, irg->visited);
153
154         pre(node, env);
155
156         if (node->op != op_Block) {
157                 ir_node *pred = get_irn_n(node, -1);
158                 if (pred->visited < irg->visited)
159                         cnt += irg_walk_2_pre(pred, pre, env);
160         }
161         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
162                 ir_node *pred = get_irn_n(node, i);
163                 if (pred->visited < irg->visited)
164                         cnt += irg_walk_2_pre(pred, pre, env);
165         }
166         return cnt;
167 }
168
169 /**
170  * specialized version of irg_walk_2, called if only post callback exists
171  *
172  * @return number of visited nodes
173  */
174 static unsigned
175 irg_walk_2_post(ir_node *node, irg_walk_func *post, void * env) {
176         int i;
177         unsigned cnt = 1;
178         ir_graph *irg = current_ir_graph;
179
180         set_irn_visited(node, irg->visited);
181
182         if (node->op != op_Block) {
183                 ir_node *pred = get_irn_n(node, -1);
184                 if (pred->visited < irg->visited)
185                         cnt += irg_walk_2_post(pred, post, env);
186         }
187         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
188                 ir_node *pred = get_irn_n(node, i);
189                 if (pred->visited < irg->visited)
190                         cnt += irg_walk_2_post(pred, post, env);
191         }
192
193         post(node, env);
194
195         return cnt;
196 }
197
198 /**
199  * specialized version of irg_walk_2, called if pre and post callbacks exist
200  *
201  * @return number of visited nodes
202  */
203 static unsigned
204 irg_walk_2_both(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env) {
205         int i;
206         unsigned cnt = 1;
207         ir_graph *irg = current_ir_graph;
208
209         set_irn_visited(node, irg->visited);
210
211         pre(node, env);
212
213         if (node->op != op_Block) {
214                 ir_node *pred = get_irn_n(node, -1);
215                 if (pred->visited < irg->visited)
216                         cnt += irg_walk_2_both(pred, pre, post, env);
217         }
218         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
219                 ir_node *pred = get_irn_n(node, i);
220                 if (pred->visited < irg->visited)
221                         cnt += irg_walk_2_both(pred, pre, post, env);
222         }
223
224         post(node, env);
225
226         return cnt;
227 }
228
229 /**
230  * Intraprozedural graph walker.
231  *
232  * @return number of visited nodes
233  */
234 static unsigned
235 irg_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
236 {
237         if (node->visited < current_ir_graph->visited) {
238                 if      (!post) return irg_walk_2_pre (node, pre, env);
239                 else if (!pre)  return irg_walk_2_post(node, post, env);
240                 else            return irg_walk_2_both(node, pre, post, env);
241         }
242         return 0;
243 }
244
245 /* a counter */
246 static unsigned nodes_touched = 0;
247
248 /*
249  * generic graph walker
250  */
251 void irg_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
252 {
253         assert(is_ir_node(node));
254
255 #ifdef INTERPROCEDURAL_VIEW
256         if (get_interprocedural_view()) {
257                 pset_new_t           irg_set;
258                 pset_new_iterator_t  iter;
259                 ir_visited_t         visited;
260                 ir_graph            *irg;
261                 assert(get_irp_ip_view_state() == ip_view_valid);
262
263                 pset_new_init(&irg_set);
264                 set_interprocedural_view(0);
265                 pset_new_insert(&irg_set, current_ir_graph);
266                 irg_walk(node, (irg_walk_func *) collect_irgs, NULL, &irg_set);
267                 set_interprocedural_view(1);
268                 visited = get_max_irg_visited() + 1;
269
270                 foreach_pset_new(&irg_set, irg, iter) {
271                         set_irg_visited(irg, visited);
272                 }
273                 irg_walk_cg(node, visited, &irg_set, pre, post, env);
274                 pset_new_destroy(&irg_set);
275         } else {
276 #endif
277                 ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
278                 inc_irg_visited(current_ir_graph);
279                 nodes_touched = irg_walk_2(node, pre, post, env);
280                 ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
281 #ifdef INTERPROCEDURAL_VIEW
282         }
283 #endif
284 }
285
286 /*
287  * walk over a graph
288  */
289 void irg_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
290         ir_graph * rem = current_ir_graph;
291
292         hook_irg_walk(irg, (generic_func *)pre, (generic_func *)post);
293         current_ir_graph = irg;
294         irg_walk(get_irg_end(irg), pre, post, env);
295         irg->estimated_node_count = nodes_touched;
296         current_ir_graph = rem;
297 }
298
299 /* Executes irg_walk(end, pre, post, env) for all irgraphs in irprog.
300    Sets current_ir_graph properly for each walk.  Conserves current
301    current_ir_graph. */
302 void all_irg_walk(irg_walk_func *pre, irg_walk_func *post, void *env) {
303         int i, n;
304         ir_graph *irg;
305
306         for (i = 0, n = get_irp_n_irgs(); i < n; i++) {
307                 irg = get_irp_irg(i);
308                 irg_walk_graph(irg, pre, post, env);
309         }
310 }
311
312 /***************************************************************************/
313
314 /**
315  * specialized version of irg_walk_in_or_dep_2, called if only pre callback exists
316  *
317  * @return number of visited nodes
318  */
319 static unsigned
320 irg_walk_in_or_dep_2_pre(ir_node *node, irg_walk_func *pre, void *env) {
321         int i;
322         unsigned cnt = 1;
323         ir_graph *irg = current_ir_graph;
324
325         set_irn_visited(node, irg->visited);
326
327         pre(node, env);
328
329         if (node->op != op_Block) {
330                 ir_node *pred = get_irn_n(node, -1);
331                 if (pred->visited < irg->visited)
332                         cnt += irg_walk_in_or_dep_2_pre(pred, pre, env);
333         }
334         for (i = get_irn_ins_or_deps(node) - 1; i >= 0; --i) {
335                 ir_node *pred = get_irn_in_or_dep(node, i);
336                 if (pred->visited < irg->visited)
337                         cnt += irg_walk_in_or_dep_2_pre(pred, pre, env);
338         }
339         return cnt;
340 }
341
342 /**
343  * specialized version of irg_walk_in_or_dep_2, called if only post callback exists
344  *
345  * @return number of visited nodes
346  */
347 static unsigned
348 irg_walk_in_or_dep_2_post(ir_node *node, irg_walk_func *post, void *env) {
349         int i;
350         unsigned cnt = 1;
351         ir_graph *irg = current_ir_graph;
352
353         set_irn_visited(node, irg->visited);
354
355         if (node->op != op_Block) {
356                 ir_node *pred = get_irn_n(node, -1);
357                 if (pred->visited < irg->visited)
358                         cnt += irg_walk_in_or_dep_2_post(pred, post, env);
359         }
360         for (i = get_irn_ins_or_deps(node) - 1; i >= 0; --i) {
361                 ir_node *pred = get_irn_in_or_dep(node, i);
362                 if (pred->visited < irg->visited)
363                         cnt += irg_walk_in_or_dep_2_post(pred, post, env);
364         }
365
366         post(node, env);
367
368         return cnt;
369 }
370
371 /**
372  * specialized version of irg_walk_in_or_dep_2, called if pre and post callbacks exist
373  *
374  * @return number of visited nodes
375  */
376 static unsigned
377 irg_walk_in_or_dep_2_both(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env) {
378         int i;
379         unsigned cnt = 1;
380         ir_graph *irg = current_ir_graph;
381
382         set_irn_visited(node, irg->visited);
383
384         pre(node, env);
385
386         if (node->op != op_Block) {
387                 ir_node *pred = get_irn_n(node, -1);
388                 if (pred->visited < irg->visited)
389                         cnt += irg_walk_in_or_dep_2_both(pred, pre, post, env);
390         }
391         for (i = get_irn_ins_or_deps(node) - 1; i >= 0; --i) {
392                 ir_node *pred = get_irn_in_or_dep(node, i);
393                 if (pred->visited < irg->visited)
394                         cnt += irg_walk_in_or_dep_2_both(pred, pre, post, env);
395         }
396
397         post(node, env);
398
399         return cnt;
400 }
401
402 /**
403  * Intraprozedural graph walker. Follows dependency edges as well.
404  *
405  * @return number of visited nodes
406  */
407 static unsigned
408 irg_walk_in_or_dep_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
409 {
410         if (node->visited < current_ir_graph->visited) {
411                 if      (! post) return irg_walk_in_or_dep_2_pre (node, pre, env);
412                 else if (! pre)  return irg_walk_in_or_dep_2_post(node, post, env);
413                 else             return irg_walk_in_or_dep_2_both(node, pre, post, env);
414         }
415         return 0;
416 }
417
418 /*
419  * Generic graph walker. Follows dependency edges as well.
420  */
421 void irg_walk_in_or_dep(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
422 {
423         assert(is_ir_node(node));
424
425         if (get_interprocedural_view()) {
426                 assert(0 && "This is not yet implemented.");
427         } else {
428                 ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
429                 inc_irg_visited(current_ir_graph);
430                 nodes_touched = irg_walk_in_or_dep_2(node, pre, post, env);
431                 ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
432         }
433 }
434
435 /*
436  * Walk over a graph. Follow all edges (including dependencies)
437  */
438 void irg_walk_in_or_dep_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
439         ir_graph * rem = current_ir_graph;
440
441         hook_irg_walk(irg, (generic_func *)pre, (generic_func *)post);
442         current_ir_graph = irg;
443         irg_walk_in_or_dep(get_irg_end(irg), pre, post, env);
444         irg->estimated_node_count = nodes_touched;
445         current_ir_graph = rem;
446 }
447
448 /***************************************************************************/
449
450 /**
451  * Returns current_ir_graph and sets it to the irg of predecessor index
452  * of node n.
453  */
454 static INLINE ir_graph *
455 switch_irg(ir_node *n, int index) {
456         ir_graph *old_current = current_ir_graph;
457
458         if (get_interprocedural_view()) {
459                 /* Only Filter and Block nodes can have predecessors in other graphs. */
460                 if (is_Filter(n))
461                         n = get_nodes_block(n);
462                 if (is_Block(n)) {
463                         ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index));
464                         if (is_ip_cfop(cfop)) {
465                                 current_ir_graph = get_irn_irg(cfop);
466                         }
467                 }
468         }
469
470         return old_current;
471 }
472
473 static void
474 cg_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
475 {
476         int i;
477         ir_graph *rem = NULL;
478         assert(node);
479
480         if (get_irn_visited(node) < get_irg_visited(current_ir_graph)) {
481                 set_irn_visited(node, get_irg_visited(current_ir_graph));
482
483                 if (pre) pre(node, env);
484
485                 if (is_no_Block(node))
486                         cg_walk_2(get_nodes_block(node), pre, post, env);
487                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
488                         rem = switch_irg(node, i);  /* @@@ AS: Is this wrong? We do have to
489                                                     switch to the irg of the predecessor, don't we? */
490                         cg_walk_2(get_irn_n(node, i), pre, post, env);
491                         current_ir_graph = rem;
492                 }
493
494                 if (post) post(node, env);
495         }
496 }
497
498 #ifdef INTERPROCEDURAL_VIEW
499 /* Walks all irgs in interprocedural view.  Visits each node only once. */
500 void cg_walk(irg_walk_func *pre, irg_walk_func *post, void *env) {
501         int i;
502         ir_graph *rem = current_ir_graph;
503         int rem_view = get_interprocedural_view();
504
505         set_interprocedural_view(1);
506
507         inc_max_irg_visited();
508         /* Fix all irg_visited flags */
509         for (i = 0; i < get_irp_n_irgs(); i++)
510                 set_irg_visited(get_irp_irg(i), get_max_irg_visited());
511
512         /* Walk starting at unreachable procedures. Only these
513          * have End blocks visible in interprocedural view. */
514         for (i = 0; i < get_irp_n_irgs(); i++) {
515                 ir_node *sb;
516                 current_ir_graph = get_irp_irg(i);
517
518                 sb = get_irg_start_block(current_ir_graph);
519
520                 if ((get_Block_n_cfgpreds(sb) > 1) ||
521                         (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
522
523                 cg_walk_2(get_irg_end(current_ir_graph), pre, post, env);
524         }
525
526         /* Check whether we walked all procedures: there could be procedures
527            with cyclic calls but no call from the outside. */
528         for (i = 0; i < get_irp_n_irgs(); i++) {
529                 ir_node *sb;
530                 current_ir_graph = get_irp_irg(i);
531
532                 /* Test start block: if inner procedure end and end block are not
533                 * visible and therefore not marked. */
534                 sb = get_irg_start_block(current_ir_graph);
535                 if (get_irn_visited(sb) < get_irg_visited(current_ir_graph)) {
536                         cg_walk_2(sb, pre, post, env);
537                 }
538         }
539
540         /* Walk all endless loops in inner procedures.
541          * We recognize an inner procedure if the End node is not visited. */
542         for (i = 0; i < get_irp_n_irgs(); i++) {
543                 ir_node *e;
544                 current_ir_graph = get_irp_irg(i);
545                 e = get_irg_end(current_ir_graph);
546                 if (get_irn_visited(e) < get_irg_visited(current_ir_graph)) {
547                         int j;
548                         /* Don't visit the End node. */
549                         for (j = 0; j < get_End_n_keepalives(e); j++)
550                                 cg_walk_2(get_End_keepalive(e, j), pre, post, env);
551                 }
552         }
553
554         set_interprocedural_view(rem_view);
555         current_ir_graph = rem;
556 }
557 #endif
558
559
560 /***************************************************************************/
561
562 /* Walks back from n until it finds a real cf op. */
563 static ir_node *get_cf_op(ir_node *n) {
564         while (!is_cfop(n) && !is_fragile_op(n) && !is_Bad(n)) {
565                 n = skip_Id(n);
566                 n = skip_Tuple(n);
567                 n = skip_Proj(n);
568         }
569         return n;
570 }
571
572 static void irg_block_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
573 {
574         int i;
575
576         if (!Block_block_visited(node)) {
577                 mark_Block_block_visited(node);
578
579                 if(pre) pre(node, env);
580
581                 for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
582                         /* find the corresponding predecessor block. */
583                         ir_node *pred = get_cf_op(get_Block_cfgpred(node, i));
584                         pred = get_nodes_block(pred);
585                         if(get_irn_opcode(pred) == iro_Block) {
586                                 /* recursion */
587                                 irg_block_walk_2(pred, pre, post, env);
588                         }
589                         else {
590                                 assert(get_irn_opcode(pred) == iro_Bad);
591                         }
592                 }
593
594                 if(post) post(node, env);
595         }
596 }
597
598
599 /* walks only over Block nodes in the graph.  Has it's own visited
600    flag, so that it can be interleaved with the other walker.         */
601 void irg_block_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
602 {
603         ir_graph *irg = current_ir_graph;
604         ir_node *block, *pred;
605         int i;
606
607         hook_irg_block_walk(irg, node, (generic_func *)pre, (generic_func *)post);
608
609         assert(node);
610         assert(!get_interprocedural_view());   /* interprocedural_view not implemented, because it
611                                                * interleaves with irg_walk */
612         ir_reserve_resources(irg, IR_RESOURCE_BLOCK_VISITED);
613         inc_irg_block_visited(irg);
614         block = is_Block(node) ? node : get_nodes_block(node);
615         assert(is_Block(block));
616         irg_block_walk_2(block, pre, post, env);
617
618         /* keepalive: the endless loops ... */
619         if (is_End(node)) {
620                 int arity = get_irn_arity(node);
621                 for (i = 0; i < arity; i++) {
622                         pred = get_irn_n(node, i);
623                         if (is_Block(pred))
624                                 irg_block_walk_2(pred, pre, post, env);
625                 }
626                 /* Sometimes the blocks died, but are still reachable through Phis.
627                 * Make sure the algorithms that try to remove these reach them. */
628                 for (i = 0; i < arity; i++) {
629                         pred = get_irn_n(node, i);
630                         if (get_irn_op(pred) == op_Phi) {
631                                 ir_node *block = get_nodes_block(pred);
632
633                                 if (! is_Bad(block))
634                                         irg_block_walk_2(block, pre, post, env);
635                         }
636                 }
637         }
638
639         ir_free_resources(irg, IR_RESOURCE_BLOCK_VISITED);
640 }
641
642 /*
643  * walk over a graph block wise
644  */
645 void irg_block_walk_graph(ir_graph *irg, irg_walk_func *pre,
646               irg_walk_func *post, void *env) {
647         ir_graph * rem = current_ir_graph;
648         current_ir_graph = irg;
649         irg_block_walk(get_irg_end(irg), pre, post, env);
650         current_ir_graph = rem;
651 }
652
653 /*
654  * Additionally walk over all anchors. Do NOT increase the visit flag.
655  */
656 void irg_walk_anchors(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
657         ir_graph * rem = current_ir_graph;
658         current_ir_graph = irg;
659
660         inc_irg_visited(irg);
661         irg_walk_2(irg->anchor, pre, post, env);
662
663         current_ir_graph = rem;
664 }
665
666 /********************************************************************/
667
668 typedef struct walk_env {
669         irg_walk_func *pre;
670         irg_walk_func *post;
671         void *env;
672 } walk_env;
673
674 static void walk_initializer(ir_initializer_t *initializer, walk_env *env)
675 {
676         switch(initializer->kind) {
677     case IR_INITIALIZER_CONST:
678         irg_walk(initializer->consti.value, env->pre, env->post, env->env);
679         return;
680     case IR_INITIALIZER_TARVAL:
681     case IR_INITIALIZER_NULL:
682         return;
683
684     case IR_INITIALIZER_COMPOUND: {
685         size_t i;
686         for(i = 0; i < initializer->compound.n_initializers; ++i) {
687             ir_initializer_t *subinitializer
688                 = initializer->compound.initializers[i];
689             walk_initializer(subinitializer, env);
690         }
691         return;
692     }
693         }
694         panic("invalid initializer found");
695 }
696
697 /**
698  * Walk to all constant expressions in this entity.
699  */
700 static void walk_entity(ir_entity *ent, void *env)
701 {
702         walk_env *my_env = (walk_env *)env;
703
704         if (get_entity_variability(ent) != variability_uninitialized) {
705                 if (ent->has_initializer) {
706                         walk_initializer(ent->attr.initializer, my_env);
707                 } else if (is_atomic_entity(ent)) {
708                         irg_walk(get_atomic_ent_value(ent), my_env->pre, my_env->post, my_env->env);
709                 } else {
710                         int i, n_vals = get_compound_ent_n_values(ent);
711
712                         for (i = 0; i < n_vals; i++)
713                                 irg_walk(get_compound_ent_value(ent, i), my_env->pre, my_env->post, my_env->env);
714                 }
715         }
716 }
717
718 /* Walks over all code in const_code_irg. */
719 void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env) {
720         int i, j, n_types;
721         walk_env my_env;
722
723         ir_graph *rem = current_ir_graph;
724         current_ir_graph = get_const_code_irg();
725         inc_irg_visited(current_ir_graph);
726
727         my_env.pre = pre;
728         my_env.post = post;
729         my_env.env = env;
730
731         /* Walk all types that can contain constant entities.  */
732         walk_types_entities(get_glob_type(), &walk_entity, &my_env);
733         n_types = get_irp_n_types();
734         for (i = 0; i < n_types; i++)
735                 walk_types_entities(get_irp_type(i), &walk_entity, &my_env);
736         for (i = 0; i < get_irp_n_irgs(); i++)
737                 walk_types_entities(get_irg_frame_type(get_irp_irg(i)), &walk_entity, &my_env);
738
739         /* Walk constant array bounds. */
740         for (i = 0; i < n_types; i++) {
741                 ir_type *tp = get_irp_type(i);
742                 if (is_Array_type(tp)) {
743                         int n_dim = get_array_n_dimensions(tp);
744                         for (j = 0; j < n_dim; j++) {
745                                 ir_node *n = get_array_lower_bound(tp, j);
746                                 if (n) irg_walk(n, pre, post, env);
747                                 n = get_array_upper_bound(tp, j);
748                                 if (n) irg_walk(n, pre, post, env);
749                         }
750                 }
751         }
752
753         current_ir_graph = rem;
754 }