27769fd7539de8e12ac2dffe079df7c463c9ace9
[libfirm] / ir / ana2 / pto.c
1 /* -*- c -*- */
2
3 /*
4  * Project:     libFIRM
5  * File name:   ir/ana/pto.c
6  * Purpose:     Pto
7  * Author:      Florian
8  * Modified by:
9  * Created:     Mon 18 Oct 2004
10  * CVS-ID:      $Id$
11  * Copyright:   (c) 1999-2004 Universität Karlsruhe
12  * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
13  */
14
15
16 # ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 # endif
19
20 # include "pto.h"
21
22 # include "irnode_t.h"
23 # include "irprog_t.h"
24
25 # include "eset.h"
26 # include "irgwalk.h"
27 # include "irgmod.h"
28 # include "irvrfy.h"
29 # include "trvrfy.h"
30 # include "xmalloc.h"
31
32 # ifndef TRUE
33 #  define TRUE 1
34 #  define FALSE 0
35 # endif /* not defined TRUE */
36
37 typedef struct walk_mem_env_str {
38   ir_graph *graph;              /* the graph we're visiting */
39   int visited;                  /* 'visited' marker */
40   irg_walk_func *pre;           /* pre action */
41   irg_walk_func *post;          /* post action */
42   void *env;                    /* user-defined environment */
43
44   struct walk_mem_env_str *prev; /* link up walking instances */
45   /* what else? */
46 } walk_mem_env_t;
47
48 /* Link up walking instances */
49 static walk_mem_env_t *walk_envs = NULL;
50
51 /* MEMORY WALK */
52
53 /* BEGIN TEST */
54 static void print_node_pre (ir_node *node, void *__unused)
55 {
56   fprintf (stdout, "PRE  MEM Node (0x%08x) (%s)\n",
57            (int)  node,
58            get_op_name (get_irn_op (node)));
59 }
60
61 static void print_node_post (ir_node *node, void *__unused)
62 {
63   const opcode op = get_irn_opcode (node);
64
65
66   if (iro_Call == op) {
67     entity *ent = NULL;
68     ir_graph *graph = NULL;
69     fprintf (stdout, "POST MEM Call Node (0x%08x)\n",
70              (int) node);
71
72     ir_node *ptr = get_Call_ptr (node);
73
74     if (iro_Sel == get_irn_opcode (ptr)) {
75       ent = get_Sel_entity (ptr);
76     } else if (iro_SymConst == get_irn_opcode (ptr)) {
77       if (get_SymConst_kind(ptr) == symconst_addr_ent) {
78         ent = get_SymConst_entity (ptr);
79       }
80     }
81
82     if (NULL != ent) {
83       graph = get_entity_irg (ent);
84       if (NULL != graph) {
85         if (! get_irg_is_mem_visited (graph)) {
86
87           fprintf (stdout, " -> visit  graph (0x%08x) of \"%s.%s\"\n",
88                    (int) graph,
89                    get_type_name (get_entity_owner (get_irg_entity (graph))),
90                    get_entity_name (get_irg_entity (graph)));
91
92           irg_walk_mem (graph, print_node_pre, print_node_post, NULL);
93         }
94       }
95     }
96
97   } else {
98     fprintf (stdout, "POST MEM Node (0x%08x) (%s)\n",
99              (int)  node,
100              get_op_name (get_irn_op (node)));
101   }
102
103 }
104
105
106 /* END TEST */
107
108 /*
109    See whether the given graph is being visited right now.
110 */
111 int get_irg_is_mem_visited (ir_graph *graph)
112 {
113   walk_mem_env_t *walk_env = walk_envs;
114
115   while (NULL != walk_env) {
116     if (graph == walk_env->graph) {
117       return (TRUE);
118     }
119
120     walk_env = walk_env->prev;
121   }
122
123   return (FALSE);
124 }
125
126 /*
127   Walk over the firm nodes of a graph via the memory edges (only)
128   starting from a node that has a memory input.
129 */
130 void irg_walk_mem_node (ir_node *node,
131                         walk_mem_env_t *walk_env)
132 {
133   const opcode op = get_irn_opcode (node);
134   ir_node *in = NULL;
135
136   if (get_irn_visited (node) >= walk_env->visited) {
137     return;
138   } else {
139     set_irn_visited (node, walk_env->visited + 1);
140   }
141
142   fprintf (stdout, "Node (0x%08x).op = %s\n", (int)
143            node,
144            get_op_name (get_irn_op (node)));
145
146   if (NULL != walk_env->pre) {
147     walk_env->pre (node, walk_env->env);
148   }
149
150   switch (op) {
151   case (iro_Start): {
152   } break;
153   case (iro_Load): {
154     in = get_Load_mem (node);
155
156     irg_walk_mem_node (in, walk_env);
157   } break;
158   case (iro_Store): {
159     in = get_Store_mem (node);
160
161     irg_walk_mem_node (in, walk_env);
162   } break;
163   case (iro_Alloc): {
164     in = get_Alloc_mem (node);
165
166     irg_walk_mem_node (in, walk_env);
167   } break;
168   case (iro_Free): {
169     in = get_Free_mem (node);
170     /* WTF? */
171     irg_walk_mem_node (in, walk_env);
172   } break;
173   case (iro_Raise): {
174     in = get_Raise_mem (node);
175
176     irg_walk_mem_node (in, walk_env);
177   } break;
178   case (iro_Sel): {
179     in = get_Sel_mem (node);
180
181     irg_walk_mem_node (in, walk_env);
182   } break;
183   case (iro_Call): {
184     in = get_Call_mem (node);
185
186     irg_walk_mem_node (in, walk_env);
187   } break;
188   case (iro_Return): {
189     in = get_Return_mem (node);
190
191     irg_walk_mem_node (in, walk_env);
192   } break;
193   case (iro_Proj): {
194     in = get_Proj_pred (node);
195
196     irg_walk_mem_node (in, walk_env);
197   } break;
198   case (iro_Phi): {
199     int i;
200     int n_ins = get_irn_arity (node);
201
202
203     for (i = 0; i < n_ins; i ++) {
204       in = get_irn_n (node, i);
205
206       irg_walk_mem_node (in, walk_env);
207     }
208   } break;
209   case (iro_Div): {
210     in = get_Div_mem (node);
211
212     irg_walk_mem_node (in, walk_env);
213   } break;
214   case (iro_Quot): {
215     in = get_Quot_mem (node);
216
217     irg_walk_mem_node (in, walk_env);
218   } break;
219   case (iro_Mod): {
220     in = get_Mod_mem (node);
221
222     irg_walk_mem_node (in, walk_env);
223   } break;
224   case (iro_DivMod): {
225     in = get_DivMod_mem (node);
226
227     irg_walk_mem_node (in, walk_env);
228   } break;
229   default: {
230     assert (0 && "something not handled");
231   }
232   }
233
234   if (NULL != walk_env->post) {
235     walk_env->post (node, walk_env->env);
236   }
237 }
238
239 /*
240   Walk over the nodes of the given graph via the memory edges (only).
241   Each graph can only be subject to this walk once at any given time.
242 */
243 void irg_walk_mem (ir_graph *graph,
244                    irg_walk_func *pre, irg_walk_func *post,
245                    void *env)
246 {
247   int i;
248   ir_node *ret = NULL;
249   ir_node *end = get_irg_end_block (graph);
250   int n_ins;
251   walk_mem_env_t *walk_env = (walk_mem_env_t*) xmalloc (sizeof (walk_mem_env_t));
252
253   assert (! get_irg_is_mem_visited (graph));
254
255   walk_env->graph = graph;
256   inc_irg_visited (walk_env->graph);
257   walk_env->visited = get_irg_visited (graph);
258
259   walk_env->prev = walk_envs;
260   walk_envs = walk_env;
261
262   walk_env->pre = pre;
263   walk_env->post = post;
264   walk_env->env  = env;
265
266   /* 'graph' is not actually being visited right now, but it should be reported that way */
267   assert (get_irg_is_mem_visited (graph));
268
269   /* all return nodes */
270   n_ins = get_irn_arity (end);
271   for (i = 0; i < n_ins; i ++) {
272     ret = get_irn_n (end, i);
273
274     irg_walk_mem_node (ret, walk_env);
275   }
276
277   /*
278     The end NODE sometimes has some more ins. not sure whether we need to walk them.
279   */
280
281   /* allow only properly nested calls right now */
282   assert (walk_envs == walk_env);
283   walk_envs = walk_envs->prev;
284
285   free (walk_env);
286
287   assert (! get_irg_is_mem_visited (graph));
288 }
289
290 /*
291    Test irg_walk_mem
292 */
293 void pto_test_mem ()
294 {
295   int i;
296
297   fprintf (stdout, "START PTO TEST\n");
298
299   for (i = 0; i < get_irp_n_irgs(); i++) {
300     ir_graph *graph = get_irp_irg (i);
301
302     fprintf (stdout, "START GRAPH (0x%08x) of \"%s.%s\"\n",
303              (int) graph,
304              get_type_name (get_entity_owner (get_irg_entity (graph))),
305              get_entity_name (get_irg_entity (graph)));
306     irg_walk_mem (graph, print_node_pre, print_node_post, NULL);
307     fprintf (stdout, "END   GRAPH (0x%08x)\n", (int) graph);
308   }
309
310   fprintf (stdout, "END   PTO TEST\n");
311 }
312
313
314 /*
315  * $Log$
316  * Revision 1.1  2004/10/20 14:59:42  liekweg
317  * Added ana2, added ecg and pto
318  *
319  */