Beispiel #1
0
int values_in_mode(const ir_mode *sm, const ir_mode *lm)
{
    assert(sm != NULL);
    assert(lm != NULL);
    if (sm == lm)
        return true;

    if (sm == mode_b)
        return mode_is_int(lm) || mode_is_float(lm);

    ir_mode_arithmetic larith = get_mode_arithmetic(lm);
    ir_mode_arithmetic sarith = get_mode_arithmetic(sm);
    switch (larith) {
    case irma_x86_extended_float:
    case irma_ieee754:
        if (sarith == irma_ieee754 || sarith == irma_x86_extended_float) {
            return get_mode_size_bits(sm) <= get_mode_size_bits(lm);
        } else if (sarith == irma_twos_complement) {
            unsigned int_mantissa
                = get_mode_size_bits(sm) - (mode_is_signed(sm) ? 1 : 0);
            unsigned float_mantissa = get_mode_mantissa_size(lm) + 1;
            return int_mantissa <= float_mantissa;
        }
        break;
    case irma_twos_complement:
        if (sarith == irma_twos_complement)
            return get_mode_size_bits(sm) <= get_mode_size_bits(lm);
        break;
    case irma_none:
        break;
    }
    return false;
}
Beispiel #2
0
int smaller_mode(const ir_mode *sm, const ir_mode *lm)
{
    assert(sm != NULL);
    assert(lm != NULL);
    if (sm == lm) return true;

    switch (get_mode_sort(sm)) {
    case irms_int_number:
        switch (get_mode_sort(lm)) {
        case irms_int_number:
            if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm))
                return false;

            /* only two complement implemented */
            assert(get_mode_arithmetic(sm) == irma_twos_complement);

            /* integers are convertable if
             * - both have the same sign and lm is the larger one
             * - lm is signed and is at least one bit larger (the sign) */
            unsigned sm_bits = get_mode_size_bits(sm);
            unsigned lm_bits = get_mode_size_bits(lm);
            if (mode_is_signed(sm)) {
                if (!mode_is_signed(lm))
                    return false;
            } else {
                if (mode_is_signed(lm))
                    return sm_bits < lm_bits;
            }
            return sm_bits <= lm_bits;

        case irms_auxiliary:
        case irms_data:
        case irms_internal_boolean:
        case irms_reference:
        case irms_float_number:
            /* int to float works if the float is large enough */
            return false;
        }
        panic("invalid mode_sort");

    case irms_float_number:
        return get_mode_arithmetic(sm) == get_mode_arithmetic(lm)
               && mode_is_float(lm)
               && get_mode_size_bits(lm) >= get_mode_size_bits(sm);

    case irms_auxiliary:
    case irms_data:
    case irms_internal_boolean:
    case irms_reference:
        /* do exist machines out there with different pointer lengths ?*/
        return false;
    }

    panic("invalid mode_sort");
}
Beispiel #3
0
int is_reinterpret_cast(const ir_mode *src, const ir_mode *dst)
{
    if (src == dst)
        return true;
    if (get_mode_size_bits(src) != get_mode_size_bits(dst))
        return false;
    ir_mode_arithmetic ma = get_mode_arithmetic(src);
    if (ma != get_mode_arithmetic(dst))
        return false;

    return ma == irma_twos_complement;
}
Beispiel #4
0
bool x86_match_immediate(x86_imm32_t *immediate, const ir_node *node,
                         char const constraint)
{
	ir_mode *const mode = get_irn_mode(node);
	if (get_mode_arithmetic(mode) != irma_twos_complement)
		return false;

	ir_tarval *offset;
	ir_entity *entity;
	if (!be_match_immediate(node, &offset, &entity))
		return false;

	long val = 0;
	if (offset) {
		if (!tarval_is_long(offset)) {
			be_warningf(node, "tarval is not long");
			return false;
		}

		val = get_tarval_long(offset);
		if (!check_immediate_constraint(val, constraint))
			return false;
	}

	if (entity != NULL) {
		/* we need full 32bits for entities */
		if (constraint != 'i' && constraint != 'g')
			return false;
	}

	/* we are fine */
	immediate->entity = entity;
	immediate->offset = (int32_t)val;
	return true;
}
Beispiel #5
0
static ir_tarval *bitinfo_min(bitinfo *info)
{
	ir_tarval *z    = info->z;
	ir_tarval *o    = info->o;
	ir_mode   *mode = get_tarval_mode(z);
	ir_tarval *min  = get_mode_min(mode);

	assert(get_mode_arithmetic(mode) == irma_twos_complement);
	return tarval_or(o, tarval_and(z, min));
}
Beispiel #6
0
static void handle_intrinsic(ir_node *node, void *data)
{
	(void)data;
	if (is_Div(node)) {
		ir_mode *mode = get_Div_resmode(node);
		if (get_mode_arithmetic(mode) == irma_twos_complement) {
			ir_entity *entity = mode_is_signed(mode) ? divsi3 : udivsi3;
			be_map_exc_node_to_runtime_call(node, mode, entity, pn_Div_M,
			                                pn_Div_X_regular, pn_Div_X_except,
			                                pn_Div_res);
		}
	} else if (is_Mod(node)) {
		ir_mode *mode = get_Mod_resmode(node);
		assert(get_mode_arithmetic(mode) == irma_twos_complement);
		ir_entity *entity = mode_is_signed(mode) ? modsi3 : umodsi3;
		be_map_exc_node_to_runtime_call(node, mode, entity, pn_Mod_M,
		                                pn_Mod_X_regular, pn_Mod_X_except,
		                                pn_Mod_res);
	}
}
Beispiel #7
0
/**
 * 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);
	}
}
Beispiel #8
0
/**
 * @return The type of the function replacing the given node.
 */
