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"); }
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; }
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); }
/** * 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; }
/** * 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, <ype); 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; }
/** * 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; }