graph_info_t *ginfo = graph_infos_list;
while (NULL != ginfo) {
- hnd (ginfo, env);
+ /* do not visit graphs that have 0 == ginfo->n_ctxs, since they
+ are not called */
+ if (0 != ginfo->n_ctxs) {
+ hnd (ginfo, env);
+ }
ginfo = ginfo->prev;
}
/*
$Log$
+ Revision 1.6 2004/11/24 14:53:55 liekweg
+ Bugfixes
+
Revision 1.5 2004/11/20 21:20:29 liekweg
Added iterator functions
+++ /dev/null
-/* -*- c -*- */
-
-/*
- * Project: libFIRM
- * File name: ir/ana2/pto.c
- * Purpose: Pto
- * Author: Florian
- * Modified by:
- * Created: Mon 18 Oct 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
-
-# include "pto.h"
-# include "pto_util.h"
-# include "pto_init.h"
-
-# include "entity.h"
-
-# include "irnode.h"
-# include "irprog.h"
-
-/* # include "eset.h" */
-# include "irgraph.h"
-# include "irgwalk.h"
-# include "irgmod.h"
-# include "irvrfy.h"
-# include "trvrfy.h"
-# include "xmalloc.h"
-
-# include "typewalk.h"
-# include "irmemwalk.h"
-
-# define DBGPRINT(lvl, msg) if (get_pto_verbose () > lvl) { fprintf msg; }
-# define DBGEXE(lvl, cmd) if (get_pto_verbose () > lvl) { cmd; }
-
-/*
- Local Protos
-*/
-static void pto_node (ir_node*, void*);
-static void pto_node_pre (ir_node*, void*);
-static void pto_node_post (ir_node*, void*);
-
-/*
- Get the pto infos of a node
-*/
-static pto_t *get_pto (ir_node *node)
-{
-
-
- return ((pto_t*) get_irn_link (node));
-}
-
-/*
- Propagate pto values up to the given node, and return the propagated
- value. This recursion has to stop at important nodes, such as
- loads and allocs, where pto is computed differently (albeit this may
- involve more calls to this function for a different ptr value).
-*/
-static pto_t *compute_pto (ir_node *node, void *env)
-{
- pto_t *node_pto = get_pto (node);
-
- if ((NULL != node_pto) && (pto_is_dummy (node_pto))) {
- /* weed out initialisation data as good as possible */
-
- DBGPRINT (0, (stdout, "%s: dummy pto for (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (node)),
- get_irn_node_nr (node)));
-
- pto_delete (node_pto);
- node_pto = NULL;
- }
-
- if (NULL == node_pto) {
- DBGPRINT (1, (stdout, "%s: must compute pto for %s[%li]\n",
- __FUNCTION__,
- get_op_name (get_irn_op (node)),
- get_irn_node_nr (node)));
-
- pto_node (node, env);
-
- node_pto = get_pto (node);
- }
-
- assert (node_pto);
-
- return (node_pto);
-}
-
-/*
- Transfer the actual arguments to the given call's formal arguments
-*/
-static void set_call_args (ir_node *call, ir_graph *graph, void *env)
-{
- ir_node **args = find_irg_args (graph);
- int i;
-
- const int n_call_args = get_irn_arity (call);
-
- /* call: M x meth_ptr x Arg x Arg x ... x Arg */
- /* projT(start): Arg x Arg x ... x Arg */
- /* projM(start): M */
-
- for (i = 2; i < n_call_args; i ++) {
- if (NULL != args [i-2]) {
- if (mode_P == get_irn_mode (args [i-2])) {
- pto_t *arg_pto = compute_pto (get_irn_n (call, i), env);
- /* off-by-two because of ProjT bd */
- set_pto (args [i-2], arg_pto);
- } else {
- /* not a pointer value */
- }
- }
- }
- free (args);
-}
-
-/*
- Transfer the return value of a call to the callR node
-*/
-static void get_call_ret (ir_node *call, ir_graph *graph, void *env)
-{
- entity *ent = get_irg_ent (graph);
- type *ent_tp = get_entity_type (ent);
-
- if (NULL != get_pto (call)) {
- pto_t *old = get_pto (call);
-
- if (pto_is_dummy (old)) {
- DBGPRINT (2, (stdout, "%s: dummy pto (0x%08x) from call[%li]\n",
- __FUNCTION__, (int) old, get_irn_node_nr (call)));
- }
-
- pto_delete (old);
- }
-
- if (0 != get_method_n_ress (ent_tp)) {
- type *ent_ret_tp = get_method_res_type (ent_tp, 0);
-
- if (mode_P == get_type_mode (ent_ret_tp)) {
- pto_t *res_pto = get_pto (get_irg_end_block (graph));
-
- set_pto (call, res_pto);
- }
- }
-}
-
-
-/*
- Take care of a single proj node. Basically a multiplex/dispatch for the
- different node types that a proj can have as a predecessor.
-*/
-static void pto_node_proj (ir_node *proj, void *env)
-{
- /*
- pto for proj({proj(start),load,call,alloc,raise?,...}) node
- */
- ir_node *in = get_Proj_pred (proj);
- const opcode in_op = get_irn_opcode (in);
- const long proj_proj = get_Proj_proj (proj);
-
- DBGPRINT (3, (stdout, "%s: --> Proj[%li] (%s)\n",
- __FUNCTION__,
- get_irn_node_nr (proj),
- get_op_name (get_irn_op (in))));
-
- switch (in_op) {
- case (iro_Start): {
- /* nothing (handled by proj(proj)) */
- } break;
-
- case (iro_Load): {
- /* copy from load */
- if (pn_Load_res == proj_proj) {
- set_pto (proj, compute_pto (in, env));
- } else {
- /* ProjM(load) or ProjX(load) - do nothing */
- }
- } break;
-
- case (iro_Store): {
- /* ProjM (store) or ProjX (store) - nothing */
- } break;
-
- case (iro_Alloc): {
- /* copy from alloc */
- if (pn_Alloc_res == proj_proj) {
- set_pto (proj, compute_pto (in, env));
- } else {
- /* ProjM(alloc) or ProjX (alloc) -- nothing */
- }
- } break;
-
- case (iro_Raise): {
- /* ProjX (raise), ProjM (raise) -- nothing */
- } break;
-
- case (iro_Call): {
- if (pn_Call_M_regular == proj_proj) {
- /* ProjM(call) -- nothing */
- } else if (pn_Call_T_result == proj_proj) {
- /* copy return value of call */
- pto_t *call_pto = get_pto (in); /* get result from call */
- assert (call_pto);
- set_pto (proj, call_pto);
- } else if (pn_Call_P_value_res_base == proj_proj) {
- /* wtf? */
- assert (0 && "what's with pn_Call_P_value_res_base?");
- } else {
- /* ProjX (call) or ProjM_exc (call) -- nothing */
- }
-
- } break;
-
- case (iro_Proj): {
- const ir_node *in_in = get_Proj_pred (in);
- const opcode in_in_op = get_irn_opcode (in_in);
-
- switch (in_in_op) {
- case (iro_Call): {
- /* projP (projT (call)) */
- /* copy from projT to projP */
- pto_t *in_pto = compute_pto (in, env);
- set_pto (proj, in_pto);
- } break;
- case (iro_Start): {
- /* proj(proj(start)) - make sure the arguments are initialised */
- assert (get_pto (proj));
- } break;
- default: {
- DBGPRINT (1, (stdout, "%s:%i: proj(proj(%s)) not handled\n",
- __FILE__, __LINE__, get_op_name (get_irn_op (in_in))));
- assert (0);
- }
- }
- } break;
-
- case (iro_Cast): {
- /* make sure the input has been analysed */
- pto_t *cast_pto = compute_pto (in, env);
- set_pto (proj, cast_pto);
-
- } break;
-
- default: {
- fprintf (stderr, "%s: opcode %s of Node %ld not handled\n",
- __FUNCTION__,
- get_op_name (get_irn_op (in)),
- get_irn_node_nr (in));
-
- assert (0 && "something not handled");
- }
- }
-
- DBGPRINT (2, (stdout, "%s: Proj (%s)\n",
- __FUNCTION__,
- get_op_name (get_irn_op (in))));
-}
-
-static void pto_node_obj_load (ir_node *load, ir_node *ptr,
- entity *ent, void *env)
-{
- /*
- pto for obj load node
-
- so far:
- load.ptr analysed
- todo:
- look up
- */
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
-
- DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (ptr)),
- get_irn_node_nr (ptr)));
-
- if (! is_pointer_type (get_entity_type (ent))) {
- return;
- }
-
- if (NULL != get_pto (load)) {
- pto_t *old = get_pto (load);
-
- if (pto_is_dummy (old)) {
- DBGPRINT (1, (stdout, "%s: dummy pto (0x%08x) from load[%li]\n",
- __FUNCTION__, (int) old, get_irn_node_nr (load)));
- }
-
- pto_delete (old);
- }
-
- DBGPRINT (1, (stdout, "%s: obj load from ent (0x%08x) \"%s.%s\"\n",
- __FUNCTION__,
- (int) ent,
- own_name,
- ent_name));
-
- pto_t *ptr_objs = compute_pto (ptr, env);
- qset_t *objs = ptr_objs->objs;
- pto_t *res = pto_new_empty (load);
- obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
-
- DBGPRINT (1, (stdout, "%s: ptr_pto = ", __FUNCTION__));
- DBGEXE (1, qset_print (objs, stdout));
-
- while (NULL != obj_desc) {
- qset_t *cnts = pto_lookup (obj_desc, ent);
-
- DBGPRINT (1, (stdout, "%s: cnts = ", __FUNCTION__));
- DBGEXE (1, qset_print (cnts, stdout));
-
- pto_add_all_names (res, cnts);
-
- obj_desc = (obj_desc_t*) qset_next (objs);
- }
-
- set_pto (load, res);
-
- DBGPRINT (1, (stdout, "%s\n", __FUNCTION__));
-}
-
-static void pto_node_arr_load (ir_node *load, ir_node *ptr,
- entity *ent, void *env)
-{
- /*
- pto for array load node
-
- so far:
- load.ptr analysed or can be computed on-the-fly
- todo:
- look up
- */
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
-
- /* load from array */
- DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (ptr)),
- get_irn_node_nr (ptr)));
-
- if (! is_pointer_type (get_entity_type (ent))) {
- return;
- }
-
- DBGPRINT (1, (stdout, "%s: array load from ent (0x%08x) \"%s.%s\"\n",
- __FUNCTION__,
- (int) ent,
- own_name,
- ent_name));
-
- pto_t *ptr_objs = compute_pto (ptr, env);
- qset_t *objs = ptr_objs->objs;
- pto_t *res = pto_new_empty (load);
-
- obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
-
- while (NULL != obj_desc) {
- qset_t *cnts = pto_lookup (obj_desc, NULL);
-
- pto_add_all_names (res, cnts);
-
- obj_desc = (obj_desc_t*) qset_next (objs);
- }
-
- set_pto (load, res);
-}
-
-static void pto_node_load (ir_node *load, void *env)
-{
- /*
- pto for load node
-
- so far:
- load.ptr analysed or can be computed on-the-fly
- todo:
- look up
- */
- ir_node *ptr = get_Load_ptr (load);
- const opcode op = get_irn_opcode (ptr);
- entity *ent = NULL;
-
- /* check the funny cases */
- if (iro_Proj == op) {
- /* then it's an unused Load(this) (or whatever) and we don't need to look at it */
- DBGPRINT (1, (stderr, "%s: %s[%li] ignored\n",
- __FUNCTION__,
- get_op_name (get_irn_op (ptr)),
- get_irn_node_nr (ptr)));
- return;
- } else if (iro_Cast == op) {
- /* then it's (whatever) and we don't know where to look at */
- DBGPRINT (1, (stderr, "%s: %s[%li] ignored\n",
- __FUNCTION__,
- get_op_name (get_irn_op (ptr)),
- get_irn_node_nr (ptr)));
- return;
- }
-
- ent = get_ptr_ent (ptr);
-
- assert (ent);
-
- /* array load or obj load? */
- if ((iro_Sel == op) && (3 == get_irn_arity (ptr))) {
- pto_node_arr_load (load, ptr, ent, env);
- } else {
- pto_node_obj_load (load, ptr, ent, env);
- }
-
-}
-
-static void pto_node_obj_store (ir_node *store,
- ir_node *ptr,
- entity *ent,
- ir_node *val,
- void *env)
-{
- /*
- pto for obj store node
-
- so far: ptr analysed or can be computed on-the-fly
- todo:
- update
- */
-
-
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
-
- DBGPRINT (1, (stdout, "%s: obj store to ent (0x%08x) \"%s.%s\"\n",
- __FUNCTION__,
- (int) ent, own_name, ent_name));
-
- pto_t *ptr_pto = compute_pto (ptr, env);
- pto_t *val_pto = compute_pto (val, env);
- qset_t *objs = ptr_pto->objs;
- qset_t *vals = val_pto->objs;
-
- obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
-
- DBGPRINT (1, (stdout, "%s: ptr_pto = ", __FUNCTION__));
- DBGEXE (1, qset_print (objs, stdout));
-
- DBGPRINT (1, (stdout, "%s: ptr_val = ", __FUNCTION__));
- DBGEXE (1, qset_print (vals, stdout));
-
- while (NULL != obj_desc) {
- qset_t *cnts = pto_lookup (obj_desc, ent);
-
- qset_insert_all (cnts, vals);
-
- DBGPRINT (1, (stdout, "%s: cnts = ", __FUNCTION__));
- DBGEXE (1, qset_print (cnts, stdout));
-
- obj_desc = (obj_desc_t*) qset_next (objs);
- }
-
- DBGPRINT (1, (stdout, "%s\n", __FUNCTION__));
-}
-
-static void pto_node_arr_store (ir_node *store,
- ir_node *ptr,
- entity *ent,
- ir_node *val,
- void *env)
-{
- /*
- pto for array store node
-
- so far: ptr analysed or can be computed on-the-fly
- todo:
- update
- */
-
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
-
- DBGPRINT (1, (stdout, "%s: array store to ent (0x%08x) \"%s.%s\"\n",
- __FUNCTION__,
- (int) ent, own_name, ent_name));
-
- pto_t *ptr_pto = compute_pto (ptr, env);
- pto_t *val_pto = compute_pto (val, env);
- qset_t *objs = ptr_pto->objs;
- qset_t *vals = val_pto->objs;
-
- obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
-
- while (NULL != obj_desc) {
- qset_t *cnts = pto_lookup (obj_desc, NULL);
-
- qset_insert_all (cnts, vals);
-
- obj_desc = (obj_desc_t*) qset_next (objs);
- }
-}
-
-static void pto_node_store (ir_node *store, void *env)
-{
- /*
- pto for store node
-
- so far: ptr analysed or can be computed on-the-fly
- todo:
- update
- */
-
- ir_node *ptr = get_Store_ptr (store);
- ir_node *val = get_Store_value (store);
- const opcode op = get_irn_opcode (ptr);
- entity *ent = get_ptr_ent (ptr);
-
- if (mode_P != get_irn_mode (val)) {
- return;
- }
-
- /* array load or obj load? */
- if ((iro_Sel == op) && (3 == get_irn_arity (ptr))) {
- pto_node_arr_store (store, ptr, ent, val, env);
- } else {
- pto_node_obj_store (store, ptr, ent, val, env);
- }
-
-}
-
-static void pto_node_alloc (ir_node *alloc, void *env)
-{
- /*
- pto for alloc node
-
- so far: nothing to do
- todo:
- invent new name
- */
-
- if (NULL == get_pto (alloc)) {
- type *tp = get_Alloc_type (alloc);
-
- pto_t *alloc_pto = pto_new_name (alloc, tp);
- set_pto (alloc, alloc_pto);
- DBGPRINT (0, (stdout, "%s (%s[%li]): new pto\n",
- __FUNCTION__,
- get_op_name (get_irn_op (alloc)),
- get_irn_node_nr (alloc)));
- } else {
- DBGPRINT (0, (stdout, "%s (%s[%li]): reusing pto\n",
- __FUNCTION__,
- get_op_name (get_irn_op (alloc)),
- get_irn_node_nr (alloc)));
- }
-
-}
-
-static void pto_node_free (ir_node *free, void *env)
-{
- /*
- pto for free node
-
- so far: ptr analysed or can be computed on-the-fly
- todo:
- nothing, actually
- */
- /* still, copy somthing */
- ir_node *ptr = get_Free_ptr (free);
-
- pto_t *ptr_pto = compute_pto (ptr, env);
- set_pto (free, ptr_pto);
-}
-
-static void pto_node_raise (ir_node *raise, void *env)
-{
- /*
- pto for raise node
-
- so far: ptr analysed or can be computed on-the-fly
- todo:
-
- */
-
- /* right now, just copy something */
- ir_node *ptr = get_Raise_exo_ptr (raise);
-
- pto_t *ptr_pto = compute_pto (ptr, env);
-
- set_pto (raise, ptr_pto);
-}
-
-static void pto_node_sel (ir_node *sel, void *env)
-{
- /*
- pto for sel node
-
- so far: input selected or can be computed on-the-fly
- todo:
- just copy (the selected entity is used in the load/store)
- */
-
- ir_node *sel_in = get_Sel_ptr (sel);
- pto_t *sel_pto = compute_pto (sel_in, env);
-
- if (NULL == sel_pto) {
- fprintf (stdout, "%s:%i: sel.in = %s[%li]\n",
- __FUNCTION__, __LINE__,
- get_op_name (get_irn_op (sel_in)),
- get_irn_node_nr (sel_in));
- }
- assert (sel_pto);
-
- set_pto (sel, sel_pto);
-}
-
-static void pto_node_call (ir_node *call, void *env)
-{
- ir_graph *graph = NULL;
- ir_node *ptr = get_Call_ptr (call);
- entity *ent = get_ptr_ent (ptr);
-
- DBGPRINT (1, (stdout, "%s (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (call)),
- get_irn_node_nr (call)));
-
-
- const char *ent_name = (char*) get_entity_name (ent);
- const char *own_name = (char*) get_type_name (get_entity_owner (ent));
-
- /* Todo: Iterate over all graphs in 'get_implementing_graphs' */
- graph = get_entity_irg (ent);
- if (NULL != graph) {
- if (! get_irg_is_mem_visited (graph)) {
- DBGPRINT (1, (stdout, " -> visit graph (0x%08x) of \"%s.%s\"\n",
- (int) graph, own_name, ent_name));
-
- /* compute call arguments */
- set_call_args (call, graph, env);
- /* traverse callEd */
- irg_walk_mem (graph, pto_node_pre, pto_node_post, NULL);
- /* maybe get result from called graph */
- get_call_ret (call, graph, env);
- }
- } else {
- DBGPRINT (0, (stdout, "%s:%i: Warning: no graph for ent \"%s.%s\" in call[%li]\n",
- __FILE__, __LINE__, own_name, ent_name, get_irn_node_nr (call)));
- }
-}
-
-static void pto_node_ret (ir_node *ret, void *env)
-{
- /*
- pto for return node
-
- so far:
- input should be availlable
- todo:
- just copy
- */
-
- if ((0 != get_Return_n_ress (ret)) &&
- (mode_P == get_irn_mode (get_Return_res (ret, 0)))) {
- ir_node *ret_in = get_Return_res (ret, 0);
-
- pto_t *ret_pto = compute_pto (ret_in, env);
-
- DBGPRINT (4, (stdout, "--> Return Node (%ld) (%s)\n",
- get_irn_node_nr (ret),
- get_op_name (get_irn_op (ret))));
-
- set_pto (ret, ret_pto);
- } else {
- /* nothing to do! */
- }
-}
-
-static void pto_node_phi (ir_node *phi, void *env)
-{
- /*
- pto for phi node
-
- so far:
- all ins present or can be computed on-the-fly
- todo:
- collect ins
- */
-
- int i;
- int n_ins = get_irn_arity (phi);
- ir_node *in = NULL;
-
- if (mode_P != get_irn_mode (phi)) {
- return;
- }
-
- assert (0 && "test phi");
-
- pto_t *phi_pto = get_pto (phi);
-
- if (NULL == phi_pto) {
- phi_pto = pto_new_empty (phi);
- set_pto (phi, phi_pto);
- }
-
- for (i = 0; i < n_ins; i ++) {
- in = get_irn_n (phi, i);
-
- pto_t *in_pto = compute_pto (in, env);
-
- DBGPRINT (0, (stdout, "%s: IN PHI Node (%ld) (%s) (pto = 0x%08x)\n",
- __FUNCTION__,
- get_irn_node_nr (in),
- get_op_name (get_irn_op (in)),
- (int) in_pto));
-
- qset_insert_all (phi_pto->objs, in_pto->objs);
- }
-}
-
-static void pto_node_cnst (ir_node *cnst, void *env)
-{
- /*
- pto for const node
-
- so far: nothing
- todo:
- if this represents something nameable, name it
- */
- type *tp = get_Const_type (cnst);
- pto_t *cnst_pto = pto_new_name (cnst, tp); /* WRONG */
-
-
- set_pto (cnst, cnst_pto);
-}
-
-static void pto_node_sym_cnst (ir_node *sym_cnst, void *env)
-{
- /*
- pto for const node
-
- so far: nothing
- todo:
- if this represents something nameable, name it
- */
- entity *ent = get_SymConst_entity (sym_cnst);
- type *tp = get_entity_type (ent);
-
- if (is_pointer_type (tp)) {
- tp = get_pointer_points_to_type (tp);
- pto_t *sym_cnst_pto = (pto_t*) get_entity_link (ent);
-
- DBGPRINT (2, (stdout, "%s: SymConst (%ld) (%s)\n",
- __FUNCTION__,
- get_irn_node_nr (sym_cnst),
- get_op_name (get_irn_op (sym_cnst))));
-
-
- if (NULL == sym_cnst_pto) {
- sym_cnst_pto = pto_new_name (sym_cnst, tp);
-
- DBGPRINT (1, (stdout, "%s: SymConst (%ld) (%s): NEW PTO\n",
- __FUNCTION__,
- get_irn_node_nr (sym_cnst),
- get_op_name (get_irn_op (sym_cnst))));
-
- set_entity_link (ent, sym_cnst_pto);
- } else {
- DBGPRINT (1, (stdout, "%s: SymConst (%ld) (%s): reusing pto\n",
- __FUNCTION__,
- get_irn_node_nr (sym_cnst),
- get_op_name (get_irn_op (sym_cnst))));
- }
-
- set_pto (sym_cnst, sym_cnst_pto);
- } else {
- /* nothing to do */
- }
-}
-
-static void pto_node_end_block (ir_node *end, void *env)
-{
- /*
- pto for const node
-
- so far: all returns are set or can be computed on-the-fly
- todo:
- collect results, set to node.
- */
- entity *ent = get_irg_entity (get_irn_irg (end));
- type *tp = get_entity_type (ent);
-
- DBGPRINT (2, (stdout, "%s: End Block (%ld) (%s)\n",
- __FUNCTION__,
- get_irn_node_nr (end),
- get_op_name (get_irn_op (end))));
-
- if (0 != get_method_n_ress (tp)) {
- tp = get_method_res_type (tp, 0);
-
- if (mode_P == get_type_mode (tp)) {
- int i;
- int n_ins = get_irn_arity (end);
- pto_t *end_pto = pto_new_empty (end);
-
- for (i = 0; i < n_ins; i ++) {
- ir_node *ret = get_irn_n (end, i);
-
- if (iro_Return == get_irn_opcode (ret)) {
- pto_t *ret_pto = get_pto (ret);
- assert (ret_pto);
-
- pto_add_all_names (end_pto, ret_pto->objs);
- }
- }
-
- set_pto (end, end_pto);
- }
- }
-}
-
-/*
- Take care of a single node. Basically a multiplex/dispatch for the
- different node types.
-*/
-static void pto_node (ir_node *node, void *env)
-{
- const opcode op = get_irn_opcode (node);
-
- DBGPRINT (1, (stdout, "%s (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (node)),
- get_irn_node_nr (node)));
-
- switch (op) {
- case (iro_Start): {
- /* pto_node_start (node, env); */
- /* nothing to do */
-
- } break;
- case (iro_Load): {
- pto_node_load (node, env);
-
- } break;
- case (iro_Store): {
- pto_node_store (node, env);
-
- } break;
- case (iro_Alloc): {
- pto_node_alloc (node, env);
-
- } break;
- case (iro_Free): {
- pto_node_free (node, env);
-
- } break;
- case (iro_Raise): {
- pto_node_raise (node, env);
-
- } break;
- case (iro_Sel): {
- pto_node_sel (node, env);
-
- } break;
- case (iro_Call): {
- /* assert (0 && "calls must be handled in main loop"); */
- pto_node_call (node, env);
- } break;
- case (iro_Return): {
- if (0 < get_Return_n_ress (node)) {
- pto_node_ret (node, env);
- }
- } break;
- case (iro_Proj): {
- pto_node_proj (node, env);
- } break;
- case (iro_Phi): {
- pto_node_phi (node, env);
- } break;
- case (iro_Const): {
- pto_node_cnst (node, env);
- } break;
- case (iro_SymConst): {
- pto_node_sym_cnst (node, env);
- } break;
- case (iro_Cast): {
- pto_t *cast_pto = compute_pto (get_Cast_op (node), env);
- set_pto (node, cast_pto);
- } break;
- case (iro_Block): {
- /* End Block ONLY */
- pto_node_end_block (node, env);
- } break;
- /* all the uninteresting stuff */
- case (iro_Div):
- case (iro_Quot):
- case (iro_Mod):
- case (iro_DivMod):
- set_pto (node, NULL);
- break;
- default: {
- /* stopgap measure */
- DBGPRINT (0, (stdout, "%s: not handled: node[%li].op = %s\n",
- __FUNCTION__,
- get_irn_node_nr (node),
- get_op_name (get_irn_op (node))));
- assert (0 && "something not handled");
- }
- }
-}
-static void pto_node_pre (ir_node *node, void *env)
-{
- DBGPRINT (1, (stdout, "%s (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (node)),
- get_irn_node_nr (node)));
-
- pto_init_node (node);
-}
-
-static void pto_node_post (ir_node *node, void *env)
-{
- DBGPRINT (1, (stdout, "%s (%s[%li])\n",
- __FUNCTION__,
- get_op_name (get_irn_op (node)),
- get_irn_node_nr (node)));
-
- pto_node (node, env);
-}
-
-static int pto_verbose = 0;
-
-/*
- Helper to pto_init --- clear the link fields of class types
-*/
-static void clear_type_link (type_or_ent *thing, void *__unused)
-{
- if (is_type (thing)) {
- type *tp = (type*) thing;
-
- if (is_class_type (tp)) {
- DBGPRINT (1, (stdout, "%s (\"%s\")\n",
- __FUNCTION__, get_type_name (tp)));
-
- set_type_link (tp, NULL);
- }
- } else if (is_entity (thing)) {
- entity *ent = (entity*) thing;
-
- DBGPRINT (1, (stdout, "%s (\"%s\")\n",
- __FUNCTION__, get_entity_name (ent)));
-
- set_entity_link (ent, NULL);
- }
-}
-
-/*
- Helper to pto_cleanup --- deallocate the field closure lists and clear the link fields of class types
-*/
-static void free_field_list (type_or_ent *thing, void *__unused)
-{
- if (is_type) {
- type *tp = (type*) thing;
-
- if (is_class_type (tp)) {
- if (NULL != get_type_link (tp)) {
- entity **fields = (entity**) get_type_link (tp);
-
- free (fields);
- }
-
- set_type_link (tp, NULL);
- }
- }
-}
-
-
-void set_pto (ir_node *node, pto_t *pto)
-{
- check_pto (pto);
-
- set_irn_link (node, (void*) pto);
-}
-
-int get_pto_verbose ()
-{
- return (pto_verbose);
-}
-
-void set_pto_verbose (int verbose)
-{
- pto_verbose = verbose;
-}
-
-/*
- Initialise Pto
-*/
-void pto_init ()
-{
- type_walk (clear_type_link, NULL, NULL);
-}
-
-
-/*
- Run Pto
-*/
-void pto_run (int do_verbose)
-{
- /* int i; */
- set_pto_verbose (do_verbose);
- set_pto_verbose (2);
-
- DBGPRINT (0, (stdout, "START PTO\n"));
-
- ir_graph *graph = get_irp_main_irg ();
-
- 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))));
-
- /* Set args for main graph */
- {
- type *meth_tp = get_entity_type (get_irg_entity (graph));
- type *param_tp = get_method_param_type (meth_tp, 1);
- param_tp = get_pointer_points_to_type (param_tp);
-
- const long n_args = /* wtf? */
- get_method_n_params (meth_tp);
- ir_node **args = find_irg_args (graph);
- pto_t *main_pto = pto_new_name (args [1], param_tp);
- int i;
-
- for (i = 0; i < n_args; i ++) {
- DBGPRINT (2, (stdout, "arg [%i] = %s[%ld]\n",
- i,
- args [i] ? get_op_name (get_irn_op (args [i])) : "none",
- args [i] ? get_irn_node_nr (args [i]) : -1));
- }
- set_pto (args [1], main_pto);
-
- free (args);
- }
-
- irg_walk_mem (graph, pto_node_pre, pto_node_post, NULL);
-
- DBGPRINT (0, (stdout, "END GRAPH (0x%08x)\n", (int) graph));
- DBGPRINT (0, (stdout, "END PTO\n"));
-
- obj_desc_list_all (NULL);
-}
-
-/*
- Clean Up
-*/
-void pto_cleanup ()
-{
- type_walk (free_field_list, NULL, NULL);
-}
-
-
-\f
-/*
- * $Log$
- * Revision 1.6 2004/11/09 16:47:09 liekweg
- * fix SymConst handling
- *
- * Revision 1.5 2004/11/08 12:33:06 liekweg
- * initialisation; sanitize print levels, misc fixes
- *
- * Revision 1.4 2004/11/04 14:58:38 liekweg
- * expanded pto, added initialisation, added debugging printing
- *
- * Revision 1.3 2004/10/25 11:59:45 liekweg
- * Copy Only works
- *
- * Revision 1.2 2004/10/21 11:09:37 liekweg
- * Moved memwalk stuf into irmemwalk
- * Moved lset stuff into lset
- * Moved typalise stuff into typalise
- *
- * Revision 1.1 2004/10/20 14:59:42 liekweg
- * Added ana2, added ecg and pto
- *
- */
/*
Project: libFIRM
File name: ir/ana/pto.h
- Purpose: Import all includes needed for PTO
+ Purpose: Import all includes needed for PTO/Entry to PTO
Author: Florian
Modified by:
Created: Sat Nov 13 19:35:27 CET 2004
/* ===================================================
Global Defines:
=================================================== */
+# define N_INITIAL_OJBS 10
/* ===================================================
Global Data Types:
/* ===================================================
Global Prototypes:
=================================================== */
+/* Perform PTO on all visible graphs. */
+void pto_init (int);
+void pto_run (void);
+void pto_cleanup (void);
/* ===================================================
Global Variables:
\f
/*
$Log$
+ Revision 1.6 2004/11/24 14:53:55 liekweg
+ Bugfixes
+
Revision 1.5 2004/11/18 16:37:07 liekweg
rewrite
# include "pto_comp.h"
# include "pto_util.h"
+# include "pto_name.h"
# include "pto_ctx.h"
# include "irnode.h"
/* Local Data Types: */
typedef struct pto_env_str {
- int dummy;
+ int ctx_idx;
} pto_env_t;
char *spaces = NULL;
/* Local Prototypes: */
-static void pto_graph (ir_graph*);
static void pto_call (ir_graph*, ir_node*, pto_env_t*);
/* ===================================================
pto_t *in_pto = NULL;
pto_t *proj_pto = get_node_pto (proj);
+ ir_node *proj_in_in = NULL;
+
switch (in_op) {
case (iro_Start): /* ProjT (Start) */
assert (0 && "pto from ProjT(Start) requested");
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)) */
if (NULL != proj_pto) {
return (proj_pto);
} else {
- in_pto = get_alloc_pto (proj_in);
+ in_pto = get_node_pto (proj_in);
assert (in_pto);
set_node_pto (proj, in_pto);
return (NULL);
}
+static pto_t *get_pto_sel (ir_node *sel)
+{
+ pto_t *pto = get_node_pto (sel);
+
+ if (NULL == pto) {
+ ir_node *in = get_Sel_ptr (sel);
+
+ pto = get_node_pto (in);
+ set_node_pto (sel, pto);
+ }
+
+ return (pto);
+}
+
static pto_t *get_pto_ret (ir_node *ret)
{
pto_t *pto = get_node_pto (ret);
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_Sel): return (get_pto_sel (node));
case (iro_Return): return (get_pto_ret (node));
default:
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 (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__, OPNAME (load), OPNUM (load), (void*) get_node_pto (load)));
+
+ ir_node *ptr = get_Load_ptr (load);
+ pto_t *ptr_pto = get_pto (ptr);
+
+ DBGPRINT (0, (stdout, "%s (%s[%li]): ptr = %p\n", __FUNCTION__, OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
}
static void pto_store (ir_node *store, pto_env_t *pto_env)
{
/* perform store */
- DBGPRINT (0, (stdout, "%s (%s[%li])\n", __FUNCTION__,
+ DBGPRINT (0, (stdout, "%s (%s[%li]) (no pto)\n", __FUNCTION__,
OPNAME (store), OPNUM (store)));
}
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)));
+ DBGPRINT (0, (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);
DBGPRINT (0, (stdout, "%s:%i (%s[%li]), graph %i\n",
__FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), i ++));
- pto_call (callEd_info->callEd, call, pto_env);
+ /* dike this out until we do procedure arguments and return
+ values */
+ if (0) {
+ pto_call (callEd_info->callEd, call, pto_env);
+ }
callEd_info = callEd_info->prev;
}
/* Todo: Compute Arguments */
- /* Initialise Alloc Names and Node values */
- pto_reset_graph_pto (graph, ctx_idx);
+ /* Initialise Alloc Names and Node values (nope, done in pto_graph ()) */
+ /* pto_reset_graph_pto (graph, ctx_idx); */
/* Visit/Iterate Graph */
- pto_graph (graph);
+ pto_graph (graph, ctx_idx);
/* Restore CTX */
set_curr_ctx (old_ctx);
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)));
+ DBGPRINT (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
+ OPNAME (raise), OPNUM (raise), (void*) get_node_pto (raise)));
}
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)));
+ DBGPRINT (0, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
+ OPNAME (end_block), OPNUM (end_block),
+ (void*) get_node_pto (end_block)));
}
/* Perform the appropriate action on the given node */
}
+/* ===================================================
+ Exported Implementation:
+ =================================================== */
/* Main loop: Initialise and iterate over the given graph */
-static void pto_graph (ir_graph *graph)
+void pto_graph (ir_graph *graph, int ctx_idx)
{
pto_env_t *pto_env = xmalloc (sizeof (pto_env_t));
- HERE ("start");
+ pto_env->ctx_idx = ctx_idx;
+
+ /* HERE ("start"); */
+
+ DBGPRINT (0, (stdout, "%s: start for ctx %i\n",
+ __FUNCTION__,
+ ctx_idx));
+
+ /* todo: pto_reset_graph_pto */
+ pto_reset_graph_pto (graph, ctx_idx);
/* todo (here): iterate, obey 'changed' attribute */
pto_graph_pass (graph, pto_env);
HERE ("end");
}
-/* "Fake" the arguments to the main method */
-static void fake_main_args (ir_graph *graph)
-{
- HERE ("start");
- /* todo: fake the arguments to the main method */
-
- HERE ("end");
-}
-
-/* Helper to pto_init */
-static void pto_init_graph_wrapper (graph_info_t *ginfo, void *__unused)
-{
- ir_graph *graph = ginfo->graph;
-
- pto_init_graph (graph);
-}
-
-
-/* ===================================================
- Exported Implementation:
- =================================================== */
/* Set the PTO value for the given non-alloc node */
void set_node_pto (ir_node *node, pto_t *pto)
{
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);
-
- 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");
-}
-
-void pto_run (int dbg_lvl)
-{
- HERE ("start");
- set_dbg_lvl (dbg_lvl);
-
- ir_graph *graph = get_irp_main_irg ();
- fake_main_args (graph);
-
- /* todo: clear entity/type links */
-
- 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);
-
- DBGPRINT (0, (stdout, "END PTO\n"));
- HERE ("end");
-}
-
-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.3 2004/11/24 14:53:55 liekweg
+ Bugfixes
+
Revision 1.2 2004/11/20 21:21:56 liekweg
Finalise initialisation
# ifndef _PTO_COMP_
# define _PTO_COMP_
+# include "pto.h"
# include "irnode.h"
+# include "qset.h"
/* ===================================================
Global Defines:
Global Data Types:
=================================================== */
typedef struct pto_str {
- int dummy;
+ qset_t *values;
} pto_t;
typedef struct alloc_pto_str {
/* ===================================================
Global Prototypes:
=================================================== */
+/* Main loop: Initialise the graph for the given ctx_idx and iterate over it */
+void pto_graph (ir_graph*, int);
+
/* Set the PTO value for the given node */
void set_node_pto (ir_node*, pto_t*);
/*Get the PTO value for the given non-alloc node */
pto_t *get_alloc_pto (ir_node*);
-/* Perform PTO on all visible graphs. */
-void pto_init (void);
-void pto_run (int);
-void pto_cleanup (void);
-
/* ===================================================
Global Variables:
=================================================== */
\f
/*
$Log$
+ Revision 1.2 2004/11/24 14:53:55 liekweg
+ Bugfixes
+
Revision 1.1 2004/11/18 16:37:34 liekweg
rewritten
# include "ecg.h"
# include "irnode.h"
-# include "xmalloc.h"
+/* # include "xmalloc.h" */
/* Local Defines: */
\f
/*
$Log$
+ Revision 1.3 2004/11/24 14:53:55 liekweg
+ Bugfixes
+
Revision 1.2 2004/11/20 21:21:35 liekweg
Add pto_ctx_allocs
# include "pto_debug.h"
# include "irnode.h"
-# include "xmalloc.h"
+/* # include "xmalloc.h" */
/* Local Defines: */
\f
/*
$Log$
+ Revision 1.2 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.1 2004/11/18 16:37:34 liekweg
rewritten
# define DBGEXE(lvl, cmd) if (get_dbg_lvl () > lvl) {cmd;}
# define OPNAME(node) get_op_name (get_irn_op (node))
# define OPNUM(node) get_irn_node_nr (node)
-# define HERE(msg) fprintf (stdout, "%s:%i: %s\n", __FUNCTION__, __LINE__, msg)
+# define HERE(msg) fprintf (stdout, "%s:%i %s\n", __FUNCTION__, __LINE__, msg)
# define HERE2(msg1, msg2) fprintf (stdout, "%s:%i: %s %s\n", __FUNCTION__, __LINE__, msg1, msg2)
# define HERE3(msg1, msg2, msg3) fprintf (stdout, "%s:%i: %s %s %s\n", __FUNCTION__, __LINE__, msg1, msg2, msg3)
\f
/*
$Log$
+ Revision 1.2 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.1 2004/11/18 16:37:34 liekweg
rewritten
pto_init: Initialisation Functions
*/
+# include <obstack.h>
+# include <string.h>
+
+# include "pto.h"
# include "pto_init.h"
# include "pto_debug.h"
# include "pto_comp.h"
+# include "pto_name.h"
+# include "pto_util.h"
# include "typewalk.h"
# include "irgwalk.h"
# include "xmalloc.h"
/* Local Defines: */
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
/* Local Data Types: */
typedef struct init_env_str
} reset_env_t;
/* Local Variables: */
+extern struct obstack *qset_obst; /* from pto_name */
+
+static struct obstack *pto_obst = NULL; /* all pto_t's go onto this one */
/* Local Prototypes: */
/* Allocate a new pto */
static pto_t *new_pto (ir_node *node)
{
- /* dummy implementation for fake_pto */
- pto_t *pto = xmalloc (sizeof (pto_t));
+ pto_t *pto = obstack_alloc (pto_obst, sizeof (pto_t));
+ pto->values = qset_new (N_INITIAL_OJBS, qset_obst);
return (pto);
}
/* Allocate a new alloc_pto */
-static alloc_pto_t *new_alloc_pto (ir_node *node, int n_ctxs)
+static alloc_pto_t *new_alloc_pto (ir_node *alloc, int n_ctxs)
{
+ assert (iro_Alloc == get_irn_opcode (alloc));
+
int i;
- /* dummy implementation for testing */
- alloc_pto_t *alloc_pto = xmalloc (sizeof (alloc_pto_t));
+ alloc_pto_t *alloc_pto = obstack_alloc (pto_obst, sizeof (alloc_pto_t));
+ type *tp = get_Alloc_type (alloc);
- alloc_pto->ptos = (pto_t**) xmalloc (n_ctxs * sizeof (pto_t*));
+ alloc_pto->ptos = (pto_t**) obstack_alloc (pto_obst, n_ctxs * sizeof (pto_t*));
for (i = 0; i < n_ctxs; i ++) {
- alloc_pto->ptos [i] = new_pto (node);
+ desc_t *desc = new_name (tp, alloc);
+ alloc_pto->ptos [i] = new_pto (alloc);
+ qset_insert (alloc_pto->ptos [i]->values, desc);
}
return (alloc_pto);
}
+/* Allocate a new pto for a symconst */
+static pto_t* new_symconst_pto (ir_node *symconst)
+{
+ assert (iro_SymConst == get_irn_opcode (symconst));
+
+ pto_t *pto = new_pto (symconst);
+ entity *ent = get_SymConst_entity (symconst);
+ desc_t *desc = new_ent_name (ent);
+
+ qset_insert (pto->values, desc);
+
+ return (pto);
+}
/* Helper to pto_init --- clear the link fields of class types */
static void clear_type_link (type_or_ent *thing, void *__unused)
case (iro_Const):
case (iro_Call):
case (iro_Phi): {
- /* todo: allocate 'empty' pto values */
+ /* allocate 'empty' pto values */
pto_t *pto = new_pto (node);
set_node_pto (node, pto);
} break;
case (iro_Alloc): {
- /* todo: set alloc to 'right' current pto */
+ /* 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];
} break;
}
/* Temporary fix until we get 'real' ptos: Allocate some dummy for pto */
-static void init_alloc_pto (ir_node *node, void *env)
+static void init_pto (ir_node *node, void *env)
{
init_env_t *init_env = (init_env_t*) env;
int n_ctxs = init_env->n_ctxs;
const opcode op = get_irn_opcode (node);
switch (op) {
- case (iro_Load):
- case (iro_SymConst):
- case (iro_Const):
- case (iro_Call):
- case (iro_Phi): {
- /* nothing (handled by init_node_pto) */
- } break;
-
+ case (iro_SymConst): {
+ const symconst_kind kind = get_SymConst_kind (node);
+
+ if ((kind == symconst_addr_name) || (kind == symconst_addr_ent)) {
+ entity *ent = get_SymConst_entity (node);
+
+ if (is_pointer_type (get_entity_type (ent))) {
+ DBGPRINT (0, (stdout, "%s: new name \"%s\" for symconst \"%s[%li]\"\n",
+ __FUNCTION__,
+ get_entity_name (ent),
+ OPNAME (node),
+ OPNUM (node)));
+
+ pto_t *symconst_pto = new_symconst_pto (node);
+ set_node_pto (node, symconst_pto);
+ }
+ }
+ } break;
case (iro_Alloc): {
- /* todo: alloc 'right' ptos */
+ type *tp = get_Alloc_type (node); /* debugging only */
alloc_pto_t *alloc_pto = new_alloc_pto (node, n_ctxs);
set_alloc_pto (node, alloc_pto);
- } break;
+ DBGPRINT (0, (stdout, "%s: %i names \"%s\" for alloc \"%s[%li]\"\n",
+ __FUNCTION__,
+ n_ctxs,
+ get_type_name (tp),
+ OPNAME (node),
+ OPNUM (node)));
+ } break;
+
+ case (iro_Load):
+ case (iro_Call):
+ case (iro_Phi):
+ case (iro_Const):
+ /* nothing --- handled by reset_node_pto on each pass */
+ break;
default: {
/* nothing */
} break;
HERE ("start");
- irg_walk_graph (graph, init_alloc_pto, NULL, init_env);
+ irg_walk_graph (graph, init_pto, NULL, init_env);
+
+ memset (init_env, 0x00, sizeof (init_env_t));
+ free (init_env);
HERE ("end");
}
/* ===================================================
Exported Implementation:
=================================================== */
+/* "Fake" the arguments to the main method */
+void fake_main_args (ir_graph *graph)
+{
+ HERE ("start");
+
+ 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[]*[]* */
+
+ /* 'main' has signature 'void(int, char[]*[]*)' */
+ assert (NULL == args [2]);
+
+ assert (is_pointer_type (ctp));
+
+ ctp = get_pointer_points_to_type (ctp); /* ctp == char[]*[] */
+
+ assert (is_array_type (ctp));
+
+ desc_t *arg_desc = new_name (ctp, args [1]);
+ pto_t *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);
+
+# 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 ()
+{
+ pto_obst = (struct obstack*) xmalloc (sizeof (struct obstack));
+
+ obstack_init (pto_obst);
+}
+
+/* Cleanup the Init module */
+void pto_init_cleanup ()
+{
+ 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 ()
{
irg_walk_graph (graph, reset_node_pto, NULL, reset_env);
+ memset (reset_env, 0x00, sizeof (reset_env_t));
+ free (reset_env);
HERE ("end");
}
\f
/*
$Log$
+ Revision 1.5 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.4 2004/11/20 21:21:56 liekweg
Finalise initialisation
/* ===================================================
Global Prototypes:
=================================================== */
+/* "Fake" the arguments to the main method */
+void fake_main_args (ir_graph*);
+
+/* Initialise the Init module */
+void pto_init_init (void);
+
+/* Cleanup the Init module */
+void pto_init_cleanup (void);
+
/* Initialise the Names of the Types/Entities */
void pto_init_type_names (void);
\f
/*
$Log$
+ Revision 1.4 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.3 2004/11/20 21:21:56 liekweg
Finalise initialisation
/* -*- c -*- */
/*
- Project: libFIRM
- File name: ir/ana/pto_name.c
- Purpose: ...
- 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.
+ Project: libFIRM
+ File name: ir/ana/pto_name.c
+ Purpose: Names for abstract objects
+ 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
# endif
/*
- pto_name: ...
+ pto_name: Names for abstract objects
*/
+# include "pto.h"
# include "pto_name.h"
+# include "pto_util.h"
+
+# include <string.h> /* for memcpy */
+# include <obstack.h>
# include "irnode.h"
+# include "irprog.h"
# include "xmalloc.h"
# include "pto_debug.h"
/* Local Defines: */
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
+
+# define NALLOC(size) obstack_alloc (name_obst, size)
/* Local Data Types: */
/* Local Variables: */
+struct obstack *qset_obst = NULL;
+struct obstack *name_obst = NULL;
/* Local Prototypes: */
/* ===================================================
Local Implementation:
=================================================== */
+/* See whether the given entity is a field. */
+static int is_field (entity *ent)
+{
+ type *tp = get_entity_type (ent);
+
+ if (is_primitive_type (tp) || is_pointer_type (tp)) {
+ /* actually, we could get by by restricting ourselves to pointer types */
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+/* Helper to collect_fields(type*): collect all fields of the given
+ clazz and its super classes into the given obstack. */
+static void _collect_fields (type *clazz, struct obstack *obst)
+{
+ int n_members = get_class_n_members (clazz);
+ int n_supers = get_class_n_supertypes (clazz);
+ int i;
+
+ for (i = 0; i < n_members; i ++) {
+ entity *ent = get_class_member (clazz, i);
+
+ if (is_field (ent)) {
+ if (allocation_static != get_entity_allocation (ent)) {
+ obstack_ptr_grow (obst, ent);
+ }
+ }
+ }
+
+ for (i = 0; i < n_supers; i ++) {
+ type *s_clazz = get_class_supertype (clazz, i);
+
+ _collect_fields (s_clazz, obst);
+ }
+}
+
+/* Collect the fields of the given class and its super classes into an array.
+ The last entry of the array is written NULL. */
+static entity **collect_fields (type *clazz)
+{
+ if (NULL != get_type_link (clazz)) {
+ DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
+ __FUNCTION__, get_type_name (clazz)));
+
+ return ((entity **) get_type_link (clazz));
+ } else {
+ DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
+ __FUNCTION__, get_type_name (clazz)));
+ }
+
+ struct obstack obst;
+
+ obstack_init (&obst);
+
+ _collect_fields (clazz, &obst);
+
+ /* append terminating NULL */
+ int *the_null = NULL;
+ obstack_ptr_grow (&obst, the_null);
+
+ int n_fields = obstack_object_size (&obst) / sizeof (void*);
+
+ entity ** fields = (entity**) NALLOC (n_fields * sizeof (entity*));
+ void *tmp = obstack_finish (&obst);
+
+ memcpy (fields, tmp, n_fields * sizeof (entity*));
+
+ obstack_free (&obst, NULL);
+
+ set_type_link (clazz, (void*) fields);
+
+ return (fields);
+}
+
/* ===================================================
Exported Implementation:
=================================================== */
+static desc_t *all_descs = NULL;
+
+/* get a new descriptor for the given type at the given node */
+desc_t *new_name (type *tp, ir_node *node)
+{
+ desc_t *desc = NULL;
+
+ assert ((is_class_type (tp) || is_array_type (tp)) && "unsuitable type");
+
+ DBGPRINT (2, (stdout, "%s: new name for type \"%s\"\n", __FUNCTION__,
+ get_type_name (tp)));
+ fflush (stdout);
+
+ if (is_class_type (tp)) {
+ obj_desc_t *obj_desc = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
+ int i;
+ int n_fields;
+
+ obj_desc->kind = object;
+ obj_desc->fields = collect_fields (tp);
+
+ for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
+ /* nothing, just count ... */
+ }
+
+ obj_desc->n_fields = n_fields;
+ obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t));
+ for (i = 0; i < n_fields; i ++) {
+ obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
+ }
+ desc = (desc_t*) obj_desc;
+ } else if (is_array_type (tp)) {
+ arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
+ arr_desc->kind = array;
+ arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
+
+ desc = (desc_t*) arr_desc;
+ }
+
+ desc->tp = tp;
+ desc->node = node;
+
+ desc->prev = all_descs;
+ all_descs = desc;
+
+ return (desc);
+}
+
+# define N_GLOB_INITIAL_FIELDS 20
+static obj_desc_t *obj_glob = NULL;
+static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
+
+/* get a new descriptor for the given (presumably static) entity */
+desc_t *new_ent_name (entity *ent)
+{
+ int i;
+ int missing = TRUE;
+ type *tp = get_entity_type (ent);
+
+ assert (is_pointer_type (tp));
+ tp = get_pointer_points_to_type (tp);
+ assert (is_class_type (tp));
+
+ assert (((allocation_static == get_entity_allocation (ent)) ||
+ (allocation_automatic == get_entity_allocation (ent))) &&
+ "not a static/automatic field");
+
+ if (NULL == obj_glob) {
+ obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
+
+ obj_glob->kind = object;
+ obj_glob->tp = get_glob_type ();
+ obj_glob->node = NULL;
+
+ obj_glob->n_fields = 0;
+ obj_glob->fields = (entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (entity*));
+ obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
+
+ obj_glob->prev = all_descs;
+ all_descs = (desc_t*) obj_glob;
+ }
+
+ for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
+ if (ent == obj_glob->fields [i]) {
+ missing = FALSE;
+ }
+ }
+
+ if (missing) {
+ if (obj_glob->n_fields == n_glob_fields) {
+ entity **fields = obj_glob->fields;
+ qset_t **values = obj_glob->values;
+
+ n_glob_fields *= 2;
+ obj_glob->fields = (entity**) NALLOC (n_glob_fields * sizeof (entity*));
+ obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
+
+ memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (entity*));
+ memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
+
+ /* free (fields); */
+ /* free (values); */
+ }
+
+ obj_glob->fields [obj_glob->n_fields ] = ent;
+ obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
+ }
+
+ return ((desc_t*) obj_glob);
+}
+# undef N_GLOB_INITIAL_FIELDS
+
+/* Initialise the name module */
+void pto_name_init ()
+{
+ DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
+ assert (NULL == name_obst);
+ assert (NULL == qset_obst);
+
+ name_obst = xmalloc (sizeof (struct obstack));
+ qset_obst = xmalloc (sizeof (struct obstack));
+
+ obstack_init (name_obst);
+ obstack_init (qset_obst);
+}
+
+/* Cleanup the name module */
+void pto_name_cleanup ()
+{
+ DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
+ obstack_free (name_obst, NULL);
+ obstack_free (qset_obst, NULL);
+
+ memset (name_obst, 0x00, sizeof (struct obstack));
+ memset (qset_obst, 0x00, sizeof (struct obstack));
+
+ free (name_obst);
+ free (qset_obst);
+
+ name_obst = NULL;
+ qset_obst = NULL;
+}
\f
/*
$Log$
+ Revision 1.2 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.1 2004/11/18 16:37:34 liekweg
rewritten
/* -*- c -*- */
/*
- Project: libFIRM
- File name: ir/ana/pto_name.h
- Purpose: ...
- 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.
+ Project: libFIRM
+ File name: ir/ana/pto_name.h
+ Purpose: Names for abstract objects
+ 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.
*/
# ifndef _PTO_NAME_
# define _PTO_NAME_
+# include "pto_comp.h" /* for pto_t */
+# include "irnode.h"
+# include "type.h"
+# include "qset.h"
+
/* ===================================================
Global Defines:
=================================================== */
/* ===================================================
- Global Data Types:
- =================================================== */
+ Global Data Types:
+ =================================================== */
+typedef enum desc_kind_enum {
+ none,
+ object,
+ array
+} desc_kind_t;
+
+/* abstract super class for all descriptors */
+typedef struct desc_str
+{
+ desc_kind_t kind;
+ type *tp;
+ ir_node *node; /* allocation node */
+ struct desc_str *prev; /* linked list */
+} desc_t;
+
+/* object descriptor */
+typedef struct obj_desc_str
+{
+ desc_kind_t kind;
+ type *tp;
+ ir_node *node; /* allocation node */
+ struct desc_str *prev; /* linked list */
+
+ int n_fields;
+ entity **fields;
+ qset_t **values;
+} obj_desc_t;
+
+/* array descriptor */
+typedef struct arr_desc_str
+{
+ desc_kind_t kind;
+ type *tp;
+ ir_node *node; /* allocation node */
+ struct desc_str *prev; /* linked list */
+
+ qset_t *value;
+} arr_desc_t;
/* ===================================================
Global Prototypes:
=================================================== */
+/* get a new descriptor for the given type at the given node */
+desc_t *new_name (type*, ir_node*);
+
+/* get a new descriptor for the given (presumably static) entity */
+desc_t *new_ent_name (entity*);
+
+/* Initialise the name module */
+void pto_name_init (void);
+
+/* Cleanup the name module */
+void pto_name_cleanup (void);
/* ===================================================
Global Variables:
\f
/*
$Log$
+ Revision 1.2 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.1 2004/11/18 16:37:34 liekweg
rewritten
# include "pto_util.h"
# include "irnode.h"
+# include "irgwalk.h"
# include "xmalloc.h"
# include "pto_debug.h"
/* Local Defines: */
/* Local Data Types: */
+/* Environment for find_irg_args */
+typedef struct find_irg_args_env {
+ ir_node **args;
+ ir_node *arg;
+} find_irg_args_env_t;
+
/* Local Variables: */
/* ===================================================
Local Implementation:
=================================================== */
+/* Helper for find_irg_args */
+static void find_irg_arg (ir_node *node, void *env)
+{
+ find_irg_args_env_t *arg_env = (find_irg_args_env_t*) env;
+ if (iro_Proj == get_irn_opcode (node)) {
+ if (arg_env->arg == get_Proj_pred (node)) {
+ long n = get_Proj_proj (node);
+
+ assert (! arg_env->args [n]);
+
+ arg_env->args [n] = node;
+ }
+ }
+}
/* ===================================================
Exported Implementation:
=================================================== */
+/* Find the arguments of a graph. For a method that has n args, the
+ result array has 'n+1' entries, the last of which is written NULL. */
+ir_node **find_irg_args (ir_graph *graph)
+{
+ type *tp = get_entity_type (get_irg_entity (graph));
+ const int n_args = get_method_n_params (tp);
+ ir_node **args = (ir_node**) xmalloc (sizeof (ir_node*) * (n_args+1));
+ ir_node *arg = get_irg_args (graph);
+ find_irg_args_env_t *arg_env =
+ (find_irg_args_env_t*) xmalloc (sizeof (find_irg_args_env_t));
+
+ arg_env->args = args;
+ arg_env->arg = arg;
+
+ /* or use get_irg_end ?!? */
+ {
+ ir_graph *save = get_current_ir_graph ();
+ set_current_ir_graph (graph);
+ irg_walk (get_irg_end (graph), find_irg_arg, NULL, arg_env);
+ set_current_ir_graph (save);
+ }
+
+ free (arg_env);
+
+ args [n_args] = NULL;
+
+ return (args);
+}
/* Get the entity of a ptr */
entity *get_ptr_ent (ir_node *ptr)
{
\f
/*
$Log$
+ Revision 1.7 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.6 2004/11/18 16:37:07 liekweg
rewrite
/* ===================================================
Global Prototypes:
=================================================== */
+/* Get the entity of a ptr */
entity *get_ptr_ent (ir_node*);
+/* Find the arguments of a graph. For a method that has n args, the
+ result array has 'n+1' entries, the last of which is written NULL. */
+ir_node **find_irg_args (ir_graph*);
+
/* ===================================================
Global Variables:
=================================================== */
\f
/*
$Log$
+ Revision 1.5 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.4 2004/11/18 16:37:07 liekweg
rewrite
/* -*- c -*- */
/*
- * Time-stamp: <11.11.2004 16:42:15h liekweg>
+ * Time-stamp: <23.11.2004 13:26:21h liekweg>
* Project: libFIRM
* File name: ir/ana2/qset.c
* Purpose: yet another set implementation
# include <assert.h>
# include <string.h>
# include <sys/time.h>
+# include <obstack.h>
# include "timing.h"
# include "qset.h"
return ((a < b) ? -1 : +1);
}
+/*
+ Wrapper for mixed allocation
+*/
+static void *mix_malloc (struct obstack *obst, size_t size)
+{
+ if (NULL != obst) {
+ return (obstack_alloc (obst, size));
+ } else {
+ return (malloc (size));
+ }
+}
+
/*
Allocate a list of sortables of the given length.
*/
-static sortable_t *alloc_list (const int len)
+static sortable_t *alloc_list (const int len, struct obstack *obst)
{
- sortable_t *values = (sortable_t*) malloc (len * sizeof (sortable_t));
+ sortable_t *values = (sortable_t*) mix_malloc (obst, len * sizeof (sortable_t));
memset (values, 0x00, len * sizeof (sortable_t));
/*
Create a list of sortables of the given length.
*/
-static sortable_t *gen_list (const int len)
+static sortable_t *gen_list (const int len, struct obstack *obst)
{
int i;
- sortable_t *values = alloc_list (len);
+ sortable_t *values = alloc_list (len, obst);
for (i = 0; i < len; i ++) {
values [i] = rand () >> 16;
int qtotal = 0;
for (i = 0; i < n_runs; i ++) {
- sortable_t *list = gen_list (n_elems);
+ sortable_t *list = gen_list (n_elems, NULL);
timing_t *timing = start_timing ();
q_sort (list, n_elems);
}
for (i = 0; i < n_runs; i ++) {
- sortable_t *list = gen_list (n_elems);
+ sortable_t *list = gen_list (n_elems, NULL);
timing_t *timing = start_timing ();
qsort (list, n_elems, sizeof (sortable_t), sortable_compare);
int i;
int n1, n2, n;
- qset_t *q1 = qset_new (n_entries);
- qset_t *q2 = qset_new (n_entries);
+ qset_t *q1 = qset_new (n_entries, NULL);
+ qset_t *q2 = qset_new (n_entries, NULL);
qset_t *q = NULL;
- sortable_t *values = gen_list (n_entries);
+ sortable_t *values = gen_list (n_entries, NULL);
for (i = 0; i < n_entries; i ++) {
qset_insert (q1, values [i]);
new_size *= 2;
}
- values = alloc_list (new_size);
+ values = alloc_list (new_size, qset->obst);
memcpy (values, qset->values, qset->n_elems * sizeof (sortable_t));
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t)); /* debug only */
Merge two sorted lists. Keep duplicates (if present)
*/
static sortable_t *q_merge (sortable_t *list1, const int n1_elems,
- sortable_t *list2, const int n2_elems)
+ sortable_t *list2, const int n2_elems,
+ struct obstack *obst)
{
const int n_elems = n1_elems + n2_elems;
- sortable_t *res = alloc_list (n_elems);
+ sortable_t *res = alloc_list (n_elems, obst);
int i1 = 0;
int i2 = 0;
/*
Allocate a new qset with initial space for up to n_elems.
+ If a non-NULL obstack is given, it is used for all allocations of this qset
+ and must be initialised and deleted by the user of the qset.
*/
-qset_t *qset_new (const int n_elems)
+qset_t *qset_new (const int n_elems, struct obstack *obst)
{
- qset_t *qset = (qset_t*) malloc (sizeof (qset_t));
+ qset_t *qset = (qset_t*) mix_malloc (obst, sizeof (qset_t));
- qset->values = alloc_list (n_elems);
+ qset->obst = obst;
+ qset->values = alloc_list (n_elems, obst);
memset (qset->values, 0x00, n_elems * sizeof (sortable_t));
qset->n_slots = n_elems;
*/
void qset_compact (qset_t *qset)
{
- sortable_t *values = (sortable_t*) malloc (qset->n_elems * sizeof (sortable_t));
+ sortable_t *values = (sortable_t*) mix_malloc (qset->obst,
+ qset->n_elems * sizeof (sortable_t));
memcpy (values, qset->values, qset->n_elems * sizeof (sortable_t));
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t));
void qset_delete (qset_t *qset)
{
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t));
- free (qset->values);
+
+ if (NULL == qset->obst) {
+ free (qset->values);
+ }
memset (qset, 0x00, sizeof (qset_t));
- free (qset);
+ if (NULL == qset->obst) {
+ free (qset);
+ }
}
/*
qset_sort (qset2);
qset1->values = q_merge (qset1->values, qset1->n_elems,
- qset2->values, qset2->n_elems);
+ qset2->values, qset2->n_elems,
+ qset1->obst);
qset1->n_elems = qset1->n_elems + qset2->n_elems;
qset1->n_slots = qset1->n_elems;
*/
qset_t *qset_union (qset_t *qset1, qset_t *qset2)
{
- qset_t *qset = (qset_t*) malloc (sizeof (qset_t));
+ qset_t *qset = (qset_t*) mix_malloc (qset1->obst, sizeof (qset_t));
const int n_elems = qset1->n_elems + qset2->n_elems;
- qset->values = alloc_list (n_elems);
+ qset->values = alloc_list (n_elems, qset1->obst);
memcpy (qset->values, qset1->values,
qset1->n_elems * sizeof (sortable_t));
memcpy (qset->values+qset1->n_elems,
qset2->values, qset2->n_elems * sizeof (sortable_t));
+ qset->obst = qset1->obst;
qset->n_elems = n_elems;
qset->n_slots = qset->n_elems;
/*
$Log$
+ Revision 1.5 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.4 2004/11/18 16:35:45 liekweg
Added unique ids for debugging
/* -*- c -*- */
/*
- * Time-stamp: <11.11.2004 16:42:22h liekweg>
+ * Time-stamp: <23.11.2004 13:23:46h liekweg>
* Project: libFIRM
* File name: ir/ana2/qset.h
* Purpose: yet another set implementation
/* typedef unsigned int sortable_t; */
typedef void* sortable_t;
+struct obstack; /* forward decl */
+
typedef struct qset_str
{
+ struct obstack *obst;
sortable_t *values;
int n_slots;
int n_elems;
/* QSET INTERFACE */
-/* Allocate a new qset with initial space for up to n_elems. */
-qset_t *qset_new (const int);
+/* Allocate a new qset with initial space for up to n_elems.
+ If a non-NULL obstack is given, it is used for all allocations of this qset
+ and must be initialised and deleted by the user of the qset. */
+qset_t *qset_new (const int, struct obstack*);
/* Sort the entries of the given qset. */
void qset_sort (qset_t*);
/*
$Log$
+ Revision 1.4 2004/11/24 14:53:56 liekweg
+ Bugfixes
+
Revision 1.3 2004/11/18 16:35:46 liekweg
Added unique ids for debugging