/** 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. */
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.
*/
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
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. */
*/
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.
/* 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);
}
*
* @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);
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.
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);
- }
}
}
}
* 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);
}
/**
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;
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);
}
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;
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, ¶m_map);
+ arg_type = compute_arg_type(irg, call, method_type, ¶m_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;
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) {
/* 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);
}
_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;
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);
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;
}
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.
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;
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) {
++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);
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;
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 */
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.
}
}
-/**
- * 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;
+ }
+ }
+ }
+ }
}
/**
*/
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;
}
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);
}
/**
*/
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;
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)) {
}
/* 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);
}
}
-/**
- * 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.
*/
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)
{
{
ir_entity *ent;
ir_type *mtp;
+ ir_type *lowered_mtp;
unsigned n_idx;
obstack_init(&env->obst);
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 */
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);
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;
/* 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:
} 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. */
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);
} 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));
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)
/* 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;
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();
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);
}
/**
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));
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)
#define FIRM_TR_ENTITY_T_H
#include <assert.h>
+#include <stdbool.h>
#include "typerep.h"
#include "type_t.h"
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. */
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);
#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)
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;
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;
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]));
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)
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)
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>"));
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. */
/** 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.
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) {