5 File name: ir/ana/pto_comp.c
6 Purpose: Main Implementation of PTO
9 Created: Sat Nov 13 19:35:27 CET 2004
11 Copyright: (c) 1999-2004 Universität Karlsruhe
12 Licence: This file is protected by the GPL - GNU GENERAL PUBLIC LICENSE.
20 pto_comp: Main Implementation of PTO
23 # include <string.h> /* for memset */
25 # include "pto_comp.h"
26 # include "pto_util.h"
27 # include "pto_name.h"
33 # include "irmemwalk.h"
35 # include "pto_debug.h"
36 # include "pto_init.h"
42 /* Local Data Types: */
43 typedef struct pto_env_str {
48 /* Local Variables: */
53 /* Local Prototypes: */
54 static void pto_call (ir_graph*, ir_node*, pto_env_t*);
56 /* ===================================================
58 =================================================== */
60 /* Propagation of PTO values */
61 static pto_t *get_pto_proj (ir_node *proj)
63 ir_node *proj_in = get_Proj_pred (proj);
64 const long proj_proj = get_Proj_proj (proj);
65 const opcode in_op = get_irn_opcode (proj_in);
67 pto_t *proj_pto = get_node_pto (proj);
69 ir_node *proj_in_in = NULL;
72 case (iro_Start): /* ProjT (Start) */
73 assert (0 && "pto from ProjT(Start) requested");
76 case (iro_Proj): /* ProjT (Start), ProjT (Call) */
77 proj_in_in = get_Proj_pred (proj_in);
78 const opcode in_in_op = get_irn_opcode (proj_in_in);
79 const long proj_in_proj = get_Proj_proj (proj_in);
81 assert ((pn_Start_T_args == proj_in_proj) ||
82 (pn_Call_T_result == proj_in_proj));
85 case (iro_Start): /* ProjArg (ProjT (Start)) */
86 /* then the pto value must have been set to the node */
90 case (iro_Call): /* ProjV (ProjT (Call)) */
91 if (NULL != proj_pto) {
94 in_pto = get_node_pto (proj_in);
95 set_node_pto (proj, in_pto);
99 default: assert (0 && "Proj(Proj(?))");
101 /* done with case (in_op == iro_Proj) */
103 case (iro_Load): /* ProjV (Load) */
104 assert (pn_Load_res == proj_proj);
106 case (iro_Call): /* ProjT (Call) */
108 case (iro_Alloc): /* ProjV (Alloc) */
109 if (NULL != proj_pto) {
112 in_pto = get_node_pto (proj_in);
115 set_node_pto (proj, in_pto);
119 fprintf (stderr, "%s: not handled: proj (%s[%li])\n",
121 get_op_name (get_irn_op (proj_in)),
122 get_irn_node_nr (proj_in));
123 assert (0 && "Proj(?)");
128 static pto_t *get_pto_phi (ir_node *phi)
133 static pto_t *get_pto_sel (ir_node *sel)
135 pto_t *pto = get_node_pto (sel);
138 ir_node *in = get_Sel_ptr (sel);
140 pto = get_node_pto (in);
141 set_node_pto (sel, pto);
147 static pto_t *get_pto_ret (ir_node *ret)
149 pto_t *pto = get_node_pto (ret);
152 ir_node *in = get_Return_res (ret, 0);
154 pto = get_node_pto (in);
155 set_node_pto (ret, pto);
162 /* Dispatch to propagate PTO values */
163 static pto_t *get_pto (ir_node *node)
165 const opcode op = get_irn_opcode (node);
168 case (iro_Cast): return (get_pto (get_Cast_op (node)));
169 case (iro_Proj): return (get_pto_proj (node));
170 case (iro_Phi): return (get_pto_phi (node));
171 case (iro_Sel): return (get_pto_sel (node));
172 case (iro_Return): return (get_pto_ret (node));
175 /* stopgap measure */
176 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
178 get_irn_node_nr (node),
179 get_op_name (get_irn_op (node)));
180 assert (0 && "something not handled");
186 /* Actions for the nodes: */
187 static void pto_load (ir_node *load, pto_env_t *pto_env)
190 DBGPRINT (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__, OPNAME (load), OPNUM (load), (void*) get_node_pto (load)));
192 ir_node *ptr = get_Load_ptr (load);
193 pto_t *ptr_pto = get_pto (ptr);
195 DBGPRINT (0, (stdout, "%s (%s[%li]): ptr = %p\n", __FUNCTION__, OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
198 static void pto_store (ir_node *store, pto_env_t *pto_env)
201 DBGPRINT (0, (stdout, "%s (%s[%li]) (no pto)\n", __FUNCTION__,
202 OPNAME (store), OPNUM (store)));
205 static void pto_method (ir_node *call, pto_env_t *pto_env)
207 DBGPRINT (0, (stdout, "%s:%i (%s[%li]): pto = %p\n",
208 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), (void*) get_node_pto (call)));
210 callEd_info_t *callEd_info = ecg_get_callEd_info (call);
213 while (NULL != callEd_info) {
214 DBGPRINT (0, (stdout, "%s:%i (%s[%li]), graph %i\n",
215 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), i ++));
217 /* dike this out until we do procedure arguments and return
220 pto_call (callEd_info->callEd, call, pto_env);
223 callEd_info = callEd_info->prev;
228 /* Continue PTO for one of the graphs called at a Call */
229 static void pto_call (ir_graph *graph, ir_node *call, pto_env_t *pto_env)
232 DBGPRINT (0, (stdout, "%s:%i (%s[%li])\n",
233 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
235 /* only for debugging stuff: */
236 entity *ent = get_irg_entity (graph);
237 const char *ent_name = (char*) get_entity_name (ent);
238 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
240 if (! get_irg_is_mem_visited (graph)) {
241 graph_info_t *ginfo = ecg_get_info (graph);
244 int ctx_idx = find_ctx_idx (call, ginfo, get_curr_ctx ());
245 ctx_info_t *call_ctx = get_ctx (ginfo, ctx_idx);
246 ctx_info_t *old_ctx = set_curr_ctx (call_ctx);
247 DBGPRINT (1, (stdout, "%s>CTX: ", -- spaces));
248 DBGEXE (1, ecg_print_ctx (call_ctx, stdout));
250 /* Todo: Compute Arguments */
252 /* Initialise Alloc Names and Node values (nope, done in pto_graph ()) */
253 /* pto_reset_graph_pto (graph, ctx_idx); */
255 /* Visit/Iterate Graph */
256 pto_graph (graph, ctx_idx);
259 set_curr_ctx (old_ctx);
261 DBGPRINT (1, (stdout, "%s<CTX: ", spaces ++));
262 DBGEXE (1, ecg_print_ctx (call_ctx, stdout));
264 /* Don't need to reset alloc names unless we handle recursion here */
267 /* Get Return Value from Graph */
269 DBGPRINT (0, (stdout, "%s: recursion into \"%s.%s\"\n",
270 __FUNCTION__, own_name, ent_name));
273 /* Todo: Set 'Unknown' Value as Return Value when the graph is not
277 static void pto_raise (ir_node *raise, pto_env_t *pto_env)
280 DBGPRINT (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
281 OPNAME (raise), OPNUM (raise), (void*) get_node_pto (raise)));
284 static void pto_end_block (ir_node *end_block, pto_env_t *pto_env)
286 /* perform end block */
287 DBGPRINT (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
288 OPNAME (end_block), OPNUM (end_block),
289 (void*) get_node_pto (end_block)));
292 /* Perform the appropriate action on the given node */
293 static void pto_node_node (ir_node *node, pto_env_t *pto_env)
295 const opcode op = get_irn_opcode (node);
298 case (iro_Start): /* nothing */ break;
300 pto_load (node, pto_env);
304 pto_store (node, pto_env);
308 pto_method (node, pto_env);
312 pto_raise (node, pto_env);
324 pto_end_block (node, pto_env);
329 assert (mode_M == get_irn_mode (node));
333 /* uninteresting stuff: */
337 case (iro_DivMod): /* nothing to do */ break;
340 /* stopgap measure */
341 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
343 get_irn_node_nr (node),
344 get_op_name (get_irn_op (node)));
345 assert (0 && "something not handled");
353 /* Callback function to execute in pre-order */
354 static void pto_node_pre (ir_node *node, void *env)
359 /* Callback function to execute in post-order */
360 static void pto_node_post (ir_node *node, void *env)
362 pto_env_t *pto_env = (pto_env_t*) env;
364 pto_node_node (node, pto_env);
367 /* Perform a single pass over the given graph */
368 static void pto_graph_pass (ir_graph *graph, void *pto_env)
370 entity *ent = get_irg_entity (graph);
371 const char *ent_name = (char*) get_entity_name (ent);
372 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
373 HERE3 ("start", own_name, ent_name);
375 irg_walk_mem (graph, pto_node_pre, pto_node_post, pto_env);
377 HERE3 ("end ", own_name, ent_name);
381 /* ===================================================
382 Exported Implementation:
383 =================================================== */
384 /* Main loop: Initialise and iterate over the given graph */
385 void pto_graph (ir_graph *graph, int ctx_idx)
387 pto_env_t *pto_env = xmalloc (sizeof (pto_env_t));
388 pto_env->ctx_idx = ctx_idx;
390 /* HERE ("start"); */
392 DBGPRINT (0, (stdout, "%s: start for ctx %i\n",
396 /* todo: pto_reset_graph_pto */
397 pto_reset_graph_pto (graph, ctx_idx);
399 /* todo (here): iterate, obey 'changed' attribute */
400 pto_graph_pass (graph, pto_env);
402 memset (pto_env, 0x00, sizeof (pto_env_t));
407 /* Set the PTO value for the given non-alloc node */
408 void set_node_pto (ir_node *node, pto_t *pto)
410 assert (iro_Alloc != get_irn_opcode (node));
412 set_irn_link (node, (void*) pto);
415 /*Get the PTO value for the given non-alloc node */
416 pto_t *get_node_pto (ir_node *node)
418 assert (iro_Alloc != get_irn_opcode (node));
420 return ((pto_t*) get_irn_link (node));
423 /* Set the PTO value for the given alloc node */
424 void set_alloc_pto (ir_node *alloc, alloc_pto_t *alloc_pto)
426 assert (iro_Alloc == get_irn_opcode (alloc));
428 set_irn_link (alloc, (void*) alloc_pto);
431 /*Get the current PTO value for the given alloc node */
432 pto_t *get_alloc_pto (ir_node *alloc)
434 alloc_pto_t *alloc_pto = (alloc_pto_t*) get_irn_link (alloc);
436 assert (iro_Alloc == get_irn_opcode (alloc));
438 return (alloc_pto -> curr_pto);
444 Revision 1.3 2004/11/24 14:53:55 liekweg
447 Revision 1.2 2004/11/20 21:21:56 liekweg
448 Finalise initialisation
450 Revision 1.1 2004/11/18 16:37:34 liekweg