implement some missing builtin variants
[cparser] / type.c
diff --git a/type.c b/type.c
index 88219a4..c2484b8 100644 (file)
--- a/type.c
+++ b/type.c
@@ -43,13 +43,6 @@ static bool           print_implicit_array_size = false;
 static void intern_print_type_pre(const type_t *type);
 static void intern_print_type_post(const type_t *type);
 
-typedef struct atomic_type_properties_t atomic_type_properties_t;
-struct atomic_type_properties_t {
-       unsigned   size;              /**< type size in bytes */
-       unsigned   alignment;         /**< type alignment in bytes */
-       unsigned   flags;             /**< type flags from atomic_type_flag_t */
-};
-
 /**
  * Returns the size of a type node.
  *
@@ -61,7 +54,6 @@ static size_t get_type_struct_size(type_kind_t kind)
                [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),
@@ -91,35 +83,32 @@ type_t *allocate_type_zero(type_kind_t kind)
 /**
  * Properties of atomic types.
  */
-static atomic_type_properties_t atomic_type_properties[ATOMIC_TYPE_LAST+1] = {
-       //ATOMIC_TYPE_INVALID = 0,
+atomic_type_properties_t atomic_type_properties[ATOMIC_TYPE_LAST+1] = {
        [ATOMIC_TYPE_VOID] = {
-               .size       = 0,
-               .alignment  = 0,
-               .flags      = ATOMIC_TYPE_FLAG_NONE
+               .size      = 0,
+               .alignment = 0,
+               .flags     = ATOMIC_TYPE_FLAG_NONE
        },
        [ATOMIC_TYPE_WCHAR_T] = {
-               .size       = (unsigned)-1,
-               .alignment  = (unsigned)-1,
-               /* signed flag will be set when known */
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+               .size      = (unsigned)-1,
+               .alignment = (unsigned)-1,
+               .flags     = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
        },
        [ATOMIC_TYPE_CHAR] = {
-               .size       = 1,
-               .alignment  = 1,
-               /* signed flag will be set when known */
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+               .size      = 1,
+               .alignment = 1,
+               .flags     = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
        },
        [ATOMIC_TYPE_SCHAR] = {
-               .size       = 1,
-               .alignment  = 1,
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
-                             | ATOMIC_TYPE_FLAG_SIGNED,
+               .size      = 1,
+               .alignment = 1,
+               .flags     = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
+                          | ATOMIC_TYPE_FLAG_SIGNED,
        },
        [ATOMIC_TYPE_UCHAR] = {
-               .size       = 1,
-               .alignment  = 1,
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+               .size      = 1,
+               .alignment = 1,
+               .flags     = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
        },
        [ATOMIC_TYPE_SHORT] = {
                .size       = 2,
@@ -154,41 +143,28 @@ static atomic_type_properties_t atomic_type_properties[ATOMIC_TYPE_LAST+1] = {
                .alignment  = (unsigned) -1,
                .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
        },
-       [ATOMIC_TYPE_LONGLONG] = {
-               .size       = (unsigned) -1,
-               .alignment  = (unsigned) -1,
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
-                             | ATOMIC_TYPE_FLAG_SIGNED,
-       },
-       [ATOMIC_TYPE_ULONGLONG] = {
-               .size       = (unsigned) -1,
-               .alignment  = (unsigned) -1,
-               .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
-       },
        [ATOMIC_TYPE_BOOL] = {
-               .size       = (unsigned) -1,
-               .alignment  = (unsigned) -1,
+               .size       = 1,
+               .alignment  = 1,
                .flags      = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
        },
        [ATOMIC_TYPE_FLOAT] = {
                .size       = 4,
-               .alignment  = (unsigned) -1,
+               .alignment  = 4,
                .flags      = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_ARITHMETIC
                              | ATOMIC_TYPE_FLAG_SIGNED,
        },
        [ATOMIC_TYPE_DOUBLE] = {
                .size       = 8,
-               .alignment  = (unsigned) -1,
-               .flags      = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_ARITHMETIC
-                             | ATOMIC_TYPE_FLAG_SIGNED,
-       },
-       [ATOMIC_TYPE_LONG_DOUBLE] = {
-               .size       = (unsigned) -1, /* will be filled in later */
-               .alignment  = (unsigned) -1,
+               .alignment  = 8,
                .flags      = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_ARITHMETIC
                              | ATOMIC_TYPE_FLAG_SIGNED,
        },
-       /* complex and imaginary types are set in init_types */
+};
+atomic_type_properties_t pointer_properties = {
+       .size      = 4,
+       .alignment = 4,
+       .flags     = ATOMIC_TYPE_FLAG_NONE,
 };
 
 static inline bool is_po2(unsigned x)
@@ -196,64 +172,41 @@ static inline bool is_po2(unsigned x)
        return (x & (x-1)) == 0;
 }
 
-void init_types(void)
+void init_types(unsigned machine_size)
 {
        obstack_init(&type_obst);
 
        atomic_type_properties_t *props = atomic_type_properties;
 
-       if (char_is_signed) {
-               props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED;
-       }
+       /* atempt to set some sane defaults based on machine size */
 
        unsigned int_size   = machine_size < 32 ? 2 : 4;
-       /* long is always 32bit on windows */
-       unsigned long_size  = c_mode & _MS ? 4 : (machine_size < 64 ? 4 : 8);
-       unsigned llong_size = machine_size < 32 ? 4 : 8;
-
-       props[ATOMIC_TYPE_INT].size            = int_size;
-       props[ATOMIC_TYPE_INT].alignment       = int_size;
-       props[ATOMIC_TYPE_UINT].size           = int_size;
-       props[ATOMIC_TYPE_UINT].alignment      = int_size;
-       props[ATOMIC_TYPE_LONG].size           = long_size;
-       props[ATOMIC_TYPE_LONG].alignment      = long_size;
-       props[ATOMIC_TYPE_ULONG].size          = long_size;
-       props[ATOMIC_TYPE_ULONG].alignment     = long_size;
-       props[ATOMIC_TYPE_LONGLONG].size       = llong_size;
-       props[ATOMIC_TYPE_LONGLONG].alignment  = llong_size;
-       props[ATOMIC_TYPE_ULONGLONG].size      = llong_size;
-       props[ATOMIC_TYPE_ULONGLONG].alignment = llong_size;
-
-       /* TODO: backend specific, need a way to query the backend for this.
-        * The following are good settings for x86 */
-       if (machine_size <= 32) {
-               props[ATOMIC_TYPE_FLOAT].alignment       = 4;
-               props[ATOMIC_TYPE_DOUBLE].alignment      = 4;
-               props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 4;
-               props[ATOMIC_TYPE_LONGLONG].alignment    = 4;
-               props[ATOMIC_TYPE_ULONGLONG].alignment   = 4;
-       } else {
-               props[ATOMIC_TYPE_FLOAT].alignment       = 4;
-               props[ATOMIC_TYPE_DOUBLE].alignment      = 8;
-               props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 8;
-               props[ATOMIC_TYPE_LONGLONG].alignment    = 8;
-               props[ATOMIC_TYPE_ULONGLONG].alignment   = 8;
+       unsigned long_size  = machine_size < 64 ? 4 : 8;
+
+       props[ATOMIC_TYPE_INT].size        = int_size;
+       props[ATOMIC_TYPE_INT].alignment   = int_size;
+       props[ATOMIC_TYPE_UINT].size       = int_size;
+       props[ATOMIC_TYPE_UINT].alignment  = int_size;
+       props[ATOMIC_TYPE_LONG].size       = long_size;
+       props[ATOMIC_TYPE_LONG].alignment  = long_size;
+       props[ATOMIC_TYPE_ULONG].size      = long_size;
+       props[ATOMIC_TYPE_ULONG].alignment = long_size;
+
+       pointer_properties.size             = long_size;
+       pointer_properties.alignment        = long_size;
+       pointer_properties.struct_alignment = long_size;
+
+       props[ATOMIC_TYPE_LONGLONG]    = props[ATOMIC_TYPE_LONG];
+       props[ATOMIC_TYPE_ULONGLONG]   = props[ATOMIC_TYPE_ULONG];
+       props[ATOMIC_TYPE_LONG_DOUBLE] = props[ATOMIC_TYPE_DOUBLE];
+       props[ATOMIC_TYPE_WCHAR_T]     = props[ATOMIC_TYPE_INT];
+
+       /* set struct alignments to the same value as alignment */
+       for (size_t i = 0;
+            i < sizeof(atomic_type_properties)/sizeof(atomic_type_properties[0]);
+            ++i) {
+               props[i].struct_alignment = props[i].alignment;
        }
-
-       if (long_double_size > 0) {
-               props[ATOMIC_TYPE_LONG_DOUBLE].size      = long_double_size;
-               if (is_po2(long_double_size)) {
-                       props[ATOMIC_TYPE_LONG_DOUBLE].alignment = long_double_size;
-               }
-       } else {
-               props[ATOMIC_TYPE_LONG_DOUBLE] = props[ATOMIC_TYPE_DOUBLE];
-       }
-
-       /* TODO: make this configurable for platforms which do not use byte sized
-        * bools. */
-       props[ATOMIC_TYPE_BOOL] = props[ATOMIC_TYPE_UCHAR];
-
-       props[ATOMIC_TYPE_WCHAR_T] = props[wchar_atomic_kind];
 }
 
 void exit_types(void)
@@ -540,18 +493,6 @@ static void print_array_type_post(const array_type_t *type)
        intern_print_type_post(type->element_type);
 }
 
-/**
- * Prints the postfix part of a bitfield type.
- *
- * @param type   The array type.
- */
-static void print_bitfield_type_post(const bitfield_type_t *type)
-{
-       print_string(" : ");
-       print_expression(type->size_expression);
-       intern_print_type_post(type->base_type);
-}
-
 /**
  * Prints an enum definition.
  *
@@ -574,9 +515,6 @@ void print_enum_definition(const enum_t *enume)
 
                        /* skip the implicit cast */
                        expression_t *expression = entry->enum_value.value;
-                       if (expression->kind == EXPR_UNARY_CAST_IMPLICIT) {
-                               expression = expression->unary.value;
-                       }
                        print_expression(expression);
                }
                print_string(",\n");
