semantic: Extend expression classification to detect integer constant expressions.
[cparser] / ast2firm.c
index 26bddff..9ddd3b2 100644 (file)
@@ -1,21 +1,6 @@
 /*
  * This file is part of cparser.
- * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
  */
 #include <config.h>
 
@@ -151,11 +136,8 @@ static void enqueue_inner_function(entity_t *entity)
 static ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
 {
        const entity_t *entity = get_irg_loc_description(irg, pos);
-
-       if (entity != NULL) {
-               position_t const *const pos = &entity->base.pos;
-               warningf(WARN_UNINITIALIZED, pos, "'%N' might be used uninitialized", entity);
-       }
+       if (entity)
+               warningf(WARN_UNINITIALIZED, &entity->base.pos, "'%N' might be used uninitialized", entity);
        return new_r_Unknown(irg, mode);
 }
 
@@ -500,10 +482,12 @@ static ir_type *get_signed_int_type_for_bit_size(ir_type *base_tp,
 
        mode = s_modes[size];
        if (mode == NULL) {
-               char name[32];
+               ir_mode *base_mode    = get_type_mode(base_tp);
+               unsigned modulo_shift = get_mode_modulo_shift(base_mode);
 
+               char name[32];
                snprintf(name, sizeof(name), "bf_I%u", size);
-               mode = new_int_mode(name, irma_twos_complement, size, 1, 0);
+               mode = new_int_mode(name, irma_twos_complement, size, 1, modulo_shift);
                s_modes[size] = mode;
        }
 
@@ -532,10 +516,12 @@ static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp,
 
        mode = u_modes[size];
        if (mode == NULL) {
-               char name[32];
+               ir_mode *base_mode    = get_type_mode(base_tp);
+               unsigned modulo_shift = get_mode_modulo_shift(base_mode);
 
+               char name[32];
                snprintf(name, sizeof(name), "bf_U%u", size);
-               mode = new_int_mode(name, irma_twos_complement, size, 0, 0);
+               mode = new_int_mode(name, irma_twos_complement, size, 0, modulo_shift);
                u_modes[size] = mode;
        }
 
@@ -615,15 +601,15 @@ static ir_type *create_compound_type(compound_type_t *const type, bool const inc
 
                symbol_t *symbol     = entry->base.symbol;
                type_t   *entry_type = entry->declaration.type;
-               ident    *ident;
+               ident    *member_id;
                if (symbol == NULL) {
                        /* anonymous bitfield member, skip */
                        if (entry->compound_member.bitfield)
                                continue;
                        assert(is_type_compound(entry_type));
-                       ident = id_unique("anon.%u");
+                       member_id = id_unique("anon.%u");
                } else {
-                       ident = new_id_from_str(symbol->string);
+                       member_id = new_id_from_str(symbol->string);
                }
 
                dbg_info *dbgi = get_dbg_info(&entry->base.pos);
@@ -634,7 +620,7 @@ static ir_type *create_compound_type(compound_type_t *const type, bool const inc
                } else {
                        entry_irtype = get_ir_type(entry_type);
                }
-               ir_entity *entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
+               ir_entity *entity = new_d_entity(irtype, member_id, entry_irtype, dbgi);
 
                set_entity_offset(entity, entry->compound_member.offset);
                set_entity_offset_bits_remainder(entity,
@@ -2172,10 +2158,10 @@ static ir_node *handle_assume_compare(dbg_info *dbi,
        }
 
        expression_t *con = NULL;
-       if (is_local_variable(op1) && is_constant_expression(op2) == EXPR_CLASS_CONSTANT) {
+       if (is_local_variable(op1) && is_constant_expression(op2) != EXPR_CLASS_VARIABLE) {
                var = op1->reference.entity;
                con = op2;
-       } else if (is_constant_expression(op1) == EXPR_CLASS_CONSTANT && is_local_variable(op2)) {
+       } else if (is_constant_expression(op1) != EXPR_CLASS_VARIABLE && is_local_variable(op2)) {
                relation = get_inversed_relation(relation);
                var = op2->reference.entity;
                con = op1;
@@ -2222,10 +2208,13 @@ static ir_node *create_cast(unary_expression_t const *const expr)
        if (is_type_void(type))
                return NULL;
 
-       ir_node        *value     = expression_to_value(expr->value);
-       dbg_info *const dbgi      = get_dbg_info(&expr->base.pos);
-       type_t   *const from_type = skip_typeref(expr->value->base.type);
-       ir_mode  *const mode      = get_ir_mode_storage(type);
+       type_t  *const from_type = skip_typeref(expr->value->base.type);
+       ir_node       *value     = is_type_complex(from_type)
+               ? expression_to_complex(expr->value).real
+               : expression_to_value(expr->value);
+
+       dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+       ir_mode  *const mode = get_ir_mode_storage(type);
        /* check for conversion from / to __based types */
        if (is_type_pointer(type) && is_type_pointer(from_type)) {
                const variable_t *from_var = from_type->pointer.base_variable;
@@ -2455,7 +2444,7 @@ static void compare_to_control_flow(expression_t const *const expr, ir_node *con
                /* set branch prediction info based on __builtin_expect */
                if (is_builtin_expect(expr) && is_Cond(cond)) {
                        call_argument_t *const argument = expr->call.arguments->next;
-                       if (is_constant_expression(argument->expression) == EXPR_CLASS_CONSTANT) {
+                       if (is_constant_expression(argument->expression) != EXPR_CLASS_VARIABLE) {
                                bool               const cnst = fold_constant_to_bool(argument->expression);
                                cond_jmp_predicate const pred = cnst ? COND_JMP_PRED_TRUE : COND_JMP_PRED_FALSE;
                                set_Cond_jmp_pred(cond, pred);
@@ -2655,9 +2644,10 @@ static ir_node *compound_literal_addr(compound_literal_expression_t const *const
        type_t        *type        = expression->type;
        initializer_t *initializer = expression->initializer;
 
-       if (expression->global_scope ||
-               ((type->base.qualifiers & TYPE_QUALIFIER_CONST)
-           && is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT)) {
+       if (expression->global_scope || (
+             type->base.qualifiers & TYPE_QUALIFIER_CONST &&
+             is_constant_initializer(initializer) != EXPR_CLASS_VARIABLE
+           )) {
                ir_entity *entity = create_initializer_entity(dbgi, initializer, type);
                return create_symconst(dbgi, entity);
        } else {
@@ -2756,7 +2746,7 @@ static void init_ir_types(void);
 
 ir_tarval *fold_constant_to_tarval(const expression_t *expression)
 {
-       assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+       assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
 
        bool constant_folding_old = constant_folding;
        constant_folding = true;
@@ -2782,7 +2772,7 @@ ir_tarval *fold_constant_to_tarval(const expression_t *expression)
 
 static complex_constant fold_complex_constant(const expression_t *expression)
 {
-       assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+       assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
 
        bool constant_folding_old = constant_folding;
        constant_folding = true;
@@ -3156,7 +3146,7 @@ static ir_node *builtin_constant_to_firm(
                const builtin_constant_expression_t *expression)
 {
        ir_mode *const mode = get_ir_mode_storage(expression->base.type);
-       bool     const v    = is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT;
+       bool     const v    = is_constant_expression(expression->value) != EXPR_CLASS_VARIABLE;
        return create_Const_from_bool(mode, v);
 }
 
@@ -3326,9 +3316,9 @@ static void complex_equality_evaluation(const binary_expression_t *binexpr,
        jump_target *const true_target, jump_target *const false_target,
        ir_relation relation);
 
-static complex_value create_complex_condition_evaluation(
-       const expression_t *const expression, jump_target *const true_target,
-       jump_target *const false_target);
+static complex_value complex_to_control_flow(const expression_t *expression,
+                                             jump_target *true_target,
+                                             jump_target *false_target);
 
 /**
  * create a short-circuit expression evaluation that tries to construct
@@ -3399,7 +3389,7 @@ static ir_node *expression_to_control_flow(expression_t const *const expr, jump_
        default:;
                        type_t *const type = skip_typeref(expr->base.type);
                        if (is_type_complex(type)) {
-                               create_complex_condition_evaluation(expr, true_target, false_target);
+                               complex_to_control_flow(expr, true_target, false_target);
                                return NULL;
                        }
 
@@ -3823,13 +3813,25 @@ static void complex_equality_evaluation(const binary_expression_t *binexpr,
        set_unreachable_now();
 }
 
-static complex_value create_complex_condition_evaluation(
+static complex_value complex_to_control_flow(
        const expression_t *const expression, jump_target *const true_target,
        jump_target *const false_target)
 {
        jump_target extra_target;
        init_jump_target(&extra_target, NULL);
        complex_value       value      = expression_to_complex(expression);
+       if (is_Const(value.real) && is_Const(value.imag)) {
+               ir_tarval *tv_real = get_Const_tarval(value.real);
+               ir_tarval *tv_imag = get_Const_tarval(value.imag);
+               if (tarval_is_null(tv_real) && tarval_is_null(tv_imag)) {
+                       jump_to_target(false_target);
+               } else {
+                       jump_to_target(true_target);
+               }
+               set_unreachable_now();
+               return value;
+       }
+
        dbg_info     *const dbgi       = get_dbg_info(&expression->base.pos);
        type_t       *const type       = expression->base.type;
        ir_mode      *const mode       = get_complex_mode_arithmetic(type);
@@ -3860,23 +3862,6 @@ static complex_value create_complex_condition_evaluation(
 static complex_value complex_conditional_to_firm(
        const conditional_expression_t *const expression)
 {
-       /* first try to fold a constant condition */
-       if (is_constant_expression(expression->condition) == EXPR_CLASS_CONSTANT) {
-               bool val = fold_constant_to_bool(expression->condition);
-               if (val) {
-                       expression_t *true_expression = expression->true_expression;
-                       if (true_expression == NULL) {
-                               /* we will evaluate true_expression a second time here, but in
-                                * this case it is harmless since constant expression have no
-                                * side effects */
-                               true_expression = expression->condition;
-                       }
-                       return expression_to_complex(true_expression);
-               } else {
-                       return expression_to_complex(expression->false_expression);
-               }
-       }
-
        jump_target true_target;
        jump_target false_target;
        init_jump_target(&true_target,  NULL);
@@ -3885,17 +3870,19 @@ static complex_value complex_conditional_to_firm(
        memset(&cond_val, 0, sizeof(cond_val));
        if (expression->true_expression == NULL) {
                assert(is_type_complex(skip_typeref(expression->condition->base.type)));
-               cond_val
-                       = create_complex_condition_evaluation(expression->condition,
-                                                             &true_target, &false_target);
+               cond_val = complex_to_control_flow(expression->condition,
+                                                  &true_target, &false_target);
        } else {
                expression_to_control_flow(expression->condition, &true_target, &false_target);
        }
 
-       complex_value val;
+       complex_value  val;
        memset(&val, 0, sizeof(val));
-       jump_target   exit_target;
+       jump_target    exit_target;
        init_jump_target(&exit_target, NULL);
+       type_t   *const type = skip_typeref(expression->base.type);
+       ir_mode  *const mode = get_complex_mode_arithmetic(type);
+       dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
 
        if (enter_jump_target(&true_target)) {
                if (expression->true_expression) {
@@ -3904,19 +3891,18 @@ static complex_value complex_conditional_to_firm(
                        assert(cond_val.real != NULL);
                        val = cond_val;
                }
+               val = complex_conv(dbgi, val, mode);
                jump_to_target(&exit_target);
        }
 
-       type_t *const type = skip_typeref(expression->base.type);
        if (enter_jump_target(&false_target)) {
                complex_value false_val
                        = expression_to_complex(expression->false_expression);
+               false_val = complex_conv(dbgi, false_val, mode);
                jump_to_target(&exit_target);
                if (val.real != NULL) {
                        ir_node  *const inr[] = { val.real, false_val.real };
                        ir_node  *const ini[] = { val.imag, false_val.imag };
-                       dbg_info *const dbgi  = get_dbg_info(&expression->base.pos);
-                       ir_mode  *const mode  = get_complex_mode_arithmetic(type);
                        ir_node  *const block = exit_target.block;
                        val.real = new_rd_Phi(dbgi, block, lengthof(inr), inr, mode);
                        val.imag = new_rd_Phi(dbgi, block, lengthof(ini), ini, mode);
@@ -3928,9 +3914,7 @@ static complex_value complex_conditional_to_firm(
        if (!enter_jump_target(&exit_target)) {
                set_cur_block(new_Block(0, NULL));
                assert(!is_type_void(type));
-               ir_mode *mode = get_complex_mode_arithmetic(type);
-               val.real = new_Unknown(mode);
-               val.imag = val.real;
+               val.real = val.imag = new_Bad(mode);
        }
        return val;
 }
@@ -3964,6 +3948,15 @@ static complex_value compound_statement_to_firm_complex(
        return result;
 }
 
+static complex_value complex_assign_to_firm(const binary_expression_t *expr)
+{
+       dbg_info     *const dbgi  = get_dbg_info(&expr->base.pos);
+       complex_value const value = expression_to_complex(expr->right);
+       ir_node      *const addr  = expression_to_addr(expr->left);
+       set_complex_value_for_expression(dbgi, expr->left, value, addr);
+       return value;
+}
+
 static complex_value complex_statement_expression_to_firm(
        const statement_expression_t *const expr)
 {
@@ -4021,14 +4014,8 @@ static complex_value expression_to_complex(const expression_t *expression)
                return complex_negate_to_firm(&expression->unary);
        case EXPR_UNARY_COMPLEMENT:
                return complex_complement_to_firm(&expression->unary);
-       case EXPR_BINARY_ASSIGN: {
-               const binary_expression_t *binexpr = &expression->binary;
-               dbg_info                  *dbgi   = get_dbg_info(&binexpr->base.pos);
-               complex_value value = expression_to_complex(binexpr->right);
-               ir_node      *addr  = expression_to_addr(binexpr->left);
-               set_complex_value_for_expression(dbgi, binexpr->left, value, addr);
-               return value;
-       }
+       case EXPR_BINARY_ASSIGN:
+               return complex_assign_to_firm(&expression->binary);
        case EXPR_LITERAL_CASES:
                return complex_literal_to_firm(&expression->literal);
        case EXPR_CALL:
@@ -4734,12 +4721,12 @@ static void create_variable_initializer(entity_t *entity)
                                                && get_entity_owner(irentity) != get_tls_type()) {
                                        add_entity_linkage(irentity, IR_LINKAGE_CONSTANT);
                                }
-                               ir_initializer_t *initializer = create_initializer_compound(2);
+                               ir_initializer_t *complex_init = create_initializer_compound(2);
                                ir_initializer_t *reali = create_initializer_const(real);
-                               set_initializer_compound_value(initializer, 0, reali);
+                               set_initializer_compound_value(complex_init, 0, reali);
                                ir_initializer_t *imagi = create_initializer_const(imag);
-                               set_initializer_compound_value(initializer, 1, imagi);
-                               set_entity_initializer(irentity, initializer);
+                               set_initializer_compound_value(complex_init, 1, imagi);
+                               set_entity_initializer(irentity, complex_init);
                        }
                        return;
                } else if (!is_type_scalar(init_type)) {
@@ -5166,7 +5153,7 @@ static ir_node *do_while_statement_to_firm(do_while_statement_t *statement)
 
        expression_t *const cond = statement->condition;
        /* Avoid an explicit body block in case of do ... while (0);. */
-       if (is_constant_expression(cond) == EXPR_CLASS_CONSTANT && !fold_constant_to_bool(cond)) {
+       if (is_constant_expression(cond) != EXPR_CLASS_VARIABLE && !fold_constant_to_bool(cond)) {
                /* do ... while (0);. */
                statement_to_firm(statement->body);
                jump_to_target(&continue_target);
@@ -5222,7 +5209,7 @@ static ir_node *for_statement_to_firm(for_statement_t *statement)
 
        /* Create the condition. */
        expression_t *const cond = statement->condition;
-       if (cond && (is_constant_expression(cond) != EXPR_CLASS_CONSTANT || !fold_constant_to_bool(cond))) {
+       if (cond && (is_constant_expression(cond) == EXPR_CLASS_VARIABLE || !fold_constant_to_bool(cond))) {
                jump_target body_target;
                init_jump_target(&body_target, NULL);
                expression_to_control_flow(cond, &body_target, &break_target);