Replace magic numbers for expression precedences by an enum. Do not unnecessarily...
[cparser] / ast2firm.c
index d7f7b1f..40ad71d 100644 (file)
@@ -39,6 +39,7 @@
 #include "diagnostic.h"
 #include "lang_features.h"
 #include "types.h"
+#include "walk_statements.h"
 #include "warning.h"
 #include "entitymap_t.h"
 #include "driver/firm_opt.h"
@@ -59,9 +60,13 @@ static ir_node        *break_label;
 static ir_node        *current_switch_cond;
 static bool            saw_default_label;
 static declaration_t **all_labels;
+static declaration_t **inner_functions;
+static int             inner_function_idx;
 static ir_node        *ijmp_list;
 static bool            constant_folding;
 
+extern bool            have_const_functions;
+
 static const declaration_t *current_function_decl;
 static ir_node             *current_function_name;
 static ir_node             *current_funcsig;
@@ -84,12 +89,32 @@ typedef enum declaration_kind_t {
        DECLARATION_KIND_ENUM_ENTRY,
        DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE,
        DECLARATION_KIND_COMPOUND_TYPE_COMPLETE,
-       DECLARATION_KIND_TYPE
+       DECLARATION_KIND_TYPE,
+       DECLARATION_KIND_INNER_FUNCTION
 } declaration_kind_t;
 
 static ir_type *get_ir_type(type_t *type);
 static ir_type *get_ir_type_incomplete(type_t *type);
-static int count_decls_in_stmts(const statement_t *stmt);
+
+static void enqueue_inner_function(declaration_t *declaration) {
+       if (inner_functions == NULL) {
+               inner_functions = NEW_ARR_F(declaration_t *, 16);
+               inner_functions[0] = declaration;
+               inner_function_idx = 1;
+       } else {
+               int size = ARR_LEN(inner_functions);
+               if (inner_function_idx >= size) {
+                       ARR_RESIZE(declaration_t *, inner_functions, size + 16);
+               }
+               inner_functions[inner_function_idx++] = declaration;
+       }
+}
+
+static declaration_t *next_inner_function(void) {
+       if (inner_function_idx == 0)
+               return 0;
+       return inner_functions[--inner_function_idx];
+}
 
 ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
 {
@@ -151,13 +176,13 @@ static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
 
                if (flags & ATOMIC_TYPE_FLAG_INTEGER) {
                        assert(! (flags & ATOMIC_TYPE_FLAG_FLOAT));
-                       snprintf(name, sizeof(name), "i%s%d", is_signed?"":"u", bit_size);
+                       snprintf(name, sizeof(name), "i%s%u", is_signed ? "" : "u", bit_size);
                        sort         = irms_int_number;
                        arithmetic   = irma_twos_complement;
                        modulo_shift = bit_size < machine_size ? machine_size : bit_size;
                } else {
                        assert(flags & ATOMIC_TYPE_FLAG_FLOAT);
-                       snprintf(name, sizeof(name), "f%d", bit_size);
+                       snprintf(name, sizeof(name), "f%u", bit_size);
                        sort         = irms_float_number;
                        arithmetic   = irma_ieee754;
                        modulo_shift = 0;
@@ -192,7 +217,7 @@ static void init_atomic_modes(void)
        unsigned        modulo_shift
                = bit_size < machine_size ? machine_size : bit_size;
 
-       snprintf(name, sizeof(name), "p%d", machine_size);
+       snprintf(name, sizeof(name), "p%u", machine_size);
        ir_mode *ptr_mode = new_ir_mode(name, sort, bit_size, is_signed, arithmetic,
                                        modulo_shift);
 
@@ -1024,6 +1049,10 @@ static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
                   __attribute__((pure)) specifier. */
                set_entity_additional_property(ent, mtp_property_pure);
        }
+       if (decl->modifiers & DM_CONST) {
+               set_entity_additional_property(ent, mtp_property_const);
+               have_const_functions = true;
+       }
        if (decl->modifiers & DM_USED) {
                /* TRUE if the declaration includes the GNU
                   __attribute__((used)) specifier. */
@@ -1038,7 +1067,8 @@ static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl)
  */
 static ir_entity *get_function_entity(declaration_t *declaration)
 {
-       if (declaration->declaration_kind == DECLARATION_KIND_FUNCTION)
+       if (declaration->declaration_kind == DECLARATION_KIND_FUNCTION ||
+           declaration->declaration_kind == DECLARATION_KIND_INNER_FUNCTION)
                return declaration->v.entity;
        assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN);
 
@@ -1431,6 +1461,17 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
                ir_mode *const mode = get_ir_mode(type);
                return create_symconst(dbgi, mode, declaration->v.entity);
        }