@@ -723,9 +661,6 @@ static void intern_print_type_pre(const type_t *const type)
        case TYPE_REFERENCE:
                print_reference_type_pre(&type->reference);
                return;
-       case TYPE_BITFIELD:
-               intern_print_type_pre(type->bitfield.base_type);
-               return;
        case TYPE_ARRAY:
                print_array_type_pre(&type->array);
                return;
@@ -759,9 +694,6 @@ static void intern_print_type_post(const type_t *const type)
        case TYPE_ARRAY:
                print_array_type_post(&type->array);
                return;
-       case TYPE_BITFIELD:
-               print_bitfield_type_post(&type->bitfield);
-               return;
        case TYPE_ERROR:
        case TYPE_INVALID:
        case TYPE_ATOMIC:
@@ -897,9 +829,6 @@ bool is_type_integer(const type_t *type)
 
        if (type->kind == TYPE_ENUM)
                return true;
-       if (type->kind == TYPE_BITFIELD)
-               return true;
-
        if (type->kind != TYPE_ATOMIC)
                return false;
 
@@ -963,9 +892,6 @@ bool is_type_signed(const type_t *type)
        /* enum types are int for now */
        if (type->kind == TYPE_ENUM)
                return true;
-       if (type->kind == TYPE_BITFIELD)
-               return is_type_signed(type->bitfield.base_type);
-
        if (type->kind != TYPE_ATOMIC)
                return false;
 
