use ir_tarval to calculate case values
[cparser] / ast2firm.c
index 18283b8..43e7deb 100644 (file)
@@ -76,9 +76,9 @@ static ir_node   *continue_label;
 static ir_node   *break_label;
 static ir_node   *current_switch;
 static bool       saw_default_label;
-static label_t  **all_labels;
 static entity_t **inner_functions;
 static ir_node   *ijmp_list;
+static ir_node  **ijmp_blocks;
 static bool       constant_folding;
 
 #define PUSH_BREAK(val) \
@@ -625,9 +625,7 @@ static ir_type *create_compound_type(compound_type_t *const type, bool const inc
        return irtype;
 }
 
-static ir_tarval *fold_constant_to_tarval(expression_t const *);
-
-static void determine_enum_values(enum_type_t *const type)
+void determine_enum_values(enum_type_t *const type)
 {
        ir_mode   *const mode    = atomic_modes[type->base.akind];
        ir_tarval *const one     = get_mode_one(mode);
@@ -899,12 +897,19 @@ static void handle_decl_modifiers(ir_entity *irentity, entity_t *entity)
        decl_modifiers_t modifiers = entity->declaration.modifiers;
 
        if (is_method_entity(irentity)) {
-               if (modifiers & DM_PURE) {
-                       set_entity_additional_properties(irentity, mtp_property_pure);
-               }
-               if (modifiers & DM_CONST) {
+               if (modifiers & DM_PURE)
+                       add_entity_additional_properties(irentity, mtp_property_pure);
+               if (modifiers & DM_CONST)
                        add_entity_additional_properties(irentity, mtp_property_const);
-               }
+               if (modifiers & DM_NOINLINE)
+                       add_entity_additional_properties(irentity, mtp_property_noinline);
+               if (modifiers & DM_FORCEINLINE)
+                       add_entity_additional_properties(irentity, mtp_property_always_inline);
+               if (modifiers & DM_NAKED)
+                       add_entity_additional_properties(irentity, mtp_property_naked);
+               if (entity->kind == ENTITY_FUNCTION && entity->function.is_inline)
+                       add_entity_additional_properties(irentity,
+                                                                                        mtp_property_inline_recommended);
        }
        if ((modifiers & DM_USED) && declaration_is_definition(entity)) {
                add_entity_linkage(irentity, IR_LINKAGE_HIDDEN_USER);
@@ -2836,7 +2841,7 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
 
 static void init_ir_types(void);
 
-static ir_tarval *fold_constant_to_tarval(const expression_t *expression)
+ir_tarval *fold_constant_to_tarval(const expression_t *expression)
 {
        assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
 
@@ -3234,8 +3239,8 @@ static ir_node *get_label_block(label_t *label)
 
        ir_node *block = new_immBlock();
        label->block = block;
-
-       ARR_APP1(label_t *, all_labels, label);
+       if (label->address_taken)
+               ARR_APP1(ir_node*, ijmp_blocks, block);
        return block;
 }
 
@@ -4681,11 +4686,9 @@ static ir_switch_table *create_switch_table(const switch_statement_t *statement)
                }
                if (l->is_empty_range)
                        continue;
-               ir_tarval *min = fold_constant_to_tarval(l->expression);
-               ir_tarval *max = min;
+               ir_tarval *min = l->first_case;
+               ir_tarval *max = l->last_case;
                long       pn  = (long) i+1;
-               if (l->end_range != NULL)
-                       max = fold_constant_to_tarval(l->end_range);
                ir_switch_table_set(res, i++, min, max, pn);
                l->pn = pn;
        }
