started working on bitfields
authorMatthias Braun <matze@braunis.de>
Sat, 8 Dec 2007 13:21:26 +0000 (13:21 +0000)
committerMatthias Braun <matze@braunis.de>
Sat, 8 Dec 2007 13:21:26 +0000 (13:21 +0000)
[r18648]

12 files changed:
Makefile
ast.c
ast2firm.c
ast_t.h
diagnostic.c
format_check.c
main.c
parser.c
type.c
type.h
type_hash.c
type_t.h

index 995f2c0..88c4760 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -88,8 +88,8 @@ build/adt build/driver:
 build/%.o: %.c
        @echo '===> CC $<'
 #-$(Q)build/cparser $(CPPFLAGS) $(CFLAGS) -fsyntax-only $<
-#$(Q)$(ICC) $(CPPFLAGS) $(ICC_CFLAGS) -c $< -o $@
-#      $(Q)$(GCCO1) $(CPPFLAGS) $(CFLAGS) -O1 -c $< -o $@
+       $(Q)$(ICC) $(CPPFLAGS) $(ICC_CFLAGS) -c $< -o $@
+       $(Q)$(GCCO1) $(CPPFLAGS) $(CFLAGS) -O1 -c $< -o $@
        $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 clean:
diff --git a/ast.c b/ast.c
index a8b66e0..6a4f111 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -761,7 +761,7 @@ static void print_normal_declaration(const declaration_t *declaration)
 {
        print_storage_class(declaration->storage_class);
        if(declaration->is_inline) {
-               if (declaration->decl_modifiers & DM_FORCEINLINE)
+               if (declaration->modifiers & DM_FORCEINLINE)
                        fputs("__forceinline ", out);
                else
                        fputs("inline ", out);
index b5cca3d..e132b24 100644 (file)
@@ -332,6 +332,8 @@ static unsigned get_type_size(type_t *type)
                return get_array_type_size(&type->array);
        case TYPE_BUILTIN:
                return get_type_size(type->builtin.real_type);
+       case TYPE_BITFIELD:
+               panic("type size of bitfield request");
        case TYPE_TYPEDEF:
        case TYPE_TYPEOF:
        case TYPE_INVALID:
@@ -456,49 +458,100 @@ static ir_type *create_struct_type(compound_type_t *type)
        } else {
                id = unique_ident("__anonymous_struct");
        }
-       ir_type *ir_type = new_type_struct(id);
+       ir_type *irtype = new_type_struct(id);
 
-       type->type.firm_type = ir_type;
+       type->type.firm_type = irtype;
 
-       int align_all = 1;
-       int offset    = 0;
+       size_t align_all  = 1;
+       size_t offset     = 0;
+       size_t bit_offset = 0;
        declaration_t *entry = type->declaration->context.declarations;
        for( ; entry != NULL; entry = entry->next) {
                if(entry->namespc != NAMESPACE_NORMAL)
                        continue;
 
-               ident       *ident         = new_id_from_str(entry->symbol->string);
-               ir_type_ptr  entry_ir_type = get_ir_type(entry->type);
+               type_t *entry_type = skip_typeref(entry->type);
 
-               int entry_size      = get_type_size_bytes(entry_ir_type);
-               int entry_alignment = get_type_alignment_bytes(entry_ir_type);
-               int misalign        = offset % entry_alignment;
-               if (misalign != 0)
-                       offset += entry_alignment - misalign;
+               ir_type *base_irtype;
+               if(entry_type->kind == TYPE_BITFIELD) {
+                       base_irtype = get_ir_type(entry_type->bitfield.base);
+               } else {
+                       base_irtype = get_ir_type(entry_type);
+               }
 
-               dbg_info  *const dbgi   = get_dbg_info(&entry->source_position);
-               ir_entity *const entity = new_d_entity(ir_type, ident, entry_ir_type, dbgi);
-               set_entity_offset(entity, offset);
-               add_struct_member(ir_type, entity);
-               entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
-               entry->v.entity         = entity;
+               size_t entry_alignment = get_type_alignment_bytes(base_irtype);
+               size_t misalign        = offset % entry_alignment;
+
+               dbg_info  *dbgi   = get_dbg_info(&entry->source_position);
+               ir_entity *entity = NULL;
+               if(entry->symbol != NULL) {
+                       ident   *ident        = new_id_from_str(entry->symbol->string);
+                       ir_type *entry_irtype = get_ir_type(entry_type);
+
+                       entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
+               } else {
+                       /* only bitfields are allowed to be anonymous */
+                       assert(entry_type->kind == TYPE_BITFIELD);
+               }
+
+               size_t base;
+               size_t bits_remainder;
+               if(entry_type->kind == TYPE_BITFIELD) {
+                       size_t size_bits      = fold_constant(entry_type->bitfield.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)
+                               offset += entry_size - misalign;
+
+                       base           = offset;
+                       bits_remainder = 0;
+                       offset        += entry_size;
+                       bit_offset     = 0;
+               }
 
-               offset += entry_size;
                if(entry_alignment > align_all) {
                        if(entry_alignment % align_all != 0) {
-                               panic("Uneven alignments not supported yet");
+                               panic("uneven alignments not supported yet");
                        }
                        align_all = entry_alignment;
                }
+
+               if(entity != NULL) {
+                       set_entity_offset(entity, base);
+                       set_entity_offset_bits_remainder(entity,
+                                                        (unsigned char) bits_remainder);
+                       add_struct_member(irtype, entity);
+                       entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
+                       entry->v.entity         = entity;
+               }
        }
 
-       int misalign = offset % align_all;
-       offset += misalign;
-       set_type_alignment_bytes(ir_type, align_all);
-       set_type_size_bytes(ir_type, offset);
-       set_type_state(ir_type, layout_fixed);
+       size_t misalign = offset % align_all;
+       if(misalign > 0) {
+               offset += align_all - misalign;
+       }
+       set_type_alignment_bytes(irtype, align_all);
+       set_type_size_bytes(irtype, offset);
+       set_type_state(irtype, layout_fixed);
 
-       return ir_type;
+       return irtype;
 }
 
 static ir_type *create_union_type(compound_type_t *type)