@@ -983,7 +909,6 @@ bool is_type_arithmetic(const type_t *type)
        assert(!is_typeref(type));
 
        switch(type->kind) {
-       case TYPE_BITFIELD:
        case TYPE_ENUM:
                return true;
        case TYPE_ATOMIC:
@@ -1057,7 +982,6 @@ bool is_type_incomplete(const type_t *type)
        case TYPE_IMAGINARY:
                return type->imaginary.akind == ATOMIC_TYPE_VOID;
 
-       case TYPE_BITFIELD:
        case TYPE_FUNCTION:
        case TYPE_POINTER:
        case TYPE_REFERENCE:
@@ -1197,19 +1121,12 @@ bool types_compatible(const type_t *type1, const type_t *type2)
 
        case TYPE_COMPOUND_STRUCT:
        case TYPE_COMPOUND_UNION: {
-
-
                break;
        }
        case TYPE_ENUM:
                /* TODO: not implemented */
                break;
 
-       case TYPE_BITFIELD:
-               /* not sure if this makes sense or is even needed, implement it if you
-                * really need it! */
-               panic("type compatibility check for bitfield type");
-
        case TYPE_ERROR:
                /* Hmm, the error type should be compatible to all other types */
                return true;
@@ -1220,7 +1137,6 @@ bool types_compatible(const type_t *type1, const type_t *type2)
                panic("typerefs not skipped in compatible types?!?");
        }
 
-       /* TODO: incomplete */
        return false;
 }
 
@@ -1301,15 +1217,12 @@ unsigned get_type_size(type_t *type)
                return 0; /* non-const (but "address-const") */
        case TYPE_REFERENCE:
        case TYPE_POINTER:
-               /* TODO: make configurable by backend */
-               return 4;
+               return pointer_properties.size;
        case TYPE_ARRAY: {
                /* TODO: correct if element_type is aligned? */
                il_size_t element_size = get_type_size(type->array.element_type);
                return type->array.size * element_size;
        }
