Addded method to replace in array os a node in irnode
[libfirm] / ir / ir / irgwalk.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Author: Boris Boesler
5 **
6 ** traverse an ir graph
7 ** - execute the pre function before recursion
8 ** - execute the post function after recursion
9 */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include "irnode.h"
16 # include "irgraph.h" /* visited flag */
17
18
19 void irg_walk_2(ir_node *node,
20               void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
21               void *env)
22 {
23   int i;
24
25
26   assert(node);
27   /*      printf(" - "); DDMSG2(node);  */
28
29   if (get_irn_visited(node) < get_irg_visited(current_ir_graph)) {
30
31 /*      printf(" -> "); DDMSG2(node);  */
32     set_irn_visited(node, get_irg_visited(current_ir_graph));
33
34     if (pre) {
35       pre(node, env);
36     }
37
38     if (is_no_Block(node)) {
39       irg_walk_2(get_nodes_Block(node), pre, post, env);
40     }
41     for (i = get_irn_arity(node) - 1; i >= 0; --i) {
42 /*        printf("   "); DDMSG2(node); */
43 /*        printf("   "); DDMSG2(get_irn_n(node, i)); */
44
45       irg_walk_2(get_irn_n(node, i), pre, post, env);
46     }
47
48 /*      printf(" <- "); DDMSG2(node);  */
49     if (post)
50       post(node, env);
51   }
52   return;
53 }
54
55
56 void irg_walk(ir_node *node,
57               void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
58               void *env)
59 {
60   assert(node);
61   inc_irg_visited (current_ir_graph);
62   irg_walk_2(node, pre, post, env);
63   return;
64 }
65
66 /***************************************************************************/
67
68 /* Walks back from n until it finds a real cf op. */
69 ir_node *get_cf_op(ir_node *n) {
70   ir_node *pred;
71
72   n = skip_nop(n);
73   n = skip_Tuple(n);
74   pred = skip_Proj(n);
75   if (!(is_cfop(pred) || is_fragile_op(pred) ||
76         (get_irn_op(pred) == op_Bad)))
77     n = get_cf_op(n);
78
79   return skip_Proj(n);
80 }
81
82 void irg_block_walk_2(ir_node *node, void (pre)(ir_node*, void*),
83                       void (post)(ir_node*, void*), void *env)
84 {
85   int i;
86
87   assert(get_irn_opcode(node) == iro_Block);
88
89   if(get_Block_block_visited(node) < get_irg_block_visited(current_ir_graph)) {
90     set_Block_block_visited(node, get_irg_block_visited(current_ir_graph));
91
92     if(pre)
93       pre(node, env);
94
95     for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
96
97       /* find the corresponding predecessor block. */
98       ir_node *pred = get_cf_op(get_Block_cfgpred(node, i));
99       /* GL: I'm not sure whether this assert must go through.  There
100          could be Id chains?? Tuple/Proj .... */
101
102       assert(is_cfop(pred) || is_fragile_op(pred) ||
103              (get_irn_op(pred) == op_Bad));
104       pred = get_nodes_Block(pred);
105       if(get_irn_opcode(pred) == iro_Block) {
106         /* recursion */
107         irg_block_walk_2(pred, pre, post, env);
108       }
109       else {
110         assert(get_irn_opcode(pred) == iro_Bad);
111       }
112     }
113
114     if(post)
115       post(node, env);
116   }
117   return;
118 }
119
120
121 /* walks only over Block nodes in the graph.  Has it's own visited
122    flag, so that it can be interleaved with the other walker.         */
123 void irg_block_walk(ir_node *node,
124                     void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
125                     void *env)
126 {
127   assert(node);
128   inc_irg_block_visited(current_ir_graph);
129   if (is_no_Block(node)) node = get_nodes_Block(node);
130   assert(get_irn_opcode(node)  == iro_Block);
131   irg_block_walk_2(node, pre, post, env);
132   return;
133 }