another iteration of the struct layout code
[cparser] / ast2firm.c
index f827514..accf196 100644 (file)
@@ -323,13 +323,13 @@ static ir_type *create_complex_type(const complex_type_t *type)
 /**
  * Creates a Firm type for an imaginary type
  */
-static ir_type *create_imaginary_type(const imaginary_type_t *type)
+static ir_type *create_imaginary_type(imaginary_type_t *type)
 {
        atomic_type_kind_t  kind      = type->akind;
        ir_mode            *mode      = atomic_modes[kind];
        ident              *id        = get_mode_ident(mode);
        ir_type            *irtype    = new_type_primitive(id, mode);
-       il_alignment_t      alignment = get_type_alignment((const type_t*) type);
+       il_alignment_t      alignment = get_type_alignment((type_t*) type);
 
        set_type_alignment_bytes(irtype, alignment);
 
@@ -563,13 +563,8 @@ enum {
 
 /**
  * Construct firm type from ast struct type.
- *
- * As anonymous inner structs get flattened to a single firm type, we might get
- * irtype, outer_offset and out_align passed (they represent the position of
- * the anonymous inner struct inside the resulting firm struct)
  */
-static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
-                                     size_t *outer_offset, size_t *outer_align,
+static ir_type *create_compound_type(compound_type_t *type,
                                      bool incomplete, bool is_union)
 {
        compound_t *compound = type->compound;
@@ -578,41 +573,38 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                return compound->irtype;
        }
 
-       size_t align_all  = 1;
-       size_t offset     = 0;
-       size_t bit_offset = 0;
-       size_t size       = 0;
-
-       if (irtype == NULL) {
-               symbol_t *symbol = compound->base.symbol;
-               ident    *id;
-               if (symbol != NULL) {
-                       id = new_id_from_str(symbol->string);
-               } else {
-                       if (is_union) {
-                               id = id_unique("__anonymous_union.%u");
-                       } else {
-                               id = id_unique("__anonymous_struct.%u");
-                       }
-               }
-               dbg_info *dbgi = get_dbg_info(&compound->base.source_position);
-
+       symbol_t *symbol = compound->base.symbol;
+       ident    *id;
+       if (symbol != NULL) {
+               id = new_id_from_str(symbol->string);
+       } else {
                if (is_union) {
-                       irtype = new_d_type_union(id, dbgi);
+                       id = id_unique("__anonymous_union.%u");
                } else {
-                       irtype = new_d_type_struct(id, dbgi);
+                       id = id_unique("__anonymous_struct.%u");
                }
+       }
+       dbg_info *dbgi = get_dbg_info(&compound->base.source_position);
 
-               compound->irtype_complete = false;
-               compound->irtype          = irtype;
+       ir_type *irtype;
+       if (is_union) {
+               irtype = new_d_type_union(id, dbgi);
        } else {
-               offset    = *outer_offset;
-               align_all = *outer_align;
+               irtype = new_d_type_struct(id, dbgi);
        }
 
+       compound->irtype_complete = false;
+       compound->irtype          = irtype;
+
        if (incomplete)
                return irtype;
 
+       if (is_union) {
+               layout_union_type(type);
+       } else {
+               layout_struct_type(type);
+       }
+
        compound->irtype_complete = true;
 
        entity_t *entry = compound->members.entities;
@@ -620,128 +612,37 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
                if (entry->kind != ENTITY_COMPOUND_MEMBER)
                        continue;
 
-               size_t prev_offset = offset;
-
                symbol_t *symbol     = entry->base.symbol;
-               type_t   *entry_type = skip_typeref(entry->declaration.type);
-               dbg_info *dbgi       = get_dbg_info(&entry->base.source_position);
-
+               type_t   *entry_type = entry->declaration.type;
                ident    *ident;
-               if (symbol != NULL) {
-                       ident = new_id_from_str(symbol->string);
-               } else {
-                       if (entry_type->kind == TYPE_COMPOUND_STRUCT) {
-                               create_compound_type(&entry_type->compound, irtype, &offset,
-                                                    &align_all, false, COMPOUND_IS_STRUCT);
-                               goto finished_member;
-                       } else if (entry_type->kind == TYPE_COMPOUND_UNION) {
-                               create_compound_type(&entry_type->compound, irtype, &offset,
-                                                    &align_all, false, COMPOUND_IS_UNION);
-                               goto finished_member;
-                       } else {
-                               assert(entry_type->kind == TYPE_BITFIELD);
-                       }
+               if (symbol == NULL) {
+                       /* anonymous bitfield member, skip */
+                       if (entry_type->kind == TYPE_BITFIELD)
+                               continue;
+                       assert(entry_type->kind == TYPE_COMPOUND_STRUCT
+                                       || entry_type->kind == TYPE_COMPOUND_UNION);
                        ident = id_unique("anon.%u");
-               }
-
-               ir_type *base_irtype;
-               if (entry_type->kind == TYPE_BITFIELD) {
-                       base_irtype = get_ir_type(entry_type->bitfield.base_type);
                } else {
-                       base_irtype = get_ir_type(entry_type);
+                       ident = new_id_from_str(symbol->string);
                }
 
-               size_t entry_alignment = get_type_alignment_bytes(base_irtype);
-               size_t misalign        = offset % entry_alignment;
+               dbg_info *dbgi       = get_dbg_info(&entry->base.source_position);
 
                ir_type   *entry_irtype = get_ir_type(entry_type);
                ir_entity *entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
 
-               size_t base;
-               size_t bits_remainder;
-               if (entry_type->kind == TYPE_BITFIELD) {
-                       size_t size_bits      = entry_type->bitfield.bit_size;
-                       size_t rest_size_bits = (entry_alignment - misalign)*8 - bit_offset;
-
-                       if (size_bits > rest_size_bits) {
-                               /* start a new bucket */
-                               offset     += entry_alignment - misalign;
-                               bit_offset  = 0;
-
-                               base           = offset;
-                               bits_remainder = 0;
-                       } else {
-                               /* put into current bucket */
-                               base           = offset - misalign;
-                               bits_remainder = misalign * 8 + bit_offset;
-                       }
-
-                       offset     += size_bits / 8;
-                       bit_offset  = bit_offset + (size_bits % 8);
-               } else {
-                       size_t entry_size = get_type_size_bytes(base_irtype);
-                       if (misalign > 0 || bit_offset > 0)
-                               offset += entry_alignment - misalign;
-
-                       base           = offset;
-                       bits_remainder = 0;
-                       offset        += entry_size;
-                       bit_offset     = 0;
-               }
-
-               if (entry_alignment > align_all) {
-                       if (entry_alignment % align_all != 0) {
-                               panic("uneven alignments not supported yet");
-                       }
-                       align_all = entry_alignment;
-               }
-
-               set_entity_offset(entity, base);
+               set_entity_offset(entity, entry->compound_member.offset);
                set_entity_offset_bits_remainder(entity,
-                                                (unsigned char) bits_remainder);
-               //add_struct_member(irtype, entity);
-               entry->declaration.kind = DECLARATION_KIND_COMPOUND_MEMBER;
-               assert(entry->compound_member.entity == NULL);
-               entry->compound_member.entity = entity;
+                                                entry->compound_member.bit_offset);
 
-finished_member:
-               if (is_union) {
-                       size_t entry_size = offset - prev_offset;
-                       if (entry_size > size) {
-                               size = entry_size;
-                       }
-                       offset     = 0;
-                       bit_offset = 0;
-               }
-       }
-
-       if (!is_union) {
-               size = offset;
-       }
-
-       size_t misalign = offset % align_all;
-       if (misalign > 0 || bit_offset > 0) {
-               size += align_all - misalign;
+               assert(entry->declaration.kind == DECLARATION_KIND_UNKNOWN);
+               entry->declaration.kind       = DECLARATION_KIND_COMPOUND_MEMBER;
+               entry->compound_member.entity = entity;
        }
 
-       if (outer_offset != NULL) {
-               if (!is_union) {
-                       *outer_offset = offset;
-               } else {
-                       *outer_offset += size;
-               }
-
-               if (align_all > *outer_align) {
-                       if (align_all % *outer_align != 0) {
-                               panic("uneven alignments not supported yet");
-                       }
-                       *outer_align = align_all;
-               }
-       } else {
-               set_type_alignment_bytes(irtype, align_all);
-               set_type_size_bytes(irtype, size);
-               set_type_state(irtype, layout_fixed);
-       }
+       set_type_alignment_bytes(irtype, compound->alignment);
+       set_type_size_bytes(irtype, compound->size);
+       set_type_state(irtype, layout_fixed);
 
        return irtype;
 }
@@ -792,11 +693,9 @@ static ir_type *get_ir_type_incomplete(type_t *type)
 
        switch (type->kind) {
        case TYPE_COMPOUND_STRUCT:
-               return create_compound_type(&type->compound, NULL, NULL, NULL,
-                                           true, COMPOUND_IS_STRUCT);
+               return create_compound_type(&type->compound, true, COMPOUND_IS_STRUCT);
        case TYPE_COMPOUND_UNION:
-               return create_compound_type(&type->compound, NULL, NULL, NULL,
-                                           true, COMPOUND_IS_UNION);
+               return create_compound_type(&type->compound, true, COMPOUND_IS_UNION);
        default:
                return get_ir_type(type);
        }
@@ -841,12 +740,10 @@ ir_type *get_ir_type(type_t *type)
                firm_type = create_array_type(&type->array);
                break;
        case TYPE_COMPOUND_STRUCT:
-               firm_type = create_compound_type(&type->compound, NULL, NULL, NULL,
-                                                false, COMPOUND_IS_STRUCT);
+               firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_STRUCT);
                break;
        case TYPE_COMPOUND_UNION:
