示例#1
0
static ir_tarval *fold_expression_to_address(expression_t const *const expr)
{
	switch (expr->kind) {
	case EXPR_SELECT: {
		select_expression_t const *const sel = &expr->select;
		type_t    *const type        = skip_typeref(sel->compound->base.type);
		ir_tarval *const base_addr   = is_type_pointer(type) ? fold_expression(sel->compound) : fold_expression_to_address(sel->compound);
		ir_mode   *const mode        = get_tarval_mode(base_addr);
		ir_mode   *const mode_offset = get_reference_offset_mode(mode);
		ir_tarval *const offset      = new_tarval_from_long(sel->compound_entry->compound_member.offset, mode_offset);
		return tarval_add(base_addr, offset);
	}

	case EXPR_ARRAY_ACCESS: {
		ir_tarval *const base_addr = fold_expression_to_address(expr->array_access.array_ref);
		ir_tarval *const idx       = fold_expression(expr->array_access.index);
		ir_mode   *const mode      = get_ir_mode_arithmetic(type_size_t);
		ir_tarval *const idx_conv  = tarval_convert_to(idx, mode);
		type_t    *const elem_type = skip_typeref(expr->array_access.array_ref->base.type);
		ir_tarval *const elem_size = get_type_size_tarval(elem_type, mode);
		return tarval_add(base_addr, tarval_mul(idx_conv, elem_size));
	}

	case EXPR_UNARY_DEREFERENCE:
		return fold_expression(expr->unary.value);

	default:
		panic("unexpected expression kind");
	}
}
示例#2
0
static carry_result lower_add_carry(ir_node *left, ir_node *right, ir_mode *mode)
{
	assert(!mode_is_signed(mode));

	bitinfo *bi_left = get_bitinfo(left);
	if (!bi_left) {
		return can_carry;
	}
	bitinfo *bi_right = get_bitinfo(right);
	// If we have bitinfo for one node, we should also have it for
	// the other
	assert(bi_right);

	ir_tarval    *lmin   = tarval_convert_to(bitinfo_min(bi_left),  mode);
	ir_tarval    *rmin   = tarval_convert_to(bitinfo_min(bi_right), mode);
	ir_tarval    *lmax   = tarval_convert_to(bitinfo_max(bi_left),  mode);
	ir_tarval    *rmax   = tarval_convert_to(bitinfo_max(bi_right), mode);
	carry_result  result = no_carry;

	int old_wrap_on_overflow = tarval_get_wrap_on_overflow();
	tarval_set_wrap_on_overflow(false);

	if (tarval_add(lmax, rmax) == tarval_bad) {
		result = can_carry;
		if (tarval_add(lmin, rmin) == tarval_bad) {
			result = must_carry;
		}
	}

	tarval_set_wrap_on_overflow(old_wrap_on_overflow);

	return result;
}
示例#3
0
static complex_constant fold_complex_add(complex_constant const left,
                                         complex_constant const right)
{
	return (complex_constant) {
		tarval_add(left.real, right.real),
		tarval_add(left.imag, right.imag)
	};
}
示例#4
0
static ir_tarval *fold_binary_add(binary_expression_t const *const binexpr)
{
	ir_tarval *const l     = fold_expression(binexpr->left);
	ir_tarval *const r     = fold_expression(binexpr->right);
	ir_tarval       *ll    = l;
	ir_tarval       *rr    = r;
	type_t    *const typel = skip_typeref(binexpr->left->base.type);
	type_t    *const typer = skip_typeref(binexpr->right->base.type);
	if (is_type_pointer(typel)) {
		type_t    *const elem = skip_typeref(typel->pointer.points_to);
		ir_mode   *const mode = get_ir_mode_arithmetic(typer);
		ir_tarval *const size = get_type_size_tarval(elem, mode);
		rr = tarval_mul(rr, size);
	} else if (is_type_pointer(typer)) {
		type_t    *const elem = skip_typeref(typer->pointer.points_to);
		ir_mode   *const mode = get_ir_mode_arithmetic(typel);
		ir_tarval *const size = get_type_size_tarval(elem, mode);
		ll = tarval_mul(ll, size);
	} else {
		type_t  *const type = skip_typeref(binexpr->base.type);
		ir_mode *const mode = get_ir_mode_arithmetic(type);
		ll = tarval_convert_to(l, mode);
		rr = tarval_convert_to(r, mode);
	}
	return tarval_add(ll, rr);
}
示例#5
0
static complex_constant fold_complex_div(complex_constant const left,
                                         complex_constant const right)
{
	ir_tarval *const op1 = tarval_mul(left.real, right.real);
	ir_tarval *const op2 = tarval_mul(left.imag, right.imag);
	ir_tarval *const op3 = tarval_mul(left.imag, right.real);
	ir_tarval *const op4 = tarval_mul(left.real, right.imag);
	ir_tarval *const op5 = tarval_mul(right.real, right.real);
	ir_tarval *const op6 = tarval_mul(right.imag, right.imag);
	ir_tarval *const real_dividend = tarval_add(op1, op2);
	ir_tarval *const real_divisor  = tarval_add(op5, op6);
	ir_tarval *const imag_dividend = tarval_sub(op3, op4);
	ir_tarval *const imag_divisor  = tarval_add(op5, op6);
	return (complex_constant) {
		tarval_div(real_dividend, real_divisor),
		tarval_div(imag_dividend, imag_divisor)
	};
}
示例#6
0
static complex_constant fold_complex_mul(complex_constant const left,
                                         complex_constant const right)
{
	ir_tarval *const op1 = tarval_mul(left.real, right.real);
	ir_tarval *const op2 = tarval_mul(left.imag, right.imag);
	ir_tarval *const op3 = tarval_mul(left.real, right.imag);
	ir_tarval *const op4 = tarval_mul(left.imag, right.real);
	return (complex_constant) {
		tarval_sub(op1, op2),
		tarval_add(op3, op4)
	};
}
示例#7
0
文件: irarch.c 项目: lamproae/libfirm
/**
 * creates a tarval from a condensed representation.
 */
static ir_tarval *condensed_to_value(mul_env *env, unsigned char *R, int r)
{
	ir_tarval *tv  = get_mode_one(env->mode);
	ir_tarval *res = NULL;
	for (int i = 0; i < r; ++i) {
		int j = R[i];
		if (j != 0)
			tv = tarval_shl_unsigned(tv, j);
		res = res ? tarval_add(res, tv) : tv;
	}
	return res;
}
示例#8
0
void determine_enum_values(enum_t *const enume)
{
	if (enume->error)
		return;

	ir_mode   *const mode    = atomic_modes[enume->akind];
	ir_tarval *const one     = get_mode_one(mode);
	ir_tarval *      tv_next = get_mode_null(mode);

	for (entity_t *entry = enume->first_value;
	     entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
	     entry = entry->base.next) {
		expression_t *const init = entry->enum_value.value;
		if (init != NULL) {
			type_t *const init_type = skip_typeref(init->base.type);
			if (!is_type_valid(init_type))
				continue;
			tv_next = fold_expression(init);
		}
		assert(entry->enum_value.tv == NULL || entry->enum_value.tv == tv_next);
		entry->enum_value.tv = tv_next;
		tv_next = tarval_add(tv_next, one);
	}
}