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