Ejemplo n.º 1
0
void Remangler::mangleAnyNominalType(Node *node, EntityContext &ctx) {
  if (isSpecialized(node)) {
    Out << 'G';

    NodePointer unboundType = getUnspecialized(node);
    TemporaryNodes.push_back(unboundType);

    mangleAnyNominalType(unboundType.get(), ctx);
    mangleGenericArgs(node, ctx);
    return;
  }

  switch (node->getKind()) {
  case Node::Kind::Structure:
    mangleNominalType(node, 'V', ctx);
    break;
  case Node::Kind::Enum:
    mangleNominalType(node, 'O', ctx);
    break;
  case Node::Kind::Class:
    mangleNominalType(node, 'C', ctx);
    break;
  default:
    unreachable("bad nominal type kind");
  }
}
Ejemplo n.º 2
0
void Remangler::mangleGenericArgs(Node *node, EntityContext &ctx) {
  switch (node->getKind()) {
  case Node::Kind::Structure:
  case Node::Kind::Enum:
  case Node::Kind::Class: {
    NodePointer parentOrModule = node->getChild(0);
    mangleGenericArgs(parentOrModule, ctx);

    // No generic arguments at this level
    Out << '_';
    break;
  }

  case Node::Kind::BoundGenericStructure:
  case Node::Kind::BoundGenericEnum:
  case Node::Kind::BoundGenericClass: {
    NodePointer unboundType = node->getChild(0);
    assert(unboundType->getKind() == Node::Kind::Type);
    NodePointer nominalType = unboundType->getChild(0);
    NodePointer parentOrModule = nominalType->getChild(0);
    mangleGenericArgs(parentOrModule, ctx);

    mangleTypeList(node->getChild(1));
    break;
  }

  default:
    break;
  }
}
Ejemplo n.º 3
0
TypeInfo
swift::_getTypeByMangledName(StringRef typeName,
                             SubstGenericParameterFn substGenericParam) {
  auto demangler = getDemanglerForRuntimeTypeResolution();
  NodePointer node;

  // Check whether this is the convenience syntax "ModuleName.ClassName".
  auto getDotPosForConvenienceSyntax = [&]() -> size_t {
    size_t dotPos = typeName.find('.');
    if (dotPos == llvm::StringRef::npos)
      return llvm::StringRef::npos;
    if (typeName.find('.', dotPos + 1) != llvm::StringRef::npos)
      return llvm::StringRef::npos;
    if (typeName.find('\1') != llvm::StringRef::npos)
      return llvm::StringRef::npos;
    return dotPos;
  };

  auto dotPos = getDotPosForConvenienceSyntax();
  if (dotPos != 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 assocTypeReq = findAssociatedTypeByName(protocol, assocType);
      if (!assocTypeReq) return nullptr;

      // Call the associated type access function.
      return swift_getAssociatedTypeWitness(
                                     MetadataState::Abstract,
                                     const_cast<WitnessTable *>(witnessTable),
                                     base,
                                     *assocTypeReq).Value;
    });

  auto type = Demangle::decodeMangledType(builder, node);
  return {type, builder.getReferenceOwnership()};
}
Ejemplo n.º 4
0
	ValueType operator()(NodePointer a, NodePointer b) const {
		ValueType res1 = d1(a,b);
		ValueType res2 = d2(a,b);

		double n = sqrt((a->getModel().getSubnodes() * b->getModel().getSubnodes()));
		double beta = exp(-n/sf);
		return beta*res1 + (1-beta)*res2;
	}
