synchronized with edgcpfe: enabled combo by default
[cparser] / ast2firm.c
index 97814fc..3a2e220 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <libfirm/firm.h>
 #include <libfirm/adt/obst.h>
+#include <libfirm/be.h>
 
 #include "ast2firm.h"
 
@@ -95,9 +96,11 @@ ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
 {
        const declaration_t *declaration = get_irg_loc_description(irg, pos);
 
-       warningf(&declaration->source_position,
-                "variable '%#T' might be used uninitialized",
-                declaration->type, declaration->symbol);
+       if (declaration != NULL) {
+               warningf(&declaration->source_position,
+                        "variable '%#T' might be used uninitialized",
+                        declaration->type, declaration->symbol);
+       }
        return new_r_Unknown(irg, mode);
 }
 
@@ -218,8 +221,6 @@ static unsigned get_array_type_size(array_type_t *type)
 
 static unsigned get_type_size_const(type_t *type)
 {
-       type = skip_typeref(type);
-
        switch(type->kind) {
        case TYPE_ERROR:
                panic("error type occurred");
@@ -338,6 +339,21 @@ static ir_type *create_imaginary_type(const imaginary_type_t *type)
        return irtype;
 }
 
+/**
+ * return type of a parameter (and take transparent union gnu extension into
+ * account)
+ */
+static type_t *get_parameter_type(type_t *type)
+{
+       type = skip_typeref(type);
+       if (type->base.modifiers & TYPE_MODIFIER_TRANSPARENT_UNION) {
+               declaration_t *decl = type->compound.declaration;
+               type                = decl->scope.declarations->type;
+       }
+
+       return type;
+}
+
 static ir_type *create_method_type(const function_type_t *function_type)
 {
        type_t  *return_type  = function_type->return_type;
@@ -356,7 +372,8 @@ static ir_type *create_method_type(const function_type_t *function_type)
        function_parameter_t *parameter = function_type->parameters;
        int                   n         = 0;
        for ( ; parameter != NULL; parameter = parameter->next) {
-               ir_type *p_irtype = get_ir_type(parameter->type);
+               type_t  *type     = get_parameter_type(parameter->type);
+               ir_type *p_irtype = get_ir_type(type);
                set_method_param_type(irtype, n, p_irtype);
                ++n;
        }
@@ -365,6 +382,34 @@ static ir_type *create_method_type(const function_type_t *function_type)
                set_method_variadicity(irtype, variadicity_variadic);
        }
 
+       unsigned cc = get_method_calling_convention(irtype);
+       switch (function_type->calling_convention) {
+       case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typically cdecl */
+       case CC_CDECL:
+is_cdecl:
+               set_method_calling_convention(irtype, SET_CDECL(cc));
+               break;
+
+       case CC_STDCALL:
+               if (function_type->variadic || function_type->unspecified_parameters)
+                       goto is_cdecl;
+
+               /* only non-variadic function can use stdcall, else use cdecl */
+               set_method_calling_convention(irtype, SET_STDCALL(cc));
+               break;
+
+       case CC_FASTCALL:
+               if (function_type->variadic || function_type->unspecified_parameters)
+                       goto is_cdecl;
+               /* only non-variadic function can use fastcall, else use cdecl */
+               set_method_calling_convention(irtype, SET_FASTCALL(cc));
+               break;
+
+       case CC_THISCALL:
+               /* Hmm, leave default, not accepted by the parser yet. */
+               warningf(&function_type->base.source_position, "THISCALL calling convention not supported yet");
+               break;
+       }
        return irtype;
 }
 
@@ -483,7 +528,7 @@ static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp,
 static ir_type *create_bitfield_type(bitfield_type_t *const type)
 {
        type_t *base = skip_typeref(type->base_type);
-       assert(base->kind == TYPE_ATOMIC);
+       assert(base->kind == TYPE_ATOMIC || base->kind == TYPE_ENUM);
        ir_type *irbase = get_ir_type(base);
 
        unsigned size = fold_constant(type->size);
@@ -741,7 +786,6 @@ static ir_type *get_ir_type_incomplete(type_t *type)
        case TYPE_COMPOUND_STRUCT:
                return create_compound_type(&type->compound, NULL, NULL, NULL,
                                            true, COMPOUND_IS_STRUCT);
-               break;
        case TYPE_COMPOUND_UNION:
                return create_compound_type(&type->compound, NULL, NULL, NULL,
                                            true, COMPOUND_IS_UNION);
@@ -928,7 +972,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);
@@ -966,6 +1010,26 @@ typedef ident* (*create_ld_ident_func)(ir_entity *entity,
                                        declaration_t *declaration);
 create_ld_ident_func  create_ld_ident = create_ld_ident_linux_elf;
 
