5 * File name: ir/ana2/irmemwalk.c
6 * Purpose: walk along memory edges
9 * Created: Mon 18 Oct 2004
11 * Copyright: (c) 1999-2004 Universität Karlsruhe
12 * Licence: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
16 Walk over a firm graph along its memory edges.
18 Any number of graphs can be visited at the same time, but no graph
19 can be traversed more than once at any time.
27 # include "irgwalk.h" /* for irg_walk_func */
28 # include "irprog.h" /* for get_irp_main_irg */
34 # endif /* not defined TRUE */
40 /* environment for a single memory walker */
41 typedef struct walk_mem_env_str {
42 ir_graph *graph; /* the graph we're visiting */
43 int visited; /* 'visited' marker */
44 irg_walk_func *pre; /* pre action */
45 irg_walk_func *post; /* post action */
46 void *env; /* user-defined environment */
48 struct walk_mem_env_str *prev; /* link up walking instances */
56 /* Link up walking instances */
57 static walk_mem_env_t *walk_envs = NULL;
60 Walk over the firm nodes of a graph via the memory edges (only)
61 starting from a node that has a memory input.
63 static void irg_walk_mem_node (ir_node *node,
64 walk_mem_env_t *walk_env)
66 const opcode op = get_irn_opcode (node);
69 if (get_irn_visited (node) >= walk_env->visited) {
72 set_irn_visited (node, walk_env->visited);
76 /* We don't want to see proj nodes at all --- skip over them */
77 in = get_Proj_pred (node);
79 irg_walk_mem_node (in, walk_env);
84 /* execute the 'pre' function */
85 if (NULL != walk_env->pre) {
86 walk_env->pre (node, walk_env->env);
93 in = get_Load_mem (node);
95 irg_walk_mem_node (in, walk_env);
98 in = get_Store_mem (node);
100 irg_walk_mem_node (in, walk_env);
103 in = get_Alloc_mem (node);
105 irg_walk_mem_node (in, walk_env);
108 in = get_Free_mem (node);
110 irg_walk_mem_node (in, walk_env);
113 in = get_Raise_mem (node);
115 irg_walk_mem_node (in, walk_env);
118 in = get_Sel_mem (node);
120 irg_walk_mem_node (in, walk_env);
123 in = get_Call_mem (node);
125 irg_walk_mem_node (in, walk_env);
128 in = get_Return_mem (node);
130 irg_walk_mem_node (in, walk_env);
134 int n_ins = get_irn_arity (node);
136 for (i = 0; i < n_ins; i ++) {
137 in = get_irn_n (node, i);
139 irg_walk_mem_node (in, walk_env);
143 in = get_Div_mem (node);
145 irg_walk_mem_node (in, walk_env);
148 in = get_Quot_mem (node);
150 irg_walk_mem_node (in, walk_env);
153 in = get_Mod_mem (node);
155 irg_walk_mem_node (in, walk_env);
158 in = get_DivMod_mem (node);
160 irg_walk_mem_node (in, walk_env);
165 int n_ins = get_irn_arity (node);
167 for (i = 0; i < n_ins; i ++) {
168 ir_node *ret = get_irn_n (node, i);
170 irg_walk_mem_node (ret, walk_env);
174 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
176 get_irn_node_nr (node),
177 get_op_name (get_irn_op (node)));
179 assert (0 && "something not handled");
183 /* execute the 'post' function */
184 if (NULL != walk_env->post) {
185 walk_env->post (node, walk_env->env);
190 See whether the given graph is being visited right now.
191 We can't be visiting a graph multiple times.
193 int get_irg_is_mem_visited (ir_graph *graph)
195 walk_mem_env_t *walk_env = walk_envs;
197 while (NULL != walk_env) {
198 if (graph == walk_env->graph) {
202 walk_env = walk_env->prev;
209 Walk over the nodes of the given graph via the memory edges (only).
210 Each graph can only be subject to this walk once at any given time.
212 void irg_walk_mem (ir_graph *graph,
213 irg_walk_func *pre, irg_walk_func *post,
216 ir_node *end_block = get_irg_end_block (graph);
217 walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
219 assert (! get_irg_is_mem_visited (graph));
221 walk_env->graph = graph;
222 inc_irg_visited (walk_env->graph);
223 walk_env->visited = get_irg_visited (graph);
225 walk_env->prev = walk_envs;
226 walk_envs = walk_env;
229 walk_env->post = post;
232 /* 'graph' is not actually being visited right now, so make sure it is reported that way */
233 assert (get_irg_is_mem_visited (graph));
236 The ins of the end BLOCK are either 'return's (regular exits) or
237 'ProjX'/'Raise's (exception exits). We only walk over the
238 'return' nodes, assuming that all memory-changing nodes are found
241 irg_walk_mem_node (end_block, walk_env);
243 The end NODE sometimes has some more ins. not sure whether we need to walk them.
246 /* allow only properly nested calls right now */
247 assert (walk_envs == walk_env);
248 walk_envs = walk_envs->prev;
252 assert (! get_irg_is_mem_visited (graph));
259 Revision 1.4 2004/11/18 16:35:11 liekweg
260 Do not touch Proj nodes at all
262 Revision 1.3 2004/11/04 14:57:12 liekweg
263 fixed end block handling
265 Revision 1.2 2004/10/22 14:41:12 liekweg
266 execute 'pre' for a change. Also, add CVS log