rework taking of parameter addresses
authorMatthias Braun <matze@braunis.de>
Fri, 5 Aug 2011 08:58:44 +0000 (10:58 +0200)
committerMatthias Braun <matze@braunis.de>
Fri, 5 Aug 2011 08:58:44 +0000 (10:58 +0200)
Use a special kind of entity on the frame type instead of a value_type
struct inside a method type. This makes replacement of function types
slightly easier (it's still a complex operation though) and handling in
the backend a bit more consistent since it's more or less a normal stack
access (with special offsets).

16 files changed:
include/libfirm/irgraph.h
include/libfirm/typerep.h
ir/be/arm/arm_transform.c
ir/be/beabi.c
ir/be/sparc/sparc_transform.c
ir/ir/irgraph.c
ir/ir/irio.c
ir/lower/lower_calls.c
ir/lower/lower_dw.c
ir/opt/opt_inline.c
ir/opt/scalar_replace.c
ir/tr/entity.c
ir/tr/entity_t.h
ir/tr/type.c
ir/tr/type_t.h
ir/tr/typewalk.c

index 2a72e6a..83b89de 100644 (file)
@@ -190,9 +190,6 @@ FIRM_API ir_type *get_irg_frame_type(ir_graph *irg);
 /** Sets the frame type of an IR graph. */
 FIRM_API void set_irg_frame_type(ir_graph *irg, ir_type *ftp);
 
-/** Returns the value parameter type of an IR graph. */
-FIRM_API ir_type *get_irg_value_param_type(ir_graph *irg);
-
 /** Returns the start block of an IR graph. */
 FIRM_API ir_node *get_irg_start_block(const ir_graph *irg);
 /** Sets the start block of an IR graph. */
index ec2294e..3f49774 100644 (file)
@@ -200,6 +200,19 @@ FIRM_API ir_entity *new_entity(ir_type *owner, ident *name, ir_type *tp);
 FIRM_API ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *tp,
                                  dbg_info *db);
 
+/**
+ * Creates a new entity corresponding to a function parameter.
+ * This must be created on an irgs frame_type
+ */
+FIRM_API ir_entity *new_parameter_entity(ir_type *owner, size_t pos,
+                                         ir_type *type);
+
+/**
+ * Like new_parameter_entity() but with debug information.
+ */
+FIRM_API ir_entity *new_d_parameter_entity(ir_type *owner, size_t pos,
+                                           ir_type *type, dbg_info *dbgi);
+
 /**
  * Copies the entity if the new_owner is different from the
  * owner of the old entity,  else returns the old entity.
@@ -400,6 +413,22 @@ FIRM_API dbg_info *get_entity_dbg_info(const ir_entity *ent);
  */
 FIRM_API void set_entity_dbg_info(ir_entity *ent, dbg_info *db);
 
+/**
+ * returns true if a given entity is a parameter_entity representing the
+ * address of a function parameter
+ */
+FIRM_API int is_parameter_entity(const ir_entity *entity);
+
+/**
+ * returns number of parameter a parameter entitiy represents
+ */
+FIRM_API size_t get_entity_parameter_number(const ir_entity *entity);
+
+/**
+ * set number of parameter an entity represents
+ */
+FIRM_API void set_entity_parameter_number(ir_entity *entity, size_t n);
+
 /* -- Representation of constant values of entities -- */
 /**
  * Returns true if the the node is representable as code on
@@ -1588,18 +1617,6 @@ FIRM_API ir_type *get_method_param_type(ir_type *method, size_t pos);
     Also changes the type in the pass-by-value representation by just
     changing the type of the corresponding entity if the representation is constructed. */
 FIRM_API void set_method_param_type(ir_type *method, size_t pos, ir_type *tp);
-/** Returns an entity that represents the copied value argument.  Only necessary
-   for compounds passed by value. This information is constructed only on demand. */
-FIRM_API ir_entity *get_method_value_param_ent(ir_type *method, size_t pos);
-/**
- * Sets the type that represents the copied value arguments.
- */
-FIRM_API void set_method_value_param_type(ir_type *method, ir_type *tp);
-/**
- * Returns a type that represents the copied value arguments if one
- * was allocated, else NULL.
- */
-FIRM_API ir_type *get_method_value_param_type(const ir_type *method);
 /** Returns the number of results of a method type. */
 FIRM_API size_t get_method_n_ress(const ir_type *method);
 /** Returns the return type of a method type at position pos. */
@@ -2095,18 +2112,6 @@ FIRM_API int is_code_type(const ir_type *tp);
  */
 FIRM_API int is_frame_type(const ir_type *tp);
 
-/**
- * Checks, whether a type is a value parameter type.
- */
-FIRM_API int is_value_param_type(const ir_type *tp);
-
-/**
- * Makes a new value type. Value types are struct types,
- * so all struct access functions work.
- * Value types are not in the global list of types.
- */
-FIRM_API ir_type *new_type_value(void);
-
 /**
  * Makes a new frame type. Frame types are class types,
  * so all class access functions work.
index 36e7da7..dc1f479 100644 (file)
@@ -2034,10 +2034,6 @@ static ir_node *gen_Sel(ir_node *node)
        /* must be the frame pointer all other sels must have been lowered
         * already */
        assert(is_Proj(ptr) && is_Start(get_Proj_pred(ptr)));
-       /* we should not have value types from parameters anymore - they should be
-          lowered */
-       assert(get_entity_owner(entity) !=
-                       get_method_value_param_type(get_entity_type(get_irg_entity(get_irn_irg(node)))));
 
        return new_bd_arm_FrameAddr(dbgi, new_block, new_ptr, entity, 0);
 }
index 1c85655..b2588b4 100644 (file)
@@ -1131,51 +1131,73 @@ static void process_calls(ir_graph *irg)
  *
  * @param call          the current call ABI
  * @param method_type   the method type
- * @param val_param_tp  the value parameter type, will be destroyed
- * @param param_map     an array mapping method arguments to the stack layout type
+ * @param param_map     an array mapping method arguments to the stack layout
+ *                      type
  *
  * @return the stack argument layout type
  */
 static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
