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

simplify handling of bitfield members

We do not model them as a type anymore, but simply annotate
compound_member entities with a bit offset and bit size.
parent 13febceb
......@@ -345,18 +345,22 @@ FIRM_API const char *get_align_name(ir_align a);
/** Returns the offset of an entity (in a compound) in bytes. Only set if
* layout = fixed. */
FIRM_API int get_entity_offset(const ir_entity *ent);
FIRM_API int get_entity_offset(const ir_entity *entity);
/** Sets the offset of an entity (in a compound) in bytes. */
FIRM_API void set_entity_offset(ir_entity *ent, int offset);
FIRM_API void set_entity_offset(ir_entity *entity, int offset);
/** Returns the offset bit remainder of a bitfield entity (in a compound) in
* bits. Only set if layout = fixed. */
FIRM_API unsigned char get_entity_offset_bits_remainder(const ir_entity *ent);
/** For bitfields, returns the offset in bits to the bitfield base. */
FIRM_API unsigned get_entity_bitfield_offset(const ir_entity *entity);
/** Sets the offset bit remainder of a bitfield entity (in a compound) in bits. */
FIRM_API void set_entity_offset_bits_remainder(ir_entity *ent,
unsigned char offset);
/** Sets the offset in bits to the base for a bitfield. */
FIRM_API void set_entity_bitfield_offset(ir_entity *entity, unsigned offset);
/** Sets the size in bits for a bitfield. 0 means not a bitfield. */
FIRM_API void set_entity_bitfield_size(ir_entity *entity, unsigned size);
/** Returns the size in bits for a bitfield, 0 if entity is not a bitfield. */
FIRM_API unsigned get_entity_bitfield_size(const ir_entity *entity);
/** Returns the stored intermediate information. */
FIRM_API void *get_entity_link(const ir_entity *ent);
......@@ -1886,12 +1890,6 @@ FIRM_API ir_type *new_d_type_primitive(ir_mode *mode, type_dbg_info* db);
/** Returns true if a type is a primitive type. */
FIRM_API int is_Primitive_type(const ir_type *primitive);
/** Returns the base type of a primitive (bitfield) type or NULL if none. */
FIRM_API ir_type *get_primitive_base_type(const ir_type *tp);
/** Sets the base type of a primitive (bitfield) type. */
FIRM_API void set_primitive_base_type(ir_type *tp, ir_type *base_tp);
/**
* This type opcode marks that the corresponding type is a primitive type.
*
......
......@@ -432,22 +432,6 @@ ir_storage_class_class_t classify_pointer(const ir_node *irn,
return res;
}
/**
* If adr represents a Bitfield Sel, skip it
*/
static const ir_node *skip_Bitfield_Sels(const ir_node *adr)
{
if (is_Sel(adr)) {
ir_entity *ent = get_Sel_entity(adr);
ir_type *bf_type = get_entity_type(ent);
/* is it a bitfield type? */
if (is_Primitive_type(bf_type) && get_primitive_base_type(bf_type) != NULL)
adr = get_Sel_ptr(adr);
}
return adr;
}
/**
* Determine the alias relation between two addresses.
*
......@@ -564,16 +548,6 @@ static ir_alias_relation _get_alias_relation(
return ir_sure_alias;
}
/*
* Bitfields can be constructed as Sels from its base address.
* As they have different entities, the disambiguator would find that they are
* alias free. While this is true for its values, it is false for the addresses
* (strictly speaking, the Sel's are NOT the addresses of the bitfields).
* So, skip those bitfield selecting Sel's.
*/
adr1 = skip_Bitfield_Sels(adr1);
adr2 = skip_Bitfield_Sels(adr2);
/* skip Sels */
const ir_node *base1 = adr1;
const ir_node *base2 = adr2;
......
......@@ -673,11 +673,6 @@ static void emit_compound_type(const ir_type *type)
for (size_t i = 0; i < n_members; ++i) {
ir_entity *member = get_compound_member(type, i);
ir_type *member_type = get_entity_type(member);
if (is_Primitive_type(member_type)) {
ir_type *base = get_primitive_base_type(member_type);
if (base != NULL)
member_type = base;
}
emit_type(member_type);
}
......@@ -695,14 +690,11 @@ static void emit_compound_type(const ir_type *type)
ir_entity *member = get_compound_member(type, i);
ir_type *member_type = get_entity_type(member);
int offset = get_entity_offset(member);
ir_type *base;
if (is_Primitive_type(member_type) &&
(base = get_primitive_base_type(member_type))) {
unsigned bit_offset = get_entity_offset_bits_remainder(member);
unsigned base_size = get_type_size_bytes(base);
ir_mode *mode = get_type_mode(member_type);
unsigned bit_size = get_mode_size_bits(mode);
if (get_entity_bitfield_size(member) > 0) {
unsigned bit_offset = get_entity_bitfield_offset(member);
unsigned bit_size = get_entity_bitfield_size(member);
unsigned base_size = get_type_size_bytes(member_type);
bit_offset = base_size*8 - bit_offset - bit_size;
......@@ -710,7 +702,6 @@ static void emit_compound_type(const ir_type *type)
emit_uleb128(base_size);
emit_uleb128(bit_size);
emit_uleb128(bit_offset);
member_type = base;
} else {
emit_uleb128(abbrev_member);
}
......
......@@ -852,13 +852,13 @@ static normal_or_bitfield *glob_vals;
static size_t max_vals;
#endif
static void emit_bitfield(normal_or_bitfield *vals, size_t offset_bits,
static void emit_bitfield(normal_or_bitfield *vals, unsigned offset_bits,
unsigned bitfield_size,
const ir_initializer_t *initializer, ir_type *type)
{
static const size_t BITS_PER_BYTE = 8;
ir_mode *mode = get_type_mode(type);
ir_tarval *tv = NULL;
ir_tarval *tv = NULL;
switch (get_initializer_kind(initializer)) {
case IR_INITIALIZER_NULL:
return;
......@@ -876,14 +876,13 @@ static void emit_bitfield(normal_or_bitfield *vals, size_t offset_bits,
case IR_INITIALIZER_COMPOUND:
panic("bitfield initializer is compound");
}
if (tv == NULL) {
if (tv == NULL || tv == tarval_bad) {
panic("Couldn't get numeric value for bitfield initializer");
}
tv = tarval_convert_to(tv, get_type_mode(type));
int value_len = get_type_size_bytes(get_primitive_base_type(type));
int value_len = get_type_size_bytes(type);
size_t bit_offset = 0;
size_t end = get_mode_size_bits(mode);
size_t end = bitfield_size;
bool big_endian = be_get_backend_param()->byte_order_big_endian;
while (bit_offset < end) {
size_t src_offset = bit_offset / BITS_PER_BYTE;
......@@ -991,20 +990,13 @@ static void emit_ir_initializer(normal_or_bitfield *vals,
ir_initializer_t *sub_initializer
= get_initializer_compound_value(initializer, i);
ir_type *subtype = get_entity_type(member);
ir_mode *mode = get_type_mode(subtype);
if (mode != NULL) {
size_t offset_bits
= get_entity_offset_bits_remainder(member);
if (is_Primitive_type(subtype)
&& get_primitive_base_type(subtype) != NULL) {
emit_bitfield(&vals[offset], offset_bits,
sub_initializer, subtype);
continue;
} else {
assert(offset_bits == 0);
}
ir_type *subtype = get_entity_type(member);
unsigned bitfield_size = get_entity_bitfield_size(member);
if (bitfield_size > 0) {
unsigned offset_bits = get_entity_bitfield_offset(member);
emit_bitfield(&vals[offset], offset_bits, bitfield_size,
sub_initializer, subtype);
continue;
}
emit_ir_initializer(&vals[offset], sub_initializer, subtype);
......
......@@ -564,12 +564,18 @@ static void dump_entity_to_file_prefix(FILE *const F,
get_entity_vtable_number(ent));
}
} else { /* no entattrs */
ir_fprintf(F, "%s(%3d:%d) %+F: %s", prefix,
get_entity_offset(ent),
get_entity_offset_bits_remainder(ent), type,
get_entity_name(ent));
ir_fprintf(F, "%s %+F: %s", prefix, type, get_entity_name(ent));
if (is_Method_type(type))
fputs("(...)", F);
if (ent->entity_kind == IR_ENTITY_COMPOUND_MEMBER) {
ir_fprintf(F, " offset: %d", get_entity_offset(ent));
unsigned bitfield_size = get_entity_bitfield_size(ent);
if (bitfield_size > 0) {
unsigned bitfield_offset = get_entity_bitfield_offset(ent);
ir_fprintf(F, " bitfield offs %u size %u", bitfield_offset,
bitfield_size);
}
}
if (verbosity & dump_verbosity_accessStats) {
dump_entity_linkage(F, ent);
......@@ -594,7 +600,7 @@ static void dump_entity_to_file_prefix(FILE *const F,
fprintf(F, "\n%s aligned: %s", prefix, get_align_name(get_entity_aligned(ent)));
fprintf(F, "\n%s alignment: %u", prefix, get_entity_alignment(ent));
fprintf(F, "\n%s ld_name: %s", prefix, ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
fprintf(F, "\n%s offset: %d bytes, %d rem bits", prefix, get_entity_offset(ent), get_entity_offset_bits_remainder(ent));
fprintf(F, "\n%s offset: %d bytes", prefix, get_entity_offset(ent));
if (is_Method_type(type)) {
const ir_graph *irg = get_entity_irg(ent);
if (irg != NULL) {
......@@ -758,14 +764,6 @@ void dump_type_to_file(FILE *const F, const ir_type *const tp)
break;
case tpo_primitive:
if (verbosity & dump_verbosity_typeattrs) {
const ir_type *base_tp = get_primitive_base_type(tp);
if (base_tp != NULL)
ir_fprintf(F, "\n base type: %+F", tp);
fprintf(F, "\n");
}
break;
case tpo_none:
case tpo_unknown:
fprintf(F, "\n");
......
......@@ -559,16 +559,8 @@ static void write_type(write_env_t *env, ir_type *tp);
static void write_type_primitive(write_env_t *env, ir_type *tp)
{
ir_type *base_type = get_primitive_base_type(tp);
if (base_type != NULL)
write_type(env, base_type);
write_type_common(env, tp);
write_mode_ref(env, get_type_mode(tp));
if (base_type == NULL)
base_type = get_none_type();
write_type_ref(env, base_type);
fputc('\n', env->file);
}
......@@ -769,7 +761,8 @@ static void write_entity(write_env_t *env, ir_entity *ent)
break;
case IR_ENTITY_COMPOUND_MEMBER:
write_long(env, get_entity_offset(ent));
write_unsigned(env, get_entity_offset_bits_remainder(ent));
write_unsigned(env, get_entity_bitfield_offset(ent));
write_unsigned(env, get_entity_bitfield_size(ent));
break;
case IR_ENTITY_PARAMETER: {
size_t num = get_entity_parameter_number(ent);
......@@ -1776,11 +1769,7 @@ static void read_type(read_env_t *env)
case tpo_primitive: {
ir_mode *mode = read_mode_ref(env);
ir_type *base_type = read_type_ref(env);
type = new_type_primitive(mode);
if (base_type != get_none_type()) {
set_primitive_base_type(type, base_type);
}
goto finish_type;
}
......@@ -1880,8 +1869,9 @@ static void read_entity(read_env_t *env, ir_entity_kind kind)
entity = new_entity(owner, name, type);
if (ld_name != NULL)
set_entity_ld_ident(entity, ld_name);
set_entity_offset(entity, (int) read_long(env));
set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
set_entity_offset(entity, read_int(env));
set_entity_bitfield_offset(entity, read_unsigned(env));
set_entity_bitfield_size(entity, read_unsigned(env));
break;
case IR_ENTITY_METHOD:
entity = new_entity(owner, name, type);
......
......@@ -996,23 +996,7 @@ static unsigned optimize_load(ir_node *load)
value = find_compound_ent_value(ptr);
}
if (value != NULL) {
ir_graph *irg = get_irn_irg(load);
value = can_replace_load_by_const(load, value);
if (value != NULL && is_Sel(ptr)) {
/* frontend has inserted masking operations after bitfield accesses,
* so we might have to shift the const. */
unsigned char bit_offset = get_entity_offset_bits_remainder(get_Sel_entity(ptr));
if (bit_offset != 0) {
if (is_Const(value)) {
ir_tarval *tv_old = get_Const_tarval(value);
ir_tarval *tv_offset = new_tarval_from_long(bit_offset, mode_Bu);
ir_tarval *tv_new = tarval_shl(tv_old, tv_offset);
value = new_r_Const(irg, tv_new);
} else {
value = NULL;
}
}
}
}
}
}
......
......@@ -44,7 +44,6 @@ static ir_entity *intern_new_entity(ir_type *owner, ir_entity_kind kind,
ir_entity *res = XMALLOCZ(ir_entity);
res->kind = k_entity;
res->name = name;
res->ld_name = NULL;
res->type = type;
res->owner = owner;
......@@ -52,12 +51,7 @@ static ir_entity *intern_new_entity(ir_type *owner, ir_entity_kind kind,
res->volatility = volatility_non_volatile;
res->aligned = align_is_aligned;
res->usage = ir_usage_unknown;
res->compiler_gen = 0;
res->visibility = ir_visibility_external;
res->offset = -1;
res->offset_bit_remainder = 0;
res->alignment = 0;
res->link = NULL;
#ifdef DEBUG_libfirm
res->nr = get_irp_new_node_nr();
#endif
......@@ -90,6 +84,7 @@ ir_entity *new_d_entity(ir_type *owner, ident *name, ir_type *type,
res->attr.mtd_attr.irg = NULL;
} else if (is_compound_type(owner) && !(owner->flags & tf_segment)) {
res = intern_new_entity(owner, IR_ENTITY_COMPOUND_MEMBER, name, type, db);
res->attr.compound_member.offset = -1;
} else {
res = intern_new_entity(owner, IR_ENTITY_NORMAL, name, type, db);
}
......@@ -116,6 +111,7 @@ ir_entity *new_d_parameter_entity(ir_type *owner, size_t pos, ir_type *type,
ident *name = make_parameter_entity_name(pos);
ir_entity *res
= intern_new_entity(owner, IR_ENTITY_PARAMETER, name, type, dbgi);
res->attr.compound_member.offset = -1;
res->attr.parameter.number = pos;
hook_new_entity(res);
return res;
......@@ -717,14 +713,24 @@ void (set_entity_offset)(ir_entity *ent, int offset)
_set_entity_offset(ent, offset);
}
unsigned char (get_entity_offset_bits_remainder)(const ir_entity *ent)
unsigned (get_entity_bitfield_offset)(const ir_entity *ent)
{
return _get_entity_offset_bits_remainder(ent);
return _get_entity_bitfield_offset(ent);
}
void (set_entity_offset_bits_remainder)(ir_entity *ent, unsigned char offset)
void (set_entity_bitfield_offset)(ir_entity *ent, unsigned offset)
{
_set_entity_offset_bits_remainder(ent, offset);
_set_entity_bitfield_offset(ent, offset);
}
unsigned (get_entity_bitfield_size)(const ir_entity *ent)
{
return _get_entity_bitfield_size(ent);
}
void (set_entity_bitfield_size)(ir_entity *ent, unsigned size)
{
_set_entity_bitfield_size(ent, size);
}
void add_entity_overwrites(ir_entity *ent, ir_entity *overwritten)
......
......@@ -40,8 +40,10 @@
#define set_entity_usage(ent, flags) _set_entity_usage(ent, flags)
#define get_entity_offset(ent) _get_entity_offset(ent)
#define set_entity_offset(ent, offset) _set_entity_offset(ent, offset)
#define get_entity_offset_bits_remainder(ent) _get_entity_offset_bits_remainder(ent)
#define set_entity_offset_bits_remainder(ent, o) _set_entity_offset_bits_remainder(ent, o)
#define get_entity_bitfield_offset(ent) _get_entity_bitfield_offset(ent)
#define set_entity_bitfield_offset(ent, o) _set_entity_bitfield_offset(ent, o)
#define get_entity_bitfield_size(ent) _get_entity_bitfield_size(ent)
#define set_entity_bitfield_size(ent, s) _set_entity_bitfield_size(ent, s)
#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)
......@@ -112,7 +114,17 @@ typedef struct code_ent_attr {
ir_label_t label; /** label of the basic block */
} code_ent_attr;
typedef struct compound_member_ent_attr {
int offset; /**< Offset in bytes for this entity. Fixed
when layout of owner is determined. */
unsigned bitfield_offset; /**< for bitfields: offset in bits from base */
unsigned bitfield_size; /**< for bitfields: size of entity in bits,
0 if entity is not a bitfield. */
} compound_member_ent_attr;
typedef struct parameter_ent_attr {
compound_member_ent_attr base; /**< a parameter is also a compound_member
of the frame type. */
size_t number; /**< corresponding parameter number */
ir_mode *doubleword_low_mode;/**< entity is a lowered doubleword parameter,
so additional stores because of calling
......@@ -156,12 +168,6 @@ struct ir_entity {
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. */
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. */
......@@ -179,12 +185,14 @@ struct ir_entity {
#endif
union {
/* ------------- fields for method entities ---------------- */
method_ent_attr mtd_attr;
/* fields for code entities */
code_ent_attr code_attr;
/** attributes for method entities */
method_ent_attr mtd_attr;
/** fields for code entities */
code_ent_attr code_attr;
/** compound member attributes */
compound_member_ent_attr compound_member;
/** parameter number for parameter entities */
parameter_ent_attr parameter;
parameter_ent_attr parameter;
} attr; /**< type specific attributes */
};
......@@ -330,26 +338,44 @@ static inline void _set_entity_usage(ir_entity *ent, ir_entity_usage state)
static inline int _get_entity_offset(const ir_entity *ent)
{
assert(ent->kind == k_entity);
return ent->offset;
assert(ent->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| ent->entity_kind == IR_ENTITY_PARAMETER);
return ent->attr.compound_member.offset;
}
static inline void _set_entity_offset(ir_entity *ent, int offset)
{
assert(ent->kind == k_entity);
ent->offset = offset;
assert(ent->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| ent->entity_kind == IR_ENTITY_PARAMETER);
ent->attr.compound_member.offset = offset;
}
static inline unsigned char _get_entity_offset_bits_remainder(const ir_entity *ent)
static inline unsigned _get_entity_bitfield_offset(const ir_entity *ent)
{
assert(ent->kind == k_entity);
return ent->offset_bit_remainder;
assert(ent->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| ent->entity_kind == IR_ENTITY_PARAMETER);
return ent->attr.compound_member.bitfield_offset;
}
static inline void _set_entity_offset_bits_remainder(ir_entity *ent, unsigned char offset)
static inline void _set_entity_bitfield_offset(ir_entity *ent, unsigned offset)
{
assert(ent->kind == k_entity);
ent->offset_bit_remainder = offset;
assert(ent->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| ent->entity_kind == IR_ENTITY_PARAMETER);
ent->attr.compound_member.bitfield_offset = offset;
}
static inline unsigned _get_entity_bitfield_size(const ir_entity *entity)
{
assert(entity->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| entity->entity_kind == IR_ENTITY_PARAMETER);
return entity->attr.compound_member.bitfield_size;
}
static inline void _set_entity_bitfield_size(ir_entity *entity, unsigned size)
{
assert(entity->entity_kind == IR_ENTITY_COMPOUND_MEMBER
|| entity->entity_kind == IR_ENTITY_PARAMETER);
entity->attr.compound_member.bitfield_size = size;
}
static inline void *_get_entity_link(const ir_entity *ent)
......
......@@ -159,7 +159,7 @@ void init_tpop(void)
type_array = new_tpop(tpo_array , ID("array"), 0, sizeof(arr_attr), &array_ops);
type_enumeration = new_tpop(tpo_enumeration, ID("enumeration"), 0, sizeof(enm_attr), &enum_ops);
type_pointer = new_tpop(tpo_pointer , ID("pointer"), 0, sizeof(ptr_attr), &pointer_ops);
type_primitive = new_tpop(tpo_primitive , ID("primitive"), 0, sizeof(pri_attr), &null_ops);
type_primitive = new_tpop(tpo_primitive , ID("primitive"), 0, 0, &null_ops);
tpop_code = new_tpop(tpo_code , ID("code"), 0, 0, &null_ops);
tpop_none = new_tpop(tpo_none , ID("None"), 0, 0, &pseudo_ops);
tpop_unknown = new_tpop(tpo_unknown , ID("Unknown"), 0, 0, &pseudo_ops);
......
......@@ -1478,7 +1478,6 @@ ir_type *new_d_type_primitive(ir_mode *mode, type_dbg_info *db)
ir_type *res = new_type(type_primitive, mode, db);
res->size = get_mode_size_bytes(mode);
res->flags |= tf_layout_fixed;
res->attr.ba.base_type = NULL;
hook_new_type(res);
return res;
}
......@@ -1503,19 +1502,6 @@ void set_primitive_mode(ir_type *tp, ir_mode *mode)
tp->mode = mode;
}
ir_type *get_primitive_base_type(const ir_type *tp)
{
assert(is_Primitive_type(tp));
return tp->attr.ba.base_type;
}
void set_primitive_base_type(ir_type *tp, ir_type *base_tp)
{
assert(is_Primitive_type(tp));
tp->attr.ba.base_type = base_tp;
}
int (is_atomic_type)(const ir_type *tp)
{
......@@ -1658,6 +1644,10 @@ void default_layout_compound_type(ir_type *type)
if (is_Method_type(entity_type))
continue;
if (get_entity_bitfield_size(entity) > 0) {
panic("default_layout_compound_type() cannot handle bitfield members (in %+F)", type);
}
unsigned entity_size;
if (i+1 < n || !var_size) {
assert(get_type_state(entity_type) == layout_fixed);
......
......@@ -140,11 +140,6 @@ typedef struct {
ir_type *points_to; /**< The type of the ir_entity the pointer points to. */
} ptr_attr;
/** Primitive type attributes. */
typedef struct {
ir_type *base_type; /**< For bitfield types: The base primitive type, NULL else. */
} pri_attr;
/** General type attributes. */
typedef union {
cls_attr ca; /**< Attributes of a class type */
......@@ -154,7 +149,6 @@ typedef union {
arr_attr aa; /**< Attributes of an array type */
enm_attr ea; /**< Attributes of an enumeration type */
ptr_attr pa; /**< Attributes of a pointer type */
pri_attr ba; /**< Attributes of a primitive bitfield type */
} tp_attr;
/** Additional type flags. */
......
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