*/
# ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
# endif
/*
# include "pto_comp.h"
# include "pto_util.h"
+# include "pto_name.h"
# include "pto_ctx.h"
+# include "pto_mod.h"
-# include "irnode.h"
+# include "irnode_t.h"
# include "irprog.h"
# include "xmalloc.h"
# include "irmemwalk.h"
/* Local Data Types: */
typedef struct pto_env_str {
- int dummy;
+ int ctx_idx;
+ int change;
} pto_env_t;
char *spaces = NULL;
/* Local Prototypes: */
-static void pto_graph (ir_graph*);
+static pto_t *get_pto (ir_node*, pto_env_t*);
static void pto_call (ir_graph*, ir_node*, pto_env_t*);
+static void pto_raise (ir_node*, pto_env_t*);
+static void pto_load (ir_node*, pto_env_t*);
+static void pto_store (ir_node*, pto_env_t*);
+static void pto_method (ir_node*, pto_env_t*);
+static void pto_end_block (ir_node*, pto_env_t*);
/* ===================================================
Local Implementation:
=================================================== */
+/* Transfer the actual arguments to the formal arguments */
+static void set_graph_args (ir_graph *graph, ir_node *call, pto_env_t *env)
+{
+ assert (iro_Call == get_irn_opcode (call));
+
+ type *meth = get_entity_type (get_irg_entity (graph));
+ ir_node **args = find_irg_args (graph);
+ int n_args = get_Call_n_params (call);
+ int i;
+
+ for (i = 0; i < n_args; i ++) {
+ if (NULL != args [i]) {
+ if (mode_P == get_type_mode (get_method_param_type (meth, i))) {
+ ir_node *call_arg = get_Call_param (call, i);
+ pto_t *pto = get_pto (call_arg, env);
+ assert (pto);
+ set_node_pto (args [i], pto);
+
+ DBGPRINT (1, (stdout, "%s: arg [%i]: %s[%li] -> %s[%li] (%i)\n",
+ __FUNCTION__,
+ i,
+ OPNAME (call_arg), OPNUM (call_arg),
+ OPNAME (args [i]), OPNUM (args [i]),
+ pto->values->id));
+ }
+ }
+ }
+}
+
+/* Transfer the graph's result to the call */
+static int set_graph_result (ir_graph *graph, ir_node *call)
+{
+ type *tp = get_entity_type (get_irg_entity (graph));
+ int change = FALSE;
+
+ if (0 == get_method_n_ress (tp)) {
+ return (change);
+ }
+
+ tp = get_method_res_type (tp, 0);
+
+ if (mode_P != get_type_mode (tp)) {
+ set_node_pto (call, NULL);
+
+ return (change);
+ }
+
+ ir_node *end_block = get_irg_end_block (graph);
+ pto_t *ret_pto = get_node_pto (end_block);
+
+ pto_t *call_pto = get_node_pto (call);
+
+ assert (call_pto);
+
+ change |= qset_insert_all (call_pto->values, ret_pto->values);
+
+ return (change);
+}
/* Propagation of PTO values */
-static pto_t *get_pto_proj (ir_node *proj)
+static pto_t *get_pto_proj (ir_node *proj, pto_env_t *env)
{
ir_node *proj_in = get_Proj_pred (proj);
const long proj_proj = get_Proj_proj (proj);
const opcode in_op = get_irn_opcode (proj_in);
pto_t *in_pto = NULL;
- pto_t *proj_pto = get_node_pto (proj);
+ pto_t *proj_pto = NULL; /* get_node_pto (proj); */
+
+ ir_node *proj_in_in = NULL;
switch (in_op) {
case (iro_Start): /* ProjT (Start) */
return (NULL);
case (iro_Proj): /* ProjT (Start), ProjT (Call) */
- assert ((pn_Start_T_args == proj_proj) ||
- (pn_Call_T_result == proj_proj));
- ir_node *proj_in_in = get_Proj_pred (proj_in);
+ proj_in_in = get_Proj_pred (proj_in);
const opcode in_in_op = get_irn_opcode (proj_in_in);
+ const long proj_in_proj = get_Proj_proj (proj_in);
+
+ assert ((pn_Start_T_args == proj_in_proj) ||
+ (pn_Call_T_result == proj_in_proj));
switch (in_in_op) {
case (iro_Start): /* ProjArg (ProjT (Start)) */
/* then the pto value must have been set to the node */
+ proj_pto = get_node_pto (proj);
assert (proj_pto);
return (proj_pto);
if (NULL != proj_pto) {
return (proj_pto);
} else {
- in_pto = get_node_pto (proj_in);
+ in_pto = get_pto (proj_in, env);
set_node_pto (proj, in_pto);
+ assert (in_pto);
+
return (in_pto);
}
default: assert (0 && "Proj(Proj(?))");
if (NULL != proj_pto) {
return (proj_pto);
} else {
- in_pto = get_alloc_pto (proj_in);
+ in_pto = get_pto (proj_in, env);
assert (in_pto);
set_node_pto (proj, in_pto);
}
-static pto_t *get_pto_phi (ir_node *phi)
+static pto_t *get_pto_phi (ir_node *phi, pto_env_t *env)
{
- return (NULL);
+ assert (mode_P == get_irn_mode (phi));
+
+ pto_t *pto = get_node_pto (phi);
+ int change = FALSE;
+
+ assert (pto); /* must be initialised */
+
+ int n_ins = get_irn_arity (phi);
+ int i;
+
+ for (i = 0; i < n_ins; i ++) {
+ ir_node *in = get_irn_n (phi, i);
+ pto_t *in_pto = get_pto (in, env);
+
+ assert (in_pto);
+
+ change |= qset_insert_all (pto->values, in_pto->values);
+ }
+
+ env->change |= change;
+
+ return (pto);
+}
+
+static pto_t *get_pto_sel (ir_node *sel, pto_env_t *env)
+{
+ pto_t *pto = NULL; /* get_node_pto (sel); */
+
+ if (NULL == pto) {
+ ir_node *in = get_Sel_ptr (sel);
+
+ pto = get_pto (in, env);
+ set_node_pto (sel, pto);
+ }
+
+ return (pto);
}
-static pto_t *get_pto_ret (ir_node *ret)
+static pto_t *get_pto_ret (ir_node *ret, pto_env_t *env)
{
- pto_t *pto = get_node_pto (ret);
+ pto_t *pto = NULL; /* get_node_pto (ret); */
if (NULL == pto) {
ir_node *in = get_Return_res (ret, 0);
- pto = get_node_pto (in);
+ pto = get_pto (in, env);
set_node_pto (ret, pto);
}
+ assert (pto);
+
return (pto);
}
/* Dispatch to propagate PTO values */
-static pto_t *get_pto (ir_node *node)
+static pto_t *get_pto (ir_node *node, pto_env_t *env)
{
const opcode op = get_irn_opcode (node);
+ DBGPRINT (2, (stdout, "%s (%s[%li])\n", __FUNCTION__,
+ OPNAME (node), OPNUM (node)));
+
switch (op) {
- case (iro_Cast): return (get_pto (get_Cast_op (node)));
- case (iro_Proj): return (get_pto_proj (node));
- case (iro_Phi): return (get_pto_phi (node));
- case (iro_Return): return (get_pto_ret (node));
+ case (iro_Cast): return (get_pto (get_Cast_op (node), env));
+ case (iro_Proj): return (get_pto_proj (node, env));
+ case (iro_Phi): return (get_pto_phi (node, env));
+ case (iro_Sel): return (get_pto_sel (node, env));
+ case (iro_Alloc): return (get_alloc_pto (node));
+ case (iro_Return): return (get_pto_ret (node, env));
+
+ case (iro_Call): /* FALLTHROUGH */
+ case (iro_Load): /* FALLTHROUGH */
+ case (iro_Const): /* FALLTHROUGH */
+ case (iro_SymConst): return (get_node_pto (node));
default:
/* stopgap measure */
static void pto_load (ir_node *load, pto_env_t *pto_env)
{
/* perform load */
- DBGPRINT (0, (stdout, "%s (%s[%li])\n", __FUNCTION__, OPNAME (load), OPNUM (load)));
-}
+ DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
+ OPNAME (load), OPNUM (load), (void*) get_node_pto (load)));
-static void pto_store (ir_node *store, pto_env_t *pto_env)
-{
- /* perform store */
- DBGPRINT (0, (stdout, "%s (%s[%li])\n", __FUNCTION__,
- OPNAME (store), OPNUM (store)));
-}
+ ir_node *ptr = get_Load_ptr (load);
-static void pto_method (ir_node *call, pto_env_t *pto_env)
-{
- DBGPRINT (0, (stdout, "%s:%i (%s[%li])\n",
- __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
+ if (is_dummy_load_ptr (ptr)) {
+ return;
+ }
- callEd_info_t *callEd_info = ecg_get_callEd_info (call);
+ entity *ent = get_ptr_ent (ptr);
+ pto_t *ptr_pto = get_pto (ptr, pto_env);
- int i = 0;
- while (NULL != callEd_info) {
- DBGPRINT (0, (stdout, "%s:%i (%s[%li]), graph %i\n",
- __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), i ++));
+ assert (ptr_pto);
- pto_call (callEd_info->callEd, call, pto_env);
+ DBGPRINT (1, (stdout, "%s (%s[%li]): ptr = %p\n", __FUNCTION__,
+ OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
- callEd_info = callEd_info->prev;
- }
+ pto_env->change |= mod_load (load, ent, ptr_pto);
}
-
-/* Continue PTO for one of the graphs called at a Call */
-static void pto_call (ir_graph *graph, ir_node *call, pto_env_t *pto_env)
+static void pto_store (ir_node *store, pto_env_t *pto_env)
{
- /* perform call */
- DBGPRINT (0, (stdout, "%s:%i (%s[%li])\n",
- __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
-
- /* only for debugging stuff: */
- entity *ent = get_irg_entity (graph);
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
+ /* perform store */
+ DBGPRINT (2, (stdout, "%s (%s[%li]) (no pto)\n", __FUNCTION__,
+ OPNAME (store), OPNUM (store)));
- if (! get_irg_is_mem_visited (graph)) {
- graph_info_t *ginfo = ecg_get_info (graph);
+ ir_node *ptr = get_Store_ptr (store);
+ ir_node *val = get_Store_value (store);
- /* Save CTX */
- int ctx_idx = find_ctx_idx (call, ginfo, get_curr_ctx ());
- ctx_info_t *call_ctx = get_ctx (ginfo, ctx_idx);
- ctx_info_t *old_ctx = set_curr_ctx (call_ctx);
- DBGPRINT (1, (stdout, "%s>CTX: ", -- spaces));
- DBGEXE (1, ecg_print_ctx (call_ctx, stdout));
+ if (mode_P != get_irn_mode (val)) {
+ return;
+ }
- /* Todo: Compute Arguments */
+ entity *ent = get_ptr_ent (ptr);
- /* Initialise Alloc Names and Node values */
- pto_reset_graph_pto (graph, ctx_idx);
+ pto_t *ptr_pto = get_pto (ptr, pto_env);
+ pto_t *val_pto = get_pto (val, pto_env);
- /* Visit/Iterate Graph */
- pto_graph (graph);
+ assert (ptr_pto);
+ assert (val_pto);
- /* Restore CTX */
- set_curr_ctx (old_ctx);
+ DBGPRINT (2, (stdout, "%s (%s[%li]): ptr_pto = %p\n", __FUNCTION__,
+ OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
+ DBGPRINT (2, (stdout, "%s (%s[%li]): val_pto = %p\n", __FUNCTION__,
+ OPNAME (val), OPNUM (val), (void*) val_pto));
- DBGPRINT (1, (stdout, "%s<CTX: ", spaces ++));
- DBGEXE (1, ecg_print_ctx (call_ctx, stdout));
+ pto_env->change |= mod_store (store, ent, ptr_pto, val_pto);
+}
- /* Don't need to reset alloc names unless we handle recursion here */
+static void pto_method (ir_node *call, pto_env_t *pto_env)
+{
+ DBGPRINT (2, (stdout, "%s:%i (%s[%li]): pto = %p\n",
+ __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call),
+ (void*) get_node_pto (call)));
+ callEd_info_t *callEd_info = ecg_get_callEd_info (call);
- /* Get Return Value from Graph */
- } else {
- DBGPRINT (0, (stdout, "%s: recursion into \"%s.%s\"\n",
- __FUNCTION__, own_name, ent_name));
+ if (NULL == callEd_info) {
+ DBGPRINT (2, (stdout, "%s:%i (%s[%li]), no graph\n",
+ __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
}
- /* Todo: Set 'Unknown' Value as Return Value when the graph is not
- known */
-}
+ int i = 0;
+ while (NULL != callEd_info) {
+ DBGPRINT (2, (stdout, "%s:%i (%s[%li]), graph %i\n",
+ __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), i ++));
-static void pto_raise (ir_node *raise, pto_env_t *pto_env)
-{
- /* perform raise */
- DBGPRINT (0, (stdout, "%s (%s[%li])\n", __FUNCTION__,
- OPNAME (raise), OPNUM (raise)));
-}
+ pto_call (callEd_info->callEd, call, pto_env);
-static void pto_end_block (ir_node *end_block, pto_env_t *pto_env)
-{
- /* perform end block */
- DBGPRINT (0, (stdout, "%s (%s[%li])\n", __FUNCTION__,
- OPNAME (end_block), OPNUM (end_block)));
+ callEd_info = callEd_info->prev;
+ }
}
/* Perform the appropriate action on the given node */
static void pto_node_node (ir_node *node, pto_env_t *pto_env)
{
+ DBGPRINT (1, (stdout, "%s (%s[%li])\n", __FUNCTION__,
+ OPNAME (node), OPNUM (node)));
+
const opcode op = get_irn_opcode (node);
switch (op) {
get_op_name (get_irn_op (node)));
assert (0 && "something not handled");
}
-
-
-
}
entity *ent = get_irg_entity (graph);
const char *ent_name = (char*) get_entity_name (ent);
const char *own_name = (char*) get_type_name (get_entity_owner (ent));
- HERE3 ("start", own_name, ent_name);
+ /* HERE3 ("start", own_name, ent_name); */
irg_walk_mem (graph, pto_node_pre, pto_node_post, pto_env);
- HERE3 ("end ", own_name, ent_name);
+ /* HERE3 ("end ", own_name, ent_name); */
}
-
-/* Main loop: Initialise and iterate over the given graph */
-static void pto_graph (ir_graph *graph)
+/* Continue PTO for one of the graphs called at a Call */
+static void pto_call (ir_graph *graph, ir_node *call, pto_env_t *pto_env)
{
- pto_env_t *pto_env = xmalloc (sizeof (pto_env_t));
- HERE ("start");
+ int change = FALSE;
- /* todo (here): iterate, obey 'changed' attribute */
- pto_graph_pass (graph, pto_env);
+ /* perform call */
+ DBGPRINT (1, (stdout, "%s:%i (%s[%li])\n",
+ __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
- memset (pto_env, 0x00, sizeof (pto_env_t));
- free (pto_env);
- HERE ("end");
+ /* only for debugging stuff: */
+ entity *ent = get_irg_entity (graph);
+ const char *ent_name = (char*) get_entity_name (ent);
+ const char *own_name = (char*) get_type_name (get_entity_owner (ent));
+
+ if (! get_irg_is_mem_visited (graph)) {
+ graph_info_t *ginfo = ecg_get_info (graph);
+
+ /* Save CTX */
+ int ctx_idx = find_ctx_idx (call, ginfo, get_curr_ctx ());
+ ctx_info_t *call_ctx = get_ctx (ginfo, ctx_idx);
+ ctx_info_t *old_ctx = set_curr_ctx (call_ctx);
+ DBGPRINT (3, (stdout, "%s>CTX: ", -- spaces));
+ DBGEXE (3, ecg_print_ctx (call_ctx, stdout));
+
+ /* Initialise Alloc Names and Node values */
+ pto_reset_graph_pto (graph, ctx_idx);
+
+ /* Compute Arguments */
+ set_graph_args (graph, call, pto_env);
+
+ /* Visit/Iterate Graph */
+ pto_graph (graph, ctx_idx);
+
+ /* Restore CTX */
+ set_curr_ctx (old_ctx);
+
+ change |= set_graph_result (graph, call);
+
+ DBGPRINT (3, (stdout, "%s<CTX: ", spaces ++));
+ DBGEXE (3, ecg_print_ctx (call_ctx, stdout));
+
+ /* Don't need to reset alloc names unless we handle recursion here */
+
+
+ /* Get Return Value from Graph */
+ } else {
+ DBGPRINT (2, (stdout, "%s: recursion into \"%s.%s\"\n",
+ __FUNCTION__, own_name, ent_name));
+ }
+
+ /* Todo: Set 'Unknown' Value as Return Value when the graph is not
+ known */
+
+ pto_env->change |= change;
}
-/* "Fake" the arguments to the main method */
-static void fake_main_args (ir_graph *graph)
+static void pto_raise (ir_node *raise, pto_env_t *pto_env)
{
- HERE ("start");
- /* todo: fake the arguments to the main method */
-
- HERE ("end");
+ /* perform raise */
+ DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
+ OPNAME (raise), OPNUM (raise), (void*) get_node_pto (raise)));
}
-/* Helper to pto_init */
-static void pto_init_graph_wrapper (graph_info_t *ginfo, void *__unused)
+static void pto_end_block (ir_node *end_block, pto_env_t *pto_env)
{
- ir_graph *graph = ginfo->graph;
+ /* perform end block */
+ type *tp = get_entity_type (get_irg_entity (get_irn_irg (end_block)));
- pto_init_graph (graph);
-}
+ if (0 == get_method_n_ress (tp)) {
+ return;
+ }
+
+ tp = get_method_res_type (tp, 0);
+
+ if (mode_P != get_type_mode (tp)) {
+ return;
+ }
+
+ DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
+ OPNAME (end_block), OPNUM (end_block),
+ (void*) get_node_pto (end_block)));
+
+ pto_t *end_pto = get_node_pto (end_block);
+ assert (end_pto);
+
+ int n_ins = get_irn_arity (end_block);
+ int i;
+ for (i = 0; i < n_ins; i ++) {
+ ir_node *in = get_irn_n (end_block, i);
+
+ if (iro_Return == get_irn_opcode (in)) {
+ pto_t *in_pto = get_pto (in, pto_env);
+
+ pto_env->change |= qset_insert_all (end_pto->values, in_pto->values);
+ }
+ }
+}
/* ===================================================
Exported Implementation:
=================================================== */
+/* Main loop: Initialise and iterate over the given graph */
+void pto_graph (ir_graph *graph, int ctx_idx)
+{
+ /* Also exported, since we need it in 'pto.c' */
+ pto_env_t *pto_env = xmalloc (sizeof (pto_env_t));
+ pto_env->ctx_idx = ctx_idx;
+ pto_env->change = TRUE;
+
+ /* HERE ("start"); */
+
+ DBGPRINT (2, (stdout, "%s: start for ctx %i\n",
+ __FUNCTION__,
+ ctx_idx));
+
+ /* todo (here): iterate, obey 'changed' attribute */
+ int run = 0;
+ while (0 != pto_env->change) {
+ run ++;
+ pto_env->change = FALSE;
+ pto_graph_pass (graph, pto_env);
+ }
+
+ DBGPRINT (1, (stdout, "%s: %i runs on \"%s.%s\"\n",
+ __FUNCTION__,
+ run,
+ get_type_name (get_entity_owner (get_irg_entity (graph))),
+ get_entity_name (get_irg_entity (graph))));
+
+
+ memset (pto_env, 0x00, sizeof (pto_env_t));
+ free (pto_env);
+ /* HERE ("end"); */
+}
+
/* Set the PTO value for the given non-alloc node */
void set_node_pto (ir_node *node, pto_t *pto)
{
{
assert (iro_Alloc == get_irn_opcode (alloc));
+ assert (alloc_pto);
+
set_irn_link (alloc, (void*) alloc_pto);
}
assert (iro_Alloc == get_irn_opcode (alloc));
- return (alloc_pto -> curr_pto);
-}
-
-/* Initialise the module (not in pto_init.c because it's the entry to pto) */
-void pto_init ()
-{
- HERE ("start");
- ecg_init (1);
-
- /* todo: initialise globals etc */
- pto_init_type_names ();
-
- /* todo: allocate ctx-sens names for allocs and set ... etc etc */
- pto_init_type_names ();
-
- ecg_iterate_graphs (pto_init_graph_wrapper, NULL);
+ assert (alloc_pto -> curr_pto);
- spaces = (char*) xmalloc (512 * sizeof (char));
- memset (spaces, ' ', 512);
- spaces += 511;
- *spaces = '\0';
-
- /* initialise for the CTX-sensitive ecg-traversal */
- set_curr_ctx (get_main_ctx ());
- HERE ("end");
+ return (alloc_pto -> curr_pto);
}
-void pto_run (int dbg_lvl)
-{
- HERE ("start");
- set_dbg_lvl (dbg_lvl);
+\f
+/*
+ $Log$
+ Revision 1.7 2004/12/06 12:55:06 liekweg
+ actually iterate
- ir_graph *graph = get_irp_main_irg ();
- fake_main_args (graph);
+ Revision 1.6 2004/12/02 16:17:51 beck
+ fixed config.h include
- /* todo: clear entity/type links */
+ Revision 1.5 2004/11/30 14:47:54 liekweg
+ fix initialisation; do correct iteration
- DBGPRINT (0, (stdout, "START PTO\n"));
- DBGPRINT (0, (stdout, "START GRAPH (0x%08x) of \"%s.%s\"\n",
- (int) graph,
- get_type_name (get_entity_owner (get_irg_entity (graph))),
- get_entity_name (get_irg_entity (graph))));
-
- /* do we need some kind of environment here? */
- pto_graph (graph);
+ Revision 1.4 2004/11/26 15:59:40 liekweg
+ verify pto_{load,store}
- DBGPRINT (0, (stdout, "END PTO\n"));
- HERE ("end");
-}
+ Revision 1.3 2004/11/24 14:53:55 liekweg
+ Bugfixes
-void pto_cleanup ()
-{
- HERE ("start");
- /* todo: clean up our own mess */
- spaces -= 511; /* hope that all changes to spaces are
- properly nested */
- memset (spaces, 0x00, 512);
- free (spaces);
-
- /* clean up ecg infos */
- ecg_cleanup ();
- HERE ("end");
-}
-
-\f
-/*
- $Log$
Revision 1.2 2004/11/20 21:21:56 liekweg
Finalise initialisation