improve/cleanup some tests
[cparser] / ast2firm.c
index a042cca..7211342 100644 (file)
@@ -133,10 +133,10 @@ static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
        if( (flags & (ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_FLOAT))
                        && !(flags & ATOMIC_TYPE_FLAG_COMPLEX)) {
                char            name[64];
-               mode_sort       sort;
+               ir_mode_sort    sort;
                unsigned        bit_size     = size * 8;
                bool            is_signed    = (flags & ATOMIC_TYPE_FLAG_SIGNED) != 0;
-               mode_arithmetic arithmetic;
+               ir_mode_arithmetic arithmetic;
                unsigned        modulo_shift;
 
                if(flags & ATOMIC_TYPE_FLAG_INTEGER) {
@@ -175,10 +175,10 @@ static void init_atomic_modes(void)
 
        /* initialize pointer modes */
        char            name[64];
-       mode_sort       sort         = irms_reference;
+       ir_mode_sort    sort         = irms_reference;
        unsigned        bit_size     = machine_size;
        bool            is_signed    = 0;
-       mode_arithmetic arithmetic   = irma_twos_complement;
+       ir_mode_arithmetic arithmetic   = irma_twos_complement;
        unsigned        modulo_shift
                = bit_size < machine_size ? machine_size : bit_size;
 
@@ -814,8 +814,6 @@ static inline ir_mode *get_ir_mode(type_t *type)
        return mode;
 }
 
-static ident *predef_idents[rts_max];
-
 /** Names of the runtime functions. */
 static const struct {
        int        id;           /**< the rts id */
@@ -826,6 +824,7 @@ static const struct {
 } rts_data[] = {
        { rts_debugbreak, 0, "__debugbreak", 0, _MS },
        { rts_abort,      0, "abort",        0, _C89 },
+       { rts_alloca,     1, "alloca",       1, _GNUC },
        { rts_abs,        1, "abs",          1, _C89 },
        { rts_labs,       1, "labs",         1, _C89 },
        { rts_llabs,      1, "llabs",        1, _C99 },
@@ -897,6 +896,8 @@ static const struct {
        { rts_strncmp,    1, "strncmp",      3, _C89 }
 };
 
+static ident *rts_idents[sizeof(rts_data) / sizeof(rts_data[0])];
+
 /**
  * Mangles an entity linker (ld) name for win32 usage.
  *
@@ -980,36 +981,27 @@ static ir_entity* get_function_entity(declaration_t *declaration)
                set_entity_visibility(entity, visibility_external_visible);
        } else {
                set_entity_visibility(entity, visibility_external_allocated);
-
-               /* 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);
-               int    i;
-
-               if (n_params == 0 && n_res == 0 && id == predef_idents[rts_abort]) {
-                       /* found abort(), store for later */
-                       //abort_ent = ent;
-                       //abort_tp  = ftype;
-               } else {
-                       if (! firm_opt.freestanding) {
-                               /* check for a known runtime function */
-                               for (i = 0; i < rts_max; ++i) {
-                                       /* ignore those rts functions not necessary needed for current mode */
-                                       if ((c_mode & rts_data[i].flags) == 0)
-                                               continue;
-                                       if (n_params == rts_data[i].n_params && n_res == rts_data[i].n_res &&
-                                               id == predef_idents[rts_data[i].id])
-                                               rts_entities[rts_data[i].id] = entity;
-                               }
-                       }
-               }
        }
        set_entity_allocation(entity, allocation_static);
 
        declaration->declaration_kind = DECLARATION_KIND_FUNCTION;
        declaration->v.entity         = entity;
 
+       /* We should check for file scope here, but as long as we compile C only
+          this is not needed. */
+       if (! firm_opt.freestanding) {
+               /* check for a known runtime function */
+               for (size_t i = 0; i < sizeof(rts_data) / sizeof(rts_data[0]); ++i) {
+                       if (id != rts_idents[i])
+                               continue;
+
+                       /* ignore those rts functions not necessary needed for current mode */
+                       if ((c_mode & rts_data[i].flags) == 0)
+                               continue;
+                       rts_entities[rts_data[i].id] = entity;
+               }
+       }
+
        return entity;
 }
 
@@ -1237,6 +1229,23 @@ static ir_node *get_local_frame(ir_entity *const ent)
        }
 }
 
+static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode)
+{
+       ir_mode *value_mode = get_irn_mode(value);
+
+       if (value_mode == dest_mode || is_Bad(value))
+               return value;
+
+       if(dest_mode == mode_b) {
+               ir_node *zero = new_Const(value_mode, get_mode_null(value_mode));
+               ir_node *cmp  = new_d_Cmp(dbgi, value, zero);
+               ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pn_Cmp_Lg);
+               return proj;
+       }
+
+       return new_d_Conv(dbgi, value, dest_mode);
+}
+
 static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
 {
        dbg_info      *dbgi        = get_dbg_info(&ref->base.source_position);
@@ -1362,6 +1371,12 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 
                return res;
        }