@@ -511,9 +564,9 @@ static ir_type *create_union_type(compound_type_t *type)
        } else {
                id = unique_ident("__anonymous_union");
        }
-       ir_type  *ir_type = new_type_union(id);
+       ir_type *irtype = new_type_union(id);
 
-       type->type.firm_type = ir_type;
+       type->type.firm_type = irtype;
 
        int align_all = 1;
        int size      = 0;
@@ -522,15 +575,16 @@ static ir_type *create_union_type(compound_type_t *type)
                if(entry->namespc != NAMESPACE_NORMAL)
                        continue;
 
-               ident       *ident         = new_id_from_str(entry->symbol->string);
-               ir_type_ptr  entry_ir_type = get_ir_type(entry->type);
+               ident   *ident         = new_id_from_str(entry->symbol->string);
+               ir_type *entry_ir_type = get_ir_type(entry->type);
 
                int entry_size      = get_type_size_bytes(entry_ir_type);
                int entry_alignment = get_type_alignment_bytes(entry_ir_type);
 
                dbg_info  *const dbgi   = get_dbg_info(&entry->source_position);
-               ir_entity *const entity = new_d_entity(ir_type, ident, entry_ir_type, dbgi);
-               add_union_member(ir_type, entity);
+               ir_entity *const entity = new_d_entity(irtype, ident, entry_ir_type,
+                                                      dbgi);
+               add_union_member(irtype, entity);
                set_entity_offset(entity, 0);
                entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
                entry->v.entity         = entity;
@@ -546,11 +600,11 @@ static ir_type *create_union_type(compound_type_t *type)
                }
        }
 
