+ 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)) {