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 "irnode_t.h"
28 # include "irgwalk.h" /* for irg_walk_func */
29 # include "irprog.h" /* for get_irp_main_irg */
35 # endif /* not defined TRUE */
41 /** environment for a single memory walker */
42 typedef struct walk_mem_env_str {
43 ir_graph *graph; /**< the graph we're visiting */
44 unsigned long visited; /**< 'visited' marker */
45 irg_walk_func *pre; /**< pre action */
46 irg_walk_func *post; /**< post action */
47 void *env; /**< user-defined environment */
49 struct walk_mem_env_str *prev; /**< link up walking instances */
57 /* Link up walking instances */
58 static walk_mem_env_t *walk_envs = NULL;
61 Walk over the firm nodes of a graph via the memory edges (only)
62 starting from a node that has a memory input.
64 static void irg_walk_mem_node (ir_node *node,
65 walk_mem_env_t *walk_env)
67 const opcode op = get_irn_opcode (node);
70 if (get_irn_visited (node) >= walk_env->visited) {
73 set_irn_visited (node, walk_env->visited);
76 if (op_NoMem == get_irn_op (node)) {
77 /* We don't want to see it it if it's not memory */
82 /* We don't want to see proj nodes at all --- skip over them */
83 in = get_Proj_pred (node);
85 irg_walk_mem_node (in, walk_env);
90 /* execute the 'pre' function */
91 if (NULL != walk_env->pre) {
92 walk_env->pre (node, walk_env->env);
99 in = get_Load_mem (node);
101 irg_walk_mem_node (in, walk_env);
104 in = get_Store_mem (node);
106 irg_walk_mem_node (in, walk_env);
109 in = get_Alloc_mem (node);
111 irg_walk_mem_node (in, walk_env);
114 in = get_Free_mem (node);
116 irg_walk_mem_node (in, walk_env);
119 in = get_Raise_mem (node);
121 irg_walk_mem_node (in, walk_env);
124 in = get_Sel_mem (node);
126 irg_walk_mem_node (in, walk_env);
129 in = get_Call_mem (node);
131 irg_walk_mem_node (in, walk_env);
134 in = get_Return_mem (node);
136 irg_walk_mem_node (in, walk_env);
140 int n_ins = get_irn_arity (node);
142 for (i = 0; i < n_ins; i ++) {
143 in = get_irn_n (node, i);
145 irg_walk_mem_node (in, walk_env);
149 in = get_Div_mem (node);
151 irg_walk_mem_node (in, walk_env);
154 in = get_Quot_mem (node);
156 irg_walk_mem_node (in, walk_env);
159 in = get_Mod_mem (node);
161 irg_walk_mem_node (in, walk_env);
164 in = get_DivMod_mem (node);
166 irg_walk_mem_node (in, walk_env);
171 int n_ins = get_irn_arity (node);
173 for (i = 0; i < n_ins; i ++) {
174 ir_node *ret = get_irn_n (node, i);
176 irg_walk_mem_node (ret, walk_env);
180 fprintf (stderr, "irg_walk_mem_node(): not handled: node[%li].op = %s\n",
181 get_irn_node_nr (node),
182 get_op_name (get_irn_op (node)));
184 assert (0 && "something not handled");
188 /* execute the 'post' function */
189 if (NULL != walk_env->post) {
190 walk_env->post (node, walk_env->env);
195 See whether the given graph is being visited right now.
196 We can't be visiting a graph multiple times.
198 int get_irg_is_mem_visited (ir_graph *graph)
200 walk_mem_env_t *walk_env = walk_envs;
202 while (NULL != walk_env) {
203 if (graph == walk_env->graph) {
207 walk_env = walk_env->prev;
214 Walk over the nodes of the given graph via the memory edges (only).
215 Each graph can only be subject to this walk once at any given time.
217 void irg_walk_mem (ir_graph *graph,
218 irg_walk_func *pre, irg_walk_func *post,
221 ir_node *end_block = get_irg_end_block (graph);
222 walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
224 assert (! get_irg_is_mem_visited (graph));
226 walk_env->graph = graph;
227 inc_irg_visited (walk_env->graph);
228 walk_env->visited = get_irg_visited (graph);
230 walk_env->prev = walk_envs;
231 walk_envs = walk_env;
234 walk_env->post = post;
237 /* 'graph' is not actually being visited right now, so make sure it is reported that way */
238 assert (get_irg_is_mem_visited (graph));
241 The ins of the end BLOCK are either 'return's (regular exits) or
242 'ProjX'/'Raise's (exception exits). We only walk over the
243 'return' nodes, assuming that all memory-changing nodes are found
246 irg_walk_mem_node (end_block, walk_env);
248 The end NODE sometimes has some more ins. not sure whether we need to walk them.
251 /* allow only properly nested calls right now */
252 assert (walk_envs == walk_env);
253 walk_envs = walk_envs->prev;
257 assert (! get_irg_is_mem_visited (graph));
264 Revision 1.7 2004/12/21 14:25:35 beck
265 removed C99 constructs
266 make visit counter of same type as irn visit counter
268 Revision 1.6 2004/12/02 16:17:51 beck
269 fixed config.h include
271 Revision 1.5 2004/11/19 10:35:20 liekweg
274 Revision 1.4 2004/11/18 16:35:11 liekweg
275 Do not touch Proj nodes at all
277 Revision 1.3 2004/11/04 14:57:12 liekweg
278 fixed end block handling
280 Revision 1.2 2004/10/22 14:41:12 liekweg
281 execute 'pre' for a change. Also, add CVS log