-       set_type_alignment_bytes(ir_type, align_all);
-       set_type_size_bytes(ir_type, size);
-       set_type_state(ir_type, layout_fixed);
+       set_type_alignment_bytes(irtype, align_all);
+       set_type_size_bytes(irtype, size);
+       set_type_state(irtype, layout_fixed);
 
-       return ir_type;
+       return irtype;
 }
 
 static ir_node *expression_to_firm(const expression_t *expression);
@@ -586,6 +640,92 @@ static ir_type *create_enum_type(enum_type_t *const type)
        return ir_type_int;
 }
 
+/**
+ * Return the signed integer type of size bits.
+ *
+ * @param size   the size
+ */
+static ir_type *get_signed_int_type_for_bit_size(ir_type *base_tp,
+                                                 unsigned size)
+{
+       static ir_mode *s_modes[64 + 1] = {NULL, };
+       ir_type *res;
+       ir_mode *mode;
+
+       if (size <= 0 || size > 64)
+               return NULL;
+
+       mode = s_modes[size];
+       if (mode == NULL) {
+               char name[32];
+
+               snprintf(name, sizeof(name), "bf_I%u", size);
+               mode = new_ir_mode(name, irms_int_number, size, 1, irma_twos_complement,
+                                  size <= 32 ? 32 : size );
+               s_modes[size] = mode;
+       }
+
+       char name[32];
+       snprintf(name, sizeof(name), "I%u", size);
+       ident *id = new_id_from_str(name);
+       res = new_type_primitive(mangle_u(get_type_ident(base_tp), id), mode);
+       set_primitive_base_type(res, base_tp);
+
+       return res;
+}
+
+/**
+ * Return the unsigned integer type of size bits.
+ *
+ * @param size   the size
+ */
+static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp,
+                                                   unsigned size)
+{
+       static ir_mode *u_modes[64 + 1] = {NULL, };
+       ir_type *res;
+       ir_mode *mode;
+
+       if (size <= 0 || size > 64)
+               return NULL;
+
+       mode = u_modes[size];
+       if (mode == NULL) {
+               char name[32];
+
+               snprintf(name, sizeof(name), "bf_U%u", size);
+               mode = new_ir_mode(name, irms_int_number, size, 0, irma_twos_complement,
+                                  size <= 32 ? 32 : size );
+               u_modes[size] = mode;
+       }
+
+       char name[32];
+
+       snprintf(name, sizeof(name), "U%u", size);
+       ident *id = new_id_from_str(name);
+       res = new_type_primitive(mangle_u(get_type_ident(base_tp), id), mode);
+       set_primitive_base_type(res, base_tp);
+
+       return res;
+}
+
+static ir_type *create_bitfield_type(bitfield_type_t *const type)
+{
+       type_t *base = skip_typeref(type->base);
+       assert(base->kind == TYPE_ATOMIC);
+
+       ir_type *irbase = get_ir_type(base);
+
+       unsigned size = fold_constant(type->size);
+
+       assert(!is_type_floating(base));
+       if(is_type_signed(base)) {
+               return get_signed_int_type_for_bit_size(irbase, size);
+       } else {
+               return get_unsigned_int_type_for_bit_size(irbase, size);
+       }
+}
+
 static ir_type *get_ir_type(type_t *type)
 {
        assert(type != NULL);
@@ -623,6 +763,10 @@ static ir_type *get_ir_type(type_t *type)
        case TYPE_BUILTIN:
                firm_type = get_ir_type(type->builtin.real_type);
                break;
+       case TYPE_BITFIELD:
+               firm_type = create_bitfield_type(&type->bitfield);
+               break;
+
        case TYPE_TYPEOF:
        case TYPE_TYPEDEF:
        case TYPE_INVALID:
@@ -758,10 +902,9 @@ static ir_entity* get_function_entity(declaration_t *declaration)
 
                /* We should check for file scope here, but as long as we compile C only
                   this is not needed. */
-               int n_params     = get_method_n_params(ir_type_method);
-               int n_res        = get_method_n_ress(ir_type_method);
-               ir_ident_ptr id  = get_entity_ident(entity);
-               int i;
+               int    n_params = get_method_n_params(ir_type_method);
+               int    n_res    = get_method_n_ress(ir_type_method);
+               int    i;
 
                if (n_params == 0 && n_res == 0 && id == predef_idents[rts_abort]) {
                        /* found abort(), store for later */
@@ -812,7 +955,8 @@ static ir_node *const_to_firm(const const_expression_t *cnst)
        return new_d_Const(dbgi, mode, tv);
 }
 
-static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode, ir_entity *entity)
+static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode,
+                                ir_entity *entity)
 {
        assert(entity != NULL);
        union symconst_symbol sym;
@@ -1333,7 +1477,8 @@ static pn_Cmp get_pnc(const expression_kind_t kind)
  *  - const rel val
  *  - var rel var
  */
-static ir_node *handle_assume_compare(dbg_info *dbi, const binary_expression_t *expression)
+static ir_node *handle_assume_compare(dbg_info *dbi,
+                                      const binary_expression_t *expression)
 {
        expression_t  *op1 = expression->left;
        expression_t  *op2 = expression->right;
@@ -3397,9 +3542,11 @@ static int count_decls_in_expression(const expression_t *expression) {
        switch(expression->base.kind) {
        case EXPR_STATEMENT:
                return count_decls_in_stmts(expression->statement.statement);
-       EXPR_BINARY_CASES
-               return count_decls_in_expression(expression->binary.left)
-                       + count_decls_in_expression(expression->binary.right);
+       EXPR_BINARY_CASES {
+               int count_left  = count_decls_in_expression(expression->binary.left);
+               int count_right = count_decls_in_expression(expression->binary.right);
+               return count_left + count_right;
+       }
        EXPR_UNARY_CASES
                return count_decls_in_expression(expression->unary.value);
 
@@ -3620,7 +3767,7 @@ static void create_function(declaration_t *declaration)
        /* set inline flags */
        if (declaration->is_inline)
        set_irg_inline_property(irg, irg_inline_recomended);
-    handle_decl_modifier_irg(irg, declaration->decl_modifiers);
+    handle_decl_modifier_irg(irg, declaration->modifiers);
 
        next_value_number_function = 0;
        initialize_function_parameters(declaration);
@@ -3739,7 +3886,8 @@ global_var:
                        goto create_var;
 
 create_var:
-                       create_declaration_entity(declaration, DECLARATION_KIND_GLOBAL_VARIABLE,
+                       create_declaration_entity(declaration,
+                                                 DECLARATION_KIND_GLOBAL_VARIABLE,
                                                  var_type);
                        set_entity_visibility(declaration->v.entity, vis);
 
diff --git a/ast_t.h b/ast_t.h
index 6b9f1c0..e3039e6 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -392,7 +392,7 @@ typedef unsigned short decl_modifiers_t;
 struct declaration_t {
        unsigned char       namespc;
        unsigned char       storage_class;
-       decl_modifiers_t    decl_modifiers;
+       decl_modifiers_t    modifiers;
        unsigned int        address_taken : 1;
        unsigned int        is_inline     : 1;
        type_t             *type;
index ce6de55..930b9bd 100644 (file)
@@ -44,7 +44,7 @@ static void diagnosticvf(const char *const fmt, va_list ap)
                                }
 
                                case 'c': {
-                                       const unsigned char val = va_arg(ap, int);
+                                       const unsigned char val = (unsigned char) va_arg(ap, int);
                                        fputc(val, stderr);
                                        break;
                                }
index a0f2cbc..93781fd 100644 (file)
@@ -33,7 +33,7 @@ typedef enum format_length_modifier_t {
 
 static void warn_invalid_length_modifier(const source_position_t pos,
                                          const format_length_modifier_t mod,
-                                         const char conversion)
+                                         const wchar_rep_t conversion)
 {
        static const char* const names[] = {
                [FMT_MOD_NONE] = "",
@@ -205,7 +205,7 @@ break_fmt_flags:
                        break;
                }
 
-               const type_t   *expected_type;
+               const type_t   *expected_type = NULL;
                format_flags_t  allowed_flags;
                switch (*fmt) {
                        case 'd':
diff --git a/main.c b/main.c
index 15c6784..0c95dbd 100644 (file)
--- a/main.c
+++ b/main.c
@@ -384,7 +384,7 @@ int main(int argc, char **argv)
                } else if(strcmp(arg, "--version") == 0) {
                        firm_version_t ver;
                        firm_get_version(&ver);
-                       printf("cparser (%d.%d %s) using libFirm (%d.%d", 0, 1, cparser_REVISION, ver.major, ver.minor);
+                       printf("cparser (%d.%d %s) using libFirm (%u.%u", 0, 1, cparser_REVISION, ver.major, ver.minor);
                        if(ver.revision[0] != 0) {
                                putchar(' ');
                                fputs(ver.revision, stdout);
@@ -514,7 +514,7 @@ int main(int argc, char **argv)
        init_parser();
        init_ast2firm();
 
-       FILE *out;
+       FILE *out = NULL;
        char  outnamebuf[4096];
        if(outname == NULL) {
                switch(mode) {
index 4dec832..2e52b78 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -237,6 +237,7 @@ static size_t get_type_struct_size(type_kind_t kind)
 {
        static const size_t sizes[] = {
                [TYPE_ATOMIC]          = sizeof(atomic_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),
@@ -722,6 +723,9 @@ static int get_rank(const type_t *type)
 
 static type_t *promote_integer(type_t *type)
 {
+       if(type->kind == TYPE_BITFIELD)
+               return promote_integer(type->bitfield.base);
+
        if(get_rank(type) < ATOMIC_TYPE_INT)
                type = type_int;
 
@@ -791,9 +795,11 @@ static expression_t *create_implicit_cast(expression_t *expression,
        switch (dest_type->kind) {
                case TYPE_ENUM:
                        /* TODO warning for implicitly converting to enum */
+               case TYPE_BITFIELD:
                case TYPE_ATOMIC:
                        if (source_type->kind != TYPE_ATOMIC &&
-                                       source_type->kind != TYPE_ENUM) {
+                                       source_type->kind != TYPE_ENUM &&
+                                       source_type->kind != TYPE_BITFIELD) {
                                panic("casting of non-atomic types not implemented yet");
                        }
 
@@ -2308,7 +2314,7 @@ static declaration_t *parse_declarator(
        type_t        *type         = specifiers->type;
        declaration_t *declaration  = allocate_ast_zero(sizeof(declaration[0]));
        declaration->storage_class  = specifiers->storage_class;
-       declaration->decl_modifiers = specifiers->decl_modifiers;
+       declaration->modifiers      = specifiers->decl_modifiers;
        declaration->is_inline      = specifiers->is_inline;
 
        construct_type_t *construct_type
@@ -2706,26 +2712,50 @@ end_of_parse_external_declaration:
        environment_pop_to(top);
 }
 
+static type_t *make_bitfield_type(type_t *base, expression_t *size)
+{
+       type_t *type        = allocate_type_zero(TYPE_BITFIELD);
+       type->bitfield.base = base;
+       type->bitfield.size = size;
+
+       return type;
+}
+
 static void parse_struct_declarators(const declaration_specifiers_t *specifiers)
 {
+       /* TODO: check constraints for struct declarations (in specifiers) */
        while(1) {
+               declaration_t *declaration;
+
                if(token.type == ':') {
                        next_token();
-                       parse_constant_expression();
-                       /* TODO (bitfields) */
-               } else {
-                       declaration_t *declaration = parse_declarator(specifiers, /*may_be_abstract=*/true);
 
-                       /* TODO: check constraints for struct declarations */
-                       /* TODO: check for doubled fields */
+                       type_t *base_type = specifiers->type;
+                       expression_t *size = parse_constant_expression();
+
+                       type_t *type = make_bitfield_type(base_type, size);
+
+                       declaration = allocate_ast_zero(sizeof(declaration[0]));
+
+                       declaration->namespc         = NAMESPACE_NORMAL;
+                       declaration->storage_class   = STORAGE_CLASS_NONE;
+                       declaration->source_position = token.source_position;
+                       declaration->modifiers       = specifiers->decl_modifiers;
+                       declaration->type            = type;
+
                        record_declaration(declaration);
+               } else {
+                       declaration = parse_declarator(specifiers,/*may_be_abstract=*/true);
 
                        if(token.type == ':') {
                                next_token();
-                               parse_constant_expression();
-                               /* TODO (bitfields) */
+                               expression_t *size = parse_constant_expression();
+
+                               type_t *type = make_bitfield_type(declaration->type, size);
+                               declaration->type = type;
                        }
                }
+               record_declaration(declaration);
 
                if(token.type != ',')
                        break;
@@ -3436,7 +3466,7 @@ static expression_t *parse_primary_expression(void)
                return parse_int_const();
        case T_FLOATINGPOINT:
                return parse_float_const();
-       case T_STRING_LITERAL: /* TODO merge */
+       case T_STRING_LITERAL:
                return parse_string_const();
        case T_WIDE_STRING_LITERAL:
                return parse_wide_string_const();
diff --git a/type.c b/type.c
index 157021c..15adcc1 100644 (file)
--- a/type.c
+++ b/type.c
@@ -159,6 +159,13 @@ static void print_array_type_post(const array_type_t *type)
        intern_print_type_post(type->element_type, false);
 }
 
+static void print_bitfield_type_post(const bitfield_type_t *type)
+{
+       fputs(" : ", out);
+       print_expression(type->size);
+       intern_print_type_post(type->base, false);
+}
+
 void print_enum_definition(const declaration_t *declaration)
 {
        fputs("{\n", out);
@@ -276,6 +283,9 @@ static void intern_print_type_pre(const type_t *const type, const bool top)
        case TYPE_POINTER:
                print_pointer_type_pre(&type->pointer);
                return;
+       case TYPE_BITFIELD:
+               intern_print_type_pre(type->bitfield.base, top);
+               return;
        case TYPE_ARRAY:
                print_array_type_pre(&type->array);
                return;
@@ -301,6 +311,9 @@ static void intern_print_type_post(const type_t *const type, const bool top)
        case TYPE_ARRAY:
                print_array_type_post(&type->array);
                return;
+       case TYPE_BITFIELD:
+               print_bitfield_type_post(&type->bitfield);
+               return;
        case TYPE_INVALID:
        case TYPE_ATOMIC:
        case TYPE_ENUM:
@@ -351,6 +364,7 @@ static size_t get_type_size(type_t *type)
        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_INVALID:         panic("invalid type found");
        }
        panic("unknown type found");
@@ -498,6 +512,9 @@ bool is_type_arithmetic(const type_t *type)
 {
        assert(!is_typeref(type));
 
+       if(type->kind == TYPE_BITFIELD)
+               return true;
+
        if(is_type_integer(type) || is_type_floating(type))
                return true;
 
@@ -511,7 +528,7 @@ bool is_type_scalar(const type_t *type)
        switch (type->kind) {
                case TYPE_POINTER: return true;
                case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
-               default:           break;
+               default:            break;
        }
 
        return is_type_arithmetic(type);
@@ -528,6 +545,7 @@ bool is_type_incomplete(const type_t *type)
                declaration_t         *declaration   = compound_type->declaration;
                return !declaration->init.is_defined;
        }
+       case TYPE_BITFIELD:
        case TYPE_FUNCTION:
                return true;
 
@@ -535,6 +553,8 @@ bool is_type_incomplete(const type_t *type)
                return type->array.size == NULL;
 
        case TYPE_ATOMIC:
+               return type->atomic.atype == ATOMIC_TYPE_VOID;
+
        case TYPE_POINTER:
        case TYPE_ENUM:
        case TYPE_BUILTIN:
@@ -633,6 +653,11 @@ bool types_compatible(const type_t *type1, const type_t *type2)
                /* 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_INVALID:
                panic("invalid type found in compatible types");
        case TYPE_TYPEDEF:
diff --git a/type.h b/type.h
index 805a0d2..5c00fd3 100644 (file)
--- a/type.h
+++ b/type.h
@@ -15,6 +15,7 @@ typedef struct enum_type_t           enum_type_t;
 typedef struct builtin_type_t        builtin_type_t;
 typedef struct array_type_t          array_type_t;
 typedef struct typedef_type_t        typedef_type_t;
+typedef struct bitfield_type_t       bitfield_type_t;
 typedef struct typeof_type_t         typeof_type_t;
 typedef union  type_t                type_t;
 
index 344d458..be14de6 100644 (file)
@@ -77,6 +77,14 @@ static unsigned hash_typeof_type(const typeof_type_t *type)
        return result;
 }
 
+static unsigned hash_bitfield_type(const bitfield_type_t *type)
+{
+       unsigned result  = hash_ptr(type->base);
+       result          ^= 27172145;
+
+       return result;
+}
+
 static unsigned hash_type(const type_t *type)
 {
        unsigned hash = 0;
@@ -113,6 +121,9 @@ static unsigned hash_type(const type_t *type)
        case TYPE_TYPEOF:
                hash = hash_typeof_type(&type->typeoft);
                break;
+       case TYPE_BITFIELD:
+               hash = hash_bitfield_type(&type->bitfield);
+               break;
        }
 
        unsigned some_prime = 99991;
@@ -168,11 +179,10 @@ static bool array_types_equal(const array_type_t *type1,
                return false;
        if(type1->is_static != type2->is_static)
                return false;
-       /* TODO: compare expressions for equality... */
-       if(type1->size != type2->size)
-               return false;
 
-       return true;
+       /* TODO: compare size expressions for equality... */
+
+       return false;
 }
 
 static bool builtin_types_equal(const builtin_type_t *type1,
@@ -210,6 +220,15 @@ static bool typeof_types_equal(const typeof_type_t *type1,
        return true;
 }
 
+static bool bitfield_types_equal(const bitfield_type_t *type1,
+                                 const bitfield_type_t *type2)
+{
+       if(type1->base != type2->base)
+               return false;
+       /* TODO: compare size expression */
+       return false;
+}
+
 static bool types_equal(const type_t *type1, const type_t *type2)
 {
        if(type1 == type2)
@@ -241,6 +260,8 @@ static bool types_equal(const type_t *type1, const type_t *type2)
                return typeof_types_equal(&type1->typeoft, &type2->typeoft);
        case TYPE_TYPEDEF:
                return typedef_types_equal(&type1->typedeft, &type2->typedeft);
+       case TYPE_BITFIELD:
+               return bitfield_types_equal(&type1->bitfield, &type2->bitfield);
        }
 
        abort();
index 01e04c0..10ce845 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -12,7 +12,7 @@
 #include "ast_t.h"
 #include "adt/obst.h"
 
-struct obstack *type_obst;
+extern struct obstack *type_obst;
 
 typedef enum {
        TYPE_INVALID,
@@ -23,6 +23,7 @@ typedef enum {
        TYPE_FUNCTION,
        TYPE_POINTER,
        TYPE_ARRAY,
+       TYPE_BITFIELD,
        TYPE_BUILTIN,
        TYPE_TYPEDEF,
        TYPE_TYPEOF,
@@ -141,6 +142,12 @@ struct typeof_type_t {
        type_t       *resolved_type;
 };
 
+struct bitfield_type_t {
+       type_base_t   type;
+       type_t       *base;
+       expression_t *size;
+};
+
 union type_t {
        type_kind_t      kind;
        type_base_t      base;
@@ -152,6 +159,7 @@ union type_t {
        compound_type_t  compound;
        enum_type_t      enumt;
        typedef_type_t   typedeft;
+       bitfield_type_t  bitfield;
        typeof_type_t    typeoft;
 };