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 */
36 # endif /* not defined TRUE */
42 /** environment for a single memory walker */
43 typedef struct walk_mem_env_str {
44 ir_graph *graph; /**< the graph we're visiting */
45 unsigned long visited; /**< 'visited' marker
46 (unsigned long in case we walk more than 2^32 graphs) */
47 irg_walk_func *pre; /**< pre action */
48 irg_walk_func *post; /**< post action */
49 void *env; /**< user-defined environment */
51 struct walk_mem_env_str *prev; /**< link up walking instances */
59 /* Link up walking instances */
60 static walk_mem_env_t *walk_envs = NULL;
63 Walk over the firm nodes of a graph via the memory edges (only)
64 starting from a node that has a memory input.
66 static void irg_walk_mem_node (ir_node *node,
67 walk_mem_env_t *walk_env)
69 const ir_opcode op = get_irn_opcode (node);
72 if (get_irn_visited (node) >= walk_env->visited) {
75 set_irn_visited (node, walk_env->visited);
78 if (op_NoMem == get_irn_op (node)) {
79 /* We don't want to see it it if it's not memory */
84 /* We don't want to see proj nodes at all --- skip over them */
85 in = get_Proj_pred (node);
87 irg_walk_mem_node (in, walk_env);
92 /* execute the 'pre' function */
93 if (NULL != walk_env->pre) {
94 walk_env->pre (node, walk_env->env);
101 in = get_Load_mem (node);
103 irg_walk_mem_node (in, walk_env);
106 in = get_Store_mem (node);
108 irg_walk_mem_node (in, walk_env);
111 in = get_Alloc_mem (node);
113 irg_walk_mem_node (in, walk_env);
116 in = get_Free_mem (node);
118 irg_walk_mem_node (in, walk_env);
121 in = get_Raise_mem (node);
123 irg_walk_mem_node (in, walk_env);
126 in = get_Sel_mem (node);
128 irg_walk_mem_node (in, walk_env);
131 in = get_Call_mem (node);
133 irg_walk_mem_node (in, walk_env);
136 in = get_Return_mem (node);
138 irg_walk_mem_node (in, walk_env);
142 int n_ins = get_irn_arity (node);
144 for (i = 0; i < n_ins; i ++) {
145 in = get_irn_n (node, i);
147 irg_walk_mem_node (in, walk_env);
151 in = get_Div_mem (node);
153 irg_walk_mem_node (in, walk_env);
156 in = get_Quot_mem (node);
158 irg_walk_mem_node (in, walk_env);
161 in = get_Mod_mem (node);
163 irg_walk_mem_node (in, walk_env);
166 in = get_DivMod_mem (node);
168 irg_walk_mem_node (in, walk_env);
173 int n_ins = get_irn_arity (node);
175 for (i = 0; i < n_ins; i ++) {
176 ir_node *ret = get_irn_n (node, i);
178 irg_walk_mem_node (ret, walk_env);
182 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
184 get_irn_node_nr (node),
185 get_op_name (get_irn_op (node)));
187 assert (0 && "something not handled");
191 /* execute the 'post' function */
192 if (NULL != walk_env->post) {
193 walk_env->post (node, walk_env->env);
198 See whether the given graph is being visited right now.
199 We can't be visiting a graph multiple times.
201 int get_irg_is_mem_visited (ir_graph *graph)
203 walk_mem_env_t *walk_env = walk_envs;
205 while (NULL != walk_env) {
206 if (graph == walk_env->graph) {
210 walk_env = walk_env->prev;
217 Walk over the nodes of the given graph via the memory edges (only).
218 Each graph can only be subject to this walk once at any given time.
220 void irg_walk_mem (ir_graph *graph,
221 irg_walk_func *pre, irg_walk_func *post,
224 ir_node *end_block = get_irg_end_block (graph);
225 walk_mem_env_t *walk_env = xmalloc (sizeof (walk_mem_env_t));
227 assert (! get_irg_is_mem_visited (graph));
229 walk_env->graph = graph;
230 inc_irg_visited (walk_env->graph);
231 walk_env->visited = get_irg_visited (graph);
233 walk_env->prev = walk_envs;
234 walk_envs = walk_env;
237 walk_env->post = post;
240 /* 'graph' is not actually being visited right now, so make sure it is reported that way */
241 assert (get_irg_is_mem_visited (graph));
244 The ins of the end BLOCK are either 'return's (regular exits) or
245 'ProjX'/'Raise's (exception exits). We only walk over the
246 'return' nodes, assuming that all memory-changing nodes are found
249 irg_walk_mem_node (end_block, walk_env);
251 The end NODE sometimes has some more ins. not sure whether we need to walk them.
254 /* allow only properly nested calls right now */
255 assert (walk_envs == walk_env);
256 walk_envs = walk_envs->prev;
260 assert (! get_irg_is_mem_visited (graph));
267 Revision 1.12 2007/01/16 15:45:42 beck
268 renamed type opcode to ir_opcode
270 Revision 1.11 2005/01/26 12:20:20 beck
273 Revision 1.10 2005/01/14 13:34:48 liekweg
276 Revision 1.9 2005/01/10 17:26:34 liekweg
277 fixup printfs, don't put environments on the stack
279 Revision 1.8 2004/12/22 14:43:14 beck
280 made allocations C-like
282 Revision 1.7 2004/12/21 14:25:35 beck
283 removed C99 constructs
284 make visit counter of same type as irn visit counter
286 Revision 1.6 2004/12/02 16:17:51 beck
287 fixed config.h include
289 Revision 1.5 2004/11/19 10:35:20 liekweg
292 Revision 1.4 2004/11/18 16:35:11 liekweg
293 Do not touch Proj nodes at all
295 Revision 1.3 2004/11/04 14:57:12 liekweg
296 fixed end block handling
298 Revision 1.2 2004/10/22 14:41:12 liekweg
299 execute 'pre' for a change. Also, add CVS log