__attribute__((sentinel)) is first available in GCC 4.
[cparser] / ast2firm.c
index d6981ef..7db20e2 100644 (file)
 
 #define MAGIC_DEFAULT_PN_NUMBER            (long) -314159265
 
+/* some idents needed for name mangling */
+static ident *id_underscore;
+static ident *id_imp;
+
 static ir_type *ir_type_const_char;
 static ir_type *ir_type_wchar_t;
 static ir_type *ir_type_void;
@@ -112,17 +116,6 @@ static dbg_info *get_dbg_info(const source_position_t *pos)
        return (dbg_info*) pos;
 }
 
-static unsigned unique_id = 0;
-
-static ident *unique_ident(const char *tag)
-{
-       char buf[256];
-
-       snprintf(buf, sizeof(buf), "%s.%u", tag, unique_id);
-       unique_id++;
-       return new_id_from_str(buf);
-}
-
 static ir_mode *_atomic_modes[ATOMIC_TYPE_LAST+1];
 
 static ir_mode *mode_int, *mode_uint;
@@ -221,6 +214,10 @@ static unsigned get_type_size_const(type_t *type)
                panic("error type occured");
        case TYPE_ATOMIC:
                return get_atomic_type_size(type->atomic.akind);
+       case TYPE_COMPLEX:
+               return 2 * get_atomic_type_size(type->complex.akind);
+       case TYPE_IMAGINARY:
+               return get_atomic_type_size(type->imaginary.akind);
        case TYPE_ENUM:
                return get_mode_size_bytes(mode_int);
        case TYPE_COMPOUND_UNION:
@@ -281,19 +278,51 @@ static unsigned count_parameters(const function_type_t *function_type)
        return count;
 }
 
+/**
+ * Creates a Firm type for an atomic type
+ */
 static ir_type *create_atomic_type(const atomic_type_t *type)
 {
        dbg_info           *dbgi      = get_dbg_info(&type->base.source_position);
        atomic_type_kind_t  kind      = type->akind;
        ir_mode            *mode      = _atomic_modes[kind];
-       unsigned            alignment = get_atomic_type_alignment(kind);
        ident              *id        = get_mode_ident(mode);
        ir_type            *irtype    = new_d_type_primitive(id, mode, dbgi);
 
-       if(type->base.alignment > alignment)
-               alignment = type->base.alignment;
+       set_type_alignment_bytes(irtype, type->base.alignment);
 
-       set_type_alignment_bytes(irtype, alignment);
+       return irtype;
+}
+
+/**
+ * Creates a Firm type for a complex type
+ */
+static ir_type *create_complex_type(const complex_type_t *type)
+{
+       dbg_info           *dbgi      = get_dbg_info(&type->base.source_position);
+       atomic_type_kind_t  kind      = type->akind;
+       ir_mode            *mode      = _atomic_modes[kind];
+       ident              *id        = get_mode_ident(mode);
+
+       (void) id;
+       (void) dbgi;
+
+       /* FIXME: finish the array */
+       return NULL;
+}
+
+/**
+ * Creates a Firm type for an imaginary type
+ */
+static ir_type *create_imaginary_type(const imaginary_type_t *type)
+{
+       dbg_info           *dbgi      = get_dbg_info(&type->base.source_position);
+       atomic_type_kind_t  kind      = type->akind;
+       ir_mode            *mode      = _atomic_modes[kind];
+       ident              *id        = get_mode_ident(mode);
+       ir_type            *irtype    = new_d_type_primitive(id, mode, dbgi);
+
+       set_type_alignment_bytes(irtype, type->base.alignment);
 
        return irtype;
 }
