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);
75 if (op_NoMem == get_irn_op (node)) {
76 /* We don't want to see it it if it's not memory */
81 /* We don't want to see proj nodes at all --- skip over them */
82 in = get_Proj_pred (node);
84 irg_walk_mem_node (in, walk_env);
89 /* execute the 'pre' function */
90 if (NULL != walk_env->pre) {
91 walk_env->pre (node, walk_env->env);
98 in = get_Load_mem (node);
100 irg_walk_mem_node (in, walk_env);
103 in = get_Store_mem (node);
105 irg_walk_mem_node (in, walk_env);
108 in = get_Alloc_mem (node);
110 irg_walk_mem_node (in, walk_env);
113 in = get_Free_mem (node);
115 irg_walk_mem_node (in, walk_env);
118 in = get_Raise_mem (node);
120 irg_walk_mem_node (in, walk_env);
123 in = get_Sel_mem (node);
125 irg_walk_mem_node (in, walk_env);
128 in = get_Call_mem (node);
130 irg_walk_mem_node (in, walk_env);
133 in = get_Return_mem (node);
135 irg_walk_mem_node (in, walk_env);
139 int n_ins = get_irn_arity (node);
141 for (i = 0; i < n_ins; i ++) {
142 in = get_irn_n (node, i);
144 irg_walk_mem_node (in, walk_env);
148 in = get_Div_mem (node);
150 irg_walk_mem_node (in, walk_env);
153 in = get_Quot_mem (node);
155 irg_walk_mem_node (in, walk_env);
158 in = get_Mod_mem (node);
160 irg_walk_mem_node (in, walk_env);
163 in = get_DivMod_mem (node);
165 irg_walk_mem_node (in, walk_env);
170 int n_ins = get_irn_arity (node);
172 for (i = 0; i < n_ins; i ++) {
173 ir_node *ret = get_irn_n (node, i);
175 irg_walk_mem_node (ret, walk_env);
179 fprintf (stderr, "%s: 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.6 2004/12/02 16:17:51 beck
265 fixed config.h include
267 Revision 1.5 2004/11/19 10:35:20 liekweg
270 Revision 1.4 2004/11/18 16:35:11 liekweg
271 Do not touch Proj nodes at all
273 Revision 1.3 2004/11/04 14:57:12 liekweg
274 fixed end block handling
276 Revision 1.2 2004/10/22 14:41:12 liekweg
277 execute 'pre' for a change. Also, add CVS log