add test for escape escape
[cparser] / ast2firm.c
index 6e39f79..af8aa2d 100644 (file)
@@ -44,8 +44,6 @@
 #include "driver/firm_opt.h"
 #include "driver/firm_cmdline.h"
 
-#define MAGIC_DEFAULT_PN_NUMBER            (long) -314159265
-
 /* some idents needed for name mangling */
 static ident *id_underscore;
 static ident *id_imp;
@@ -55,8 +53,6 @@ static ir_type *ir_type_wchar_t;
 static ir_type *ir_type_void;
 static ir_type *ir_type_int;
 
-static type_t *type_const_char;
-
 static int       next_value_number_function;
 static ir_node  *continue_label;
 static ir_node  *break_label;
@@ -68,6 +64,7 @@ static bool constant_folding;
 static const declaration_t *current_function_decl;
 static ir_node             *current_function_name;
 static ir_node             *current_funcsig;
+static switch_statement_t  *current_switch;
 
 static entitymap_t  entitymap;
 
@@ -96,9 +93,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);
 }
 
@@ -380,6 +379,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;
 }
 
@@ -1018,14 +1045,6 @@ static ir_entity *get_function_entity(declaration_t *declaration)
        ir_type  *ir_type_method = get_ir_type(declaration->type);
        assert(is_Method_type(ir_type_method));
 
-       if (declaration->modifiers & DM_CDECL) {
-               set_method_calling_convention(ir_type_method, cc_fixed | cc_cdecl_set);
-       } else if (declaration->modifiers & DM_FASTCALL) {
-               set_method_calling_convention(ir_type_method, cc_fixed | cc_fastcall_set);
-       } else if (declaration->modifiers & DM_STDCALL) {
-               set_method_calling_convention(ir_type_method, cc_fixed | cc_stdcall_set);
-       }
-
        /* already an entity defined? */
        ir_entity *entity = entitymap_get(&entitymap, symbol);
        if (entity != NULL) {
@@ -1046,7 +1065,7 @@ static ir_entity *get_function_entity(declaration_t *declaration)
         * extern inline             => local
         * inline without definition => local
         * inline with definition    => external_visible */
-       storage_class_tag_t const storage_class = declaration->storage_class;
+       storage_class_tag_t const storage_class = (storage_class_tag_t)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) {
@@ -1680,7 +1699,8 @@ static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size)
        tarval *all_one   = get_mode_all_one(mode);
        int     mode_size = get_mode_size_bits(mode);
 