@@ -302,7 +331,7 @@ static ir_type *create_method_type(const function_type_t *function_type)
 {
        type_t  *return_type  = function_type->return_type;
 
-       ident   *id           = unique_ident("functiontype");
+       ident   *id           = id_unique("functiontype.%u");
        int      n_parameters = count_parameters(function_type);
        int      n_results    = return_type == type_void ? 0 : 1;
        dbg_info *dbgi        = get_dbg_info(&function_type->base.source_position);
@@ -337,7 +366,7 @@ static ir_type *create_pointer_type(pointer_type_t *type)
         * and then set the real points_to type
         */
        dbg_info *dbgi    = get_dbg_info(&type->base.source_position);
-       ir_type  *ir_type = new_d_type_pointer(unique_ident("pointer"),
+       ir_type  *ir_type = new_d_type_pointer(id_unique("pointer.%u"),
                                            ir_type_void, mode_P_data, dbgi);
        type->base.firm_type  = ir_type;
 
@@ -352,7 +381,7 @@ static ir_type *create_array_type(array_type_t *type)
        type_t  *element_type    = type->element_type;
        ir_type *ir_element_type = get_ir_type(element_type);
 
-       ident    *id      = unique_ident("array");
+       ident    *id      = id_unique("array.%u");
        dbg_info *dbgi    = get_dbg_info(&type->base.source_position);
        ir_type  *ir_type = new_d_type_array(id, 1, ir_element_type, dbgi);
 
@@ -484,9 +513,9 @@ static ir_type *create_struct_type(compound_type_t *type, ir_type *irtype,
                symbol_t *symbol = declaration->symbol;
                ident    *id;
                if(symbol != NULL) {
-                       id = unique_ident(symbol->string);
+                       id = new_id_from_str(symbol->string);
                } else {
-                       id = unique_ident("__anonymous_struct");
+                       id = id_unique("__anonymous_struct.%u");
                }
                dbg_info *dbgi  = get_dbg_info(&type->base.source_position);
 
@@ -522,7 +551,7 @@ static ir_type *create_struct_type(compound_type_t *type, ir_type *irtype,
                        } else {
                                assert(entry_type->kind == TYPE_BITFIELD);
                        }
-                       ident = unique_ident("anon");
+                       ident = id_unique("anon.%u");
                }
 
                ir_type *base_irtype;
@@ -619,9 +648,9 @@ static ir_type *create_union_type(compound_type_t *type, ir_type *irtype,
                symbol_t      *symbol      = declaration->symbol;
                ident         *id;
                if(symbol != NULL) {
-                       id = unique_ident(symbol->string);
+                       id = new_id_from_str(symbol->string);
                } else {
-                       id = unique_ident("__anonymous_union");
+                       id = id_unique("__anonymous_union.%u");
                }
                dbg_info *dbgi = get_dbg_info(&type->base.source_position);
 
@@ -665,7 +694,7 @@ static ir_type *create_union_type(compound_type_t *type, ir_type *irtype,
                        if(entry_size > size) {
                                size = entry_size;
                        }
-                       ident = unique_ident("anon");
+                       ident = id_unique("anon.%u");
                }
 
                size_t entry_size      = get_type_size_bytes(entry_ir_type);
@@ -759,10 +788,16 @@ static ir_type *get_ir_type(type_t *type)
        ir_type *firm_type = NULL;
        switch(type->kind) {
        case TYPE_ERROR:
-               panic("error type occured");
+               panic("error type occurred");
        case TYPE_ATOMIC:
                firm_type = create_atomic_type(&type->atomic);
                break;
+       case TYPE_COMPLEX:
+               firm_type = create_complex_type(&type->complex);
+               break;
+       case TYPE_IMAGINARY:
+               firm_type = create_imaginary_type(&type->imaginary);
+               break;
        case TYPE_FUNCTION:
                firm_type = create_method_type(&type->function);
                break;
@@ -900,44 +935,58 @@ static const struct {
 /**
  * Mangles an entity linker (ld) name for win32 usage.
  *
- * @param ent             the entity to be mangled
- * @param decl_modifiers  the set of modifiers for this entity
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
  */
-static ir_ident_ptr decorate_win32(ir_entity_ptr ent, decl_modifiers_t decl_modifiers) {
-       ir_ident_ptr id;
+static ident *create_ld_ident_win32(ir_entity *ent, declaration_t *declaration)
+{
+       ident *id;
 
        if (is_Method_type(get_entity_type(ent)))
                id = decorate_win32_c_fkt(ent, get_entity_ident(ent));
        else {
                /* always add an underscore in win32 */
-               id = mangle(new_id_from_chars("_", 1), get_entity_ident(ent));
+               id = mangle(id_underscore, get_entity_ident(ent));
        }
 
+       decl_modifiers_t decl_modifiers = declaration->decl_modifiers;
        if (decl_modifiers & DM_DLLIMPORT) {
                /* add prefix for imported symbols */
-               id = mangle(new_id_from_chars("__imp_", 6), id);
+               id = mangle(id_imp, id);
        }
        return id;
 }
 
 /**
- * Mangles an entity linker (ld) name from a declaration.
+ * Mangles an entity linker (ld) name for Linux ELF usage.
  *
- * @param ent             the entity to be mangled
- * @param declaration     the declaration
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
  */
-static void mangle_ent_from_decl(ir_entity *ent, declaration_t *declaration)
+static ident *create_ld_ident_linux_elf(ir_entity *entity,
+                                        declaration_t *declaration)
 {
-       ident *id;
-
-       if (firm_opt.os_support == OS_SUPPORT_MINGW)
-               id = decorate_win32(ent, declaration->decl_modifiers);
-       else
-               id = get_entity_ident(ent);
+       (void) declaration;
+       return get_entity_ident(entity);
+}
 
-       set_entity_ld_ident(ent, id);
+/**
+ * Mangles an entity linker (ld) name for Mach-O usage.
+ *
+ * @param ent          the entity to be mangled
+ * @param declaration  the declaration
+ */
+static ident *create_ld_ident_macho(ir_entity *ent, declaration_t *declaration)
+{
+       (void) declaration;
+       ident *id = mangle(id_underscore, get_entity_ident(ent));
+       return id;
 }
 
+typedef ident* (*create_ld_ident_func)(ir_entity *entity,
+                                       declaration_t *declaration);
+create_ld_ident_func  create_ld_ident = create_ld_ident_linux_elf;
+
 static ir_entity* get_function_entity(declaration_t *declaration)
 {
        if(declaration->declaration_kind == DECLARATION_KIND_FUNCTION)
@@ -953,7 +1002,7 @@ static ir_entity* get_function_entity(declaration_t *declaration)
 
        dbg_info  *const dbgi   = get_dbg_info(&declaration->source_position);
        ir_entity *const entity = new_d_entity(global_type, id, ir_type_method, dbgi);
-       mangle_ent_from_decl(entity, declaration);
+       set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
        if(declaration->storage_class == STORAGE_CLASS_STATIC
                        || declaration->is_inline) {
                set_entity_visibility(entity, visibility_local);
@@ -1048,7 +1097,7 @@ static ir_node *wide_character_constant_to_firm(const const_expression_t *cnst)
 }
 
 static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode,
-                                ir_entity *entity)
+                              ir_entity *entity)
 {
        assert(entity != NULL);
        union symconst_symbol sym;
@@ -1062,10 +1111,10 @@ static ir_node *string_to_firm(const source_position_t *const src_pos,
 {
        ir_type  *const global_type = get_glob_type();
        dbg_info *const dbgi        = get_dbg_info(src_pos);
-       ir_type  *const type        = new_d_type_array(unique_ident("strtype"), 1,
+       ir_type  *const type        = new_d_type_array(id_unique("strtype.%u"), 1,
                                                       ir_type_const_char, dbgi);
 
-       ident     *const id     = unique_ident(id_prefix);
+       ident     *const id     = id_unique(id_prefix);
        ir_entity *const entity = new_d_entity(global_type, id, type, dbgi);
        set_entity_ld_ident(entity, id);
        set_entity_variability(entity, variability_constant);
@@ -1096,7 +1145,7 @@ static ir_node *string_to_firm(const source_position_t *const src_pos,
 static ir_node *string_literal_to_firm(
                const string_literal_expression_t* literal)
 {
-       return string_to_firm(&literal->base.source_position, "Lstr",
+       return string_to_firm(&literal->base.source_position, "Lstr.%u",
                              &literal->value);
 }
 
@@ -1106,10 +1155,10 @@ static ir_node *wide_string_literal_to_firm(
        ir_type *const global_type = get_glob_type();
        ir_type *const elem_type   = ir_type_wchar_t;
        dbg_info *const dbgi       = get_dbg_info(&literal->base.source_position);
-       ir_type *const type        = new_d_type_array(unique_ident("strtype"), 1,
+       ir_type *const type        = new_d_type_array(id_unique("strtype.%u"), 1,
                                                    elem_type, dbgi);
 
-       ident     *const id     = unique_ident("Lstr");
+       ident     *const id     = id_unique("Lstr.%u");
        ir_entity *const entity = new_d_entity(global_type, id, type, dbgi);
        set_entity_ld_ident(entity, id);
        set_entity_variability(entity, variability_constant);
@@ -1384,7 +1433,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
                 * arguments... */
                int n_res       = get_method_n_ress(ir_method_type);
                dbg_info *dbgi  = get_dbg_info(&call->base.source_position);
-               new_method_type = new_d_type_method(unique_ident("calltype"),
+               new_method_type = new_d_type_method(id_unique("calltype.%u"),
                                                  n_parameters, n_res, dbgi);
                set_method_calling_convention(new_method_type,
                               get_method_calling_convention(ir_method_type));
@@ -2330,7 +2379,7 @@ static ir_node *compound_literal_to_firm(
        /* create an entity on the stack */
        ir_type *frame_type = get_irg_frame_type(current_ir_graph);
 
-       ident     *const id     = unique_ident("CompLit");
+       ident     *const id     = id_unique("CompLit.%u");
        ir_type   *const irtype = get_ir_type(type);
        dbg_info  *const dbgi   = get_dbg_info(&expression->base.source_position);
        ir_entity *const entity = new_d_entity(frame_type, id, irtype, dbgi);
@@ -2534,7 +2583,7 @@ static ir_node *classify_type_to_firm(const classify_type_expression_t *const ex
        {
                case TYPE_ATOMIC: {
                        const atomic_type_t *const atomic_type = &type->atomic;
-                       switch ((atomic_type_kind_t) atomic_type->akind) {
+                       switch (atomic_type->akind) {
                                /* should not be reached */
                                case ATOMIC_TYPE_INVALID:
                                        tc = no_type_class;
@@ -2565,21 +2614,12 @@ static ir_node *classify_type_to_firm(const classify_type_expression_t *const ex
                                case ATOMIC_TYPE_LONG_DOUBLE:
                                        tc = real_type_class;
                                        goto make_const;
-
-                               case ATOMIC_TYPE_FLOAT_COMPLEX:
-                               case ATOMIC_TYPE_DOUBLE_COMPLEX:
-                               case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
-                                       tc = complex_type_class;
-                                       goto make_const;
-                               case ATOMIC_TYPE_FLOAT_IMAGINARY:
-                               case ATOMIC_TYPE_DOUBLE_IMAGINARY:
-                               case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
-                                       tc = complex_type_class;
-                                       goto make_const;
                        }
                        panic("Unexpected atomic type in classify_type_to_firm().");
                }
 
+               case TYPE_COMPLEX:         tc = complex_type_class; goto make_const;
+               case TYPE_IMAGINARY:       tc = complex_type_class; goto make_const;
                case TYPE_BITFIELD:        tc = integer_type_class; goto make_const;
                case TYPE_ARRAY:           /* gcc handles this as pointer */
                case TYPE_FUNCTION:        /* gcc handles this as pointer */
@@ -2618,7 +2658,7 @@ static ir_node *function_name_to_firm(
                        const source_position_t *const src_pos = &expr->base.source_position;
                        const char *const name = current_function_decl->symbol->string;
                        const string_t string = { name, strlen(name) + 1 };
-                       current_function_name = string_to_firm(src_pos, "__func__", &string);
+                       current_function_name = string_to_firm(src_pos, "__func__.%u", &string);
                }
                return current_function_name;
        case FUNCNAME_FUNCSIG:
@@ -2627,7 +2667,7 @@ static ir_node *function_name_to_firm(
                        ir_entity *ent = get_irg_entity(current_ir_graph);
                        const char *const name = get_entity_ld_name(ent);
                        const string_t string = { name, strlen(name) + 1 };
-                       current_funcsig = string_to_firm(src_pos, "__FUNCSIG__", &string);
+                       current_funcsig = string_to_firm(src_pos, "__FUNCSIG__.%u", &string);
                }
                return current_funcsig;
        }
@@ -2896,11 +2936,11 @@ static void create_declaration_entity(declaration_t *declaration,
        ir_type   *const irtype = get_ir_type(type);
        dbg_info  *const dbgi   = get_dbg_info(&declaration->source_position);
        ir_entity *const entity = new_d_entity(parent_type, id, irtype, dbgi);
-       mangle_ent_from_decl(entity, declaration);
 
        declaration->declaration_kind = (unsigned char) declaration_kind;
        declaration->v.entity         = entity;
        set_entity_variability(entity, variability_uninitialized);
+       set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
        if(parent_type == get_tls_type())
                set_entity_allocation(entity, allocation_automatic);
        else if(declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
@@ -3232,7 +3272,7 @@ static ir_initializer_t *create_ir_initializer_string(
                if(i < string_len)
                        c = string[i];
 
-               tarval           *tv = new_tarval_from_long(string[i], mode);
+               tarval           *tv = new_tarval_from_long(c, mode);
                ir_initializer_t *char_initializer = create_initializer_tarval(tv);
 
                set_initializer_compound_value(irinitializer, i, char_initializer);
@@ -3257,7 +3297,7 @@ static ir_initializer_t *create_ir_initializer_wide_string(
                if(i < string_len) {
                        c = string[i];
                }
-               tarval *tv = new_tarval_from_long(string[i], mode);
+               tarval *tv = new_tarval_from_long(c, mode);
                ir_initializer_t *char_initializer = create_initializer_tarval(tv);
 
                set_initializer_compound_value(irinitializer, i, char_initializer);
@@ -3289,6 +3329,7 @@ static ir_initializer_t *create_ir_initializer(
        panic("unknown initializer");
 }
 
+#if 0
 static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi,
                                             ir_node *base_addr)
 {
@@ -3302,6 +3343,7 @@ static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi,
        ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M);
        set_store(proj_m);
 }
+#endif
 
 static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                ir_type *type, dbg_info *dbgi, ir_node *base_addr)
@@ -3435,7 +3477,7 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi,
        current_ir_graph = old_current_ir_graph;
 
        /* create a "template" entity which is copied to the entity on the stack */
-       ident     *const id          = unique_ident("initializer");
+       ident     *const id          = id_unique("initializer.%u");
        ir_type   *const irtype      = get_ir_type(type);
        ir_type   *const global_type = get_glob_type();
        ir_entity *const init_entity = new_d_entity(global_type, id, irtype, dbgi);
@@ -3571,11 +3613,10 @@ static void create_local_static_variable(declaration_t *declaration)
 
        type_t    *const type        = skip_typeref(declaration->type);
        ir_type   *const global_type = get_glob_type();
-       ident     *const id          = unique_ident(declaration->symbol->string);
+       ident     *const id          = new_id_from_str(declaration->symbol->string);
        ir_type   *const irtype      = get_ir_type(type);
        dbg_info  *const dbgi        = get_dbg_info(&declaration->source_position);
        ir_entity *const entity      = new_d_entity(global_type, id, irtype, dbgi);
-       mangle_ent_from_decl(entity, declaration);
 
        if(type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
                set_entity_volatility(entity, volatility_is_volatile);
@@ -3583,6 +3624,7 @@ static void create_local_static_variable(declaration_t *declaration)
 
        declaration->declaration_kind = DECLARATION_KIND_GLOBAL_VARIABLE;
        declaration->v.entity         = entity;
+       set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
        set_entity_variability(entity, variability_uninitialized);
        set_entity_visibility(entity, visibility_local);
        set_entity_allocation(entity, allocation_static);
@@ -4795,6 +4837,27 @@ void init_ast2firm(void)
        obstack_init(&asm_obst);
        init_atomic_modes();
 
+       id_underscore = new_id_from_chars("_", 1);
+       id_imp        = new_id_from_chars("__imp_", 6);
+
+       /* OS option must be set to the backend */
+       const char *s = "ia32-gasmode=linux";
+       switch (firm_opt.os_support) {
+       case OS_SUPPORT_WIN32:
+               create_ld_ident = create_ld_ident_win32;
+               s = "ia32-gasmode=mingw";
+               break;
+       case OS_SUPPORT_LINUX:
+               create_ld_ident = create_ld_ident_linux_elf;
+               s = "ia32-gasmode=linux"; break;
+               break;
+       case OS_SUPPORT_MACHO:
+               create_ld_ident = create_ld_ident_macho;
+               s = "ia32-gasmode=macho"; break;
+               break;
+       }
+       firm_be_option(s);
+
        /* create idents for all known runtime functions */
        for (size_t i = 0; i < sizeof(rts_data) / sizeof(rts_data[0]); ++i) {
                predef_idents[rts_data[i].id] = new_id_from_str(rts_data[i].name);