Commit 36408645 authored by Matthias Braun's avatar Matthias Braun
Browse files

split Sel node into Member and Sel

- Compound type selection is performed with Member
- Array indexing is performed with Sel
- Instead of the simpleSel constructor functions you can use the normal Member
  constructors now
- The concept of array element entities has been removed, Sel nodes just
  contain a pointer to the array type now.
parent b78e1f6d
......@@ -353,67 +353,6 @@ FIRM_API ir_node *new_Const_long(ir_mode *mode, long value);
/** @} */
/** @addtogroup Sel
* @{
*/
/** Constructor for a simpleSel node.
*
* This is a shortcut for the new_rd_Sel() constructor. To be used for
* Sel nodes that do not select from an array, i.e., have no index
* inputs. It adds the two parameters 0, NULL.
*
* @param *db A pointer for debug information.
* @param *block The IR block the node belongs to.
* @param *objptr The object from that the Sel operation selects a
* single attribute out.
* @param *ent The entity to select.
*/
FIRM_API ir_node *new_rd_simpleSel(dbg_info *db, ir_node *block,
ir_node *objptr, ir_entity *ent);
/** Constructor for a simpleSel node.
*
* This is a shortcut for the new_d_Sel() constructor. To be used for
* Sel nodes that do not select from an array, i.e., have no index
* inputs. It adds the two parameters 0, NULL.
*
* @param *block The IR block the node belongs to.
* @param *objptr The object from that the Sel operation selects a
* single attribute out.
* @param *ent The entity to select.
* @ingroup Sel
*/
FIRM_API ir_node *new_r_simpleSel(ir_node *block, ir_node *objptr,
ir_entity *ent);
/** Constructor for a simpleSel node.
*
* This is a shortcut for the new_d_Sel() constructor. To be used for
* Sel nodes that do not select from an array, i.e., have no index
* inputs. It adds the two parameters 0, NULL.
*
* @param *db A pointer for debug information.
* @param *objptr The object from that the Sel operation selects a
* single attribute out.
* @param *ent The entity to select.
*/
FIRM_API ir_node *new_d_simpleSel(dbg_info *db, ir_node *objptr,
ir_entity *ent);
/** Constructor for a simpelSel node.
*
* This is a shortcut for the new_Sel() constructor. To be used for
* Sel nodes that do not select from an array, i.e., have no index
* inputs. It adds the two parameters 0, NULL.
*
* @param *objptr The object from that the Sel operation selects a single attribute out.
* @param *ent The entity to select.
*/
FIRM_API ir_node *new_simpleSel(ir_node *objptr, ir_entity *ent);
/** @} */
/** @addtogroup Div
* @{
*/
......
......@@ -1531,12 +1531,6 @@ FIRM_API void set_array_element_type(ir_type *array, ir_type *tp);
/** Returns the array element type. */
FIRM_API ir_type *get_array_element_type(const ir_type *array);
/** Sets the array element entity. */
FIRM_API void set_array_element_entity(ir_type *array, ir_entity *ent);
/** Returns the array element entity. */
FIRM_API ir_entity *get_array_element_entity(const ir_type *array);
/**
* Sets the array variable size flag.
* If this flag is set then no upper/lower bounds need to be set and
......
......@@ -65,7 +65,7 @@ static ptr_access_kind analyze_arg(ir_node *arg, ptr_access_kind bits)
bits |= get_method_param_access(callee, p);
}
}
} else if (is_Sel(ptr) && get_irp_callee_info_state() == irg_callee_info_consistent) {
} else if (is_Member(ptr) && get_irp_callee_info_state() == irg_callee_info_consistent) {
/* is be a polymorphic call but callee information is available */
size_t n_params = get_Call_n_params(succ);
......
......@@ -140,11 +140,11 @@ static ir_entity **get_impl_methods(ir_entity *method)
/** Analyze address computations.
*
* Compute for all Sel nodes the set of methods that can be selected.
* Compute for all Member nodes the set of methods that can be selected.
* For each entity we store the set of subentities in the link field.
*
* Further do some optimizations:
* - Call standard optimizations for Sel nodes: this removes polymorphic
* - Call standard optimizations for Member nodes: this removes polymorphic
* calls.
*
* @param node The node to analyze
......@@ -152,7 +152,7 @@ static ir_entity **get_impl_methods(ir_entity *method)
static void sel_methods_walker(ir_node *node, void *env)
{
(void)env;
if (!is_Sel(node))
if (!is_Member(node))
return;
/* Call standard optimizations */
......@@ -160,11 +160,11 @@ static void sel_methods_walker(ir_node *node, void *env)
if (node != new_node) {
exchange(node, new_node);
node = new_node;
if (!is_Sel(node))
if (!is_Member(node))
return;
}
ir_entity *const entity = get_Sel_entity(node);
ir_entity *const entity = get_Member_entity(node);
if (!is_method_entity(entity))
return;
/* we may have a vtable entry and need this redirection to get the actually
......@@ -185,7 +185,7 @@ static void sel_methods_walker(ir_node *node, void *env)
* Computes a set of entities that overwrite an entity and contain
* an implementation. The set is stored in the entity's link field.
*
* Further replaces Sel nodes where this set contains exactly one
* Further replaces Member nodes where this set contains exactly one
* method by Address nodes.
*/
static void sel_methods_init(void)
......@@ -203,37 +203,37 @@ static void sel_methods_init(void)
/*--------------------------------------------------------------------------*/
/**
* Returns an array of all methods that could be called at a Sel node.
* Returns an array of all methods that could be called at a Member node.
* This array contains every entry only once.
*
* @param sel the Sel node
* @param member the Member node
*/
static ir_entity **get_Sel_arr(ir_node *sel)
static ir_entity **get_member_arr(ir_node *member)
{
ir_entity *const entity = get_Sel_entity(sel);
ir_entity *const entity = get_Member_entity(member);
assert(is_Method_type(get_entity_type(entity))); /* what else? */
return (ir_entity**)get_entity_link(entity);
}
/**
* Returns the number of possible called methods at a Sel node.
* Returns the number of possible called methods at a Member node.
*
* @param sel the Sel node
* @param member the Member node
*/
static size_t get_Sel_n_methods(ir_node *sel)
static size_t get_member_n_methods(ir_node *member)
{
ir_entity **const arr = get_Sel_arr(sel);
ir_entity **const arr = get_member_arr(member);
if (arr == NULL)
return 0;
return ARR_LEN(arr);
}
/**
* Returns the ith possible called method entity at a Sel node.
* Returns the ith possible called method entity at a Member node.
*/
static ir_entity *get_Sel_method(ir_node *sel, size_t pos)
static ir_entity *get_member_method(ir_node *member, size_t pos)
{
ir_entity **arr = get_Sel_arr(sel);
ir_entity **arr = get_member_arr(member);
assert(pos < ARR_LEN(arr));
return arr[pos];
}
......@@ -294,11 +294,11 @@ static void free_mark(ir_node *node, pset *set)
set_irn_link(node, MARK);
switch (get_irn_opcode(node)) {
case iro_Sel: {
const ir_entity *ent = get_Sel_entity(node);
case iro_Member: {
const ir_entity *ent = get_Member_entity(node);
if (is_method_entity(ent)) {
for (size_t i = 0, n = get_Sel_n_methods(node); i < n; ++i) {
pset_insert_ptr(set, get_Sel_method(node, i));
for (size_t i = 0, n = get_member_n_methods(node); i < n; ++i) {
pset_insert_ptr(set, get_member_method(node, i));
}
}
break;
......@@ -341,7 +341,7 @@ static void free_ana_walker(ir_node *node, void *env)
/* special nodes */
case iro_Address:
case iro_Align:
case iro_Sel:
case iro_Member:
case iro_Const:
case iro_Offset:
case iro_Phi:
......@@ -568,13 +568,13 @@ static void callee_ana_node(ir_node *node, pset *methods)
break;
}
case iro_Sel: {
ir_entity *entity = get_Sel_entity(node);
case iro_Member: {
ir_entity *entity = get_Member_entity(node);
if (!is_method_entity(entity))
break;
/* polymorphic method */
for (size_t i = 0, n = get_Sel_n_methods(node); i < n; ++i) {
ir_entity *ent = get_Sel_method(node, i);
for (size_t i = 0, n = get_member_n_methods(node); i < n; ++i) {
ir_entity *ent = get_member_method(node, i);
if (ent != NULL) {
pset_insert_ptr(methods, ent);
} else {
......@@ -686,7 +686,8 @@ static void destruct_walker(ir_node *node, void *env)
size_t cgana(ir_entity ***free_methods)
{
/* Optimize Address/Sel nodes and compute all methods that implement an entity. */
/* Optimize Address/Member nodes and compute all methods that implement an
* entity. */
sel_methods_init();
size_t length = get_free_methods(free_methods);
callee_ana();
......@@ -715,11 +716,11 @@ void opt_call_addrs(void)
* all ir graphs:
* - All Address operations that refer to intern methods are replaced
* by Const operations referring to the corresponding entity.
* - Sel nodes, that select entities that are not overwritten are
* - Member nodes, that select entities that are not overwritten are
* replaced by Const nodes referring to the selected entity.
* - Sel nodes, for which no method exists at all are replaced by Bad
* - Member nodes, for which no method exists at all are replaced by Bad
* nodes.
* - Sel nodes with a pointer input that is an Alloc node are replaced
* - Member nodes with a pointer input that is an Alloc node are replaced
* by Const nodes referring to the entity that implements the method in
* the type given by the Alloc node.
*/
......
......@@ -75,23 +75,30 @@ ir_storage_class_class_t get_base_sc(ir_storage_class_class_t x)
}
/**
* Find the base address and entity of an Sel node.
* Find the base address and entity of an Sel/Member node.
*
* @param sel the node
* @param node the node
* @param pEnt after return points to the base entity.
*
* @return the base address.
*/
static ir_node *find_base_adr(const ir_node *sel, ir_entity **pEnt)
static const ir_node *find_base_adr(const ir_node *node, ir_entity **pEnt)
{
ir_node *ptr = get_Sel_ptr(sel);
while (is_Sel(ptr)) {
sel = ptr;
ptr = get_Sel_ptr(sel);
const ir_node *member = NULL;
for (;;) {
if (is_Sel(node)) {
node = get_Sel_ptr(node);
continue;
} else if (is_Member(node)) {
member = node;
node = get_Member_ptr(node);
} else {
break;
}
}
*pEnt = get_Sel_entity(sel);
return ptr;
if (member != NULL)
*pEnt = get_Member_entity(member);
return node;
}
/**
......@@ -347,13 +354,13 @@ static ir_alias_relation different_types(const ir_node *adr1,
if (is_Address(adr1))
ent1 = get_Address_entity(adr1);
else if (is_Sel(adr1))
ent1 = get_Sel_entity(adr1);
else if (is_Member(adr1))
ent1 = get_Member_entity(adr1);
if (is_Address(adr2))
ent2 = get_Address_entity(adr2);
else if (is_Sel(adr2))
ent2 = get_Sel_entity(adr2);
else if (is_Member(adr2))
ent2 = get_Member_entity(adr2);
if (ent1 != NULL && ent2 != NULL) {
ir_type *tp1 = get_entity_type(ent1);
......@@ -558,19 +565,13 @@ static ir_alias_relation _get_alias_relation(
return ir_sure_alias;
}
/* skip Sels */
const ir_node *base1 = adr1;
const ir_node *base2 = adr2;
ir_entity *ent1 = NULL;
ir_entity *ent2 = NULL;
if (is_Sel(adr1)) {
base1 = find_base_adr(adr1, &ent1);
}
if (is_Sel(adr2)) {
base2 = find_base_adr(adr2, &ent2);
}
/* skip Sels/Members */
ir_entity *ent1 = NULL;
ir_entity *ent2 = NULL;
const ir_node *base1 = find_base_adr(adr1, &ent1);
const ir_node *base2 = find_base_adr(adr2, &ent2);
/* same base address -> compare Sel entities */
/* same base address -> compare entities */
if (base1 == base2 && ent1 != NULL && ent2 != NULL) {
if (ent1 != ent2) {
long offset1 = get_entity_offset(ent1);
......@@ -872,20 +873,23 @@ static ir_entity_usage determine_entity_usage(const ir_node *irn,
break;
}
case iro_Sel:
case iro_Add:
case iro_Sub:
case iro_Id:
/* Check the successor of irn. */
res |= determine_entity_usage(succ, entity);
break;
case iro_Sel: {
ir_entity *sel_entity = get_Sel_entity(succ);
case iro_Member: {
ir_entity *member_entity = get_Member_entity(succ);
/* this analysis can't handle unions correctly */
if (is_Union_type(get_entity_owner(sel_entity))) {
if (is_Union_type(get_entity_owner(member_entity))) {
res |= ir_usage_unknown;
break;
}
/* Check the successor of irn. */
res |= determine_entity_usage(succ, sel_entity);
res |= determine_entity_usage(succ, member_entity);
break;
}
......@@ -902,11 +906,6 @@ static ir_entity_usage determine_entity_usage(const ir_node *irn,
}
break;
/* skip identities */
case iro_Id:
res |= determine_entity_usage(succ, entity);
break;
/* skip tuples */
case iro_Tuple: {
int input_nr;
......@@ -962,14 +961,11 @@ static void analyse_irg_entity_usage(ir_graph *irg)
ir_node *irg_frame = get_irg_frame(irg);
foreach_irn_out_r(irg_frame, j, succ) {
ir_entity *entity;
unsigned flags;
if (!is_Sel(succ))
if (!is_Member(succ))
continue;
entity = get_Sel_entity(succ);
flags = get_entity_usage(entity);
ir_entity *entity = get_Member_entity(succ);
unsigned flags = get_entity_usage(entity);
flags |= determine_entity_usage(succ, entity);
set_entity_usage(entity, (ir_entity_usage) flags);
}
......@@ -990,14 +986,12 @@ static void analyse_irg_entity_usage(ir_graph *irg)
foreach_irn_out_r(args, j, arg) {
if (get_Proj_proj(arg) == static_link_arg) {
foreach_irn_out_r(arg, k, succ) {
if (is_Sel(succ)) {
ir_entity *entity = get_Sel_entity(succ);
if (is_Member(succ)) {
ir_entity *entity = get_Member_entity(succ);
if (get_entity_owner(entity) == ft) {
/* found an access to the outer frame */
unsigned flags;
flags = get_entity_usage(entity);
unsigned flags = get_entity_usage(entity);
flags |= determine_entity_usage(succ, entity);
set_entity_usage(entity, (ir_entity_usage) flags);
}
......@@ -1325,8 +1319,8 @@ static ir_entity *find_entity(ir_node *ptr)
switch (get_irn_opcode(ptr)) {
case iro_Address:
return get_Address_entity(ptr);
case iro_Sel:
return get_Sel_entity(ptr);
case iro_Member:
return get_Member_entity(ptr);
case iro_Sub:
case iro_Add: {
ir_node *left = get_binop_left(ptr);
......
......@@ -356,7 +356,7 @@ static int vrp_update_node(ir_vrp_info *info, ir_node *node)
is_Carry(node) is_Cmp(node) is_Cond(node)
is_CopyB(node) is_Div(node) is_Dummy(node)
is_End(node) is_Free(node)
is_IJmp(node) is_Jmp(node) is_Load(node) is_Minus(node)
is_IJmp(node) is_Jmp(node) is_Load(node) is_Minus(node) is_Member(node)
is_Mod(node) is_Mul(node) is_Mulh(node) is_Mux(node) is_NoMem(node)
is_Offset(node) is_Pin(node) is_Proj(node)
is_Raise(node) is_Return(node) is_Sel(node) is_Start(node) is_Store(node)
......
......@@ -986,19 +986,17 @@ static ir_node *gen_Not(ir_node *const node)
return gen_unop(node, n_Not_op, &new_bd_amd64_Not);
}
static ir_node *gen_Sel(ir_node *const node)
static ir_node *gen_Member(ir_node *const node)
{
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *ptr = get_Sel_ptr(node);
ir_node *ptr = get_Member_ptr(node);
ir_graph *irg = get_irn_irg(node);
ir_node *base = get_frame_base(irg);
ir_entity *entity = get_Sel_entity(node);
ir_entity *entity = get_Member_entity(node);
if (!is_Proj(ptr) || !is_Start(get_Proj_pred(ptr)))
panic("Sel not lowered");
if (get_Sel_n_indexs(node) > 0)
panic("array Sel not lowered %+F", node);
if (is_parameter_entity(entity) &&
get_entity_parameter_number(entity) == IR_VA_START_PARAMETER_NUMBER)
panic("va_start NIY");
......@@ -1971,6 +1969,7 @@ static void amd64_register_transformers(void)
be_set_transform_function(op_IJmp, gen_IJmp);
be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Member, gen_Member);
be_set_transform_function(op_Minus, gen_Minus);
be_set_transform_function(op_Mod, gen_Mod);
be_set_transform_function(op_Mul, gen_Mul);
......@@ -1979,7 +1978,6 @@ static void amd64_register_transformers(void)
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Return, gen_Return);
be_set_transform_function(op_Sel, gen_Sel);
be_set_transform_function(op_Shl, gen_Shl);
be_set_transform_function(op_Shr, gen_Shr);
be_set_transform_function(op_Shrs, gen_Shrs);
......
......@@ -1785,14 +1785,14 @@ static ir_node *gen_Call(ir_node *node)
return res;
}
static ir_node *gen_Sel(ir_node *node)
static ir_node *gen_Member(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *ptr = get_Sel_ptr(node);
ir_node *ptr = get_Member_ptr(node);
ir_node *new_ptr = be_transform_node(ptr);
ir_entity *entity = get_Sel_entity(node);
ir_entity *entity = get_Member_entity(node);
/* must be the frame pointer all other sels must have been lowered
* already */
......@@ -1837,13 +1837,13 @@ static void arm_register_transformers(void)
be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Member, gen_Member);
be_set_transform_function(op_Minus, gen_Minus);
be_set_transform_function(op_Mul, gen_Mul);
be_set_transform_function(op_Not, gen_Not);
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Return, gen_Return);
be_set_transform_function(op_Sel, gen_Sel);
be_set_transform_function(op_Shl, gen_Shl);
be_set_transform_function(op_Shr, gen_Shr);
be_set_transform_function(op_Shrs, gen_Shrs);
......
......@@ -1159,30 +1159,29 @@ static ir_node *create_be_return(be_abi_irg_t *const env, ir_node *const irn)
return ret;
}
typedef struct lower_frame_sels_env_t {
typedef struct lower_frame_members_env_t {
ir_node *frame; /**< the current frame */
const arch_register_class_t *sp_class; /**< register class of the stack pointer */
} lower_frame_sels_env_t;
} lower_frame_members_env_t;
/**
* Walker: Replaces Sels of frame type and
* Walker: Replaces Member nodes of frame type and
* value param type entities by FrameAddress.
* Links all used entities.
*/
static void lower_frame_sels_walker(ir_node *irn, void *data)
static void lower_frame_members_walker(ir_node *irn, void *data)
{
lower_frame_sels_env_t *ctx = (lower_frame_sels_env_t*)data;
if (is_Sel(irn)) {
ir_node *ptr = get_Sel_ptr(irn);
if (ptr == ctx->frame) {
ir_entity *ent = get_Sel_entity(irn);
ir_node *bl = get_nodes_block(irn);
ir_node *nw
= be_new_FrameAddr(ctx->sp_class, bl, ctx->frame, ent);
exchange(irn, nw);
}
lower_frame_members_env_t *ctx = (lower_frame_members_env_t*)data;
if (!is_Member(irn))
return;
ir_node *ptr = get_Member_ptr(irn);
if (ptr == ctx->frame) {
ir_entity *ent = get_Member_entity(irn);
ir_node *bl = get_nodes_block(irn);
ir_node *nw
= be_new_FrameAddr(ctx->sp_class, bl, ctx->frame, ent);
exchange(irn, nw);
}
}
......@@ -1236,7 +1235,7 @@ static void modify_irg(ir_graph *const irg, be_abi_irg_t *const env)
ir_type *const arg_type = compute_arg_type(irg, call, method_type);
/* Convert the Sel nodes in the irg to frame addr nodes: */
lower_frame_sels_env_t ctx;
lower_frame_members_env_t ctx;
ctx.frame = get_irg_frame(irg);
ctx.sp_class = arch_env->sp->reg_class;
......@@ -1259,7 +1258,7 @@ static void modify_irg(ir_graph *const irg, be_abi_irg_t *const env)
be_add_parameter_entity_stores(irg);
irg_walk_graph(irg, lower_frame_sels_walker, NULL, &ctx);
irg_walk_graph(irg, lower_frame_members_walker, NULL, &ctx);
irp_free_resources(irp, IRP_RESOURCE_ENTITY_LINK);
......
......@@ -677,7 +677,7 @@ static void create_stores_for_type(ir_graph *irg, ir_type *type)
if (arg == IR_VA_START_PARAMETER_NUMBER)
continue;
addr = new_r_Sel(start_block, frame, 0, NULL, entity);
addr = new_r_Member(start_block, 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, arg);
......
......@@ -80,10 +80,10 @@ static void stack_frame_compute_initial_offset(be_stack_layout_t *frame)
}
/**
* Walker: finally lower all Sels of outer frame or parameter
* Walker: finally lower all Members of outer frame or parameter
* entities.
*/
static void lower_outer_frame_sels(ir_node *sel, void *ctx)
static void lower_outer_frame_members(ir_node *sel, void *ctx)
{
ir_node *ptr;
ir_entity *ent;
......@@ -92,12 +92,12 @@ static void lower_outer_frame_sels(ir_node *sel, void *ctx)
ir_graph *irg;
(void) ctx;
if (! is_Sel(sel))
if (!is_Member(sel))
return;
ent = get_Sel_entity(sel);
ent = get_Member_entity(sel);
owner = get_entity_owner(ent);
ptr = get_Sel_ptr(sel);
ptr = get_Member_ptr(sel);
irg = get_irn_irg(sel);
layout = be_get_irg_stack_layout(irg);
......@@ -238,7 +238,7 @@ void be_abi_fix_stack_bias(ir_graph *irg)
continue;
ir_graph *irg = get_entity_irg(ent);
if (irg != NULL)
irg_walk_graph(irg, NULL, lower_outer_frame_sels, NULL);
irg_walk_graph(irg, NULL, lower_outer_frame_members, NULL);
}
}
......
......@@ -2222,14 +2222,14 @@ static ir_node *gen_Call(ir_node *node)
return res;
}
static ir_node *gen_Sel(ir_node *node)
static ir_node *gen_Member(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);