Ejemplo n.º 5
0
Optional<ASTBuilder::ForeignModuleKind>
ASTBuilder::getForeignModuleKind(NodePointer node) {
  if (node->getKind() == Demangle::Node::Kind::DeclContext)
    return getForeignModuleKind(node->getFirstChild());

  if (node->getKind() != Demangle::Node::Kind::Module)
    return None;

  return llvm::StringSwitch<Optional<ForeignModuleKind>>(node->getText())
      .Case(MANGLING_MODULE_OBJC, ForeignModuleKind::Imported)
      .Case(MANGLING_MODULE_CLANG_IMPORTER,
            ForeignModuleKind::SynthesizedByImporter)
      .Default(None);
}
Ejemplo n.º 6
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()};
}
Ejemplo n.º 7
0
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(const NodePointer &node) {
  if (!node) return "";

  DemanglerPrinter printer;
  Remangler(printer).mangle(node.get());
  return std::move(printer).str();
}
Ejemplo n.º 8
0
bool Context::isThunkSymbol(llvm::StringRef MangledName) {
  if (isMangledName(MangledName)) {
    // First do a quick check
    if (MangledName.endswith("TA") ||  // partial application forwarder
        MangledName.endswith("Ta") ||  // ObjC partial application forwarder
        MangledName.endswith("To") ||  // swift-as-ObjC thunk
        MangledName.endswith("TO") ||  // ObjC-as-swift thunk
        MangledName.endswith("TR") ||  // reabstraction thunk helper function
        MangledName.endswith("Tr") ||  // reabstraction thunk
        MangledName.endswith("TW") ||  // protocol witness thunk
        MangledName.endswith("fC")) {  // allocating constructor

      // To avoid false positives, we need to fully demangle the symbol.
      NodePointer Nd = D->demangleSymbol(MangledName);
      if (!Nd || Nd->getKind() != Node::Kind::Global ||
          Nd->getNumChildren() == 0)
        return false;

      switch (Nd->getFirstChild()->getKind()) {
        case Node::Kind::ObjCAttribute:
        case Node::Kind::NonObjCAttribute:
        case Node::Kind::PartialApplyObjCForwarder:
        case Node::Kind::PartialApplyForwarder:
        case Node::Kind::ReabstractionThunkHelper:
        case Node::Kind::ReabstractionThunk:
        case Node::Kind::ProtocolWitness:
        case Node::Kind::Allocator:
          return true;
        default:
          break;
      }
    }
    return false;
  }

  if (MangledName.startswith("_T")) {
    // Old mangling.
    StringRef Remaining = MangledName.substr(2);
    if (Remaining.startswith("To") ||   // swift-as-ObjC thunk
        Remaining.startswith("TO") ||   // ObjC-as-swift thunk
        Remaining.startswith("PA_") ||  // partial application forwarder
        Remaining.startswith("PAo_")) { // ObjC partial application forwarder
      return true;
    }
  }
  return false;
}
Ejemplo n.º 9
0
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(const NodePointer &node) {
  if (!node) return "";

  std::string str;
  DemanglerPrinter printer(str);
  Remangler(printer).mangle(node.get());
  return str;
}
Ejemplo n.º 10
0
void Remangler::mangleSILBoxTypeWithLayout(Node *node) {
  assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout);
  assert(node->getNumChildren() == 1 || node->getNumChildren() == 3);
  Out << "XB";
  auto layout = node->getChild(0);
  assert(layout->getKind() == Node::Kind::SILBoxLayout);
  NodePointer genericArgs = nullptr;
  if (node->getNumChildren() == 3) {
    NodePointer signature = node->getChild(1);
    assert(signature->getKind() == Node::Kind::DependentGenericSignature);
    genericArgs = node->getChild(2);
    assert(genericArgs->getKind() == Node::Kind::TypeList);
    
    Out << 'G';
    mangleDependentGenericSignature(signature);
  }
  mangleSILBoxLayout(layout);
  if (genericArgs) {
    for (unsigned i = 0; i < genericArgs->getNumChildren(); ++i) {
      auto type = genericArgs->getChild(i);
      assert(genericArgs->getKind() == Node::Kind::Type);
      mangleType(type);
    }
    Out << '_';  
  }
}
Ejemplo n.º 11
0
static const TypeContextDescriptor *
_findNominalTypeDescriptor(Demangle::NodePointer node,
                           Demangle::Demangler &Dem) {
  const TypeContextDescriptor *foundNominal = nullptr;
  auto &T = TypeMetadataRecords.get();

  // If we have a symbolic reference to a context, resolve it immediately.
  NodePointer symbolicNode = node;
  if (symbolicNode->getKind() == Node::Kind::Type)
    symbolicNode = symbolicNode->getChild(0);
  if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
    return cast<TypeContextDescriptor>(
      (const ContextDescriptor *)symbolicNode->getIndex());

  auto mangledName =
    Demangle::mangleNode(node,
                         [&](const void *context) -> NodePointer {
                           return _buildDemanglingForContext(
                               (const ContextDescriptor *) context,
                               {}, false, Dem);
                         });

  // Look for an existing entry.
  // Find the bucket for the metadata entry.
  if (auto Value = T.NominalCache.find(mangledName))
    return Value->getDescription();

  // Check type metadata records
  foundNominal = _searchTypeMetadataRecords(T, node);

  // Check protocol conformances table. Note that this has no support for
  // resolving generic types yet.
  if (!foundNominal)
    foundNominal = _searchConformancesByMangledTypeName(node);

  if (foundNominal) {
    T.NominalCache.getOrInsert(mangledName, foundNominal);
  }

  return foundNominal;
}
Ejemplo n.º 12
0
std::string SpecializationMangler::finalize() {
  StringRef MangledSpecialization(Storage.data(), Storage.size());
  AttributeDemangler D;
  NodePointer TopLevel = D.createNode(Node::Kind::Global);
  D.demangleAndAddAsChildren(MangledSpecialization, TopLevel);

  StringRef FuncName = Function->getName();
  NodePointer FuncTopLevel = nullptr;
  if (FuncName.startswith(MANGLING_PREFIX_STR)) {
    FuncTopLevel = D.demangleSymbol(FuncName);
    assert(FuncTopLevel);
  }
  if (!FuncTopLevel) {
    FuncTopLevel = D.createNode(Node::Kind::Global);
    FuncTopLevel->addChild(D.createNode(Node::Kind::Identifier, FuncName), D);
  }
  for (NodePointer FuncChild : *FuncTopLevel) {
    TopLevel->addChild(FuncChild, D);
  }
  std::string mangledName = Demangle::mangleNode(TopLevel);
  verify(mangledName);
  return mangledName;
}
Ejemplo n.º 13
0
static const ProtocolDescriptor *
_findProtocolDescriptor(const Demangle::NodePointer &node,
                        Demangle::Demangler &Dem,
                        std::string &mangledName) {
  const ProtocolDescriptor *foundProtocol = nullptr;
  auto &T = Protocols.get();

  // If we have a symbolic reference to a context, resolve it immediately.
  NodePointer symbolicNode = node;
  if (symbolicNode->getKind() == Node::Kind::Type)
    symbolicNode = symbolicNode->getChild(0);
  if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
    return cast<ProtocolDescriptor>(
      (const ContextDescriptor *)symbolicNode->getIndex());

  mangledName =
    Demangle::mangleNode(node,
                         [&](const void *context) -> NodePointer {
                           return _buildDemanglingForContext(
                               (const ContextDescriptor *) context,
                               {}, Dem);
                         });

  // Look for an existing entry.
  // Find the bucket for the metadata entry.
  if (auto Value = T.ProtocolCache.find(mangledName))
    return Value->getDescription();

  // Check type metadata records
  foundProtocol = _searchProtocolRecords(T, node);

  if (foundProtocol) {
    T.ProtocolCache.getOrInsert(mangledName, foundProtocol);
  }

  return foundProtocol;
}
Ejemplo n.º 14
0
void Remangler::mangleFunctionSignatureSpecializationParam(Node *node) {
  if (!node->hasChildren()) {
    Out << "n_";
    return;
  }

  // The first child is always a kind that specifies the type of param that we
  // have.
  NodePointer firstChild = node->getChild(0);
  unsigned kindValue = firstChild->getIndex();
  auto kind = FunctionSigSpecializationParamKind(kindValue);

  switch (kind) {
  case FunctionSigSpecializationParamKind::ConstantPropFunction:
    Out << "cpfr";
    mangleIdentifier(node->getChild(1).get());
    Out << '_';
    return;
  case FunctionSigSpecializationParamKind::ConstantPropGlobal:
    Out << "cpg";
    mangleIdentifier(node->getChild(1).get());
    Out << '_';
    return;
  case FunctionSigSpecializationParamKind::ConstantPropInteger:
    Out << "cpi" << node->getChild(1)->getText() << '_';
    return;
  case FunctionSigSpecializationParamKind::ConstantPropFloat:
    Out << "cpfl" << node->getChild(1)->getText() << '_';
    return;
  case FunctionSigSpecializationParamKind::ConstantPropString: {
    Out << "cpse";
    StringRef encodingStr = node->getChild(1)->getText();
    if (encodingStr == "u8")
      Out << '0';
    else if (encodingStr == "u16")
      Out << '1';
    else
      unreachable("Unknown encoding");
    Out << 'v';
    mangleIdentifier(node->getChild(2).get());
    Out << '_';
    return;
  }
  case FunctionSigSpecializationParamKind::ClosureProp:
    Out << "cl";
    mangleIdentifier(node->getChild(1).get());
    for (unsigned i = 2, e = node->getNumChildren(); i != e; ++i) {
      mangleType(node->getChild(i).get());
    }
    Out << '_';
    return;
  case FunctionSigSpecializationParamKind::BoxToValue:
    Out << "i_";
    return;
  case FunctionSigSpecializationParamKind::BoxToStack:
    Out << "k_";
    return;
  default:
    if (kindValue &
        unsigned(FunctionSigSpecializationParamKind::Dead))
      Out << 'd';
    if (kindValue &
        unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed))
      Out << 'g';
    if (kindValue & unsigned(FunctionSigSpecializationParamKind::SROA))
      Out << 's';
    Out << '_';
    return;
  }
}
Ejemplo n.º 15
0
NodePointer Demangle::stripGenericArgsFromContextNode(NodePointer node,
                                                      NodeFactory &factory) {
  switch (node->getKind()) {
  case Demangle::Node::Kind::BoundGenericClass:
  case Demangle::Node::Kind::BoundGenericEnum:
  case Demangle::Node::Kind::BoundGenericStructure:
  case Demangle::Node::Kind::BoundGenericOtherNominalType:
    // Bound generic types have a 'Type' node under them, whose child is
    // the non-generic reference. If we don't see that structure, do nothing.
    if (node->getNumChildren() < 2 ||
        node->getChild(0)->getKind() != Demangle::Node::Kind::Type ||
        node->getChild(0)->getNumChildren() < 1)
      return node;

    // Strip generic arguments from that child, then return it.
    return stripGenericArgsFromContextNode(node->getChild(0)->getChild(0),
                                          factory);

  case Demangle::Node::Kind::Class:
  case Demangle::Node::Kind::Enum:
  case Demangle::Node::Kind::Structure:
  case Demangle::Node::Kind::OtherNominalType: {
    if (node->getNumChildren() < 2)
      return node;

    auto newContext = stripGenericArgsFromContextNode(node->getChild(0),
                                                      factory);
    if (newContext == node->getChild(0)) return node;

    auto newNode = factory.createNode(node->getKind());
    newNode->addChild(newContext, factory);
    for (unsigned i = 1, n = node->getNumChildren(); i != n; ++i)
      newNode->addChild(node->getChild(i), factory);
    return newNode;
  }
      
  case Demangle::Node::Kind::Extension: {
    // Strip generic arguments from the extended type.
    if (node->getNumChildren() < 2)
      return node;
    
    auto newExtended = stripGenericArgsFromContextNode(node->getChild(1),
                                                       factory);
    if (newExtended == node->getChild(1)) return node;
    
    auto newNode = factory.createNode(Node::Kind::Extension);
    newNode->addChild(node->getChild(0), factory);
    newNode->addChild(newExtended, factory);
    if (node->getNumChildren() == 3)
      newNode->addChild(node->getChild(2), factory);
    return newNode;
  }

  case Demangle::Node::Kind::Module:
    // Modules terminate the recursion.
    return node;

  default:
    // FIXME: Handle local contexts.
    return node;
  }
}
Ejemplo n.º 16
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];
  }
}
Ejemplo n.º 17
0
NodePointer Remangler::getUnspecialized(Node *node) {
  switch (node->getKind()) {
  case Node::Kind::Structure:
  case Node::Kind::Enum:
  case Node::Kind::Class: {
    NodePointer result = NodeFactory::create(node->getKind());
    NodePointer parentOrModule = node->getChild(0);
    if (isSpecialized(parentOrModule.get()))
      result->addChild(getUnspecialized(parentOrModule.get()));
    else
      result->addChild(parentOrModule);
    result->addChild(node->getChild(1));
    return result;
  }

  case Node::Kind::BoundGenericStructure:
  case Node::Kind::BoundGenericEnum:
  case Node::Kind::BoundGenericClass: {
    NodePointer unboundType = node->getChild(0);
    assert(unboundType->getKind() == Node::Kind::Type);
    NodePointer nominalType = unboundType->getChild(0);
    if (isSpecialized(nominalType.get()))
      return getUnspecialized(nominalType.get());
    else
      return nominalType;
  }

  default:
    unreachable("bad nominal type kind");
  }
}
Ejemplo n.º 18
0
 ~AutoClear() { mPtr->Clear(); }
