ir/ir/irop_t.h added
[libfirm] / ir / ana2 / pto_init.c
index e0c91b4..781cfd8 100644 (file)
 /* -*- c -*- */
 
 /*
- * Project:     libFIRM
- * File name:   ir/ana2/pto_init.c
- * Purpose:     Pto Initialization
- * Author:      Florian
- * Modified by:
- * Created:     Wed  3 Nov 2004
- * CVS-ID:      $Id$
- * Copyright:   (c) 1999-2004 Universität Karlsruhe
- * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
- */
-
-
-# ifdef HAVE_CONFIG_H
-#  include <config.h>
-# endif
+   Project:     libFIRM
+   File name:   ir/ana/pto_init.c
+   Purpose:     Initialisation Functions
+   Author:      Florian
+   Modified by:
+   Created:     Sat Nov 13 19:35:27 CET 2004
+   CVS-ID:      $Id$
+   Copyright:   (c) 1999-2004 Universität Karlsruhe
+   Licence:     This file is protected by the GPL -  GNU GENERAL PUBLIC LICENSE.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*
+ pto_init: Initialisation Functions
+*/
+
+# include <assert.h>
+# include <obstack.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
 
 # include "pto.h"
+# include "pto_init.h"
+# include "pto_debug.h"
+# include "pto_comp.h"
+# include "pto_name.h"
 # include "pto_util.h"
 
-# include "entity.h"
-# include "irnode.h"
+# include "typewalk.h"
+# include "irgwalk.h"
+# include "tv.h"
 # include "xmalloc.h"
 
-# define DBGPRINT(lvl, msg) if (get_pto_verbose () > lvl) { fprintf msg; }
+# include "gnu_ext.h"
 
-static void pto_init_proj_load (ir_node *proj, ir_node *load)
+/* Local Defines: */
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free  free
+
+/* Local Data Types: */
+typedef struct init_env_str
 {
-  assert ((mode_P == get_irn_mode (proj)) && "wrong proj(load)");
+  int n_ctxs;
+} init_env_t;
 
-# ifdef PTO_DUMMY
-  ir_node *ptr = get_Load_ptr (load);
-  entity *ent = get_ptr_ent (ptr);
-  type *tp = get_entity_type (ent);
-# endif /* defined PTO_DUMMY */
+typedef struct reset_env_str
+{
+  int ctx_idx;
+} reset_env_t;
 
-  pto_t *pto = pto_new_empty (proj);
+/* Local Variables: */
+extern struct obstack *qset_obst; /* from pto_name */
 
-  DBGPRINT (1, (stdout, "%s: pto (%s[%li]) = 0x%08x\n",
-                __FUNCTION__,
-                get_op_name (get_irn_op (proj)),
-                get_irn_node_nr (proj),
-                (int) pto));
+static struct obstack *pto_obst = NULL; /* all pto_t's go onto this one */
 
-  set_pto (proj, pto);
-}
+/* Local Prototypes: */
 
-static void pto_init_call (ir_node *call)
+/* ===================================================
+   Local Implementation:
+   =================================================== */
+/** Allocate a new pto */
+static pto_t *new_pto (ir_node *node)
 {
-  /* check return value: */
-  ir_node *ptr = get_Call_ptr (call);
-  entity *ent = get_ptr_ent (ptr);
-  type *meth_tp = get_entity_type (ent);
-
-  if (0 == get_method_n_ress (meth_tp)) {
-    /* can't be a pointer */
-    return;
-  }
+  pto_t *pto = obstack_alloc (pto_obst, sizeof (pto_t));
+  pto->values = qset_new (N_INITIAL_OJBS, qset_obst);
 
-  type *ret_tp  = get_method_res_type (meth_tp, 0);
+  return (pto);
+}
 
-  if (mode_P != get_type_mode (ret_tp)) {
-    return;
-  }
+/** Allocate a new alloc_pto */
+static alloc_pto_t *new_alloc_pto (ir_node *alloc, int n_ctxs)
+{
+  int i;
+  alloc_pto_t *alloc_pto = obstack_alloc (pto_obst, sizeof (alloc_pto_t));
+  type *tp;
 
-# ifdef PTO_DUMMY
-  ir_node *ptr = get_Call_ptr (call);
-  entity *ent = get_ptr_ent (ptr);
-  type *tp = get_entity_type (ent);
+  assert (op_Alloc == get_irn_op(alloc));
 
-  obj_desc_t *obj_desc = obj_desc_new (tp);
-  obj_desc_set_dummy (obj_desc);
-# endif /* defined PTO_DUMMY */
+  tp = get_Alloc_type (alloc);
 
-  pto_t *pto = pto_new_empty (call);
+  alloc_pto->ptos = (pto_t**) obstack_alloc (pto_obst, n_ctxs * sizeof (pto_t*));
 
-  DBGPRINT (1, (stdout, "%s: pto (%s[%li]) = 0x%08x\n",
-                __FUNCTION__,
-                get_op_name (get_irn_op (call)),
-                get_irn_node_nr (call),
-                (int) pto));
+  for (i = 0; i < n_ctxs; i ++) {
+    desc_t *desc = new_name (tp, alloc, i);
+    alloc_pto->ptos [i] = new_pto (alloc);
+    qset_insert (alloc_pto->ptos [i]->values, desc);
+  }
 
-  set_pto (call, pto);
+  return (alloc_pto);
 }
 
