Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
                         });
  }
}