Beispiel #1
0
bool types_compatible_ignore_qualifiers(const type_t *type1,
                                        const type_t *type2)
{
	assert(!is_typeref(type1));
	assert(!is_typeref(type2));

	/* shortcut: the same type is always compatible */
	if (type1 == type2)
		return true;

	if (type1->kind != type2->kind) {
		/* enum types are compatible to their base integer type */
		if ((type1->kind == TYPE_ENUM
		     && is_type_atomic(type2, type1->enumt.base.akind))
		    || (type2->kind == TYPE_ENUM
		     && is_type_atomic(type1, type2->enumt.base.akind)))
		    return true;
		/* error types are compatible to everything to avoid follow-up errors */
		if (!is_type_valid(type1) || !is_type_valid(type2))
			return true;
		return false;
	}

	switch (type1->kind) {
	case TYPE_FUNCTION:
		return function_types_compatible(&type1->function, &type2->function);
	case TYPE_ATOMIC:
	case TYPE_IMAGINARY:
	case TYPE_COMPLEX:
		return type1->atomic.akind == type2->atomic.akind;
	case TYPE_ARRAY:
		return array_types_compatible(&type1->array, &type2->array);
	case TYPE_POINTER: {
		const type_t *const to1 = skip_typeref(type1->pointer.points_to);
		const type_t *const to2 = skip_typeref(type2->pointer.points_to);
		return types_compatible(to1, to2);
	}
	case TYPE_REFERENCE: {
		const type_t *const to1 = skip_typeref(type1->reference.refers_to);
		const type_t *const to2 = skip_typeref(type2->reference.refers_to);
		return types_compatible(to1, to2);
	}
	case TYPE_COMPOUND_STRUCT:
	case TYPE_COMPOUND_UNION:
		return type1->compound.compound == type2->compound.compound;
	case TYPE_ENUM:
		return type1->enumt.enume == type2->enumt.enume;
	case TYPE_ERROR:
	case TYPE_VOID:
		return true;
	case TYPE_TYPEDEF:
	case TYPE_TYPEOF:
		break; /* we already tested for is_typeref() above */
	case TYPE_BUILTIN_TEMPLATE:
		panic("unexpected type");
	}
	panic("invalid type kind");
}
Beispiel #2
0
bool types_compatible(const type_t *type1, const type_t *type2)
{
	assert(!is_typeref(type1));
	assert(!is_typeref(type2));

	/* shortcut: the same type is always compatible */
	if (type1 == type2)
		return true;

	if (!is_type_valid(type1) || !is_type_valid(type2))
		return true;

	if (type1->base.qualifiers != type2->base.qualifiers)
		return false;
	if (type1->kind != type2->kind)
		return false;

	switch (type1->kind) {
	case TYPE_FUNCTION:
		return function_types_compatible(&type1->function, &type2->function);
	case TYPE_ATOMIC:
	case TYPE_IMAGINARY:
	case TYPE_COMPLEX:
		return type1->atomic.akind == type2->atomic.akind;
	case TYPE_ARRAY:
		return array_types_compatible(&type1->array, &type2->array);

	case TYPE_POINTER: {
		const type_t *const to1 = skip_typeref(type1->pointer.points_to);
		const type_t *const to2 = skip_typeref(type2->pointer.points_to);
		return types_compatible(to1, to2);
	}

	case TYPE_REFERENCE: {
		const type_t *const to1 = skip_typeref(type1->reference.refers_to);
		const type_t *const to2 = skip_typeref(type2->reference.refers_to);
		return types_compatible(to1, to2);
	}

	case TYPE_COMPOUND_STRUCT:
	case TYPE_COMPOUND_UNION: {
		break;
	}
	case TYPE_ENUM:
		/* TODO: not implemented */
		break;

	case TYPE_ERROR:
		/* Hmm, the error type should be compatible to all other types */
		return true;
	case TYPE_TYPEDEF:
	case TYPE_TYPEOF:
		panic("typerefs not skipped in compatible types?!?");
	}

	return false;
}
Beispiel #3
0
bool types_compatible(const type_t *type1, const type_t *type2)
{
	assert(!is_typeref(type1));
	assert(!is_typeref(type2));

	/* shortcut: the same type is always compatible */
	if (type1 == type2)
		return true;

	if (type1->base.qualifiers == type2->base.qualifiers &&
	    type1->kind            == type2->kind) {
		switch (type1->kind) {
		case TYPE_FUNCTION:
			return function_types_compatible(&type1->function, &type2->function);
		case TYPE_ATOMIC:
		case TYPE_IMAGINARY:
		case TYPE_COMPLEX:
			return type1->atomic.akind == type2->atomic.akind;
		case TYPE_ARRAY:
			return array_types_compatible(&type1->array, &type2->array);

		case TYPE_POINTER: {
			const type_t *const to1 = skip_typeref(type1->pointer.points_to);
			const type_t *const to2 = skip_typeref(type2->pointer.points_to);
			return types_compatible(to1, to2);
		}

		case TYPE_REFERENCE: {
			const type_t *const to1 = skip_typeref(type1->reference.refers_to);
			const type_t *const to2 = skip_typeref(type2->reference.refers_to);
			return types_compatible(to1, to2);
		}

		case TYPE_COMPOUND_STRUCT:
		case TYPE_COMPOUND_UNION:
			break;

		case TYPE_ENUM:
			/* TODO: not implemented */
			break;

		case TYPE_ERROR:
		case TYPE_VOID:
			return true;

		case TYPE_TYPEDEF:
		case TYPE_TYPEOF:
			panic("typeref not skipped");
		case TYPE_BUILTIN_TEMPLATE:
			panic("unexpected type");
		}
	}

	return !is_type_valid(type1) || !is_type_valid(type2);
}
Beispiel #4
0
/**
 * Check if two function types are compatible.
 */