static ir_type *get_softfloat_type(const ir_node *n)
{
	ir_node *operand      = get_irn_n(n, 0);
	ir_mode *operand_mode = get_irn_mode(operand);

	switch (get_irn_opcode(n)) {
	case iro_Div:
		operand_mode = get_irn_mode(get_Div_left(n));
		/* fall through */
	case iro_Add:
	case iro_Mul:
	case iro_Sub:
		if (operand_mode == mode_F)
			return binop_tp_f;
		else if (operand_mode == mode_D)
			return binop_tp_d;
		break;
	case iro_Cmp:
		if (operand_mode == mode_F)
			return cmp_tp_f;
		else if (operand_mode == mode_D)
			return cmp_tp_d;
		break;

	case iro_Conv: {
		ir_mode *const mode = get_irn_mode(n);
		if (operand_mode == mode_D) {
			if (mode == mode_F)
				return unop_tp_d_f;
			else if (get_mode_arithmetic(mode) == irma_twos_complement) {
				if (get_mode_size_bits(mode) <= 32)
					return mode_is_signed(mode) ? unop_tp_d_is : unop_tp_d_iu;
				else if (get_mode_size_bits(mode) == 64)
					return mode_is_signed(mode) ? unop_tp_d_ls : unop_tp_d_lu;
			}
		} else if (operand_mode == mode_F) {
			if (mode == mode_D)
				return unop_tp_f_d;
			else if (get_mode_arithmetic(mode) == irma_twos_complement) {
				if (get_mode_size_bits(mode) <= 32)
					return mode_is_signed(mode) ? unop_tp_f_is : unop_tp_f_iu;
				else if (get_mode_size_bits(mode) == 64)
					return mode_is_signed(mode) ? unop_tp_f_ls : unop_tp_f_lu;
			}
		} else if (get_mode_arithmetic(operand_mode) == irma_twos_complement) {
			if (mode_is_signed(operand_mode)) {
				if (get_mode_size_bits(operand_mode) <= 32) {
					if (mode == mode_D)
						return unop_tp_is_d;
					else if (mode == mode_F)
						return unop_tp_is_f;
				} else if (get_mode_size_bits(operand_mode) == 64) {
					if (mode == mode_D)
						return unop_tp_ls_d;
					else if (mode == mode_F)
						return unop_tp_ls_f;
				}
			} else {
				if (get_mode_size_bits(operand_mode) <= 32) {
					if (mode == mode_D)
						return unop_tp_iu_d;
					else if (mode == mode_F)
						return unop_tp_iu_f;
				} else if (get_mode_size_bits(operand_mode) == 64) {
					if (mode == mode_D)
						return unop_tp_lu_d;
					else if (mode == mode_F)
						return unop_tp_lu_f;
				}
			}
		}
		break;
	}

	case iro_Minus:
		if (operand_mode == mode_F)
			return unop_tp_f;
		else if (operand_mode == mode_D)
			return unop_tp_d;
		break;
	default: break;
	}

	panic("could not determine a suitable type");
}
Beispiel #9
0
int smaller_mode(const ir_mode *sm, const ir_mode *lm)
{
    int sm_bits, lm_bits;

    assert(sm);
    assert(lm);

    if (sm == lm) return 1;

    sm_bits = get_mode_size_bits(sm);
    lm_bits = get_mode_size_bits(lm);

    switch (get_mode_sort(sm)) {
    case irms_int_number:
        switch (get_mode_sort(lm)) {
        case irms_int_number:
            if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm))
                return 0;

            /* only two complement implemented */
            assert(get_mode_arithmetic(sm) == irma_twos_complement);

            /* integers are convertable if
             *   - both have the same sign and lm is the larger one
             *   - lm is the signed one and is at least two bits larger
             *     (one for the sign, one for the highest bit of sm)
             *   - sm & lm are two_complement and lm has greater or equal number of bits
             */
            if (mode_is_signed(sm)) {
                if (!mode_is_signed(lm))
                    return 0;
                return sm_bits <= lm_bits;
            } else {
                if (mode_is_signed(lm)) {
                    return sm_bits < lm_bits;
                }
                return sm_bits <= lm_bits;
            }

        case irms_float_number:
            /* int to float works if the float is large enough */
            return 0;

        default:
            break;
        }
        break;

    case irms_float_number:
        if (get_mode_arithmetic(sm) == get_mode_arithmetic(lm)) {
            if ( (get_mode_sort(lm) == irms_float_number)
                    && (get_mode_size_bits(lm) >= get_mode_size_bits(sm)) )
                return 1;
        }
        break;

    case irms_reference:
        /* do exist machines out there with different pointer lengths ?*/
        return 0;

    case irms_internal_boolean:
        return mode_is_int(lm);

    default:
        break;
    }

    /* else */
    return 0;
}