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 */
33 # endif /* not defined TRUE */
39 /* environment for a single memory walker */
40 typedef struct walk_mem_env_str {
41 ir_graph *graph; /* the graph we're visiting */
42 int visited; /* 'visited' marker */
43 irg_walk_func *pre; /* pre action */
44 irg_walk_func *post; /* post action */
45 void *env; /* user-defined environment */
47 struct walk_mem_env_str *prev; /* link up walking instances */
55 /* Link up walking instances */
56 static walk_mem_env_t *walk_envs = NULL;
59 Walk over the firm nodes of a graph via the memory edges (only)
60 starting from a node that has a memory input.
62 static void irg_walk_mem_node (ir_node *node,
63 walk_mem_env_t *walk_env)
65 const opcode op = get_irn_opcode (node);
68 if (get_irn_visited (node) >= walk_env->visited) {
71 set_irn_visited (node, walk_env->visited + 1);
74 fprintf (stdout, "Node (0x%08x).op = %s\n", (int)
76 get_op_name (get_irn_op (node)));
78 if (NULL != walk_env->pre) {
79 walk_env->pre (node, walk_env->env);
86 in = get_Load_mem (node);
88 irg_walk_mem_node (in, walk_env);
91 in = get_Store_mem (node);
93 irg_walk_mem_node (in, walk_env);
96 in = get_Alloc_mem (node);
98 irg_walk_mem_node (in, walk_env);
101 in = get_Free_mem (node);
103 irg_walk_mem_node (in, walk_env);
106 in = get_Raise_mem (node);
108 irg_walk_mem_node (in, walk_env);
111 in = get_Sel_mem (node);
113 irg_walk_mem_node (in, walk_env);
116 in = get_Call_mem (node);
118 irg_walk_mem_node (in, walk_env);
121 in = get_Return_mem (node);
123 irg_walk_mem_node (in, walk_env);
126 in = get_Proj_pred (node);
128 irg_walk_mem_node (in, walk_env);
132 int n_ins = get_irn_arity (node);
135 for (i = 0; i < n_ins; i ++) {
136 in = get_irn_n (node, i);
138 irg_walk_mem_node (in, walk_env);
142 in = get_Div_mem (node);
144 irg_walk_mem_node (in, walk_env);
147 in = get_Quot_mem (node);
149 irg_walk_mem_node (in, walk_env);
152 in = get_Mod_mem (node);
154 irg_walk_mem_node (in, walk_env);
157 in = get_DivMod_mem (node);
159 irg_walk_mem_node (in, walk_env);
162 assert (0 && "something not handled");
166 if (NULL != walk_env->post) {
167 walk_env->post (node, walk_env->env);
172 See whether the given graph is being visited right now.
173 We can't be visiting a graph multiple times.
175 int get_irg_is_mem_visited (ir_graph *graph)
177 walk_mem_env_t *walk_env = walk_envs;
179 while (NULL != walk_env) {
180 if (graph == walk_env->graph) {
184 walk_env = walk_env->prev;
191 Walk over the nodes of the given graph via the memory edges (only).
192 Each graph can only be subject to this walk once at any given time.
194 void irg_walk_mem (ir_graph *graph,
195 irg_walk_func *pre, irg_walk_func *post,
200 ir_node *end = get_irg_end_block (graph);
202 walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
204 assert (! get_irg_is_mem_visited (graph));
206 walk_env->graph = graph;
207 inc_irg_visited (walk_env->graph);
208 walk_env->visited = get_irg_visited (graph);
210 walk_env->prev = walk_envs;
211 walk_envs = walk_env;
214 walk_env->post = post;
217 /* 'graph' is not actually being visited right now, but it should be reported that way */
218 assert (get_irg_is_mem_visited (graph));
220 /* all return nodes */
221 n_ins = get_irn_arity (end);
222 for (i = 0; i < n_ins; i ++) {
223 ret = get_irn_n (end, i);
225 irg_walk_mem_node (ret, walk_env);
229 The end NODE sometimes has some more ins. not sure whether we need to walk them.
232 /* allow only properly nested calls right now */
233 assert (walk_envs == walk_env);
234 walk_envs = walk_envs->prev;
238 assert (! get_irg_is_mem_visited (graph));