예제 #1
0
/// Normalize a mangled name so it can be matched with string equality.
static std::string normalizeReflectionName(Demangler &dem, StringRef reflectionName) {
  reflectionName = dropSwiftManglingPrefix(reflectionName);
  
  // Remangle the reflection name to resolve symbolic references.
  if (auto node = dem.demangleType(reflectionName)) {
    return mangleNode(node);
  }

  // Fall back to the raw string.
  return reflectionName;
}
예제 #2
0
TypeInfo
swift::_getTypeByMangledName(StringRef typeName,
                             SubstGenericParameterFn substGenericParam) {

  Demangler demangler;
  NodePointer node;

  // Check whether this is the convenience syntax "ModuleName.ClassName".
  size_t dotPos = typeName.find('.');
  if (dotPos != llvm::StringRef::npos &&
      typeName.find('.', dotPos + 1) == llvm::StringRef::npos) {
    // Form a demangle tree for this class.
    NodePointer classNode = demangler.createNode(Node::Kind::Class);
    NodePointer moduleNode = demangler.createNode(Node::Kind::Module,
                                                  typeName.substr(0, dotPos));
    NodePointer nameNode = demangler.createNode(Node::Kind::Identifier,
                                            typeName.substr(dotPos + 1));
    classNode->addChild(moduleNode, demangler);
    classNode->addChild(nameNode, demangler);

    node = classNode;
  } else {
    // Demangle the type name.
    node = demangler.demangleType(typeName);
    if (!node)
      return TypeInfo();
  }

  DecodedMetadataBuilder builder(demangler, substGenericParam,
    [](const Metadata *base, StringRef assocType,
       const ProtocolDescriptor *protocol) -> const Metadata * {
      // Look for a conformance of the base type to the protocol.
      auto witnessTable = swift_conformsToProtocol(base, protocol);
      if (!witnessTable) return nullptr;

      // Look for the named associated type within the protocol.
      auto assocTypeReqIndex = findAssociatedTypeByName(protocol, assocType);
      if (!assocTypeReqIndex) return nullptr;

      // Call the associated type access function.
      using AssociatedTypeAccessFn =
        const Metadata *(*)(const Metadata *base, const WitnessTable *);
      return ((const AssociatedTypeAccessFn *)witnessTable)[*assocTypeReqIndex]
                (base, witnessTable);
    });

  auto type = Demangle::decodeMangledType(builder, node);
  return {type, builder.getOwnership()};
}
예제 #3
0
void swift::gatherWrittenGenericArgs(
                             const Metadata *metadata,
                             const TypeContextDescriptor *description,
                             std::vector<const Metadata *> &allGenericArgs) {
  auto generics = description->getGenericContext();
  if (!generics)
    return;

  bool missingWrittenArguments = false;
  auto genericArgs = description->getGenericArguments(metadata);
  for (auto param : generics->getGenericParams()) {
    switch (param.getKind()) {
    case GenericParamKind::Type:
      // The type should have a key argument unless it's been same-typed to
      // another type.
      if (param.hasKeyArgument()) {
        auto genericArg = *genericArgs++;
        allGenericArgs.push_back(genericArg);
      } else {
        // Leave a gap for us to fill in by looking at same type info.
        allGenericArgs.push_back(nullptr);
        missingWrittenArguments = true;
      }

      // We don't know about type parameters with extra arguments. Leave
      // a hole for it.
      if (param.hasExtraArgument()) {
        allGenericArgs.push_back(nullptr);
        ++genericArgs;
      }
      break;

    default:
      // We don't know about this kind of parameter. Create placeholders where
      // needed.
      if (param.hasKeyArgument()) {
        allGenericArgs.push_back(nullptr);
        ++genericArgs;
      }

      if (param.hasExtraArgument()) {
        allGenericArgs.push_back(nullptr);
        ++genericArgs;
      }
      break;
    }
  }

  // If there is no follow-up work to do, we're done.
  if (!missingWrittenArguments)
    return;

  // We have generic arguments that would be written, but have been
  // canonicalized away. Use same-type requirements to reconstitute them.

  // Retrieve the mapping information needed for depth/index -> flat index.
  std::vector<unsigned> genericParamCounts;
  (void)_gatherGenericParameterCounts(description, genericParamCounts);

  // Walk through the generic requirements to evaluate same-type
  // constraints that are needed to fill in missing generic arguments.
  for (const auto &req : generics->getGenericRequirements()) {
    // We only care about same-type constraints.
    if (req.Flags.getKind() != GenericRequirementKind::SameType)
      continue;

    // Where the left-hand side is a generic parameter.
    if (req.Param.begin() != req.Param.end())
      continue;

    // If we don't yet have an argument for this parameter, it's a
    // same-type-to-concrete constraint.
    unsigned lhsFlatIndex = req.Param.getRootParamIndex();
    if (lhsFlatIndex >= allGenericArgs.size())
      continue;

    if (!allGenericArgs[lhsFlatIndex]) {
      // Substitute into the right-hand side.
      SubstGenericParametersFromWrittenArgs substitutions(allGenericArgs,
                                                          genericParamCounts);
      allGenericArgs[lhsFlatIndex] =
          _getTypeByMangledName(req.getMangledTypeName(), substitutions);
      continue;
    }

    // If we do have an argument for this parameter, it might be that
    // the right-hand side is itself a generic parameter, which means
    // we have a same-type constraint A == B where A is already filled in.
    Demangler demangler;
    NodePointer node = demangler.demangleType(req.getMangledTypeName());
    if (!node)
      continue;

    // Find the flat index that the right-hand side refers to.
    if (node->getKind() == Demangle::Node::Kind::Type)
      node = node->getChild(0);
    if (node->getKind() != Demangle::Node::Kind::DependentGenericParamType)
      continue;

    auto rhsFlatIndex =
      _depthIndexToFlatIndex(node->getChild(0)->getIndex(),
                             node->getChild(1)->getIndex(),
                             genericParamCounts);
    if (!rhsFlatIndex || *rhsFlatIndex >= allGenericArgs.size())
      continue;

    if (allGenericArgs[*rhsFlatIndex] || !allGenericArgs[lhsFlatIndex])
      continue;

    allGenericArgs[*rhsFlatIndex] = allGenericArgs[lhsFlatIndex];
  }
}