Overhaul for_statement_to_firm() so it is more friendly towards SSA construction...
[cparser] / ast2firm.c
index f28509c..950ee35 100644 (file)
@@ -2524,6 +2524,11 @@ static ir_node *create_cast(dbg_info *dbgi,      ir_node *value_node,
                             type_t *from_type, type_t *type)
 {
        type = skip_typeref(type);
+       if (type == type_void) {
+               /* make sure firm type is constructed */
+               (void) get_ir_type(type);
+               return NULL;
+       }
        if (!is_type_scalar(type)) {
                /* make sure firm type is constructed */
                (void) get_ir_type(type);
@@ -4052,7 +4057,7 @@ static void advance_current_object(type_path_t *path)
 
        /* we're past the last member of the current sub-aggregate, try if we
         * can ascend in the type hierarchy and continue with another subobject */
-       size_t len = ARR_LEN(path->path);
+       size_t len = ARR_LEN(path->path);
 
        if (len > 1) {
                ascend_from_subtype(path);
@@ -4244,12 +4249,18 @@ static ir_initializer_t *create_ir_initializer(
        panic("unknown initializer");
 }
 
+/** ANSI C §6.7.8:21: If there are fewer initializers [..] than there
+ *  are elements [...] the remainder of the aggregate shall be initialized
+ *  implicitly the same as objects that have static storage duration. */
 static void create_dynamic_null_initializer(ir_entity *entity, dbg_info *dbgi,
                ir_node *base_addr)
 {
-       /* ANSI C §6.7.8:21: If there are fewer initializers [..] than there
-       are elements [...] the remainder of the aggregate shall be initialized
-       implicitly the same as objects that have static storage duration. */
+       /* for unions we must NOT do anything for null initializers */
+       ir_type *owner = get_entity_owner(entity);
+       if (is_Union_type(owner)) {
+               return;
+       }
+
        ir_type *ent_type = get_entity_type(entity);
        /* create sub-initializers for a compound type */
        if (is_compound_type(ent_type)) {
@@ -4262,6 +4273,20 @@ static void create_dynamic_null_initializer(ir_entity *entity, dbg_info *dbgi,
                }
                return;
        }
+       if (is_Array_type(ent_type)) {
+               assert(has_array_upper_bound(ent_type, 0));
+               long n = get_array_upper_bound_int(ent_type, 0);
+               for (long i = 0; i < n; ++i) {
+                       ir_tarval *index_tv = new_tarval_from_long(i, mode_uint);
+                       ir_node   *cnst     = new_d_Const(dbgi, index_tv);
+                       ir_node   *in[1]    = { cnst };
+                       ir_entity *arrent   = get_array_element_entity(ent_type);
+                       ir_node   *addr     = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in,
+                                                       arrent);
+                       create_dynamic_null_initializer(arrent, dbgi, addr);
+               }
+               return;
+       }
 
        ir_mode *value_mode = get_type_mode(ent_type);
        ir_node *node = new_Const_long(value_mode, 0);
@@ -4841,144 +4866,113 @@ static void declaration_statement_to_firm(declaration_statement_t *statement)
 
 static void if_statement_to_firm(if_statement_t *statement)
 {
-       ir_node *cur_block = get_cur_block();
-
-       ir_node *fallthrough_block = NULL;
-
-       /* the true (blocks) */
-       ir_node *true_block = NULL;
-       if (statement->true_statement != NULL) {
-               true_block = new_immBlock();
-               set_cur_block(true_block);
-               statement_to_firm(statement->true_statement);
-               if (get_cur_block() != NULL) {
-                       ir_node *jmp = new_Jmp();
-                       if (fallthrough_block == NULL)
-                               fallthrough_block = new_immBlock();
-                       add_immBlock_pred(fallthrough_block, jmp);
-               }
+       /* Create the condition. */
+       ir_node *true_block  = NULL;
+       ir_node *false_block = NULL;
+       if (get_cur_block() != NULL) {
+               true_block  = new_immBlock();
+               false_block = new_immBlock();
+               create_condition_evaluation(statement->condition, true_block, false_block);
+               mature_immBlock(true_block);
        }
 
-       /* the false (blocks) */
-       ir_node *false_block = NULL;
+       /* Create the false statement.
+        * Hadle false before true, so if no false statement is present, then the
+        * empty false block is reused as fallthrough block. */
+       ir_node *fallthrough_block = NULL;
        if (statement->false_statement != NULL) {
-               false_block = new_immBlock();
+               if (false_block != NULL) {
+                       mature_immBlock(false_block);
+               }
                set_cur_block(false_block);
-
                statement_to_firm(statement->false_statement);
                if (get_cur_block() != NULL) {
-                       ir_node *jmp = new_Jmp();
-                       if (fallthrough_block == NULL)
-                               fallthrough_block = new_immBlock();
-                       add_immBlock_pred(fallthrough_block, jmp);
+                       fallthrough_block = new_immBlock();
+                       add_immBlock_pred(fallthrough_block, new_Jmp());
                }
+       } else {
+               fallthrough_block = false_block;
        }
 
-       /* create the condition */
-       if (cur_block != NULL) {
-               if (true_block == NULL || false_block == NULL) {
-                       if (fallthrough_block == NULL)
-                               fallthrough_block = new_immBlock();
-                       if (true_block == NULL)
-                               true_block = fallthrough_block;
-                       if (false_block == NULL)
-                               false_block = fallthrough_block;
+       /* Create the true statement. */
+       set_cur_block(true_block);
+       statement_to_firm(statement->true_statement);
+       if (get_cur_block() != NULL) {
+               if (fallthrough_block == NULL) {
+                       fallthrough_block = new_immBlock();
                }
-
-               set_cur_block(cur_block);
-               create_condition_evaluation(statement->condition, true_block,
-                                           false_block);
+               add_immBlock_pred(fallthrough_block, new_Jmp());
        }
 
-       mature_immBlock(true_block);
-       if (false_block != fallthrough_block && false_block != NULL) {
-               mature_immBlock(false_block);
-       }
+       /* Handle the block after the if-statement. */
        if (fallthrough_block != NULL) {
                mature_immBlock(fallthrough_block);
        }
-
        set_cur_block(fallthrough_block);
 }
 
 static void while_statement_to_firm(while_statement_t *statement)
 {
-       ir_node *jmp = NULL;
+       /* Create the header block */
+       ir_node *const header_block = new_immBlock();
        if (get_cur_block() != NULL) {
-               jmp = new_Jmp();
+               add_immBlock_pred(header_block, new_Jmp());
        }
 
-       /* create the header block */
-       ir_node *header_block = new_immBlock();
-       if (jmp != NULL) {
-               add_immBlock_pred(header_block, jmp);
+       /* Create the condition. */
+       ir_node      *      body_block;
+       ir_node      *      false_block;
+       expression_t *const cond = statement->condition;
+       if (is_constant_expression(cond) && fold_constant_to_bool(cond)) {
+               /* Shortcut for while (true). */
+               body_block  = header_block;
+               false_block = NULL;
+
+               keep_alive(header_block);
+               keep_all_memory(header_block);
+       } else {
+               body_block  = new_immBlock();
+               false_block = new_immBlock();
+
+               set_cur_block(header_block);
+               create_condition_evaluation(cond, body_block, false_block);
+               mature_immBlock(body_block);
        }
 
-       /* the loop body */
-       ir_node *old_continue_label = continue_label;
-       ir_node *old_break_label    = break_label;
-       continue_label              = header_block;
-       break_label                 = NULL;
+       ir_node *const old_continue_label = continue_label;
+       ir_node *const old_break_label    = break_label;
+       continue_label = header_block;
+       break_label    = false_block;
 
-       ir_node *body_block = new_immBlock();
+       /* Create the loop body. */
        set_cur_block(body_block);
        statement_to_firm(statement->body);
-       ir_node *false_block = break_label;
-
-       assert(continue_label == header_block);
-       continue_label = old_continue_label;
-       break_label    = old_break_label;
-
        if (get_cur_block() != NULL) {
-               jmp = new_Jmp();
-               add_immBlock_pred(header_block, jmp);
-       }
-
-       /* shortcut for while(true) */
-       if (is_constant_expression(statement->condition)
-                       && fold_constant_to_bool(statement->condition) != 0) {
-               set_cur_block(header_block);
-               ir_node *header_jmp = new_Jmp();
-               add_immBlock_pred(body_block, header_jmp);
-
-               keep_alive(body_block);
-               keep_all_memory(body_block);
-               set_cur_block(body_block);
-       } else {
-               if (false_block == NULL) {
-                       false_block = new_immBlock();
-               }
-
-               /* create the condition */
-               set_cur_block(header_block);
-
-               create_condition_evaluation(statement->condition, body_block,
-                                           false_block);
+               add_immBlock_pred(header_block, new_Jmp());
        }
 
-       mature_immBlock(body_block);
        mature_immBlock(header_block);
+       assert(false_block == NULL || false_block == break_label);
+       false_block = break_label;
        if (false_block != NULL) {
                mature_immBlock(false_block);
        }
-
        set_cur_block(false_block);
+
+       assert(continue_label == header_block);
+       continue_label = old_continue_label;
+       break_label    = old_break_label;
 }
 
 static void do_while_statement_to_firm(do_while_statement_t *statement)
 {
-       ir_node *jmp = NULL;
-       if (get_cur_block() != NULL) {
-               jmp = new_Jmp();
-       }
-
        /* create the header block */
        ir_node *header_block = new_immBlock();
 
        /* the loop body */
        ir_node *body_block = new_immBlock();
-       if (jmp != NULL) {
-               add_immBlock_pred(body_block, jmp);
+       if (get_cur_block() != NULL) {
+               add_immBlock_pred(body_block, new_Jmp());
        }
 
        ir_node *old_continue_label = continue_label;
@@ -4997,7 +4991,6 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
        if (get_cur_block() != NULL) {
                ir_node *body_jmp = new_Jmp();
                add_immBlock_pred(header_block, body_jmp);
-               mature_immBlock(header_block);
        }
 
        if (false_block == NULL) {
@@ -5005,11 +4998,11 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
        }
 
        /* create the condition */
+       mature_immBlock(header_block);
        set_cur_block(header_block);
 
        create_condition_evaluation(statement->condition, body_block, false_block);
        mature_immBlock(body_block);
-       mature_immBlock(header_block);
        mature_immBlock(false_block);
 
        set_cur_block(false_block);
@@ -5017,8 +5010,6 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
 
 static void for_statement_to_firm(for_statement_t *statement)
 {
-       ir_node *jmp = NULL;
-
        /* create declarations */
        entity_t *entity = statement->scope.entities;
        for ( ; entity != NULL; entity = entity->base.next) {
@@ -5040,74 +5031,73 @@ static void for_statement_to_firm(for_statement_t *statement)
                if (statement->initialisation != NULL) {
                        expression_to_firm(statement->initialisation);
                }
+       }
 
-               jmp = new_Jmp();
+       /* Create the header block */
+       ir_node *const header_block = new_immBlock();
+       if (get_cur_block() != NULL) {
+               add_immBlock_pred(header_block, new_Jmp());
        }
 
+       /* Create the condition. */
+       ir_node *body_block;
+       ir_node *false_block;
+       if (statement->condition != NULL) {
+               body_block  = new_immBlock();
+               false_block = new_immBlock();
+
+               set_cur_block(header_block);
+               create_condition_evaluation(statement->condition, body_block, false_block);
+               mature_immBlock(body_block);
+       } else {
+               /* for-ever. */
+               body_block  = header_block;
+               false_block = NULL;
 
-       /* create the step block */
-       ir_node *const step_block = new_immBlock();
-       set_cur_block(step_block);
-       if (statement->step != NULL) {
-               expression_to_firm(statement->step);
+               keep_alive(header_block);
+               keep_all_memory(header_block);
        }
-       ir_node *const step_jmp = new_Jmp();
 
-       /* create the header block */
-       ir_node *const header_block = new_immBlock();
-       set_cur_block(header_block);
-       if (jmp != NULL) {
-               add_immBlock_pred(header_block, jmp);
+       /* Create the step block, if necessary. */
+       ir_node      *      step_block = header_block;
+       expression_t *const step       = statement->step;
+       if (step != NULL) {
+               step_block = new_immBlock();
        }
-       add_immBlock_pred(header_block, step_jmp);
-
-       /* the false block */
-       ir_node *const false_block = new_immBlock();
-
-       /* the loop body */
-       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();
-               set_cur_block(body_block);
-               statement_to_firm(statement->body);
+       ir_node *const old_continue_label = continue_label;
+       ir_node *const old_break_label    = break_label;
+       continue_label = step_block;
+       break_label    = false_block;
 
-               assert(continue_label == step_block);
-               assert(break_label    == false_block);
-               continue_label = old_continue_label;
-               break_label    = old_break_label;
+       /* Create the loop body. */
+       set_cur_block(body_block);
+       statement_to_firm(statement->body);
+       if (get_cur_block() != NULL) {
+               add_immBlock_pred(step_block, new_Jmp());
+       }
 
+       /* Create the step code. */
+       if (step != NULL) {
+               mature_immBlock(step_block);
+               set_cur_block(step_block);
+               expression_to_firm(step);
                if (get_cur_block() != NULL) {
-                       jmp = new_Jmp();
-                       add_immBlock_pred(step_block, jmp);
+                       add_immBlock_pred(header_block, new_Jmp());
                }
-       } else {
-               body_block = step_block;
        }
 
-       /* create the condition */
-       set_cur_block(header_block);
-       if (statement->condition != NULL) {
-               create_condition_evaluation(statement->condition, body_block,
-                                           false_block);
-       } else {
-               keep_alive(header_block);
-               keep_all_memory(header_block);
-               jmp = new_Jmp();
-               add_immBlock_pred(body_block, jmp);
-       }
-
-       mature_immBlock(body_block);
-       mature_immBlock(false_block);
-       mature_immBlock(step_block);
        mature_immBlock(header_block);
-       mature_immBlock(false_block);
-
+       assert(false_block == NULL || false_block == break_label);
+       false_block = break_label;
+       if (false_block != NULL) {
+               mature_immBlock(false_block);
+       }
        set_cur_block(false_block);
+
+       assert(continue_label == step_block);
+       continue_label = old_continue_label;
+       break_label    = old_break_label;
 }
 
 static void create_jump_statement(const statement_t *statement,
@@ -5211,9 +5201,7 @@ static void switch_statement_to_firm(switch_statement_t *statement)
                set_Cond_default_proj(cond, default_proj_nr);
        }
 
-       if (statement->body != NULL) {
-               statement_to_firm(statement->body);
-       }
+       statement_to_firm(statement->body);
 
        if (get_cur_block() != NULL) {
                ir_node *jmp = new_Jmp();
@@ -5243,42 +5231,37 @@ static void case_label_to_firm(const case_label_statement_t *statement)
        if (statement->is_empty_range)
                return;
 
-       dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
-
-       ir_node *const fallthrough = (get_cur_block() == NULL ? NULL : new_Jmp());
-
-       ir_node *proj;
        ir_node *block = new_immBlock();
 
+       if (get_cur_block() != NULL) {
+               /* Fallthrough from previous case */
+               add_immBlock_pred(block, new_Jmp());
+       }
+
        if (current_switch_cond != NULL) {
                set_cur_block(get_nodes_block(current_switch_cond));
+               dbg_info *const dbgi = get_dbg_info(&statement->base.source_position);
                if (statement->expression != NULL) {
                        long pn     = statement->first_case;
                        long end_pn = statement->last_case;
                        assert(pn <= end_pn);
                        /* create jumps for all cases in the given range */
                        do {
-                               proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
+                               ir_node *const proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
                                add_immBlock_pred(block, proj);
                        } while (pn++ < end_pn);
                } else {
                        saw_default_label = true;
-                       proj = new_d_Proj(dbgi, current_switch_cond, mode_X,
-                                         current_switch->default_proj_nr);
-
+                       ir_node *const proj = new_d_Proj(dbgi, current_switch_cond, mode_X,
+                                                        current_switch->default_proj_nr);
                        add_immBlock_pred(block, proj);
                }
        }
 
-       if (fallthrough != NULL) {
-               add_immBlock_pred(block, fallthrough);
-       }
        mature_immBlock(block);
        set_cur_block(block);
 
-       if (statement->statement != NULL) {
-               statement_to_firm(statement->statement);
-       }
+       statement_to_firm(statement->statement);
 }
 
 static void label_to_firm(const label_statement_t *statement)
@@ -5294,9 +5277,7 @@ static void label_to_firm(const label_statement_t *statement)
        keep_alive(block);
        keep_all_memory(block);
 
-       if (statement->statement != NULL) {
-               statement_to_firm(statement->statement);
-       }
+       statement_to_firm(statement->statement);
 }
 
 static void goto_to_firm(const goto_statement_t *statement)
@@ -5827,7 +5808,7 @@ static void add_function_pointer(ir_type *segment, ir_entity *method,
 
        set_entity_ld_ident(ptr, new_id_from_chars("", 0));
        set_entity_compiler_generated(ptr, 1);
-       set_entity_visibility(ptr, ir_visibility_local);
+       set_entity_visibility(ptr, ir_visibility_private);
        add_entity_linkage(ptr, IR_LINKAGE_CONSTANT|IR_LINKAGE_HIDDEN_USER);
        set_atomic_ent_value(ptr, val);
 }