-static void pto_init_raise (ir_node *raise)
+/** Allocate a new pto for a symconst */
+static pto_t* new_symconst_pto (ir_node *symconst)
 {
-  /* assert (0 && "initialise raise?"); */
+  pto_t *pto;
+  entity *ent;
+  desc_t *desc = NULL;
+
+  assert (op_SymConst == get_irn_op(symconst));
+
+  pto = new_pto (symconst);
+  ent = get_SymConst_entity (symconst);
+
+  /*
+  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);
+  */
+  /* Ok, so if the symconst has a pointer-to-mumble, it's some address
+     calculation, but if it's the mumble itself, it's just the same,
+     except it's presumably a constant of mumble. In any case, we need to
+     branch on this.  "How's that for object fucking oriented? --jwz" */
+  if (is_Pointer_type (get_entity_type (ent))) {
+    desc = new_ent_name (ent);
+  } else if (is_Class_type (get_entity_type (ent))) {
+    desc = new_name (get_entity_type (ent), symconst, -1);
+  } else {
+    fprintf (stderr, "%s: not handled: %s[%li] (\"%s\")\n",
+             __FUNCTION__,
+             get_op_name (get_irn_op (symconst)),
+             get_irn_node_nr (symconst),
+             get_entity_name (ent));
+    assert (0 && "something not handled");
+  }
+
+  qset_insert (pto->values, desc);
+
+  /* HERE3 ("end", own_name, ent_name); */
 
-  /* right now, do nothing and hope that a raise can always be
-     analysed on-the-fly. */
+  return (pto);
 }
 