+/**
+ * Handle GNU attributes for entities
+ *
+ * @param ent   the entity
+ * @param decl  the routine declaration
+ */
+static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
+{
+       if (decl->modifiers & DM_PURE) {
+               /* TRUE if the declaration includes the GNU
+                  __attribute__((pure)) specifier. */
+               set_entity_additional_property(ent, mtp_property_pure);
+       }
+       if (decl->modifiers & DM_USED) {
+               /* TRUE if the declaration includes the GNU
+                  __attribute__((used)) specifier. */
+               set_entity_stickyness(ent, stickyness_sticky);
+       }
+}
+
 /**
  * Creates an entity representing a function.
  *
@@ -997,15 +1061,26 @@ static ir_entity *get_function_entity(declaration_t *declaration)
        dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
        entity               = new_d_entity(global_type, id, ir_type_method, dbgi);
        set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
-       if (declaration->storage_class == STORAGE_CLASS_STATIC &&
-               declaration->init.statement == NULL) {
-               /* this entity was declared, but never defined */
-               set_entity_peculiarity(entity, peculiarity_description);
-       }
-       if (declaration->storage_class == STORAGE_CLASS_STATIC
-                       || declaration->is_inline) {
+
+       handle_gnu_attributes_ent(entity, declaration);
+
+       /* static inline             => local
+        * extern inline             => local
+        * inline without definition => local
+        * inline with definition    => external_visible */
+       storage_class_tag_t const storage_class = declaration->storage_class;
+       bool                const is_inline     = declaration->is_inline;
+       bool                const has_body      = declaration->init.statement != NULL;
+       if (is_inline && storage_class == STORAGE_CLASS_NONE && has_body) {
+               set_entity_visibility(entity, visibility_external_visible);
+       } else if (storage_class == STORAGE_CLASS_STATIC ||
+                  (is_inline && has_body)) {
+               if (!has_body) {
+                       /* this entity was declared, but is defined nowhere */
+                       set_entity_peculiarity(entity, peculiarity_description);
+               }
                set_entity_visibility(entity, visibility_local);
-       } else if (declaration->init.statement != NULL) {
+       } else if (has_body) {
                set_entity_visibility(entity, visibility_external_visible);
        } else {
                set_entity_visibility(entity, visibility_external_allocated);
@@ -1472,9 +1547,10 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 
 /**
  * Transform a call expression.
- * Handles some special cases, like alloca() calls, which must be resolved BEFORE the inlines runs.
- * Inlining routines calling alloca() is dangerous, 176.gcc for instance might allocate 2GB instead of
- * 256 MB if alloca is not handled right...
+ * Handles some special cases, like alloca() calls, which must be resolved
+ * BEFORE the inlines runs. Inlining routines calling alloca() is dangerous,
+ * 176.gcc for instance might allocate 2GB instead of 256 MB if alloca is not
+ * handled right...
  */
 static ir_node *call_expression_to_firm(const call_expression_t *call)
 {
@@ -2072,8 +2148,13 @@ static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi,
                ir_node *value, type_t *type)
 {
        pointer_type_t *const pointer_type = &type->pointer;
-       type_t         *const points_to    = pointer_type->points_to;
-       const unsigned        elem_size    = get_type_size_const(points_to);
+       type_t         *const points_to    = skip_typeref(pointer_type->points_to);
+       unsigned              elem_size    = get_type_size_const(points_to);
+
+       /* gcc extension */
+       if (elem_size == 0 && is_type_atomic(points_to, ATOMIC_TYPE_VOID)) {
+               elem_size = 1;
+       }
 
        assert(elem_size >= 1);
        if (elem_size == 1)
@@ -3394,7 +3475,7 @@ static ir_initializer_t *create_ir_initializer_string(
        ir_initializer_t *irinitializer = create_initializer_compound(len);
 
        const char *string = initializer->string.begin;
-       ir_mode    *mode   = get_type_mode(ir_type_const_char);
+       ir_mode    *mode   = get_ir_mode(type->array.element_type);
 
        for(size_t i = 0; i < len; ++i) {
                char c = 0;
@@ -3666,6 +3747,8 @@ static void create_declaration_initializer(declaration_t *declaration)
                return;
        }
 
+       type_t *type = skip_typeref(declaration->type);
+
        if (initializer->kind == INITIALIZER_VALUE) {
                initializer_value_t *initializer_value = &initializer->value;
                dbg_info            *dbgi
@@ -3681,7 +3764,11 @@ static void create_declaration_initializer(declaration_t *declaration)
 
                        ir_entity *entity = declaration->v.entity;
 
-                       set_entity_variability(entity, variability_initialized);
+                       if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+                               set_entity_variability(entity, variability_constant);
+                       } else {
+                               set_entity_variability(entity, variability_initialized);
+                       }
                        set_atomic_ent_value(entity, value);
                }
        } else {
@@ -3690,37 +3777,52 @@ static void create_declaration_initializer(declaration_t *declaration)
 
                ir_entity        *entity        = declaration->v.entity;
                ir_initializer_t *irinitializer
-                       = create_ir_initializer(initializer, declaration->type);
+                       = create_ir_initializer(initializer, type);
 
-               set_entity_variability(entity, variability_initialized);
+               if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+                       set_entity_variability(entity, variability_constant);
+               } else {
+                       set_entity_variability(entity, variability_initialized);
+               }
                set_entity_initializer(entity, irinitializer);
        }
 }
 
 static void create_variable_length_array(declaration_t *declaration)
 {
+       /* initializers are not allowed for VLAs */
+       assert(declaration->init.initializer == NULL);
+
+       declaration->declaration_kind = DECLARATION_KIND_VARIABLE_LENGTH_ARRAY;
+       declaration->v.vla_base       = NULL;
+
+       /* TODO: record VLA somewhere so we create the free node when we leave
+        * it's scope */
+}
+
+static void allocate_variable_length_array(declaration_t *declaration)
+{
+       /* initializers are not allowed for VLAs */
+       assert(declaration->init.initializer == NULL);
+       assert(get_cur_block() != NULL);
+
        dbg_info *dbgi      = get_dbg_info(&declaration->source_position);
        type_t   *type      = declaration->type;
-       ir_node  *mem       = get_store();
        ir_type  *el_type   = get_ir_type(type->array.element_type);
 
        /* make sure size_node is calculated */
        get_type_size(type);
        ir_node  *elems = type->array.size_node;
+       ir_node  *mem   = get_store();
        ir_node  *alloc = new_d_Alloc(dbgi, mem, elems, el_type, stack_alloc);
 
        ir_node  *proj_m = new_d_Proj(dbgi, alloc, mode_M, pn_Alloc_M);
        ir_node  *addr   = new_d_Proj(dbgi, alloc, mode_P_data, pn_Alloc_res);
        set_store(proj_m);
 
-       /* initializers are not allowed for VLAs */
-       assert(declaration->init.initializer == NULL);
-
-       declaration->declaration_kind = DECLARATION_KIND_VARIABLE_LENGTH_ARRAY;
+       assert(declaration->declaration_kind
+                       == DECLARATION_KIND_VARIABLE_LENGTH_ARRAY);
        declaration->v.vla_base       = addr;
-
-       /* TODO: record VLA somewhere so we create the free node when we leave
-        * it's scope */
 }
 
 /**
@@ -3984,10 +4086,13 @@ static void initialize_local_declaration(declaration_t *declaration)
                create_declaration_initializer(declaration);
                return;
 
+       case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
+               allocate_variable_length_array(declaration);
+               return;
+
        case DECLARATION_KIND_LABEL_BLOCK:
        case DECLARATION_KIND_COMPOUND_MEMBER:
        case DECLARATION_KIND_GLOBAL_VARIABLE:
-       case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY:
        case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE:
        case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE:
        case DECLARATION_KIND_FUNCTION:
@@ -4432,29 +4537,31 @@ static void goto_to_firm(const goto_statement_t *statement)
        set_cur_block(NULL);
 }
 
-typedef enum modifier_t {
-       ASM_MODIFIER_WRITE_ONLY   = 1 << 0,
-       ASM_MODIFIER_READ_WRITE   = 1 << 1,
-       ASM_MODIFIER_COMMUTATIVE  = 1 << 2,
-       ASM_MODIFIER_EARLYCLOBBER = 1 << 3,
-} modifier_t;
-
 static void asm_statement_to_firm(const asm_statement_t *statement)
 {
-       (void) statement;
-       fprintf(stderr, "WARNING asm not implemented yet!\n");
-#if 0
        bool needs_memory = false;
 
+       if (statement->is_volatile) {
+               needs_memory = true;
+       }
+
        size_t         n_clobbers = 0;
        asm_clobber_t *clobber    = statement->clobbers;
        for( ; clobber != NULL; clobber = clobber->next) {
-               if (strcmp(clobber->clobber, "memory") == 0) {
+               const char *clobber_str = clobber->clobber.begin;
+
+               if (!be_is_valid_clobber(clobber_str)) {
+                       errorf(&statement->base.source_position,
+                                  "invalid clobber '%s' specified", clobber->clobber);
+                       continue;
+               }
+
+               if (strcmp(clobber_str, "memory") == 0) {
                        needs_memory = true;
                        continue;
                }
 
-               ident *id = new_id_from_str(clobber->clobber);
+               ident *id = new_id_from_str(clobber_str);
                obstack_ptr_grow(&asm_obst, id);
                ++n_clobbers;
        }
@@ -4464,68 +4571,216 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
                clobbers = obstack_finish(&asm_obst);
        }
 
-       /* find and count input and output constraints */
-       asm_constraint_t *constraint = statement->inputs;
-       for( ; constraint != NULL; constraint = constraint->next) {
-               int  modifiers      = 0;
-               bool supports_memop = false;
-               for(const char *c = constraint->constraints; *c != 0; ++c) {
-                       /* TODO: improve error messages */
-                       switch(*c) {
-                       case '?':
-                       case '!':
-                               panic("multiple alternative assembler constraints not "
-                                     "supported");
-                       case 'm':
-                       case 'o':
-                       case 'V':
-                       case '<':
-                       case '>':
-                       case 'X':
-                               supports_memop = true;
-                               obstack_1grow(&asm_obst, *c);
-                               break;
-                       case '=':
-                               if (modifiers & ASM_MODIFIER_READ_WRITE)
-                                       panic("inconsistent register constraints");
-                               modifiers |= ASM_MODIFIER_WRITE_ONLY;
-                               break;
-                       case '+':
-                               if (modifiers & ASM_MODIFIER_WRITE_ONLY)
-                                       panic("inconsistent register constraints");
-                               modifiers |= ASM_MODIFIER_READ_WRITE;
-                               break;
-                       case '&':
-                               modifiers |= ASM_MODIFIER_EARLYCLOBBER;
-                               panic("early clobber assembler constraint not supported yet");
-                               break;
-                       case '%':
-                               modifiers |= ASM_MODIFIER_COMMUTATIVE;
-                               panic("commutative assembler constraint not supported yet");
-                               break;
-                       case '#':
-                               /* skip register preferences stuff... */
-                               while(*c != 0 && *c != ',')
-                                       ++c;
-                               break;
-                       case '*':
-                               /* skip register preferences stuff... */
-                               ++c;
-                               break;
-                       default:
-                               obstack_1grow(&asm_obst, *c);
-                               break;
+       size_t n_inputs  = 0;
+       asm_argument_t *argument = statement->inputs;
+       for ( ; argument != NULL; argument = argument->next)
+               n_inputs++;
+       size_t n_outputs = 0;
+       argument = statement->outputs;
+       for ( ; argument != NULL; argument = argument->next)
+               n_outputs++;
+
+       unsigned next_pos = 0;
+
+       ir_node *ins[n_inputs + n_outputs + 1];
+       size_t   in_size = 0;
+
+       ir_asm_constraint *tmp_in_constraints
+               = xmalloc(n_outputs * sizeof(tmp_in_constraints[0]));
+
+       const expression_t *out_exprs[n_outputs];
+       ir_node            *out_addrs[n_outputs];
+       size_t              out_size = 0;
+
+       argument = statement->outputs;
+       for ( ; argument != NULL; argument = argument->next) {
+               const char *constraints = argument->constraints.begin;
+               asm_constraint_flags_t asm_flags
+                       = be_parse_asm_constraints(constraints);
+
+               if (asm_flags & ASM_CONSTRAINT_FLAG_NO_SUPPORT) {
+                       errorf(&statement->base.source_position,
+                              "some constraints in '%s' are not supported", constraints);
+                       continue;
+               }
+               if (asm_flags & ASM_CONSTRAINT_FLAG_INVALID) {
+                       errorf(&statement->base.source_position,
+                              "some constraints in '%s' are invalid", constraints);
+                       continue;
+               }
+               if (! (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE)) {
+                       errorf(&statement->base.source_position,
+                              "no write flag specified for output constraints '%s'",
+                              constraints);
+                       continue;
+               }
+
+               unsigned pos = next_pos++;
+               if ( (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE)
+                               || (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER) ) {
+                       expression_t *expr = argument->expression;
+                       ir_node      *addr = expression_to_addr(expr);
+                       /* in+output, construct an artifical same_as constraint on the
+                        * input */
+                       if (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ) {
+                               char     buf[64];
+                               ir_node *value = get_value_from_lvalue(expr, addr);
+
+                               snprintf(buf, sizeof(buf), "%d", pos);
+
+                               ir_asm_constraint constraint;
+                               constraint.pos              = pos;
+                               constraint.constraint       = new_id_from_str(buf);
+                               constraint.mode             = get_ir_mode(expr->base.type);
+                               tmp_in_constraints[in_size] = constraint;
+                               ins[in_size] = value;
+
+                               ++in_size;
                        }
+
+                       out_exprs[out_size] = expr;
+                       out_addrs[out_size] = addr;
+                       ++out_size;
+               } else if (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP) {
+                       /* pure memory ops need no input (but we have to make sure we
+                        * attach to the memory) */
+                       assert(! (asm_flags &
+                                               (ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
+                                                | ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER)));
+                       needs_memory = true;
+
+                       /* we need to attach the address to the inputs */
+                       expression_t *expr = argument->expression;
+
+                       ir_asm_constraint constraint;
+                       constraint.pos              = pos;
+                       constraint.constraint       = new_id_from_str(constraints);
+                       constraint.mode             = NULL;
+                       tmp_in_constraints[in_size] = constraint;
+
+                       ins[in_size]          = expression_to_addr(expr);
+                       ++in_size;
+                       continue;
+               } else {
+                       errorf(&statement->base.source_position,
+                              "only modifiers but no place set in constraints '%s'",
+                              constraints);
+                       continue;
                }
-               obstack_1grow(&asm_obst, '\0');
-               const char *constraint_string = obstack_finish(&asm_obst);
 
-               needs_memory |= supports_memop;
-               if (supports_memop) {
+               ir_asm_constraint constraint;
+               constraint.pos        = pos;
+               constraint.constraint = new_id_from_str(constraints);
+               constraint.mode       = get_ir_mode(argument->expression->base.type);
+
+               obstack_grow(&asm_obst, &constraint, sizeof(constraint));
+       }
+       assert(obstack_object_size(&asm_obst)
+                       == out_size * sizeof(ir_asm_constraint));
+       ir_asm_constraint *output_constraints = obstack_finish(&asm_obst);
+
+
+       obstack_grow(&asm_obst, tmp_in_constraints,
+                    in_size * sizeof(tmp_in_constraints[0]));
+       free(tmp_in_constraints);
+       /* find and count input and output arguments */
+       argument = statement->inputs;
+       for( ; argument != NULL; argument = argument->next) {
+               const char *constraints = argument->constraints.begin;
+               asm_constraint_flags_t asm_flags
+                       = be_parse_asm_constraints(constraints);
+
+               if (asm_flags & ASM_CONSTRAINT_FLAG_NO_SUPPORT) {
+                       errorf(&statement->base.source_position,
+                              "some constraints in '%s' are not supported", constraints);
+                       continue;
+               }
+               if (asm_flags & ASM_CONSTRAINT_FLAG_INVALID) {
+                       errorf(&statement->base.source_position,
+                              "some constraints in '%s' are invalid", constraints);
+                       continue;
+               }
+               if (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE) {
+                       errorf(&statement->base.source_position,
+                              "write flag specified for input constraints '%s'",
+                              constraints);
+                       continue;
+               }
 
+               ir_node *input;
+               if ( (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE)
+                               || (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER) ) {
+                       /* we can treat this as "normal" input */
+                       input = expression_to_firm(argument->expression);
+               } else if (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP) {
+                       /* pure memory ops need no input (but we have to make sure we
+                        * attach to the memory) */
+                       assert(! (asm_flags &
+                                               (ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
+                                                | ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER)));
+                       needs_memory = true;
+                       input = expression_to_addr(argument->expression);
+               } else {
+                       errorf(&statement->base.source_position,
+                              "only modifiers but no place set in constraints '%s'",
+                              constraints);
+                       continue;
                }
+
+               ir_asm_constraint constraint;
+               constraint.pos        = next_pos++;
+               constraint.constraint = new_id_from_str(constraints);
+               constraint.mode       = get_irn_mode(input);
+
+               obstack_grow(&asm_obst, &constraint, sizeof(constraint));
+               ins[in_size++] = input;
+       }
+
+       if (needs_memory) {
+               ir_asm_constraint constraint;
+               constraint.pos        = next_pos++;
+               constraint.constraint = new_id_from_str("");
+               constraint.mode       = mode_M;
+
+               obstack_grow(&asm_obst, &constraint, sizeof(constraint));
+               ins[in_size++] = get_store();
+       }
+
+       assert(obstack_object_size(&asm_obst)
+                       == in_size * sizeof(ir_asm_constraint));
+       ir_asm_constraint *input_constraints = obstack_finish(&asm_obst);
+
+       /* create asm node */
+       dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
+
+       ident *asm_text = new_id_from_str(statement->asm_text.begin);
+
+       ir_node *node = new_d_ASM(dbgi, in_size, ins, input_constraints,
+                                 out_size, output_constraints,
+                                 n_clobbers, clobbers, asm_text);
+
+       if (statement->is_volatile) {
+               set_irn_pinned(node, op_pin_state_pinned);
+       } else {
+               set_irn_pinned(node, op_pin_state_floats);
+       }
+
+       /* create output projs & connect them */
+       if (needs_memory) {
+               ir_node *projm = new_Proj(node, mode_M, out_size+1);
+               set_store(projm);
+       }
+
+       size_t i;
+       for (i = 0; i < out_size; ++i) {
+               const expression_t *out_expr = out_exprs[i];
+               long                pn       = i;
+               ir_mode            *mode     = get_ir_mode(out_expr->base.type);
+               ir_node            *proj     = new_Proj(node, mode, pn);
+               ir_node            *addr     = out_addrs[i];
+
+               set_value_for_expression_addr(out_expr, proj, addr);
        }
-#endif
 }
 
 static void    ms_try_statement_to_firm(ms_try_statement_t *statement) {
@@ -4618,7 +4873,8 @@ static int count_local_declarations(const declaration_t *      decl,
        for (; decl != end; decl = decl->next) {
                if (decl->namespc != NAMESPACE_NORMAL)
                        continue;
-               const type_t *type = skip_typeref(decl->type);
+               type_t *type = skip_typeref(decl->type);
+
                if (!decl->address_taken && is_type_scalar(type))
                        ++count;
                const initializer_t *initializer = decl->init.initializer;
@@ -4883,7 +5139,7 @@ static void initialize_function_parameters(declaration_t *declaration)
                long     pn    = n;
                ir_node *value = new_r_Proj(irg, start_block, args, param_mode, pn);
 
-               ir_mode *mode = get_ir_mode(parameter->type);
+               ir_mode *mode = get_ir_mode(type);
                value = create_conv(NULL, value, mode);
                value = do_strict_conv(NULL, value);
 
@@ -4931,6 +5187,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.
  */
@@ -4941,6 +5215,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;
@@ -4960,7 +5243,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);
@@ -5106,14 +5389,16 @@ void init_ast2firm(void)
                break;
        case OS_SUPPORT_LINUX:
                create_ld_ident = create_ld_ident_linux_elf;
-               s = "ia32-gasmode=linux"; break;
+               s = "ia32-gasmode=elf";
                break;
        case OS_SUPPORT_MACHO:
                create_ld_ident = create_ld_ident_macho;
-               s = "ia32-gasmode=macho"; break;
+               s = "ia32-gasmode=macho";
                break;
        }
-       firm_be_option(s);
+       int res = firm_be_option(s);
+       (void) res;
+       assert(res);
 
        /* create idents for all known runtime functions */
        for (size_t i = 0; i < sizeof(rts_data) / sizeof(rts_data[0]); ++i) {
@@ -5146,6 +5431,23 @@ void exit_ast2firm(void)
        obstack_free(&asm_obst, NULL);
 }
 
+static void global_asm_to_firm(statement_t *s)
+{
+       for (; s != NULL; s = s->base.next) {
+               assert(s->kind == STATEMENT_ASM);
+
+               char const *const text = s->asms.asm_text.begin;
+               size_t            size = s->asms.asm_text.size;
+
+               /* skip the last \0 */
+               if (text[size - 1] == '\0')
+                       --size;
+
+               ident *const id = new_id_from_chars(text, size);
+               add_irp_asm(id);
+       }
+}
+
 void translation_unit_to_firm(translation_unit_t *unit)
 {
        /* just to be sure */
@@ -5156,4 +5458,5 @@ void translation_unit_to_firm(translation_unit_t *unit)
        init_ir_types();
 
        scope_to_firm(&unit->scope);
+       global_asm_to_firm(unit->global_asm);
 }