-               firm_type = create_compound_type(&type->compound, NULL, NULL, NULL,
-                                                false, COMPOUND_IS_UNION);
+               firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_UNION);
                break;
        case TYPE_ENUM:
                firm_type = create_enum_type(&type->enumt);
@@ -1037,8 +934,8 @@ static bool is_main(entity_t *entity)
 static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
 {
        assert(entity->kind == ENTITY_FUNCTION);
-       if (entity->function.entity != NULL) {
-               return entity->function.entity;
+       if (entity->function.irentity != NULL) {
+               return entity->function.irentity;
        }
 
        if (is_main(entity)) {
@@ -1140,8 +1037,8 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
        entitymap_insert(&entitymap, symbol, irentity);
 
 entity_created:
-       entity->declaration.kind = DECLARATION_KIND_FUNCTION;
-       entity->function.entity  = irentity;
+       entity->declaration.kind  = DECLARATION_KIND_FUNCTION;
+       entity->function.irentity = irentity;
 
        return irentity;
 }
@@ -1354,6 +1251,7 @@ static ir_node *string_to_firm(const source_position_t *const src_pos,
        set_entity_ld_ident(entity, id);
        set_entity_variability(entity, variability_constant);
        set_entity_allocation(entity, allocation_static);
+       set_entity_visibility(entity, visibility_local);
 
        ir_type *const elem_type = ir_type_const_char;
        ir_mode *const mode      = get_type_mode(elem_type);
@@ -1587,16 +1485,16 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
 
                        return res;
                }
-               return create_symconst(dbgi, mode, entity->function.entity);
+               return create_symconst(dbgi, mode, entity->function.irentity);
        }
        case DECLARATION_KIND_INNER_FUNCTION: {
                ir_mode *const mode = get_ir_mode_storage(type);
                if (!entity->function.goto_to_outer && !entity->function.need_closure) {
                        /* inner function not using the closure */
-                       return create_symconst(dbgi, mode, entity->function.entity);
+                       return create_symconst(dbgi, mode, entity->function.irentity);
                } else {
                        /* need trampoline here */
-                       return create_trampoline(dbgi, mode, entity->function.entity);
+                       return create_trampoline(dbgi, mode, entity->function.irentity);
                }
        }
        case DECLARATION_KIND_GLOBAL_VARIABLE: {
@@ -1667,7 +1565,7 @@ static ir_node *reference_addr(const reference_expression_t *ref)
        case DECLARATION_KIND_FUNCTION: {
                type_t  *const type = skip_typeref(entity->declaration.type);
                ir_mode *const mode = get_ir_mode_storage(type);
-               return create_symconst(dbgi, mode, entity->function.entity);
+               return create_symconst(dbgi, mode, entity->function.irentity);
        }
 
        case DECLARATION_KIND_INNER_FUNCTION: {
@@ -1675,10 +1573,10 @@ static ir_node *reference_addr(const reference_expression_t *ref)
                ir_mode *const mode = get_ir_mode_storage(type);
                if (!entity->function.goto_to_outer && !entity->function.need_closure) {
                        /* inner function not using the closure */
-                       return create_symconst(dbgi, mode, entity->function.entity);
+                       return create_symconst(dbgi, mode, entity->function.irentity);
                } else {
                        /* need trampoline here */
-                       return create_trampoline(dbgi, mode, entity->function.entity);
+                       return create_trampoline(dbgi, mode, entity->function.irentity);
                }
        }
 
@@ -1818,8 +1716,8 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                return NULL;
        case bk_gnu_builtin_frame_address: {
                expression_t *const expression = call->arguments->expression;
-               long val = fold_constant(expression);
-               if (val == 0) {
+               bool val = fold_constant_to_bool(expression);
+               if (!val) {
                        /* the nice case */
                        return get_irg_frame(current_ir_graph);
                } else {
@@ -1956,28 +1854,32 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                const reference_expression_t *ref    = &function->reference;
                entity_t                     *entity = ref->entity;
 
-               if (ref->entity->kind == ENTITY_FUNCTION &&
-                   ref->entity->function.btk != bk_none) {
-                       return process_builtin_call(call);
-               }
+               if (entity->kind == ENTITY_FUNCTION) {
+                       if (entity->function.btk != bk_none) {
+                               return process_builtin_call(call);
+                       }
 
-               if (entity->kind == ENTITY_FUNCTION
-                               && entity->function.entity == rts_entities[rts_alloca]) {
-                       /* handle alloca() call */
-                       expression_t *argument = call->arguments->expression;
-                       ir_node      *size     = expression_to_firm(argument);
-                       ir_mode      *mode     = get_ir_mode_arithmetic(type_size_t);
+                       ir_entity *irentity = entity->function.irentity;
+                       if (irentity == NULL)
+                               irentity = get_function_entity(entity, NULL);
 
-                       size = create_conv(dbgi, size, mode);
+                       if (irentity == rts_entities[rts_alloca]) {
+                               /* handle alloca() call */
+                               expression_t *argument = call->arguments->expression;
+                               ir_node      *size     = expression_to_firm(argument);
+                               ir_mode      *mode     = get_ir_mode_arithmetic(type_size_t);
 
-                       ir_node  *store  = get_store();
-                       ir_node  *alloca = new_d_Alloc(dbgi, store, size, firm_unknown_type,
-                                                      stack_alloc);
-                       ir_node  *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
-                       set_store(proj_m);
-                       ir_node  *res    = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+                               size = create_conv(dbgi, size, mode);
 
-                       return res;
+                               ir_node  *store  = get_store();
+                               ir_node  *alloca = new_d_Alloc(dbgi, store, size,
+                                                              firm_unknown_type, stack_alloc);
+                               ir_node  *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
+                               set_store(proj_m);
+                               ir_node  *res    = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+
+                               return res;
+                       }
                }
        }
        ir_node *callee = expression_to_firm(function);
@@ -2771,22 +2673,22 @@ static ir_node *create_lazy_op(const binary_expression_t *expression)
        ir_mode  *mode = get_ir_mode_arithmetic(type);
 
        if (is_constant_expression(expression->left)) {
-               long val = fold_constant(expression->left);
+               bool val = fold_constant_to_bool(expression->left);
                expression_kind_t ekind = expression->base.kind;
                assert(ekind == EXPR_BINARY_LOGICAL_AND || ekind == EXPR_BINARY_LOGICAL_OR);
                if (ekind == EXPR_BINARY_LOGICAL_AND) {
-                       if (val == 0) {
+                       if (!val) {
                                return new_Const(get_mode_null(mode));
                        }
                } else {
-                       if (val != 0) {
+                       if (val) {
                                return new_Const(get_mode_one(mode));
                        }
                }
 
                if (is_constant_expression(expression->right)) {
-                       long const valr = fold_constant(expression->right);
-                       return valr != 0 ?
+                       bool valr = fold_constant_to_bool(expression->right);
+                       return valr ?
                                new_Const(get_mode_one(mode)) :
                                new_Const(get_mode_null(mode));
                }
@@ -2960,7 +2862,7 @@ static long get_offsetof_offset(const offsetof_expression_t *expression)
                        assert(designator->array_index != NULL);
                        assert(is_type_array(type));
 
-                       long index         = fold_constant(array_index);
+                       long index         = fold_constant_to_int(array_index);
                        ir_type *arr_type  = get_ir_type(type);
                        ir_type *elem_type = get_array_element_type(arr_type);
                        long     elem_size = get_type_size_bytes(elem_type);
@@ -3086,11 +2988,8 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
 
 static void init_ir_types(void);
 
-long fold_constant(const expression_t *expression)
+static tarval *fold_constant_to_tarval(const expression_t *expression)
 {
-       if (expression->kind == EXPR_INVALID)
-               return 0;
-
        assert(is_type_valid(skip_typeref(expression->base.type)));
 
        bool constant_folding_old = constant_folding;
@@ -3110,23 +3009,40 @@ long fold_constant(const expression_t *expression)
                panic("couldn't fold constant");
        }
 
+       constant_folding = constant_folding_old;
+
        tarval *tv = get_Const_tarval(cnst);
+       return tv;
+}
+
+long fold_constant_to_int(const expression_t *expression)
+{
+       if (expression->kind == EXPR_INVALID)
+               return 0;
+
+       tarval *tv = fold_constant_to_tarval(expression);
        if (!tarval_is_long(tv)) {
                panic("result of constant folding is not integer");
        }
 
-       constant_folding = constant_folding_old;
-
        return get_tarval_long(tv);
 }
 
+bool fold_constant_to_bool(const expression_t *expression)
+{
+       if (expression->kind == EXPR_INVALID)
+               return false;
+       tarval *tv = fold_constant_to_tarval(expression);
+       return !tarval_is_null(tv);
+}
+
 static ir_node *conditional_to_firm(const conditional_expression_t *expression)
 {
        dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
 
        /* first try to fold a constant condition */
        if (is_constant_expression(expression->condition)) {
-               long val = fold_constant(expression->condition);
+               bool val = fold_constant_to_bool(expression->condition);
                if (val) {
                        expression_t *true_expression = expression->true_expression;
                        if (true_expression == NULL)
@@ -3727,10 +3643,10 @@ static ir_node *create_condition_evaluation(const expression_t *expression,
        if (is_builtin_expect(expression) && is_Cond(cond)) {
                call_argument_t *argument = expression->call.arguments->next;
                if (is_constant_expression(argument->expression)) {
-                       long               cnst = fold_constant(argument->expression);
+                       bool             cnst = fold_constant_to_bool(argument->expression);
                        cond_jmp_predicate pred;
 
-                       if (cnst == 0) {
+                       if (cnst == false) {
                                pred = COND_JMP_PRED_FALSE;
                        } else {
                                pred = COND_JMP_PRED_TRUE;
@@ -3953,7 +3869,7 @@ static void walk_designator(type_path_t *path, const designator_t *designator)
                        assert(designator->array_index != NULL);
                        assert(is_type_array(type));
 
-                       long index = fold_constant(array_index);
+                       long index = fold_constant_to_int(array_index);
                        assert(index >= 0);
 #ifndef NDEBUG
                        if (type->array.size_constant) {
@@ -4883,7 +4799,7 @@ static void while_statement_to_firm(while_statement_t *statement)
 
        /* shortcut for while(true) */
        if (is_constant_expression(statement->condition)
-                       && fold_constant(statement->condition) != 0) {
+                       && fold_constant_to_bool(statement->condition) != 0) {
                set_cur_block(header_block);
                ir_node *header_jmp = new_Jmp();
                add_immBlock_pred(body_block, header_jmp);
@@ -5789,6 +5705,10 @@ static void create_function(entity_t *entity)
        if (entity->function.statement == NULL)
                return;
 
+       if (is_main(entity) && firm_opt.os_support == OS_SUPPORT_MINGW) {
+               prepare_main_collect2(entity);
+       }
+
        inner_functions     = NULL;
        current_trampolines = NULL;