void GenericEnvironment::addMapping(GenericParamKey key, Type contextType) { // We're going to pass InterfaceToArchetypeMap to Type::subst(), which // expects the keys to be canonical, otherwise it won't be able to // find them. auto genericParams = Signature->getGenericParams(); auto genericParam = genericParams[key.findIndexIn(genericParams)]; auto canParamTy = cast<GenericTypeParamType>(genericParam->getCanonicalType()); // Add the mapping form the generic parameter to the context type. assert(InterfaceToArchetypeMap.count(canParamTy) == 0 && "Duplicate entry"); InterfaceToArchetypeMap[canParamTy] = contextType; // If we mapped the generic parameter to an archetype, add it to the // reverse mapping. auto *archetype = contextType->getAs<ArchetypeType>(); if (!archetype) return; // Check whether we've already recorded an interface type for this archetype. // If not, record one and we're done. auto result = ArchetypeToInterfaceMap.insert({archetype, genericParam}); if (result.second) return; // Multiple generic parameters map to the same archetype. If the // existing entry comes from a later generic parameter, replace it with // the earlier generic parameter. This gives us a deterministic reverse // mapping. auto otherGP = result.first->second->castTo<GenericTypeParamType>(); if (std::make_pair(canParamTy->getDepth(), canParamTy->getIndex()) < std::make_pair(otherGP->getDepth(), otherGP->getIndex())) result.first->second = genericParam; }
void GenericEnvironment::addMapping(GenericParamKey key, Type contextType) { // Find the index into the parallel arrays of generic parameters and // context types. auto genericParams = Signature->getGenericParams(); unsigned index = key.findIndexIn(genericParams); assert(genericParams[index] == key && "Bad generic parameter"); // Add the mapping from the generic parameter to the context type. assert(getContextTypes()[index].isNull() && "Already recoded this mapping"); getContextTypes()[index] = contextType; }
Optional<Type> GenericEnvironment::getMappingIfPresent( GenericParamKey key) const { // Find the index into the parallel arrays of generic parameters and // context types. auto genericParams = Signature->getGenericParams(); unsigned index = key.findIndexIn(genericParams); assert(genericParams[index] == key && "Bad generic parameter"); if (auto type = getContextTypes()[index]) return type; return None; }
void GenericEnvironment::addMapping(GenericParamKey key, Type contextType) { // Find the index into the parallel arrays of generic parameters and // context types. auto genericParams = Signature->getGenericParams(); unsigned index = key.findIndexIn(genericParams); assert(genericParams[index] == key && "Bad generic parameter"); // Add the mapping from the generic parameter to the context type. assert(getContextTypes()[index].isNull() && "Already recoded this mapping"); getContextTypes()[index] = contextType; // If we mapped the generic parameter to an archetype, add it to the // reverse mapping. if (auto *archetype = contextType->getAs<ArchetypeType>()) { auto genericParam = genericParams[index]; // Check whether we've already recorded a generic parameter for this // archetype. Note that we always perform a linear search, because we // won't have sorted the list yet. bool found = false; for (auto &mapping : getActiveArchetypeToInterfaceMappings()) { if (mapping.first != archetype) continue; // Multiple generic parameters map to the same archetype. If the // existing entry comes from a later generic parameter, replace it with // the earlier generic parameter. This gives us a deterministic reverse // mapping. auto otherGP = mapping.second->castTo<GenericTypeParamType>(); if (GenericParamKey(genericParam) < GenericParamKey(otherGP)) mapping.second = genericParam; found = true; break; } // If we haven't recorded a generic parameter for this archetype, do so now. if (!found) { void *ptr = getArchetypeToInterfaceMappingsBuffer().data() + NumArchetypeToInterfaceMappings; new (ptr) ArchetypeToInterfaceMapping(archetype, genericParam); ++NumArchetypeToInterfaceMappings; } } // Note that we've recorded this mapping. ++NumMappingsRecorded; // If we've recorded all of the mappings, go ahead and sort the array of // archetype-to-interface-type mappings. if (NumMappingsRecorded == genericParams.size()) { llvm::array_pod_sort(getActiveArchetypeToInterfaceMappings().begin(), getActiveArchetypeToInterfaceMappings().end(), [](const ArchetypeToInterfaceMapping *lhs, const ArchetypeToInterfaceMapping *rhs) -> int { std::less<ArchetypeType *> compare; if (compare(lhs->first, rhs->first)) return -1; if (compare(rhs->first, lhs->first)) return 1; return 0; }); } }