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 (unsigned long in case we walk more than 2^32 graphs) */
46 irg_walk_func *pre; /**< pre action */
47 irg_walk_func *post; /**< post action */
48 void *env; /**< user-defined environment */
50 struct walk_mem_env_str *prev; /**< link up walking instances */
58 /* Link up walking instances */
59 static walk_mem_env_t *walk_envs = NULL;
62 Walk over the firm nodes of a graph via the memory edges (only)
63 starting from a node that has a memory input.
65 static void irg_walk_mem_node (ir_node *node,
66 walk_mem_env_t *walk_env)
68 const opcode op = get_irn_opcode (node);
71 if (get_irn_visited (node) >= walk_env->visited) {
74 set_irn_visited (node, walk_env->visited);
77 if (op_NoMem == get_irn_op (node)) {
78 /* We don't want to see it it if it's not memory */
83 /* We don't want to see proj nodes at all --- skip over them */
84 in = get_Proj_pred (node);
86 irg_walk_mem_node (in, walk_env);
91 /* execute the 'pre' function */
92 if (NULL != walk_env->pre) {
93 walk_env->pre (node, walk_env->env);
100 in = get_Load_mem (node);
102 irg_walk_mem_node (in, walk_env);
105 in = get_Store_mem (node);
107 irg_walk_mem_node (in, walk_env);
110 in = get_Alloc_mem (node);
112 irg_walk_mem_node (in, walk_env);
115 in = get_Free_mem (node);
117 irg_walk_mem_node (in, walk_env);
120 in = get_Raise_mem (node);
122 irg_walk_mem_node (in, walk_env);
125 in = get_Sel_mem (node);
127 irg_walk_mem_node (in, walk_env);
130 in = get_Call_mem (node);
132 irg_walk_mem_node (in, walk_env);
135 in = get_Return_mem (node);
137 irg_walk_mem_node (in, walk_env);
141 int n_ins = get_irn_arity (node);
143 for (i = 0; i < n_ins; i ++) {
144 in = get_irn_n (node, i);
146 irg_walk_mem_node (in, walk_env);
150 in = get_Div_mem (node);
152 irg_walk_mem_node (in, walk_env);
155 in = get_Quot_mem (node);
157 irg_walk_mem_node (in, walk_env);
160 in = get_Mod_mem (node);
162 irg_walk_mem_node (in, walk_env);
165 in = get_DivMod_mem (node);
167 irg_walk_mem_node (in, walk_env);
172 int n_ins = get_irn_arity (node);
174 for (i = 0; i < n_ins; i ++) {
175 ir_node *ret = get_irn_n (node, i);
177 irg_walk_mem_node (ret, walk_env);
181 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
183 get_irn_node_nr (node),
184 get_op_name (get_irn_op (node)));
186 assert (0 && "something not handled");
190 /* execute the 'post' function */
191 if (NULL != walk_env->post) {
192 walk_env->post (node, walk_env->env);
197 See whether the given graph is being visited right now.
198 We can't be visiting a graph multiple times.
200 int get_irg_is_mem_visited (ir_graph *graph)
202 walk_mem_env_t *walk_env = walk_envs;
204 while (NULL != walk_env) {
205 if (graph == walk_env->graph) {
209 walk_env = walk_env->prev;
216 Walk over the nodes of the given graph via the memory edges (only).
217 Each graph can only be subject to this walk once at any given time.
219 void irg_walk_mem (ir_graph *graph,
220 irg_walk_func *pre, irg_walk_func *post,
223 ir_node *end_block = get_irg_end_block (graph);
224 walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
226 assert (! get_irg_is_mem_visited (graph));
228 walk_env->graph = graph;
229 inc_irg_visited (walk_env->graph);
230 walk_env->visited = get_irg_visited (graph);
232 walk_env->prev = walk_envs;
233 walk_envs = walk_env;
236 walk_env->post = post;
239 /* 'graph' is not actually being visited right now, so make sure it is reported that way */
240 assert (get_irg_is_mem_visited (graph));
243 The ins of the end BLOCK are either 'return's (regular exits) or
244 'ProjX'/'Raise's (exception exits). We only walk over the
245 'return' nodes, assuming that all memory-changing nodes are found
248 irg_walk_mem_node (end_block, walk_env);
250 The end NODE sometimes has some more ins. not sure whether we need to walk them.
253 /* allow only properly nested calls right now */
254 assert (walk_envs == walk_env);
255 walk_envs = walk_envs->prev;
259 assert (! get_irg_is_mem_visited (graph));
266 Revision 1.9 2005/01/10 17:26:34 liekweg
267 fixup printfs, don't put environments on the stack
269 Revision 1.8 2004/12/22 14:43:14 beck
270 made allocations C-like
272 Revision 1.7 2004/12/21 14:25:35 beck
273 removed C99 constructs
274 make visit counter of same type as irn visit counter
276 Revision 1.6 2004/12/02 16:17:51 beck
277 fixed config.h include
279 Revision 1.5 2004/11/19 10:35:20 liekweg
282 Revision 1.4 2004/11/18 16:35:11 liekweg
283 Do not touch Proj nodes at all
285 Revision 1.3 2004/11/04 14:57:12 liekweg
286 fixed end block handling
288 Revision 1.2 2004/10/22 14:41:12 liekweg
289 execute 'pre' for a change. Also, add CVS log