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