static bool function_types_compatible(const function_type_t *func1,
                                      const function_type_t *func2)
{
	const type_t* const ret1 = skip_typeref(func1->return_type);
	const type_t* const ret2 = skip_typeref(func2->return_type);
	if (!types_compatible(ret1, ret2))
		return false;

	if (func1->linkage != func2->linkage)
		return false;

	cc_kind_t cc1 = func1->calling_convention;
	if (cc1 == CC_DEFAULT)
		cc1 = default_calling_convention;
	cc_kind_t cc2 = func2->calling_convention;
	if (cc2 == CC_DEFAULT)
		cc2 = default_calling_convention;

	if (cc1 != cc2)
		return false;

	if (func1->variadic != func2->variadic)
		return false;

	/* can parameters be compared? */
	if ((func1->unspecified_parameters && !func1->kr_style_parameters)
			|| (func2->unspecified_parameters && !func2->kr_style_parameters))
		return true;

	/* TODO: handling of unspecified parameters not correct yet */

	/* all argument types must be compatible */
	function_parameter_t *parameter1 = func1->parameters;
	function_parameter_t *parameter2 = func2->parameters;
	for ( ; parameter1 != NULL && parameter2 != NULL;
			parameter1 = parameter1->next, parameter2 = parameter2->next) {
		type_t *parameter1_type = skip_typeref(parameter1->type);
		type_t *parameter2_type = skip_typeref(parameter2->type);

		parameter1_type = get_unqualified_type(parameter1_type);
		parameter2_type = get_unqualified_type(parameter2_type);

		if (!types_compatible(parameter1_type, parameter2_type))
			return false;
	}
	/* same number of arguments? */
	if (parameter1 != NULL || parameter2 != NULL)
		return false;

	return true;
}
Beispiel #5
0
/**
 * Check if two array types are compatible.
 */
static bool array_types_compatible(const array_type_t *array1,
                                   const array_type_t *array2)
{
	type_t *element_type1 = skip_typeref(array1->element_type);
	type_t *element_type2 = skip_typeref(array2->element_type);
	if (!types_compatible(element_type1, element_type2))
		return false;

	if (!array1->size_constant || !array2->size_constant)
		return true;

	return array1->size == array2->size;
}
/**
 * mtrr_add_page - Add a memory type region
 * @base: Physical base address of region in pages (in units of 4 kB!)
 * @size: Physical size of region in pages (4 kB)
 * @type: Type of MTRR desired
 * @increment: If this is true do usage counting on the region
 *
 * Memory type region registers control the caching on newer Intel and
 * non Intel processors. This function allows drivers to request an
 * MTRR is added. The details and hardware specifics of each processor's
 * implementation are hidden from the caller, but nevertheless the
 * caller should expect to need to provide a power of two size on an
 * equivalent power of two boundary.
 *
 * If the region cannot be added either because all regions are in use
 * or the CPU cannot support it a negative value is returned. On success
 * the register number for this entry is returned, but should be treated
 * as a cookie only.
 *
 * On a multiprocessor machine the changes are made to all processors.
 * This is required on x86 by the Intel processors.
 *
 * The available types are
 *
 * %MTRR_TYPE_UNCACHABLE - No caching
 *
 * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
 *
 * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
 *
 * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
 *
 * BUGS: Needs a quiet flag for the cases where drivers do not mind
 * failures and do not wish system log messages to be sent.
 */
