do something with some of the gnu attributes
authorMatthias Braun <matze@braunis.de>
Thu, 31 Jul 2008 09:18:06 +0000 (09:18 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 31 Jul 2008 09:18:06 +0000 (09:18 +0000)
[r20829]

ast.c
ast2firm.c
ast_t.h
parser.c
parsetest/gnu99/construct_destruct.c [new file with mode: 0644]

diff --git a/ast.c b/ast.c
index 80fadcc..7869a05 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1268,7 +1268,7 @@ static void print_ms_modifiers(const declaration_t *declaration) {
        if((c_mode & _MS) == 0)
                return;
 
-       decl_modifiers_t modifiers = declaration->decl_modifiers;
+       decl_modifiers_t modifiers = declaration->modifiers;
 
        /* DM_FORCEINLINE handled outside. */
        if((modifiers & ~DM_FORCEINLINE) != 0 ||
@@ -1342,10 +1342,10 @@ static void print_normal_declaration(const declaration_t *declaration)
 {
        print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
        if(declaration->is_inline) {
-               if(declaration->decl_modifiers & DM_FORCEINLINE)
+               if(declaration->modifiers & DM_FORCEINLINE)
                        fputs("__forceinline ", out);
                else {
-                       if(declaration->decl_modifiers & DM_MICROSOFT_INLINE)
+                       if(declaration->modifiers & DM_MICROSOFT_INLINE)
                                fputs("__inline ", out);
                        else
                                fputs("inline ", out);
index 7b248a7..35ceade 100644 (file)
@@ -928,7 +928,7 @@ static ident *create_ld_ident_win32(ir_entity *ent, declaration_t *declaration)
                id = mangle(id_underscore, get_entity_ident(ent));
        }
 
-       decl_modifiers_t decl_modifiers = declaration->decl_modifiers;
+       decl_modifiers_t decl_modifiers = declaration->modifiers;
        if (decl_modifiers & DM_DLLIMPORT) {
                /* add prefix for imported symbols */
                id = mangle(id_imp, id);
@@ -5099,6 +5099,24 @@ static void handle_decl_modifier_irg(ir_graph_ptr irg, decl_modifiers_t decl_mod
        }
 }
 
+static void add_function_pointer(ir_type *segment, ir_entity *method,
+                                 const char *unique_template)
+{
+       ir_type   *method_type  = get_entity_type(method);
+       ident     *id           = id_unique(unique_template);
+       ir_type   *ptr_type     = new_type_pointer(id, method_type, mode_P_code);
+
+       ident     *ide          = id_unique(unique_template);
+       ir_entity *ptr          = new_entity(segment, ide, ptr_type);
+       ir_graph  *irg          = get_const_code_irg();
+       ir_node   *val          = new_rd_SymConst_addr_ent(NULL, irg, mode_P_code,
+                                                          method, NULL);
+
+       set_entity_compiler_generated(ptr, 1);
+       set_entity_variability(ptr, variability_constant);
+       set_atomic_ent_value(ptr, val);
+}
+
 /**
  * Create code for a function.
  */
@@ -5109,6 +5127,15 @@ static void create_function(declaration_t *declaration)
        if (declaration->init.statement == NULL)
                return;
 
+       if (declaration->modifiers & DM_CONSTRUCTOR) {
+               ir_type *segment = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
+               add_function_pointer(segment, function_entity, "constructor_ptr.%u");
+       }
+       if (declaration->modifiers & DM_DESTRUCTOR) {
+               ir_type *segment = get_segment_type(IR_SEGMENT_DESTRUCTORS);
+               add_function_pointer(segment, function_entity, "destructor_ptr.%u");
+       }
+
        current_function_decl = declaration;
        current_function_name = NULL;
        current_funcsig       = NULL;
@@ -5128,7 +5155,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);
diff --git a/ast_t.h b/ast_t.h
index 3221f3c..aa5a8bb 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -510,29 +510,34 @@ typedef enum gnu_attribute_kind_t {
  * Extended microsoft modifier.
  */
 typedef enum {
-       DM_DLLIMPORT        = (1 <<  0),
-       DM_DLLEXPORT        = (1 <<  1),
-       DM_THREAD           = (1 <<  2),
-       DM_NAKED            = (1 <<  3),
-       DM_MICROSOFT_INLINE = (1 <<  4),
-       DM_FORCEINLINE      = (1 <<  5),
-       DM_SELECTANY        = (1 <<  6),
-       DM_NOTHROW          = (1 <<  7),
-       DM_NOVTABLE         = (1 <<  8),
-       DM_NORETURN         = (1 <<  9),
-       DM_NOINLINE         = (1 << 10),
-       DM_RESTRICT         = (1 << 11),
-       DM_NOALIAS          = (1 << 12)
+       DM_DLLIMPORT         = (1 <<  0),
+       DM_DLLEXPORT         = (1 <<  1),
+       DM_THREAD            = (1 <<  2),
+       DM_NAKED             = (1 <<  3),
+       DM_MICROSOFT_INLINE  = (1 <<  4),
+       DM_FORCEINLINE       = (1 <<  5),
+       DM_SELECTANY         = (1 <<  6),
+       DM_NOTHROW           = (1 <<  7),
+       DM_NOVTABLE          = (1 <<  8),
+       DM_NORETURN          = (1 <<  9),
+       DM_NOINLINE          = (1 << 10),
+       DM_RESTRICT          = (1 << 11),
+       DM_NOALIAS           = (1 << 12),
+       DM_PACKED            = (1 << 13),
+       DM_TRANSPARENT_UNION = (1 << 14),
+       DM_PURE              = (1 << 15),
+       DM_CONSTRUCTOR       = (1 << 16),
+       DM_DESTRUCTOR        = (1 << 17)
 } decl_modifier_t;
 
-typedef unsigned short decl_modifiers_t;
+typedef unsigned decl_modifiers_t;
 
 struct declaration_t {
        unsigned char       namespc;
        unsigned char       declared_storage_class;
        unsigned char       storage_class;
        unsigned char       alignment;          /**< Alignment of the declaration, 0 for default. */
-       decl_modifiers_t    decl_modifiers;     /**< MS __declspec modifiers. */
+       decl_modifiers_t    modifiers;          /**< modifiers. */
        const char         *deprecated_string;  /**< MS deprecated string if any. */
        symbol_t           *get_property_sym;   /**< MS get property. */
        symbol_t           *put_property_sym;   /**< MS put property. */
index ac0a255..80e17c0 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -67,7 +67,7 @@ struct declaration_specifiers_t {
        unsigned char      alignment;         /**< Alignment, 0 if not set. */
        unsigned int       is_inline : 1;
        unsigned int       deprecated : 1;
-       decl_modifiers_t   decl_modifiers;    /**< MS __declspec extended modifier mask */
+       decl_modifiers_t   modifiers;         /**< declaration modifiers */
        gnu_attribute_t   *gnu_attributes;    /**< list of GNU attributes */
        const char        *deprecated_string; /**< can be set if declaration was marked deprecated. */
        symbol_t          *get_property_sym;  /**< the name of the get property if set. */
@@ -1311,6 +1311,19 @@ end_error:
        attribute->u.value = true;
 }
 
+static void check_no_argument(gnu_attribute_t *attribute, const char *name)
+{
+       if(!attribute->have_arguments)
+               return;
+
+       /* should have no arguments */
+       errorf(HERE, "wrong number of arguments specified for '%s' attribute", name);
+       eat_until_matching_token('(');
+       /* we have already consumed '(', so we stop before ')', eat it */
+       eat(')');
+       attribute->invalid = true;
+}
+
 /**
  * Parse one GNU attribute.
  *
@@ -1387,10 +1400,11 @@ end_error:
  *  interrupt( string literal )
  *  sentinel( constant expression )
  */
-static void parse_gnu_attribute(gnu_attribute_t **attributes)
+static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes)
 {
-       gnu_attribute_t *head = *attributes;
-       gnu_attribute_t *last = *attributes;
+       gnu_attribute_t *head      = *attributes;
+       gnu_attribute_t *last      = *attributes;
+       decl_modifiers_t modifiers = 0;
        gnu_attribute_t *attribute;
 
        eat(T___attribute__);
@@ -1457,20 +1471,11 @@ static void parse_gnu_attribute(gnu_attribute_t **attributes)
                                case GNU_AK_STDCALL:
                                case GNU_AK_FASTCALL:
                                case GNU_AK_DEPRECATED:
-                               case GNU_AK_NOINLINE:
-                               case GNU_AK_NORETURN:
                                case GNU_AK_NAKED:
-                               case GNU_AK_PURE:
-                               case GNU_AK_ALWAYS_INLINE:
                                case GNU_AK_MALLOC:
                                case GNU_AK_WEAK:
-                               case GNU_AK_CONSTRUCTOR:
-                               case GNU_AK_DESTRUCTOR:
-                               case GNU_AK_NOTHROW:
-                               case GNU_AK_TRANSPARENT_UNION:
                                case GNU_AK_COMMON:
                                case GNU_AK_NOCOMMON:
-                               case GNU_AK_PACKED:
                                case GNU_AK_SHARED:
                                case GNU_AK_NOTSHARED:
                                case GNU_AK_USED:
@@ -1498,16 +1503,62 @@ static void parse_gnu_attribute(gnu_attribute_t **attributes)
                                case GNU_AK_MAY_ALIAS:
                                case GNU_AK_MS_STRUCT:
                                case GNU_AK_GCC_STRUCT:
+                                       check_no_argument(attribute, name);
+                                       break;
+
+                               case GNU_AK_PURE:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_PURE;
+                                       break;
+
+                               case GNU_AK_ALWAYS_INLINE:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_FORCEINLINE;
+                                       break;
+
                                case GNU_AK_DLLIMPORT:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_DLLIMPORT;
+                                       break;
+
                                case GNU_AK_DLLEXPORT:
-                                       if(attribute->have_arguments) {
-                                               /* should have no arguments */
-                                               errorf(HERE, "wrong number of arguments specified for '%s' attribute", name);
-                                               eat_until_matching_token('(');
-                                               /* we have already consumed '(', so we stop before ')', eat it */
-                                               eat(')');
-                                               attribute->invalid = true;
-                                       }
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_DLLEXPORT;
+                                       break;
+
+                               case GNU_AK_PACKED:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_PACKED;
+                                       break;
+
+                               case GNU_AK_NOINLINE:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_NOINLINE;
+                                       break;
+
+                               case GNU_AK_NORETURN:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_NORETURN;
+                                       break;
+
+                               case GNU_AK_NOTHROW:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_NOTHROW;
+                                       break;
+
+                               case GNU_AK_TRANSPARENT_UNION:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_TRANSPARENT_UNION;
+                                       break;
+
+                               case GNU_AK_CONSTRUCTOR:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_CONSTRUCTOR;
+                                       break;
+
+                               case GNU_AK_DESTRUCTOR:
+                                       check_no_argument(attribute, name);
+                                       modifiers |= DM_DESTRUCTOR;
                                        break;
 
                                case GNU_AK_ALIGNED:
@@ -1611,17 +1662,21 @@ static void parse_gnu_attribute(gnu_attribute_t **attributes)
        expect(')');
 end_error:
        *attributes = head;
+
+       return modifiers;
 }
 
 /**
  * Parse GNU attributes.
  */
-static void parse_attributes(gnu_attribute_t **attributes)
+static decl_modifiers_t parse_attributes(gnu_attribute_t **attributes)
 {
+       decl_modifiers_t modifiers = 0;
+
        while(true) {
                switch(token.type) {
                case T___attribute__: {
-                       parse_gnu_attribute(attributes);
+                       modifiers |= parse_gnu_attribute(attributes);
                        break;
                }
                case T_asm:
@@ -1644,7 +1699,7 @@ static void parse_attributes(gnu_attribute_t **attributes)
 
 attributes_finished:
 end_error:
-       return;
+       return modifiers;
 }
 
 static designator_t *parse_designation(void)
@@ -2718,7 +2773,7 @@ static bool check_elignment_value(long long intvalue) {
 
 static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *specifiers)
 {
-       decl_modifiers_t *modifiers = &specifiers->decl_modifiers;
+       decl_modifiers_t *modifiers = &specifiers->modifiers;
 
        while(true) {
                if(token.type == T_restrict) {
@@ -2961,7 +3016,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
 
                case T__forceinline:
                        /* only in microsoft mode */
-                       specifiers->decl_modifiers |= DM_FORCEINLINE;
+                       specifiers->modifiers |= DM_FORCEINLINE;
 
                case T_inline:
                        next_token();
@@ -3003,7 +3058,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        break;
 
                case T___attribute__:
-                       parse_attributes(&specifiers->gnu_attributes);
+                       specifiers->modifiers
+                               |= parse_attributes(&specifiers->gnu_attributes);
                        break;
 
                case T_IDENTIFIER: {
@@ -3522,7 +3578,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
        }
 
        /* TODO: find out if this is correct */
-       parse_attributes(&attributes);
+       declaration->modifiers |= parse_attributes(&attributes);
 
        construct_type_t *inner_types = NULL;
 
@@ -3586,7 +3642,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
        }
 
 declarator_finished:
-       parse_attributes(&attributes);
+       declaration->modifiers |= parse_attributes(&attributes);
 
        /* append inner_types at the end of the list, we don't to set last anymore
         * as it's not needed anymore */
@@ -3697,7 +3753,7 @@ static declaration_t *parse_declarator(
 {
        declaration_t *const declaration    = allocate_declaration_zero();
        declaration->declared_storage_class = specifiers->declared_storage_class;
-       declaration->decl_modifiers         = specifiers->decl_modifiers;
+       declaration->modifiers              = specifiers->modifiers;
        declaration->deprecated             = specifiers->deprecated;
        declaration->deprecated_string      = specifiers->deprecated_string;
        declaration->get_property_sym       = specifiers->get_property_sym;
@@ -4050,7 +4106,7 @@ static void parse_anonymous_declaration_rest(
        declaration->type                   = specifiers->type;
        declaration->declared_storage_class = specifiers->declared_storage_class;
        declaration->source_position        = specifiers->source_position;
-       declaration->decl_modifiers         = specifiers->decl_modifiers;
+       declaration->modifiers              = specifiers->modifiers;
 
        if (declaration->declared_storage_class != STORAGE_CLASS_NONE) {
                warningf(&declaration->source_position,
@@ -4527,7 +4583,7 @@ static void parse_compound_declarators(declaration_t *struct_declaration,
                        declaration->declared_storage_class = STORAGE_CLASS_NONE;
                        declaration->storage_class          = STORAGE_CLASS_NONE;
                        declaration->source_position        = source_position;
-                       declaration->decl_modifiers         = specifiers->decl_modifiers;
+                       declaration->modifiers              = specifiers->modifiers;
                        declaration->type                   = type;
                } else {
                        declaration = parse_declarator(specifiers,/*may_be_abstract=*/true);
diff --git a/parsetest/gnu99/construct_destruct.c b/parsetest/gnu99/construct_destruct.c
new file mode 100644 (file)
index 0000000..6a33018
--- /dev/null
@@ -0,0 +1,17 @@
+int puts(const char *str);
+
+void __attribute__((constructor)) construct(void)
+{
+       puts("Hello");
+}
+
+void __attribute__((destructor)) destruct(void)
+{
+       puts("Goobye");
+}
+
+int main(void)
+{
+       puts("Main");
+       return 0;
+}