Ejemplo n.º 19
0
// Build a demangled type tree for a type.
Demangle::NodePointer
swift::_swift_buildDemanglingForMetadata(const Metadata *type,
                                         Demangle::Demangler &Dem) {
  using namespace Demangle;

  switch (type->getKind()) {
  case MetadataKind::Class:
  case MetadataKind::Enum:
  case MetadataKind::Optional:
  case MetadataKind::Struct:
    return _buildDemanglingForNominalType(type, Dem);
  case MetadataKind::ObjCClassWrapper: {
#if SWIFT_OBJC_INTEROP
    auto objcWrapper = static_cast<const ObjCClassWrapperMetadata *>(type);
    const char *className = class_getName(objcWrapper->getObjCClassObject());
    
    // ObjC classes mangle as being in the magic "__ObjC" module.
    auto module = Dem.createNode(Node::Kind::Module, "__ObjC");
    
    auto node = Dem.createNode(Node::Kind::Class);
    node->addChild(module, Dem);
    node->addChild(Dem.createNode(Node::Kind::Identifier,
                                       llvm::StringRef(className)), Dem);
    
    return node;
#else
    assert(false && "no ObjC interop");
    return nullptr;
#endif
  }
  case MetadataKind::ForeignClass: {
    auto foreign = static_cast<const ForeignClassMetadata *>(type);
    return Dem.demangleType(foreign->getName());
  }
  case MetadataKind::Existential: {
    auto exis = static_cast<const ExistentialTypeMetadata *>(type);
    
    std::vector<const ProtocolDescriptor *> protocols;
    protocols.reserve(exis->Protocols.NumProtocols);
    for (unsigned i = 0, e = exis->Protocols.NumProtocols; i < e; ++i)
      protocols.push_back(exis->Protocols[i]);

    auto type_list = Dem.createNode(Node::Kind::TypeList);
    auto proto_list = Dem.createNode(Node::Kind::ProtocolList);
    proto_list->addChild(type_list, Dem);

    // The protocol descriptors should be pre-sorted since the compiler will
    // only ever make a swift_getExistentialTypeMetadata invocation using
    // its canonical ordering of protocols.

    for (auto *protocol : protocols) {
      // The protocol name is mangled as a type symbol, with the _Tt prefix.
      StringRef ProtoName(protocol->Name);
      NodePointer protocolNode = Dem.demangleSymbol(ProtoName);

      // ObjC protocol names aren't mangled.
      if (!protocolNode) {
        auto module = Dem.createNode(Node::Kind::Module,
                                          MANGLING_MODULE_OBJC);
        auto node = Dem.createNode(Node::Kind::Protocol);
        node->addChild(module, Dem);
        node->addChild(Dem.createNode(Node::Kind::Identifier,
                                        llvm::StringRef(protocol->Name)), Dem);
        auto typeNode = Dem.createNode(Node::Kind::Type);
        typeNode->addChild(node, Dem);
        type_list->addChild(typeNode, Dem);
        continue;
      }

      // FIXME: We have to dig through a ridiculous number of nodes to get
      // to the Protocol node here.
      protocolNode = protocolNode->getChild(0); // Global -> TypeMangling
      protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
      protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
      protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
      protocolNode = protocolNode->getChild(0); // TypeList -> Type
      
      assert(protocolNode->getKind() == Node::Kind::Type);
      assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
      type_list->addChild(protocolNode, Dem);
    }

    if (auto superclass = exis->getSuperclassConstraint()) {
      // If there is a superclass constraint, we mangle it specially.
      auto result = Dem.createNode(Node::Kind::ProtocolListWithClass);
      auto superclassNode = _swift_buildDemanglingForMetadata(superclass, Dem);

      result->addChild(proto_list, Dem);
      result->addChild(superclassNode, Dem);
      return result;
    }

    if (exis->isClassBounded()) {
      // Check if the class constraint is implied by any of our
      // protocols.
      bool requiresClassImplicit = false;

      for (auto *protocol : protocols) {
        if (protocol->Flags.getClassConstraint()
            == ProtocolClassConstraint::Class)
          requiresClassImplicit = true;
      }

      // If it was implied, we don't do anything special.
      if (requiresClassImplicit)
        return proto_list;

      // If the existential type has an explicit AnyObject constraint,
      // we must mangle it as such.
      auto result = Dem.createNode(Node::Kind::ProtocolListWithAnyObject);
      result->addChild(proto_list, Dem);
      return result;
    }

    // Just a simple composition of protocols.
    return proto_list;
  }
  case MetadataKind::ExistentialMetatype: {
    auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
    auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,
                                                      Dem);
    auto node = Dem.createNode(Node::Kind::ExistentialMetatype);
    node->addChild(instance, Dem);
    return node;
  }
  case MetadataKind::Function: {
    auto func = static_cast<const FunctionTypeMetadata *>(type);

    Node::Kind kind;
    switch (func->getConvention()) {
    case FunctionMetadataConvention::Swift:
      kind = Node::Kind::FunctionType;
      break;
    case FunctionMetadataConvention::Block:
      kind = Node::Kind::ObjCBlock;
      break;
    case FunctionMetadataConvention::CFunctionPointer:
      kind = Node::Kind::CFunctionPointer;
      break;
    case FunctionMetadataConvention::Thin:
      kind = Node::Kind::ThinFunctionType;
      break;
    }
    
    std::vector<NodePointer> inputs;
    for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
      auto param = func->getParameter(i);
      auto flags = func->getParameterFlags(i);
      auto input = _swift_buildDemanglingForMetadata(param, Dem);

      if (flags.isInOut()) {
        NodePointer inout = Dem.createNode(Node::Kind::InOut);
        inout->addChild(input, Dem);
        input = inout;
      } else if (flags.isShared()) {
        NodePointer shared = Dem.createNode(Node::Kind::Shared);
        shared->addChild(input, Dem);
        input = shared;
      }
      inputs.push_back(input);
    }

    NodePointer totalInput = nullptr;
    switch (inputs.size()) {
    case 1:
      totalInput = inputs.front();
      break;

    // This covers both none and multiple parameters.
    default:
      auto tuple = Dem.createNode(Node::Kind::Tuple);
      for (auto &input : inputs)
        tuple->addChild(input, Dem);
      totalInput = tuple;
      break;
    }

    NodePointer args = Dem.createNode(Node::Kind::ArgumentTuple);
    args->addChild(totalInput, Dem);
    
    NodePointer resultTy = _swift_buildDemanglingForMetadata(func->ResultType,
                                                             Dem);
    NodePointer result = Dem.createNode(Node::Kind::ReturnType);
    result->addChild(resultTy, Dem);
    
    auto funcNode = Dem.createNode(kind);
    if (func->throws())
      funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
    funcNode->addChild(args, Dem);
    funcNode->addChild(result, Dem);
    return funcNode;
  }
  case MetadataKind::Metatype: {
    auto metatype = static_cast<const MetatypeMetadata *>(type);
    auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,
                                                      Dem);
    auto typeNode = Dem.createNode(Node::Kind::Type);
    typeNode->addChild(instance, Dem);
    auto node = Dem.createNode(Node::Kind::Metatype);
    node->addChild(typeNode, Dem);
    return node;
  }
  case MetadataKind::Tuple: {
    auto tuple = static_cast<const TupleTypeMetadata *>(type);
    const char *labels = tuple->Labels;
    auto tupleNode = Dem.createNode(Node::Kind::Tuple);
    for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
      auto elt = Dem.createNode(Node::Kind::TupleElement);

      // Add a label child if applicable:
      if (labels) {
        // Look for the next space in the labels string.
        if (const char *space = strchr(labels, ' ')) {
          // If there is one, and the label isn't empty, add a label child.
          if (labels != space) {
            auto eltName =
              Dem.createNode(Node::Kind::TupleElementName,
                                  llvm::StringRef(labels, space - labels));
            elt->addChild(eltName, Dem);
          }

          // Skip past the space.
          labels = space + 1;
        }
      }

      // Add the element type child.
      auto eltType =
        _swift_buildDemanglingForMetadata(tuple->getElement(i).Type, Dem);
      elt->addChild(eltType, Dem);

      // Add the completed element to the tuple.
      tupleNode->addChild(elt, Dem);
    }
    return tupleNode;
  }
  case MetadataKind::Opaque:
    // FIXME: Some opaque types do have manglings, but we don't have enough info
    // to figure them out.
  case MetadataKind::HeapLocalVariable:
  case MetadataKind::HeapGenericLocalVariable:
  case MetadataKind::ErrorObject:
    break;
  }
  // Not a type.
  return nullptr;
}
Ejemplo n.º 20
0
// Build a demangled type tree for a type.
Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *type) {
    using namespace Demangle;

    switch (type->getKind()) {
    case MetadataKind::Class: {
        auto classType = static_cast<const ClassMetadata *>(type);
        return _buildDemanglingForNominalType(Node::Kind::BoundGenericClass,
                                              type, classType->getDescription());
    }
    case MetadataKind::Enum:
    case MetadataKind::Optional: {
        auto structType = static_cast<const EnumMetadata *>(type);
        return _buildDemanglingForNominalType(Node::Kind::BoundGenericEnum,
                                              type, structType->Description);
    }
    case MetadataKind::Struct: {
        auto structType = static_cast<const StructMetadata *>(type);
        return _buildDemanglingForNominalType(Node::Kind::BoundGenericStructure,
                                              type, structType->Description);
    }
    case MetadataKind::ObjCClassWrapper: {
#if SWIFT_OBJC_INTEROP
        auto objcWrapper = static_cast<const ObjCClassWrapperMetadata *>(type);
        const char *className = class_getName((Class)objcWrapper->Class);

        // ObjC classes mangle as being in the magic "__ObjC" module.
        auto module = NodeFactory::create(Node::Kind::Module, "__ObjC");

        auto node = NodeFactory::create(Node::Kind::Class);
        node->addChild(module);
        node->addChild(NodeFactory::create(Node::Kind::Identifier,
                                           llvm::StringRef(className)));

        return node;
#else
        assert(false && "no ObjC interop");
        return nullptr;
#endif
    }
    case MetadataKind::ForeignClass: {
        auto foreign = static_cast<const ForeignClassMetadata *>(type);
        return Demangle::demangleTypeAsNode(foreign->getName(),
                                            strlen(foreign->getName()));
    }
    case MetadataKind::Existential: {
        auto exis = static_cast<const ExistentialTypeMetadata *>(type);
        NodePointer proto_list = NodeFactory::create(Node::Kind::ProtocolList);
        NodePointer type_list = NodeFactory::create(Node::Kind::TypeList);

        proto_list->addChild(type_list);

        std::vector<const ProtocolDescriptor *> protocols;
        protocols.reserve(exis->Protocols.NumProtocols);
        for (unsigned i = 0, e = exis->Protocols.NumProtocols; i < e; ++i)
            protocols.push_back(exis->Protocols[i]);

        // Sort the protocols by their mangled names.
        // The ordering in the existential type metadata is by metadata pointer,
        // which isn't necessarily stable across invocations.
        std::sort(protocols.begin(), protocols.end(),
        [](const ProtocolDescriptor *a, const ProtocolDescriptor *b) -> bool {
            return strcmp(a->Name, b->Name) < 0;
        });

        for (auto *protocol : protocols) {
            // The protocol name is mangled as a type symbol, with the _Tt prefix.
            auto protocolNode = demangleSymbolAsNode(protocol->Name,
                                strlen(protocol->Name));

            // ObjC protocol names aren't mangled.
            if (!protocolNode) {
                auto module = NodeFactory::create(Node::Kind::Module,
                                                  MANGLING_MODULE_OBJC);
                auto node = NodeFactory::create(Node::Kind::Protocol);
                node->addChild(module);
                node->addChild(NodeFactory::create(Node::Kind::Identifier,
                                                   llvm::StringRef(protocol->Name)));
                auto typeNode = NodeFactory::create(Node::Kind::Type);
                typeNode->addChild(node);
                type_list->addChild(typeNode);
                continue;
            }

            // FIXME: We have to dig through a ridiculous number of nodes to get
            // to the Protocol node here.
            protocolNode = protocolNode->getChild(0); // Global -> TypeMangling
            protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
            protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
            protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
            protocolNode = protocolNode->getChild(0); // TypeList -> Type

            assert(protocolNode->getKind() == Node::Kind::Type);
            assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
            type_list->addChild(protocolNode);
        }

        return proto_list;
    }
    case MetadataKind::ExistentialMetatype: {
        auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
        auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType);
        auto node = NodeFactory::create(Node::Kind::ExistentialMetatype);
        node->addChild(instance);
        return node;
    }
    case MetadataKind::Function: {
        auto func = static_cast<const FunctionTypeMetadata *>(type);

        Node::Kind kind;
        switch (func->getConvention()) {
        case FunctionMetadataConvention::Swift:
            kind = Node::Kind::FunctionType;
            break;
        case FunctionMetadataConvention::Block:
            kind = Node::Kind::ObjCBlock;
            break;
        case FunctionMetadataConvention::CFunctionPointer:
            kind = Node::Kind::CFunctionPointer;
            break;
        case FunctionMetadataConvention::Thin:
            kind = Node::Kind::ThinFunctionType;
            break;
        }

        std::vector<NodePointer> inputs;
        for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) {
            auto arg = func->getArguments()[i];
            auto input = _swift_buildDemanglingForMetadata(arg.getPointer());
            if (arg.getFlag()) {
                NodePointer inout = NodeFactory::create(Node::Kind::InOut);
                inout->addChild(input);
                input = inout;
            }
            inputs.push_back(input);
        }

        NodePointer totalInput;
        if (inputs.size() > 1) {
            auto tuple = NodeFactory::create(Node::Kind::NonVariadicTuple);
            for (auto &input : inputs)
                tuple->addChild(input);
            totalInput = tuple;
        } else {
            totalInput = inputs.front();
        }

        NodePointer args = NodeFactory::create(Node::Kind::ArgumentTuple);
        args->addChild(totalInput);

        NodePointer resultTy = _swift_buildDemanglingForMetadata(func->ResultType);
        NodePointer result = NodeFactory::create(Node::Kind::ReturnType);
        result->addChild(resultTy);

        auto funcNode = NodeFactory::create(kind);
        if (func->throws())
            funcNode->addChild(NodeFactory::create(Node::Kind::ThrowsAnnotation));
        funcNode->addChild(args);
        funcNode->addChild(result);
        return funcNode;
    }
    case MetadataKind::Metatype: {
        auto metatype = static_cast<const MetatypeMetadata *>(type);
        auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType);
        auto node = NodeFactory::create(Node::Kind::Metatype);
        node->addChild(instance);
        return node;
    }
    case MetadataKind::Tuple: {
        auto tuple = static_cast<const TupleTypeMetadata *>(type);
        auto tupleNode = NodeFactory::create(Node::Kind::NonVariadicTuple);
        for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
            auto elt = _swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
            tupleNode->addChild(elt);
        }
        return tupleNode;
    }
    case MetadataKind::Opaque:
    // FIXME: Some opaque types do have manglings, but we don't have enough info
    // to figure them out.
    case MetadataKind::HeapLocalVariable:
    case MetadataKind::HeapGenericLocalVariable:
    case MetadataKind::ErrorObject:
        break;
    }
    // Not a type.
    return nullptr;
}