-                                                                ir_type *method_type, ir_type *val_param_tp,
-                                                                ir_entity ***param_map)
+                                                                ir_type *method_type, ir_entity ***param_map)
 {
-       int n    = get_method_n_params(method_type);
        struct obstack *obst = be_get_be_obst(irg);
-       int ofs  = 0;
+       ir_type *frame_type      = get_irg_frame_type(irg);
+       size_t   n_params        = get_method_n_params(method_type);
+       size_t   n_frame_members = get_compound_n_members(frame_type);
+       size_t   f;
+       int      ofs  = 0;
 
-       char buf[128];
        ir_type *res;
-       int i;
-       ident *id = get_entity_ident(get_irg_entity(irg));
+       size_t i;
        ir_entity **map;
 
-       *param_map = map = OALLOCN(obst, ir_entity*, n);
-       res = new_type_struct(id_mangle_u(id, new_id_from_chars("arg_type", 8)));
-       for (i = 0; i < n; ++i) {
-               ir_type *param_type    = get_method_param_type(method_type, i);
-               be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 1);
+       *param_map = map = OALLOCNZ(obst, ir_entity*, n_params);
+       res = new_type_struct(new_id_from_chars("arg_type", 8));
 
-               map[i] = NULL;
-               if (arg->on_stack) {
-                       if (val_param_tp != NULL) {
-                               /* the entity was already created, create a copy in the param type */
-                               ir_entity *val_ent = get_method_value_param_ent(method_type, i);
-                               arg->stack_ent = copy_entity_own(val_ent, res);
-                               set_entity_link(val_ent, arg->stack_ent);
-                               set_entity_link(arg->stack_ent, NULL);
-                       } else {
-                               /* create a new entity */
-                               snprintf(buf, sizeof(buf), "param_%d", i);
-                               arg->stack_ent = new_entity(res, new_id_from_str(buf), param_type);
-                       }
-                       ofs += arg->space_before;
-                       ofs = round_up2(ofs, arg->alignment);
-                       set_entity_offset(arg->stack_ent, ofs);
-                       ofs += arg->space_after;
-                       ofs += get_type_size_bytes(param_type);
-                       map[i] = arg->stack_ent;
+       /* collect existing entities for value_param_types */
+       for (f = n_frame_members; f > 0; ) {
+               ir_entity         *entity = get_compound_member(frame_type, --f);
+               size_t             num;
+               be_abi_call_arg_t *arg;
+
+               set_entity_link(entity, NULL);
+               if (!is_parameter_entity(entity))
+                       continue;
+               num = get_entity_parameter_number(entity);
+               assert(num < n_params);
+               if (map[num] != NULL)
+                       panic("multiple entities for parameter %u in %+F found", f, irg);
+
+               arg = get_call_arg(call, 0, num, 1);
+               if (!arg->on_stack) {
+                       map[num] = NULL;
+                       /* don't move this entity */
+                       continue;
+               }
+
+               map[num] = entity;
+               /* move entity to new arg_type */
+               set_entity_owner(entity, res);
+       }
+
+       for (i = 0; i < n_params; ++i) {
+               be_abi_call_arg_t *arg        = get_call_arg(call, 0, i, 1);
+               ir_type           *param_type = get_method_param_type(method_type, i);
+               ir_entity         *entity;
+
+               if (!arg->on_stack) {
+                       continue;
+               }
+               entity = map[i];
+               if (entity == NULL) {
+                       /* create a new entity */
+                       entity = new_parameter_entity(res, i, param_type);
                }
+               ofs += arg->space_before;
+               ofs = round_up2(ofs, arg->alignment);
+               set_entity_offset(entity, ofs);
+               ofs += arg->space_after;
+               ofs += get_type_size_bytes(param_type);
+               arg->stack_ent = entity;
        }
        set_type_size_bytes(res, ofs);
        set_type_state(res, layout_fixed);
@@ -1330,57 +1352,15 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
        return ret;
 }
 
-typedef struct ent_pos_pair ent_pos_pair;
-struct ent_pos_pair {
-       ir_entity    *ent;   /**< a value param entity */
-       int          pos;    /**< its parameter number */
-       ent_pos_pair *next;  /**< for linking */
-};
-
 typedef struct lower_frame_sels_env_t {
-       ent_pos_pair *value_param_list;          /**< the list of all value param entities */
+       ir_entity   **value_param_list;          /**< the list of all value param entities */
        ir_node      *frame;                     /**< the current frame */
        const arch_register_class_t *sp_class;   /**< register class of the stack pointer */
        const arch_register_class_t *link_class; /**< register class of the link pointer */
-       ir_type      *value_tp;                  /**< the value type if any */
        ir_type      *frame_tp;                  /**< the frame type */
        int          static_link_pos;            /**< argument number of the hidden static link */
 } lower_frame_sels_env_t;
 
-/**
- * Return an entity from the backend for an value param entity.
- *
- * @param ent  an value param type entity
- * @param ctx  context
- */
-static ir_entity *get_argument_entity(ir_entity *ent, lower_frame_sels_env_t *ctx)
-{
-       ir_entity *argument_ent = (ir_entity*)get_entity_link(ent);
-
-       if (argument_ent == NULL) {
-               /* we have NO argument entity yet: This is bad, as we will
-               * need one for backing store.
-               * Create one here.
-               */
-               ir_type *frame_tp = ctx->frame_tp;
-               unsigned offset   = get_type_size_bytes(frame_tp);
-               ir_type  *tp      = get_entity_type(ent);
-               unsigned align    = get_type_alignment_bytes(tp);
-
-               offset += align - 1;
-               offset &= ~(align - 1);
-
-               argument_ent = copy_entity_own(ent, frame_tp);
-
-               /* must be automatic to set a fixed layout */
-               set_entity_offset(argument_ent, offset);
-               offset += get_type_size_bytes(tp);
-
-               set_type_size_bytes(frame_tp, offset);
-               set_entity_link(ent, argument_ent);
-       }
-       return argument_ent;
-}
 /**
  * Walker: Replaces Sels of frame type and
  * value param type entities by FrameAddress.
@@ -1397,31 +1377,16 @@ static void lower_frame_sels_walker(ir_node *irn, void *data)
                        ir_entity    *ent = get_Sel_entity(irn);
                        ir_node      *bl  = get_nodes_block(irn);
                        ir_node      *nw;
-                       int          pos = 0;
-                       int          is_value_param = 0;
-
-                       if (get_entity_owner(ent) == ctx->value_tp) {
-                               is_value_param = 1;
 
+                       if (is_parameter_entity(ent) && get_entity_link(ent) == NULL) {
                                /* replace by its copy from the argument type */
-                               pos = get_struct_member_index(ctx->value_tp, ent);
-                               ent = get_argument_entity(ent, ctx);
+                               ARR_APP1(ir_entity*, ctx->value_param_list, ent);
+                               /* just a mark */
+                               set_entity_link(ent, ctx->value_param_list);
                        }
 
                        nw = be_new_FrameAddr(ctx->sp_class, bl, ctx->frame, ent);
                        exchange(irn, nw);
-
-                       /* check, if it's a param Sel and if have not seen this entity before */
-                       if (is_value_param && get_entity_link(ent) == NULL) {
-                               ent_pos_pair pair;
-
-                               pair.ent  = ent;
-                               pair.pos  = pos;
-                               pair.next = NULL;
-                               ARR_APP1(ent_pos_pair, ctx->value_param_list, pair);
-                               /* just a mark */
-                               set_entity_link(ent, ctx->value_param_list);
-                       }
                }
        }
 }
@@ -1438,104 +1403,84 @@ static void lower_frame_sels_walker(ir_node *irn, void *data)
  * a backing store into the first block.
  */
 static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_graph *irg,
