Summary is not a doxygen tag
[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  * @brief
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 #include <stdlib.h>
33
34 #include "irnode_t.h"
35 #include "irgraph_t.h"
36 #include "irprog.h"
37 #include "irgwalk.h"
38 #include "irhooks.h"
39 #include "ircgcons.h"
40 #include "entity_t.h"
41
42 #include "error.h"
43 #include "pset_new.h"
44 #include "array.h"
45
46 #ifdef INTERPROCEDURAL_VIEW
47 /**
48  * Walk over an interprocedural graph (callgraph).
49  * Visits only graphs in irg_set.
50  */
51 static void irg_walk_cg(ir_node * node, ir_visited_t visited,
52                         pset_new_t *irg_set, irg_walk_func *pre,
53                         irg_walk_func *post, void * env)
54 {
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  * Insert all ir_graphs in irg_set, that are (transitive) reachable.
125  */
126 static void collect_irgs(ir_node * node, pset_new_t *irg_set) {
127         if (is_Call(node)) {
128                 int i;
129                 for (i = get_Call_n_callees(node) - 1; i >= 0; --i) {
130                         ir_entity * ent = get_Call_callee(node, i);
131                         ir_graph * irg = get_entity_irg(ent);
132                         if (irg && !pset_new_contains(irg_set, irg)) {
133                                 pset_new_insert(irg_set, irg);
134                                 irg_walk_graph(irg, (irg_walk_func *) collect_irgs, NULL, irg_set);
135                         }
136                 }
137         }
138 }
139 #endif
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 #ifdef INTERPROCEDURAL_VIEW
474 static void
475 cg_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
476 {
477         int i;
478         ir_graph *rem = NULL;
479         assert(node);
480
481         if (get_irn_visited(node) < get_irg_visited(current_ir_graph)) {
482                 set_irn_visited(node, get_irg_visited(current_ir_graph));
483
484                 if (pre) pre(node, env);
485
486                 if (is_no_Block(node))
487                         cg_walk_2(get_nodes_block(node), pre, post, env);
488                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
489                         rem = switch_irg(node, i);  /* @@@ AS: Is this wrong? We do have to
490                                                     switch to the irg of the predecessor, don't we? */
491                         cg_walk_2(get_irn_n(node, i), pre, post, env);
492                         current_ir_graph = rem;
493                 }
494
495                 if (post) post(node, env);
496         }
497 }
498
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                                 pred = get_nodes_block(pred);
625                                 if (!is_Block(pred)) {
626                                         /* if rare cases a kept node might have a bad block input */
627                                         continue;
628                                 }
629                         }
630                         /* Sometimes the blocks died, but are still reachable through kept nodes.
631                          * Make sure the algorithms that try to remove these reach them. */
632                         irg_block_walk_2(pred, pre, post, env);
633                 }
634         }
635
636         ir_free_resources(irg, IR_RESOURCE_BLOCK_VISITED);
637 }
638
639 /*
640  * walk over a graph block wise
641  */
642 void irg_block_walk_graph(ir_graph *irg, irg_walk_func *pre,
643               irg_walk_func *post, void *env) {
644         ir_graph * rem = current_ir_graph;
645         current_ir_graph = irg;
646         irg_block_walk(get_irg_end(irg), pre, post, env);
647         current_ir_graph = rem;
648 }
649
650 /*
651  * Additionally walk over all anchors. Do NOT increase the visit flag.
652  */
653 void irg_walk_anchors(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
654         ir_graph * rem = current_ir_graph;
655         current_ir_graph = irg;
656
657         inc_irg_visited(irg);
658         irg_walk_2(irg->anchor, pre, post, env);
659
660         current_ir_graph = rem;
661 }
662
663 /********************************************************************/
664
665 typedef struct walk_env {
666         irg_walk_func *pre;
667         irg_walk_func *post;
668         void *env;
669 } walk_env;
670
671 static void walk_initializer(ir_initializer_t *initializer, walk_env *env)
672 {
673         switch(initializer->kind) {
674     case IR_INITIALIZER_CONST:
675         irg_walk(initializer->consti.value, env->pre, env->post, env->env);
676         return;
677     case IR_INITIALIZER_TARVAL:
678     case IR_INITIALIZER_NULL:
679         return;
680
681     case IR_INITIALIZER_COMPOUND: {
682         size_t i;
683         for(i = 0; i < initializer->compound.n_initializers; ++i) {
684             ir_initializer_t *subinitializer
685                 = initializer->compound.initializers[i];
686             walk_initializer(subinitializer, env);
687         }
688         return;
689     }
690         }
691         panic("invalid initializer found");
692 }
693
694 /**
695  * Walk to all constant expressions in this entity.
696  */
697 static void walk_entity(ir_entity *ent, void *env)
698 {
699         walk_env *my_env = (walk_env *)env;
700
701         if (get_entity_variability(ent) != variability_uninitialized) {
702                 if (ent->has_initializer) {
703                         walk_initializer(ent->attr.initializer, my_env);
704                 } else if (is_atomic_entity(ent)) {
705                         irg_walk(get_atomic_ent_value(ent), my_env->pre, my_env->post, my_env->env);
706                 } else {
707                         int i, n_vals = get_compound_ent_n_values(ent);
708
709                         for (i = 0; i < n_vals; i++)
710                                 irg_walk(get_compound_ent_value(ent, i), my_env->pre, my_env->post, my_env->env);
711                 }
712         }
713 }
714
715 /* Walks over all code in const_code_irg. */
716 void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env) {
717         int i, j, n_types;
718         walk_env my_env;
719
720         ir_graph *rem = current_ir_graph;
721         current_ir_graph = get_const_code_irg();
722         inc_irg_visited(current_ir_graph);
723
724         my_env.pre = pre;
725         my_env.post = post;
726         my_env.env = env;
727
728         /* Walk all types that can contain constant entities.  */
729         for (i = 0; i < IR_SEGMENT_COUNT; i++)
730                 walk_types_entities(get_segment_type((ir_segment_t) i), &walk_entity, &my_env);
731         n_types = get_irp_n_types();
732         for (i = 0; i < n_types; i++)
733                 walk_types_entities(get_irp_type(i), &walk_entity, &my_env);
734         for (i = 0; i < get_irp_n_irgs(); i++)
735                 walk_types_entities(get_irg_frame_type(get_irp_irg(i)), &walk_entity, &my_env);
736
737         /* Walk constant array bounds. */
738         for (i = 0; i < n_types; i++) {
739                 ir_type *tp = get_irp_type(i);
740                 if (is_Array_type(tp)) {
741                         int n_dim = get_array_n_dimensions(tp);
742                         for (j = 0; j < n_dim; j++) {
743                                 ir_node *n = get_array_lower_bound(tp, j);
744                                 if (n) irg_walk(n, pre, post, env);
745                                 n = get_array_upper_bound(tp, j);
746                                 if (n) irg_walk(n, pre, post, env);
747                         }
748                 }
749         }
750
751         current_ir_graph = rem;
752 }