+       case T___builtin_huge_val: {
+               ir_mode *mode = get_ir_mode(function_type->function.return_type);
+               tarval  *tv   = get_mode_infinite(mode);
+               ir_node *res  = new_d_Const(dbgi, mode, tv);
+               return   res;
+       }
        case T___builtin_nan:
        case T___builtin_nanf:
        case T___builtin_nand: {
@@ -1396,23 +1411,23 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
        assert(is_type_function(points_to));
        function_type_t *function_type = &points_to->function;
 
-       int              n_parameters = 0;
-       call_argument_t *argument     = call->arguments;
-       for( ; argument != NULL; argument = argument->next) {
-               ++n_parameters;
-       }
-
        dbg_info *dbgi  = get_dbg_info(&call->base.source_position);
 
+       int      n_parameters = 0;
        ir_type *ir_method_type  = get_ir_type((type_t*) function_type);
        ir_type *new_method_type = NULL;
        if(function_type->variadic || function_type->unspecified_parameters) {
+               const call_argument_t *argument = call->arguments;
+               for( ; argument != NULL; argument = argument->next) {
+                       ++n_parameters;
+               }
+
                /* we need to construct a new method type matching the 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(id_unique("calltype.%u"),
-                                                 n_parameters, n_res, dbgi);
+                                                   n_parameters, n_res, dbgi);
                set_method_calling_convention(new_method_type,
                               get_method_calling_convention(ir_method_type));
                set_method_additional_properties(new_method_type,
@@ -1424,29 +1439,30 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
                        set_method_res_type(new_method_type, i,
                                            get_method_res_type(ir_method_type, i));
                }
+               argument = call->arguments;
+               for(int i = 0; i < n_parameters; ++i, argument = argument->next) {
+                       expression_t *expression = argument->expression;
+                       ir_type      *irtype     = get_ir_type(expression->base.type);
+                       set_method_param_type(new_method_type, i, irtype);
+               }
+               ir_method_type = new_method_type;
+       } else {
+               n_parameters = get_method_n_params(ir_method_type);
        }
+
        ir_node *in[n_parameters];
 
-       argument = call->arguments;
-       int n = 0;
-       for( ; argument != NULL; argument = argument->next) {
+       const call_argument_t *argument = call->arguments;
+       for(int n = 0; n < n_parameters; ++n) {
                expression_t *expression = argument->expression;
                ir_node      *arg_node   = expression_to_firm(expression);
 
                arg_node = do_strict_conv(dbgi, arg_node);
 
                in[n] = arg_node;
-               if(new_method_type != NULL) {
-                       ir_type *irtype = get_ir_type(expression->base.type);
-                       set_method_param_type(new_method_type, n, irtype);
-               }
 
-               n++;
+               argument = argument->next;
        }
-       assert(n == n_parameters);
-
-       if(new_method_type != NULL)
-               ir_method_type = new_method_type;
 
        ir_node  *store = get_store();
        ir_node  *node  = new_d_Call(dbgi, store, callee, n_parameters, in,
@@ -1531,7 +1547,7 @@ static void bitfield_store_to_firm(const unary_expression_t *expression,
        ir_mode      *mode   = get_ir_mode(type->bitfield.base_type);
        ir_node      *addr   = expression_to_addr(select);
 
-       assert(get_irn_mode(value) == mode);
+       assert(get_irn_mode(value) == mode || is_Bad(value));
 
        dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
 
@@ -1597,23 +1613,6 @@ static void set_value_for_expression(const expression_t *expression,
        assign_value(dbgi, addr, type, value);
 }
 
-static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode)
-{
-       ir_mode *value_mode = get_irn_mode(value);
-
-       if (value_mode == dest_mode || is_Bad(value))
-               return value;
-
-       if(dest_mode == mode_b) {
-               ir_node *zero = new_Const(value_mode, get_mode_null(value_mode));
-               ir_node *cmp  = new_d_Cmp(dbgi, value, zero);
-               ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pn_Cmp_Lg);
-               return proj;
-       }
-
-       return new_d_Conv(dbgi, value, dest_mode);
-}
-
 static ir_node *create_incdec(const unary_expression_t *expression)
 {
        dbg_info     *dbgi  = get_dbg_info(&expression->base.source_position);
@@ -2264,15 +2263,22 @@ static ir_node *array_access_addr(const array_access_expression_t *expression)
        dbg_info *dbgi      = get_dbg_info(&expression->base.source_position);
        ir_node  *base_addr = expression_to_firm(expression->array_ref);
        ir_node  *offset    = expression_to_firm(expression->index);
-       offset              = create_conv(dbgi, offset, mode_uint);
+
+       /* Matze: it would be better to force mode to mode_uint as this creates more
+        * opportunities for CSE. Unforunately we still have some optimisations that
+        * are too conservative in the presence of convs. So we better go with the
+        * mode of offset and avoid the conv */
+       ir_mode  *mode = get_irn_mode(offset);
+       offset         = create_conv(dbgi, offset, mode);
 
        type_t *ref_type = skip_typeref(expression->array_ref->base.type);
        assert(is_type_pointer(ref_type));
        pointer_type_t *pointer_type = &ref_type->pointer;
 
        ir_node *elem_size_const = get_type_size(pointer_type->points_to);
+       elem_size_const          = create_conv(dbgi, elem_size_const, mode);
        ir_node *real_offset     = new_d_Mul(dbgi, offset, elem_size_const,
-                                            mode_uint);
+                                            mode);
        ir_node *result          = new_d_Add(dbgi, base_addr, real_offset, mode_P_data);
 
        return result;
@@ -3625,9 +3631,14 @@ 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          = 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);
+
+       size_t l = strlen(declaration->symbol->string);
+       char   buf[l + sizeof(".%u")];
+       snprintf(buf, sizeof(buf), "%s.%%u", declaration->symbol->string);
+       ident     *const id = id_unique(buf);
+
        ir_entity *const entity      = new_d_entity(global_type, id, irtype, dbgi);
 
        if(type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
@@ -4087,6 +4098,7 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
        ir_node *const old_switch_cond       = current_switch_cond;
        ir_node *const old_break_label       = break_label;
        const bool     old_saw_default_label = saw_default_label;
+       saw_default_label                    = false;
        current_switch_cond                  = cond;
        break_label                          = break_block;
 
@@ -4877,7 +4889,7 @@ void init_ast2firm(void)
 
        /* 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);
+               rts_idents[i] = new_id_from_str(rts_data[i].name);
        }
 }