/// 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; }
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()}; }
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]; } }