-       assert(offset >= 0 && size >= 0);
+       assert(offset >= 0);
+       assert(size   >= 0);
        assert(offset + size <= mode_size);
        if (size == mode_size) {
                return all_one;
@@ -2129,8 +2149,9 @@ static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi,
        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)) {
+       /* gcc extension: allow arithmetic with void * and function * */
+       if ((elem_size == 0 && is_type_atomic(points_to, ATOMIC_TYPE_VOID)) ||
+           is_type_function(points_to))  {
                elem_size = 1;
        }
 
@@ -2270,12 +2291,11 @@ static ir_node *create_lazy_op(const binary_expression_t *expression)
        if (is_constant_expression(expression->left)) {
                long val = fold_constant(expression->left);
                expression_kind_t ekind = expression->base.kind;
-               if ((ekind == EXPR_BINARY_LOGICAL_AND && val != 0)
-                               || (ekind == EXPR_BINARY_LOGICAL_OR && val == 0)) {
+               assert(ekind == EXPR_BINARY_LOGICAL_AND || ekind == EXPR_BINARY_LOGICAL_OR);
+               if ((ekind == EXPR_BINARY_LOGICAL_AND && val != 0) ||
+                   (ekind == EXPR_BINARY_LOGICAL_OR  && val == 0)) {
                        return expression_to_firm(expression->right);
                } else {
-                       assert((ekind == EXPR_BINARY_LOGICAL_AND && val == 0)
-                                       || (ekind == EXPR_BINARY_LOGICAL_OR && val != 0));
                        return new_Const(mode, get_mode_one(mode));
                }
        }
@@ -2551,6 +2571,7 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
 }
 
 static void init_ir_types(void);
+
 long fold_constant(const expression_t *expression)
 {
        bool constant_folding_old = constant_folding;
@@ -3448,7 +3469,8 @@ static ir_initializer_t *create_ir_initializer_string(
        type = skip_typeref(type);
 
        size_t            string_len    = initializer->string.size;
-       assert(type->kind == TYPE_ARRAY && type->array.size_constant);
+       assert(type->kind == TYPE_ARRAY);
+       assert(type->array.size_constant);
        size_t            len           = type->array.size;
        ir_initializer_t *irinitializer = create_initializer_compound(len);
 
@@ -3473,7 +3495,8 @@ static ir_initializer_t *create_ir_initializer_wide_string(
                const initializer_wide_string_t *initializer, type_t *type)
 {
        size_t            string_len    = initializer->string.size;
-       assert(type->kind == TYPE_ARRAY && type->array.size_constant);
+       assert(type->kind == TYPE_ARRAY);
+       assert(type->array.size_constant);
        size_t            len           = type->array.size;
        ir_initializer_t *irinitializer = create_initializer_compound(len);
 
@@ -4374,7 +4397,7 @@ static ir_node *get_break_label(void)
        return break_label;
 }
 
-static void switch_statement_to_firm(const switch_statement_t *statement)
+static void switch_statement_to_firm(switch_statement_t *statement)
 {
        dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
 
@@ -4389,6 +4412,57 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
        saw_default_label                    = false;
        current_switch_cond                  = cond;
        break_label                          = NULL;
+       switch_statement_t *const old_switch = current_switch;
+       current_switch                       = statement;
+
+       /* determine a free number for the default label */
+       unsigned long num_cases = 0;
+       long def_nr = 0;
+       for (case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) {
+               if (l->expression == NULL) {
+                       /* default case */
+                       continue;
+               }
+               for (long cns = l->first_case; cns <= l->last_case; ++cns)
+                       ++num_cases;
+               if (l->last_case > def_nr)
+                       def_nr = l->last_case;
+       }
+
+       if (def_nr + 1 < 0) {
+               /* Bad: an overflow occurred, we cannot be sure that the
+        * maximum + 1 is a free number. Scan the values a second
+        * time to find a free number.
+        */
+               unsigned char *bits = xmalloc((num_cases + 7) >> 3);
+               unsigned long i;
+
+               memset(bits, 0, (num_cases + 7) >> 3);
+               for (case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) {
+                       if (l->expression == NULL) {
+                               /* default case */
+                               continue;
+                       }
+                       for (long cns = l->first_case; cns <= l->last_case; ++cns) {
+                               if (cns >= 0 && (unsigned long)cns < num_cases)
+                                       bits[cns >> 3] |= (1 << (cns & 7));
+                       }
+               }
+               /* We look at the first num_cases constants:
+                * Either they are densed, so we took the last (num_cases)
+                * one, or they are non densed, so we will find one free
+                * there...
+                */
+               for (i = 0; i < num_cases; ++i)
+                       if ((bits[i >> 3] & (i & 7)) == 0)
+                               break;
+
+               free(bits);
+               def_nr = i;
+       } else {
+               ++def_nr;
+       }
+       statement->default_proj_nr = def_nr;
 
        if (statement->body != NULL) {
                statement_to_firm(statement->body);
@@ -4402,7 +4476,7 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
        if (!saw_default_label) {
                set_cur_block(get_nodes_block(cond));
                ir_node *const proj = new_d_defaultProj(dbgi, cond,
-                                                       MAGIC_DEFAULT_PN_NUMBER);
+                                                       statement->default_proj_nr);
                add_immBlock_pred(get_break_label(), proj);
        }
 
@@ -4412,6 +4486,7 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
        set_cur_block(break_label);
 
        assert(current_switch_cond == cond);
+       current_switch      = old_switch;
        current_switch_cond = old_switch_cond;
        break_label         = old_break_label;
        saw_default_label   = old_saw_default_label;
@@ -4419,37 +4494,31 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
 
 static void case_label_to_firm(const case_label_statement_t *statement)
 {
+       if (statement->is_empty)
+               return;
+
        dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
 
        ir_node *const fallthrough = (get_cur_block() == NULL ? NULL : new_Jmp());
 
-       /* let's create a node and hope firm constant folding creates a Const
-        * node... */
        ir_node *proj;
        ir_node *old_block = get_nodes_block(current_switch_cond);
        ir_node *block     = new_immBlock();
 
        set_cur_block(old_block);
        if (statement->expression != NULL) {
-               long start_pn = fold_constant(statement->expression);
-               long end_pn = start_pn;
-               if (statement->end_range != NULL) {
-                       end_pn = fold_constant(statement->end_range);
-               }
+               long start_pn = statement->first_case;
+               long end_pn   = statement->last_case;
                assert(start_pn <= end_pn);
                /* create jumps for all cases in the given range */
                for (long pn = start_pn; pn <= end_pn; ++pn) {
-                       if (pn == MAGIC_DEFAULT_PN_NUMBER) {
-                               /* oops someone detected our cheating... */
-                               panic("magic default pn used");
-                       }
                        proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
                        add_immBlock_pred(block, proj);
                }
        } else {
                saw_default_label = true;
                proj = new_d_defaultProj(dbgi, current_switch_cond,
-                                        MAGIC_DEFAULT_PN_NUMBER);
+                                        current_switch->default_proj_nr);
 
                add_immBlock_pred(block, proj);
        }
@@ -4563,8 +4632,7 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
        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]));
+       ir_asm_constraint tmp_in_constraints[n_outputs];
 
        const expression_t *out_exprs[n_outputs];
        ir_node            *out_addrs[n_outputs];
@@ -4660,7 +4728,6 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
 
        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) {
@@ -5255,11 +5322,6 @@ static void create_function(declaration_t *declaration)
                                in[0] = new_Const(mode, get_mode_null(mode));
                        } else {
                                in[0] = new_Unknown(mode);
-                               if (warning.return_type) {
-                                       warningf(&declaration->source_position,
-                                               "missing return statement at end of non-void function '%Y'",
-                                               declaration->symbol);
-                               }
                        }
                        ret = new_Return(get_store(), 1, in);
                }
@@ -5393,10 +5455,6 @@ static void init_ir_types(void)
                return;
        ir_types_initialized = 1;
 
-       type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
-       type_void       = make_atomic_type(ATOMIC_TYPE_VOID, TYPE_QUALIFIER_NONE);
-       type_int        = make_atomic_type(ATOMIC_TYPE_INT,  TYPE_QUALIFIER_NONE);
-
        ir_type_int        = get_ir_type(type_int);
        ir_type_const_char = get_ir_type(type_const_char);
        ir_type_wchar_t    = get_ir_type(type_wchar_t);
@@ -5409,6 +5467,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 */
@@ -5419,4 +5494,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);
 }