-static void pto_init_proj (ir_node *proj)
+/* Helper to pto_init --- clear the link fields of class types */
+static void clear_type_link (type_or_ent *thing, void *_unused)
 {
-  ir_node *in = get_Proj_pred (proj);
-  const opcode in_op = get_irn_opcode (in);
+  if (is_type (thing)) {
+    type *tp = (type*) thing;
 
-  switch (in_op) {
-  case (iro_Proj): {
-    ir_node *in_in = get_Proj_pred (in);
-    const opcode in_in_op = get_irn_opcode (in_in);
+    if (is_Class_type (tp)) {
+      DBGPRINT (1, (stdout, "%s (\"%s\")\n",
+                    __FUNCTION__,
+                    get_type_name (tp)));
 
-    switch (in_in_op) {
-    case (iro_Start): {
-      /* nothing (always initialised with actual values) */
-    } break;
+      set_type_link (tp, NULL);
+    }
+  } else if (is_entity (thing)) {
+    entity *ent = (entity*) thing;
 
-    case (iro_Call): {
-      /* nothing (must use call itself) */
-    } break;
+    DBGPRINT (1, (stdout, "%s (\"%s\")\n",
+                  __FUNCTION__,
+                  get_entity_name (ent)));
 
-    default: {
-      fprintf (stderr, "%s: proj(proj(%s[%ld])) not handled\n",
-               __FUNCTION__,
-               get_op_name (get_irn_op (in_in)),
-               get_irn_node_nr (in_in));
-      assert (0);
-    }
-    } /* end switch(Proj.Proj.op) */
-  } break; /* iro_Proj */
+    set_entity_link (ent, NULL);
+  }
+}
 
-  case (iro_Start): {
-    /* ProjM (start) or ProjT (start) --- nothing */
-  } break;
+/** Helper to pto_init_graph --- clear the links of the given node */
+static void clear_node_link (ir_node *node, void *_unused)
+{
+  set_irn_link (node, NULL);
+}
 
-  case (iro_Call): {
-    /* ProjT (start) --- nothing */
-  } break;
+/** Helper to pto_init_graph --- clear the links of all nodes */
+static void clear_graph_links (ir_graph *graph)
+{
+  irg_walk_graph (graph, clear_node_link, NULL, NULL);
+}
 
-  case (iro_Load): {
-    /* Todo: ProjM (load) or ProjV(load) */
-    if (mode_P == get_irn_mode (proj)) {
-      pto_init_proj_load (proj, in);
-    } else {
-      /* nothing to do */
-    }
-  } break;
+/** Reset ALL the pto values for a new pass */
+static void reset_node_pto (ir_node *node, void *env)
+{
+  reset_env_t *reset_env = (reset_env_t*) env;
+  int ctx_idx = reset_env->ctx_idx;
+  opcode op = get_irn_opcode (node);
+
+  /* HERE ("start"); */
 
-  case (iro_Store): {
-    /* ProjM (store) --- nothing */
+  switch (op) {
+  case (iro_Load):
+  case (iro_Call):
+  case (iro_Block):             /* END BLOCK only */
+  case (iro_Phi): {
+    /* allocate 'empty' pto values */
+    pto_t *pto = new_pto (node);
+    set_node_pto (node, pto);
   } break;
 
   case (iro_Alloc): {
-    /* nothing to do --- can always be computed on-the-fly */
-  } break;
+    /* set alloc to 'right' current pto */
+    alloc_pto_t *alloc_pto = (alloc_pto_t*) get_irn_link (node);
+    alloc_pto->curr_pto = alloc_pto->ptos [ctx_idx];
 
-  case (iro_Raise): {
-    /* ProjM (raise) or Proj???(raise) --- TODO */
-  } break;
+    DBGPRINT (1, (stdout, "%s: setting pto of \"%s[%li]\" for ctx %i\n",
+                  __FUNCTION__,
+                  OPNAME (node),
+                  OPNUM (node),
+                  ctx_idx));
 
-  case (iro_Cast): {
-    /* not needed */
+    assert (alloc_pto->curr_pto);
   } break;
+  case (iro_Const):
+  case (iro_SymConst): {
+      /* nothing, leave as-is */
+    } break;
 
   default: {
-    fprintf (stderr, "%s: proj(%s[%ld]) not handled\n",
-             __FUNCTION__,
-             get_op_name (get_irn_op (in)),
-             get_irn_node_nr (in));
-    assert (0);
+    /* basically, nothing */
+    DBGPRINT (2, (stdout, "%s: resetting pto of \"%s[%li]\"\n",
+                  __FUNCTION__,
+                  OPNAME (node),
+                  OPNUM (node)));
+    set_node_pto (node, NULL);
+  } break;
   }
-  } /* end switch (Proj.op) */
 
+  /* HERE ("end"); */
 }
 
-void pto_init_node (ir_node *node)
+/** Initialise primary name sources */
+static void init_pto (ir_node *node, void *env)
 {
-  const opcode op = get_irn_opcode (node);
+  init_env_t *init_env = (init_env_t*) env;
+  int n_ctxs = init_env->n_ctxs;
 
-  DBGPRINT (1, (stdout, "%s (%s[%li])\n",
-                __FUNCTION__,
-                get_op_name (get_irn_op (node)),
-                get_irn_node_nr (node)));
+  opcode op = get_irn_opcode (node);
 
   switch (op) {
-  case (iro_Start): {
-    /* nothing (not needed) */
+  case (iro_SymConst): {
+    if (mode_is_reference (get_irn_mode (node))) {
+      entity *ent = get_SymConst_entity (node);
+      type   *tp = get_entity_type (ent);
+      if (is_Class_type (tp) || is_Pointer_type (tp)) {
+        pto_t *symconst_pto = new_symconst_pto (node);
+        set_node_pto (node, symconst_pto);
+
+        /* debugging only */
+        DBGPRINT (1, (stdout, "%s: new name \"%s\" for \"%s[%li]\"\n",
+                      __FUNCTION__,
+                      get_entity_name (ent),
+                      OPNAME (node),
+                      OPNUM (node)));
+      }
+    }
   } break;
 
-  case (iro_Load): {
-    /* nothing (not needed) */
+  case (iro_Alloc): {
+    alloc_pto_t *alloc_pto = new_alloc_pto (node, n_ctxs);
+    type *tp;
+
+    set_alloc_pto (node, alloc_pto);
+
+    tp = get_Alloc_type (node); /* debugging only */
+    DBGPRINT (1, (stdout, "%s: %i names \"%s\" for \"%s[%li]\"\n",
+                  __FUNCTION__,
+                  n_ctxs,
+                  get_type_name (tp),
+                  OPNAME (node),
+                  OPNUM (node)));
   } break;
 
-  case (iro_Store): {
-    /* nothing (not needed) */
+  case (iro_Const): {
+    tarval *tv = get_Const_tarval (node);
+
+    /* only need 'NULL' pointer constants */
+    if (mode_P == get_tarval_mode (tv)) {
+      if (get_tarval_null (mode_P) == tv) {
+        pto_t *pto = new_pto (node);
+        set_node_pto (node, pto);
+      }
+    }
   } break;
-
-  case (iro_Alloc): {
-    /* nothing (can always be computed on-the-fly) */
+  case (iro_Load):
+  case (iro_Call):
+  case (iro_Phi):
+    /* nothing --- handled by reset_node_pto on each pass */
+    break;
+  default: {
+    /* nothing */
   } break;
+  }
+}
 
-  case (iro_Raise): {
-    /* Todo: Check how a Raise works */
-    pto_init_raise (node);
-  } break;
 
-  case (iro_Call): {
-    /* pretend we have a return value */
-    pto_init_call (node);
-  } break;
+/** Initialise the given graph for a new pass run */
+static void pto_init_graph_allocs (ir_graph *graph)
+{
+  graph_info_t *ginfo = ecg_get_info (graph);
+  init_env_t *init_env;
 
-  case (iro_Proj): {
-    /* this actually does most of the work */
-    pto_init_proj (node);
-  } break;
+  init_env = xmalloc (sizeof (init_env_t));
+  init_env->n_ctxs = ginfo->n_ctxs;
 
-  case (iro_Cast): {
-    /* nothing (can always be computed on-the-fly) */
-  } break;
+  /* HERE ("start"); */
 
-  case (iro_SymConst): {
-    /* nothing (can always be computed on-the-fly) */
-  } break;
+  irg_walk_graph (graph, init_pto, NULL, init_env);
 
-  case (iro_Const): {
-    /* nothing (can always be computed on-the-fly) */
-  } break;
+  /* HERE ("end"); */
+  memset (init_env, 0x00, sizeof (init_env_t));
+  free (init_env);
+}
 
-  case (iro_Block): {
-    /* nothing (this is only interesting for the end block, and that
-       can always be computed on-the-fly) */
-  } break;
+/* ===================================================
+   Exported Implementation:
+   =================================================== */
+/* "Fake" the arguments to the main method */
+void fake_main_args (ir_graph *graph)
+{
+  /* HERE ("start"); */
 
-  case (iro_Phi): {
-    /* nothing (This would need the predecessors to be initialized! Do this on-the-fly) */
-  } break;
+  entity *ent = get_irg_entity (graph);
+  type *mtp = get_entity_type (ent);
+  ir_node **args = find_irg_args (graph);
+  type *ctp = get_method_param_type (mtp, 1); /* ctp == char[]*[]* */
+  desc_t *arg_desc;
+  pto_t *arg_pto;
 
-  /* now, enumerate everything else that is uninteresting */
-  case (iro_Return):
-  case (iro_Div):
-  case (iro_Quot):
-  case (iro_Mod):
-  case (iro_DivMod): {
-    /* nothing (not needed) */
-  } break;
+  /* 'main' has signature 'void(int, char[]*[]*)' */
+  assert (NULL == args [2]);
 
-  default: {
-    fprintf (stderr, "%s: %s[%ld] not handled\n",
-             __FUNCTION__,
-             get_op_name (get_irn_op (node)),
-             get_irn_node_nr (node));
-    assert (0);
-  } break;
+  assert (is_Pointer_type (ctp));
 
-  }
+  ctp = get_pointer_points_to_type (ctp); /* ctp == char[]*[] */
+
+  assert (is_Array_type (ctp));
+
+  arg_desc = new_name (ctp, args [1], -1);
+  arg_pto = new_pto (args [1]);
+  /* todo: simulate 'store' to arg1[] ?!? */
+  qset_insert (arg_pto->values, arg_desc);
+
+  set_node_pto (args [1], arg_pto);
+
+  DBGPRINT (1, (stdout, "%s:%i (%s[%li])\n",
+                __FUNCTION__, __LINE__,
+                OPNAME (args [1]), OPNUM (args [1])));
+
+# ifdef TEST_MAIN_TYPE
+  ctp = get_array_element_type (ctp); /* ctp == char[]* */
+
+  assert (is_Pointer_type (ctp));
+
+  ctp = get_pointer_points_to_type (ctp); /* ctp == char[] */
+
+  assert (is_Array_type (ctp));
+
+  ctp = get_array_element_type (ctp); /* ctp == char */
+
+  assert (is_primitive_type (ctp));
+# endif /* defined  TEST_MAIN_TYPE */
+
+  /* HERE ("end"); */
+}
+
+/* Initialise the Init module */
+void pto_init_init (void)
+{
+  pto_obst = (struct obstack*) xmalloc (sizeof (struct obstack));
+
+  obstack_init (pto_obst);
+}
+
+/* Cleanup the Init module */
+void pto_init_cleanup (void)
+{
+  obstack_free (pto_obst, NULL);
+  memset (pto_obst, 0x00, sizeof (struct obstack));
+  free (pto_obst);
+  pto_obst = NULL;
 }
 
 
+/* Initialise the Names of the Types/Entities */
+void pto_init_type_names (void)
+{
+  /* HERE ("start"); */
+  type_walk (clear_type_link, NULL, NULL);
+  /* HERE ("end"); */
+}
+
+/* Initialise the given graph for a new pass run */
+void pto_init_graph (ir_graph *graph)
+{
+  ir_node **proj_args;
+  graph_info_t *ginfo = ecg_get_info (graph);
+  const int n_ctxs = ginfo->n_ctxs;
+
+  /* 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));
+
+  DBGPRINT (2, (stdout, "%s: init \"%s.%s\" for %i ctxs\n",
+                __FUNCTION__,
+                own_name, ent_name, n_ctxs));
+
+  /* HERE ("start"); */
+
+  clear_graph_links     (graph);
+  pto_init_graph_allocs (graph);
+
+  /* HERE ("end"); */
+
+  assert (NULL == get_irg_proj_args (graph));
+  proj_args = find_irg_args (graph);
+  set_irg_proj_args (graph, proj_args);
+  assert (proj_args == get_irg_proj_args (graph));
+}
+
+/* Reset the given graph for a new pass run */
+void pto_reset_graph_pto (ir_graph *graph, int ctx_idx)
+{
+  reset_env_t *reset_env;
+
+  reset_env = (reset_env_t*) xmalloc (sizeof (reset_env_t));
+  reset_env->ctx_idx = ctx_idx;
+
+  /* HERE ("start"); */
+
+  irg_walk_graph (graph, reset_node_pto, NULL, reset_env);
+
+  /* HERE ("end"); */
+  memset (reset_env, 0x00, sizeof (reset_env_t));
+  free (reset_env);
+}
+
 \f
 /*
- * $Log$
- * Revision 1.1  2004/11/04 14:58:59  liekweg
- * added initialisation
- *
- *
- */
+  $Log$
+  Revision 1.20  2005/12/05 12:19:54  beck
+  added missing include <assert.h> (not anymore included in libFirm)
+
+  Revision 1.19  2005/06/17 17:42:32  beck
+  added doxygen docu
+  fixed (void) function headers
+
+  Revision 1.18  2005/02/16 13:27:52  beck
+  added needed tv.h include
+
+  Revision 1.17  2005/01/14 14:12:51  liekweg
+  prepare gnu extension fix
+
+  Revision 1.16  2005/01/14 13:36:50  liekweg
+  don't put environments on the stack; handle consts
+
+  Revision 1.15  2005/01/10 17:26:34  liekweg
+  fixup printfs, don't put environments on the stack
+
+  Revision 1.14  2005/01/05 14:25:54  beck
+  renames all is_x*_type() functions to is_X*_type() to prevent name clash with EDG fronten
+
+  Revision 1.13  2004/12/21 15:07:55  beck
+  removed C99 contructs
+  removed unnecessary allocation
+  removed use of mode_P, use mode_is_reference() instead
+  removed handling of Const with pointer tarvals, these constructs are removed
+
+  Revision 1.12  2004/12/20 17:41:14  liekweg
+  __unused -> _unused
+
+  Revision 1.11  2004/12/20 17:34:35  liekweg
+  fix recursion handling
+
+  Revision 1.10  2004/12/15 13:31:00  liekweg
+  store ctx idx in names
+
+  Revision 1.9  2004/12/15 09:18:18  liekweg
+  pto_name.c
+
+  Revision 1.8  2004/12/02 16:17:51  beck
+  fixed config.h include
+
+  Revision 1.7  2004/11/30 14:47:54  liekweg
+  fix initialisation; do correct iteration
+
+  Revision 1.6  2004/11/26 16:00:41  liekweg
+  recognize class consts vs. ptr-to-class consts
+
+  Revision 1.5  2004/11/24 14:53:56  liekweg
+  Bugfixes
+
+  Revision 1.4  2004/11/20 21:21:56  liekweg
+  Finalise initialisation
+
+  Revision 1.3  2004/11/18 16:37:07  liekweg
+  rewrite
+
+
+*/