-       case TYPE_BITFIELD:
-               return 0;
        case TYPE_TYPEDEF:
                return get_type_size(type->typedeft.typedefe->type);
        case TYPE_TYPEOF:
@@ -1344,16 +1257,13 @@ unsigned get_type_alignment(type_t *type)
        case TYPE_ENUM:
                return get_atomic_type_alignment(type->enumt.akind);
        case TYPE_FUNCTION:
-               /* what is correct here? */
-               return 4;
+               /* gcc says 1 here... */
+               return 1;
        case TYPE_REFERENCE:
        case TYPE_POINTER:
-               /* TODO: make configurable by backend */
-               return 4;
+               return pointer_properties.alignment;
        case TYPE_ARRAY:
                return get_type_alignment(type->array.element_type);
-       case TYPE_BITFIELD:
-               return 0;
        case TYPE_TYPEDEF: {
                il_alignment_t alignment
                        = get_type_alignment(type->typedeft.typedefe->type);
@@ -1372,6 +1282,13 @@ unsigned get_type_alignment(type_t *type)
        panic("invalid type in get_type_alignment");
 }
 
+unsigned get_type_alignment_compound(type_t *type)
+{
+       if (type->kind == TYPE_ATOMIC)
+               return atomic_type_properties[type->atomic.akind].struct_alignment;
+       return get_type_alignment(type);
+}
+
 decl_modifiers_t get_type_modifiers(const type_t *type)
 {
        switch(type->kind) {
@@ -1389,7 +1306,6 @@ decl_modifiers_t get_type_modifiers(const type_t *type)
        case TYPE_IMAGINARY:
        case TYPE_REFERENCE:
        case TYPE_POINTER:
-       case TYPE_BITFIELD:
        case TYPE_ARRAY:
                return 0;
        case TYPE_TYPEDEF: {
@@ -1458,26 +1374,6 @@ unsigned get_atomic_type_flags(atomic_type_kind_t kind)
        return atomic_type_properties[kind].flags;
 }
 
-atomic_type_kind_t get_intptr_kind(void)
-{
-       if (machine_size <= 32)
-               return ATOMIC_TYPE_INT;
-       else if (machine_size <= 64)
-               return ATOMIC_TYPE_LONG;
-       else
-               return ATOMIC_TYPE_LONGLONG;
-}
-
-atomic_type_kind_t get_uintptr_kind(void)
-{
-       if (machine_size <= 32)
-               return ATOMIC_TYPE_UINT;
-       else if (machine_size <= 64)
-               return ATOMIC_TYPE_ULONG;
-       else
-               return ATOMIC_TYPE_ULONGLONG;
-}
-
 /**
  * Find the atomic type kind representing a given size (signed).
  */
@@ -1665,18 +1561,16 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
        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)
+               if (!member->compound_member.bitfield)
                        break;
 
-               type_t *base_type = skip_typeref(type->bitfield.base_type);
-               il_alignment_t base_alignment = get_type_alignment(base_type);
+               type_t *base_type = member->declaration.type;
+               il_alignment_t base_alignment = get_type_alignment_compound(base_type);
                il_alignment_t alignment_mask = base_alignment-1;
                if (base_alignment > alignment)
                        alignment = base_alignment;
 
-               size_t bit_size = type->bitfield.bit_size;
+               size_t bit_size = member->compound_member.bit_size;
                if (!packed) {
                        bit_offset += (offset & alignment_mask) * BITS_PER_BYTE;
                        offset     &= ~alignment_mask;
@@ -1739,13 +1633,13 @@ void layout_struct_type(compound_type_t *type)
                        continue;
                }
 
-               if (skipped->kind == TYPE_BITFIELD) {
+               if (entry->compound_member.bitfield) {
                        entry = pack_bitfield_members(&offset, &alignment,
                                                      compound->packed, entry);
                        continue;
                }
 
-               il_alignment_t m_alignment = get_type_alignment(m_type);
+               il_alignment_t m_alignment = get_type_alignment_compound(m_type);
                if (m_alignment > alignment)
                        alignment = m_alignment;
 
@@ -1808,7 +1702,7 @@ void layout_union_type(compound_type_t *type)
                il_size_t m_size = get_type_size(m_type);
                if (m_size > size)
                        size = m_size;
-               il_alignment_t m_alignment = get_type_alignment(m_type);
+               il_alignment_t m_alignment = get_type_alignment_compound(m_type);
                if (m_alignment > alignment)
                        alignment = m_alignment;
        }