update copyright message
[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 #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 #ifdef INTERPROCEDURAL_VIEW
255         if (get_interprocedural_view()) {
256                 pset_new_t           irg_set;
257                 pset_new_iterator_t  iter;
258                 unsigned long        visited;
259                 ir_graph            *irg;
260                 assert(get_irp_ip_view_state() == ip_view_valid);
261
262                 pset_new_init(&irg_set);
263                 set_interprocedural_view(0);
264                 pset_new_insert(&irg_set, current_ir_graph);
265                 irg_walk(node, (irg_walk_func *) collect_irgs, NULL, &irg_set);
266                 set_interprocedural_view(1);
267                 visited = get_max_irg_visited() + 1;
268
269                 foreach_pset_new(&irg_set, irg, iter) {
270                         set_irg_visited(irg, visited);
271                 }
272                 irg_walk_cg(node, visited, &irg_set, pre, post, env);
273                 pset_new_destroy(&irg_set);
274         } else {
275 #endif
276                 set_using_visited(current_ir_graph);
277                 inc_irg_visited(current_ir_graph);
278                 nodes_touched = irg_walk_2(node, pre, post, env);
279                 clear_using_visited(current_ir_graph);
280 #ifdef INTERPROCEDURAL_VIEW
281         }
282 #endif
283         return;
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                 set_using_visited(current_ir_graph);
429                 inc_irg_visited(current_ir_graph);
430                 nodes_touched = irg_walk_in_or_dep_2(node, pre, post, env);
431                 clear_using_visited(current_ir_graph);
432         }
433         return;
434 }
435
436 /*
437  * Walk over a graph. Follow all edges (including dependencies)
438  */
439 void irg_walk_in_or_dep_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
440         ir_graph * rem = current_ir_graph;
441
442         hook_irg_walk(irg, (generic_func *)pre, (generic_func *)post);
443         current_ir_graph = irg;
444         irg_walk_in_or_dep(get_irg_end(irg), pre, post, env);
445         irg->estimated_node_count = nodes_touched;
446         current_ir_graph = rem;
447 }
448
449 /***************************************************************************/
450
451 /**
452  * Returns current_ir_graph and sets it to the irg of predecessor index
453  * of node n.
454  */
455 static INLINE ir_graph *
456 switch_irg(ir_node *n, int index) {
457         ir_graph *old_current = current_ir_graph;
458
459         if (get_interprocedural_view()) {
460                 /* Only Filter and Block nodes can have predecessors in other graphs. */
461                 if (get_irn_op(n) == op_Filter)
462                         n = get_nodes_block(n);
463                 if (get_irn_op(n) == op_Block) {
464                         ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index));
465                         if (is_ip_cfop(cfop)) {
466                                 current_ir_graph = get_irn_irg(cfop);
467                         }
468                 }
469         }
470
471         return old_current;
472 }
473
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         return;
498 }
499
500 #ifdef INTERPROCEDURAL_VIEW
501 /* Walks all irgs in interprocedural view.  Visits each node only once. */
502 void cg_walk(irg_walk_func *pre, irg_walk_func *post, void *env) {
503         int i;
504         ir_graph *rem = current_ir_graph;
505         int rem_view = get_interprocedural_view();
506
507         set_interprocedural_view(1);
508
509         inc_max_irg_visited();
510         /* Fix all irg_visited flags */
511         for (i = 0; i < get_irp_n_irgs(); i++)
512                 set_irg_visited(get_irp_irg(i), get_max_irg_visited());
513
514         /* Walk starting at unreachable procedures. Only these
515          * have End blocks visible in interprocedural view. */
516         for (i = 0; i < get_irp_n_irgs(); i++) {
517                 ir_node *sb;
518                 current_ir_graph = get_irp_irg(i);
519
520                 sb = get_irg_start_block(current_ir_graph);
521
522                 if ((get_Block_n_cfgpreds(sb) > 1) ||
523                         (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
524
525                 cg_walk_2(get_irg_end(current_ir_graph), pre, post, env);
526         }
527
528         /* Check whether we walked all procedures: there could be procedures
529            with cyclic calls but no call from the outside. */
530         for (i = 0; i < get_irp_n_irgs(); i++) {
531                 ir_node *sb;
532                 current_ir_graph = get_irp_irg(i);
533
534                 /* Test start block: if inner procedure end and end block are not
535                 * visible and therefore not marked. */
536                 sb = get_irg_start_block(current_ir_graph);
537                 if (get_irn_visited(sb) < get_irg_visited(current_ir_graph)) {
538                         cg_walk_2(sb, pre, post, env);
539                 }
540         }
541
542         /* Walk all endless loops in inner procedures.
543          * We recognize an inner procedure if the End node is not visited. */
544         for (i = 0; i < get_irp_n_irgs(); i++) {
545                 ir_node *e;
546                 current_ir_graph = get_irp_irg(i);
547                 e = get_irg_end(current_ir_graph);
548                 if (get_irn_visited(e) < get_irg_visited(current_ir_graph)) {
549                         int j;
550                         /* Don't visit the End node. */
551                         for (j = 0; j < get_End_n_keepalives(e); j++)
552                                 cg_walk_2(get_End_keepalive(e, j), pre, post, env);
553                 }
554         }
555
556         set_interprocedural_view(rem_view);
557         current_ir_graph = rem;
558 }
559 #endif
560
561
562 /***************************************************************************/
563
564 /* Walks back from n until it finds a real cf op. */
565 static ir_node *get_cf_op(ir_node *n) {
566         ir_node *pred;
567
568         n = skip_Id(n);
569         n = skip_Tuple(n);
570         pred = skip_Proj(n);
571         if (!(is_cfop(pred) || is_fragile_op(pred) || is_Bad(pred)))
572                 n = get_cf_op(n);
573
574         return skip_Proj(n);
575 }
576
577 static void irg_block_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
578 {
579         int i;
580
581         if (Block_not_block_visited(node)) {
582                 mark_Block_block_visited(node);
583
584                 if(pre) pre(node, env);
585
586                 for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
587                         /* find the corresponding predecessor block. */
588                         ir_node *pred = get_cf_op(get_Block_cfgpred(node, i));
589                         pred = get_nodes_block(pred);
590                         if(get_irn_opcode(pred) == iro_Block) {
591                                 /* recursion */
592                                 irg_block_walk_2(pred, pre, post, env);
593                         }
594                         else {
595                                 assert(get_irn_opcode(pred) == iro_Bad);
596                         }
597                 }
598
599                 if(post) post(node, env);
600         }
601 }
602
603
604 /* walks only over Block nodes in the graph.  Has it's own visited
605    flag, so that it can be interleaved with the other walker.         */
606 void irg_block_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
607 {
608         ir_node *block, *pred;
609         int i;
610
611         hook_irg_block_walk(current_ir_graph, node, (generic_func *)pre, (generic_func *)post);
612
613         assert(node);
614         assert(!get_interprocedural_view());   /* interprocedural_view not implemented, because it
615                                                * interleaves with irg_walk */
616         set_using_block_visited(current_ir_graph);
617         inc_irg_block_visited(current_ir_graph);
618         block = is_Block(node) ? node : get_nodes_block(node);
619         assert(get_irn_op(block) == op_Block);
620         irg_block_walk_2(block, pre, post, env);
621
622         /* keepalive: the endless loops ... */
623         if (get_irn_op(node) == op_End) {
624                 int arity = get_irn_arity(node);
625                 for (i = 0; i < arity; i++) {
626                         pred = get_irn_n(node, i);
627                         if (get_irn_op(pred) == op_Block)
628                                 irg_block_walk_2(pred, pre, post, env);
629                 }
630                 /* Sometimes the blocks died, but are still reachable through Phis.
631                 * Make sure the algorithms that try to remove these reach them. */
632                 for (i = 0; i < arity; i++) {
633                         pred = get_irn_n(node, i);
634                         if (get_irn_op(pred) == op_Phi) {
635                                 ir_node *block = get_nodes_block(pred);
636
637                                 if (! is_Bad(block))
638                                         irg_block_walk_2(block, pre, post, env);
639                         }
640                 }
641         }
642
643         clear_using_block_visited(current_ir_graph);
644 }
645
646 /*
647  * walk over a graph block wise
648  */
649 void irg_block_walk_graph(ir_graph *irg, irg_walk_func *pre,
650               irg_walk_func *post, void *env) {
651         ir_graph * rem = current_ir_graph;
652         current_ir_graph = irg;
653         irg_block_walk(get_irg_end(irg), pre, post, env);
654         current_ir_graph = rem;
655 }
656
657 /*
658  * Additionally walk over all anchors. Do NOT increase the visit flag.
659  */
660 void irg_walk_anchors(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
661         ir_graph * rem = current_ir_graph;
662         current_ir_graph = irg;
663
664         inc_irg_visited(irg);
665         irg_walk_2(irg->anchor, pre, post, env);
666
667         current_ir_graph = rem;
668 }
669
670 /********************************************************************/
671
672 typedef struct walk_env {
673         irg_walk_func *pre;
674         irg_walk_func *post;
675         void *env;
676 } walk_env;
677
678 /**
679  * Walk to all constant expressions in this entity.
680  */
681 static void walk_entity(ir_entity *ent, void *env)
682 {
683         walk_env *my_env = (walk_env *)env;
684
685         if (get_entity_variability(ent) != variability_uninitialized) {
686                 if (is_atomic_entity(ent)) {
687                         irg_walk(get_atomic_ent_value(ent), my_env->pre, my_env->post, my_env->env);
688                 } else {
689                         int i, n_vals = get_compound_ent_n_values(ent);
690
691                         for (i = 0; i < n_vals; i++)
692                                 irg_walk(get_compound_ent_value(ent, i), my_env->pre, my_env->post, my_env->env);
693                 }
694         }
695 }
696
697 /* Walks over all code in const_code_irg. */
698 void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env) {
699         int i, j, n_types;
700         walk_env my_env;
701
702         ir_graph *rem = current_ir_graph;
703         current_ir_graph = get_const_code_irg();
704         inc_irg_visited(current_ir_graph);
705
706         my_env.pre = pre;
707         my_env.post = post;
708         my_env.env = env;
709
710         /* Walk all types that can contain constant entities.  */
711         walk_types_entities(get_glob_type(), &walk_entity, &my_env);
712         n_types = get_irp_n_types();
713         for (i = 0; i < n_types; i++)
714                 walk_types_entities(get_irp_type(i), &walk_entity, &my_env);
715         for (i = 0; i < get_irp_n_irgs(); i++)
716                 walk_types_entities(get_irg_frame_type(get_irp_irg(i)), &walk_entity, &my_env);
717
718         /* Walk constant array bounds. */
719         for (i = 0; i < n_types; i++) {
720                 ir_type *tp = get_irp_type(i);
721                 if (is_Array_type(tp)) {
722                         int n_dim = get_array_n_dimensions(tp);
723                         for (j = 0; j < n_dim; j++) {
724                                 ir_node *n = get_array_lower_bound(tp, j);
725                                 if (n) irg_walk(n, pre, post, env);
726                                 n = get_array_upper_bound(tp, j);
727                                 if (n) irg_walk(n, pre, post, env);
728                         }
729                 }
730         }
731
732         current_ir_graph = rem;
733 }