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