semantic: Extend expression classification to detect integer constant expressions.
[cparser] / ast2firm.c
index 7e605af..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>
 
@@ -59,6 +44,16 @@ struct trampoline_region {
        ir_entity        *region;      /**< created region for the trampoline */
 };
 
+typedef struct complex_value {
+       ir_node *real;
+       ir_node *imag;
+} complex_value;
+
+typedef struct complex_constant {
+       ir_tarval *real;
+       ir_tarval *imag;
+} complex_constant;
+
 fp_model_t firm_fp_model = fp_model_precise;
 
 static const backend_params *be_params;
@@ -141,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);
 }
 
@@ -193,8 +185,9 @@ static void set_unreachable_now(void)
 
 ir_mode *atomic_modes[ATOMIC_TYPE_LAST+1];
 
-static ir_node *_expression_to_firm(const expression_t *expression);
-static ir_node *expression_to_firm(const expression_t *expression);
+static ir_node *expression_to_control_flow(expression_t const *expr, jump_target *true_target, jump_target *false_target);
+static ir_node *expression_to_value(expression_t const *expr);
+static complex_value expression_to_complex(const expression_t *expression);
 
 static unsigned decide_modulo_shift(unsigned type_size)
 {
@@ -252,7 +245,7 @@ static ir_node *get_vla_size(array_type_t *const type)
 {
        ir_node *size_node = type->size_node;
        if (size_node == NULL) {
-               size_node = expression_to_firm(type->size_expression);
+               size_node = expression_to_value(type->size_expression);
                type->size_node = size_node;
        }
        return size_node;
@@ -312,6 +305,7 @@ static ir_type *create_complex_type(atomic_type_kind_t akind,
                elemsize += align - (elemsize % align);
        }
        set_type_size_bytes(irtype, n_elements * elemsize);
+       set_type_state(irtype, layout_fixed);
 
        return irtype;
 }
@@ -488,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;
        }
 
@@ -520,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;
        }
 
@@ -603,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);
@@ -622,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,
@@ -738,7 +736,7 @@ static ir_mode *get_ir_mode_storage(type_t *type)
        type = skip_typeref(type);
 
        /* Firm doesn't report a mode for arrays and structs/unions. */
-       if (!is_type_scalar(type)) {
+       if (!is_type_scalar(type) || is_type_complex(type)) {
                return mode_P_data;
        }
 
@@ -748,6 +746,15 @@ static ir_mode *get_ir_mode_storage(type_t *type)
        return mode;
 }
 
+static ir_mode *get_complex_mode_storage(type_t *type)
+{
+       assert(is_type_complex(skip_typeref(type)));
+       ir_type *const irtype = get_ir_type(type);
+       ir_type *const etype  = get_array_element_type(irtype);
+       ir_mode *const mode   = get_type_mode(etype);
+       return mode;
+}
+
 /*
  * get arithmetic mode for a type. This is different from get_ir_mode_storage,
  * int that it returns bigger modes for floating point on some platforms
@@ -763,13 +770,22 @@ static ir_mode *get_ir_mode_arithmetic(type_t *type)
        return mode;
 }
 
+static ir_mode *get_complex_mode_arithmetic(type_t *type)
+{
+       ir_mode *mode = get_complex_mode_storage(type);
+       if (mode_is_float(mode) && mode_float_arithmetic != NULL) {
+               return mode_float_arithmetic;
+       }
+
+       return mode;
+}
+
 /**
  * Return a node representing the size of a type.
  */
 static ir_node *get_type_size_node(type_t *type)
 {
-       unsigned size;
-       ir_mode *mode = get_ir_mode_arithmetic(type_size_t);
+       ir_mode *const mode = get_ir_mode_storage(type_size_t);
        type = skip_typeref(type);
 
        if (is_type_array(type) && type->array.is_vla) {
@@ -779,7 +795,7 @@ static ir_node *get_type_size_node(type_t *type)
                return real_size;
        }
 
-       size = get_type_size(type);
+       unsigned const size = get_type_size(type);
        return new_Const_long(mode, size);
 }
 
@@ -1089,33 +1105,6 @@ static ir_node *create_Const_from_bool(ir_mode *const mode, bool const v)
        return new_Const((v ? get_mode_one : get_mode_null)(mode));
 }
 
-static ir_node *create_conv_from_b(dbg_info *dbgi, ir_node *value,
-                                   ir_mode *dest_mode)
-{
-       if (is_Const(value)) {
-               return create_Const_from_bool(dest_mode, !is_Const_null(value));
-       }
-
-       ir_node *cond       = new_d_Cond(dbgi, value);
-       ir_node *proj_true  = new_Proj(cond, mode_X, pn_Cond_true);
-       ir_node *proj_false = new_Proj(cond, mode_X, pn_Cond_false);
-       ir_node *tblock     = new_Block(1, &proj_true);
-       ir_node *fblock     = new_Block(1, &proj_false);
-       set_cur_block(tblock);
-       ir_node *const1 = new_Const(get_mode_one(dest_mode));
-       ir_node *tjump  = new_Jmp();
-       set_cur_block(fblock);
-       ir_node *const0 = new_Const(get_mode_null(dest_mode));
-       ir_node *fjump  = new_Jmp();
-
-       ir_node *in[2]      = { tjump, fjump };
-       ir_node *mergeblock = new_Block(2, in);
-       set_cur_block(mergeblock);
-       ir_node *phi_in[2]  = { const1, const0 };
-       ir_node *phi        = new_Phi(2, phi_in, dest_mode);
-       return phi;
-}
-
 static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode)
 {
        ir_mode *value_mode = get_irn_mode(value);
@@ -1123,17 +1112,15 @@ static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode)
        if (value_mode == dest_mode)
                return value;
 
-       if (dest_mode == mode_b) {
-               ir_node *zero = new_Const(get_mode_null(value_mode));
-               ir_node *cmp  = new_d_Cmp(dbgi, value, zero, ir_relation_unordered_less_greater);
-               return cmp;
-       } else if (value_mode == mode_b) {
-               return create_conv_from_b(dbgi, value, dest_mode);
-       }
-
        return new_d_Conv(dbgi, value, dest_mode);
 }
 
+static ir_node *conv_to_storage_type(dbg_info *const dbgi, ir_node *const val, type_t *const type)
+{
+       ir_mode *const mode = get_ir_mode_storage(type);
+       return create_conv(dbgi, val, mode);
+}
+
 /**
  * Creates a SymConst node representing a string constant.
  *
@@ -1203,7 +1190,7 @@ finish:;
 
 static bool try_create_integer(literal_expression_t *literal, type_t *type)
 {
-       assert(type->kind == TYPE_ATOMIC);
+       assert(type->kind == TYPE_ATOMIC || type->kind == TYPE_COMPLEX);
        atomic_type_kind_t akind = type->atomic.akind;
 
        ir_mode    *const mode = atomic_modes[akind];
@@ -1260,10 +1247,9 @@ finished:
 /**
  * Creates a Const node representing a constant.
  */
-static ir_node *literal_to_firm(const literal_expression_t *literal)
+static ir_node *literal_to_firm_(const literal_expression_t *literal,
+                                 ir_mode *mode)
 {
-       type_t     *type   = skip_typeref(literal->base.type);
-       ir_mode    *mode   = get_ir_mode_storage(type);
        const char *string = literal->value.begin;
        size_t      size   = literal->value.size;
        ir_tarval  *tv;
@@ -1292,10 +1278,15 @@ static ir_node *literal_to_firm(const literal_expression_t *literal)
                panic("invalid literal kind");
        }
 
-       dbg_info *dbgi       = get_dbg_info(&literal->base.pos);
-       ir_node  *res        = new_d_Const(dbgi, tv);
-       ir_mode  *mode_arith = get_ir_mode_arithmetic(type);
-       return create_conv(dbgi, res, mode_arith);
+       dbg_info *const dbgi = get_dbg_info(&literal->base.pos);
+       return new_d_Const(dbgi, tv);
+}
+
+static ir_node *literal_to_firm(const literal_expression_t *literal)
+{
+       type_t  *type         = skip_typeref(literal->base.type);
+       ir_mode *mode_storage = get_ir_mode_storage(type);
+       return literal_to_firm_(literal, mode_storage);
 }
 
 /**
@@ -1342,10 +1333,8 @@ static ir_node *char_literal_to_firm(string_literal_expression_t const *literal)
                panic("invalid literal kind");
        }
 
-       dbg_info *dbgi       = get_dbg_info(&literal->base.pos);
-       ir_node  *res        = new_d_Const(dbgi, tv);
-       ir_mode  *mode_arith = get_ir_mode_arithmetic(type);
-       return create_conv(dbgi, res, mode_arith);
+       dbg_info *const dbgi = get_dbg_info(&literal->base.pos);
+       return new_d_Const(dbgi, tv);
 }
 
 /*
@@ -1460,9 +1449,7 @@ static ir_node *deref_address(dbg_info *const dbgi, type_t *const type,
        ir_node *const load_res = new_d_Proj(dbgi, load, mode,   pn_Load_res);
 
        set_store(load_mem);
-
-       ir_mode *const mode_arithmetic = get_ir_mode_arithmetic(skipped);
-       return create_conv(dbgi, load_res, mode_arithmetic);
+       return load_res;
 }
 
 /**
@@ -1519,14 +1506,12 @@ static ir_node *reference_addr(const reference_expression_t *ref)
                        warningf(WARN_OTHER, pos, "taking address of builtin '%N'", ref->entity);
 
                        /* simply create a NULL pointer */
-                       ir_mode  *mode = get_ir_mode_arithmetic(type_void_ptr);
-                       ir_node  *res  = new_Const(get_mode_null(mode));
-
-                       return res;
+                       ir_mode *const mode = get_ir_mode_storage(type_void_ptr);
+                       return new_Const(get_mode_null(mode));
                }
        }
 
