+static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
+ ir_node *addr)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ type_t *type = expression->base.type;
+ ir_mode *mode = get_ir_mode_storage(type);
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode, cons_none);
+ 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 */
+ assert(expression->compound_entry->kind == ENTITY_COMPOUND_MEMBER);
+ ir_entity *entity = expression->compound_entry->compound_member.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, 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, 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);
+}
+
+/* make sure the selected compound type is constructed */
+static void construct_select_compound(const select_expression_t *expression)
+{
+ type_t *type = skip_typeref(expression->compound->base.type);
+ if (is_type_pointer(type)) {
+ type = type->pointer.points_to;
+ }
+ (void) get_ir_type(type);
+}
+
+static ir_node *set_value_for_expression_addr(const expression_t *expression,
+ ir_node *value, ir_node *addr)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ type_t *type = skip_typeref(expression->base.type);
+
+ if (!is_type_compound(type)) {
+ ir_mode *mode = get_ir_mode_storage(type);
+ value = create_conv(dbgi, value, mode);
+ value = do_strict_conv(dbgi, value);
+ }
+
+ if (expression->kind == EXPR_REFERENCE) {
+ const reference_expression_t *ref = &expression->reference;
+
+ entity_t *entity = ref->entity;
+ assert(is_declaration(entity));
+ assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ set_value(entity->variable.v.value_number, value);
+ return value;
+ } else if (entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
+ set_value(entity->parameter.v.value_number, value);
+ return value;
+ }
+ }
+
+ if (addr == NULL)
+ addr = expression_to_addr(expression);
+ assert(addr != NULL);
+
+ if (expression->kind == EXPR_SELECT) {
+ const select_expression_t *select = &expression->select;
+
+ construct_select_compound(select);
+
+ entity_t *entity = select->compound_entry;
+ assert(entity->kind == ENTITY_COMPOUND_MEMBER);
+ if (entity->declaration.type->kind == TYPE_BITFIELD) {
+ ir_entity *irentity = entity->compound_member.entity;
+ bool set_volatile
+ = select->base.type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
+ value = bitfield_store_to_firm(dbgi, irentity, addr, value,
+ set_volatile);
+ return value;
+ }
+ }
+
+ assign_value(dbgi, addr, type, value);
+ return value;
+}
+
+static void set_value_for_expression(const expression_t *expression,
+ ir_node *value)
+{
+ set_value_for_expression_addr(expression, value, NULL);
+}
+
+static ir_node *get_value_from_lvalue(const expression_t *expression,
+ ir_node *addr)
+{
+ if (expression->kind == EXPR_REFERENCE) {
+ const reference_expression_t *ref = &expression->reference;
+
+ entity_t *entity = ref->entity;
+ assert(entity->kind == ENTITY_VARIABLE
+ || entity->kind == ENTITY_PARAMETER);
+ assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+ int value_number;
+ if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+ value_number = entity->variable.v.value_number;
+ assert(addr == NULL);
+ type_t *type = skip_typeref(expression->base.type);
+ ir_mode *mode = get_ir_mode_storage(type);
+ ir_node *res = get_value(value_number, mode);
+ return create_conv(NULL, res, get_ir_mode_arithmetic(type));
+ } else if (entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
+ value_number = entity->parameter.v.value_number;
+ assert(addr == NULL);
+ type_t *type = skip_typeref(expression->base.type);
+ ir_mode *mode = get_ir_mode_storage(type);
+ ir_node *res = get_value(value_number, mode);
+ return create_conv(NULL, res, get_ir_mode_arithmetic(type));
+ }
+ }
+
+ assert(addr != NULL);
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+
+ ir_node *value;
+ if (expression->kind == EXPR_SELECT &&
+ expression->select.compound_entry->declaration.type->kind == TYPE_BITFIELD){
+ construct_select_compound(&expression->select);
+ value = bitfield_extract_to_firm(&expression->select, addr);
+ } else {
+ value = deref_address(dbgi, expression->base.type, addr);
+ }
+
+ return value;