add more definitions for __builtin___XXX_chk
[cparser] / type.c
diff --git a/type.c b/type.c
index de4738d..8749b21 100644 (file)
--- a/type.c
+++ b/type.c
@@ -52,6 +52,44 @@ struct atomic_type_properties_t {
        unsigned   flags;             /**< type flags from atomic_type_flag_t */
 };
 
+/**
+ * Returns the size of a type node.
+ *
+ * @param kind  the type kind
+ */
+static size_t get_type_struct_size(type_kind_t kind)
+{
+       static const size_t sizes[] = {
+               [TYPE_ATOMIC]          = sizeof(atomic_type_t),
+               [TYPE_COMPLEX]         = sizeof(complex_type_t),
+               [TYPE_IMAGINARY]       = sizeof(imaginary_type_t),
+               [TYPE_BITFIELD]        = sizeof(bitfield_type_t),
+               [TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
+               [TYPE_COMPOUND_UNION]  = sizeof(compound_type_t),
+               [TYPE_ENUM]            = sizeof(enum_type_t),
+               [TYPE_FUNCTION]        = sizeof(function_type_t),
+               [TYPE_POINTER]         = sizeof(pointer_type_t),
+               [TYPE_ARRAY]           = sizeof(array_type_t),
+               [TYPE_BUILTIN]         = sizeof(builtin_type_t),
+               [TYPE_TYPEDEF]         = sizeof(typedef_type_t),
+               [TYPE_TYPEOF]          = sizeof(typeof_type_t),
+       };
+       assert(lengthof(sizes) == (int)TYPE_TYPEOF + 1);
+       assert(kind <= TYPE_TYPEOF);
+       assert(sizes[kind] != 0);
+       return sizes[kind];
+}
+
+type_t *allocate_type_zero(type_kind_t kind)
+{
+       size_t  size = get_type_struct_size(kind);
+       type_t *res  = obstack_alloc(type_obst, size);
+       memset(res, 0, size);
+       res->base.kind = kind;
+
+       return res;
+}
+
 /**
  * Properties of atomic types.
  */
@@ -189,9 +227,9 @@ void init_types(void)
        props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 4;
        props[ATOMIC_TYPE_LONGLONG].alignment    = 4;
        props[ATOMIC_TYPE_ULONGLONG].alignment   = 4;
-       if (firm_opt.os_support == OS_SUPPORT_MACHO) {
-               props[ATOMIC_TYPE_LONG_DOUBLE].size      = 16;
-               props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 16;
+       if (force_long_double_size > 0) {
+               props[ATOMIC_TYPE_LONG_DOUBLE].size      = force_long_double_size;
+               props[ATOMIC_TYPE_LONG_DOUBLE].alignment = force_long_double_size;
        }
 
        /* TODO: make this configurable for platforms which do not use byte sized
@@ -752,34 +790,6 @@ void print_type_ext(const type_t *const type, const symbol_t *symbol,
        }
 }
 
-/**
- * Return the size of a type AST node.
- *
- * @param type  The type.
- */
-static size_t get_type_struct_size(const type_t *type)
-{
-       switch(type->kind) {
-       case TYPE_ATOMIC:          return sizeof(atomic_type_t);
-       case TYPE_COMPLEX:         return sizeof(complex_type_t);
-       case TYPE_IMAGINARY:       return sizeof(imaginary_type_t);
-       case TYPE_COMPOUND_STRUCT:
-       case TYPE_COMPOUND_UNION:  return sizeof(compound_type_t);
-       case TYPE_ENUM:            return sizeof(enum_type_t);
-       case TYPE_FUNCTION:        return sizeof(function_type_t);
-       case TYPE_POINTER:         return sizeof(pointer_type_t);
-       case TYPE_REFERENCE:       return sizeof(reference_type_t);
-       case TYPE_ARRAY:           return sizeof(array_type_t);
-       case TYPE_BUILTIN:         return sizeof(builtin_type_t);
-       case TYPE_TYPEDEF:         return sizeof(typedef_type_t);
-       case TYPE_TYPEOF:          return sizeof(typeof_type_t);
-       case TYPE_BITFIELD:        return sizeof(bitfield_type_t);
-       case TYPE_ERROR:           panic("error type found");
-       case TYPE_INVALID:         panic("invalid type found");
-       }
-       panic("unknown type found");
-}
-
 /**
  * Duplicates a type.
  *
@@ -790,7 +800,7 @@ static size_t get_type_struct_size(const type_t *type)
  */
 type_t *duplicate_type(const type_t *type)
 {
-       size_t size = get_type_struct_size(type);
+       size_t size = get_type_struct_size(type->kind);
 
        type_t *copy = obstack_alloc(type_obst, size);
        memcpy(copy, type, size);
@@ -999,9 +1009,9 @@ bool is_type_scalar(const type_t *type)
        assert(!is_typeref(type));
 
        switch (type->kind) {
-               case TYPE_POINTER: return true;
-               case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
-               default:           break;
+       case TYPE_POINTER: return true;
+       case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
+       default:           break;
        }
 
        return is_type_arithmetic(type);
@@ -1672,6 +1682,57 @@ type_t *make_array_type(type_t *element_type, size_t size,
        return identify_new_type(type);
 }
 
+static entity_t *pack_bitfield_members_big_endian(il_size_t *struct_offset,
+               il_alignment_t *struct_alignment, bool packed, entity_t *first)
+{
+       type_t        *current_base_type = NULL;
+       il_size_t      offset            = *struct_offset;
+       il_alignment_t alignment         = *struct_alignment;
+       size_t         bit_offset        = 0;
+
+       if (packed)
+               panic("packed bitfields on big-endian arch not supported yet");
+
+       entity_t *member;
+       for (member = first; member != NULL; member = member->base.next) {
+               if (member->kind != ENTITY_COMPOUND_MEMBER)
+                       continue;
+
+               type_t *type = member->declaration.type;
+               if (type->kind != TYPE_BITFIELD)
+                       break;
+
+               size_t  bit_size  = type->bitfield.bit_size;
+               type_t *base_type = skip_typeref(type->bitfield.base_type);
+
+               /* see if we need to start a new "bucket" */
+               if (base_type != current_base_type || bit_size > bit_offset) {
+                       if (current_base_type != NULL)
+                               offset += get_type_size(current_base_type);
+
+                       current_base_type = base_type;
+                       il_alignment_t base_alignment = get_type_alignment(base_type);
+                       il_alignment_t alignment_mask = base_alignment-1;
+                       if (base_alignment > alignment)
+                               alignment = base_alignment;
+                       offset     = (offset + base_alignment-1) & ~alignment_mask;
+                       bit_offset = get_type_size(base_type) * BITS_PER_BYTE;
+                       assert(bit_offset >= bit_size);
+               }
+
+               bit_offset -= bit_size;
+               member->compound_member.offset     = offset;
+               member->compound_member.bit_offset = bit_offset;
+       }
+
+       if (current_base_type != NULL)
+               offset += get_type_size(current_base_type);
+
+       *struct_offset    = offset;
+       *struct_alignment = alignment;
+       return member;
+}
+
 static entity_t *pack_bitfield_members(il_size_t *struct_offset,
                                        il_alignment_t *struct_alignment,
                                                                           bool packed, entity_t *first)
@@ -1683,7 +1744,7 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
        entity_t *member;
        for (member = first; member != NULL; member = member->base.next) {
                if (member->kind != ENTITY_COMPOUND_MEMBER)
-                       break;
+                       continue;
 
                type_t *type = member->declaration.type;
                if (type->kind != TYPE_BITFIELD)
@@ -1721,14 +1782,9 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
 
        *struct_offset    = offset;
        *struct_alignment = alignment;
-
        return member;
 }
 
-/**
- * Finish the construction of a struct type by calculating its size, offsets,
- * alignment.
- */
 void layout_struct_type(compound_type_t *type)
 {
        assert(type->compound != NULL);
@@ -1758,8 +1814,14 @@ void layout_struct_type(compound_type_t *type)
                }
 
                if (skipped->kind == TYPE_BITFIELD) {
-                       entry = pack_bitfield_members(&offset, &alignment,
-                                                     compound->packed, entry);
+                       if (byte_order_big_endian) {
+                               entry = pack_bitfield_members_big_endian(&offset, &alignment,
+                                                                        compound->packed,
+                                                                        entry);
+                       } else {
+                               entry = pack_bitfield_members(&offset, &alignment,
+                                                             compound->packed, entry);
+                       }
                        continue;
                }
 
@@ -1805,10 +1867,6 @@ void layout_struct_type(compound_type_t *type)
        compound->layouted  = true;
 }
 
-/**
- * Finish the construction of an union type by calculating
- * its size and alignment.
- */
 void layout_union_type(compound_type_t *type)
 {
        assert(type->compound != NULL);
@@ -1843,6 +1901,89 @@ void layout_union_type(compound_type_t *type)
        compound->alignment = alignment;
 }
 
+static function_parameter_t *allocate_parameter(type_t *const type)
+{
+       function_parameter_t *const param
+               = obstack_alloc(type_obst, sizeof(*param));
+       memset(param, 0, sizeof(*param));
+       param->type = type;
+       return param;
+}
+
+type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
+                             type_t *argument_type2)
+{
+       function_parameter_t *const parameter2 = allocate_parameter(argument_type2);
+       function_parameter_t *const parameter1 = allocate_parameter(argument_type1);
+       parameter1->next = parameter2;
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter1;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
+{
+       function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_1_type_variadic(type_t *return_type,
+                                      type_t *argument_type)
+{
+       function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter;
+       type->function.variadic    = true;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_0_type(type_t *return_type)
+{
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = NULL;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_type(type_t *return_type, int n_types,
+                           type_t *const *argument_types,
+                                                  decl_modifiers_t modifiers)
+{
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.modifiers  |= modifiers;
+       type->function.linkage     = LINKAGE_C;
+
+       function_parameter_t *last  = NULL;
+       for (int i = 0; i < n_types; ++i) {
+               function_parameter_t *parameter = allocate_parameter(argument_types[i]);
+               if (last == NULL) {
+                       type->function.parameters = parameter;
+               } else {
+                       last->next = parameter;
+               }
+               last = parameter;
+       }
+
+       return identify_new_type(type);
+}
+
 /**
  * Debug helper. Prints the given type to stdout.
  */