static ir_tarval *literal_to_tarval_(const literal_expression_t *literal, ir_mode *mode) { switch (literal->base.kind) { case EXPR_LITERAL_INTEGER: assert(literal->target_value != NULL); return literal->target_value; case EXPR_LITERAL_FLOATINGPOINT: return new_tarval_from_str(literal->value->begin, literal->value->size, mode); case EXPR_LITERAL_BOOLEAN: if (literal->value->begin[0] == 't') { return get_mode_one(mode); } else { assert(literal->value->begin[0] == 'f'); case EXPR_LITERAL_MS_NOOP: return get_mode_null(mode); } default: panic("invalid literal kind"); } }
static ir_tarval *char_literal_to_tarval(string_literal_expression_t const *literal) { 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; switch (literal->value->encoding) { case STRING_ENCODING_WIDE: { utf32 v = read_utf8_char(&string); char buf[128]; size_t len = snprintf(buf, sizeof(buf), UTF32_PRINTF_FORMAT, v); return new_tarval_from_str(buf, len, mode); } case STRING_ENCODING_CHAR: { long long int v; bool char_is_signed = get_atomic_type_flags(ATOMIC_TYPE_CHAR) & ATOMIC_TYPE_FLAG_SIGNED; if (size == 1 && char_is_signed) { v = (signed char)string[0]; } else { v = 0; for (size_t i = 0; i < size; ++i) { v = (v << 8) | ((unsigned char)string[i]); } } char buf[128]; size_t len = snprintf(buf, sizeof(buf), "%lld", v); return new_tarval_from_str(buf, len, mode); } default: panic("invalid literal kind"); } }
static void check_mode(ir_mode *mode) { ir_tarval *zero = get_mode_null(mode); ir_tarval *minus_zero = tarval_neg(zero); ir_tarval *min = get_mode_min(mode); ir_tarval *max = get_mode_max(mode); ir_tarval *inf = get_mode_infinite(mode); ir_tarval *minus_inf = tarval_neg(inf); ir_tarval *one = get_mode_one(mode); ir_tarval *minus_one = tarval_neg(one); /* some random arithmetics */ ir_tarval *int_zero = get_mode_null(mode_Is); ir_tarval *int_one = get_mode_one(mode_Is); ir_tarval *int_minus_one = get_mode_all_one(mode_Is); ir_tarval *int_min = get_mode_min(mode_Is); ir_tarval *int_max = get_mode_max(mode_Is); assert(tarval_convert_to(zero, mode_Is) == int_zero); assert(tarval_convert_to(minus_zero, mode_Is) == int_zero); assert(tarval_convert_to(one, mode_Is) == int_one); assert(tarval_convert_to(minus_one, mode_Is) == int_minus_one); assert(tarval_convert_to(min, mode_Is) == int_min); assert(tarval_convert_to(max, mode_Is) == int_max); assert(tarval_convert_to(inf, mode_Is) == int_max); assert(tarval_convert_to(minus_inf, mode_Is) == int_min); static const char *const ints[] = { "0", "1", "-1", "12345", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "127", "2047" }; for (unsigned i = 0; i < ARRAY_SIZE(ints); ++i) { const char *str = ints[i]; ir_tarval *flt = new_tarval_from_str(str, strlen(str), mode); ir_tarval *intt = new_tarval_from_str(str, strlen(str), mode_Is); assert(tarval_convert_to(flt, mode_Is) == intt); assert(tarval_convert_to(intt, mode) == flt); } }
ir_tarval *fold_builtin_nan(call_expression_t const *const call, type_t const *const function_type) { ir_tarval *payload = NULL; call_argument_t *const argument = call->arguments; if (argument != NULL && argument->expression->kind == EXPR_STRING_LITERAL) { const char *str = argument->expression->string_literal.value->begin; /* sanity checking */ if (is_valid_strold_input(str)) { ir_mode *payload_mode = atomic_modes[ATOMIC_TYPE_ULONGLONG]; payload = new_tarval_from_str(str, strlen(str), payload_mode); } } type_t *type = function_type->function.return_type; ir_mode *mode = get_ir_mode_storage(type); return new_tarval_nan(mode, false, payload); }
/** * lower 64bit conversions */ static void ia32_lower_conv64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *op = get_Conv_op(node); ir_mode *mode_from = get_irn_mode(op); ir_mode *mode_to = get_irn_mode(node); if (mode_is_float(mode_from) && get_mode_size_bits(mode_to) == 64 && get_mode_arithmetic(mode_to) == irma_twos_complement) { /* We have a Conv float -> long long here */ ir_node *float_to_ll; ir_node *l_res; ir_node *h_res; if (mode_is_signed(mode)) { /* convert from float to signed 64bit */ ir_node *block = get_nodes_block(node); float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, op); l_res = new_r_Proj(float_to_ll, ia32_mode_gp, pn_ia32_l_FloattoLL_res_low); h_res = new_r_Proj(float_to_ll, mode, pn_ia32_l_FloattoLL_res_high); } else { /* Convert from float to unsigned 64bit. */ ir_graph *irg = get_irn_irg(node); ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, x86_mode_E); ir_node *flt_corr = new_r_Const(irg, flt_tv); ir_node *lower_blk = part_block_dw(node); ir_node *upper_blk = get_nodes_block(node); set_dw_control_flow_changed(); ir_node *opc = new_rd_Conv(dbg, upper_blk, op, x86_mode_E); ir_node *cmp = new_rd_Cmp(dbg, upper_blk, opc, flt_corr, ir_relation_less); ir_node *cond = new_rd_Cond(dbg, upper_blk, cmp); ir_node *in[] = { new_r_Proj(cond, mode_X, pn_Cond_true), new_r_Proj(cond, mode_X, pn_Cond_false) }; ir_node *blk = new_r_Block(irg, 1, &in[1]); in[1] = new_r_Jmp(blk); set_irn_in(lower_blk, 2, in); /* create to Phis */ ir_node *phi_in[] = { new_r_Const_null(irg, mode), new_r_Const_long(irg, mode, 0x80000000) }; ir_node *int_phi = new_r_Phi(lower_blk, ARRAY_SIZE(phi_in), phi_in, mode); ir_node *fphi_in[] = { opc, new_rd_Sub(dbg, upper_blk, opc, flt_corr, x86_mode_E) }; ir_node *flt_phi = new_r_Phi(lower_blk, ARRAY_SIZE(fphi_in), fphi_in, x86_mode_E); /* fix Phi links for next part_block() */ if (is_Phi(int_phi)) add_Block_phi(lower_blk, int_phi); if (is_Phi(flt_phi)) add_Block_phi(lower_blk, flt_phi); float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi); l_res = new_r_Proj(float_to_ll, ia32_mode_gp, pn_ia32_l_FloattoLL_res_low); h_res = new_r_Proj(float_to_ll, mode, pn_ia32_l_FloattoLL_res_high); h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, mode); /* move the call and its Proj's to the lower block */ set_nodes_block(node, lower_blk); for (ir_node *proj = (ir_node*)get_irn_link(node); proj != NULL; proj = (ir_node*)get_irn_link(proj)) { set_nodes_block(proj, lower_blk); } } ir_set_dw_lowered(node, l_res, h_res); } else if (get_mode_size_bits(mode_from) == 64 && get_mode_arithmetic(mode_from) == irma_twos_complement && mode_is_float(mode_to)) { /* We have a Conv long long -> float here */ ir_node *op_low = get_lowered_low(op); ir_node *op_high = get_lowered_high(op); ir_node *block = get_nodes_block(node); ir_node *ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, op_high, op_low, mode_to); exchange(node, ll_to_float); } else { ir_default_lower_dw_Conv(node, mode); } }