don't rely on obstack hacks
[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, unsigned long 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 (get_irn_op(pred) == op_CallBegin
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 (get_irn_op(node) == op_Block) { /* 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 ((get_irn_op(pred) != op_CallBegin
84                                 && get_irn_op(pred) != op_EndReg
85                                 && get_irn_op(pred) != op_EndExcept)
86                                 || pset_new_contains(irg_set, get_irn_irg(pred))) {
87                                         irg_walk_cg(exec, visited, irg_set, pre, post, env);
88                         }
89                 }
90         } else if (get_irn_op(node) == op_Filter) { /* filter */
91                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
92                         ir_node * pred = get_irn_n(node, i);
93                         if (get_irn_op(pred) == op_Unknown || get_irn_op(pred) == op_Bad) {
94                                 irg_walk_cg(pred, visited, irg_set, pre, post, env);
95                         } else {
96                                 ir_node * exec;
97                                 exec = skip_Proj(get_Block_cfgpred(get_nodes_block(node), i));
98
99                                 if (op_Bad == get_irn_op (exec)) {
100                                         continue;
101                                 }
102
103                                 assert(get_irn_op(exec) == op_CallBegin
104                                         || get_irn_op(exec) == op_EndReg
105                                         || get_irn_op(exec) == op_EndExcept);
106                                 if (pset_new_contains(irg_set, get_irn_irg(exec))) {
107                                         current_ir_graph = get_irn_irg(exec);
108                                         irg_walk_cg(pred, visited, irg_set, pre, post, env);
109                                         current_ir_graph = rem;
110                                 }
111                         }
112                 }
113         } else {                      /* everything else */
114                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
115                         irg_walk_cg(get_irn_n(node, i), visited, irg_set, pre, post, env);
116                 }
117         }
118
119         if (post) post(node, env);
120
121         current_ir_graph = rem;
122 }
123
124
125 /**
126  * Insert all ir_graphs in irg_set, that are (transitive) reachable.
127  */
128 static void collect_irgs(ir_node * node, pset_new_t *irg_set) {
129         if (is_Call(node)) {
130                 int i;
131                 for (i = get_Call_n_callees(node) - 1; i >= 0; --i) {
132                         ir_entity * ent = get_Call_callee(node, i);
133                         ir_graph * irg = get_entity_irg(ent);
134                         if (irg && !pset_new_contains(irg_set, irg)) {
135                                 pset_new_insert(irg_set, irg);
136                                 irg_walk_graph(irg, (irg_walk_func *) collect_irgs, NULL, irg_set);
137                         }
138                 }
139         }
140 }
141
142 /**
143  * specialized version of irg_walk_2, called if only pre callback exists
144  *
145  * @return number of visited nodes
146  */
147 static unsigned
148 irg_walk_2_pre(ir_node *node, irg_walk_func *pre, void * env) {
149         int i;
150         unsigned cnt = 1;
151         ir_graph *irg = current_ir_graph;
152
153         set_irn_visited(node, irg->visited);
154
155         pre(node, env);
156
157         if (node->op != op_Block) {
158                 ir_node *pred = get_irn_n(node, -1);
159                 if (pred->visited < irg->visited)
160                         cnt += irg_walk_2_pre(pred, pre, env);
161         }
162         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
163                 ir_node *pred = get_irn_n(node, i);
164                 if (pred->visited < irg->visited)
165                         cnt += irg_walk_2_pre(pred, pre, env);
166         }
167         return cnt;
168 }
169
170 /**
171  * specialized version of irg_walk_2, called if only post callback exists
172  *
173  * @return number of visited nodes
174  */
175 static unsigned
176 irg_walk_2_post(ir_node *node, irg_walk_func *post, void * env) {
177         int i;
178         unsigned cnt = 1;
179         ir_graph *irg = current_ir_graph;
180
181         set_irn_visited(node, irg->visited);
182
183         if (node->op != op_Block) {
184                 ir_node *pred = get_irn_n(node, -1);
185                 if (pred->visited < irg->visited)
186                         cnt += irg_walk_2_post(pred, post, env);
187         }
188         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
189                 ir_node *pred = get_irn_n(node, i);
190                 if (pred->visited < irg->visited)
191                         cnt += irg_walk_2_post(pred, post, env);
192         }
193
194         post(node, env);
195
196         return cnt;
197 }
198
199 /**
200  * specialized version of irg_walk_2, called if pre and post callbacks exist
201  *
202  * @return number of visited nodes
203  */
204 static unsigned
205 irg_walk_2_both(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env) {
206         int i;
207         unsigned cnt = 1;
208         ir_graph *irg = current_ir_graph;
209
210         set_irn_visited(node, irg->visited);
211
212         pre(node, env);
213
214         if (node->op != op_Block) {
215                 ir_node *pred = get_irn_n(node, -1);
216                 if (pred->visited < irg->visited)
217                         cnt += irg_walk_2_both(pred, pre, post, env);
218         }
219         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
220                 ir_node *pred = get_irn_n(node, i);
221                 if (pred->visited < irg->visited)
222                         cnt += irg_walk_2_both(pred, pre, post, env);
223         }
224
225         post(node, env);
226
227         return cnt;
228 }
229
230 /**
231  * Intraprozedural graph walker.
232  *
233  * @return number of visited nodes
234  */
235 static unsigned
236 irg_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
237 {
238         if (node->visited < current_ir_graph->visited) {
239                 if      (!post) return irg_walk_2_pre (node, pre, env);
240                 else if (!pre)  return irg_walk_2_post(node, post, env);
241                 else            return irg_walk_2_both(node, pre, post, env);
242         }
243         return 0;
244 }
245
246 /* a counter */
247 static unsigned nodes_touched = 0;
248
249 /*
250  * generic graph walker
251  */
252 void irg_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
253 {
254         assert(is_ir_node(node));
255
256 #ifdef INTERPROCEDURAL_VIEW
257         if (get_interprocedural_view()) {
258                 pset_new_t           irg_set;
259                 pset_new_iterator_t  iter;
260                 unsigned long        visited;
261                 ir_graph            *irg;
262                 assert(get_irp_ip_view_state() == ip_view_valid);
263
264                 pset_new_init(&irg_set);
265                 set_interprocedural_view(0);
266                 pset_new_insert(&irg_set, current_ir_graph);
267                 irg_walk(node, (irg_walk_func *) collect_irgs, NULL, &irg_set);
268                 set_interprocedural_view(1);
269                 visited = get_max_irg_visited() + 1;
270
271                 foreach_pset_new(&irg_set, irg, iter) {
272                         set_irg_visited(irg, visited);
273                 }
274                 irg_walk_cg(node, visited, &irg_set, pre, post, env);
275                 pset_new_destroy(&irg_set);
276         } else {
277 #endif
278                 set_using_irn_visited(current_ir_graph);
279                 inc_irg_visited(current_ir_graph);
280                 nodes_touched = irg_walk_2(node, pre, post, env);
281                 clear_using_irn_visited(current_ir_graph);
282 #ifdef INTERPROCEDURAL_VIEW
283         }
284 #endif
285         return;
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                 set_using_irn_visited(current_ir_graph);
431                 inc_irg_visited(current_ir_graph);
432                 nodes_touched = irg_walk_in_or_dep_2(node, pre, post, env);
433                 clear_using_irn_visited(current_ir_graph);
434         }
435         return;
436 }
437
438 /*
439  * Walk over a graph. Follow all edges (including dependencies)
440  */
441 void irg_walk_in_or_dep_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
442         ir_graph * rem = current_ir_graph;
443
444         hook_irg_walk(irg, (generic_func *)pre, (generic_func *)post);
445         current_ir_graph = irg;
446         irg_walk_in_or_dep(get_irg_end(irg), pre, post, env);
447         irg->estimated_node_count = nodes_touched;
448         current_ir_graph = rem;
449 }
450
451 /***************************************************************************/
452
453 /**
454  * Returns current_ir_graph and sets it to the irg of predecessor index
455  * of node n.
456  */
457 static INLINE ir_graph *
458 switch_irg(ir_node *n, int index) {
459         ir_graph *old_current = current_ir_graph;
460
461         if (get_interprocedural_view()) {
462                 /* Only Filter and Block nodes can have predecessors in other graphs. */
463                 if (get_irn_op(n) == op_Filter)
464                         n = get_nodes_block(n);
465                 if (get_irn_op(n) == op_Block) {
466                         ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index));
467                         if (is_ip_cfop(cfop)) {
468                                 current_ir_graph = get_irn_irg(cfop);
469                         }
470                 }
471         }
472
473         return old_current;
474 }
475
476 static void
477 cg_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
478 {
479         int i;
480         ir_graph *rem = NULL;
481         assert(node);
482
483         if (get_irn_visited(node) < get_irg_visited(current_ir_graph)) {
484                 set_irn_visited(node, get_irg_visited(current_ir_graph));
485
486                 if (pre) pre(node, env);
487
488                 if (is_no_Block(node))
489                         cg_walk_2(get_nodes_block(node), pre, post, env);
490                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
491                         rem = switch_irg(node, i);  /* @@@ AS: Is this wrong? We do have to
492                                                     switch to the irg of the predecessor, don't we? */
493                         cg_walk_2(get_irn_n(node, i), pre, post, env);
494                         current_ir_graph = rem;
495                 }
496
497                 if (post) post(node, env);
498         }
499         return;
500 }
501
502 #ifdef INTERPROCEDURAL_VIEW
503 /* Walks all irgs in interprocedural view.  Visits each node only once. */
504 void cg_walk(irg_walk_func *pre, irg_walk_func *post, void *env) {
505         int i;
506         ir_graph *rem = current_ir_graph;
507         int rem_view = get_interprocedural_view();
508
509         set_interprocedural_view(1);
510
511         inc_max_irg_visited();
512         /* Fix all irg_visited flags */
513         for (i = 0; i < get_irp_n_irgs(); i++)
514                 set_irg_visited(get_irp_irg(i), get_max_irg_visited());
515
516         /* Walk starting at unreachable procedures. Only these
517          * have End blocks visible in interprocedural view. */
518         for (i = 0; i < get_irp_n_irgs(); i++) {
519                 ir_node *sb;
520                 current_ir_graph = get_irp_irg(i);
521
522                 sb = get_irg_start_block(current_ir_graph);
523
524                 if ((get_Block_n_cfgpreds(sb) > 1) ||
525                         (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
526
527                 cg_walk_2(get_irg_end(current_ir_graph), pre, post, env);
528         }
529
530         /* Check whether we walked all procedures: there could be procedures
531            with cyclic calls but no call from the outside. */
532         for (i = 0; i < get_irp_n_irgs(); i++) {
533                 ir_node *sb;
534                 current_ir_graph = get_irp_irg(i);
535
536                 /* Test start block: if inner procedure end and end block are not
537                 * visible and therefore not marked. */
538                 sb = get_irg_start_block(current_ir_graph);
539                 if (get_irn_visited(sb) < get_irg_visited(current_ir_graph)) {
540                         cg_walk_2(sb, pre, post, env);
541                 }
542         }
543
544         /* Walk all endless loops in inner procedures.
545          * We recognize an inner procedure if the End node is not visited. */
546         for (i = 0; i < get_irp_n_irgs(); i++) {
547                 ir_node *e;
548                 current_ir_graph = get_irp_irg(i);
549                 e = get_irg_end(current_ir_graph);
550                 if (get_irn_visited(e) < get_irg_visited(current_ir_graph)) {
551                         int j;
552                         /* Don't visit the End node. */
553                         for (j = 0; j < get_End_n_keepalives(e); j++)
554                                 cg_walk_2(get_End_keepalive(e, j), pre, post, env);
555                 }
556         }
557
558         set_interprocedural_view(rem_view);
559         current_ir_graph = rem;
560 }
561 #endif
562
563
564 /***************************************************************************/
565
566 /* Walks back from n until it finds a real cf op. */
567 static ir_node *get_cf_op(ir_node *n) {
568         ir_node *pred;
569
570         n = skip_Id(n);
571         n = skip_Tuple(n);
572         pred = skip_Proj(n);
573         if (!(is_cfop(pred) || is_fragile_op(pred) || is_Bad(pred)))
574                 n = get_cf_op(n);
575
576         return skip_Proj(n);
577 }
578
579 static void irg_block_walk_2(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
580 {
581         int i;
582
583         if (Block_not_block_visited(node)) {
584                 mark_Block_block_visited(node);
585
586                 if(pre) pre(node, env);
587
588                 for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
589                         /* find the corresponding predecessor block. */
590                         ir_node *pred = get_cf_op(get_Block_cfgpred(node, i));
591                         pred = get_nodes_block(pred);
592                         if(get_irn_opcode(pred) == iro_Block) {
593                                 /* recursion */
594                                 irg_block_walk_2(pred, pre, post, env);
595                         }
596                         else {
597                                 assert(get_irn_opcode(pred) == iro_Bad);
598                         }
599                 }
600
601                 if(post) post(node, env);
602         }
603 }
604
605
606 /* walks only over Block nodes in the graph.  Has it's own visited
607    flag, so that it can be interleaved with the other walker.         */
608 void irg_block_walk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
609 {
610         ir_node *block, *pred;
611         int i;
612
613         hook_irg_block_walk(current_ir_graph, node, (generic_func *)pre, (generic_func *)post);
614
615         assert(node);
616         assert(!get_interprocedural_view());   /* interprocedural_view not implemented, because it
617                                                * interleaves with irg_walk */
618         set_using_block_visited(current_ir_graph);
619         inc_irg_block_visited(current_ir_graph);
620         block = is_Block(node) ? node : get_nodes_block(node);
621         assert(get_irn_op(block) == op_Block);
622         irg_block_walk_2(block, pre, post, env);
623
624         /* keepalive: the endless loops ... */
625         if (get_irn_op(node) == op_End) {
626                 int arity = get_irn_arity(node);
627                 for (i = 0; i < arity; i++) {
628                         pred = get_irn_n(node, i);
629                         if (get_irn_op(pred) == op_Block)
630                                 irg_block_walk_2(pred, pre, post, env);
631                 }
632                 /* Sometimes the blocks died, but are still reachable through Phis.
633                 * Make sure the algorithms that try to remove these reach them. */
634                 for (i = 0; i < arity; i++) {
635                         pred = get_irn_n(node, i);
636                         if (get_irn_op(pred) == op_Phi) {
637                                 ir_node *block = get_nodes_block(pred);
638
639                                 if (! is_Bad(block))
640                                         irg_block_walk_2(block, pre, post, env);
641                         }
642                 }
643         }
644
645         clear_using_block_visited(current_ir_graph);
646 }
647
648 /*
649  * walk over a graph block wise
650  */
651 void irg_block_walk_graph(ir_graph *irg, irg_walk_func *pre,
652               irg_walk_func *post, void *env) {
653         ir_graph * rem = current_ir_graph;
654         current_ir_graph = irg;
655         irg_block_walk(get_irg_end(irg), pre, post, env);
656         current_ir_graph = rem;
657 }
658
659 /*
660  * Additionally walk over all anchors. Do NOT increase the visit flag.
661  */
662 void irg_walk_anchors(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
663         ir_graph * rem = current_ir_graph;
664         current_ir_graph = irg;
665
666         inc_irg_visited(irg);
667         irg_walk_2(irg->anchor, pre, post, env);
668
669         current_ir_graph = rem;
670 }
671
672 /********************************************************************/
673
674 typedef struct walk_env {
675         irg_walk_func *pre;
676         irg_walk_func *post;
677         void *env;
678 } walk_env;
679
680 static void walk_initializer(ir_initializer_t *initializer, walk_env *env)
681 {
682         switch(initializer->kind) {
683     case IR_INITIALIZER_CONST:
684         irg_walk(initializer->consti.value, env->pre, env->post, env->env);
685         return;
686     case IR_INITIALIZER_TARVAL:
687     case IR_INITIALIZER_NULL:
688         return;
689
690     case IR_INITIALIZER_COMPOUND: {
691         size_t i;
692         for(i = 0; i < initializer->compound.n_initializers; ++i) {
693             ir_initializer_t *subinitializer
694                 = initializer->compound.initializers[i];
695             walk_initializer(subinitializer, env);
696         }
697         return;
698     }
699         }
700         panic("invalid initializer found");
701 }
702
703 /**
704  * Walk to all constant expressions in this entity.
705  */
706 static void walk_entity(ir_entity *ent, void *env)
707 {
708         walk_env *my_env = (walk_env *)env;
709
710         if (get_entity_variability(ent) != variability_uninitialized) {
711                 if (ent->has_initializer) {
712                         walk_initializer(ent->attr.initializer, my_env);
713                 } else if (is_atomic_entity(ent)) {
714                         irg_walk(get_atomic_ent_value(ent), my_env->pre, my_env->post, my_env->env);
715                 } else {
716                         int i, n_vals = get_compound_ent_n_values(ent);
717
718                         for (i = 0; i < n_vals; i++)
719                                 irg_walk(get_compound_ent_value(ent, i), my_env->pre, my_env->post, my_env->env);
720                 }
721         }
722 }
723
724 /* Walks over all code in const_code_irg. */
725 void walk_const_code(irg_walk_func *pre, irg_walk_func *post, void *env) {
726         int i, j, n_types;
727         walk_env my_env;
728
729         ir_graph *rem = current_ir_graph;
730         current_ir_graph = get_const_code_irg();
731         inc_irg_visited(current_ir_graph);
732
733         my_env.pre = pre;
734         my_env.post = post;
735         my_env.env = env;
736
737         /* Walk all types that can contain constant entities.  */
738         walk_types_entities(get_glob_type(), &walk_entity, &my_env);
739         n_types = get_irp_n_types();
740         for (i = 0; i < n_types; i++)
741                 walk_types_entities(get_irp_type(i), &walk_entity, &my_env);
742         for (i = 0; i < get_irp_n_irgs(); i++)
743                 walk_types_entities(get_irg_frame_type(get_irp_irg(i)), &walk_entity, &my_env);
744
745         /* Walk constant array bounds. */
746         for (i = 0; i < n_types; i++) {
747                 ir_type *tp = get_irp_type(i);
748                 if (is_Array_type(tp)) {
749                         int n_dim = get_array_n_dimensions(tp);
750                         for (j = 0; j < n_dim; j++) {
751                                 ir_node *n = get_array_lower_bound(tp, j);
752                                 if (n) irg_walk(n, pre, post, env);
753                                 n = get_array_upper_bound(tp, j);
754                                 if (n) irg_walk(n, pre, post, env);
755                         }
756                 }
757         }
758
759         current_ir_graph = rem;
760 }