-       switch((declaration_kind_t) entity->declaration.kind) {
+       switch ((declaration_kind_t) entity->declaration.kind) {
        case DECLARATION_KIND_UNKNOWN:
                break;
        case DECLARATION_KIND_PARAMETER:
@@ -1584,8 +1569,7 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        case DECLARATION_KIND_PARAMETER: {
                type_t  *const type  = skip_typeref(entity->declaration.type);
                ir_mode *const mode  = get_ir_mode_storage(type);
-               ir_node *const value = get_value(entity->variable.v.value_number, mode);
-               return create_conv(dbgi, value, get_ir_mode_arithmetic(type));
+               return get_value(entity->variable.v.value_number, mode);
        }
 
        default: {
@@ -1615,7 +1599,7 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                break;
        case BUILTIN_ALLOCA: {
                expression_t *argument = call->arguments->expression;
-               ir_node      *size     = expression_to_firm(argument);
+               ir_node      *size     = expression_to_value(argument);
 
                ir_node *store  = get_store();
                ir_node *alloca = new_d_Alloc(dbgi, store, size, get_unknown_type(),
@@ -1628,7 +1612,7 @@ static ir_node *process_builtin_call(const call_expression_t *call)
        }
        case BUILTIN_INF: {
                type_t    *type = function_type->function.return_type;
-               ir_mode   *mode = get_ir_mode_arithmetic(type);
+               ir_mode   *mode = get_ir_mode_storage(type);
                ir_tarval *tv   = get_mode_infinite(mode);
                ir_node   *res  = new_d_Const(dbgi, tv);
                return res;
@@ -1637,25 +1621,25 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                /* Ignore string for now... */
                assert(is_type_function(function_type));
                type_t    *type = function_type->function.return_type;
-               ir_mode   *mode = get_ir_mode_arithmetic(type);
+               ir_mode   *mode = get_ir_mode_storage(type);
                ir_tarval *tv   = get_mode_NAN(mode);
                ir_node   *res  = new_d_Const(dbgi, tv);
                return res;
        }
        case BUILTIN_EXPECT: {
                expression_t *argument = call->arguments->expression;
-               return _expression_to_firm(argument);
+               return expression_to_value(argument);
        }
        case BUILTIN_VA_END:
                /* evaluate the argument of va_end for its side effects */
-               _expression_to_firm(call->arguments->expression);
+               expression_to_value(call->arguments->expression);
                return NULL;
        case BUILTIN_OBJECT_SIZE: {
                /* determine value of "type" */
                expression_t *type_expression = call->arguments->next->expression;
                long          type_val        = fold_constant_to_int(type_expression);
                type_t       *type            = function_type->function.return_type;
-               ir_mode      *mode            = get_ir_mode_arithmetic(type);
+               ir_mode      *mode            = get_ir_mode_storage(type);
                /* just produce a "I don't know" result */
                ir_tarval    *result          = type_val & 2 ? get_mode_null(mode) :
                                                get_mode_minus_one(mode);
@@ -1663,15 +1647,15 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                return new_d_Const(dbgi, result);
        }
        case BUILTIN_ROTL: {
-               ir_node *val  = expression_to_firm(call->arguments->expression);
-               ir_node *shf  = expression_to_firm(call->arguments->next->expression);
+               ir_node *val  = expression_to_value(call->arguments->expression);
+               ir_node *shf  = expression_to_value(call->arguments->next->expression);
                ir_mode *mode = get_irn_mode(val);
                ir_mode *mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
                return new_d_Rotl(dbgi, val, create_conv(dbgi, shf, mode_uint), mode);
        }
        case BUILTIN_ROTR: {
-               ir_node *val  = expression_to_firm(call->arguments->expression);
-               ir_node *shf  = expression_to_firm(call->arguments->next->expression);
+               ir_node *val  = expression_to_value(call->arguments->expression);
+               ir_node *shf  = expression_to_value(call->arguments->next->expression);
                ir_mode *mode = get_irn_mode(val);
                ir_mode *mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
                ir_node *c    = new_Const_long(mode_uint, get_mode_size_bits(mode));
@@ -1687,6 +1671,9 @@ static ir_node *process_builtin_call(const call_expression_t *call)
        panic("invalid builtin");
 }
 
+static ir_node *complex_to_memory(dbg_info *dbgi, type_t *type,
+                                  complex_value value);
+
 /**
  * Transform a call expression.
  * Handles some special cases, like alloca() calls, which must be resolved
@@ -1719,7 +1706,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                }
        }
        if (!firm_builtin)
-               callee = expression_to_firm(function);
+               callee = expression_to_value(function);
 
        type_t *type = skip_typeref(function->base.type);
        assert(is_type_pointer(type));
@@ -1769,16 +1756,14 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
        const call_argument_t *argument = call->arguments;
        for (int n = 0; n < n_parameters; ++n) {
                expression_t *expression = argument->expression;
-               ir_node      *arg_node   = expression_to_firm(expression);
-
-               type_t *arg_type = skip_typeref(expression->base.type);
-               if (!is_type_compound(arg_type)) {
-                       ir_mode *const mode = get_ir_mode_storage(arg_type);
-                       arg_node = create_conv(dbgi, arg_node, mode);
+               type_t *const arg_type = skip_typeref(expression->base.type);
+               if (is_type_complex(arg_type)) {
+                       complex_value value = expression_to_complex(expression);
+                       in[n] = complex_to_memory(dbgi, arg_type, value);
+               } else {
+                       in[n] = conv_to_storage_type(dbgi, expression_to_value(expression), arg_type);
                }
 
-               in[n] = arg_node;
-
                argument = argument->next;
        }
 
@@ -1804,8 +1789,6 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                        assert(is_type_scalar(return_type));
                        ir_mode *mode = get_ir_mode_storage(return_type);
                        result = new_Proj(node, mode, pn_Builtin_max+1);
-                       ir_mode *mode_arith = get_ir_mode_arithmetic(return_type);
-                       result              = create_conv(NULL, result, mode_arith);
                }
        } else {
                node = new_d_Call(dbgi, store, callee, n_parameters, in, ir_method_type);
@@ -1815,11 +1798,9 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                }
 
                if (!is_type_void(return_type)) {
-                       ir_node *const resproj    = new_Proj(node, mode_T, pn_Call_T_result);
-                       ir_mode *const mode       = get_ir_mode_storage(return_type);
-                       result                    = new_Proj(resproj, mode, 0);
-                       ir_mode *const mode_arith = get_ir_mode_arithmetic(return_type);
-                       result                    = create_conv(NULL, result, mode_arith);
+                       ir_node *const resproj = new_Proj(node, mode_T, pn_Call_T_result);
+                       ir_mode *const mode    = get_ir_mode_storage(return_type);
+                       result                 = new_Proj(resproj, mode, 0);
                }
        }
 
@@ -1837,21 +1818,16 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
 
 static ir_node *statement_to_firm(statement_t *statement);
 static ir_node *compound_statement_to_firm(compound_statement_t *compound);
-
 static ir_node *expression_to_addr(const expression_t *expression);
-static ir_node *create_condition_evaluation(expression_t const *expression, jump_target *true_target, jump_target *false_target);
 
 static void assign_value(dbg_info *dbgi, ir_node *addr, type_t *type,
                          ir_node *value)
 {
-       if (is_type_scalar(type)) {
-               ir_mode *mode = get_ir_mode_storage(type);
-               value         = create_conv(dbgi, value, mode);
-       }
+       value = conv_to_storage_type(dbgi, value, type);
 
        ir_node *memory = get_store();
 
-       if (is_type_scalar(type)) {
+       if (is_type_scalar(type) && !is_type_complex(type)) {
                ir_cons_flags flags = type->base.qualifiers & TYPE_QUALIFIER_VOLATILE
                                      ? cons_volatile : cons_none;
                ir_node  *store     = new_d_Store(dbgi, memory, addr, value, flags);
@@ -1987,9 +1963,7 @@ static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
                shiftr = new_d_Shr(dbgi, shiftl, countr, amode);
        }
 
-       type_t  *type    = expression->base.type;
-       ir_mode *resmode = get_ir_mode_arithmetic(type);
-       return create_conv(dbgi, shiftr, resmode);
+       return conv_to_storage_type(dbgi, shiftr, expression->base.type);
 }
 
 /* make sure the selected compound type is constructed */
@@ -2007,11 +1981,7 @@ static ir_node *set_value_for_expression_addr(const expression_t *expression,
 {
        dbg_info *dbgi = get_dbg_info(&expression->base.pos);
        type_t   *type = skip_typeref(expression->base.type);
-
-       if (!is_type_compound(type)) {
-               ir_mode  *mode = get_ir_mode_storage(type);
-               value          = create_conv(dbgi, value, mode);
-       }
+       value = conv_to_storage_type(dbgi, value, type);
 
        if (expression->kind == EXPR_REFERENCE) {
                const reference_expression_t *ref = &expression->reference;
@@ -2051,12 +2021,6 @@ static ir_node *set_value_for_expression_addr(const expression_t *expression,
        return value;
 }
 
-static void set_value_for_expression(const expression_t *expression,
-                                     ir_node *value)
-{
-       set_value_for_expression_addr(expression, value, NULL);
-}
-
 static ir_node *get_value_from_lvalue(const expression_t *expression,
                                       ir_node *addr)
 {
@@ -2074,8 +2038,7 @@ static ir_node *get_value_from_lvalue(const expression_t *expression,
                        assert(addr == NULL);
                        type_t  *type = skip_typeref(expression->base.type);
                        ir_mode *mode = get_ir_mode_storage(type);
-                       ir_node *res  = get_value(value_number, mode);
-                       return create_conv(NULL, res, get_ir_mode_arithmetic(type));
+                       return get_value(value_number, mode);
                }
        }
 
@@ -2094,52 +2057,30 @@ static ir_node *get_value_from_lvalue(const expression_t *expression,
        return value;
 }
 
-
-static ir_node *create_incdec(const unary_expression_t *expression)
+static ir_node *incdec_to_firm(unary_expression_t const *const expr, bool const inc, bool const pre)
 {
-       dbg_info *const     dbgi = get_dbg_info(&expression->base.pos);
-       const expression_t *value_expr = expression->value;
-       ir_node            *addr       = expression_to_addr(value_expr);
-       ir_node            *value      = get_value_from_lvalue(value_expr, addr);
-
-       type_t  *type = skip_typeref(expression->base.type);
-       ir_mode *mode = get_ir_mode_arithmetic(expression->base.type);
+       type_t  *const type = skip_typeref(expr->base.type);
+       ir_mode *const mode = get_ir_mode_arithmetic(type);
 
        ir_node *offset;
        if (is_type_pointer(type)) {
-               pointer_type_t *pointer_type = &type->pointer;
-               offset = get_type_size_node(pointer_type->points_to);
+               offset = get_type_size_node(type->pointer.points_to);
        } else {
                assert(is_type_arithmetic(type));
                offset = new_Const(get_mode_one(mode));
        }
 
-       ir_node *result;
-       ir_node *store_value;
-       switch(expression->base.kind) {
-       case EXPR_UNARY_POSTFIX_INCREMENT:
-               result      = value;
-               store_value = new_d_Add(dbgi, value, offset, mode);
-               break;
-       case EXPR_UNARY_POSTFIX_DECREMENT:
-               result      = value;
-               store_value = new_d_Sub(dbgi, value, offset, mode);
-               break;
-       case EXPR_UNARY_PREFIX_INCREMENT:
-               result      = new_d_Add(dbgi, value, offset, mode);
-               store_value = result;
-               break;
-       case EXPR_UNARY_PREFIX_DECREMENT:
-               result      = new_d_Sub(dbgi, value, offset, mode);
-               store_value = result;
-               break;
-       default:
-               panic("no incdec expr");
-       }
-
-       set_value_for_expression_addr(value_expr, store_value, addr);
+       dbg_info           *const dbgi        = get_dbg_info(&expr->base.pos);
+       expression_t const *const value_expr  = expr->value;
+       ir_node            *const addr        = expression_to_addr(value_expr);
+       ir_node            *const value       = get_value_from_lvalue(value_expr, addr);
+       ir_node            *const value_arith = create_conv(dbgi, value, mode);
+       ir_node            *const new_value   = inc
+               ? new_d_Add(dbgi, value_arith, offset, mode)
+               : new_d_Sub(dbgi, value_arith, offset, mode);
 
-       return result;
+       ir_node *const store_value = set_value_for_expression_addr(value_expr, new_value, addr);
+       return pre ? store_value : value;
 }
 
 static bool is_local_variable(expression_t *expression)
@@ -2156,7 +2097,7 @@ static bool is_local_variable(expression_t *expression)
 
 static ir_relation get_relation(const expression_kind_t kind)
 {
-       switch(kind) {
+       switch (kind) {
        case EXPR_BINARY_EQUAL:         return ir_relation_equal;
        case EXPR_BINARY_ISLESSGREATER: return ir_relation_less_greater;
        case EXPR_BINARY_NOTEQUAL:      return ir_relation_unordered_less_greater;
@@ -2217,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;
@@ -2231,7 +2172,7 @@ static ir_node *handle_assume_compare(dbg_info *dbi,
                ir_mode *const mode = get_ir_mode_storage(type);
 
                res = get_value(var->variable.v.value_number, mode);
-               res = new_d_Confirm(dbi, res, expression_to_firm(con), relation);
+               res = new_d_Confirm(dbi, res, expression_to_value(con), relation);
                set_value(var->variable.v.value_number, res);
        }
        return res;
@@ -2243,38 +2184,37 @@ static ir_node *handle_assume_compare(dbg_info *dbi,
  * @param dbi    debug info
  * @param expr   the IL assume expression
  */
-static ir_node *handle_assume(dbg_info *dbi, const expression_t *expression)
+static ir_node *handle_assume(expression_t const *const expr)
 {
-       switch(expression->kind) {
+       switch (expr->kind) {
        case EXPR_BINARY_EQUAL:
        case EXPR_BINARY_NOTEQUAL:
        case EXPR_BINARY_LESS:
        case EXPR_BINARY_LESSEQUAL:
        case EXPR_BINARY_GREATER:
-       case EXPR_BINARY_GREATEREQUAL:
-               return handle_assume_compare(dbi, &expression->binary);
+       case EXPR_BINARY_GREATEREQUAL: {
+               dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+               return handle_assume_compare(dbgi, &expr->binary);
+       }
+
        default:
                return NULL;
        }
 }
 
-static ir_node *create_cast(dbg_info *dbgi, ir_node *value_node,
-                            type_t *from_type, type_t *type)
+static ir_node *create_cast(unary_expression_t const *const expr)
 {
-       type = skip_typeref(type);
-       if (is_type_void(type)) {
-               /* make sure firm type is constructed */
-               (void) get_ir_type(type);
+       type_t *const type = skip_typeref(expr->base.type);
+       if (is_type_void(type))
                return NULL;
-       }
-       if (!is_type_scalar(type)) {
-               /* make sure firm type is constructed */
-               (void) get_ir_type(type);
-               return value_node;
-       }
 
-       from_type     = skip_typeref(from_type);
-       ir_mode *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;
@@ -2283,135 +2223,59 @@ static ir_node *create_cast(dbg_info *dbgi, ir_node *value_node,
                        if (from_var != NULL) {
                                ir_node *const addr = create_symconst(dbgi, from_var->v.entity);
                                ir_node *const base = deref_address(dbgi, from_var->base.type, addr);
-                               value_node = new_d_Add(dbgi, value_node, base, mode);
+                               value = new_d_Add(dbgi, value, base, mode);
                        }
                        if (to_var != NULL) {
                                ir_node *const addr = create_symconst(dbgi, to_var->v.entity);
                                ir_node *const base = deref_address(dbgi, to_var->base.type, addr);
-                               value_node = new_d_Sub(dbgi, value_node, base, mode);
+                               value = new_d_Sub(dbgi, value, base, mode);
                        }
                }
        }
 
-       if (is_type_atomic(type, ATOMIC_TYPE_BOOL)) {
-               /* bool adjustments (we save a mode_Bu, but have to temporarily
-                * convert to mode_b so we only get a 0/1 value */
-               value_node = create_conv(dbgi, value_node, mode_b);
-       }
-
-       ir_mode *mode_arith = get_ir_mode_arithmetic(type);
-       ir_node *node       = create_conv(dbgi, value_node, mode);
-       node                = create_conv(dbgi, node, mode_arith);
-
-       return node;
+       return create_conv(dbgi, value, mode);
 }
 
-static ir_node *unary_expression_to_firm(const unary_expression_t *expression)
+static ir_node *complement_to_firm(unary_expression_t const *const expr)
 {
-       dbg_info *dbgi = get_dbg_info(&expression->base.pos);
-       type_t   *type = skip_typeref(expression->base.type);
-
-       const expression_t *value = expression->value;
-
-       switch(expression->base.kind) {
-       case EXPR_UNARY_TAKE_ADDRESS:
-               return expression_to_addr(value);
-
-       case EXPR_UNARY_NEGATE: {
-               ir_node *value_node = expression_to_firm(value);
-               ir_mode *mode       = get_ir_mode_arithmetic(type);
-               return new_d_Minus(dbgi, value_node, mode);
-       }
-       case EXPR_UNARY_PLUS:
-               return expression_to_firm(value);
-       case EXPR_UNARY_BITWISE_NEGATE: {
-               ir_node *value_node = expression_to_firm(value);
-               ir_mode *mode       = get_ir_mode_arithmetic(type);
-               return new_d_Not(dbgi, value_node, mode);
-       }
-       case EXPR_UNARY_NOT: {
-               ir_node *value_node = _expression_to_firm(value);
-               value_node          = create_conv(dbgi, value_node, mode_b);
-               ir_node *res        = new_d_Not(dbgi, value_node, mode_b);
-               return res;
-       }
-       case EXPR_UNARY_DEREFERENCE: {
-               ir_node *value_node = expression_to_firm(value);
-               type_t  *value_type = skip_typeref(value->base.type);
-               assert(is_type_pointer(value_type));
-
-               /* check for __based */
-               const variable_t *const base_var = value_type->pointer.base_variable;
-               if (base_var != NULL) {
-                       ir_node *const addr = create_symconst(dbgi, base_var->v.entity);
-                       ir_node *const base = deref_address(dbgi, base_var->base.type, addr);
-                       value_node = new_d_Add(dbgi, value_node, base, get_ir_mode_storage(value_type));
-               }
-               type_t  *points_to  = value_type->pointer.points_to;
-               return deref_address(dbgi, points_to, value_node);
-       }
-       case EXPR_UNARY_POSTFIX_INCREMENT:
-       case EXPR_UNARY_POSTFIX_DECREMENT:
-       case EXPR_UNARY_PREFIX_INCREMENT:
-       case EXPR_UNARY_PREFIX_DECREMENT:
-               return create_incdec(expression);
-       case EXPR_UNARY_CAST: {
-               ir_node *value_node = expression_to_firm(value);
-               type_t  *from_type  = value->base.type;
-               return create_cast(dbgi, value_node, from_type, type);
-       }
-       case EXPR_UNARY_ASSUME:
-               return handle_assume(dbgi, value);
-
-       default:
-               break;
-       }
-       panic("invalid unary expression type");
+       dbg_info *const dbgi  = get_dbg_info(&expr->base.pos);
+       type_t   *const type  = skip_typeref(expr->base.type);
+       ir_mode  *const mode  = get_ir_mode_arithmetic(type);
+       ir_node  *const value = create_conv(dbgi, expression_to_value(expr->value), mode);
+       return new_d_Not(dbgi, value, mode);
 }
 
-/**
- * produces a 0/1 depending of the value of a mode_b node
- */
-static ir_node *produce_condition_result(const expression_t *expression,
-                                         ir_mode *mode, dbg_info *dbgi)
+static ir_node *dereference_to_firm(unary_expression_t const *const expr)
 {
-       jump_target true_target;
-       jump_target false_target;
-       init_jump_target(&true_target,  NULL);
-       init_jump_target(&false_target, NULL);
-       create_condition_evaluation(expression, &true_target, &false_target);
-
-       ir_node    *val = NULL;
-       jump_target exit_target;
-       init_jump_target(&exit_target, NULL);
-
-       if (enter_jump_target(&true_target)) {
-               val = new_Const(get_mode_one(mode));
-               jump_to_target(&exit_target);
-       }
+       dbg_info *const dbgi       = get_dbg_info(&expr->base.pos);
+       ir_node        *value      = expression_to_value(expr->value);
+       type_t   *const value_type = skip_typeref(expr->value->base.type);
+       assert(is_type_pointer(value_type));
 
-       if (enter_jump_target(&false_target)) {
-               ir_node *const zero = new_Const(get_mode_null(mode));
-               jump_to_target(&exit_target);
-               if (val) {
-                       ir_node *const in[] = { val, zero };
-                       val = new_rd_Phi(dbgi, exit_target.block, lengthof(in), in, mode);
-               } else {
-                       val = zero;
-               }
+       /* check for __based */
+       variable_t const *const base_var = value_type->pointer.base_variable;
+       if (base_var) {
+               ir_node *const addr = create_symconst(dbgi, base_var->v.entity);
+               ir_node *const base = deref_address(dbgi, base_var->base.type, addr);
+               value = new_d_Add(dbgi, value, base, get_ir_mode_storage(value_type));
        }
+       type_t *const points_to = value_type->pointer.points_to;
+       return deref_address(dbgi, points_to, value);
+}
 
-       if (!enter_jump_target(&exit_target)) {
-               set_cur_block(new_Block(0, NULL));
-               val = new_Unknown(mode);
-       }
-       return val;
+static ir_node *negate_to_firm(unary_expression_t const *const expr)
+{
+       dbg_info *const dbgi  = get_dbg_info(&expr->base.pos);
+       type_t   *const type  = skip_typeref(expr->base.type);
+       ir_mode  *const mode  = get_ir_mode_arithmetic(type);
+       ir_node  *const value = create_conv(dbgi, expression_to_value(expr->value), mode);
+       return new_d_Minus(dbgi, value, mode);
 }
 
 static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi,
                ir_node *value, type_t *type)
 {
-       ir_mode        *const mode         = get_ir_mode_arithmetic(type_ptrdiff_t);
+       ir_mode        *const mode         = get_ir_mode_storage(type_ptrdiff_t);
        assert(is_type_pointer(type));
        pointer_type_t *const pointer_type = &type->pointer;
        type_t         *const points_to    = skip_typeref(pointer_type->points_to);
@@ -2422,21 +2286,29 @@ static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi,
        return mul;
 }
 
-static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression,
-                          ir_node *left, ir_node *right)
+static ir_node *create_div(dbg_info *dbgi, ir_node *left, ir_node *right,
+                           ir_mode *mode)
 {
-       ir_mode  *mode;
-       type_t   *type_left  = skip_typeref(expression->left->base.type);
-       type_t   *type_right = skip_typeref(expression->right->base.type);
-
-       expression_kind_t kind = expression->base.kind;
+       ir_node *pin = new_Pin(new_NoMem());
+       ir_node *op  = new_d_Div(dbgi, pin, left, right, mode,
+                                op_pin_state_floats);
+       return new_d_Proj(dbgi, op, mode, pn_Div_res);
+}
 
+static ir_node *create_op(binary_expression_t const *const expr, ir_node *left, ir_node *right)
+{
+       ir_mode                *mode;
+       dbg_info         *const dbgi       = get_dbg_info(&expr->base.pos);
+       type_t           *const type_left  = skip_typeref(expr->left->base.type);
+       type_t           *const type_right = skip_typeref(expr->right->base.type);
+       expression_kind_t const kind       = expr->base.kind;
        switch (kind) {
        case EXPR_BINARY_SHIFTLEFT:
        case EXPR_BINARY_SHIFTRIGHT:
        case EXPR_BINARY_SHIFTLEFT_ASSIGN:
        case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
-               mode  = get_ir_mode_arithmetic(expression->base.type);
+               mode  = get_ir_mode_arithmetic(expr->base.type);
+               left  = create_conv(dbgi, left,  mode);
                right = create_conv(dbgi, right, atomic_modes[ATOMIC_TYPE_UINT]);
                break;
 
@@ -2444,7 +2316,7 @@ static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression,
                if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
                        const pointer_type_t *const ptr_type = &type_left->pointer;
 
-                       mode = get_ir_mode_arithmetic(expression->base.type);
+                       mode = get_ir_mode_storage(expr->base.type);
                        ir_node *const elem_size = get_type_size_node(ptr_type->points_to);
                        ir_node *const conv_size = new_d_Conv(dbgi, elem_size, mode);
                        ir_node *const sub       = new_d_Sub(dbgi, left, right, mode);
@@ -2457,7 +2329,7 @@ static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression,
        case EXPR_BINARY_SUB_ASSIGN:
                if (is_type_pointer(type_left)) {
                        right = adjust_for_pointer_arithmetic(dbgi, right, type_left);
-                       mode  = get_ir_mode_arithmetic(type_left);
+                       mode  = get_ir_mode_storage(type_left);
                        break;
                }
                goto normal_node;
@@ -2466,19 +2338,20 @@ static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression,
        case EXPR_BINARY_ADD_ASSIGN:
                if (is_type_pointer(type_left)) {
                        right = adjust_for_pointer_arithmetic(dbgi, right, type_left);
-                       mode  = get_ir_mode_arithmetic(type_left);
+                       mode  = get_ir_mode_storage(type_left);
                        break;
                } else if (is_type_pointer(type_right)) {
                        left  = adjust_for_pointer_arithmetic(dbgi, left, type_right);
-                       mode  = get_ir_mode_arithmetic(type_right);
+                       mode  = get_ir_mode_storage(type_right);
                        break;
                }
                goto normal_node;
 
        default:
 normal_node:
-               mode = get_ir_mode_arithmetic(type_right);
-               left = create_conv(dbgi, left, mode);
+               mode  = get_ir_mode_arithmetic(type_right);
+               left  = create_conv(dbgi, left,  mode);
+               right = create_conv(dbgi, right, mode);
                break;
        }
 
@@ -2492,6 +2365,9 @@ normal_node:
        case EXPR_BINARY_MUL_ASSIGN:
        case EXPR_BINARY_MUL:
                return new_d_Mul(dbgi, left, right, mode);
+       case EXPR_BINARY_DIV:
+       case EXPR_BINARY_DIV_ASSIGN:
+               return create_div(dbgi, left, right, mode);
        case EXPR_BINARY_BITWISE_AND:
        case EXPR_BINARY_BITWISE_AND_ASSIGN:
                return new_d_And(dbgi, left, right, mode);
@@ -2511,14 +2387,6 @@ normal_node:
                } else {
                        return new_d_Shr(dbgi, left, right, mode);
                }
-       case EXPR_BINARY_DIV:
-       case EXPR_BINARY_DIV_ASSIGN: {
-               ir_node *pin = new_Pin(new_NoMem());
-               ir_node *op  = new_d_Div(dbgi, pin, left, right, mode,
-                                        op_pin_state_floats);
-               ir_node *res = new_d_Proj(dbgi, op, mode, pn_Div_res);
-               return res;
-       }
        case EXPR_BINARY_MOD:
        case EXPR_BINARY_MOD_ASSIGN: {
                ir_node *pin = new_Pin(new_NoMem());
@@ -2532,153 +2400,156 @@ normal_node:
        }
 }
 
-static ir_node *create_lazy_op(const binary_expression_t *expression)
+static ir_node *binop_to_firm(binary_expression_t const *const expr)
 {
-       dbg_info *dbgi = get_dbg_info(&expression->base.pos);
-       type_t   *type = skip_typeref(expression->base.type);
-       ir_mode  *mode = get_ir_mode_arithmetic(type);
-
-       if (is_constant_expression(expression->left) == EXPR_CLASS_CONSTANT) {
-               bool val = fold_constant_to_bool(expression->left);
-               expression_kind_t ekind = expression->base.kind;
-               assert(ekind == EXPR_BINARY_LOGICAL_AND || ekind == EXPR_BINARY_LOGICAL_OR);
-               if (ekind == EXPR_BINARY_LOGICAL_AND) {
-                       if (!val) {
-                               return new_Const(get_mode_null(mode));
-                       }
-               } else {
-                       if (val) {
-                               return new_Const(get_mode_one(mode));
-                       }
-               }
+       ir_node *const left  = expression_to_value(expr->left);
+       ir_node *const right = expression_to_value(expr->right);
+       return create_op(expr, left, right);
+}
 
-               if (is_constant_expression(expression->right) == EXPR_CLASS_CONSTANT) {
-                       bool valr = fold_constant_to_bool(expression->right);
-                       return create_Const_from_bool(mode, valr);
-               }
+/**
+ * Check if a given expression is a GNU __builtin_expect() call.
+ */
+static bool is_builtin_expect(const expression_t *expression)
+{
+       if (expression->kind != EXPR_CALL)
+               return false;
 
-               return produce_condition_result(expression->right, mode, dbgi);
-       }
+       expression_t *function = expression->call.function;
+       if (function->kind != EXPR_REFERENCE)
+               return false;
+       reference_expression_t *ref = &function->reference;
+       if (ref->entity->kind         != ENTITY_FUNCTION ||
+           ref->entity->function.btk != BUILTIN_EXPECT)
+               return false;
 
-       return produce_condition_result((const expression_t*) expression, mode,
-                                       dbgi);
+       return true;
 }
 
-typedef ir_node * (*create_arithmetic_func)(dbg_info *dbgi, ir_node *left,
-                                            ir_node *right, ir_mode *mode);
-
-static ir_node *create_assign_binop(const binary_expression_t *expression)
+static void compare_to_control_flow(expression_t const *const expr, ir_node *const left, ir_node *const right, ir_relation const relation, jump_target *const true_target, jump_target *const false_target)
 {
-       dbg_info *const     dbgi = get_dbg_info(&expression->base.pos);
-       const expression_t *left_expr = expression->left;
-       type_t             *type      = skip_typeref(left_expr->base.type);
-       ir_node            *right     = expression_to_firm(expression->right);
-       ir_node            *left_addr = expression_to_addr(left_expr);
-       ir_node            *left      = get_value_from_lvalue(left_expr, left_addr);
-       ir_node            *result    = create_op(dbgi, expression, left, right);
-
-       result = create_cast(dbgi, result, expression->right->base.type, type);
+       dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+       ir_node  *const cmp  = new_d_Cmp(dbgi, left, right, relation);
+       if (is_Const(cmp)) {
+               if (tarval_is_null(get_Const_tarval(cmp))) {
+                       jump_to_target(false_target);
+               } else {
+                       jump_to_target(true_target);
+               }
+       } else {
+               ir_node *const cond       = new_d_Cond(dbgi, cmp);
+               ir_node *const true_proj  = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
+               ir_node *const false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false);
 
-       result = set_value_for_expression_addr(left_expr, result, left_addr);
+               /* 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_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);
+                       }
+               }
 
-       if (!is_type_compound(type)) {
-               ir_mode *mode_arithmetic = get_ir_mode_arithmetic(type);
-               result = create_conv(dbgi, result, mode_arithmetic);
+               add_pred_to_jump_target(true_target,  true_proj);
+               add_pred_to_jump_target(false_target, false_proj);
        }
-       return result;
+       set_unreachable_now();
 }
 
-static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
+static ir_node *control_flow_to_1_0(expression_t const *const expr, jump_target *const true_target, jump_target *const false_target)
 {
-       expression_kind_t kind = expression->base.kind;
+       ir_node        *val  = NULL;
+       dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+       ir_mode  *const mode = get_ir_mode_storage(expr->base.type);
+       jump_target     exit_target;
+       init_jump_target(&exit_target, NULL);
 
-       switch(kind) {
-       case EXPR_BINARY_EQUAL:
-       case EXPR_BINARY_NOTEQUAL:
-       case EXPR_BINARY_LESS:
-       case EXPR_BINARY_LESSEQUAL:
-       case EXPR_BINARY_GREATER:
-       case EXPR_BINARY_GREATEREQUAL:
-       case EXPR_BINARY_ISGREATER:
-       case EXPR_BINARY_ISGREATEREQUAL:
-       case EXPR_BINARY_ISLESS:
-       case EXPR_BINARY_ISLESSEQUAL:
-       case EXPR_BINARY_ISLESSGREATER:
-       case EXPR_BINARY_ISUNORDERED: {
-               dbg_info   *dbgi     = get_dbg_info(&expression->base.pos);
-               ir_node    *left     = expression_to_firm(expression->left);
-               ir_node    *right    = expression_to_firm(expression->right);
-               ir_relation relation = get_relation(kind);
-               ir_node    *cmp      = new_d_Cmp(dbgi, left, right, relation);
-               return cmp;
-       }
-       case EXPR_BINARY_ASSIGN: {
-               ir_node *addr  = expression_to_addr(expression->left);
-               ir_node *right = expression_to_firm(expression->right);
-               ir_node *res
-                       = set_value_for_expression_addr(expression->left, right, addr);
-
-               type_t  *type            = skip_typeref(expression->base.type);
-               if (!is_type_compound(type)) {
-                       ir_mode *mode_arithmetic = get_ir_mode_arithmetic(type);
-                       res                      = create_conv(NULL, res, mode_arithmetic);
-               }
-               return res;
+       if (enter_jump_target(true_target)) {
+               jump_to_target(&exit_target);
+               val = new_d_Const(dbgi, get_mode_one(mode));
        }
-       case EXPR_BINARY_ADD:
-       case EXPR_BINARY_SUB:
-       case EXPR_BINARY_MUL:
-       case EXPR_BINARY_DIV:
-       case EXPR_BINARY_MOD:
-       case EXPR_BINARY_BITWISE_AND:
-       case EXPR_BINARY_BITWISE_OR:
-       case EXPR_BINARY_BITWISE_XOR:
-       case EXPR_BINARY_SHIFTLEFT:
-       case EXPR_BINARY_SHIFTRIGHT:
-       {
-               dbg_info *dbgi  = get_dbg_info(&expression->base.pos);
-               ir_node  *left  = expression_to_firm(expression->left);
-               ir_node  *right = expression_to_firm(expression->right);
-               return create_op(dbgi, expression, left, right);
+
+       if (enter_jump_target(false_target)) {
+               jump_to_target(&exit_target);
+               ir_node *const zero = new_d_Const(dbgi, get_mode_null(mode));
+               if (val) {
+                       ir_node *const in[] = { val, zero };
+                       val = new_rd_Phi(dbgi, exit_target.block, lengthof(in), in, mode);
+               } else {
+                       val = zero;
+               }
        }
-       case EXPR_BINARY_LOGICAL_AND:
-       case EXPR_BINARY_LOGICAL_OR:
-               return create_lazy_op(expression);
-       case EXPR_BINARY_COMMA:
-               /* create side effects of left side */
-               (void) expression_to_firm(expression->left);
-               return _expression_to_firm(expression->right);
 
-       case EXPR_BINARY_ADD_ASSIGN:
-       case EXPR_BINARY_SUB_ASSIGN:
-       case EXPR_BINARY_MUL_ASSIGN:
-       case EXPR_BINARY_MOD_ASSIGN:
-       case EXPR_BINARY_DIV_ASSIGN:
-       case EXPR_BINARY_BITWISE_AND_ASSIGN:
-       case EXPR_BINARY_BITWISE_OR_ASSIGN:
-       case EXPR_BINARY_BITWISE_XOR_ASSIGN:
-       case EXPR_BINARY_SHIFTLEFT_ASSIGN:
-       case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
-               return create_assign_binop(expression);
-       default:
-               panic("invalid binexpr type");
+       if (!enter_jump_target(&exit_target)) {
+               set_cur_block(new_Block(0, NULL));
+               val = new_d_Bad(dbgi, mode);
        }
+       return val;
 }
 
-static ir_node *array_access_addr(const array_access_expression_t *expression)
+static ir_node *binop_assign_to_firm(binary_expression_t const *const expr)
 {
-       dbg_info *dbgi        = get_dbg_info(&expression->base.pos);
-       ir_node  *base_addr   = expression_to_firm(expression->array_ref);
-       ir_node  *offset      = expression_to_firm(expression->index);
-       type_t   *ref_type    = skip_typeref(expression->array_ref->base.type);
-       ir_node  *real_offset = adjust_for_pointer_arithmetic(dbgi, offset, ref_type);
-       ir_node  *result      = new_d_Add(dbgi, base_addr, real_offset, mode_P_data);
+       ir_node            *const right     = expression_to_value(expr->right);
+       expression_t const *const left_expr = expr->left;
+       ir_node            *const addr      = expression_to_addr(left_expr);
+       ir_node            *const left      = get_value_from_lvalue(left_expr, addr);
+       ir_node                  *result    = create_op(expr, left, right);
 
-       return result;
+       type_t *const type = skip_typeref(expr->base.type);
+       if (is_type_atomic(type, ATOMIC_TYPE_BOOL)) {
+               jump_target true_target;
+               jump_target false_target;
+               init_jump_target(&true_target,  NULL);
+               init_jump_target(&false_target, NULL);
+               ir_mode *const mode = get_irn_mode(result);
+               ir_node *const zero = new_Const(get_mode_null(mode));
+               compare_to_control_flow((expression_t const*)expr, result, zero, ir_relation_unordered_less_greater, &true_target, &false_target);
+               result = control_flow_to_1_0((expression_t const*)expr, &true_target, &false_target);
+       }
+
+       return set_value_for_expression_addr(left_expr, result, addr);
 }
 
-static ir_node *array_access_to_firm(
-               const array_access_expression_t *expression)
+static ir_node *assign_expression_to_firm(binary_expression_t const *const expr)
+{
+       ir_node *const addr  = expression_to_addr(expr->left);
+       ir_node *const right = expression_to_value(expr->right);
+       return set_value_for_expression_addr(expr->left, right, addr);
+}
+
+/** evaluate an expression and discard the result, but still produce the
+ * side-effects. */
+static void evaluate_expression_discard_result(const expression_t *expression)
+{
+       type_t *type = skip_typeref(expression->base.type);
+       if (is_type_complex(type)) {
+               expression_to_complex(expression);
+       } else {
+               expression_to_value(expression);
+       }
+}
+
+static ir_node *comma_expression_to_firm(binary_expression_t const *const expr)
+{
+       evaluate_expression_discard_result(expr->left);
+       return expression_to_value(expr->right);
+}
+
+static ir_node *array_access_addr(const array_access_expression_t *expression)
+{
+       dbg_info *dbgi        = get_dbg_info(&expression->base.pos);
+       ir_node  *base_addr   = expression_to_value(expression->array_ref);
+       ir_node  *offset      = expression_to_value(expression->index);
+       type_t   *ref_type    = skip_typeref(expression->array_ref->base.type);
+       ir_node  *real_offset = adjust_for_pointer_arithmetic(dbgi, offset, ref_type);
+       ir_node  *result      = new_d_Add(dbgi, base_addr, real_offset, mode_P_data);
+
+       return result;
+}
+
+static ir_node *array_access_to_firm(
+               const array_access_expression_t *expression)
 {
        dbg_info *dbgi   = get_dbg_info(&expression->base.pos);
        ir_node  *addr   = array_access_addr(expression);
@@ -2734,7 +2605,7 @@ static long get_offsetof_offset(const offsetof_expression_t *expression)
 
 static ir_node *offsetof_to_firm(const offsetof_expression_t *expression)
 {
-       ir_mode   *mode   = get_ir_mode_arithmetic(expression->base.type);
+       ir_mode   *mode   = get_ir_mode_storage(expression->base.type);
        long       offset = get_offsetof_offset(expression);
        ir_tarval *tv     = new_tarval_from_long(offset, mode);
        dbg_info  *dbgi   = get_dbg_info(&expression->base.pos);
@@ -2773,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 {
@@ -2814,7 +2686,7 @@ static ir_node *sizeof_to_firm(const typeprop_expression_t *expression)
        /* Â§6.5.3.4:2 if the type is a VLA, evaluate the expression. */
        if (is_type_array(type) && type->array.is_vla
                        && expression->tp_expression != NULL) {
-               expression_to_firm(expression->tp_expression);
+               expression_to_value(expression->tp_expression);
        }
 
        return get_type_size_node(type);
@@ -2830,7 +2702,7 @@ static entity_t *get_expression_entity(const expression_t *expression)
 
 static unsigned get_cparser_entity_alignment(const entity_t *entity)
 {
-       switch(entity->kind) {
+       switch (entity->kind) {
        case DECLARATION_KIND_CASES:
                return entity->declaration.alignment;
        case ENTITY_STRUCT:
@@ -2865,7 +2737,7 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
        }
 
        dbg_info  *dbgi = get_dbg_info(&expression->base.pos);
-       ir_mode   *mode = get_ir_mode_arithmetic(expression->base.type);
+       ir_mode   *mode = get_ir_mode_storage(expression->base.type);
        ir_tarval *tv   = new_tarval_from_long(alignment, mode);
        return new_d_Const(dbgi, tv);
 }
@@ -2874,7 +2746,33 @@ 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;
+       int old_optimize         = get_optimize();
+       int old_constant_folding = get_opt_constant_folding();
+       set_optimize(1);
+       set_opt_constant_folding(1);
+
+       init_ir_types();
+
+       PUSH_IRG(get_const_code_irg());
+       ir_node *const cnst = expression_to_value(expression);
+       POP_IRG();
+
+       set_optimize(old_optimize);
+       set_opt_constant_folding(old_constant_folding);
+       constant_folding = constant_folding_old;
+
+       if (!is_Const(cnst))
+               panic("couldn't fold constant");
+       return get_Const_tarval(cnst);
+}
+
+static complex_constant fold_complex_constant(const expression_t *expression)
+{
+       assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
 
        bool constant_folding_old = constant_folding;
        constant_folding = true;
@@ -2886,21 +2784,22 @@ ir_tarval *fold_constant_to_tarval(const expression_t *expression)
        init_ir_types();
 
        PUSH_IRG(get_const_code_irg());
-       ir_node *const cnst = _expression_to_firm(expression);
+       complex_value value = expression_to_complex(expression);
        POP_IRG();
 
        set_optimize(old_optimize);
        set_opt_constant_folding(old_constant_folding);
 
-       if (!is_Const(cnst)) {
+       if (!is_Const(value.real) || !is_Const(value.imag)) {
                panic("couldn't fold constant");
        }
 
        constant_folding = constant_folding_old;
 
-       ir_tarval *const tv   = get_Const_tarval(cnst);
-       ir_mode   *const mode = get_ir_mode_arithmetic(skip_typeref(expression->base.type));
-       return tarval_convert_to(tv, mode);
+       return (complex_constant) {
+               get_Const_tarval(value.real),
+               get_Const_tarval(value.imag)
+       };
 }
 
 /* this function is only used in parser.c, but it relies on libfirm functionality */
@@ -2922,54 +2821,53 @@ long fold_constant_to_int(const expression_t *expression)
 
 bool fold_constant_to_bool(const expression_t *expression)
 {
-       ir_tarval *tv = fold_constant_to_tarval(expression);
-       return !tarval_is_null(tv);
+       type_t *type = skip_typeref(expression->base.type);
+       if (is_type_complex(type)) {
+               complex_constant tvs = fold_complex_constant(expression);
+               return !tarval_is_null(tvs.real) || !tarval_is_null(tvs.imag);
+       } else {
+               ir_tarval *tv = fold_constant_to_tarval(expression);
+               return !tarval_is_null(tv);
+       }
 }
 
 static ir_node *conditional_to_firm(const conditional_expression_t *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)
-                               true_expression = expression->condition;
-                       return expression_to_firm(true_expression);
-               } else {
-                       return expression_to_firm(expression->false_expression);
-               }
-       }
-
        jump_target true_target;
        jump_target false_target;
        init_jump_target(&true_target,  NULL);
        init_jump_target(&false_target, NULL);
-       ir_node *const cond_expr = create_condition_evaluation(expression->condition, &true_target, &false_target);
+       ir_node *const cond_expr = expression_to_control_flow(expression->condition, &true_target, &false_target);
 
-       ir_node    *val = NULL;
+       ir_node        *val  = NULL;
+       dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
+       type_t   *const type = skip_typeref(expression->base.type);
+       ir_mode  *const mode = get_ir_mode_arithmetic(type);
        jump_target exit_target;
        init_jump_target(&exit_target, NULL);
 
        if (enter_jump_target(&true_target)) {
                if (expression->true_expression) {
-                       val = expression_to_firm(expression->true_expression);
-               } else if (cond_expr && get_irn_mode(cond_expr) != mode_b) {
+                       val = expression_to_value(expression->true_expression);
+               } else if (cond_expr) {
                        val = cond_expr;
                } else {
                        /* Condition ended with a short circuit (&&, ||, !) operation or a
                         * comparison.  Generate a "1" as value for the true branch. */
-                       val = new_Const(get_mode_one(mode_Is));
+                       val = new_Const(get_mode_one(mode));
                }
+               if (val)
+                       val = create_conv(dbgi, val, mode);
                jump_to_target(&exit_target);
        }
 
        if (enter_jump_target(&false_target)) {
-               ir_node *const false_val = expression_to_firm(expression->false_expression);
+               ir_node *false_val = expression_to_value(expression->false_expression);
+               if (false_val)
+                       false_val = create_conv(dbgi, false_val, mode);
                jump_to_target(&exit_target);
                if (val) {
-                       ir_node  *const in[] = { val, false_val };
-                       dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
+                       ir_node *const in[] = { val, false_val };
                        val = new_rd_Phi(dbgi, exit_target.block, lengthof(in), in, get_irn_mode(val));
                } else {
                        val = false_val;
@@ -2978,9 +2876,8 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression)
 
        if (!enter_jump_target(&exit_target)) {
                set_cur_block(new_Block(0, NULL));
-               type_t *const type = skip_typeref(expression->base.type);
                if (!is_type_void(type))
-                       val = new_Unknown(get_ir_mode_arithmetic(type));
+                       val = new_Bad(mode);
        }
        return val;
 }
@@ -2994,7 +2891,7 @@ static ir_node *select_addr(const select_expression_t *expression)
 
        construct_select_compound(expression);
 
-       ir_node *compound_addr = expression_to_firm(expression->compound);
+       ir_node *compound_addr = expression_to_value(expression->compound);
 
        entity_t *entry = expression->compound_entry;
        assert(entry->kind == ENTITY_COMPOUND_MEMBER);
@@ -3131,7 +3028,7 @@ make_const:;
 static ir_node *function_name_to_firm(
                const funcname_expression_t *const expr)
 {
-       switch(expr->kind) {
+       switch (expr->kind) {
        case FUNCNAME_FUNCTION:
        case FUNCNAME_PRETTY_FUNCTION:
        case FUNCNAME_FUNCDNAME:
@@ -3180,7 +3077,7 @@ static ir_node *va_start_expression_to_firm(
        ir_node  *const no_mem  = new_NoMem();
        ir_node  *const arg_sel = new_d_simpleSel(dbgi, no_mem, frame, param_ent);
 
-       set_value_for_expression(expr->ap, arg_sel);
+       set_value_for_expression_addr(expr->ap, arg_sel, NULL);
 
        return NULL;
 }
@@ -3212,15 +3109,15 @@ static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr)
  */
 static ir_node *va_copy_expression_to_firm(const va_copy_expression_t *const expr)
 {
-       ir_node *const src = expression_to_firm(expr->src);
-       set_value_for_expression(expr->dst, src);
+       ir_node *const src = expression_to_value(expr->src);
+       set_value_for_expression_addr(expr->dst, src, NULL);
        return NULL;
 }
 
 static ir_node *dereference_addr(const unary_expression_t *const expression)
 {
        assert(expression->base.kind == EXPR_UNARY_DEREFERENCE);
-       return expression_to_firm(expression->value);
+       return expression_to_value(expression->value);
 }
 
 /**
@@ -3228,11 +3125,9 @@ static ir_node *dereference_addr(const unary_expression_t *const expression)
  */
 static ir_node *expression_to_addr(const expression_t *expression)
 {
-       switch(expression->kind) {
+       switch (expression->kind) {
        case EXPR_ARRAY_ACCESS:
                return array_access_addr(&expression->array_access);
-       case EXPR_CALL:
-               return call_expression_to_firm(&expression->call);
        case EXPR_COMPOUND_LITERAL:
                return compound_literal_addr(&expression->compound_literal);
        case EXPR_REFERENCE:
@@ -3250,8 +3145,8 @@ static ir_node *expression_to_addr(const expression_t *expression)
 static ir_node *builtin_constant_to_firm(
                const builtin_constant_expression_t *expression)
 {
-       ir_mode *const mode = get_ir_mode_arithmetic(expression->base.type);
-       bool     const v    = is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT;
+       ir_mode *const mode = get_ir_mode_storage(expression->base.type);
+       bool     const v    = is_constant_expression(expression->value) != EXPR_CLASS_VARIABLE;
        return create_Const_from_bool(mode, v);
 }
 
@@ -3261,7 +3156,7 @@ static ir_node *builtin_types_compatible_to_firm(
        type_t  *const left  = get_unqualified_type(skip_typeref(expression->left));
        type_t  *const right = get_unqualified_type(skip_typeref(expression->right));
        bool     const value = types_compatible(left, right);
-       ir_mode *const mode  = get_ir_mode_arithmetic(expression->base.type);
+       ir_mode *const mode  = get_ir_mode_storage(expression->base.type);
        return create_Const_from_bool(mode, value);
 }
 
@@ -3293,78 +3188,172 @@ static ir_node *label_address_to_firm(const label_address_expression_t *label)
        return new_d_SymConst(dbgi, mode_P_code, value, symconst_addr_ent);
 }
 
-/**
- * creates firm nodes for an expression. The difference between this function
- * and expression_to_firm is, that this version might produce mode_b nodes
- * instead of mode_Is.
- */
-static ir_node *_expression_to_firm(expression_t const *const expr)
+static ir_node *expression_to_value(expression_t const *const expr)
 {
 #ifndef NDEBUG
        if (!constant_folding) {
                assert(!expr->base.transformed);
                ((expression_t*)expr)->base.transformed = true;
        }
+       assert(!is_type_complex(skip_typeref(expr->base.type)));
 #endif
 
        switch (expr->kind) {
+       case EXPR_UNARY_CAST:
+               if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_BOOL)) {
+       case EXPR_BINARY_EQUAL:
+       case EXPR_BINARY_GREATER:
+       case EXPR_BINARY_GREATEREQUAL:
+       case EXPR_BINARY_ISGREATER:
+       case EXPR_BINARY_ISGREATEREQUAL:
+       case EXPR_BINARY_ISLESS:
+       case EXPR_BINARY_ISLESSEQUAL:
+       case EXPR_BINARY_ISLESSGREATER:
+       case EXPR_BINARY_ISUNORDERED:
+       case EXPR_BINARY_LESS:
+       case EXPR_BINARY_LESSEQUAL:
+       case EXPR_BINARY_LOGICAL_AND:
+       case EXPR_BINARY_LOGICAL_OR:
+       case EXPR_BINARY_NOTEQUAL:
+       case EXPR_UNARY_NOT:;
+                       jump_target true_target;
+                       jump_target false_target;
+                       init_jump_target(&true_target,  NULL);
+                       init_jump_target(&false_target, NULL);
+                       expression_to_control_flow(expr, &true_target, &false_target);
+                       return control_flow_to_1_0(expr, &true_target, &false_target);
+               } else {
+                       return create_cast(&expr->unary);
+               }
+
+       case EXPR_BINARY_ADD:
+       case EXPR_BINARY_BITWISE_AND:
+       case EXPR_BINARY_BITWISE_OR:
+       case EXPR_BINARY_BITWISE_XOR:
+       case EXPR_BINARY_DIV:
+       case EXPR_BINARY_MOD:
+       case EXPR_BINARY_MUL:
+       case EXPR_BINARY_SHIFTLEFT:
+       case EXPR_BINARY_SHIFTRIGHT:
+       case EXPR_BINARY_SUB:
+               return binop_to_firm(&expr->binary);
+
+       case EXPR_BINARY_ADD_ASSIGN:
+       case EXPR_BINARY_BITWISE_AND_ASSIGN:
+       case EXPR_BINARY_BITWISE_OR_ASSIGN:
+       case EXPR_BINARY_BITWISE_XOR_ASSIGN:
+       case EXPR_BINARY_DIV_ASSIGN:
+       case EXPR_BINARY_MOD_ASSIGN:
+       case EXPR_BINARY_MUL_ASSIGN:
+       case EXPR_BINARY_SHIFTLEFT_ASSIGN:
+       case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
+       case EXPR_BINARY_SUB_ASSIGN:
+               return binop_assign_to_firm(&expr->binary);
+
+       {
+               bool inc;
+               bool pre;
+       case EXPR_UNARY_POSTFIX_DECREMENT: inc = false; pre = false; goto incdec;
+       case EXPR_UNARY_POSTFIX_INCREMENT: inc = true;  pre = false; goto incdec;
+       case EXPR_UNARY_PREFIX_DECREMENT:  inc = false; pre = true;  goto incdec;
+       case EXPR_UNARY_PREFIX_INCREMENT:  inc = true;  pre = true;  goto incdec;
+incdec:
+               return incdec_to_firm(&expr->unary, inc, pre);
+       }
+
+       case EXPR_UNARY_IMAG: {
+               complex_value irvalue = expression_to_complex(expr->unary.value);
+               return irvalue.imag;
+       }
+       case EXPR_UNARY_REAL: {
+               complex_value irvalue = expression_to_complex(expr->unary.value);
+               return irvalue.real;
+       }
+
        case EXPR_ALIGNOF:                    return alignof_to_firm(                 &expr->typeprop);
        case EXPR_ARRAY_ACCESS:               return array_access_to_firm(            &expr->array_access);
-       case EXPR_BINARY_CASES:               return binary_expression_to_firm(       &expr->binary);
+       case EXPR_BINARY_ASSIGN:              return assign_expression_to_firm(       &expr->binary);
+       case EXPR_BINARY_COMMA:               return comma_expression_to_firm(        &expr->binary);
        case EXPR_BUILTIN_CONSTANT_P:         return builtin_constant_to_firm(        &expr->builtin_constant);
        case EXPR_BUILTIN_TYPES_COMPATIBLE_P: return builtin_types_compatible_to_firm(&expr->builtin_types_compatible);
        case EXPR_CALL:                       return call_expression_to_firm(         &expr->call);
        case EXPR_CLASSIFY_TYPE:              return classify_type_to_firm(           &expr->classify_type);
        case EXPR_COMPOUND_LITERAL:           return compound_literal_to_firm(        &expr->compound_literal);
        case EXPR_CONDITIONAL:                return conditional_to_firm(             &expr->conditional);
+       case EXPR_ENUM_CONSTANT:              return enum_constant_to_firm(           &expr->reference);
        case EXPR_FUNCNAME:                   return function_name_to_firm(           &expr->funcname);
        case EXPR_LABEL_ADDRESS:              return label_address_to_firm(           &expr->label_address);
        case EXPR_LITERAL_CASES:              return literal_to_firm(                 &expr->literal);
        case EXPR_LITERAL_CHARACTER:          return char_literal_to_firm(            &expr->string_literal);
        case EXPR_OFFSETOF:                   return offsetof_to_firm(                &expr->offsetofe);
        case EXPR_REFERENCE:                  return reference_expression_to_firm(    &expr->reference);
-       case EXPR_ENUM_CONSTANT:              return enum_constant_to_firm(           &expr->reference);
        case EXPR_SELECT:                     return select_to_firm(                  &expr->select);
        case EXPR_SIZEOF:                     return sizeof_to_firm(                  &expr->typeprop);
        case EXPR_STATEMENT:                  return statement_expression_to_firm(    &expr->statement);
-       case EXPR_UNARY_CASES:                return unary_expression_to_firm(        &expr->unary);
+       case EXPR_STRING_LITERAL:             return string_to_firm(                  &expr->base.pos, "str.%u", &expr->string_literal.value);
+       case EXPR_UNARY_ASSUME:               return handle_assume(                    expr->unary.value);
+       case EXPR_UNARY_COMPLEMENT:           return complement_to_firm(              &expr->unary);
+       case EXPR_UNARY_DEREFERENCE:          return dereference_to_firm(             &expr->unary);
+       case EXPR_UNARY_NEGATE:               return negate_to_firm(                  &expr->unary);
+       case EXPR_UNARY_PLUS:                 return expression_to_value(              expr->unary.value);
+       case EXPR_UNARY_TAKE_ADDRESS:         return expression_to_addr(               expr->unary.value);
        case EXPR_VA_ARG:                     return va_arg_expression_to_firm(       &expr->va_arge);
        case EXPR_VA_COPY:                    return va_copy_expression_to_firm(      &expr->va_copye);
        case EXPR_VA_START:                   return va_start_expression_to_firm(     &expr->va_starte);
 
-       case EXPR_STRING_LITERAL: return string_to_firm(&expr->base.pos, "str.%u", &expr->string_literal.value);
+       case EXPR_UNARY_DELETE:
+       case EXPR_UNARY_DELETE_ARRAY:
+       case EXPR_UNARY_THROW:
+               panic("expression not implemented");
 
-       case EXPR_ERROR: break;
+       case EXPR_ERROR:
+               break;
        }
        panic("invalid expression");
 }
 
+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 complex_to_control_flow(const expression_t *expression,
+                                             jump_target *true_target,
+                                             jump_target *false_target);
+
 /**
- * Check if a given expression is a GNU __builtin_expect() call.
+ * create a short-circuit expression evaluation that tries to construct
+ * efficient control flow structures for &&, || and ! expressions
  */
-static bool is_builtin_expect(const expression_t *expression)
+static ir_node *expression_to_control_flow(expression_t const *const expr, jump_target *const true_target, jump_target *const false_target)
 {
-       if (expression->kind != EXPR_CALL)
-               return false;
+       switch (expr->kind) {
+       case EXPR_UNARY_NOT:
+               expression_to_control_flow(expr->unary.value, false_target, true_target);
+               return NULL;
 
-       expression_t *function = expression->call.function;
-       if (function->kind != EXPR_REFERENCE)
-               return false;
-       reference_expression_t *ref = &function->reference;
-       if (ref->entity->kind         != ENTITY_FUNCTION ||
-           ref->entity->function.btk != BUILTIN_EXPECT)
-               return false;
+       case EXPR_BINARY_LOGICAL_AND: {
+               jump_target extra_target;
+               init_jump_target(&extra_target, NULL);
+               expression_to_control_flow(expr->binary.left, &extra_target, false_target);
+               if (enter_jump_target(&extra_target))
+                       expression_to_control_flow(expr->binary.right, true_target, false_target);
+               return NULL;
+       }
 
-       return true;
-}
+       case EXPR_BINARY_LOGICAL_OR: {
+               jump_target extra_target;
+               init_jump_target(&extra_target, NULL);
+               expression_to_control_flow(expr->binary.left, true_target, &extra_target);
+               if (enter_jump_target(&extra_target))
+                       expression_to_control_flow(expr->binary.right, true_target, false_target);
+               return NULL;
+       }
+
+       case EXPR_BINARY_COMMA:
+               evaluate_expression_discard_result(expr->binary.left);
+               return expression_to_control_flow(expr->binary.right, true_target, false_target);
 
-static bool produces_mode_b(const expression_t *expression)
-{
-       switch (expression->kind) {
        case EXPR_BINARY_EQUAL:
-       case EXPR_BINARY_NOTEQUAL:
-       case EXPR_BINARY_LESS:
-       case EXPR_BINARY_LESSEQUAL:
        case EXPR_BINARY_GREATER:
        case EXPR_BINARY_GREATEREQUAL:
        case EXPR_BINARY_ISGREATER:
@@ -3373,104 +3362,675 @@ static bool produces_mode_b(const expression_t *expression)
        case EXPR_BINARY_ISLESSEQUAL:
        case EXPR_BINARY_ISLESSGREATER:
        case EXPR_BINARY_ISUNORDERED:
-       case EXPR_UNARY_NOT:
-               return true;
-
-       case EXPR_CALL:
-               if (is_builtin_expect(expression)) {
-                       expression_t *argument = expression->call.arguments->expression;
-                       return produces_mode_b(argument);
+       case EXPR_BINARY_LESS:
+       case EXPR_BINARY_LESSEQUAL:
+       case EXPR_BINARY_NOTEQUAL: {
+               type_t     *const type     = skip_typeref(expr->binary.left->base.type);
+               ir_relation const relation = get_relation(expr->kind);
+               if (is_type_complex(type)) {
+                       complex_equality_evaluation(&expr->binary, true_target,
+                                                   false_target, relation);
+                       return NULL;
                }
-               return false;
-       case EXPR_BINARY_COMMA:
-               return produces_mode_b(expression->binary.right);
 
-       default:
-               return false;
+               dbg_info *const dbgi  = get_dbg_info(&expr->base.pos);
+               ir_mode  *const mode  = get_ir_mode_arithmetic(type);
+               ir_node  *const left  = create_conv(dbgi, expression_to_value(expr->binary.left),  mode);
+               ir_node  *const right = create_conv(dbgi, expression_to_value(expr->binary.right), mode);
+               compare_to_control_flow(expr, left, right, relation, true_target, false_target);
+               return NULL;
+       }
+
+       case EXPR_UNARY_CAST:
+               if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_BOOL)) {
+                       expression_to_control_flow(expr->unary.value, true_target, false_target);
+                       return NULL;
+               } else {
+       default:;
+                       type_t *const type = skip_typeref(expr->base.type);
+                       if (is_type_complex(type)) {
+                               complex_to_control_flow(expr, true_target, false_target);
+                               return NULL;
+                       }
+
+                       dbg_info   *const dbgi  = get_dbg_info(&expr->base.pos);
+                       ir_mode    *const mode  = get_ir_mode_arithmetic(type);
+                       ir_node    *const val   = create_conv(dbgi, expression_to_value(expr), mode);
+                       ir_node    *const left  = val;
+                       ir_node    *const right = new_Const(get_mode_null(get_irn_mode(val)));
+                       ir_relation const relation = ir_relation_unordered_less_greater;
+                       compare_to_control_flow(expr, left, right, relation, true_target, false_target);
+                       return val;
+               }
        }
 }
 
-static ir_node *expression_to_firm(const expression_t *expression)
+static complex_value complex_conv(dbg_info *dbgi, complex_value value,
+                                  ir_mode *mode)
 {
-       if (!produces_mode_b(expression)) {
-               ir_node *res = _expression_to_firm(expression);
-               assert(res == NULL || get_irn_mode(res) != mode_b);
-               return res;
-       }
+       return (complex_value) {
+               create_conv(dbgi, value.real, mode),
+               create_conv(dbgi, value.imag, mode)
+       };
+}
+
+static complex_value complex_conv_to_storage(dbg_info *const dbgi,
+       complex_value const value, type_t *const type)
+{
+       ir_mode *const mode = get_complex_mode_storage(type);
+       return complex_conv(dbgi, value, mode);
+}
+
+static void store_complex(dbg_info *dbgi, ir_node *addr, type_t *type,
+                          complex_value value)
+{
+       value = complex_conv_to_storage(dbgi, value, type);
+       ir_graph  *const irg    = current_ir_graph;
+       ir_type   *const irtype = get_ir_type(type);
+       ir_node   *const mem    = get_store();
+       ir_node   *const nomem  = get_irg_no_mem(irg);
+       ir_mode   *const mode   = get_complex_mode_storage(type);
+       ir_node   *const real   = create_conv(dbgi, value.real, mode);
+       ir_node   *const imag   = create_conv(dbgi, value.imag, mode);
+       ir_node   *const storer = new_d_Store(dbgi, mem, addr, real, cons_floats);
+       ir_node   *const memr   = new_Proj(storer, mode_M, pn_Store_M);
+       ir_mode   *const muint  = atomic_modes[ATOMIC_TYPE_UINT];
+       ir_node   *const one    = new_Const(get_mode_one(muint));
+       ir_node   *const in[1]  = { one };
+       ir_entity *const arrent = get_array_element_entity(irtype);
+       ir_node   *const addri  = new_d_Sel(dbgi, nomem, addr, 1, in, arrent);
+       ir_node   *const storei = new_d_Store(dbgi, memr, addri, imag, cons_floats);
+       ir_node   *const memi   = new_Proj(storei, mode_M, pn_Store_M);
+       set_store(memi);
+}
+
+static ir_node *complex_to_memory(dbg_info *dbgi, type_t *type,
+                                  complex_value value)
+{
+       ir_graph  *const irg         = current_ir_graph;
+       ir_type   *const frame_type  = get_irg_frame_type(irg);
+       ident     *const id          = id_unique("cmplex_tmp.%u");
+       ir_type   *const irtype      = get_ir_type(type);
+       ir_entity *const tmp_storage = new_entity(frame_type, id, irtype);
+       ir_node   *const frame       = get_irg_frame(irg);
+       ir_node   *const nomem       = get_irg_no_mem(irg);
+       ir_node   *const addr        = new_simpleSel(nomem, frame, tmp_storage);
+       set_entity_compiler_generated(tmp_storage, 1);
+       store_complex(dbgi, addr, type, value);
+       return addr;
+}
+
+static complex_value read_localvar_complex(dbg_info *dbgi, entity_t *const entity)
+{
+       assert(entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE
+           || entity->declaration.kind == DECLARATION_KIND_PARAMETER);
+       type_t  *const type = skip_typeref(entity->declaration.type);
+       ir_mode *const mode = get_complex_mode_storage(type);
+       ir_node *const real = get_value(entity->variable.v.value_number, mode);
+       ir_node *const imag = get_value(entity->variable.v.value_number+1, mode);
+       ir_mode *const mode_arithmetic = get_complex_mode_arithmetic(type);
+       return (complex_value) {
+               create_conv(dbgi, real, mode_arithmetic),
+               create_conv(dbgi, imag, mode_arithmetic)
+       };
+}
+
+static complex_value complex_deref_address(dbg_info *const dbgi,
+                                           type_t *type, ir_node *const addr,
+                                           ir_cons_flags flags)
+{
+       type = skip_typeref(type);
+       assert(is_type_complex(type));
+
+       if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE)
+               flags |= cons_volatile;
+       ir_mode   *const mode      = get_complex_mode_storage(type);
+       ir_node   *const memory    = get_store();
+       ir_node   *const load      = new_d_Load(dbgi, memory, addr, mode, flags);
+       ir_node   *const load_mem  = new_Proj(load, mode_M, pn_Load_M);
+       ir_node   *const load_res  = new_Proj(load, mode,   pn_Load_res);
+
+       ir_type   *const irtype    = get_ir_type(type);
+       ir_mode   *const mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
+       ir_node   *const in[1]     = { new_Const(get_mode_one(mode_uint)) };
+       ir_entity *const entity    = get_array_element_entity(irtype);
+       ir_node   *const nomem     = get_irg_no_mem(current_ir_graph);
+       ir_node   *const addr2     = new_Sel(nomem, addr, 1, in, entity);
+       ir_node   *const load2     = new_d_Load(dbgi, load_mem, addr2, mode, flags);
+       ir_node   *const load_mem2 = new_Proj(load2, mode_M, pn_Load_M);
+       ir_node   *const load_res2 = new_Proj(load2, mode, pn_Load_res);
+       set_store(load_mem2);
+
+       return (complex_value) { load_res, load_res2 };
+}
 
-       if (is_constant_expression(expression) == EXPR_CLASS_CONSTANT) {
-               return new_Const(fold_constant_to_tarval(expression));
+static complex_value complex_reference_to_firm(const reference_expression_t *ref)
+{
+       dbg_info *const dbgi   = get_dbg_info(&ref->base.pos);
+       entity_t *const entity = ref->entity;
+       assert(is_declaration(entity));
+
+       switch ((declaration_kind_t)entity->declaration.kind) {
+       case DECLARATION_KIND_LOCAL_VARIABLE:
+       case DECLARATION_KIND_PARAMETER:
+               return read_localvar_complex(dbgi, entity);
+       default: {
+               ir_node *const addr = reference_addr(ref);
+               return complex_deref_address(dbgi, entity->declaration.type, addr, cons_none);
        }
+       }
+}
 
-       /* we have to produce a 0/1 from the mode_b expression */
+static complex_value complex_select_to_firm(const select_expression_t *select)
+{
+       dbg_info *const dbgi = get_dbg_info(&select->base.pos);
+       ir_node  *const addr = select_addr(select);
+       type_t   *const type = skip_typeref(select->base.type);
+       return complex_deref_address(dbgi, type, addr, cons_none);
+}
+
+static complex_value complex_array_access_to_firm(
+       const array_access_expression_t *expression)
+{
        dbg_info *dbgi = get_dbg_info(&expression->base.pos);
-       ir_mode  *mode = get_ir_mode_arithmetic(expression->base.type);
-       return produce_condition_result(expression, mode, dbgi);
+       ir_node  *addr = array_access_addr(expression);
+       type_t   *type = skip_typeref(expression->base.type);
+       assert(is_type_complex(type));
+       return complex_deref_address(dbgi, type, addr, cons_none);
 }
 
-/**
- * create a short-circuit expression evaluation that tries to construct
- * efficient control flow structures for &&, || and ! expressions
- */
-static ir_node *create_condition_evaluation(expression_t const *const expression, jump_target *const true_target, jump_target *const false_target)
+static complex_value get_complex_from_lvalue(const expression_t *expression,
+                                             ir_node *addr)
 {
-       switch(expression->kind) {
-       case EXPR_UNARY_NOT: {
-               const unary_expression_t *unary_expression = &expression->unary;
-               create_condition_evaluation(unary_expression->value, false_target, true_target);
-               return NULL;
-       }
-       case EXPR_BINARY_LOGICAL_AND: {
-               jump_target extra_target;
-               init_jump_target(&extra_target, NULL);
-               create_condition_evaluation(expression->binary.left, &extra_target, false_target);
-               if (enter_jump_target(&extra_target))
-                       create_condition_evaluation(expression->binary.right, true_target, false_target);
-               return NULL;
+       dbg_info *dbgi = get_dbg_info(&expression->base.pos);
+
+       if (expression->kind == EXPR_REFERENCE) {
+               const reference_expression_t *ref = &expression->reference;
+
+               entity_t *entity = ref->entity;
+               assert(entity->kind == ENTITY_VARIABLE
+                   || entity->kind == ENTITY_PARAMETER);
+               assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+               if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE ||
+                   entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
+                   return read_localvar_complex(dbgi, entity);
+               }
        }
-       case EXPR_BINARY_LOGICAL_OR: {
-               jump_target extra_target;
-               init_jump_target(&extra_target, NULL);
-               create_condition_evaluation(expression->binary.left, true_target, &extra_target);
-               if (enter_jump_target(&extra_target))
-                       create_condition_evaluation(expression->binary.right, true_target, false_target);
-               return NULL;
+
+       assert(addr != NULL);
+       return complex_deref_address(dbgi, expression->base.type, addr, cons_none);
+}
+
+static complex_value complex_cast_to_firm(const unary_expression_t *expression)
+{
+       const expression_t *const value     = expression->value;
+       dbg_info           *const dbgi      = get_dbg_info(&expression->base.pos);
+       type_t             *const from_type = skip_typeref(value->base.type);
+       type_t             *const to_type   = skip_typeref(expression->base.type);
+       ir_mode            *const mode      = get_complex_mode_storage(to_type);
+
+       if (is_type_complex(from_type)) {
+               complex_value cvalue = expression_to_complex(value);
+               return complex_conv(dbgi, cvalue, mode);
+       } else {
+               ir_node *const value_node = expression_to_value(value);
+               ir_node *const zero       = new_Const(get_mode_null(mode));
+               ir_node *const casted     = create_conv(dbgi, value_node, mode);
+               return (complex_value) { casted, zero };
        }
-       default:
-               break;
+}
+
+static complex_value complex_literal_to_firm(const literal_expression_t *literal)
+{
+       type_t  *type     = skip_typeref(literal->base.type);
+       ir_mode *mode     = get_complex_mode_storage(type);
+       ir_node *litvalue = literal_to_firm_(literal, mode);
+       ir_node *zero     = new_Const(get_mode_null(mode));
+       return (complex_value) { zero, litvalue };
+}
+
+typedef complex_value (*new_complex_binop)(dbg_info *dbgi, complex_value left,
+                                           complex_value right, ir_mode *mode);
+
+static complex_value new_complex_add(dbg_info *dbgi, complex_value left,
+                                     complex_value right, ir_mode *mode)
+{
+       return (complex_value) {
+               new_d_Add(dbgi, left.real, right.real, mode),
+               new_d_Add(dbgi, left.imag, right.imag, mode)
+       };
+}
+
+static complex_value new_complex_sub(dbg_info *dbgi, complex_value left,
+                                     complex_value right, ir_mode *mode)
+{
+       return (complex_value) {
+               new_d_Sub(dbgi, left.real, right.real, mode),
+               new_d_Sub(dbgi, left.imag, right.imag, mode)
+       };
+}
+
+static complex_value new_complex_mul(dbg_info *dbgi, complex_value left,
+                                     complex_value right, ir_mode *mode)
+{
+       ir_node *const op1 = new_d_Mul(dbgi, left.real, right.real, mode);
+       ir_node *const op2 = new_d_Mul(dbgi, left.imag, right.imag, mode);
+       ir_node *const op3 = new_d_Mul(dbgi, left.real, right.imag, mode);
+       ir_node *const op4 = new_d_Mul(dbgi, left.imag, right.real, mode);
+       return (complex_value) {
+               new_d_Sub(dbgi, op1, op2, mode),
+               new_d_Add(dbgi, op3, op4, mode)
+       };
+}
+
+static complex_value new_complex_div(dbg_info *dbgi, complex_value left,
+                                     complex_value right, ir_mode *mode)
+{
+       ir_node *const op1 = new_d_Mul(dbgi, left.real, right.real, mode);
+       ir_node *const op2 = new_d_Mul(dbgi, left.imag, right.imag, mode);
+       ir_node *const op3 = new_d_Mul(dbgi, left.imag, right.real, mode);
+       ir_node *const op4 = new_d_Mul(dbgi, left.real, right.imag, mode);
+       ir_node *const op5 = new_d_Mul(dbgi, right.real, right.real, mode);
+       ir_node *const op6 = new_d_Mul(dbgi, right.imag, right.imag, mode);
+       ir_node *const real_dividend = new_d_Add(dbgi, op1, op2, mode);
+       ir_node *const real_divisor  = new_d_Add(dbgi, op5, op6, mode);
+       ir_node *const imag_dividend = new_d_Sub(dbgi, op3, op4, mode);
+       ir_node *const imag_divisor  = new_d_Add(dbgi, op5, op6, mode);
+       return (complex_value) {
+               create_div(dbgi, real_dividend, real_divisor, mode),
+               create_div(dbgi, imag_dividend, imag_divisor, mode)
+       };
+}
+
+typedef complex_value (*new_complex_unop)(dbg_info *dbgi, complex_value value,
+                                          ir_mode *mode);
+
+static complex_value new_complex_increment(dbg_info *dbgi, complex_value value,
+                                           ir_mode *mode)
+{
+       ir_node *one = new_Const(get_mode_one(mode));
+       return (complex_value) {
+               new_d_Add(dbgi, value.real, one, mode),
+               value.imag
+       };
+}
+
+static complex_value new_complex_decrement(dbg_info *dbgi, complex_value value,
+                                           ir_mode *mode)
+{
+       ir_node *one = new_Const(get_mode_one(mode));
+       return (complex_value) {
+               new_d_Sub(dbgi, value.real, one, mode),
+               value.imag
+       };
+}
+
+static void set_complex_value_for_expression(dbg_info *dbgi,
+                                                                                        const expression_t *expression,
+                                             complex_value value,
+                                             ir_node *addr)
+{
+       type_t  *const type = skip_typeref(expression->base.type);
+       ir_mode *const mode = get_complex_mode_storage(type);
+       ir_node *const real = create_conv(dbgi, value.real, mode);
+       ir_node *const imag = create_conv(dbgi, value.imag, mode);
+
+       if (expression->kind == EXPR_REFERENCE) {
+               const reference_expression_t *ref = &expression->reference;
+
+               entity_t *entity = ref->entity;
+               assert(is_declaration(entity));
+               assert(entity->declaration.kind != DECLARATION_KIND_UNKNOWN);
+               if (entity->declaration.kind == DECLARATION_KIND_LOCAL_VARIABLE ||
+                   entity->declaration.kind == DECLARATION_KIND_PARAMETER) {
+                       set_value(entity->variable.v.value_number, real);
+                       set_value(entity->variable.v.value_number+1, imag);
+                       return;
+               }
        }
 
-       ir_node *cond_expr = _expression_to_firm(expression);
-       if (is_Const(cond_expr)) {
-               if (tarval_is_null(get_Const_tarval(cond_expr))) {
+       if (addr == NULL)
+               addr = expression_to_addr(expression);
+       assert(addr != NULL);
+       store_complex(dbgi, addr, type, value);
+}
+
+static complex_value create_complex_assign_unop(const unary_expression_t *unop,
+                                                new_complex_unop constructor,
+                                                bool return_old)
+{
+       dbg_info *const     dbgi       = get_dbg_info(&unop->base.pos);
+       const expression_t *value_expr = unop->value;
+       ir_node            *addr       = expression_to_addr(value_expr);
+       complex_value       value      = get_complex_from_lvalue(value_expr, addr);
+       type_t             *type       = skip_typeref(unop->base.type);
+       ir_mode            *mode       = get_complex_mode_arithmetic(type);
+       value = complex_conv(dbgi, value, mode);
+       complex_value       new_value  = constructor(dbgi, value, mode);
+       set_complex_value_for_expression(dbgi, value_expr, new_value, addr);
+       return return_old ? value : new_value;
+}
+
+static complex_value complex_negate_to_firm(const unary_expression_t *expr)
+{
+       complex_value cvalue = expression_to_complex(expr->value);
+       dbg_info     *dbgi   = get_dbg_info(&expr->base.pos);
+       ir_mode      *mode   = get_complex_mode_arithmetic(expr->base.type);
+       cvalue = complex_conv(dbgi, cvalue, mode);
+       return (complex_value) {
+               new_d_Minus(dbgi, cvalue.real, mode),
+               new_d_Minus(dbgi, cvalue.imag, mode)
+       };
+}
+
+static complex_value complex_complement_to_firm(const unary_expression_t *expr)
+{
+       complex_value cvalue = expression_to_complex(expr->value);
+       dbg_info     *dbgi   = get_dbg_info(&expr->base.pos);
+       ir_mode      *mode   = get_complex_mode_arithmetic(expr->base.type);
+       cvalue = complex_conv(dbgi, cvalue, mode);
+       return (complex_value) {
+               cvalue.real,
+               new_d_Minus(dbgi, cvalue.imag, mode)
+       };
+}
+
+static complex_value create_complex_binop(const binary_expression_t *binexpr,
+                                          new_complex_binop constructor)
+{
+       dbg_info     *dbgi  = get_dbg_info(&binexpr->base.pos);
+       ir_mode      *mode  = get_complex_mode_arithmetic(binexpr->base.type);
+       complex_value left  = expression_to_complex(binexpr->left);
+       complex_value right = expression_to_complex(binexpr->right);
+       left  = complex_conv(dbgi, left, mode);
+       right = complex_conv(dbgi, right, mode);
+       return constructor(dbgi, left, right, mode);
+}
+
+static complex_value create_complex_assign_binop(const binary_expression_t *binexpr,
+                                                 new_complex_binop constructor)
+{
+       dbg_info      *dbgi   = get_dbg_info(&binexpr->base.pos);
+       expression_t  *lefte  = binexpr->left;
+       expression_t  *righte = binexpr->right;
+       ir_mode       *mode   = get_complex_mode_arithmetic(righte->base.type);
+       ir_node       *addr   = expression_to_addr(lefte);
+       complex_value  left   = get_complex_from_lvalue(lefte, addr);
+       complex_value  right  = expression_to_complex(righte);
+       left  = complex_conv(dbgi, left, mode);
+       right = complex_conv(dbgi, right, mode);
+       complex_value  new_value = constructor(dbgi, left, right, mode);
+       type_t        *res_type  = skip_typeref(binexpr->base.type);
+       set_complex_value_for_expression(dbgi, lefte, new_value, addr);
+       return complex_conv_to_storage(dbgi, new_value, res_type);
+}
+
+static complex_value complex_call_to_firm(const call_expression_t *call)
+{
+       ir_node         *result        = call_expression_to_firm(call);
+       expression_t    *function      = call->function;
+       type_t          *type          = skip_typeref(function->base.type);
+       assert(is_type_pointer(type));
+       pointer_type_t  *pointer_type  = &type->pointer;
+       type_t          *points_to     = skip_typeref(pointer_type->points_to);
+       assert(is_type_function(points_to));
+       function_type_t *function_type = &points_to->function;
+       type_t          *return_type   = skip_typeref(function_type->return_type);
+       assert(is_type_complex(return_type));
+       dbg_info        *dbgi          = get_dbg_info(&call->base.pos);
+       return complex_deref_address(dbgi, return_type, result, cons_floats);
+}
+
+static void complex_equality_evaluation(const binary_expression_t *binexpr,
+       jump_target *const true_target, jump_target *const false_target,
+       ir_relation relation)
+{
+       jump_target extra_target;
+       init_jump_target(&extra_target, NULL);
+
+       complex_value left  = expression_to_complex(binexpr->left);
+       complex_value right = expression_to_complex(binexpr->right);
+       dbg_info     *dbgi  = get_dbg_info(&binexpr->base.pos);
+       ir_mode      *mode  = get_complex_mode_arithmetic(binexpr->left->base.type);
+       left  = complex_conv(dbgi, left, mode);
+       right = complex_conv(dbgi, right, mode);
+
+       ir_node  *cmp_real   = new_d_Cmp(dbgi, left.real, right.real, relation);
+       ir_node  *cond       = new_d_Cond(dbgi, cmp_real);
+       ir_node  *true_proj  = new_Proj(cond, mode_X, pn_Cond_true);
+       ir_node  *false_proj = new_Proj(cond, mode_X, pn_Cond_false);
+       add_pred_to_jump_target(&extra_target, true_proj);
+       add_pred_to_jump_target(false_target, false_proj);
+       if (!enter_jump_target(&extra_target))
+               return;
+
+       ir_node *cmp_imag     = new_d_Cmp(dbgi, left.imag, right.imag, relation);
+       ir_node *condi        = new_d_Cond(dbgi, cmp_imag);
+       ir_node *true_proj_i  = new_Proj(condi, mode_X, pn_Cond_true);
+       ir_node *false_proj_i = new_Proj(condi, mode_X, pn_Cond_false);
+       add_pred_to_jump_target(true_target, true_proj_i);
+       add_pred_to_jump_target(false_target, false_proj_i);
+       set_unreachable_now();
+}
+
+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);
+       value = complex_conv(dbgi, value, mode);
+       ir_node      *const zero       = new_Const(get_mode_null(mode));
+       ir_node      *const cmp_real   =
+               new_d_Cmp(dbgi, value.real, zero, ir_relation_unordered_less_greater);
+       ir_node      *const cond_real  = new_d_Cond(dbgi, cmp_real);
+       ir_node      *const true_real  = new_Proj(cond_real, mode_X, pn_Cond_true);
+       ir_node      *const false_real = new_Proj(cond_real, mode_X, pn_Cond_false);
+       add_pred_to_jump_target(true_target, true_real);
+       add_pred_to_jump_target(&extra_target, false_real);
+       if (!enter_jump_target(&extra_target))
+               return value;
+
+       ir_node      *const cmp_imag   =
+               new_d_Cmp(dbgi, value.imag, zero, ir_relation_unordered_less_greater);
+       ir_node      *const cond_imag  = new_d_Cond(dbgi, cmp_imag);
+       ir_node      *const true_imag  = new_Proj(cond_imag, mode_X, pn_Cond_true);
+       ir_node      *const false_imag = new_Proj(cond_imag, mode_X, pn_Cond_false);
+       add_pred_to_jump_target(true_target, true_imag);
+       add_pred_to_jump_target(false_target, false_imag);
+       set_unreachable_now();
+
+       return value;
+}
+
+static complex_value complex_conditional_to_firm(
+       const conditional_expression_t *const expression)
+{
+       jump_target true_target;
+       jump_target false_target;
+       init_jump_target(&true_target,  NULL);
+       init_jump_target(&false_target, NULL);
+       complex_value cond_val;
+       memset(&cond_val, 0, sizeof(cond_val));
+       if (expression->true_expression == NULL) {
+               assert(is_type_complex(skip_typeref(expression->condition->base.type)));
+               cond_val = complex_to_control_flow(expression->condition,
+                                                  &true_target, &false_target);
        } else {
-               dbg_info *dbgi       = get_dbg_info(&expression->base.pos);
-               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);
+               expression_to_control_flow(expression->condition, &true_target, &false_target);
+       }
 
-               /* set branch prediction info based on __builtin_expect */
-               if (is_builtin_expect(expression) && is_Cond(cond)) {
-                       call_argument_t *argument = expression->call.arguments->next;
-                       if (is_constant_expression(argument->expression) == EXPR_CLASS_CONSTANT) {
-                               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);
-                       }
+       complex_value  val;
+       memset(&val, 0, sizeof(val));
+       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) {
+                       val = expression_to_complex(expression->true_expression);
+               } else {
+                       assert(cond_val.real != NULL);
+                       val = cond_val;
                }
+               val = complex_conv(dbgi, val, mode);
+               jump_to_target(&exit_target);
+       }
 
-               add_pred_to_jump_target(true_target,  true_proj);
-               add_pred_to_jump_target(false_target, false_proj);
+       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 };
+                       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);
+               } else {
+                       val = false_val;
+               }
        }
-       set_unreachable_now();
-       return cond_expr;
+
+       if (!enter_jump_target(&exit_target)) {
+               set_cur_block(new_Block(0, NULL));
+               assert(!is_type_void(type));
+               val.real = val.imag = new_Bad(mode);
+       }
+       return val;
+}
+
+static void create_local_declarations(entity_t*);
+
+static complex_value compound_statement_to_firm_complex(
+       const compound_statement_t *compound)
+{
+       create_local_declarations(compound->scope.entities);
+
+       complex_value result    = { NULL, NULL };
+       statement_t  *statement = compound->statements;
+       statement_t  *next;
+       for ( ; statement != NULL; statement = next) {
+               next = statement->base.next;
+               /* last statement is the return value */
+               if (next == NULL) {
+                       /* it must be an expression, otherwise we wouldn't be in the
+                        * complex variant of compound_statement_to_firm */
+                       if (statement->kind != STATEMENT_EXPRESSION)
+                               panic("last member of complex statement expression not an expression statement");
+                       expression_t *expression = statement->expression.expression;
+                       assert(is_type_complex(skip_typeref(expression->base.type)));
+                       result = expression_to_complex(expression);
+               } else {
+                       statement_to_firm(statement);
+               }
+       }
+
+       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)
+{
+       const statement_t *const statement = expr->statement;
+       assert(statement->kind == STATEMENT_COMPOUND);
+
+       return compound_statement_to_firm_complex(&statement->compound);
 }
 
+static complex_value expression_to_complex(const expression_t *expression)
+{
+       switch (expression->kind) {
+       case EXPR_REFERENCE:
+               return complex_reference_to_firm(&expression->reference);
+       case EXPR_SELECT:
+               return complex_select_to_firm(&expression->select);
+       case EXPR_ARRAY_ACCESS:
+               return complex_array_access_to_firm(&expression->array_access);
+       case EXPR_UNARY_CAST:
+               return complex_cast_to_firm(&expression->unary);
+       case EXPR_BINARY_COMMA:
+               evaluate_expression_discard_result(expression->binary.left);
+               return expression_to_complex(expression->binary.right);
+       case EXPR_BINARY_ADD:
+               return create_complex_binop(&expression->binary, new_complex_add);
+       case EXPR_BINARY_ADD_ASSIGN:
+               return create_complex_assign_binop(&expression->binary, new_complex_add);
+       case EXPR_BINARY_SUB:
+               return create_complex_binop(&expression->binary, new_complex_sub);
+       case EXPR_BINARY_SUB_ASSIGN:
+               return create_complex_assign_binop(&expression->binary, new_complex_sub);
+       case EXPR_BINARY_MUL:
+               return create_complex_binop(&expression->binary, new_complex_mul);
+       case EXPR_BINARY_MUL_ASSIGN:
+               return create_complex_assign_binop(&expression->binary, new_complex_mul);
+       case EXPR_BINARY_DIV:
+               return create_complex_binop(&expression->binary, new_complex_div);
+       case EXPR_BINARY_DIV_ASSIGN:
+               return create_complex_assign_binop(&expression->binary, new_complex_div);
+       case EXPR_UNARY_PLUS:
+               return expression_to_complex(expression->unary.value);
+       case EXPR_UNARY_PREFIX_INCREMENT:
+               return create_complex_assign_unop(&expression->unary,
+                                                 new_complex_increment, false);
+       case EXPR_UNARY_PREFIX_DECREMENT:
+               return create_complex_assign_unop(&expression->unary,
+                                                 new_complex_decrement, false);
+       case EXPR_UNARY_POSTFIX_INCREMENT:
+               return create_complex_assign_unop(&expression->unary,
+                                                 new_complex_increment, true);
+       case EXPR_UNARY_POSTFIX_DECREMENT:
+               return create_complex_assign_unop(&expression->unary,
+                                                 new_complex_decrement, true);
+       case EXPR_UNARY_NEGATE:
+               return complex_negate_to_firm(&expression->unary);
+       case EXPR_UNARY_COMPLEMENT:
+               return complex_complement_to_firm(&expression->unary);
+       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:
+               return complex_call_to_firm(&expression->call);
+       case EXPR_CONDITIONAL:
+               return complex_conditional_to_firm(&expression->conditional);
+       case EXPR_STATEMENT:
+               return complex_statement_expression_to_firm(&expression->statement);
+       default:
+               panic("unexpected complex expression");
+       }
+}
+
+
+
 static void create_variable_entity(entity_t *variable,
                                    declaration_kind_t declaration_kind,
                                    ir_type *parent_type)
@@ -3766,13 +4326,21 @@ static ir_initializer_t *create_ir_initializer_value(
                        return create_ir_initializer(expr->compound_literal.initializer,
                                                     type);
                }
+       } else if (is_type_complex(type)) {
+               complex_value     const value     = expression_to_complex(expr);
+               ir_mode          *const mode      = get_complex_mode_storage(type);
+               ir_node          *const real      = create_conv(NULL, value.real, mode);
+               ir_node          *const imag      = create_conv(NULL, value.imag, mode);
+               ir_initializer_t *const res       = create_initializer_compound(2);
+               ir_initializer_t *const init_real = create_initializer_const(real);
+               ir_initializer_t *const init_imag = create_initializer_const(imag);
+               set_initializer_compound_value(res, 0, init_real);
+               set_initializer_compound_value(res, 1, init_imag);
+               return res;
        }
 
-       ir_node *value = expression_to_firm(expr);
-       if (!is_type_compound(type)) {
-               ir_mode *mode = get_ir_mode_storage(type);
-               value         = create_conv(NULL, value, mode);
-       }
+       ir_node *value = expression_to_value(expr);
+       value = conv_to_storage_type(NULL, value, type);
        return create_initializer_const(value);
 }
 
@@ -3808,7 +4376,7 @@ static ir_initializer_t *create_ir_initializer_list(
                        const expression_t *expr      = sub_initializer->value.value;
                        const type_t       *expr_type = skip_typeref(expr->base.type);
                        /* we might have to descend into types until the types match */
-                       while(true) {
+                       while (true) {
                                type_t *orig_top_type = path.top_type;
                                type_t *top_type      = skip_typeref(orig_top_type);
 
@@ -3890,7 +4458,7 @@ static ir_initializer_t *create_ir_initializer_string(initializer_t const *const
 static ir_initializer_t *create_ir_initializer(
                const initializer_t *initializer, type_t *type)
 {
-       switch(initializer->kind) {
+       switch (initializer->kind) {
                case INITIALIZER_STRING:
                        return create_ir_initializer_string(initializer, type);
 
@@ -3965,7 +4533,7 @@ static void create_dynamic_null_initializer(ir_entity *entity, dbg_info *dbgi,
 static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
                ir_entity *entity, ir_type *type, dbg_info *dbgi, ir_node *base_addr)
 {
-       switch(get_initializer_kind(initializer)) {
+       switch (get_initializer_kind(initializer)) {
        case IR_INITIALIZER_NULL:
                create_dynamic_null_initializer(entity, dbgi, base_addr);
                return;
@@ -4080,7 +4648,7 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi,
        if (initializer->kind == INITIALIZER_VALUE) {
                initializer_value_t *initializer_value = &initializer->value;
 
-               ir_node *value = expression_to_firm(initializer_value->value);
+               ir_node *value = expression_to_value(initializer_value->value);
                type = skip_typeref(type);
                assign_value(dbgi, addr, type, value);
                return;
@@ -4137,21 +4705,40 @@ static void create_variable_initializer(entity_t *entity)
                expression_t *      value     = initializer->value.value;
                type_t       *const init_type = skip_typeref(value->base.type);
 
-               if (!is_type_scalar(init_type)) {
-                       /* skip convs */
-                       while (value->kind == EXPR_UNARY_CAST)
-                               value = value->unary.value;
-
+               if (is_type_complex(init_type)) {
+                       complex_value nodes = expression_to_complex(value);
+                       dbg_info     *dbgi  = get_dbg_info(&entity->base.pos);
+                       ir_mode      *mode  = get_complex_mode_storage(init_type);
+                       ir_node      *real  = create_conv(dbgi, nodes.real, mode);
+                       ir_node      *imag  = create_conv(dbgi, nodes.imag, mode);
+                       if (declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
+                               set_value(entity->variable.v.value_number, real);
+                               set_value(entity->variable.v.value_number+1, imag);
+                       } else {
+                               assert(declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);
+                               ir_entity *irentity = entity->variable.v.entity;
+                               if (tq & TYPE_QUALIFIER_CONST
+                                               && get_entity_owner(irentity) != get_tls_type()) {
+                                       add_entity_linkage(irentity, IR_LINKAGE_CONSTANT);
+                               }
+                               ir_initializer_t *complex_init = create_initializer_compound(2);
+                               ir_initializer_t *reali = create_initializer_const(real);
+                               set_initializer_compound_value(complex_init, 0, reali);
+                               ir_initializer_t *imagi = create_initializer_const(imag);
+                               set_initializer_compound_value(complex_init, 1, imagi);
+                               set_entity_initializer(irentity, complex_init);
+                       }
+                       return;
+               } else if (!is_type_scalar(init_type)) {
                        if (value->kind != EXPR_COMPOUND_LITERAL)
                                panic("expected non-scalar initializer to be a compound literal");
                        initializer = value->compound_literal.initializer;
                        goto have_initializer;
                }
 
-               ir_node  *      node = expression_to_firm(value);
+               ir_node  *      node = expression_to_value(value);
                dbg_info *const dbgi = get_dbg_info(&entity->base.pos);
-               ir_mode  *const mode = get_ir_mode_storage(init_type);
-               node = create_conv(dbgi, node, mode);
+               node = conv_to_storage_type(dbgi, node, init_type);
 
                if (declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) {
                        set_value(entity->variable.v.value_number, node);
@@ -4223,7 +4810,8 @@ static bool var_needs_entity(variable_t const *const var)
        if (var->address_taken)
                return true;
        type_t *const type = skip_typeref(var->base.type);
-       return !is_type_scalar(type) || type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
+       return (!is_type_scalar(type) && !is_type_complex(type))
+            || type->base.qualifiers & TYPE_QUALIFIER_VOLATILE;
 }
 
 /**
@@ -4239,6 +4827,8 @@ static void create_local_variable(entity_t *entity)
                entity->variable.v.value_number = next_value_number_function;
                set_irg_loc_description(current_ir_graph, next_value_number_function, entity);
                ++next_value_number_function;
+               if (is_type_complex(skip_typeref(entity->declaration.type)))
+                       ++next_value_number_function;
                return;
        }
 
@@ -4290,8 +4880,6 @@ static void create_local_static_variable(entity_t *entity)
        POP_IRG();
 }
 
-
-
 static ir_node *return_statement_to_firm(return_statement_t *statement)
 {
        if (!currently_reachable())
@@ -4299,22 +4887,35 @@ static ir_node *return_statement_to_firm(return_statement_t *statement)
 
        dbg_info *const dbgi = get_dbg_info(&statement->base.pos);
        type_t   *const type = skip_typeref(current_function_entity->declaration.type->function.return_type);
-       ir_node  *      res  = statement->value ? expression_to_firm(statement->value) : NULL;
 
+       ir_node *in[1];
        int in_len;
-       if (!is_type_void(type)) {
-               ir_mode *const mode = get_ir_mode_storage(type);
-               if (res) {
-                       res = create_conv(dbgi, res, mode);
+       if (is_type_void(type)) {
+               /* just create the side effects, don't return anything */
+               if (statement->value)
+                       evaluate_expression_discard_result(statement->value);
+               in[0]  = NULL;
+               in_len = 0;
+       } else if (is_type_complex(type)) {
+               if (statement->value) {
+                       complex_value value = expression_to_complex(statement->value);
+                       in[0] = complex_to_memory(dbgi, type, value);
                } else {
-                       res = new_Unknown(mode);
+                       in[0] = new_Unknown(mode_P_data);
                }
                in_len = 1;
        } else {
-               in_len = 0;
+               ir_mode *const mode = get_ir_mode_storage(type);
+               if (statement->value) {
+                       ir_node *value = expression_to_value(statement->value);
+                       value = conv_to_storage_type(dbgi, value, type);
+                       in[0] = create_conv(dbgi, value, mode);
+               } else {
+                       in[0] = new_Unknown(mode);
+               }
+               in_len = 1;
        }
 
-       ir_node *const in[1] = { res };
        ir_node *const store = get_store();
        ir_node *const ret   = new_d_Return(dbgi, store, in_len, in);
 
@@ -4330,11 +4931,16 @@ static ir_node *expression_statement_to_firm(expression_statement_t *statement)
        if (!currently_reachable())
                return NULL;
 
-       return expression_to_firm(statement->expression);
+       expression_t *expression = statement->expression;
+       type_t       *type       = skip_typeref(expression->base.type);
+       if (is_type_complex(type)) {
+               expression_to_complex(expression);
+               return NULL;
+       } else {
+               return expression_to_value(statement->expression);
+       }
 }
 
-static void create_local_declarations(entity_t*);
-
 static ir_node *compound_statement_to_firm(compound_statement_t *compound)
 {
        create_local_declarations(compound->scope.entities);
@@ -4518,7 +5124,7 @@ static ir_node *if_statement_to_firm(if_statement_t *statement)
        init_jump_target(&true_target,  NULL);
        init_jump_target(&false_target, NULL);
        if (currently_reachable())
-               create_condition_evaluation(statement->condition, &true_target, &false_target);
+               expression_to_control_flow(statement->condition, &true_target, &false_target);
 
        jump_target exit_target;
        init_jump_target(&exit_target, NULL);
@@ -4547,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);
@@ -4562,7 +5168,7 @@ static ir_node *do_while_statement_to_firm(do_while_statement_t *statement)
                statement_to_firm(statement->body);
                jump_to_target(&continue_target);
                if (enter_jump_target(&continue_target))
-                       create_condition_evaluation(statement->condition, &body_target, &break_target);
+                       expression_to_control_flow(statement->condition, &body_target, &break_target);
                enter_jump_target(&body_target);
        }
        enter_jump_target(&break_target);
@@ -4586,7 +5192,7 @@ static ir_node *for_statement_to_firm(for_statement_t *statement)
                }
 
                if (statement->initialisation != NULL) {
-                       expression_to_firm(statement->initialisation);
+                       expression_to_value(statement->initialisation);
                }
        }
 
@@ -4603,10 +5209,10 @@ 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);
-               create_condition_evaluation(cond, &body_target, &break_target);
+               expression_to_control_flow(cond, &body_target, &break_target);
                enter_jump_target(&body_target);
        }
 
@@ -4616,7 +5222,7 @@ static ir_node *for_statement_to_firm(for_statement_t *statement)
 
        /* Create the step code. */
        if (step && enter_jump_target(&continue_target)) {
-               expression_to_firm(step);
+               expression_to_value(step);
                jump_to_target(&header_target);
        }
 
@@ -4667,7 +5273,7 @@ static ir_node *switch_statement_to_firm(switch_statement_t *statement)
        ir_node  *switch_node = NULL;
 
        if (currently_reachable()) {
-               ir_node *expression = expression_to_firm(statement->expression);
+               ir_node *expression = expression_to_value(statement->expression);
                ir_switch_table *table = create_switch_table(statement);
                unsigned n_outs = (unsigned)ir_switch_table_get_n_entries(table) + 1;
 
@@ -4748,7 +5354,7 @@ static ir_node *goto_statement_to_firm(goto_statement_t *const stmt)
 static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const statement)
 {
        if (currently_reachable()) {
-               ir_node *const op = expression_to_firm(statement->expression);
+               ir_node *const op = expression_to_value(statement->expression);
                ARR_APP1(ir_node*, ijmp_ops, op);
                jump_to_target(&ijmp_target);
                set_unreachable_now();
@@ -4921,7 +5527,7 @@ static ir_node *asm_statement_to_firm(const asm_statement_t *statement)
                if ( (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE)
                                || (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER) ) {
                        /* we can treat this as "normal" input */
-                       input = expression_to_firm(argument->expression);
+                       input = expression_to_value(argument->expression);
                } else if (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP) {
                        /* pure memory ops need no input (but we have to make sure we
                         * attach to the memory) */
@@ -5050,8 +5656,10 @@ static int count_local_variables(const entity_t *entity,
        entity_t const *const end = last != NULL ? last->base.next : NULL;
        for (; entity != end; entity = entity->base.next) {
                if ((entity->kind == ENTITY_VARIABLE || entity->kind == ENTITY_PARAMETER) &&
-                   !var_needs_entity(&entity->variable))
-                       ++count;
+                   !var_needs_entity(&entity->variable)) {
+                   type_t *type = skip_typeref(entity->declaration.type);
+                       count += is_type_complex(type) ? 2 : 1;
+               }
        }
        return count;
 }
@@ -5116,8 +5724,6 @@ static void initialize_function_parameters(entity_t *entity)
                function_irtype = get_ir_type(entity->declaration.type);
        }
 
-
-
        entity_t *parameter = entity->function.parameters.entities;
        for ( ; parameter != NULL; parameter = parameter->base.next, ++n) {
                if (parameter->kind != ENTITY_PARAMETER)
@@ -5134,23 +5740,38 @@ static void initialize_function_parameters(entity_t *entity)
                                = new_d_parameter_entity(frame_type, n, param_irtype, dbgi);
                        parameter->declaration.kind  = DECLARATION_KIND_PARAMETER_ENTITY;
                        parameter->variable.v.entity = param;
-                       continue;
+               } else if (is_type_complex(type)) {
+                       ir_type   *frame_type = get_irg_frame_type(irg);
+                       ir_entity *param
+                               = new_d_parameter_entity(frame_type, n, param_irtype, dbgi);
+                       ir_node   *nomem = get_irg_no_mem(irg);
+                       ir_node   *frame = get_irg_frame(irg);
+                       ir_node   *addr  = new_simpleSel(nomem, frame, param);
+                       complex_value value = complex_deref_address(NULL, type, addr, cons_floats);
+
+                       parameter->declaration.kind        = DECLARATION_KIND_PARAMETER;
+                       parameter->variable.v.value_number = next_value_number_function;
+                       set_irg_loc_description(irg, next_value_number_function,
+                                                                       parameter);
+                       set_irg_loc_description(irg, next_value_number_function+1,
+                                                                       parameter);
+                       set_value(next_value_number_function, value.real);
+                       set_value(next_value_number_function+1, value.imag);
+                       next_value_number_function += 2;
+               } else {
+                       ir_mode *param_mode = get_type_mode(param_irtype);
+                       long     pn         = n;
+                       ir_node *value      = new_rd_Proj(dbgi, args, param_mode, pn);
+                       value = conv_to_storage_type(dbgi, value, type);
+
+                       parameter->declaration.kind        = DECLARATION_KIND_PARAMETER;
+                       parameter->variable.v.value_number = next_value_number_function;
+                       set_irg_loc_description(irg, next_value_number_function,
+                                                                       parameter);
+                       ++next_value_number_function;
+
+                       set_value(parameter->variable.v.value_number, value);
                }
-
-               ir_mode *param_mode = get_type_mode(param_irtype);
-               long     pn         = n;
-               ir_node *value      = new_rd_Proj(dbgi, args, param_mode, pn);
-
-               ir_mode *mode = get_ir_mode_storage(type);
-               value = create_conv(NULL, value, mode);
-
-               parameter->declaration.kind        = DECLARATION_KIND_PARAMETER;
-               parameter->variable.v.value_number = next_value_number_function;
-               set_irg_loc_description(current_ir_graph, next_value_number_function,
-                                       parameter);
-               ++next_value_number_function;
-
-               set_value(parameter->variable.v.value_number, value);
        }
 }
 
@@ -5223,7 +5844,6 @@ static void create_function(entity_t *entity)
        current_vararg_entity = NULL;
 
        set_irg_fp_model(irg, firm_fp_model);
-       tarval_enable_fp_ops(1);
        set_irn_dbg_info(get_irg_start_block(irg),
                         get_entity_dbg_info(function_entity));