Commit 5796136e authored by Matthias Braun's avatar Matthias Braun
Browse files

ia32: Introduce FRAMEOFFSET immediate type

This way we don't need a separate frame_entity field in the attribute
struct anymore. We can also use the immediate type to determine whether
we need to assign a fresh stackentity to a node.
This commit does not change the frame_use field, which is now a
duplicate way to indicate whether we need to assign a stackentity. This
currently requires a lot of asserts to ensure the two stay in sync. In
the future I'd like to use frame_use only for the special case when a
32bit or 64bit entity needs to be forced.
parent cf90d399
......@@ -628,14 +628,11 @@ static void perform_address_matching(ir_node *ptr, int *arity,
} else {
addr->index_input = NO_INPUT;
}
if (maddr.frame_entity != NULL) {
assert(maddr.imm.entity == NULL);
maddr.imm.entity = maddr.frame_entity;
/* not supported yet */
assert(!is_parameter_entity(maddr.frame_entity)
|| get_entity_parameter_number(maddr.frame_entity)
!= IR_VA_START_PARAMETER_NUMBER);
}
ir_entity *entity = maddr.imm.entity;
if (is_parameter_entity(entity) &&
get_entity_parameter_number(entity) == IR_VA_START_PARAMETER_NUMBER)
panic("VA_START not supported yet");
addr->immediate = maddr.imm;
addr->log_scale = maddr.scale;
}
......
......@@ -126,15 +126,29 @@ static ir_node *ia32_get_admissible_noreg(ir_node *irn, int pos)
}
}
static ir_entity *ia32_get_frame_entity(const ir_node *irn)
static ir_entity *ia32_get_frame_entity(const ir_node *node)
{
return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
if (!is_ia32_irn(node))
return NULL;
ia32_attr_t const *const attr = get_ia32_attr_const(node);
if (attr->am_imm.kind == X86_IMM_FRAMEOFFSET) {
assert(get_ia32_frame_use(node) != IA32_FRAME_USE_NONE);
return attr->am_imm.entity;
}
assert(get_ia32_frame_use(node) == IA32_FRAME_USE_NONE);
return NULL;
}
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
const ir_type *type)
{
set_ia32_frame_ent(node, entity);
ia32_attr_t *const attr = get_ia32_attr(node);
attr->am_imm = (x86_imm32_t) {
.kind = X86_IMM_FRAMEOFFSET,
.entity = entity,
.offset = attr->am_imm.offset,
};
assert(get_ia32_frame_use(node) != IA32_FRAME_USE_NONE);
/* set ls_mode based on entity unless we explicitly requested
* a certain mode */
......@@ -152,8 +166,8 @@ static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
static void ia32_set_frame_offset(ir_node *node, int bias)
{
if (get_ia32_frame_ent(node) == NULL)
return;
ia32_attr_t *const attr = get_ia32_attr(node);
assert(attr->am_imm.kind == X86_IMM_FRAMEOFFSET);
/* Pop nodes modify the stack pointer before calculating the
* destination address, fix this here */
......@@ -164,7 +178,14 @@ static void ia32_set_frame_offset(ir_node *node, int bias)
bias -= get_mode_size_bytes(mode);
}
}
add_ia32_am_offs_int(node, bias);
#ifndef NDEBUG
attr->old_frame_ent = attr->am_imm.entity;
#endif
/* This is just a simple 32bit value now */
attr->am_imm.offset += bias;
attr->am_imm.entity = NULL;
attr->am_imm.kind = X86_IMM_VALUE;
}
int ia32_get_sp_bias(const ir_node *node)
......@@ -481,8 +502,8 @@ ir_node *ia32_turn_back_am(ir_node *node)
set_irn_n(node, n_ia32_index, noreg);
ia32_attr_t *const attr = get_ia32_attr(node);
attr->am_imm = (x86_imm32_t) { .kind = X86_IMM_VALUE, .offset = 0 };
attr->frame_use = IA32_FRAME_USE_NONE;
set_ia32_am_scale(node, 0);
set_ia32_frame_ent(node, NULL);
/* rewire mem-proj */
if (get_irn_mode(node) == mode_T) {
......@@ -748,9 +769,14 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
ir_node *noreg = ia32_new_NoReg_gp(irg);
ir_node *frame = get_irg_frame(irg);
ir_node *const push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp, mode);
set_ia32_frame_ent(push, ent);
ir_node *const push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem,
noreg, sp, mode);
ia32_attr_t *const attr = get_ia32_attr(push);
attr->am_imm = (x86_imm32_t) {
.kind = X86_IMM_FRAMEOFFSET,
.entity = ent,
};
set_ia32_frame_use(push, IA32_FRAME_USE_AUTO);
set_ia32_op_type(push, ia32_AddrModeS);
set_ia32_is_spill(push);
......@@ -768,7 +794,12 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp,
ir_node *frame = get_irg_frame(irg);
ir_node *pop = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
get_irg_no_mem(irg), sp);
set_ia32_frame_ent(pop, ent);
ia32_attr_t *const attr = get_ia32_attr(pop);
attr->am_imm = (x86_imm32_t) {
.kind = X86_IMM_FRAMEOFFSET,
.entity = ent,
};
set_ia32_frame_use(pop, IA32_FRAME_USE_AUTO);
set_ia32_op_type(pop, ia32_AddrModeD);
set_ia32_ls_mode(pop, mode);
set_ia32_is_reload(pop);
......@@ -920,13 +951,20 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
be_forbid_coalescing(env);
}
if (!is_ia32_irn(node) || get_ia32_frame_ent(node) != NULL
|| get_ia32_op_type(node) != ia32_AddrModeS)
if (!is_ia32_irn(node) || get_ia32_op_type(node) != ia32_AddrModeS)
return;
ia32_attr_t const *const attr = get_ia32_attr_const(node);
if (attr->am_imm.kind != X86_IMM_FRAMEOFFSET) {
assert(get_ia32_frame_use(node) == IA32_FRAME_USE_NONE);
return;
}
if (attr->am_imm.entity != NULL)
return;
ir_type const *type;
switch (get_ia32_frame_use(node)) {
case IA32_FRAME_USE_NONE: return;
case IA32_FRAME_USE_NONE:
panic("X86_IMM_FRAMEOFFSET but IA32_FRAME_USE_NONE");
case IA32_FRAME_USE_32BIT:
type = get_type_for_mode(ia32_mode_gp);
goto request_entity;
......
......@@ -191,6 +191,7 @@ static void ia32_emit_relocation(x86_imm32_t const *const imm)
be_emit_char('-');
be_emit_string(pic_base_label);
return;
case X86_IMM_FRAMEOFFSET:
case X86_IMM_VALUE:
break;
}
......@@ -360,9 +361,6 @@ static ir_node const *get_irn_n_reg(ir_node const *const node, int const pos)
*/
static void ia32_emit_am(ir_node const *const node)
{
/* just to be sure... */
assert(get_ia32_frame_use(node) == IA32_FRAME_USE_NONE || get_ia32_frame_ent(node));
if (get_ia32_am_tls_segment(node))
be_emit_cstring("%gs:");
......
......@@ -233,8 +233,8 @@ static void ia32_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
fprintf(F, "AM scale = %u\n", get_ia32_am_scale(n));
/* dump pn code */
const ia32_attr_t *attr = get_ia32_attr_const(n);
if (has_ia32_condcode_attr(n)) {
const ia32_attr_t *attr = get_ia32_attr_const(n);
const char *cc_name = condition_code_name(get_ia32_condcode(n));
if (cc_name) {
fprintf(F, "condition_code = %s\n", cc_name);
......@@ -258,13 +258,19 @@ static void ia32_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
/* dump frame entity */
fprintf(F, "frame use = %s\n", get_frame_use_str(n));
fprintf(F, "frame entity = ");
if (get_ia32_frame_ent(n)) {
ir_fprintf(F, "%+F", get_ia32_frame_ent(n));
} else {
fprintf(F, "n/a");
if (attr->am_imm.kind == X86_IMM_FRAMEOFFSET ||
attr->old_frame_ent != NULL) {
fprintf(F, "frame entity = ");
ir_entity *entity = attr->am_imm.entity;
if (entity == NULL)
entity = attr->old_frame_ent;
if (entity != NULL) {
ir_fprintf(F, "%+F", entity);
} else {
fprintf(F, "n/a");
}
fprintf(F, "\n");
}
fprintf(F, "\n");
/* dump modes */
fprintf(F, "ls_mode = ");
......@@ -507,11 +513,13 @@ void ia32_copy_am_attrs(ir_node *to, const ir_node *from)
ia32_attr_t const *const from_attr = get_ia32_attr_const(from);
ia32_attr_t *const to_attr = get_ia32_attr(to);
to_attr->am_imm = from_attr->am_imm;
to_attr->frame_use = from_attr->frame_use;
set_ia32_ls_mode(to, get_ia32_ls_mode(from));
set_ia32_am_scale(to, get_ia32_am_scale(from));
set_ia32_frame_ent(to, get_ia32_frame_ent(from));
set_ia32_frame_use(to, get_ia32_frame_use(from));
#ifndef NDEBUG
to_attr->old_frame_ent = from_attr->old_frame_ent;
#endif
}
void set_ia32_commutative(ir_node *node)
......@@ -568,25 +576,6 @@ int is_ia32_is_remat(const ir_node *node)
return attr->is_remat;
}
ir_entity *get_ia32_frame_ent(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
return attr->frame_ent;
}
void set_ia32_frame_ent(ir_node *node, ir_entity *ent)
{
ia32_attr_t *attr = get_ia32_attr(node);
attr->frame_ent = ent;
if (!ent) {
set_ia32_frame_use(node, IA32_FRAME_USE_NONE);
} else if (get_ia32_frame_use(node) == IA32_FRAME_USE_NONE) {
/* Only set frame use to auto, if it is not set to something more specific
* already. */
set_ia32_frame_use(node, IA32_FRAME_USE_AUTO);
}
}
unsigned get_ia32_latency(const ir_node *node)
{
assert(is_ia32_irn(node));
......@@ -783,7 +772,7 @@ static int ia32_attrs_equal_(const ia32_attr_t *a, const ia32_attr_t *b)
{
/* nodes with not yet assigned entities shouldn't be CSEd (important for
* unsigned int -> double conversions */
if (a->frame_use != IA32_FRAME_USE_NONE && !a->frame_ent)
if (a->am_imm.kind == X86_IMM_FRAMEOFFSET && a->am_imm.entity == NULL)
return false;
return a->tp == b->tp
......@@ -791,7 +780,6 @@ static int ia32_attrs_equal_(const ia32_attr_t *a, const ia32_attr_t *b)
&& x86_imm32_equal(&a->am_imm, &b->am_imm)
&& a->ls_mode == b->ls_mode
&& a->frame_use == b->frame_use
&& a->frame_ent == b->frame_ent
&& a->has_except_label == b->has_except_label
&& a->ins_permuted == b->ins_permuted;
}
......
......@@ -158,12 +158,18 @@ int is_ia32_commutative(const ir_node *node);
static inline void set_ia32_frame_use(ir_node *const node, ia32_frame_use_t const val)
{
ia32_attr_t *const attr = get_ia32_attr(node);
if (attr->frame_use == val)
return;
/* Only allow more specific, the same or reset. */
assert(attr->frame_use == IA32_FRAME_USE_NONE
|| attr->frame_use == IA32_FRAME_USE_AUTO
|| attr->frame_use == val
|| val == IA32_FRAME_USE_NONE);
attr->frame_use = val;
if (val != IA32_FRAME_USE_NONE) {
assert(attr->am_imm.kind == X86_IMM_VALUE ||
attr->am_imm.kind == X86_IMM_FRAMEOFFSET);
attr->am_imm.kind = X86_IMM_FRAMEOFFSET;
}
}
static inline ia32_frame_use_t get_ia32_frame_use(ir_node const *const node)
......@@ -199,16 +205,6 @@ static inline void set_ia32_ls_mode(ir_node *const node, ir_mode *const mode)
attr->ls_mode = mode;
}
/**
* Gets the frame entity assigned to this node;
*/
ir_entity *get_ia32_frame_ent(const ir_node *node);
/**
* Sets the frame entity for this node;
*/
void set_ia32_frame_ent(ir_node *node, ir_entity *ent);
/**
* Returns the condition code of a node.
*/
......
......@@ -112,12 +112,11 @@ struct ia32_attr_t {
ir_mode *ls_mode; /**< Load/Store mode: This is the mode of the
value that is manipulated by this node. */
ir_entity *frame_ent; /**< the frame entity attached to this node */
ir_label_t exc_label; /**< the exception label iff this instruction can throw an exception */
#ifndef NDEBUG
const char *orig_node; /**< holds the name of the original ir node */
ir_entity *old_frame_ent; /**< frame entity referenced */
unsigned attr_type; /**< bitfield indicating the attribute type */
#endif
};
......
......@@ -754,7 +754,7 @@ static void peephole_ia32_Lea(ir_node *node)
return;
/* Frame entities should already be expressed in the offsets. */
assert(get_ia32_frame_use(node) == IA32_FRAME_USE_NONE || get_ia32_frame_ent(node));
assert(get_ia32_attr_const(node)->am_imm.kind != X86_IMM_FRAMEOFFSET);
/* We can transform Leas where the out register is the same as either the
* base or index register back to an Add or Shl. */
......
......@@ -872,9 +872,12 @@ static void set_address(ir_node *node, const x86_address_t *addr)
attr->am_imm = addr->imm;
set_ia32_am_scale(node, addr->scale);
set_ia32_am_tls_segment(node, addr->tls_segment);
set_ia32_frame_ent(node, addr->frame_entity);
if (addr->use_frame)
if (addr->imm.kind == X86_IMM_FRAMEOFFSET) {
assert(addr->use_frame);
set_ia32_frame_use(node, IA32_FRAME_USE_AUTO);
} else {
assert(!addr->use_frame);
}
}
/**
......@@ -1424,7 +1427,7 @@ static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
static bool am_has_immediates(const x86_address_t *addr)
{
return addr->imm.offset != 0 || addr->imm.entity != NULL
|| addr->frame_entity || addr->use_frame;
|| addr->use_frame;
}
typedef ir_node* (*new_shiftd_func)(dbg_info *dbgi, ir_node *block,
......@@ -3906,6 +3909,7 @@ static void store_gp(dbg_info *dbgi, ia32_address_mode_t *am, ir_node *block,
addr->base = frame;
addr->index = noreg_GP;
addr->mem = store_mem;
addr->imm = (x86_imm32_t) { .kind = X86_IMM_FRAMEOFFSET };
addr->use_frame = true;
am->op_type = ia32_AddrModeS;
am->ls_mode = store_mode;
......@@ -4093,6 +4097,7 @@ static void store_fp(dbg_info *dbgi, ia32_address_mode_t *am, ir_node *block,
addr->base = frame;
addr->index = noreg_GP;
addr->mem = mem;
addr->imm = (x86_imm32_t) { .kind = X86_IMM_FRAMEOFFSET };
addr->use_frame = true;
am->op_type = ia32_AddrModeS;
am->ls_mode = mode;
......@@ -5156,8 +5161,12 @@ static ir_node *make_load_from_frame(ir_node *const node, ir_entity *(*const get
set_irn_pinned(load, get_irn_pinned(node));
set_ia32_op_type(load, ia32_AddrModeS);
set_ia32_ls_mode(load, ia32_mode_gp);
set_ia32_am_offs_int(load, 0);
set_ia32_frame_ent(load, get_ent(irg));
ia32_attr_t *const attr = get_ia32_attr(node);
attr->am_imm = (x86_imm32_t) {
.kind = X86_IMM_FRAMEOFFSET,
.entity = get_ent(irg),
};
set_ia32_frame_use(load, IA32_FRAME_USE_AUTO);
if (get_irn_pinned(node) == op_pin_state_floats) {
assert((int)pn_ia32_xLoad_res == (int)pn_ia32_fld_res
......
......@@ -124,9 +124,10 @@ static ir_node *eat_immediates(x86_address_t *addr, ir_node *node,
if (eat_immediate(addr, right))
return eat_immediates(addr, left, x86_create_am_normal);
} else if (is_Member(node)) {
assert(addr->frame_entity == NULL);
addr->frame_entity = get_Member_entity(node);
addr->use_frame = true;
assert(addr->imm.entity == NULL);
addr->imm.entity = get_Member_entity(node);
addr->imm.kind = X86_IMM_FRAMEOFFSET;
addr->use_frame = true;
ir_node *ptr = get_Member_ptr(node);
assert(is_Start(get_Proj_pred(ptr)));
return ptr;
......
......@@ -28,7 +28,6 @@ typedef struct x86_address_t {
unsigned scale : 8; /**< An integer scale. {0,1,2,3} */
bool use_frame : 1; /**< Set, if the frame is accessed */
bool tls_segment : 1; /**< Set if AM is relative to TLS */
ir_entity *frame_entity; /**< The accessed frame entity if any. */
} x86_address_t;
/**
......
......@@ -23,6 +23,7 @@ typedef enum x86_immediate_kind_t {
X86_IMM_PICBASE_REL, /**< relative to pic base address */
X86_IMM_TLS_IE, /**< thread local storage, initial exec */
X86_IMM_TLS_LE, /**< thread local storage, load exec */
X86_IMM_FRAMEOFFSET, /**< offset to entity on stackframe */
} x86_immediate_kind_t;
typedef struct x86_imm32_t {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment