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 (NULL != walk_env->pre) {
76 walk_env->pre (node, walk_env->env);
83 in = get_Load_mem (node);
85 irg_walk_mem_node (in, walk_env);
88 in = get_Store_mem (node);
90 irg_walk_mem_node (in, walk_env);
93 in = get_Alloc_mem (node);
95 irg_walk_mem_node (in, walk_env);
98 in = get_Free_mem (node);
100 irg_walk_mem_node (in, walk_env);
103 in = get_Raise_mem (node);
105 irg_walk_mem_node (in, walk_env);
108 in = get_Sel_mem (node);
110 irg_walk_mem_node (in, walk_env);
113 in = get_Call_mem (node);
115 irg_walk_mem_node (in, walk_env);
118 in = get_Return_mem (node);
120 irg_walk_mem_node (in, walk_env);
123 in = get_Proj_pred (node);
125 irg_walk_mem_node (in, walk_env);
129 int n_ins = get_irn_arity (node);
131 for (i = 0; i < n_ins; i ++) {
132 in = get_irn_n (node, i);
134 irg_walk_mem_node (in, walk_env);
138 in = get_Div_mem (node);
140 irg_walk_mem_node (in, walk_env);
143 in = get_Quot_mem (node);
145 irg_walk_mem_node (in, walk_env);
148 in = get_Mod_mem (node);
150 irg_walk_mem_node (in, walk_env);
153 in = get_DivMod_mem (node);
155 irg_walk_mem_node (in, walk_env);
160 int n_ins = get_irn_arity (node);
162 for (i = 0; i < n_ins; i ++) {
163 ir_node *ret = get_irn_n (node, i);
165 irg_walk_mem_node (ret, walk_env);
169 assert (0 && "something not handled");
173 if (NULL != walk_env->post) {
174 walk_env->post (node, walk_env->env);
179 See whether the given graph is being visited right now.
180 We can't be visiting a graph multiple times.
182 int get_irg_is_mem_visited (ir_graph *graph)
184 walk_mem_env_t *walk_env = walk_envs;
186 while (NULL != walk_env) {
187 if (graph == walk_env->graph) {
191 walk_env = walk_env->prev;
198 Walk over the nodes of the given graph via the memory edges (only).
199 Each graph can only be subject to this walk once at any given time.
201 void irg_walk_mem (ir_graph *graph,
202 irg_walk_func *pre, irg_walk_func *post,
205 ir_node *end = get_irg_end_block (graph);
206 walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
208 assert (! get_irg_is_mem_visited (graph));
210 walk_env->graph = graph;
211 inc_irg_visited (walk_env->graph);
212 walk_env->visited = get_irg_visited (graph);
214 walk_env->prev = walk_envs;
215 walk_envs = walk_env;
218 walk_env->post = post;
221 /* 'graph' is not actually being visited right now, but it should be reported that way */
222 assert (get_irg_is_mem_visited (graph));
224 irg_walk_mem_node (end, walk_env);
226 The end NODE sometimes has some more ins. not sure whether we need to walk them.
229 /* allow only properly nested calls right now */
230 assert (walk_envs == walk_env);
231 walk_envs = walk_envs->prev;
235 assert (! get_irg_is_mem_visited (graph));
242 Revision 1.3 2004/11/04 14:57:12 liekweg
243 fixed end block handling
245 Revision 1.2 2004/10/22 14:41:12 liekweg
246 execute 'pre' for a change. Also, add CVS log