Count local variables for IR generation.
[cparser] / ast2firm.c
index 71dce36..f5e7a5b 100644 (file)
@@ -360,7 +360,7 @@ static ir_type *create_struct_type(compound_type_t *type)
        int offset    = 0;
        declaration_t *entry = type->declaration->context.declarations;
        for( ; entry != NULL; entry = entry->next) {
-               if(entry->namespace != NAMESPACE_NORMAL)
+               if(entry->namespc != NAMESPACE_NORMAL)
                        continue;
 
                ident       *ident         = new_id_from_str(entry->symbol->string);
@@ -413,7 +413,7 @@ static ir_type *create_union_type(compound_type_t *type)
        int size      = 0;
        declaration_t *entry = declaration->context.declarations;
        for( ; entry != NULL; entry = entry->next) {
-               if(entry->namespace != NAMESPACE_NORMAL)
+               if(entry->namespc != NAMESPACE_NORMAL)
                        continue;
 
                ident       *ident         = new_id_from_str(entry->symbol->string);
@@ -971,8 +971,8 @@ static ir_node *create_arithmetic_binop(const binary_expression_t *expression,
        ir_node  *left  = expression_to_firm(expression->left);
        ir_node  *right = expression_to_firm(expression->right);
        type_t   *type  = expression->right->datatype;
-       /* be careful with the modes, because in asithmetic assign nodes only
-        * the right operand has the mode of the arithmetic alread */
+       /* be careful with the modes, because in arithmetic assign nodes only
+        * the right operand has the mode of the arithmetic already */
        ir_mode  *mode  = get_ir_mode(type);
        left            = create_conv(dbgi, left, mode);
        ir_node  *res   = func(dbgi, left, right, mode);
@@ -1041,11 +1041,11 @@ static ir_node *create_add(const binary_expression_t *expression)
                return new_d_Add(dbgi, left, right, mode);
        }
 
-       if(type_left->type == TYPE_POINTER) {
-               return pointer_arithmetic(left, right, type_left, dbgi, new_d_Add);
+       if (type_left->type == TYPE_POINTER || type_left->type == TYPE_ARRAY) {
+               return pointer_arithmetic(left, right, type, dbgi, new_d_Add);
        } else {
-               assert(type_right->type == TYPE_POINTER);
-               return pointer_arithmetic(right, left, type_right, dbgi, new_d_Add);
+               assert(type_right->type == TYPE_POINTER || type_right->type == TYPE_ARRAY);
+               return pointer_arithmetic(right, left, type, dbgi, new_d_Add);
        }
 }
 
@@ -1535,12 +1535,16 @@ static void if_statement_to_firm(if_statement_t *statement)
        ir_node *fallthrough_block = new_immBlock();
 
        /* the true (blocks) */
-       ir_node *true_block = new_immBlock();
-
-       statement_to_firm(statement->true_statement);
-       if(get_cur_block() != NULL) {
-               ir_node *jmp = new_Jmp();
-               add_immBlock_pred(fallthrough_block, jmp);
+       ir_node *true_block;
+       if (statement->true_statement != NULL) {
+               true_block = new_immBlock();
+               statement_to_firm(statement->true_statement);
+               if(get_cur_block() != NULL) {
+                       ir_node *jmp = new_Jmp();
+                       add_immBlock_pred(fallthrough_block, jmp);
+               }
+       } else {
+               true_block = fallthrough_block;
        }
 
        /* the false (blocks) */
@@ -1590,23 +1594,27 @@ static void while_statement_to_firm(while_statement_t *statement)
        ir_node *false_block = new_immBlock();
 
        /* the loop body */
-       ir_node *body_block = new_immBlock();
-
-       ir_node *old_continue_label = continue_label;
-       ir_node *old_break_label    = break_label;
-       continue_label              = header_block;
-       break_label                 = false_block;
+       ir_node *body_block;
+       if (statement->body != NULL) {
+               ir_node *old_continue_label = continue_label;
+               ir_node *old_break_label    = break_label;
+               continue_label              = header_block;
+               break_label                 = false_block;
 
-       statement_to_firm(statement->body);
+               body_block = new_immBlock();
+               statement_to_firm(statement->body);
 
-       assert(continue_label == header_block);
-       assert(break_label    == false_block);
-       continue_label = old_continue_label;
-       break_label    = old_break_label;
+               assert(continue_label == header_block);
+               assert(break_label    == false_block);
+               continue_label = old_continue_label;
+               break_label    = old_break_label;
 
-       if(get_cur_block() != NULL) {
-               ir_node *jmp = new_Jmp();
-               add_immBlock_pred(header_block, jmp);
+               if(get_cur_block() != NULL) {
+                       ir_node *jmp = new_Jmp();
+                       add_immBlock_pred(header_block, jmp);
+               }
+       } else {
+               body_block = header_block;
        }
 
        /* create the condition */
@@ -1639,23 +1647,25 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
                add_immBlock_pred(body_block, jmp);
        }
 
-       ir_node *old_continue_label = continue_label;
-       ir_node *old_break_label    = break_label;
-       continue_label              = header_block;
-       break_label                 = false_block;
+       if (statement->body != NULL) {
+               ir_node *old_continue_label = continue_label;
+               ir_node *old_break_label    = break_label;
+               continue_label              = header_block;
+               break_label                 = false_block;
 
-       statement_to_firm(statement->body);
+               statement_to_firm(statement->body);
 
-       assert(continue_label == header_block);
-       assert(break_label    == false_block);
-       continue_label = old_continue_label;
-       break_label    = old_break_label;
+               assert(continue_label == header_block);
+               assert(break_label    == false_block);
+               continue_label = old_continue_label;
+               break_label    = old_break_label;
 
-       if(get_cur_block() == NULL) {
-               mature_immBlock(header_block);
-               mature_immBlock(body_block);
-               mature_immBlock(false_block);
-               return;
+               if (get_cur_block() == NULL) {
+                       mature_immBlock(header_block);
+                       mature_immBlock(body_block);
+                       mature_immBlock(false_block);
+                       return;
+               }
        }
 
        ir_node *body_jmp = new_Jmp();
@@ -1701,23 +1711,27 @@ static void for_statement_to_firm(for_statement_t *statement)
        ir_node *const false_block = new_immBlock();
 
        /* the loop body */
-       ir_node *const body_block = new_immBlock();
-
-       ir_node *const old_continue_label = continue_label;
-       ir_node *const old_break_label    = break_label;
-       continue_label = step_block;
-       break_label    = false_block;
-
-       statement_to_firm(statement->body);
-
-       assert(continue_label == step_block);
-       assert(break_label    == false_block);
-       continue_label = old_continue_label;
-       break_label    = old_break_label;
-
-       if (get_cur_block() != NULL) {
-               ir_node *const jmp = new_Jmp();
-               add_immBlock_pred(step_block, jmp);
+       ir_node * body_block;
+       if (statement->body != NULL) {
+               ir_node *const old_continue_label = continue_label;
+               ir_node *const old_break_label    = break_label;
+               continue_label = step_block;
+               break_label    = false_block;
+
+               body_block = new_immBlock();
+               statement_to_firm(statement->body);
+
+               assert(continue_label == step_block);
+               assert(break_label    == false_block);
+               continue_label = old_continue_label;
+               break_label    = old_break_label;
+
+               if (get_cur_block() != NULL) {
+                       ir_node *const jmp = new_Jmp();
+                       add_immBlock_pred(step_block, jmp);
+               }
+       } else {
+               body_block = step_block;
        }
 
        /* create the condition */
@@ -1943,7 +1957,7 @@ static void case_label_to_firm(const case_label_statement_t *statement)
 
 static ir_node *get_label_block(declaration_t *label)
 {
-       assert(label->namespace == NAMESPACE_LABEL);
+       assert(label->namespc == NAMESPACE_LABEL);
 
        if(label->declaration_type == DECLARATION_TYPE_LABEL_BLOCK) {
                return label->v.block;
@@ -2040,11 +2054,112 @@ static void statement_to_firm(statement_t *statement)
        panic("Statement not implemented\n");
 }
 
+static int count_local_declarations(const declaration_t *      decl,
+                                    const declaration_t *const end)
+{
+       int count = 0;
+       for (; decl != end; decl = decl->next) {
+               const type_t *type = skip_typeref(decl->type);
+               switch (type->type) {
+                       case TYPE_ATOMIC:
+                       case TYPE_ENUM:
+                       case TYPE_POINTER:
+                               if (!decl->address_taken) ++count;
+                               break;
+
+                       default: break;
+               }
+       }
+       return count;
+}
+
+static int count_decls_in_stmts(const statement_t *stmt)
+{
+       int count = 0;
+       for (; stmt != NULL; stmt = stmt->next) {
+               switch (stmt->type) {
+                       case STATEMENT_DECLARATION: {
+                               const declaration_statement_t *const decl_stmt =
+                                       (const declaration_statement_t*)stmt;
+                               count += count_local_declarations(decl_stmt->declarations_begin,
+                                                                 decl_stmt->declarations_end->next);
+                               break;
+                       }
+
+                       case STATEMENT_COMPOUND: {
+                               const compound_statement_t *const comp =
+                                       (const compound_statement_t*)stmt;
+                               count += count_decls_in_stmts(comp->statements);
+                               break;
+                       }
+
+                       case STATEMENT_IF: {
+                               const if_statement_t *const if_stmt = (const if_statement_t*)stmt;
+                               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 =
+                                       (const switch_statement_t*)stmt;
+                               count += count_decls_in_stmts(switch_stmt->body);
+                               break;
+                       }
+
+                       case STATEMENT_LABEL: {
+                               const label_statement_t *const label_stmt =
+                                       (const label_statement_t*)stmt;
+                               count += count_decls_in_stmts(label_stmt->label_statement);
+                               break;
+                       }
+
+                       case STATEMENT_WHILE: {
+                               const while_statement_t *const while_stmt =
+                                       (const while_statement_t*)stmt;
+                               count += count_decls_in_stmts(while_stmt->body);
+                               break;
+                       }
+
+                       case STATEMENT_DO_WHILE: {
+                               const do_while_statement_t *const do_while_stmt =
+                                       (const do_while_statement_t*)stmt;
+                               count += count_decls_in_stmts(do_while_stmt->body);
+                               break;
+                       }
+
+                       case STATEMENT_FOR: {
+                               const for_statement_t *const for_stmt =
+                                       (const for_statement_t*)stmt;
+                               /* TODO initialisation */
+                               count += count_decls_in_stmts(for_stmt->body);
+                               break;
+                       }
+
+                       case STATEMENT_BREAK:
+                       case STATEMENT_CASE_LABEL:
+                       case STATEMENT_CONTINUE:
+                       case STATEMENT_EXPRESSION:
+                       case STATEMENT_GOTO:
+                       case STATEMENT_INVALID:
+                       case STATEMENT_RETURN:
+                               break;
+               }
+       }
+       return count;
+}
+
 static int get_function_n_local_vars(declaration_t *declaration)
 {
-       (void) declaration;
-       /* TODO */
-       return 30;
+       int count = 0;
+
+       /* count parameters */
+       count += count_local_declarations(declaration->context.declarations, NULL);
+
+       /* count local variables declared in body */
+       count += count_decls_in_stmts(declaration->init.statement);
+
+       return count;
 }
 
 static void initialize_function_parameters(declaration_t *declaration)
@@ -2186,7 +2301,7 @@ static void context_to_firm(context_t *context)
 {
        declaration_t *declaration = context->declarations;
        for( ; declaration != NULL; declaration = declaration->next) {
-               if(declaration->namespace != NAMESPACE_NORMAL)
+               if(declaration->namespc != NAMESPACE_NORMAL)
                        continue;
                if(declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY
                                || declaration->storage_class == STORAGE_CLASS_TYPEDEF)