@@ -4738,10 +4741,7 @@ static ir_node *switch_statement_to_firm(switch_statement_t *statement)
 
 static ir_node *case_label_to_firm(const case_label_statement_t *statement)
 {
-       if (statement->is_empty_range)
-               return NULL;
-
-       if (current_switch != NULL) {
+       if (current_switch != NULL && !statement->is_empty_range) {
                ir_node *block = new_immBlock();
                /* Fallthrough from previous case */
                jump_if_reachable(block);
@@ -4758,17 +4758,34 @@ static ir_node *case_label_to_firm(const case_label_statement_t *statement)
        return statement_to_firm(statement->statement);
 }
 
+static void try_mature_label(label_t *const label)
+{
+       if (--label->n_users == 0 && !label->address_taken)
+               mature_immBlock(label->block);
+}
+
 static ir_node *label_to_firm(const label_statement_t *statement)
 {
-       ir_node *block = get_label_block(statement->label);
+       label_t *const label = statement->label;
+       ir_node *const block = get_label_block(label);
        jump_to(block);
 
        keep_alive(block);
        keep_all_memory(block);
 
+       try_mature_label(label);
+
        return statement_to_firm(statement->statement);
 }
 
+static ir_node *goto_statement_to_firm(goto_statement_t *const stmt)
+{
+       label_t *const label = stmt->label;
+       create_jump_statement((statement_t*)stmt, get_label_block(label));
+       try_mature_label(label);
+       return NULL;
+}
+
 static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const statement)
 {
        if (!currently_reachable())
@@ -5049,6 +5066,7 @@ static ir_node *statement_to_firm(statement_t *const stmt)
        case STATEMENT_EMPTY:         return NULL; /* nothing */
        case STATEMENT_EXPRESSION:    return expression_statement_to_firm( &stmt->expression);
        case STATEMENT_FOR:           return for_statement_to_firm(        &stmt->fors);
+       case STATEMENT_GOTO:          return goto_statement_to_firm(       &stmt->gotos);
        case STATEMENT_IF:            return if_statement_to_firm(         &stmt->ifs);
        case STATEMENT_LABEL:         return label_to_firm(                &stmt->label);
        case STATEMENT_LEAVE:         return leave_statement_to_firm(      &stmt->leave);
@@ -5058,7 +5076,6 @@ static ir_node *statement_to_firm(statement_t *const stmt)
 
        case STATEMENT_BREAK:         return create_jump_statement(stmt, get_break_label());
        case STATEMENT_CONTINUE:      return create_jump_statement(stmt, continue_label);
-       case STATEMENT_GOTO:          return create_jump_statement(stmt, get_label_block(stmt->gotos.label));
 
        case STATEMENT_ERROR: panic("error statement found");
        }
@@ -5176,32 +5193,6 @@ static void initialize_function_parameters(entity_t *entity)
        }
 }
 
-/**
- * Handle additional decl modifiers for IR-graphs
- *
- * @param irg            the IR-graph
- * @param dec_modifiers  additional modifiers
- */
-static void handle_decl_modifier_irg(ir_graph *irg,
-                                     decl_modifiers_t decl_modifiers)
-{
-       if (decl_modifiers & DM_NAKED) {
-               /* TRUE if the declaration includes the Microsoft
-                  __declspec(naked) specifier. */
-               add_irg_additional_properties(irg, mtp_property_naked);
-       }
-       if (decl_modifiers & DM_FORCEINLINE) {
-               /* TRUE if the declaration includes the
-                  Microsoft __forceinline specifier. */
-               set_irg_inline_property(irg, irg_inline_forced);
-       }
-       if (decl_modifiers & DM_NOINLINE) {
-               /* TRUE if the declaration includes the Microsoft
-                  __declspec(noinline) specifier. */
-               set_irg_inline_property(irg, irg_inline_forbidden);
-       }
-}
-
 static void add_function_pointer(ir_type *segment, ir_entity *method,
                                  const char *unique_template)
 {
@@ -5265,9 +5256,9 @@ static void create_function(entity_t *entity)
        current_function_name   = NULL;
        current_funcsig         = NULL;
 
-       assert(all_labels == NULL);
-       all_labels = NEW_ARR_F(label_t *, 0);
-       ijmp_list  = NULL;
+       assert(ijmp_blocks == NULL);
+       ijmp_blocks = NEW_ARR_F(ir_node*, 0);
+       ijmp_list   = NULL;
 
        int       n_local_vars = get_function_n_local_vars(entity);
        ir_graph *irg          = new_ir_graph(function_entity, n_local_vars);
@@ -5284,11 +5275,6 @@ static void create_function(entity_t *entity)
        set_irn_dbg_info(get_irg_start_block(irg),
                         get_entity_dbg_info(function_entity));
 
-       /* set inline flags */
-       if (entity->function.is_inline)
-               set_irg_inline_property(irg, irg_inline_recomended);
-       handle_decl_modifier_irg(irg, entity->declaration.modifiers);
-
        next_value_number_function = 0;
        initialize_function_parameters(entity);
        current_static_link = entity->function.static_link;
@@ -5321,16 +5307,14 @@ static void create_function(entity_t *entity)
                add_immBlock_pred(end_block, ret);
        }
 
-       for (int i = ARR_LEN(all_labels) - 1; i >= 0; --i) {
-               label_t *label = all_labels[i];
-               if (label->address_taken) {
-                       gen_ijmp_branches(label->block);
-               }
-               mature_immBlock(label->block);
+       for (size_t i = ARR_LEN(ijmp_blocks); i-- != 0;) {
+               ir_node *const block = ijmp_blocks[i];
+               gen_ijmp_branches(block);
+               mature_immBlock(block);
        }
 
-       DEL_ARR_F(all_labels);
-       all_labels = NULL;
+       DEL_ARR_F(ijmp_blocks);
+       ijmp_blocks = NULL;
 
        irg_finalize_cons(irg);