+       case DECLARATION_KIND_INNER_FUNCTION: {
+               ir_mode *const mode = get_ir_mode(type);
+               if (! declaration->goto_to_outer && !declaration->need_closure) {
+                       /* inner function not using the closure */
+                       return create_symconst(dbgi, mode, declaration->v.entity);
+               } else {
+                       /* TODO: need trampoline here */
+                       panic("Trampoline code not implemented");
+                       return create_symconst(dbgi, mode, declaration->v.entity);
+               }
+       }
        case DECLARATION_KIND_GLOBAL_VARIABLE: {
                ir_node *const addr   = get_global_var_address(dbgi, declaration);
                return deref_address(dbgi, declaration->type, addr);
@@ -1469,11 +1510,6 @@ static ir_node *reference_addr(const reference_expression_t *ref)
                /* you can store to a local variable (so we don't panic but return NULL
                 * as an indicator for no real address) */
                return NULL;
-       case DECLARATION_KIND_FUNCTION: {
-               type_t *const  type = skip_typeref(ref->base.type);
-               ir_mode *const mode = get_ir_mode(type);
-               return create_symconst(dbgi, mode, declaration->v.entity);
-       }
        case DECLARATION_KIND_GLOBAL_VARIABLE: {
                ir_node *const addr = get_global_var_address(dbgi, declaration);
                return addr;
@@ -1492,6 +1528,13 @@ static ir_node *reference_addr(const reference_expression_t *ref)
        case DECLARATION_KIND_ENUM_ENTRY:
                panic("trying to reference enum entry");
 
+       case DECLARATION_KIND_FUNCTION: {
+               type_t  *const type = skip_typeref(declaration->type);
+               ir_mode *const mode = get_ir_mode(type);
+               return create_symconst(dbgi, mode, declaration->v.entity);
+       }
+
+       case DECLARATION_KIND_INNER_FUNCTION:
        case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE:
        case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE:
        case DECLARATION_KIND_COMPOUND_MEMBER:
@@ -1535,7 +1578,11 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 
                return res;
        }
-       case T___builtin_huge_val: {
+
+       case T___builtin_huge_val:
+       case T___builtin_inf:
+       case T___builtin_inff:
+       case T___builtin_infl: {
                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);
@@ -1543,7 +1590,7 @@ static ir_node *process_builtin_call(const call_expression_t *call)
        }
        case T___builtin_nan:
        case T___builtin_nanf:
-       case T___builtin_nand: {
+       case T___builtin_nanl: {
                /* Ignore string for now... */
                assert(is_type_function(function_type));
                ir_mode *mode = get_ir_mode(function_type->function.return_type);
@@ -1741,21 +1788,19 @@ static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size)
        return mask1;
 }
 
-static void bitfield_store_to_firm(const select_expression_t *expression,
-                                   ir_node *addr, ir_node *value)
+static void bitfield_store_to_firm(dbg_info *dbgi,
+               ir_entity *entity, ir_node *addr, ir_node *value, bool set_volatile)
 {
-       type_t       *type   = expression->base.type;
-       ir_mode      *mode   = get_ir_mode(type);
-
-       assert(get_irn_mode(value) == mode || is_Bad(value));
+       ir_type *entity_type = get_entity_type(entity);
+       ir_type *base_type   = get_primitive_base_type(entity_type);
+       assert(base_type != NULL);
+       ir_mode *mode        = get_type_mode(base_type);
 
-       dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+       value = create_conv(dbgi, value, mode);
 
        /* kill upper bits of value and shift to right position */
-       ir_entity *entity       = expression->compound_entry->v.entity;
-       int        bitoffset    = get_entity_offset_bits_remainder(entity);
-       ir_type   *entity_type  = get_entity_type(entity);
-       int        bitsize      = get_mode_size_bits(get_type_mode(entity_type));
+       int      bitoffset    = get_entity_offset_bits_remainder(entity);
+       int      bitsize      = get_mode_size_bits(get_type_mode(entity_type));
 
        tarval  *mask            = create_bitfield_mask(mode, 0, bitsize);
        ir_node *mask_node       = new_d_Const(dbgi, mode, mask);
@@ -1780,7 +1825,7 @@ static void bitfield_store_to_firm(const select_expression_t *expression,
        ir_node *store_mem = new_d_Proj(dbgi, store, mode_M, pn_Store_M);
        set_store(store_mem);
 
-       if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
+       if (set_volatile) {
                set_Load_volatility(load, volatility_is_volatile);
                set_Store_volatility(store, volatility_is_volatile);
        }
@@ -1853,7 +1898,10 @@ static void set_value_for_expression_addr(const expression_t *expression,
 
                declaration_t *declaration = select->compound_entry;
                if (declaration->type->kind == TYPE_BITFIELD) {
-                       bitfield_store_to_firm(select, addr, value);
+                       ir_entity *entity = select->compound_entry->v.entity;
+                       bool       set_volatile
+                               = select->base.type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
+                       bitfield_store_to_firm(dbgi, entity, addr, value, set_volatile);
                        return;
                }
        }
@@ -2493,7 +2541,6 @@ static long get_offsetof_offset(const offsetof_expression_t *expression)
                        expression_t *array_index = designator->array_index;
                        assert(designator->array_index != NULL);
                        assert(is_type_array(type));
-                       assert(is_type_valid(array_index->base.type));
 
                        long index         = fold_constant(array_index);
                        ir_type *arr_type  = get_ir_type(type);
@@ -2597,6 +2644,8 @@ static void init_ir_types(void);
 
 long fold_constant(const expression_t *expression)
 {
+       assert(is_type_valid(skip_typeref(expression->base.type)));
+
        bool constant_folding_old = constant_folding;
        constant_folding = true;
 
@@ -3176,7 +3225,7 @@ static ir_node *create_condition_evaluation(const expression_t *expression,
 
        dbg_info *dbgi       = get_dbg_info(&expression->base.source_position);
        ir_node  *cond_expr  = _expression_to_firm(expression);
-       ir_node  *condition  = create_conv(NULL, cond_expr, mode_b);
+       ir_node  *condition  = create_conv(dbgi, cond_expr, mode_b);
        ir_node  *cond       = new_d_Cond(dbgi, condition);
        ir_node  *true_proj  = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
        ir_node  *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false);
@@ -3220,6 +3269,8 @@ static void create_declaration_entity(declaration_t *declaration,
        dbg_info  *const dbgi   = get_dbg_info(&declaration->source_position);
        ir_entity *const entity = new_d_entity(parent_type, id, irtype, dbgi);
 
+       handle_gnu_attributes_ent(entity, declaration);
+
        declaration->declaration_kind = (unsigned char) declaration_kind;
        declaration->v.entity         = entity;
        set_entity_variability(entity, variability_uninitialized);
@@ -3261,7 +3312,7 @@ static __attribute__((unused)) void debug_print_type_path(const type_path_t *pat
                if (is_type_compound(type)) {
                        fprintf(stderr, ".%s", entry->compound_entry->symbol->string);
                } else if (is_type_array(type)) {
-                       fprintf(stderr, "[%zd]", entry->index);
+                       fprintf(stderr, "[%zu]", entry->index);
                } else {
                        fprintf(stderr, "-INVALID-");
                }
@@ -3406,12 +3457,11 @@ static void walk_designator(type_path_t *path, const designator_t *designator)
                        expression_t *array_index = designator->array_index;
                        assert(designator->array_index != NULL);
                        assert(is_type_array(type));
-                       assert(is_type_valid(array_index->base.type));
 
                        long index = fold_constant(array_index);
                        assert(index >= 0);
 #ifndef NDEBUG
-                       if (type->array.size_constant == 1) {
+                       if (type->array.size_constant) {
                                long array_size = type->array.size;
                                assert(index < array_size);
                        }
@@ -3664,7 +3714,7 @@ static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi,
 }
 
 static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
-               ir_type *type, dbg_info *dbgi, ir_node *base_addr)
+               ir_entity *entity, ir_type *type, dbg_info *dbgi, ir_node *base_addr)
 {
        switch(get_initializer_kind(initializer)) {
        case IR_INITIALIZER_NULL: {
@@ -3672,11 +3722,18 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                return;
        }
        case IR_INITIALIZER_CONST: {
-               ir_node *node = get_initializer_const_value(initializer);
-               ir_mode *mode = get_irn_mode(node);
-               assert(get_type_mode(type) == mode);
+               ir_node *node     = get_initializer_const_value(initializer);
+               ir_mode *mode     = get_irn_mode(node);
+               ir_type *ent_type = get_entity_type(entity);
+
+               /* is it a bitfield type? */
+               if (is_Primitive_type(ent_type) &&
+                               get_primitive_base_type(ent_type) != NULL) {
+                       bitfield_store_to_firm(dbgi, entity, base_addr, node, false);
+                       return;
+               }
 
-               /* TODO: bitfields... */
+               assert(get_type_mode(type) == mode);
                ir_node *mem    = get_store();
                ir_node *store  = new_d_Store(dbgi, mem, base_addr, node);
                ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M);
@@ -3684,12 +3741,19 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                return;
        }
        case IR_INITIALIZER_TARVAL: {
-               tarval  *tv   = get_initializer_tarval_value(initializer);
-               ir_mode *mode = get_tarval_mode(tv);
-               ir_node *cnst = new_d_Const(dbgi, mode, tv);
-               assert(get_type_mode(type) == mode);
+               tarval  *tv       = get_initializer_tarval_value(initializer);
+               ir_mode *mode     = get_tarval_mode(tv);
+               ir_node *cnst     = new_d_Const(dbgi, mode, tv);
+               ir_type *ent_type = get_entity_type(entity);
+
+               /* is it a bitfield type? */
+               if (is_Primitive_type(ent_type) &&
+                               get_primitive_base_type(ent_type) != NULL) {
+                       bitfield_store_to_firm(dbgi, entity, base_addr, cnst, false);
+                       return;
+               }
 
-               /* TODO: bitfields... */
+               assert(get_type_mode(type) == mode);
                ir_node *mem    = get_store();
                ir_node *store  = new_d_Store(dbgi, mem, base_addr, cnst);
                ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M);
@@ -3711,26 +3775,29 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                        panic("initializer doesn't match compound type");
 
                for(int i = 0; i < n_members; ++i) {
-                       ir_node *addr;
-                       ir_type *irtype;
+                       ir_node   *addr;
+                       ir_type   *irtype;
+                       ir_entity *sub_entity;
                        if (is_Array_type(type)) {
-                               ir_entity *entity   = get_array_element_entity(type);
                                tarval    *index_tv = new_tarval_from_long(i, mode_uint);
                                ir_node   *cnst     = new_d_Const(dbgi, mode_uint, index_tv);
                                ir_node   *in[1]    = { cnst };
-                               irtype = get_array_element_type(type);
-                               addr   = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in, entity);
+                               irtype     = get_array_element_type(type);
+                               sub_entity = get_array_element_entity(type);
+                               addr       = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in,
+                                                      sub_entity);
                        } else {
-                               ir_entity *member = get_compound_member(type, i);
-
-                               irtype = get_entity_type(member);
-                               addr   = new_d_simpleSel(dbgi, new_NoMem(), base_addr, member);
+                               sub_entity = get_compound_member(type, i);
+                               irtype     = get_entity_type(sub_entity);
+                               addr       = new_d_simpleSel(dbgi, new_NoMem(), base_addr,
+                                                            sub_entity);
                        }
 
                        ir_initializer_t *sub_init
                                = get_initializer_compound_value(initializer, i);
 
-                       create_dynamic_initializer_sub(sub_init, irtype, dbgi, addr);
+                       create_dynamic_initializer_sub(sub_init, sub_entity, irtype, dbgi,
+                                                      addr);
                }
                return;
        }
@@ -3746,7 +3813,7 @@ static void create_dynamic_initializer(ir_initializer_t *initializer,
        ir_node *base_addr = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
        ir_type *type      = get_entity_type(entity);
 
-       create_dynamic_initializer_sub(initializer, type, dbgi, base_addr);
+       create_dynamic_initializer_sub(initializer, entity, type, dbgi, base_addr);
 }
 
 static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi,
@@ -3825,7 +3892,8 @@ static void create_declaration_initializer(declaration_t *declaration)
                return;
        }
 
-       type_t *type = skip_typeref(declaration->type);
+       type_t            *type = declaration->type;
+       type_qualifiers_t  tq   = get_type_qualifier(type, true);
 
        if (initializer->kind == INITIALIZER_VALUE) {
                initializer_value_t *initializer_value = &initializer->value;
@@ -3842,7 +3910,7 @@ static void create_declaration_initializer(declaration_t *declaration)
 
                        ir_entity *entity = declaration->v.entity;
 
-                       if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+                       if (tq & TYPE_QUALIFIER_CONST) {
                                set_entity_variability(entity, variability_constant);
                        } else {
                                set_entity_variability(entity, variability_initialized);
@@ -3850,14 +3918,14 @@ static void create_declaration_initializer(declaration_t *declaration)
                        set_atomic_ent_value(entity, value);
                }
        } else {
-               assert(declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY
-                               || declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
+               assert(declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY ||
+                      declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
 
                ir_entity        *entity        = declaration->v.entity;
                ir_initializer_t *irinitializer
                        = create_ir_initializer(initializer, type);
 
-               if (type->base.qualifiers & TYPE_QUALIFIER_CONST) {
+               if (tq & TYPE_QUALIFIER_CONST) {
                        set_entity_variability(entity, variability_constant);
                } else {
                        set_entity_variability(entity, variability_initialized);
@@ -4130,7 +4198,9 @@ static void create_local_declaration(declaration_t *declaration)
        case STORAGE_CLASS_REGISTER:
                if (is_type_function(type)) {
                        if (declaration->init.statement != NULL) {
-                               panic("nested functions not supported yet");
+                               get_function_entity(declaration);
+                               declaration->declaration_kind = DECLARATION_KIND_INNER_FUNCTION;
+                               enqueue_inner_function(declaration);
                        } else {
                                get_function_entity(declaration);
                        }
@@ -4176,10 +4246,11 @@ static void initialize_local_declaration(declaration_t *declaration)
        case DECLARATION_KIND_FUNCTION:
        case DECLARATION_KIND_TYPE:
        case DECLARATION_KIND_ENUM_ENTRY:
+       case DECLARATION_KIND_INNER_FUNCTION:
                return;
 
        case DECLARATION_KIND_UNKNOWN:
-               panic("can't initialize unknwon declaration");
+               panic("can't initialize unknown declaration");
        }
        panic("invalid declaration kind");
 }
@@ -4575,7 +4646,7 @@ static void switch_statement_to_firm(switch_statement_t *statement)
 
 static void case_label_to_firm(const case_label_statement_t *statement)
 {
-       if (statement->is_empty)
+       if (statement->is_empty_range)
                return;
 
        dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
@@ -4741,7 +4812,7 @@ static void asm_statement_to_firm(const asm_statement_t *statement)
                                char     buf[64];
                                ir_node *value = get_value_from_lvalue(expr, addr);
 
-                               snprintf(buf, sizeof(buf), "%d", pos);
+                               snprintf(buf, sizeof(buf), "%u", pos);
 
                                ir_asm_constraint constraint;
                                constraint.pos              = pos;
@@ -4978,8 +5049,6 @@ static void statement_to_firm(statement_t *statement)
        panic("Statement not implemented\n");
 }
 
-static int count_decls_in_expression(const expression_t *expression);
-
 static int count_local_declarations(const declaration_t *      decl,
                                     const declaration_t *const end)
 {
@@ -4991,218 +5060,29 @@ static int count_local_declarations(const declaration_t *      decl,
 
                if (!decl->address_taken && is_type_scalar(type))
                        ++count;
-               const initializer_t *initializer = decl->init.initializer;
-               /* FIXME: should walk initializer hierarchies... */
-               if (initializer != NULL && initializer->kind == INITIALIZER_VALUE) {
-                       count += count_decls_in_expression(initializer->value.value);
-               }
        }
        return count;
 }
 
-static int count_decls_in_expression(const expression_t *expression) {
-       int count = 0;
-
-       if (expression == NULL)
-               return 0;
-
-       switch((expression_kind_t) expression->base.kind) {
-       case EXPR_STATEMENT:
-               return count_decls_in_stmts(expression->statement.statement);
-       EXPR_BINARY_CASES {
-               int count_left  = count_decls_in_expression(expression->binary.left);
-               int count_right = count_decls_in_expression(expression->binary.right);
-               return count_left + count_right;
-       }
-       EXPR_UNARY_CASES
-               return count_decls_in_expression(expression->unary.value);
-       case EXPR_CALL: {
-               call_argument_t *argument = expression->call.arguments;
-               for( ; argument != NULL; argument = argument->next) {
-                       count += count_decls_in_expression(argument->expression);
-               }
-               return count;
-       }
-
-       case EXPR_UNKNOWN:
-       case EXPR_INVALID:
-               panic("unexpected expression kind");
-
-       case EXPR_COMPOUND_LITERAL:
-               /* TODO... */
-               break;
-
-       case EXPR_CONDITIONAL:
-               count += count_decls_in_expression(expression->conditional.condition);
-               count += count_decls_in_expression(expression->conditional.true_expression);
-               count += count_decls_in_expression(expression->conditional.false_expression);
-               return count;
-
-       case EXPR_BUILTIN_PREFETCH:
-               count += count_decls_in_expression(expression->builtin_prefetch.adr);
-               count += count_decls_in_expression(expression->builtin_prefetch.rw);
-               count += count_decls_in_expression(expression->builtin_prefetch.locality);
-               return count;
-
-       case EXPR_BUILTIN_CONSTANT_P:
-               count += count_decls_in_expression(expression->builtin_constant.value);
-               return count;
-
-       case EXPR_SELECT:
-               count += count_decls_in_expression(expression->select.compound);
-               return count;
-
-       case EXPR_ARRAY_ACCESS:
-               count += count_decls_in_expression(expression->array_access.array_ref);
-               count += count_decls_in_expression(expression->array_access.index);
-               return count;
-
-       case EXPR_CLASSIFY_TYPE:
-               count += count_decls_in_expression(expression->classify_type.type_expression);
-               return count;
-
-       case EXPR_SIZEOF:
-       case EXPR_ALIGNOF: {
-               expression_t *tp_expression = expression->typeprop.tp_expression;
-               if (tp_expression != NULL) {
-                       count += count_decls_in_expression(tp_expression);
-               }
-               return count;
-       }
-
-       case EXPR_OFFSETOF:
-       case EXPR_REFERENCE:
-       case EXPR_CONST:
-       case EXPR_CHARACTER_CONSTANT:
-       case EXPR_WIDE_CHARACTER_CONSTANT:
-       case EXPR_STRING_LITERAL:
-       case EXPR_WIDE_STRING_LITERAL:
-       case EXPR_FUNCNAME:
-       case EXPR_BUILTIN_SYMBOL:
-       case EXPR_VA_START:
-       case EXPR_VA_ARG:
-       case EXPR_LABEL_ADDRESS:
-               break;
-       }
-
-       /* TODO FIXME: finish/fix that firm patch that allows dynamic value numbers
-        * (or implement all the missing expressions here/implement a walker)
-        */
-
-       return 0;
-}
-
-static int count_decls_in_stmts(const statement_t *stmt)
+static void count_decls_in_stmt(statement_t *stmt, void *const env)
 {
-       int count = 0;
-       for (; stmt != NULL; stmt = stmt->base.next) {
-               switch (stmt->kind) {
-                       case STATEMENT_EMPTY:
-                               break;
-
-                       case STATEMENT_DECLARATION: {
-                               const declaration_statement_t *const decl_stmt = &stmt->declaration;
-                               count += count_local_declarations(decl_stmt->declarations_begin,
-                                                                 decl_stmt->declarations_end->next);
-                               break;
-                       }
-
-                       case STATEMENT_COMPOUND: {
-                               const compound_statement_t *const comp =
-                                       &stmt->compound;
-                               count += count_decls_in_stmts(comp->statements);
-                               break;
-                       }
-
-                       case STATEMENT_IF: {
-                               const if_statement_t *const if_stmt = &stmt->ifs;
-                               count += count_decls_in_expression(if_stmt->condition);
-                               count += count_decls_in_stmts(if_stmt->true_statement);
-                               count += count_decls_in_stmts(if_stmt->false_statement);
-                               break;
-                       }
-
-                       case STATEMENT_SWITCH: {
-                               const switch_statement_t *const switch_stmt = &stmt->switchs;
-                               count += count_decls_in_expression(switch_stmt->expression);
-                               count += count_decls_in_stmts(switch_stmt->body);
-                               break;
-                       }
-
-                       case STATEMENT_LABEL: {
-                               const label_statement_t *const label_stmt = &stmt->label;
-                               if (label_stmt->statement != NULL) {
-                                       count += count_decls_in_stmts(label_stmt->statement);
-                               }
-                               break;
-                       }
-
-                       case STATEMENT_WHILE: {
-                               const while_statement_t *const while_stmt = &stmt->whiles;
-                               count += count_decls_in_expression(while_stmt->condition);
-                               count += count_decls_in_stmts(while_stmt->body);
-                               break;
-                       }
-
-                       case STATEMENT_DO_WHILE: {
-                               const do_while_statement_t *const do_while_stmt = &stmt->do_while;
-                               count += count_decls_in_expression(do_while_stmt->condition);
-                               count += count_decls_in_stmts(do_while_stmt->body);
-                               break;
-                       }
-
-                       case STATEMENT_FOR: {
-                               const for_statement_t *const for_stmt = &stmt->fors;
-                               count += count_local_declarations(for_stmt->scope.declarations, NULL);
-                               count += count_decls_in_expression(for_stmt->initialisation);
-                               count += count_decls_in_expression(for_stmt->condition);
-                               count += count_decls_in_expression(for_stmt->step);
-                               count += count_decls_in_stmts(for_stmt->body);
-                               break;
-                       }
+       int *const count = env;
 
-                       case STATEMENT_CASE_LABEL: {
-                               const case_label_statement_t *label = &stmt->case_label;
-                               count += count_decls_in_expression(label->expression);
-                               if (label->statement != NULL) {
-                                       count += count_decls_in_stmts(label->statement);
-                               }
-                               break;
-                       }
-
-                       case STATEMENT_ASM:
-                       case STATEMENT_BREAK:
-                       case STATEMENT_CONTINUE:
-                               break;
-
-                       case STATEMENT_EXPRESSION: {
-                               const expression_statement_t *expr_stmt = &stmt->expression;
-                               count += count_decls_in_expression(expr_stmt->expression);
-                               break;
-                       }
-
-                       case STATEMENT_GOTO:
-                       case STATEMENT_LEAVE:
-                       case STATEMENT_INVALID:
-                               break;
+       switch (stmt->kind) {
+               case STATEMENT_DECLARATION: {
+                       const declaration_statement_t *const decl_stmt = &stmt->declaration;
+                       *count += count_local_declarations(decl_stmt->declarations_begin,
+                                                                                                                                                                decl_stmt->declarations_end->next);
+                       break;
+               }
 
-                       case STATEMENT_RETURN: {
-                               const return_statement_t *ret_stmt = &stmt->returns;
-                               count += count_decls_in_expression(ret_stmt->value);
-                               break;
-                       }
+               case STATEMENT_FOR:
+                       *count += count_local_declarations(stmt->fors.scope.declarations, NULL);
+                       break;
 
-                       case STATEMENT_MS_TRY: {
-                               const ms_try_statement_t *const try_stmt = &stmt->ms_try;
-                               count += count_decls_in_stmts(try_stmt->try_statement);
-                               if (try_stmt->except_expression != NULL)
-                                       count += count_decls_in_expression(try_stmt->except_expression);
-                               count += count_decls_in_stmts(try_stmt->final_statement);
-                               break;
-                       }
-               }
+               default:
+                       break;
        }
-       return count;
 }
 
 static int get_function_n_local_vars(declaration_t *declaration)
@@ -5213,8 +5093,7 @@ static int get_function_n_local_vars(declaration_t *declaration)
        count += count_local_declarations(declaration->scope.declarations, NULL);
 
        /* count local variables declared in body */
-       count += count_decls_in_stmts(declaration->init.statement);
-
+       walk_statements(declaration->init.statement, count_decls_in_stmt, &count);
        return count;
 }
 
@@ -5504,6 +5383,10 @@ static void scope_to_firm(scope_t *scope)
                type_t *type = declaration->type;
                if (type->kind == TYPE_FUNCTION) {
                        create_function(declaration);
+                       declaration_t *inner;
+                       for (inner = next_inner_function(); inner != NULL;
+                            inner = next_inner_function())
+                                create_function(inner);
                } else {
                        assert(declaration->declaration_kind
                                        == DECLARATION_KIND_GLOBAL_VARIABLE);