-                                            ent_pos_pair *value_param_list)
+                                            ir_entity **value_param_list)
 {
        be_abi_call_t    *call     = env->call;
        const arch_env_t *arch_env = be_get_irg_arch_env(irg);
-       ent_pos_pair  *entry, *new_list;
-       ir_type       *frame_tp;
-       int           i, n = ARR_LEN(value_param_list);
+       size_t         n = ARR_LEN(value_param_list);
+       size_t         i;
+       bool           need_fixes = false;
+       ir_node       *first_store = NULL;
+       ir_node       *start_bl;
+       ir_node       *frame;
+       ir_node       *imem;
+       ir_node       *mem;
+       ir_node       *args;
 
-       new_list = NULL;
        for (i = 0; i < n; ++i) {
-               int               pos  = value_param_list[i].pos;
-               be_abi_call_arg_t *arg = get_call_arg(call, 0, pos, 1);
+               ir_entity         *entity = value_param_list[i];
+               size_t             pos    = get_entity_parameter_number(entity);
+               be_abi_call_arg_t *arg    = get_call_arg(call, 0, pos, 1);
 
                if (arg->in_reg) {
+                       need_fixes = true;
                        DBG((dbg, LEVEL_2, "\targ #%d need backing store\n", pos));
-                       value_param_list[i].next = new_list;
-                       new_list = &value_param_list[i];
                }
        }
-       if (new_list != NULL) {
-               /* ok, change the graph */
-               ir_node *start_bl = get_irg_start_block(irg);
-               ir_node *first_bl = get_first_block_succ(start_bl);
-               ir_node *frame, *imem, *nmem, *store, *mem, *args;
-               optimization_state_t state;
-               unsigned offset;
-
-               assert(first_bl && first_bl != start_bl);
-               /* we had already removed critical edges, so the following
-                  assertion should be always true. */
-               assert(get_Block_n_cfgpreds(first_bl) == 1);
-
-               /* now create backing stores */
-               frame = get_irg_frame(irg);
-               imem = get_irg_initial_mem(irg);
-
-               save_optimization_state(&state);
-               set_optimize(0);
-               nmem = new_r_Proj(get_irg_start(irg), mode_M, pn_Start_M);
-               restore_optimization_state(&state);
-
-               /* reroute all edges to the new memory source */
-               edges_reroute(imem, nmem);
-
-               store   = NULL;
-               mem     = imem;
-               args    = get_irg_args(irg);
-               for (entry = new_list; entry != NULL; entry = entry->next) {
-                       int     i     = entry->pos;
-                       ir_type *tp   = get_entity_type(entry->ent);
-                       ir_mode *mode = get_type_mode(tp);
-                       ir_node *addr;
+       if (!need_fixes)
+               return;
+
+       /* ok, change the graph */
+       start_bl = get_irg_start_block(irg);
+
+       /* now create backing stores */
+       frame = get_irg_frame(irg);
+       imem  = get_irg_initial_mem(irg);
+       mem   = imem;
+       args  = get_irg_args(irg);
+       for (i = 0; i < n; ++i) {
+               ir_entity         *entity = value_param_list[i];
+               size_t             pos    = get_entity_parameter_number(entity);
+               be_abi_call_arg_t *arg    = get_call_arg(call, 0, pos, 1);
+               ir_node           *addr;
 
-                       /* address for the backing store */
-                       addr = be_new_FrameAddr(arch_env->sp->reg_class, first_bl, frame, entry->ent);
+               if (!arg->in_reg)
+                       continue;
 
-                       if (store)
-                               mem = new_r_Proj(store, mode_M, pn_Store_M);
+               /* address for the backing store */
+               addr = be_new_FrameAddr(arch_env->sp->reg_class, start_bl, frame, entity);
+
+               if (entity->attr.parameter.doubleword_low_mode != NULL) {
+                       ir_mode *mode      = entity->attr.parameter.doubleword_low_mode;
+                       ir_node *val0      = new_r_Proj(args, mode, pos);
+                       ir_node *val1      = new_r_Proj(args, mode, pos+1);
+                       ir_node *store0    = new_r_Store(start_bl, mem, addr, val0, cons_none);
+                       ir_node *mem0      = new_r_Proj(store0, mode_M, pn_Store_M);
+                       size_t   offset    = get_mode_size_bits(mode)/8;
+                       ir_mode *addr_mode = get_irn_mode(addr);
+                       ir_node *cnst      = new_r_Const_long(irg, addr_mode, offset);
+                       ir_node *next_addr = new_r_Add(start_bl, addr, cnst, addr_mode);
+                       ir_node *store1    = new_r_Store(start_bl, mem0, next_addr, val1, cons_none);
+                       mem = new_r_Proj(store1, mode_M, pn_Store_M);
+                       if (first_store == NULL)
+                               first_store = store0;
+               } else {
+                       ir_type *tp   = get_entity_type(entity);
+                       ir_mode *mode = get_type_mode(tp);
 
                        /* the backing store itself */
-                       store = new_r_Store(first_bl, mem, addr,
-                                           new_r_Proj(args, mode, i), cons_none);
-               }
-               /* the new memory Proj gets the last Proj from store */
-               set_Proj_pred(nmem, store);
-               set_Proj_proj(nmem, pn_Store_M);
-               set_nodes_block(nmem, get_nodes_block(store));
-
-               /* move all entities to the frame type */
-               frame_tp = get_irg_frame_type(irg);
-               offset   = get_type_size_bytes(frame_tp);
-
-               /* we will add new entities: set the layout to undefined */
-               assert(get_type_state(frame_tp) == layout_fixed);
-               set_type_state(frame_tp, layout_undefined);
-               for (entry = new_list; entry != NULL; entry = entry->next) {
-                       ir_entity *ent = entry->ent;
-
-                       /* If the entity is still on the argument type, move it to the
-                        * frame type.
-                        * This happens if the value_param type was build due to compound
-                        * params. */
-                       if (get_entity_owner(ent) != frame_tp) {
-                               ir_type  *tp   = get_entity_type(ent);
-                               unsigned align = get_type_alignment_bytes(tp);
-
-                               offset += align - 1;
-                               offset &= ~(align - 1);
-                               set_entity_owner(ent, frame_tp);
-                               /* must be automatic to set a fixed layout */
-                               set_entity_offset(ent, offset);
-                               offset += get_type_size_bytes(tp);
-                       }
+                       ir_node *val   = new_r_Proj(args, mode, pos);
+                       ir_node *store = new_r_Store(start_bl, mem, addr, val, cons_none);
+                       mem = new_r_Proj(store, mode_M, pn_Store_M);
+
+                       if (first_store == NULL)
+                               first_store = store;
                }
-               set_type_size_bytes(frame_tp, offset);
-               /* fix the layout again */
-               set_type_state(frame_tp, layout_fixed);
        }
+
+       assert(mem != imem);
+       edges_reroute(imem, mem);
+       set_Store_mem(first_store, imem);
 }
 
 /**
@@ -1577,7 +1522,6 @@ static void update_outer_frame_sels(ir_node *irn, void *env)
        lower_frame_sels_env_t *ctx = (lower_frame_sels_env_t*)env;
        ir_node                *ptr;
        ir_entity              *ent;
-       int                    pos = 0;
 
        if (! is_Sel(irn))
                return;
@@ -1586,22 +1530,12 @@ static void update_outer_frame_sels(ir_node *irn, void *env)
                return;
        if (get_Proj_proj(ptr) != ctx->static_link_pos)
                return;
-       ent   = get_Sel_entity(irn);
-
-       if (get_entity_owner(ent) == ctx->value_tp) {
-               /* replace by its copy from the argument type */
-               pos = get_struct_member_index(ctx->value_tp, ent);
-               ent = get_argument_entity(ent, ctx);
-               set_Sel_entity(irn, ent);
+       ent = get_Sel_entity(irn);
 
+       if (is_parameter_entity(ent)) {
                /* check, if we have not seen this entity before */
                if (get_entity_link(ent) == NULL) {
-                       ent_pos_pair pair;
-
-                       pair.ent  = ent;
-                       pair.pos  = pos;
-                       pair.next = NULL;
-                       ARR_APP1(ent_pos_pair, ctx->value_param_list, pair);
+                       ARR_APP1(ir_entity*, ctx->value_param_list, ent);
                        /* just a mark */
                        set_entity_link(ent, ctx->value_param_list);
                }
@@ -1668,7 +1602,7 @@ static void modify_irg(ir_graph *irg)
        ir_node **args;
        ir_node *arg_tuple;
        const ir_edge_t *edge;
-       ir_type *arg_type, *bet_type, *tp;
+       ir_type *arg_type, *bet_type;
        lower_frame_sels_env_t ctx;
        ir_entity **param_map;
 
@@ -1678,23 +1612,10 @@ static void modify_irg(ir_graph *irg)
 
        irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
 
-       /* set the links of all frame entities to NULL, we use it
-          to detect if an entity is already linked in the value_param_list */
-       tp = get_method_value_param_type(method_type);
-       ctx.value_tp = tp;
-       if (tp != NULL) {
-               /* clear the links of the clone type, let the
-                  original entities point to its clones */
-               for (i = get_struct_n_members(tp) - 1; i >= 0; --i) {
-                       ir_entity *mem  = get_struct_member(tp, i);
-                       set_entity_link(mem, NULL);
-               }
-       }
-
-       arg_type = compute_arg_type(irg, call, method_type, tp, &param_map);
+       arg_type = compute_arg_type(irg, call, method_type, &param_map);
 
        /* Convert the Sel nodes in the irg to frame addr nodes: */
-       ctx.value_param_list = NEW_ARR_F(ent_pos_pair, 0);
+       ctx.value_param_list = NEW_ARR_F(ir_entity*, 0);
        ctx.frame            = get_irg_frame(irg);
        ctx.sp_class         = arch_env->sp->reg_class;
        ctx.link_class       = arch_env->link_class;
@@ -1705,14 +1626,8 @@ static void modify_irg(ir_graph *irg)
                default_layout_compound_type(ctx.frame_tp);
        }
 
-       /* we will possible add new entities to the frame: set the layout to undefined */
-       assert(get_type_state(ctx.frame_tp) == layout_fixed);
-       set_type_state(ctx.frame_tp, layout_undefined);
-
        irg_walk_graph(irg, lower_frame_sels_walker, NULL, &ctx);
 
-       /* fix the frame type layout again */
-       set_type_state(ctx.frame_tp, layout_fixed);
        /* align stackframe to 4 byte */
        frame_size = get_type_size_bytes(ctx.frame_tp);
        if (frame_size % 4 != 0) {
index 7c071d0..773cba8 100644 (file)
@@ -1784,10 +1784,6 @@ static ir_node *gen_Sel(ir_node *node)
        /* must be the frame pointer all other sels must have been lowered
         * already */
        assert(is_Proj(ptr) && is_Start(get_Proj_pred(ptr)));
-       /* we should not have value types from parameters anymore - they should be
-          lowered */
-       assert(get_entity_owner(entity) !=
-                       get_method_value_param_type(get_entity_type(get_irg_entity(get_irn_irg(node)))));
 
        return new_bd_sparc_FrameAddr(dbgi, new_block, new_ptr, entity, 0);
 }
index 63a4092..423eed1 100644 (file)
@@ -606,14 +606,6 @@ void (set_irg_frame_type)(ir_graph *irg, ir_type *ftp)
        _set_irg_frame_type(irg, ftp);
 }
 
-/* Returns the value parameter type of an IR graph. */
-ir_type *get_irg_value_param_type(ir_graph *irg)
-{
-       ir_entity *ent = get_irg_entity(irg);
-       ir_type   *mtp = get_entity_type(ent);
-       return get_method_value_param_type(mtp);
-}
-
 int get_irg_n_locs(ir_graph *irg)
 {
        return irg->n_loc - 1;
index ea72867..2e656bb 100644 (file)
@@ -895,12 +895,10 @@ void ir_export_file(FILE *file, const char *outputname)
 
        for (i = 0; i < n_irgs; i++) {
                ir_graph *irg       = get_irp_irg(i);
-               ir_type  *valuetype = get_irg_value_param_type(irg);
 
-               fprintf(env.file, "\nirg %ld %ld %ld {\n",
+               fprintf(env.file, "\nirg %ld %ld {\n",
                        get_entity_nr(get_irg_entity(irg)),
-                       get_type_nr(get_irg_frame_type(irg)),
-                       valuetype == NULL ? -1 : get_type_nr(valuetype));
+                       get_type_nr(get_irg_frame_type(irg)));
 
                env.ignoreblocks = 0;
                irg_block_walk_graph(irg, NULL, export_node, &env);
@@ -1894,14 +1892,8 @@ void ir_import_file(FILE *input, const char *inputname)
                case kw_irg:
                {
                        ir_entity *irgent = get_entity(env, read_long(env));
-                       long valuetypeid;
                        ir_graph *irg = new_ir_graph(irgent, 0);
                        set_irg_frame_type(irg, get_type(env, read_long(env)));
-                       valuetypeid = read_long(env);
-                       if (valuetypeid != -1)
-                               set_method_value_param_type(get_entity_type(irgent),
-                                               get_type(env, valuetypeid));
-
                        if (!parse_graph(env, irg)) goto end;
                        break;
                }
index 31da624..32a89f2 100644 (file)
@@ -60,6 +60,27 @@ static ir_type *get_pointer_type(ir_type *dest_type)
        return res;
 }
 
+static void fix_parameter_entities(ir_graph *irg, size_t n_compound_ret)
+{
+       ir_type *frame_type = get_irg_frame_type(irg);
+       size_t   n_compound = get_compound_n_members(frame_type);
+       size_t   i;
+
+       if (n_compound_ret == 0)
+               return;
+
+       for (i = 0; i < n_compound; ++i) {
+               ir_entity *member = get_compound_member(frame_type, i);
+               size_t     num;
+               if (!is_parameter_entity(member))
+                       continue;
+
+               /* increase parameter number since we added a new parameter in front */
+               num = get_entity_parameter_number(member);
+               set_entity_parameter_number(member, num + n_compound_ret);
+       }
+}
+
 /**
  * Creates a new lowered type for a method type with compound
  * arguments. The new type is associated to the old one and returned.
@@ -164,7 +185,6 @@ typedef struct wlk_env_t {
        pmap                 *dummy_map;       /**< A map for finding the dummy arguments. */
        compound_call_lowering_flags flags;
        ir_type              *lowered_mtp;     /**< The lowered method type of the current irg if any. */
-       ir_type              *value_params;    /**< The value params type if any. */
        unsigned             only_local_mem:1; /**< Set if only local memory access was found. */
        unsigned             changed:1;        /**< Set if the current graph was changed. */
 } wlk_env;
@@ -272,20 +292,6 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx)
        ir_node *ptr;
 
        switch (get_irn_opcode(n)) {
-       case iro_Sel:
-               if (env->lowered_mtp != NULL && env->value_params != NULL) {
-                       ir_entity *ent = get_Sel_entity(n);
-
-                       if (get_entity_owner(ent) == env->value_params) {
-                               size_t pos = get_struct_member_index(env->value_params, ent) + env->arg_shift;
-                               ir_entity *new_ent;
-
-                               new_ent = get_method_value_param_ent(env->lowered_mtp, pos);
-                               set_entity_ident(new_ent, get_entity_ident(ent));
-                               set_Sel_entity(n, new_ent);
-                       }
-               }
-               break;
        case iro_Load:
        case iro_Store:
                if (env->only_local_mem) {
@@ -568,6 +574,8 @@ static void transform_irg(compound_call_lowering_flags flags, ir_graph *irg)
                        ++n_ret_com;
        }
 
+       fix_parameter_entities(irg, n_ret_com);
+
        if (n_ret_com) {
                /* much easier if we have only one return */
                normalize_one_return(irg);
@@ -588,7 +596,6 @@ static void transform_irg(compound_call_lowering_flags flags, ir_graph *irg)
        env.dummy_map      = pmap_create_ex(8);
        env.flags          = flags;
        env.lowered_mtp    = lowered_mtp;
-       env.value_params   = get_method_value_param_type(mtp);
        env.only_local_mem = 1;
        env.changed        = 0;
 
index cc75855..77ae303 100644 (file)
@@ -102,7 +102,6 @@ typedef struct lower_dw_env_t {
        lower64_entry_t **entries;     /**< entries per node */
        ir_graph      *irg;
        struct obstack obst;           /**< an obstack holding the temporary data */
-       ir_type   *l_mtp;              /**< lowered method type of the current method */
        ir_tarval *tv_mode_bytes;      /**< a tarval containing the number of bytes in the lowered modes */
        ir_tarval *tv_mode_bits;       /**< a tarval containing the number of bits in the lowered modes */
        pdeq      *waitq;              /**< a wait queue of all nodes that must be handled later */
@@ -116,13 +115,11 @@ typedef struct lower_dw_env_t {
        const lwrdw_param_t *params;   /**< transformation parameter */
        unsigned flags;                /**< some flags */
        unsigned n_entries;            /**< number of entries */
-       ir_type  *value_param_tp;      /**< the old value param type */
 } lower_dw_env_t;
 
 static lower_dw_env_t *env;
 
 static void lower_node(ir_node *node);
-static bool mtp_must_be_lowered(ir_type *mtp);
 
 /**
  * Create a method type for a Conv emulation from imode to omode.
@@ -1602,25 +1599,56 @@ static void lower_Conv(ir_node *node, ir_mode *mode)
        }
 }
 
-/**
- * Remember the new argument index of this value type entity in the lowered
- * method type.
- *
- * @param ent  the entity
- * @param pos  the argument index of this entity
- */
-static inline void set_entity_arg_idx(ir_entity *ent, size_t pos)
+static void fix_parameter_entities(ir_graph *irg)
 {
-       set_entity_link(ent, INT_TO_PTR(pos));
-}
+       ir_entity *entity   = get_irg_entity(irg);
+       ir_type   *mtp      = get_entity_type(entity);
+       ir_type   *orig_mtp = get_type_link(mtp);
+
+       size_t      orig_n_params      = get_method_n_params(orig_mtp);
+       ir_entity **parameter_entities = ALLOCANZ(ir_entity*, orig_n_params);
+
+       ir_type *frame_type = get_irg_frame_type(irg);
+       size_t   n          = get_compound_n_members(frame_type);
+       size_t   i;
+       size_t   n_param;
+
+       /* collect parameter entities */
+       for (i = 0; i < n; ++i) {
+               ir_entity *entity = get_compound_member(frame_type, i);
+               size_t     p;
+               if (!is_parameter_entity(entity))
+                       continue;
+               p = get_entity_parameter_number(entity);
+               assert(p < orig_n_params);
+               assert(parameter_entities[p] == NULL);
+               parameter_entities[p] = entity;
+       }
 
-/**
- * Retrieve the argument index of a value type entity.
- *
- * @param ent  the entity
- */
-static size_t get_entity_arg_idx(const ir_entity *ent) {
-       return PTR_TO_INT(get_entity_link(ent));
+       /* adjust indices */
+       n_param = 0;
+       for (i = 0; i < orig_n_params; ++i, ++n_param) {
+               ir_entity *entity = parameter_entities[i];
+               ir_type   *tp     = get_method_param_type(orig_mtp, i);
+               if (entity != NULL)
+                       set_entity_parameter_number(entity, n_param);
+
+               if (is_Primitive_type(tp)) {
+                       ir_mode *mode = get_type_mode(tp);
+                       if (mode == env->high_signed || mode == env->high_unsigned) {
+                               ++n_param;
+                               /* note that we do not change the type of the parameter
+                                * entities, as calling convention fixup later still needs to
+                                * know which is/was a lowered doubleword.
+                                * So we just mark/remember it for later */
+                               if (entity != NULL) {
+                                       assert(entity->attr.parameter.doubleword_low_mode == NULL);
+                                       entity->attr.parameter.doubleword_low_mode
+                                               = env->low_unsigned;
+                               }
+                       }
+               }
+       }
 }
 
 /**
@@ -1633,121 +1661,113 @@ static size_t get_entity_arg_idx(const ir_entity *ent) {
  */
 static ir_type *lower_mtp(ir_type *mtp)
 {
-       pmap_entry *entry;
-       ir_type    *res, *value_type;
+       ir_type *res;
+       size_t   i;
+       size_t   orig_n_params;
+       size_t   orig_n_res;
+       size_t   n_param;
+       size_t   n_res;
+       bool     must_be_lowered;
+
+       res = (ir_type*)pmap_get(lowered_type, mtp);
+       if (res != NULL)
+               return res;
+
+       orig_n_params   = get_method_n_params(mtp);
+       orig_n_res      = get_method_n_ress(mtp);
+       n_param         = orig_n_params;
+       n_res           = orig_n_res;
+       must_be_lowered = false;
+
+       /* count new number of params */
+       for (i = orig_n_params; i > 0;) {
+               ir_type *tp = get_method_param_type(mtp, --i);
 
-       entry = pmap_find(lowered_type, mtp);
-       if (! entry) {
-               size_t i, orig_n_params, orig_n_res, n_param, n_res;
-
-               /* count new number of params */
-               n_param = orig_n_params = get_method_n_params(mtp);
-               for (i = orig_n_params; i > 0;) {
-                       ir_type *tp = get_method_param_type(mtp, --i);
-
-                       if (is_Primitive_type(tp)) {
-                               ir_mode *mode = get_type_mode(tp);
+               if (is_Primitive_type(tp)) {
+                       ir_mode *mode = get_type_mode(tp);
 
-                               if (mode == env->high_signed || mode == env->high_unsigned)
-                                       ++n_param;
+                       if (mode == env->high_signed || mode == env->high_unsigned) {
+                               ++n_param;
+                               must_be_lowered = true;
                        }
                }
+       }
 
-               /* count new number of results */
-               n_res = orig_n_res = get_method_n_ress(mtp);
-               for (i = orig_n_res; i > 0;) {
-                       ir_type *tp = get_method_res_type(mtp, --i);
+       /* count new number of results */
+       for (i = orig_n_res; i > 0;) {
+               ir_type *tp = get_method_res_type(mtp, --i);
 
-                       if (is_Primitive_type(tp)) {
-                               ir_mode *mode = get_type_mode(tp);
+               if (is_Primitive_type(tp)) {
+                       ir_mode *mode = get_type_mode(tp);
 
-                               if (mode == env->high_signed || mode == env->high_unsigned)
-                                       ++n_res;
+                       if (mode == env->high_signed || mode == env->high_unsigned) {
+                               ++n_res;
+                               must_be_lowered = true;
                        }
                }
+       }
+       if (!must_be_lowered) {
+               set_type_link(mtp, NULL);
+               return mtp;
+       }
 
-               res = new_type_method(n_param, n_res);
+       res = new_type_method(n_param, n_res);
 
-               /* set param types and result types */
-               for (i = n_param = 0; i < orig_n_params; ++i) {
-                       ir_type *tp = get_method_param_type(mtp, i);
-
-                       if (is_Primitive_type(tp)) {
-                               ir_mode *mode = get_type_mode(tp);
-
-                               if (mode == env->high_signed) {
-                                       if (env->params->little_endian) {
-                                               set_method_param_type(res, n_param++, tp_u);
-                                               set_method_param_type(res, n_param++, tp_s);
-                                       } else {
-                                               set_method_param_type(res, n_param++, tp_s);
-                                               set_method_param_type(res, n_param++, tp_u);
-                                       }
-                               } else if (mode == env->high_unsigned) {
-                                       set_method_param_type(res, n_param++, tp_u);
+       /* set param types and result types */
+       for (i = n_param = 0; i < orig_n_params; ++i) {
+               ir_type *tp = get_method_param_type(mtp, i);
+
+               if (is_Primitive_type(tp)) {
+                       ir_mode *mode = get_type_mode(tp);
+
+                       if (mode == env->high_signed) {
+                               if (env->params->little_endian) {
                                        set_method_param_type(res, n_param++, tp_u);
+                                       set_method_param_type(res, n_param++, tp_s);
                                } else {
-                                       set_method_param_type(res, n_param++, tp);
+                                       set_method_param_type(res, n_param++, tp_s);
+                                       set_method_param_type(res, n_param++, tp_u);
                                }
+                       } else if (mode == env->high_unsigned) {
+                               set_method_param_type(res, n_param++, tp_u);
+                               set_method_param_type(res, n_param++, tp_u);
                        } else {
-                               set_method_param_type(res, n_param++, tp);
+                               set_method_param_type(res, n_param, tp);
+                               ++n_param;
                        }
+               } else {
+                       set_method_param_type(res, n_param, tp);
+                       ++n_param;
                }
-               for (i = n_res = 0; i < orig_n_res; ++i) {
-                       ir_type *tp = get_method_res_type(mtp, i);
-
-                       if (is_Primitive_type(tp)) {
-                               ir_mode *mode = get_type_mode(tp);
-
-                               if (mode == env->high_signed) {
-                                       if (env->params->little_endian) {
-                                               set_method_res_type(res, n_res++, tp_u);
-                                               set_method_res_type(res, n_res++, tp_s);
-                                       } else {
-                                               set_method_res_type(res, n_res++, tp_s);
-                                               set_method_res_type(res, n_res++, tp_u);
-                                       }
-                               } else if (mode == env->high_unsigned) {
-                                       set_method_res_type(res, n_res++, tp_u);
+       }
+       for (i = n_res = 0; i < orig_n_res; ++i) {
+               ir_type *tp = get_method_res_type(mtp, i);
+
+               if (is_Primitive_type(tp)) {
+                       ir_mode *mode = get_type_mode(tp);
+
+                       if (mode == env->high_signed) {
+                               if (env->params->little_endian) {
                                        set_method_res_type(res, n_res++, tp_u);
+                                       set_method_res_type(res, n_res++, tp_s);
                                } else {
-                                       set_method_res_type(res, n_res++, tp);
+                                       set_method_res_type(res, n_res++, tp_s);
+                                       set_method_res_type(res, n_res++, tp_u);
                                }
+                       } else if (mode == env->high_unsigned) {
+                               set_method_res_type(res, n_res++, tp_u);
+                               set_method_res_type(res, n_res++, tp_u);
                        } else {
                                set_method_res_type(res, n_res++, tp);
                        }
+               } else {
+                       set_method_res_type(res, n_res++, tp);
                }
-               set_lowered_type(mtp, res);
-               pmap_insert(lowered_type, mtp, res);
-
-               value_type = get_method_value_param_type(mtp);
-               if (value_type != NULL) {
-                       /* this creates a new value parameter type */
-                       (void)get_method_value_param_ent(res, 0);
-
-                       /* set new param positions for all entities of the value type */
-                       for (i = n_param = 0; i < orig_n_params; ++i) {
-                               ir_type   *tp  = get_method_param_type(mtp, i);
-                               ir_entity *ent = get_method_value_param_ent(mtp, i);
-
-                               set_entity_arg_idx(ent, n_param);
-                               if (is_Primitive_type(tp)) {
-                                       ir_mode *mode = get_type_mode(tp);
-
-                                       if (mode == env->high_signed
-                                           || mode == env->high_unsigned) {
-                                               n_param += 2;
-                                               continue;
-                                       }
-                               }
-                               ++n_param;
-                       }
-
-                       set_lowered_type(value_type, get_method_value_param_type(res));
-               }
-       } else {
-               res = (ir_type*)entry->value;
        }
+       set_lowered_type(mtp, res);
+       set_type_link(res, mtp);
+
+       pmap_insert(lowered_type, mtp, res);
        return res;
 }
 
@@ -1778,32 +1798,31 @@ static void lower_Return(ir_node *node, ir_mode *mode)
        ent = get_irg_entity(irg);
        mtp = get_entity_type(ent);
 
-       mtp = lower_mtp(mtp);
-       set_entity_type(ent, mtp);
-
        /* create a new in array */
        NEW_ARR_A(ir_node *, in, get_method_n_ress(mtp) + 1);
-       in[0] = get_Return_mem(node);
+       j = 0;
+       in[j++] = get_Return_mem(node);
 
-       for (j = i = 0, n = get_Return_n_ress(node); i < n; ++i) {
+       for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
                ir_node *pred      = get_Return_res(node, i);
                ir_mode *pred_mode = get_irn_mode(pred);
 
                if (pred_mode == env->high_signed || pred_mode == env->high_unsigned) {
                        const lower64_entry_t *entry = get_node_entry(pred);
                        if (env->params->little_endian) {
-                               in[++j] = entry->low_word;
-                               in[++j] = entry->high_word;
+                               in[j++] = entry->low_word;
+                               in[j++] = entry->high_word;
                        } else {
-                               in[++j] = entry->high_word;
-                               in[++j] = entry->low_word;
+                               in[j++] = entry->high_word;
+                               in[j++] = entry->low_word;
                        }
                } else {
-                       in[++j] = pred;
+                       in[j++] = pred;
                }
        }
+       assert(j == get_method_n_ress(mtp)+1);
 
-       set_irn_in(node, j+1, in);
+       set_irn_in(node, j, in);
 }
 
 /**
@@ -1811,9 +1830,10 @@ static void lower_Return(ir_node *node, ir_mode *mode)
  */
 static void lower_Start(ir_node *node, ir_mode *high_mode)
 {
-       ir_graph  *irg = get_irn_irg(node);
-       ir_entity *ent = get_irg_entity(irg);
-       ir_type   *tp  = get_entity_type(ent);
+       ir_graph  *irg      = get_irn_irg(node);
+       ir_entity *ent      = get_irg_entity(irg);
+       ir_type   *mtp      = get_entity_type(ent);
+       ir_type   *orig_mtp = get_type_link(mtp);
        ir_node   *args;
        long      *new_projs;
        size_t    i, j, n_params;
@@ -1821,16 +1841,18 @@ static void lower_Start(ir_node *node, ir_mode *high_mode)
        const ir_edge_t *next;
        (void) high_mode;
 
-       if (!mtp_must_be_lowered(tp))
+       /* if type link is NULL then the type was not lowered, hence no changes
+        * at Start necessary */
+       if (orig_mtp == NULL)
                return;
 
-       n_params = get_method_n_params(tp);
+       n_params = get_method_n_params(orig_mtp);
 
        NEW_ARR_A(long, new_projs, n_params);
 
        /* Calculate mapping of proj numbers in new_projs */
        for (i = j = 0; i < n_params; ++i, ++j) {
-               ir_type *ptp = get_method_param_type(tp, i);
+               ir_type *ptp = get_method_param_type(orig_mtp, i);
 
                new_projs[i] = j;
                if (is_Primitive_type(ptp)) {
@@ -1841,9 +1863,6 @@ static void lower_Start(ir_node *node, ir_mode *high_mode)
        }
 
        /* lower method type */
-       tp = lower_mtp(tp);
-       set_entity_type(ent, tp);
-
        args = NULL;
        foreach_out_edge(node, edge) {
                ir_node *proj = get_edge_src_irn(edge);
@@ -2259,26 +2278,6 @@ static void lower_ASM(ir_node *asmn, ir_mode *mode)
        }
 }
 
-/**
- * Translate a Sel node.
- */
-static void lower_Sel(ir_node *sel, ir_mode *mode)
-{
-       (void) mode;
-
-       /* we must only lower value parameter Sels if we change the
-          value parameter type. */
-       if (env->value_param_tp != NULL) {
-               ir_entity *ent = get_Sel_entity(sel);
-           if (get_entity_owner(ent) == env->value_param_tp) {
-                       size_t pos = get_entity_arg_idx(ent);
-
-                       ent = get_method_value_param_ent(env->l_mtp, pos);
-                       set_Sel_entity(sel, ent);
-               }
-       }
-}
-
 /**
  * check for opcodes that must always be lowered.
  */
@@ -2331,29 +2330,6 @@ void ir_register_dw_lower_function(ir_op *op, lower_dw_func func)
        op->ops.generic = (op_func)func;
 }
 
-/**
- * Returns non-zero if a method type must be lowered.
- *
- * @param mtp  the method type
- */
-static bool mtp_must_be_lowered(ir_type *mtp)
-{
-       size_t i, n_params = get_method_n_params(mtp);
-
-       /* first check if we have parameters that must be fixed */
-       for (i = 0; i < n_params; ++i) {
-               ir_type *tp = get_method_param_type(mtp, i);
-
-               if (is_Primitive_type(tp)) {
-                       ir_mode *mode = get_type_mode(tp);
-
-                       if (mode == env->high_signed || mode == env->high_unsigned)
-                               return true;
-               }
-       }
-       return false;
-}
-
 /* Determine which modes need to be lowered */
 static void setup_modes(void)
 {
@@ -2512,6 +2488,7 @@ static void lower_irg(ir_graph *irg)
 {
        ir_entity *ent;
        ir_type   *mtp;
+       ir_type   *lowered_mtp;
        unsigned   n_idx;
 
        obstack_init(&env->obst);
@@ -2527,19 +2504,17 @@ static void lower_irg(ir_graph *irg)
        memset(env->entries, 0, sizeof(env->entries[0]) * n_idx);
 
        env->irg            = irg;
-       env->l_mtp          = NULL;
        env->flags          = 0;
-       env->value_param_tp = NULL;
 
        ent = get_irg_entity(irg);
        mtp = get_entity_type(ent);
+       lowered_mtp = lower_mtp(mtp);
 
-       if (mtp_must_be_lowered(mtp)) {
-               ir_type *ltp = lower_mtp(mtp);
-               /* Do not update the entity type yet, this will be done by lower_Start! */
+       if (lowered_mtp != mtp) {
+               set_entity_type(ent, lowered_mtp);
                env->flags |= MUST_BE_LOWERED;
-               env->l_mtp = ltp;
-               env->value_param_tp = get_method_value_param_type(mtp);
+
+               fix_parameter_entities(irg);
        }
 
        /* first step: link all nodes and allocate data */
@@ -2614,7 +2589,6 @@ void ir_prepare_dw_lowering(const lwrdw_param_t *new_param)
        ir_register_dw_lower_function(op_Not,     lower_Not);
        ir_register_dw_lower_function(op_Or,      lower_Or);
        ir_register_dw_lower_function(op_Return,  lower_Return);
-       ir_register_dw_lower_function(op_Sel,     lower_Sel);
        ir_register_dw_lower_function(op_Shl,     lower_Shl);
        ir_register_dw_lower_function(op_Shr,     lower_Shr);
        ir_register_dw_lower_function(op_Shrs,    lower_Shrs);
@@ -2708,11 +2682,13 @@ void ir_lower_dw_ops(void)
        lenv.first_id      = new_id_from_chars(param->little_endian ? ".l" : ".h", 2);
        lenv.next_id       = new_id_from_chars(param->little_endian ? ".h" : ".l", 2);
 
+       irp_reserve_resources(irp, IRP_RESOURCE_TYPE_LINK);
        /* transform all graphs */
        for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
                ir_graph *irg = get_irp_irg(i);
                lower_irg(irg);
        }
+       irp_free_resources(irp, IRP_RESOURCE_TYPE_LINK);
        del_pdeq(lenv.waitq);
 
        env = NULL;
index 6c5e336..0fdcec1 100644 (file)
@@ -155,6 +155,9 @@ static void find_addr(ir_node *node, void *env)
                                /* access to value_type */
                                *allow_inline = false;
                        }
+                       if (is_parameter_entity(ent)) {
+                               *allow_inline = false;
+                       }
                }
        } else if (is_Alloc(node) && get_Alloc_where(node) == stack_alloc) {
                /* From GCC:
index d10e291..c5f2a75 100644 (file)
@@ -79,7 +79,10 @@ typedef struct path_t {
 } path_t;
 
 /** The size of a path in bytes. */
-#define PATH_SIZE(p)  (sizeof(*(p)) + sizeof((p)->path[0]) * ((p)->path_len - 1))
+static size_t path_size(path_t *p)
+{
+       return sizeof(*p) + sizeof(p->path[0]) * (p->path_len-1);
+}
 
 typedef struct scalars_t {
        ir_entity *ent;              /**< A entity for scalar replacement. */
@@ -496,7 +499,7 @@ static unsigned allocate_value_numbers(pset *sels, ir_entity *ent, unsigned vnum
                pset_insert_ptr(sels, sel);
 
                key  = find_path(sel, 0);
-               path = (path_t*)set_find(pathes, key, PATH_SIZE(key), path_hash(key));
+               path = (path_t*)set_find(pathes, key, path_size(key), path_hash(key));
 
                if (path) {
                        set_vnum(sel, path->vnum);
@@ -504,7 +507,7 @@ static unsigned allocate_value_numbers(pset *sels, ir_entity *ent, unsigned vnum
                } else {
                        key->vnum = vnum++;
 
-                       set_insert(pathes, key, PATH_SIZE(key), path_hash(key));
+                       set_insert(pathes, key, path_size(key), path_hash(key));
 
                        set_vnum(sel, key->vnum);
                        DB((dbg, SET_LEVEL_3, "  %+F represents value %u\n", sel, key->vnum));
@@ -713,8 +716,9 @@ int scalar_replacement_opt(ir_graph *irg)
                                ir_entity *ent = get_Sel_entity(succ);
 
                                /* we are only interested in entities on the frame, NOT
-                                  on the value type */
-                               if (get_entity_owner(ent) != frame_tp)
+                                  parameters */
+                               if (get_entity_owner(ent) != frame_tp
+                                   || is_parameter_entity(ent))
                                        continue;
 
                                if (get_entity_link(ent) == NULL || get_entity_link(ent) == ADDRESS_TAKEN)
index e7541d1..27612ca 100644 (file)
@@ -60,13 +60,11 @@ ir_entity *get_unknown_entity(void) { return unknown_entity; }
 /* ENTITY                                                          */
 /*-----------------------------------------------------------------*/
 
-ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *type,
-                        dbg_info *db)
+static ir_entity *intern_new_entity(ir_type *owner, ident *name, ir_type *type,
+                                    dbg_info *dbgi)
 {
        ir_entity *res;
 
-       assert(!id_contains_char(name, ' ') && "entity name should not contain spaces");
-
        res = XMALLOCZ(ir_entity);
 
        res->kind    = k_entity;
@@ -85,6 +83,24 @@ ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *type,
        res->alignment            = 0;
        res->link                 = NULL;
        res->repr_class           = NULL;
+#ifdef DEBUG_libfirm
+       res->nr = get_irp_new_node_nr();
+#endif
+
+       /* Remember entity in its owner. */
+       if (owner != NULL)
+               add_compound_member(owner, res);
+
+       res->visit = 0;
+       set_entity_dbg_info(res, dbgi);
+
+       return res;
+}
+
+ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *type,
+                        dbg_info *db)
+{
+       ir_entity *res = intern_new_entity(owner, name, type, db);
 
        if (is_Method_type(type)) {
                ir_graph *irg = get_const_code_irg();
@@ -105,25 +121,36 @@ ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *type,
                res->attr.code_attr.label = (ir_label_t) -1;
        }
 
-       /* Remember entity in its owner. */
-       if (owner != NULL)
-               add_compound_member(owner, res);
+       hook_new_entity(res);
+       return res;
+}
 
-#ifdef DEBUG_libfirm
-       res->nr = get_irp_new_node_nr();
-#endif
+ir_entity *new_entity(ir_type *owner, ident *name, ir_type *type)
+{
+       return new_d_entity(owner, name, type, NULL);
+}
 
-       res->visit = 0;
-       set_entity_dbg_info(res, db);
+static ident *make_parameter_entity_name(size_t pos)
+{
+       char buf[64];
+       snprintf(buf, sizeof(buf), "parameter.%lu", (unsigned long) pos);
+       return new_id_from_str(buf);
+}
 
+ir_entity *new_d_parameter_entity(ir_type *owner, size_t pos, ir_type *type,
+                                  dbg_info *dbgi)
+{
+       ident     *name            = make_parameter_entity_name(pos);
+       ir_entity *res             = intern_new_entity(owner, name, type, dbgi);
+       res->is_parameter          = true;
+       res->attr.parameter.number = pos;
        hook_new_entity(res);
-
        return res;
 }
 
-ir_entity *new_entity(ir_type *owner, ident *name, ir_type *type)
+ir_entity *new_parameter_entity(ir_type *owner, size_t pos, ir_type *type)
 {
-       return new_d_entity(owner, name, type, NULL);
+       return new_d_parameter_entity(owner, pos, type, NULL);
 }
 
 /**
@@ -864,6 +891,22 @@ void set_entity_irg(ir_entity *ent, ir_graph *irg)
        ent->attr.mtd_attr.irg = irg;
 }
 
+int (is_parameter_entity)(const ir_entity *entity)
+{
+       return _is_parameter_entity(entity);
+}
+
+size_t (get_entity_parameter_number)(const ir_entity *entity)
+{
+       return _get_entity_parameter_number(entity);
+}
+
+void set_entity_parameter_number(ir_entity *entity, size_t n)
+{
+       assert(is_parameter_entity(entity));
+       entity->attr.parameter.number = n;
+}
+
 unsigned get_entity_vtable_number(const ir_entity *ent)
 {
        assert(is_method_entity((ir_entity *)ent));
@@ -894,7 +937,7 @@ int is_compound_entity(const ir_entity *ent)
        ir_type     *t  = get_entity_type(ent);
        const tp_op *op = get_type_tpop(t);
        return (op == type_class || op == type_struct ||
-               op == type_array || op == type_union);
+               op == type_array || op == type_union);
 }
 
 int is_method_entity(const ir_entity *ent)
index cdd8aff..282b5ec 100644 (file)
@@ -27,6 +27,7 @@
 #define FIRM_TR_ENTITY_T_H
 
 #include <assert.h>
+#include <stdbool.h>
 
 #include "typerep.h"
 #include "type_t.h"
@@ -97,74 +98,79 @@ typedef struct code_ent_attr {
        ir_label_t  label;       /** label of the basic block */
 } code_ent_attr;
 
+typedef struct parameter_ent_attr {
+       /**< parameters might be compounds too */
+       compound_ent_attr  cmpd_attr;
+
+       size_t   number; /**< corresponding parameter number */
+       ir_mode *doubleword_low_mode;/**< entity is a lowered doubleword parameter,
+                                                               so additional stores because of calling
+                                                               convention are correctly performed.
+                                   Matze: This is a hack. In an ideal
+                                   wor^H^H^Hlibfirm we would first establish
+                                   calling conventions and then perform doubleword
+                                   lowering...) */
+} parameter_ent_attr;
+
 
 /**
  * An abstract data type to represent program entities.
- *
- * @see  ir_type
  */
 struct ir_entity {
-       firm_kind kind;       /**< The dynamic type tag for entity. */
-       ident *name;          /**< The name of this entity. */
-       ident *ld_name;       /**< Unique name of this entity, i.e., the mangled
-                                  name.  If the field is read before written a default
-                                  mangling is applies.  The name of the owner is prepended
-                                  to the name of the entity, separated by a underscore.
-                                  E.g.,  for a class `A' with field `a' this
-                                  is the ident for `A_a'. */
-       ir_type *type;        /**< The type of this entity, e.g., a method type, a
-                                  basic type of the language or a class itself. */
-       ir_type *owner;       /**< The compound type (e.g. class type) this entity belongs to. */
-       unsigned linkage:10;        /**< Specifies linkage type */
-       unsigned volatility:1;      /**< Specifies volatility of entities content.*/
-       unsigned aligned:1;         /**< Specifies alignment of entities content. */
-       unsigned usage:4;           /**< flag indicating usage types of this entity,
-                                        see ir_entity_usage. */
-       unsigned compiler_gen:1;    /**< If set, this entity was compiler generated.
-                                    */
-       unsigned visibility:3;      /**< @deprecated */
-       unsigned allocation:3;      /**< @deprecated */
-       unsigned peculiarity:3;     /**< @deprecated */
-       unsigned final:1;           /**< @deprecated */
-       int offset;                 /**< Offset in bytes for this entity. Fixed
-                                        when layout of owner is determined. */
-       unsigned alignment;         /**< entity alignment in bytes */
-       unsigned char offset_bit_remainder;
-                                   /**< If the entity is a bit field, this is the
-                                        offset of the start of the bit field
-                                        within the byte specified by offset. */
-       ir_visited_t visit;         /**< visited counter for walks of the type
-                                        information. */
-       struct dbg_info *dbi;       /**< A pointer to information for debug support.
-                                    */
-       void *link;                 /**< To store some intermediate information. */
-       ir_type *repr_class;        /**< If this entity represents a class info, the
-                                        associated class. */
-
-       /* ------------- fields for entities owned by a class type ---------------*/
-
-       ir_entity **overwrites;     /**< A list of entities this entity overwrites.
-                                    */
-       ir_entity **overwrittenby;  /**< A list of entities that overwrite this
-                                        entity. */
-
-       /* ------------- fields for atomic entities  --------------- */
+       firm_kind kind;          /**< The dynamic type tag for entity. */
+       ident *name;             /**< The name of this entity. */
+       ident *ld_name;          /**< Unique name of this entity, i.e., the mangled
+                                     name. May be NULL to indicate that a default
+                                     mangling based on the name should happen */
+       ir_type *type;           /**< The type of this entity */
+       ir_type *owner;          /**< The compound type (e.g. class type) this
+                                                             entity belongs to. */
+       unsigned linkage:10;     /**< Specifies linkage type */
+       unsigned volatility:1;   /**< Specifies volatility of entities content.*/
+       unsigned aligned:1;      /**< Specifies alignment of entities content. */
+       unsigned usage:4;        /**< flag indicating usage types of this entity,
+                                     see ir_entity_usage. */
+       unsigned compiler_gen:1; /**< If set, this entity was compiler generated.
+                                 */
+       unsigned visibility:3;   /**< @deprecated */
+       unsigned allocation:3;   /**< @deprecated */
+       unsigned peculiarity:3;  /**< @deprecated */
+       unsigned final:1;        /**< @deprecated */
+       unsigned offset_bit_remainder:8;
+                                /**< If the entity is a bit field, this is the
+                                     offset of the start of the bit field
+                                     within the byte specified by offset. */
+       unsigned is_parameter:1; /**< 1 if this represents a function parameter */
+       int offset;              /**< Offset in bytes for this entity. Fixed
+                                     when layout of owner is determined. */
+       unsigned alignment;      /**< entity alignment in bytes */
+       ir_visited_t visit;      /**< visited counter for walks of the type
+                                     information. */
+       struct dbg_info *dbi;    /**< A pointer to information for debug support. */
+       void *link;              /**< To store some intermediate information. */
+       ir_type *repr_class;     /**< If this entity represents a class info, the
+                                     associated class. */
+
+       ir_entity **overwrites;  /**< A list of entities this entity overwrites. */
+       ir_entity **overwrittenby; /**< A list of entities that overwrite this
+                                       entity. */
+
        ir_initializer_t *initializer; /**< entity initializer */
+#ifdef DEBUG_libfirm
+       long nr;             /**< A unique node number for each node to make output
+                                 readable. */
+#endif
+
        union {
                /* ------------- fields for compound entities -------------- */
-               compound_ent_attr cmpd_attr;
+               compound_ent_attr  cmpd_attr;
                /* ------------- fields for method entities ---------------- */
-               method_ent_attr   mtd_attr;
+               method_ent_attr    mtd_attr;
                /* fields for code entities */
-               code_ent_attr     code_attr;
+               code_ent_attr      code_attr;
+               /** parameter number for parameter entities */
+               parameter_ent_attr parameter;
        } attr; /**< type specific attributes */
-
-       /* ------------- fields for analyses ---------------*/
-
-#ifdef DEBUG_libfirm
-       long nr;             /**< A unique node number for each node to make output
-                                 readable. */
-#endif
 };
 
 /** Initialize the entity module. */
@@ -374,6 +380,17 @@ static inline int _entity_not_visited(const ir_entity *ent)
        return _get_entity_visited(ent) < firm_type_visited;
 }
 
+static inline int _is_parameter_entity(const ir_entity *entity)
+{
+       return entity->is_parameter;
+}
+
+static inline size_t _get_entity_parameter_number(const ir_entity *entity)
+{
+       assert(entity->is_parameter);
+       return entity->attr.parameter.number;
+}
+
 static inline ir_type *_get_entity_repr_class(const ir_entity *ent)
 {
        assert(ent && ent->kind == k_entity);
@@ -418,6 +435,8 @@ static inline void _set_entity_dbg_info(ir_entity *ent, dbg_info *db)
 #define get_entity_link(ent)                     _get_entity_link(ent)
 #define set_entity_link(ent, l)                  _set_entity_link(ent, l)
 #define get_entity_irg(ent)                      _get_entity_irg(ent)
+#define is_parameter_entity(ent)                 _is_parameter_entity(ent)
+#define get_entity_parameter_number(ent)         _get_entity_parameter_number(ent)
 #define get_entity_visited(ent)                  _get_entity_visited(ent)
 #define set_entity_visited(ent, num)             _set_entity_visited(ent, num)
 #define mark_entity_visited(ent)                 _mark_entity_visited(ent)
index 5627f25..a27ea24 100644 (file)
@@ -1142,34 +1142,6 @@ void set_struct_size(ir_type *tp, unsigned size)
        tp->size = size;
 }
 
-
-/**
- * Lazy construction of value argument / result representation.
- * Constructs a struct type and its member.  The types of the members
- * are passed in the argument list.
- *
- * @param name    name of the type constructed
- * @param len     number of fields
- * @param tps     array of field types with length len
- */
-static ir_type *build_value_type(char const* name, size_t len, tp_ent_pair *tps)
-{
-       size_t i;
-       ir_type *res = new_type_struct(new_id_from_str(name));
-       res->flags |= tf_value_param_type;
-       /* Remove type from type list.  Must be treated differently than other types. */
-       remove_irp_type(res);
-       for (i = 0; i < len; ++i) {
-               ident *id = new_id_from_str("elt");
-
-               /* use res as default if corresponding type is not yet set. */
-               ir_type *elt_type = tps[i].tp ? tps[i].tp : res;
-               tps[i].ent = new_entity(res, id, elt_type);
-               set_entity_allocation(tps[i].ent, allocation_parameter);
-       }
-       return res;
-}
-
 ir_type *new_d_type_method(size_t n_param, size_t n_res, type_dbg_info *db)
 {
        ir_type *res;
@@ -1180,7 +1152,6 @@ ir_type *new_d_type_method(size_t n_param, size_t n_res, type_dbg_info *db)
        res->size                         = get_mode_size_bytes(mode_P_code);
        res->attr.ma.n_params             = n_param;
        res->attr.ma.params               = XMALLOCNZ(tp_ent_pair, n_param);
-       res->attr.ma.value_params         = NULL;
        res->attr.ma.n_res                = n_res;
        res->attr.ma.res_type             = XMALLOCNZ(tp_ent_pair, n_res);
        res->attr.ma.variadicity          = variadicity_non_variadic;
@@ -1217,7 +1188,6 @@ ir_type *clone_type_method(ir_type *tp)
        res->attr.ma.n_params              = n_params;
        res->attr.ma.params                = XMALLOCN(tp_ent_pair, n_params);
        memcpy(res->attr.ma.params, tp->attr.ma.params, n_params * sizeof(res->attr.ma.params[0]));
-       res->attr.ma.value_params          = tp->attr.ma.value_params;
        res->attr.ma.n_res                 = n_res;
        res->attr.ma.res_type              = XMALLOCN(tp_ent_pair, n_res);
        memcpy(res->attr.ma.res_type, tp->attr.ma.res_type, n_res * sizeof(res->attr.ma.res_type[0]));
@@ -1239,12 +1209,6 @@ void free_method_attrs(ir_type *method)
        assert(method && (method->type_op == type_method));
        free(method->attr.ma.params);
        free(method->attr.ma.res_type);
-       /* cannot free it yet, type could be cloned ...
-       if (method->attr.ma.value_params) {
-               free_type_entities(method->attr.ma.value_params);
-               free_type(method->attr.ma.value_params);
-       }
-       */
 }
 
 size_t (get_method_n_params)(const ir_type *method)
@@ -1267,54 +1231,6 @@ void set_method_param_type(ir_type *method, size_t pos, ir_type *tp)
        assert(method->type_op == type_method);
        assert(pos < get_method_n_params(method));
        method->attr.ma.params[pos].tp = tp;
-       /* If information constructed set pass-by-value representation. */
-       if (method->attr.ma.value_params) {
-               assert(get_method_n_params(method) == get_struct_n_members(method->attr.ma.value_params));
-               set_entity_type(get_struct_member(method->attr.ma.value_params, pos), tp);
-       }
-}
-
-ir_entity *get_method_value_param_ent(ir_type *method, size_t pos)
-{
-       assert(method && (method->type_op == type_method));
-       assert(pos < get_method_n_params(method));
-
-       if (!method->attr.ma.value_params) {
-               /* parameter value type not created yet, build */
-               method->attr.ma.value_params = build_value_type("<value param>",
-                       get_method_n_params(method), method->attr.ma.params);
-       }
-       /*
-        * build_value_type() sets the method->attr.ma.value_params type as default if
-        * no type is set!
-        */
-       assert((get_entity_type(method->attr.ma.params[pos].ent) != method->attr.ma.value_params)
-              && "param type not yet set");
-       return method->attr.ma.params[pos].ent;
-}
-
-void set_method_value_param_type(ir_type *method, ir_type *tp)
-{
-       size_t i;
-       size_t n;
-
-       assert(method && (method->type_op == type_method));
-       assert(is_value_param_type(tp));
-       assert(get_method_n_params(method) == get_struct_n_members(tp));
-
-       method->attr.ma.value_params = tp;
-
-       n = get_struct_n_members(tp);
-       for (i = 0; i < n; i++) {
-               ir_entity *ent = get_struct_member(tp, i);
-               method->attr.ma.params[i].ent = ent;
-       }
-}
-
-ir_type *get_method_value_param_type(const ir_type *method)
-{
-       assert(method && (method->type_op == type_method));
-       return method->attr.ma.value_params;
 }
 
 size_t (get_method_n_ress)(const ir_type *method)
@@ -2040,23 +1956,6 @@ int is_frame_type(const ir_type *tp)
        return tp->flags & tf_frame_type;
 }
 
-int is_value_param_type(const ir_type *tp)
-{
-       return tp->flags & tf_value_param_type;
-}
-
-ir_type *new_type_value(void)
-{
-       ir_type *res = new_type_struct(new_id_from_str("<value_type>"));
-
-       res->flags |= tf_value_param_type;
-
-       /* Remove type from type list.  Must be treated differently than other types. */
-       remove_irp_type(res);
-
-       return res;
-}
-
 ir_type *new_type_frame(void)
 {
        ir_type *res = new_type_class(new_id_from_str("<frame_type>"));
index e61a951..3b7c3bd 100644 (file)
@@ -69,7 +69,6 @@ typedef struct {
 typedef struct {
        size_t       n_params;          /**< Number of parameters. */
        tp_ent_pair *params;            /**< Array of parameter type/value entities pairs. */
-       ir_type     *value_params;      /**< A type whose entities represent copied value arguments. */
        size_t       n_res;             /**< Number of results. */
        tp_ent_pair *res_type;          /**< Array of result type/value ir_entity pairs. */
        ir_variadicity variadicity;     /**< The variadicity of the method. */
@@ -130,17 +129,17 @@ typedef union {
 
 /** Additional type flags. */
 enum type_flags {
-       tf_none             =   0, /**< No flags. */
-       tf_lowered_type     =   1, /**< Set if this is a lowered type. */
-       tf_layout_fixed     =   2, /**< Set if the layout of a type is fixed */
-
-       tf_frame_type       =   4, /**< Set if this is a frame type. */
-       tf_value_param_type =   8, /**< Set if this is a value param type. */
-       tf_global_type      =  16, /**< Set only for the global type */
-       tf_tls_type         =  32, /**< Set only for the tls type */
-       tf_constructors     =  64, /**< Set only for the constructors segment type */
-       tf_destructors      = 128, /**< Set only for the destructors segment type */
+       tf_none             = 0, /**< No flags. */
+       tf_lowered_type     = 1U << 0, /**< Set if this is a lowered type. */
+       tf_layout_fixed     = 1U << 1, /**< Set if the layout of a type is fixed */
+
+       tf_frame_type       = 1U << 2, /**< Set if this is a frame type. */
+       tf_global_type      = 1U << 3, /**< Set only for the global type */
+       tf_tls_type         = 1U << 4, /**< Set only for the tls type */
+       tf_constructors     = 1U << 5, /**< Set only for the constructors segment type */
+       tf_destructors      = 1U << 6, /**< Set only for the destructors segment type */
 };
+ENUM_BITSET(type_flags)
 
 /**
  *  An abstract data type to represent types.
index bd0466e..d888d2b 100644 (file)
@@ -285,10 +285,6 @@ void type_walk_prog(type_walk_func *pre, type_walk_func *post, void *env)
                ir_graph *irg = get_irp_irg(i);
                cont.typ = get_irg_frame_type(irg);
                do_type_walk(cont, pre, post, env);
-
-               cont.typ = get_method_value_param_type(get_entity_type(get_irg_entity(irg)));
-               if (cont.typ)
-                       do_type_walk(cont, pre, post, env);
        }
 
        for (i = IR_SEGMENT_FIRST; i <= IR_SEGMENT_LAST; ++i) {