Ejemplo n.º 1
0
static ir_tarval *fold_binary_sub(binary_expression_t const *const binexpr)
{
	ir_tarval *const l        = fold_expression(binexpr->left);
	ir_tarval *const r        = fold_expression(binexpr->right);
	type_t    *const type     = skip_typeref(binexpr->base.type);
	ir_mode   *const res_mode = get_ir_mode_arithmetic(type);
	type_t    *const typel    = skip_typeref(binexpr->left->base.type);
	if (is_type_pointer(typel)) {
		type_t *const elem  = skip_typeref(typel->pointer.points_to);
		type_t *const typer = skip_typeref(binexpr->right->base.type);
		if (is_type_pointer(typer)) {
			ir_tarval *const size = get_type_size_tarval(elem, res_mode);
			ir_tarval *const diff = tarval_sub(l, r);
			return tarval_div(diff, size);
		} else {
			ir_mode   *const mode = get_tarval_mode(r);
			ir_tarval *const size = get_type_size_tarval(elem, mode);
			ir_tarval *const rr   = tarval_mul(r, size);
			return tarval_sub(l, rr);
		}
	} else {
		ir_tarval *const conv_l = tarval_convert_to(l, res_mode);
		ir_tarval *const conv_r = tarval_convert_to(r, res_mode);
		return tarval_sub(conv_l, conv_r);
	}
}
Ejemplo n.º 2
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");
	}
}
Ejemplo n.º 3
0
static complex_constant convert_complex_constant(const complex_constant cnst,
                                                 ir_mode *mode)
{
	if (get_tarval_mode(cnst.real) == mode)
		return cnst;
	return (complex_constant) {
		tarval_convert_to(cnst.real, mode),
		tarval_convert_to(cnst.imag, mode)
	};
}
Ejemplo n.º 4
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));
}
Ejemplo n.º 5
0
static bool tarval_possible(ir_tarval *tv)
{
	ir_mode *mode = get_tarval_mode(tv);
	if (get_mode_size_bits(mode) <= 32) {
		assert(tarval_is_long(tv));
		return true;
	}

	if (!tarval_is_long(tv))
		return false;
	/* immediates on x86_64 are at most 32bit and get sign extended */
	long    val   = get_tarval_long(tv);
	int32_t val32 = (long)val;
	return val == (long)val32;
}
Ejemplo n.º 6
0
/**
 * Returns the condensed representation of the tarval tv
 */
static unsigned char *value_to_condensed(mul_env *env, ir_tarval *tv, int *pr)
{
	ir_mode       *mode = get_tarval_mode(tv);
	unsigned       bits = get_mode_size_bits(mode);
	unsigned char *R    = OALLOCN(&env->obst, unsigned char, bits);

	int r = 0;
	for (unsigned i = 0, l = 0; i < bits; ++i) {
		if (tarval_get_bit(tv, i)) {
			R[r] = i - l;
			l = i;
			++r;
		}
	}

	*pr = r;
	return R;
}
Ejemplo n.º 7
0
/**
 * construct an interval from a value
 *
 * @return the filled interval or NULL if no interval
 *         can be created (happens only on floating point
 */
