- add alignment to types and declarations
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Mar 2008 16:16:25 +0000 (16:16 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Mar 2008 16:16:25 +0000 (16:16 +0000)
- parses alignment and copy it to declarations
- add warnings/errors for double/wrong MS modifiers

[r18922]

ast.c
ast_t.h
parser.c
parsetest/MS/declspec.c
type.c
type_t.h
types.c

diff --git a/ast.c b/ast.c
index af5ae48..61fa312 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1213,7 +1213,7 @@ static void print_ms_modifiers(const declaration_t *declaration) {
        decl_modifiers_t modifiers = declaration->modifiers;
 
        /* DM_FORCEINLINE handled outside. */
-       if((modifiers & ~DM_FORCEINLINE) != 0) {
+       if((modifiers & ~DM_FORCEINLINE) != 0 || declaration->alignment != 0) {
                char next = '(';
 
                fputs("__declspec", out);
@@ -1244,6 +1244,9 @@ static void print_ms_modifiers(const declaration_t *declaration) {
                if(modifiers & DM_NOINLINE) {
                        fputc(next, out); next = ' '; fputs("noinline", out);
                }
+               if(declaration->alignment != 0) {
+                       fputc(next, out); next = ' '; fprintf(out, "align(%u)", declaration->alignment);
+               }
                fputs(") ", out);
        }
 }
diff --git a/ast_t.h b/ast_t.h
index cbe83ce..9610181 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -438,6 +438,7 @@ struct declaration_t {
        unsigned char       namespc;
        unsigned char       declared_storage_class;
        unsigned char       storage_class;
+       unsigned char       alignment;          /**< Alignmnet of the declaration, 0 for default. */
        decl_modifiers_t    modifiers;
        unsigned int        address_taken : 1;
        unsigned int        is_inline     : 1;
index 02bc78a..fb65bf5 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -52,6 +52,7 @@ typedef struct declaration_specifiers_t  declaration_specifiers_t;
 struct declaration_specifiers_t {
        source_position_t  source_position;
        unsigned char      declared_storage_class;
+       unsigned char      alignment;      /**< Alignment, 0 if not set. */
        bool               is_inline;
        decl_modifiers_t   decl_modifiers;
        type_t            *type;
@@ -189,7 +190,8 @@ static void *allocate_ast_zero(size_t size)
 static declaration_t *allocate_declaration_zero(void)
 {
        declaration_t *declaration = allocate_ast_zero(sizeof(declaration_t));
-       declaration->type = type_error_type;
+       declaration->type      = type_error_type;
+       declaration->alignment = 0;
        return declaration;
 }
 
@@ -1949,9 +1951,32 @@ static type_t *get_typedef_type(symbol_t *symbol)
        return type;
 }
 
-static void parse_microsoft_extended_decl_modifier(decl_modifiers_t *modifiers)
+/**
+ * check for the allowed MS alignment values.
+ */
+static bool check_elignment_value(long long intvalue) {
+       if(intvalue < 1 || intvalue > 8192) {
+               errorf(HERE, "illegal alignment value");
+               return false;
+       }
+       unsigned v = (unsigned)intvalue;
+       for(unsigned i = 1; i <= 8192; i += i) {
+               if (i == v)
+                       return true;
+       }
+       errorf(HERE, "alignment must be power of two");
+       return false;
+}
+
+#define DET_MOD(name, tag) do { \
+       if(*modifiers & tag) warningf(HERE, #name " used more than once"); \
+       *modifiers |= tag; \
+} while(0)
+
+static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *specifiers)
 {
        symbol_t         *symbol;
+       decl_modifiers_t *modifiers = &specifiers->decl_modifiers;
 
        while(true) {
                switch(token.type) {
@@ -1960,42 +1985,46 @@ static void parse_microsoft_extended_decl_modifier(decl_modifiers_t *modifiers)
                        if(symbol == sym_align) {
                                next_token();
                                expect('(');
-                               if (token.type != T_INTEGER)
+                               if(token.type != T_INTEGER)
                                        goto end_error;
-                               (void)token.v.intvalue;
+                               if(check_elignment_value(token.v.intvalue)) {
+                                       if(specifiers->alignment != 0)
+                                               warningf(HERE, "align used more than once");
+                                       specifiers->alignment = (unsigned char)token.v.intvalue;
+                               }
                                next_token();
                                expect(')');
                        } else if(symbol == sym_allocate) {
                                next_token();
                                expect('(');
-                               if (token.type != T_IDENTIFIER)
+                               if(token.type != T_IDENTIFIER)
                                        goto end_error;
                                (void)token.v.symbol;
                                expect(')');
                        } else if(symbol == sym_dllimport) {
                                next_token();
-                               *modifiers |= DM_DLLIMPORT;
+                               DET_MOD(dllimport, DM_DLLIMPORT);
                        } else if(symbol == sym_dllexport) {
                                next_token();
-                               *modifiers |= DM_DLLEXPORT;
+                               DET_MOD(dllexport, DM_DLLEXPORT);
                        } else if(symbol == sym_thread) {
                                next_token();
-                               *modifiers |= DM_THREAD;
+                               DET_MOD(thread, DM_THREAD);
                        } else if(symbol == sym_naked) {
                                next_token();
-                               *modifiers |= DM_NAKED;
+                               DET_MOD(naked, DM_NAKED);
                        } else if(symbol == sym_noinline) {
                                next_token();
-                               *modifiers |= DM_NOINLINE;
+                               DET_MOD(noinline, DM_NOINLINE);
                        } else if(symbol == sym_noreturn) {
                                next_token();
-                               *modifiers |= DM_NORETURN;
+                               DET_MOD(noreturn, DM_NORETURN);
                        } else if(symbol == sym_nothrow) {
                                next_token();
-                               *modifiers |= DM_NOTHROW;
+                               DET_MOD(nothrow, DM_NOTHROW);
                        } else if(symbol == sym_novtable) {
                                next_token();
-                               *modifiers |= DM_NOVTABLE;
+                               DET_MOD(novtable, DM_NOVTABLE);
                        } else if(symbol == sym_property) {
                                next_token();
                                expect('(');
@@ -2014,6 +2043,7 @@ static void parse_microsoft_extended_decl_modifier(decl_modifiers_t *modifiers)
                                expect(')');
                        } else if(symbol == sym_selectany) {
                                next_token();
+                               DET_MOD(selectany, DM_SELECTANY);
                        } else if(symbol == sym_uuid) {
                                next_token();
                                expect('(');
@@ -2062,7 +2092,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                case T_declspec:
                        next_token();
                        expect('(');
-                       parse_microsoft_extended_decl_modifier(&specifiers->decl_modifiers);
+                       parse_microsoft_extended_decl_modifier(specifiers);
                        expect(')');
                        break;
 
@@ -2800,6 +2830,11 @@ static declaration_t *parse_declarator(
                declaration->storage_class = STORAGE_CLASS_AUTO;
        }
 
+       if(specifiers->alignment != 0) {
+               /* TODO: add checks here */
+               declaration->alignment = specifiers->alignment;
+       }
+
        construct_type_t *construct_type
                = parse_inner_declarator(declaration, may_be_abstract);
        type_t *const type = specifiers->type;
index cdf21cc..e397865 100644 (file)
@@ -1,6 +1,6 @@
 int __declspec(align(4)) x;
 
 int __declspec(dllimport) y;
-int __declspec(dllexport) z;
+int __declspec(dllexport align(4) align (8)) z;
 
 int __declspec(noinline naked)func(void);
diff --git a/type.c b/type.c
index e12c560..89e7b75 100644 (file)
--- a/type.c
+++ b/type.c
@@ -955,8 +955,11 @@ type_t *make_atomic_type(atomic_type_kind_t atype, type_qualifiers_t qualifiers)
 
        type->kind            = TYPE_ATOMIC;
        type->base.qualifiers = qualifiers;
+       type->base.alignment  = 0;
        type->atomic.akind    = atype;
 
+       /* TODO: set the aligmnent depending on the atype here */
+
        return identify_new_type(type);
 }
 
@@ -973,6 +976,7 @@ type_t *make_pointer_type(type_t *points_to, type_qualifiers_t qualifiers)
 
        type->kind              = TYPE_POINTER;
        type->base.qualifiers   = qualifiers;
+       type->base.alignment    = 0;
        type->pointer.points_to = points_to;
 
        return identify_new_type(type);
@@ -986,6 +990,7 @@ type_t *make_array_type(type_t *element_type, size_t size,
 
        type->kind                = TYPE_ARRAY;
        type->base.qualifiers     = qualifiers;
+       type->base.alignment      = 0;
        type->array.element_type  = element_type;
        type->array.size          = size;
        type->array.size_constant = true;
index 40d6f10..2d602ec 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -92,6 +92,7 @@ typedef unsigned int type_qualifiers_t;
 struct type_base_t {
        type_kind_t       kind;
        type_qualifiers_t qualifiers;
+       unsigned char     alignment;      /**< The extra alignment of the type, 0 for default. */
        source_position_t source_position;
 
        ir_type          *firm_type;
diff --git a/types.c b/types.c
index b59e4b4..d8bae8d 100644 (file)
--- a/types.c
+++ b/types.c
@@ -64,7 +64,7 @@ type_t *type_wchar_t_ptr;
 
 void init_basic_types(void)
 {
-       static const type_base_t error = { TYPE_ERROR, TYPE_QUALIFIER_NONE, { NULL, 0 }, NULL };
+       static const type_base_t error = { TYPE_ERROR, TYPE_QUALIFIER_NONE, 0, { NULL, 0 }, NULL };
 
        type_error_type         = (type_t*)&error;
        type_signed_char        = make_atomic_type(ATOMIC_TYPE_SCHAR,       TYPE_QUALIFIER_NONE);