}
size_t misalign = offset % align_all;
- if(misalign > 0) {
+ if(misalign > 0 || bit_offset > 0) {
offset += align_all - misalign;
}
set_type_alignment_bytes(irtype, align_all);
{
value = do_strict_conv(dbgi, value);
- ir_node *memory = get_store();
+ ir_node *memory = get_store();
if(is_type_scalar(type)) {
ir_node *store = new_d_Store(dbgi, memory, addr, value);
}
}
+static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size)
+{
+ tarval *all_one = get_mode_all_one(mode);
+ int mode_size = get_mode_size_bits(mode);
+
+ assert(offset >= 0 && size >= 0);
+ assert(offset + size <= mode_size);
+ if(size == mode_size) {
+ return all_one;
+ }
+
+ long shiftr = get_mode_size_bits(mode) - size;
+ long shiftl = offset;
+ tarval *tv_shiftr = new_tarval_from_long(shiftr, mode_uint);
+ tarval *tv_shiftl = new_tarval_from_long(shiftl, mode_uint);
+ tarval *mask0 = tarval_shr(all_one, tv_shiftr);
+ tarval *mask1 = tarval_shl(mask0, tv_shiftl);
+
+ return mask1;
+}
+
+static void bitfield_store_to_firm(const unary_expression_t *expression,
+ ir_node *value)
+{
+ expression_t *select = expression->value;
+ assert(select->kind == EXPR_SELECT);
+ type_t *type = select->base.datatype;
+ assert(type->kind == TYPE_BITFIELD);
+ ir_mode *mode = get_ir_mode(type->bitfield.base);
+ ir_node *addr = expression_to_addr(select);
+
+ assert(get_irn_mode(value) == mode);
+
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+ /* kill upper bits of value and shift to right position */
+ ir_entity *entity = select->select.compound_entry->v.entity;
+ int bitoffset = get_entity_offset_bits_remainder(entity);
+ ir_type *entity_type = get_entity_type(entity);
+ int bitsize = get_mode_size_bits(get_type_mode(entity_type));
+
+ tarval *mask = create_bitfield_mask(mode, 0, bitsize);
+ ir_node *mask_node = new_d_Const(dbgi, mode, mask);
+ ir_node *value_masked = new_d_And(dbgi, value, mask_node, mode);
+ tarval *shiftl = new_tarval_from_long(bitoffset, mode_uint);
+ ir_node *shiftcount = new_d_Const(dbgi, mode_uint, shiftl);
+ ir_node *value_maskshift = new_d_Shl(dbgi, value_masked, shiftcount, mode);
+
+ /* load current value */
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+ tarval *shift_mask = create_bitfield_mask(mode, bitoffset, bitsize);
+ tarval *inv_mask = tarval_not(shift_mask);
+ ir_node *inv_mask_node = new_d_Const(dbgi, mode, inv_mask);
+ ir_node *load_res_masked = new_d_And(dbgi, load_res, inv_mask_node, mode);
+
+ /* construct new value and store */
+ ir_node *new_val = new_d_Or(dbgi, load_res_masked, value_maskshift, mode);
+ ir_node *store = new_d_Store(dbgi, load_mem, addr, new_val);
+ ir_node *store_mem = new_d_Proj(dbgi, store, mode_M, pn_Store_M);
+ set_store(store_mem);
+}
+
static void set_value_for_expression(const expression_t *expression,
ir_node *value)
{
}
}
+ if(expression->kind == EXPR_UNARY_BITFIELD_EXTRACT) {
+ bitfield_store_to_firm(&expression->unary, value);
+ return;
+ }
+
ir_node *addr = expression_to_addr(expression);
type_t *type = skip_typeref(expression->base.datatype);
assign_value(dbgi, addr, type, value);
}
}
+static ir_node *bitfield_extract_to_firm(const unary_expression_t *expression)
+{
+ expression_t *select = expression->value;
+ assert(select->kind == EXPR_SELECT);
+
+ type_t *type = select->base.datatype;
+ assert(type->kind == TYPE_BITFIELD);
+ ir_mode *mode = get_ir_mode(type->bitfield.base);
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *addr = expression_to_addr(select);
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+
+ load_res = create_conv(dbgi, load_res, mode_int);
+
+ set_store(load_mem);
+
+ /* kill upper bits */
+ ir_entity *entity = select->select.compound_entry->v.entity;
+ int bitoffset = get_entity_offset_bits_remainder(entity);
+ ir_type *entity_type = get_entity_type(entity);
+ int bitsize = get_mode_size_bits(get_type_mode(entity_type));
+ long shift_bitsl = machine_size - bitoffset - bitsize;
+ assert(shift_bitsl >= 0);
+ tarval *tvl = new_tarval_from_long(shift_bitsl, mode_uint);
+ ir_node *countl = new_d_Const(dbgi, mode_uint, tvl);
+ ir_node *shiftl = new_d_Shl(dbgi, load_res, countl, mode_int);
+
+ long shift_bitsr = bitoffset + shift_bitsl;
+ assert(shift_bitsr <= (long) machine_size);
+ tarval *tvr = new_tarval_from_long(shift_bitsr, mode_uint);
+ ir_node *countr = new_d_Const(dbgi, mode_uint, tvr);
+ ir_node *shiftr;
+ if(mode_is_signed(mode)) {
+ shiftr = new_d_Shrs(dbgi, shiftl, countr, mode_int);
+ } else {
+ shiftr = new_d_Shr(dbgi, shiftl, countr, mode_int);
+ }
+
+ return create_conv(dbgi, shiftr, mode);
+}
+
static ir_node *unary_expression_to_firm(const unary_expression_t *expression)
{
dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
return handle_assume(dbgi, value);
else
return NULL;
+ case EXPR_UNARY_BITFIELD_EXTRACT:
+ return bitfield_extract_to_firm(expression);
default:
break;
panic("trying to get address of non-lvalue");
}
-static ir_node *builtin_constant_to_firm(const builtin_constant_expression_t *expression)
+static ir_node *builtin_constant_to_firm(
+ const builtin_constant_expression_t *expression)
{
ir_mode *mode = get_ir_mode(expression->expression.datatype);
long v;
return new_Const_long(mode, v);
}
-static ir_node *builtin_prefetch_to_firm(const builtin_prefetch_expression_t *expression)
+static ir_node *builtin_prefetch_to_firm(
+ const builtin_prefetch_expression_t *expression)
{
ir_node *adr = expression_to_firm(expression->adr);
/* no Firm support for prefetch yet */
}
case EXPR_SELECT: {
const select_expression_t *select = &expression->select;
- type_t *orig_type = select->compound_entry->type;
- type_t *type = skip_typeref(orig_type);
- if(type->kind == TYPE_BITFIELD) {
- return type->bitfield.base;
- } else {
- return orig_type;
- }
+ return select->compound_entry->type;
}
case EXPR_UNARY_DEREFERENCE: {
expression_t *value = expression->unary.value;
}
type_t *type = declaration->type;
- type_t *skipped_type = skip_typeref(type);
- if(skipped_type->kind == TYPE_BITFIELD) {
- type = skipped_type->bitfield.base;
- }
/* we always do the auto-type conversions; the & and sizeof parser contains
* code to revert this! */
/* we always do the auto-type conversions; the & and sizeof parser contains
* code to revert this! */
type_t *expression_type = automatic_type_conversion(iter->type);
- if(expression_type->kind == TYPE_BITFIELD) {
- expression_type = expression_type->bitfield.base;
- }
select->select.compound_entry = iter;
select->base.datatype = expression_type;
+ if(expression_type->kind == TYPE_BITFIELD) {
+ expression_t *extract
+ = allocate_expression_zero(EXPR_UNARY_BITFIELD_EXTRACT);
+ extract->unary.value = select;
+ extract->base.datatype = expression_type->bitfield.base;
+
+ return extract;
+ }
+
return select;
}
return;
}
if(type_left->base.qualifiers & TYPE_QUALIFIER_CONST) {
- errorf(HERE, "assignment to readonly location '%E' (type '%T')", left, orig_type_left);
+ errorf(HERE, "assignment to readonly location '%E' (type '%T')", left,
+ orig_type_left);
return;
}
if(is_type_incomplete(type_left)) {
- errorf(HERE, "left-hand side of assignment '%E' has incomplete type '%T'", left, orig_type_left);
+ errorf(HERE,
+ "left-hand side of assignment '%E' has incomplete type '%T'",
+ left, orig_type_left);
return;
}
if(is_type_compound(type_left) && has_const_fields(&type_left->compound)) {
- errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields", left, orig_type_left);
+ errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields",
+ left, orig_type_left);
return;
}