static interval_t *get_interval_from_tv(interval_t *iv, ir_tarval *tv)
{
	ir_mode *mode = get_tarval_mode(tv);

	if (tv == tarval_bad) {
		if (mode_is_float(mode)) {
			/* NaN could be included which we cannot handle */
			iv->min   = tarval_bad;
			iv->max   = tarval_bad;
			iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
			return NULL;
		} else {
			/* [-oo, +oo] */
			iv->min   = get_mode_min(mode);
			iv->max   = get_mode_max(mode);
			iv->flags = MIN_INCLUDED | MAX_INCLUDED;
			return iv;
		}
	}

	if (mode_is_float(mode)) {
		if (tv == get_mode_NAN(mode)) {
			/* arg, we cannot handle NaN's. */
			iv->min   = tarval_bad;
			iv->max   = tarval_bad;
			iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
			return NULL;
		}
	}

	/* [tv, tv] */
	iv->min   = tv;
	iv->max   = tv;
	iv->flags = MIN_INCLUDED | MAX_INCLUDED;

	return iv;
}
Ejemplo n.º 8
0
static bool check_initializer(const ir_initializer_t *initializer,
                              const ir_type *type,
                              const ir_entity *context)
{
	bool fine = true;
	switch (get_initializer_kind(initializer)) {
	case IR_INITIALIZER_NULL:
		return fine;
	case IR_INITIALIZER_TARVAL: {
		ir_tarval *tv = get_initializer_tarval_value(initializer);
		if (get_type_mode(type) != get_tarval_mode(tv)) {
			report_error("tarval initializer for entity %+F has wrong mode: %+F vs %+F", context, get_type_mode(type), get_tarval_mode(tv));
			fine = false;
		}
		return fine;
	}
	case IR_INITIALIZER_CONST: {
		ir_node *value = get_initializer_const_value(initializer);
		if (get_type_mode(type) != get_irn_mode(value)) {
			report_error("const initializer for entity %+F has wrong mode: %+F vs %+F", context, get_type_mode(type), get_irn_mode(value));
			fine = false;
		}
		if (!constant_on_correct_irg(value)) {
			report_error("initializer const value %+F for entity %+F not on const-code irg", value, context);
			fine = false;
		}
		return fine;
	}
	case IR_INITIALIZER_COMPOUND: {
		size_t n_entries = get_initializer_compound_n_entries(initializer);
		if (is_Array_type(type)) {
			ir_type *element_type = get_array_element_type(type);
			/* TODO: check array bounds? */
			for (size_t i = 0; i < n_entries; ++i) {
				const ir_initializer_t *sub_initializer
					= get_initializer_compound_value(initializer, i);
				check_initializer(sub_initializer, element_type, context);
			}
		} else if (is_compound_type(type)) {
			size_t n_members = get_compound_n_members(type);
			if (n_entries > n_members) {
				report_error("too many values in compound initializer of %+F",
				             context);
				fine = false;
			}
			for (size_t i = 0; i < n_entries; ++i) {
				if (i >= n_members)
					break;
				ir_entity *member      = get_compound_member(type, i);
				ir_type   *member_type = get_entity_type(member);
				const ir_initializer_t *sub_initializer
					= get_initializer_compound_value(initializer, i);
				check_initializer(sub_initializer, member_type, context);
			}
		} else {
			report_error("compound initiailizer for non-array/compound type in entity %+F",
			             context);
			fine = false;
		}
		return fine;
	}
	}
	report_error("invalid initializer for entity %+F", context);
	return false;
}
Ejemplo n.º 9
0
int check_entity(const ir_entity *entity)
{
	bool        fine    = true;
	ir_type    *tp      = get_entity_type(entity);
	ir_linkage  linkage = get_entity_linkage(entity);

	fine &= constants_on_wrong_irg(entity);

	if (is_method_entity(entity)) {
		ir_graph *irg = get_entity_irg(entity);
		if (irg != NULL) {
			ir_entity *irg_entity = get_irg_entity(irg);
			if (irg_entity != entity) {
				report_error("entity(%+F)->irg->entity(%+F) relation invalid",
				             entity, irg_entity);
				fine = false;
			}
		}
		if (get_entity_peculiarity(entity) == peculiarity_existent) {
			ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity));
			if (impl == NULL) {
				report_error("inherited method entity %+F must have constant pointing to existent entity.", entity);
				fine = false;
			}
		}
	}

	if (linkage & IR_LINKAGE_NO_CODEGEN) {
		if (!is_method_entity(entity)) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity);
			fine = false;
		} else if (get_entity_irg(entity) == NULL) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity);
			fine = false;
		}
		if (get_entity_visibility(entity) != ir_visibility_external) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity);
			fine = false;
		}
	}
	check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK");
	check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT,
	                       "GARBAGE_COLLECT");
	check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE");

	if (is_atomic_entity(entity) && entity->initializer != NULL) {
		ir_mode *mode = NULL;
		ir_initializer_t *initializer = entity->initializer;
		switch (initializer->kind) {
		case IR_INITIALIZER_CONST:
			mode = get_irn_mode(get_initializer_const_value(initializer));
			break;
		case IR_INITIALIZER_TARVAL:
			mode = get_tarval_mode(get_initializer_tarval_value(initializer));
			break;
		case IR_INITIALIZER_NULL:
		case IR_INITIALIZER_COMPOUND:
			break;
		}
		if (mode != NULL && mode != get_type_mode(tp)) {
			report_error("initializer of entity %+F has wrong mode.", entity);
			fine = false;
		}
	}
	return fine;
}