int mtrr_add_page(unsigned long base, unsigned long size,
		  unsigned int type, bool increment)
{
	unsigned long lbase, lsize;
	int i, replace, error;
	mtrr_type ltype;

	if (!mtrr_if)
		return -ENXIO;

	error = mtrr_if->validate_add_page(base, size, type);
	if (error)
		return error;

	if (type >= MTRR_NUM_TYPES) {
		pr_warning("mtrr: type: %u invalid\n", type);
		return -EINVAL;
	}

	/* If the type is WC, check that this processor supports it */
	if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
		pr_warning("mtrr: your processor doesn't support write-combining\n");
		return -ENOSYS;
	}

	if (!size) {
		pr_warning("mtrr: zero sized request\n");
		return -EINVAL;
	}

	if (base & size_or_mask || size & size_or_mask) {
		pr_warning("mtrr: base or size exceeds the MTRR width\n");
		return -EINVAL;
	}

	error = -EINVAL;
	replace = -1;

	/* No CPU hotplug when we change MTRR entries */
	get_online_cpus();

	/* Search for existing MTRR  */
	mutex_lock(&mtrr_mutex);
	for (i = 0; i < num_var_ranges; ++i) {
		mtrr_if->get(i, &lbase, &lsize, &ltype);
		if (!lsize || base > lbase + lsize - 1 ||
		    base + size - 1 < lbase)
			continue;
		/*
		 * At this point we know there is some kind of
		 * overlap/enclosure
		 */
		if (base < lbase || base + size - 1 > lbase + lsize - 1) {
			if (base <= lbase &&
			    base + size - 1 >= lbase + lsize - 1) {
				/*  New region encloses an existing region  */
				if (type == ltype) {
					replace = replace == -1 ? i : -2;
					continue;
				} else if (types_compatible(type, ltype))
					continue;
			}
			pr_warning("mtrr: 0x%lx000,0x%lx000 overlaps existing"
				" 0x%lx000,0x%lx000\n", base, size, lbase,
				lsize);
			goto out;
		}
		/* New region is enclosed by an existing region */
		if (ltype != type) {
			if (types_compatible(type, ltype))
				continue;
			pr_warning("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
				base, size, mtrr_attrib_to_str(ltype),
				mtrr_attrib_to_str(type));
			goto out;
		}
		if (increment)
			++mtrr_usage_table[i];
		error = i;
		goto out;
	}
	/* Search for an empty MTRR */
	i = mtrr_if->get_free_region(base, size, replace);
	if (i >= 0) {
		set_mtrr(i, base, size, type);
		if (likely(replace < 0)) {
			mtrr_usage_table[i] = 1;
		} else {
			mtrr_usage_table[i] = mtrr_usage_table[replace];
			if (increment)
				mtrr_usage_table[i]++;
			if (unlikely(replace != i)) {
				set_mtrr(replace, 0, 0, 0);
				mtrr_usage_table[replace] = 0;
			}
		}
	} else {
		pr_info("mtrr: no more MTRRs available\n");
	}
	error = i;
 out:
	mutex_unlock(&mtrr_mutex);
	put_online_cpus();
	return error;
}
Beispiel #7
0
/**
 * Check if two function types are compatible.
 */
static bool function_types_compatible(const function_type_t *func1,
                                      const function_type_t *func2)
{
	const type_t* const ret1 = skip_typeref(func1->return_type);
	const type_t* const ret2 = skip_typeref(func2->return_type);
	if (!types_compatible(ret1, ret2))
		return false;

	if (func1->linkage != func2->linkage)
		return false;

	cc_kind_t cc1 = func1->calling_convention;
	if (cc1 == CC_DEFAULT)
		cc1 = default_calling_convention;
	cc_kind_t cc2 = func2->calling_convention;
	if (cc2 == CC_DEFAULT)
		cc2 = default_calling_convention;

	if (cc1 != cc2)
		return false;

	if (func1->variadic != func2->variadic)
		return false;

	/* can parameters be compared? */
	if (func1->unspecified_parameters && !func1->kr_style_parameters) {
		if (func2->unspecified_parameters && !func2->kr_style_parameters)
			return true;
		const function_type_t *const temp = func1;
		func1 = func2;
		func2 = temp;
		goto check_promoted_types;
	} else if (func2->unspecified_parameters && !func2->kr_style_parameters) {
check_promoted_types:
		/* all argument types must already be promoted */
		for (function_parameter_t *parameter = func1->parameters;
		     parameter != NULL; parameter = parameter->next) {
			type_t *const parameter_type = skip_typeref(parameter->type);
			type_t *const promoted
				= get_default_promoted_type(parameter_type);
			if (promoted != parameter_type)
				return false;
		}
		return true;
	}

	/* all argument types must be compatible */
	function_parameter_t *parameter1 = func1->parameters;
	function_parameter_t *parameter2 = func2->parameters;
	for ( ; parameter1 != NULL && parameter2 != NULL;
	     parameter1 = parameter1->next, parameter2 = parameter2->next) {
		type_t *parameter1_type = skip_typeref(parameter1->type);
		type_t *parameter2_type = skip_typeref(parameter2->type);

		if (!types_compatible_ignore_qualifiers(parameter1_type,
		                                        parameter2_type))
			return false;
	}
	/* same number of arguments? */
	if (parameter1 != NULL || parameter2 != NULL)
		return false;

	return true;
}