diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index 99e22f4ad2f46..97189dbd8ce4b 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -484,11 +484,6 @@ enum class OperatorKind { Infix, }; -/// Mangle an identifier using Swift's mangling rules. -void mangleIdentifier(const char *data, size_t length, - OperatorKind operatorKind, std::string &out, - bool usePunycode = true); - /// Remangle a demangled parse tree. std::string mangleNode(NodePointer root); @@ -511,9 +506,20 @@ llvm::StringRef mangleNode(NodePointer root, SymbolicResolver resolver, /// Remangle in the old mangling scheme. /// /// This is only used for objc-runtime names. -/// If \p BorrowFrom is specified, the initial bump pointer memory is -/// borrowed from the free memory of BorrowFrom. -std::string mangleNodeOld(NodePointer root, NodeFactory *BorrowFrom = nullptr); +std::string mangleNodeOld(NodePointer root); + +/// Remangle in the old mangling scheme. +/// +/// This is only used for objc-runtime names. +/// The returned string is owned by \p Factory. This means \p Factory must stay +/// alive as long as the returned string is used. +llvm::StringRef mangleNodeOld(NodePointer node, NodeFactory &Factory); + +/// Remangle in the old mangling scheme and embed the name in "_Tt_". +/// +/// The returned string is null terminated and owned by \p Factory. This means +/// \p Factory must stay alive as long as the returned string is used. +const char *mangleNodeAsObjcCString(NodePointer node, NodeFactory &Factory); /// Transform the node structure to a string. /// diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index 70d06608c1c92..aca002f21c41a 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -18,12 +18,12 @@ #include "swift/Demangling/Demangler.h" #include "swift/Demangling/Punycode.h" +#include "swift/Demangling/ManglingUtils.h" #include "swift/AST/Ownership.h" #include "swift/Strings.h" -#include +#include "RemanglerBase.h" #include #include -#include using namespace swift; using namespace Demangle; @@ -34,191 +34,10 @@ static void unreachable(const char *Message) { std::abort(); } -/// Translate the given operator character into its mangled form. -/// -/// Current operator characters: @/=-+*%<>!&|^~ and the special operator '..' -static char mangleOperatorChar(char op) { - switch (op) { - case '&': return 'a'; // 'and' - case '@': return 'c'; // 'commercial at sign' - case '/': return 'd'; // 'divide' - case '=': return 'e'; // 'equal' - case '>': return 'g'; // 'greater' - case '<': return 'l'; // 'less' - case '*': return 'm'; // 'multiply' - case '!': return 'n'; // 'negate' - case '|': return 'o'; // 'or' - case '+': return 'p'; // 'plus' - case '?': return 'q'; // 'question' - case '%': return 'r'; // 'remainder' - case '-': return 's'; // 'subtract' - case '~': return 't'; // 'tilde' - case '^': return 'x'; // 'xor' - case '.': return 'z'; // 'zperiod' (the z is silent) - default: - return op; - } -} - -static bool isNonAscii(StringRef str) { - for (unsigned char c : str) { - if (c >= 0x80) - return true; - } - return false; -} - -static char mangleOperatorKind(OperatorKind operatorKind) { - switch (operatorKind) { - case OperatorKind::NotOperator: unreachable("invalid"); - case OperatorKind::Infix: return 'i'; - case OperatorKind::Prefix: return 'p'; - case OperatorKind::Postfix: return 'P'; - } - unreachable("invalid"); -} - -static void mangleIdentifier(StringRef ident, OperatorKind operatorKind, - bool usePunycode, DemanglerPrinter &out) { - std::string punycodeBuf; - if (usePunycode) { - // If the identifier contains non-ASCII character, we mangle - // with an initial X and Punycode the identifier string. - if (isNonAscii(ident)) { - out << 'X'; - Punycode::encodePunycodeUTF8(ident, punycodeBuf); - ident = punycodeBuf; - } - } - - // Mangle normal identifiers as - // count identifier-char+ - // where the count is the number of characters in the identifier, - // and where individual identifier characters represent themselves. - if (operatorKind == OperatorKind::NotOperator) { - out << ident.size() << ident; - return; - } - - // Mangle operator identifiers as - // operator ::= 'o' operator-fixity count operator-char+ - // operator-fixity ::= 'p' // prefix - // operator-fixity ::= 'P' // postfix - // operator-fixity ::= 'i' // infix - // where the count is the number of characters in the operator, - // and where the individual operator characters are translated. - out << 'o' << mangleOperatorKind(operatorKind); - - // Mangle ASCII operators directly. - out << ident.size(); - for (char ch : ident) { - out << mangleOperatorChar(ch); - } -} - -void Demangle::mangleIdentifier(const char *data, size_t length, - OperatorKind operatorKind, - std::string &out, bool usePunycode) { - DemanglerPrinter printer; - ::mangleIdentifier(StringRef(data, length), operatorKind, - usePunycode, printer); - out = std::move(printer).str(); -} - -namespace { - struct DeepHasher { - size_t value = 0; - - void combine(size_t newValue) { - value = 33 * value + newValue; - } - - void hash(Node *node) { - combine((size_t) node->getKind()); - if (node->hasIndex()) { - combine(node->getIndex()); - } else if (node->hasText()) { - StringRef text = node->getText(); - for (char c : text) { - combine((unsigned char) c); - } - } - for (const auto &child : *node) { - hash(child); - } - } - }; -} // end anonymous namespace - -static size_t deepHash(Node *node) { - DeepHasher hasher; - hasher.hash(node); - return hasher.value; -} - -static bool deepEquals(Node *lhs, Node *rhs) { - if (lhs->getKind() != rhs->getKind()) - return false; - if (lhs->hasIndex()) { - if (!rhs->hasIndex()) - return false; - if (lhs->getIndex() != rhs->getIndex()) - return false; - } else if (lhs->hasText()) { - if (!rhs->hasText()) - return false; - if (lhs->getText() != rhs->getText()) - return false; - } else if (rhs->hasIndex() || rhs->hasText()) { - return false; - } - - if (lhs->getNumChildren() != rhs->getNumChildren()) - return false; - - for (auto li = lhs->begin(), ri = lhs->begin(), le = lhs->end(); - li != le; ++li, ++ri) { - if (!deepEquals(*li, *ri)) - return false; - } - - return true; -} - namespace { - struct SubstitutionEntry { - Node *TheNode; - size_t StoredHash; - - // Note that the constructor leaves this uninitialized. - - struct Hasher { - size_t operator()(const SubstitutionEntry &entry) const { - return entry.StoredHash; - } - }; - friend bool operator==(const SubstitutionEntry &lhs, - const SubstitutionEntry &rhs) { - return (lhs.StoredHash == rhs.StoredHash && - deepEquals(lhs.TheNode, lhs.TheNode)); - } - }; - - class Remangler { - DemanglerPrinter &Out; - - // We have to cons up temporary nodes sometimes when remangling - // nested generics. This factory owns them. - NodeFactory Factory; - - std::unordered_map Substitutions; + class Remangler : public RemanglerBase { public: - Remangler(DemanglerPrinter &out, - NodeFactory *BorrowFrom) : Out(out) { - if (BorrowFrom) - Factory.providePreallocatedMemory(*BorrowFrom); - } + Remangler(NodeFactory &Factory) : RemanglerBase(Factory) { } class EntityContext { bool AsContext = false; @@ -314,8 +133,6 @@ namespace { bool trySubstitution(Node *node, SubstitutionEntry &entry); bool mangleStandardSubstitution(Node *node); - void addSubstitution(const SubstitutionEntry &entry); - void resetSubstitutions(); void mangleDependentGenericParamIndex(Node *node); void mangleConstrainedType(Node *node); @@ -398,27 +215,19 @@ static NodePointer applyParamLabels(NodePointer LabelList, NodePointer OrigType, return Type; } -/// Reset the currently-active set of substitutions. This is useful -/// when part of the mangling is done independently, e.g. when an -/// optimization pass modifies a pass. -void Remangler::resetSubstitutions() { - Substitutions.clear(); -} - bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) { if (mangleStandardSubstitution(node)) return true; // Go ahead and initialize the substitution entry. - entry.TheNode = node; - entry.StoredHash = deepHash(node); + entry.setNode(node, /*treatAsIdentifier=*/ false); - auto it = Substitutions.find(entry); - if (it == Substitutions.end()) + int Idx = findSubstitution(entry); + if (Idx < 0) return false; - Out << 'S'; - mangleIndex(it->second); + Buffer << 'S'; + mangleIndex(Idx); return true; } @@ -436,7 +245,7 @@ bool Remangler::mangleStandardSubstitution(Node *node) { #define SUCCESS_IF_IS(VALUE, EXPECTED, SUBSTITUTION) \ do { \ if ((VALUE) == (EXPECTED)) { \ - Out << SUBSTITUTION; \ + Buffer << SUBSTITUTION; \ return true; \ } \ } while (0) @@ -485,12 +294,6 @@ bool Remangler::mangleStandardSubstitution(Node *node) { return false; } -void Remangler::addSubstitution(const SubstitutionEntry &entry) { - auto result = Substitutions.insert({entry, Substitutions.size()}); - assert(result.second); - (void) result; -} - void Remangler::mangleIdentifier(Node *node) { mangleIdentifier(node->getText(), OperatorKind::NotOperator); } @@ -504,7 +307,35 @@ void Remangler::mangleInfixOperator(Node *node) { mangleIdentifier(node->getText(), OperatorKind::Infix); } void Remangler::mangleIdentifier(StringRef ident, OperatorKind operatorKind) { - ::mangleIdentifier(ident, operatorKind, /*usePunycode*/ false, Out); + // Mangle normal identifiers as + // count identifier-char+ + // where the count is the number of characters in the identifier, + // and where individual identifier characters represent themselves. + if (operatorKind == OperatorKind::NotOperator) { + Buffer << ident.size() << ident; + return; + } + + // Mangle operator identifiers as + // operator ::= 'o' operator-fixity count operator-char+ + // operator-fixity ::= 'p' // prefix + // operator-fixity ::= 'P' // postfix + // operator-fixity ::= 'i' // infix + // where the count is the number of characters in the operator, + // and where the individual operator characters are translated. + Buffer << 'o'; + switch (operatorKind) { + case OperatorKind::NotOperator: unreachable("invalid"); + case OperatorKind::Infix: Buffer << 'i'; break; + case OperatorKind::Prefix: Buffer << 'p'; break; + case OperatorKind::Postfix: Buffer << 'P'; break; + } + + // Mangle ASCII operators directly. + Buffer << ident.size(); + for (char ch : ident) { + Buffer << Mangle::translateOperatorChar(ch); + } } void Remangler::mangleNumber(Node *node) { @@ -512,164 +343,64 @@ void Remangler::mangleNumber(Node *node) { } void Remangler::mangleIndex(Node::IndexType value) { if (value == 0) { - Out << '_'; + Buffer << '_'; } else { - Out << (value - 1) << '_'; + Buffer << (value - 1) << '_'; } } void Remangler::mangleGlobal(Node *node) { - Out << "_T"; + Buffer << "_T"; mangleChildNodes(node); } void Remangler::mangleSuffix(Node *node) { // Just add the suffix back on. - Out << node->getText(); + Buffer << node->getText(); } void Remangler::mangleGenericSpecialization(Node *node) { - Out << "TSg"; - mangleChildNodes(node); // GenericSpecializationParams - - // Specializations are just prepended to already-mangled names. - resetSubstitutions(); - - // Start another mangled name. - Out << "__T"; + unreachable("unsupported"); } void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) { - Out << "TSr"; - mangleChildNodes(node); // GenericSpecializationParams - - // Specializations are just prepended to already-mangled names. - resetSubstitutions(); - - // Start another mangled name. - Out << "__T"; + unreachable("unsupported"); } void Remangler::mangleInlinedGenericFunction(Node *node) { - Out << "TSi"; - mangleChildNodes(node); // GenericSpecializationParams - - // Specializations are just prepended to already-mangled names. - resetSubstitutions(); - - // Start another mangled name. - Out << "__T"; + unreachable("unsupported"); } void Remangler::mangleGenericPartialSpecialization(Node *node) { - unreachable("todo"); + unreachable("unsupported"); } void Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node) { - unreachable("todo"); + unreachable("unsupported"); } void Remangler::mangleGenericSpecializationParam(Node *node) { - // Should be a type followed by a series of protocol conformances. - mangleChildNodes(node); - Out << '_'; + unreachable("unsupported"); } void Remangler::mangleFunctionSignatureSpecialization(Node *node) { - Out << "TSf"; - mangleChildNodes(node); // FunctionSignatureSpecializationParams - - // Specializations are just prepended to already-mangled names. - resetSubstitutions(); - - // Start another mangled name. - Out << "__T"; + unreachable("unsupported"); } void Remangler::mangleSpecializationPassID(Node *node) { - Out << node->getIndex(); + unreachable("unsupported"); } void Remangler::mangleIsSerialized(Node *node) { - Out << "q"; + Buffer << "q"; } void Remangler::mangleFunctionSignatureSpecializationReturn(Node *node) { - mangleFunctionSignatureSpecializationParam(node); + unreachable("unsupported"); } 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)); - Out << '_'; - return; - case FunctionSigSpecializationParamKind::ConstantPropGlobal: - Out << "cpg"; - mangleIdentifier(node->getChild(1)); - 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)); - Out << '_'; - return; - } - case FunctionSigSpecializationParamKind::ClosureProp: - Out << "cl"; - mangleIdentifier(node->getChild(1)); - for (unsigned i = 2, e = node->getNumChildren(); i != e; ++i) { - mangleType(node->getChild(i)); - } - 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::GuaranteedToOwned)) - Out << 'o'; - if (kindValue & unsigned(FunctionSigSpecializationParamKind::SROA)) - Out << 's'; - Out << '_'; - return; - } + unreachable("unsupported"); } void Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node) { @@ -733,72 +464,72 @@ void Remangler::mangleProtocolConformance(Node *node) { } void Remangler::mangleObjCAttribute(Node *node) { - Out << "To"; + Buffer << "To"; } void Remangler::mangleNonObjCAttribute(Node *node) { - Out << "TO"; + Buffer << "TO"; } void Remangler::mangleDirectMethodReferenceAttribute(Node *node) { - Out << "Td"; + Buffer << "Td"; } void Remangler::mangleDynamicAttribute(Node *node) { - Out << "TD"; + Buffer << "TD"; } void Remangler::mangleVTableAttribute(Node *node) { - Out << "TV"; + Buffer << "TV"; } void Remangler::mangleGenericTypeMetadataPattern(Node *node) { - Out << "MP"; + Buffer << "MP"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataAccessFunction(Node *node) { - Out << "Ma"; + Buffer << "Ma"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataInstantiationCache(Node *node) { - Out << "MI"; + Buffer << "MI"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) { - Out << "Mi"; + Buffer << "Mi"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataSingletonInitializationCache(Node *node) { - Out << "Ml"; + Buffer << "Ml"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataCompletionFunction(Node *node) { - Out << "Mr"; + Buffer << "Mr"; mangleSingleChildNode(node); // type } void Remangler::mangleTypeMetadataLazyCache(Node *node) { - Out << "ML"; + Buffer << "ML"; mangleSingleChildNode(node); // type } void Remangler::mangleMetaclass(Node *node) { - Out << "Mm"; + Buffer << "Mm"; mangleSingleChildNode(node); // type } void Remangler::mangleClassMetadataBaseOffset(Node *node) { - Out << "Mo"; + Buffer << "Mo"; mangleSingleChildNode(node); // type } void Remangler::mangleNominalTypeDescriptor(Node *node) { - Out << "Mn"; + Buffer << "Mn"; mangleSingleChildNode(node); // type } @@ -807,22 +538,22 @@ void Remangler::manglePropertyDescriptor(Node *node) { } void Remangler::mangleTypeMetadata(Node *node) { - Out << "M"; + Buffer << "M"; mangleSingleChildNode(node); // type } void Remangler::mangleFullTypeMetadata(Node *node) { - Out << "Mf"; + Buffer << "Mf"; mangleChildNodes(node); // type } void Remangler::mangleProtocolDescriptor(Node *node) { - Out << "Mp"; + Buffer << "Mp"; mangleProtocolWithoutPrefix(node->begin()[0]); } void Remangler::mangleProtocolRequirementsBaseDescriptor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleProtocolWitnessTablePattern(Node *node) { @@ -830,39 +561,39 @@ void Remangler::mangleProtocolWitnessTablePattern(Node *node) { } void Remangler::mangleProtocolConformanceDescriptor(Node *node) { - Out << "Mc"; + Buffer << "Mc"; mangleProtocolConformance(node->begin()[0]); } void Remangler::mangleProtocolSelfConformanceDescriptor(Node *node) { - Out << "MS"; + Buffer << "MS"; mangleProtocol(node->begin()[0]); } void Remangler::manglePartialApplyForwarder(Node *node) { - Out << "PA__T"; + Buffer << "PA__T"; mangleSingleChildNode(node); // global } void Remangler::manglePartialApplyObjCForwarder(Node *node) { - Out << "PAo__T"; + Buffer << "PAo__T"; mangleSingleChildNode(node); // global } void Remangler::mangleMergedFunction(Node *node) { - Out << "Tm"; + Buffer << "Tm"; } void Remangler::mangleDynamicallyReplaceableFunctionImpl(Node *node) { - Out << "TI"; + Buffer << "TI"; } void Remangler::mangleDynamicallyReplaceableFunctionKey(Node *node) { - Out << "Tx"; + Buffer << "Tx"; } void Remangler::mangleDynamicallyReplaceableFunctionVar(Node *node) { - Out << "TX"; + Buffer << "TX"; } void Remangler::mangleDirectness(Node *node) { @@ -873,7 +604,7 @@ void Remangler::mangleDirectness(Node *node) { } unreachable("bad directness kind"); }; - Out << getChar(Directness(node->getIndex())); + Buffer << getChar(Directness(node->getIndex())); } void Remangler::mangleValueWitness(Node *node) { @@ -883,41 +614,41 @@ void Remangler::mangleValueWitness(Node *node) { case ValueWitnessKind::NAME: Code = #MANGLING; break; #include "swift/Demangling/ValueWitnessMangling.def" } - Out << 'w' << Code; + Buffer << 'w' << Code; mangleChildNode(node, 1); // type } void Remangler::mangleValueWitnessTable(Node *node) { - Out << "WV"; + Buffer << "WV"; mangleSingleChildNode(node); // type } void Remangler::mangleThrowsAnnotation(Node *node) { - Out << "z"; + Buffer << "z"; } void Remangler::mangleFieldOffset(Node *node) { - Out << "Wv"; + Buffer << "Wv"; mangleChildNodes(node); // directness, entity } void Remangler::mangleEnumCase(Node *node) { - Out << "WC"; + Buffer << "WC"; mangleSingleChildNode(node); // enum case } void Remangler::mangleProtocolSelfConformanceWitnessTable(Node *node) { - Out << "WS"; + Buffer << "WS"; mangleSingleChildNode(node); // protocol } void Remangler::mangleProtocolWitnessTable(Node *node) { - Out << "WP"; + Buffer << "WP"; mangleSingleChildNode(node); // protocol conformance } void Remangler::mangleGenericProtocolWitnessTable(Node *node) { - Out << "WG"; + Buffer << "WG"; mangleSingleChildNode(node); // protocol conformance } @@ -927,52 +658,52 @@ void Remangler::mangleResilientProtocolWitnessTable(Node *node) { void Remangler::mangleGenericProtocolWitnessTableInstantiationFunction( Node *node) { - Out << "WI"; + Buffer << "WI"; mangleSingleChildNode(node); // protocol conformance } void Remangler::mangleProtocolWitnessTableAccessor(Node *node) { - Out << "Wa"; + Buffer << "Wa"; mangleSingleChildNode(node); // protocol conformance } void Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node) { - Out << "Wl"; + Buffer << "Wl"; mangleChildNodes(node); // type, protocol conformance } void Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node) { - Out << "WL"; + Buffer << "WL"; mangleChildNodes(node); // type, protocol conformance } void Remangler::mangleAssociatedTypeDescriptor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleAssociatedConformanceDescriptor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleBaseConformanceDescriptor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) { - Out << "Wt"; + Buffer << "Wt"; mangleChildNodes(node); // protocol conformance, identifier } void Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) { - Out << "WT"; + Buffer << "WT"; assert(node->getNumChildren() == 3); mangleChildNode(node, 0); // protocol conformance mangleChildNode(node, 1); // type @@ -980,28 +711,28 @@ void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) { } void Remangler::mangleBaseWitnessTableAccessor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleReabstractionThunkHelper(Node *node) { - Out << "TR"; - if (node->getNumChildren() == 3) Out << 'G'; + Buffer << "TR"; + if (node->getNumChildren() == 3) Buffer << 'G'; mangleChildNodes(node); // generic signature?, type, type } void Remangler::mangleReabstractionThunk(Node *node) { - Out << "Tr"; - if (node->getNumChildren() == 3) Out << 'G'; + Buffer << "Tr"; + if (node->getNumChildren() == 3) Buffer << 'G'; mangleChildNodes(node); // generic signature?, type, type } void Remangler::mangleProtocolSelfConformanceWitness(Node *node) { - Out << "TS"; + Buffer << "TS"; mangleSingleChildNode(node); // entity } void Remangler::mangleProtocolWitness(Node *node) { - Out << "TW"; + Buffer << "TW"; mangleChildNodes(node); // protocol conformance, entity } @@ -1019,9 +750,9 @@ void Remangler::mangleSubscript(Node *node, EntityContext &ctx) { void Remangler::mangleAccessor(Node *storageNode, StringRef accessorCode, EntityContext &ctx) { - Out << 'F'; + Buffer << 'F'; mangleEntityContext(storageNode->getChild(0), ctx); - Out << accessorCode; + Buffer << accessorCode; auto mangleAccessorType = [&](unsigned TypeIndex) { auto LabelList = storageNode->getChild(TypeIndex); @@ -1165,7 +896,7 @@ void Remangler::mangleImplicitClosure(Node *node, EntityContext &ctx) { } void Remangler::mangleStatic(Node *node, EntityContext &ctx) { - Out << 'Z'; + Buffer << 'Z'; mangleEntityContext(node->getChild(0), ctx); } @@ -1173,9 +904,9 @@ void Remangler::mangleSimpleEntity(Node *node, char basicKind, StringRef entityKind, EntityContext &ctx) { assert(node->getNumChildren() == 1); - Out << basicKind; + Buffer << basicKind; mangleEntityContext(node->begin()[0], ctx); - Out << entityKind; + Buffer << entityKind; } void Remangler::mangleNamedEntity(Node *node, char basicKind, @@ -1183,9 +914,9 @@ void Remangler::mangleNamedEntity(Node *node, char basicKind, EntityContext &ctx, StringRef artificialPrivateDiscriminator) { assert(node->getNumChildren() == 2); - if (basicKind != '\0') Out << basicKind; + if (basicKind != '\0') Buffer << basicKind; mangleEntityContext(node->begin()[0], ctx); - Out << entityKind; + Buffer << entityKind; auto privateDiscriminator = ctx.takeAnonymousContextDiscriminator(); if (!privateDiscriminator.empty() && isdigit(privateDiscriminator[0])) @@ -1198,10 +929,8 @@ void Remangler::mangleNamedEntity(Node *node, char basicKind, auto name = node->getChild(1); if (!privateDiscriminator.empty() && name->getKind() == Node::Kind::Identifier) { - Out << 'P'; - ::mangleIdentifier(privateDiscriminator, - OperatorKind::NotOperator, - /*punycode*/ false, Out); + Buffer << 'P'; + mangleIdentifier(privateDiscriminator, OperatorKind::NotOperator); } mangle(name); } @@ -1210,9 +939,9 @@ void Remangler::mangleTypedEntity(Node *node, char basicKind, StringRef entityKind, EntityContext &ctx) { assert(node->getNumChildren() == 2 || node->getNumChildren() == 3); - Out << basicKind; + Buffer << basicKind; mangleEntityContext(node->begin()[0], ctx); - Out << entityKind; + Buffer << entityKind; if (node->begin()[1]->getKind() == Node::Kind::LabelList) { auto LabelList = node->begin()[1]; @@ -1227,9 +956,9 @@ void Remangler::mangleNamedAndTypedEntity(Node *node, char basicKind, StringRef entityKind, EntityContext &ctx) { assert(node->getNumChildren() == 3 || node->getNumChildren() == 4); - Out << basicKind; + Buffer << basicKind; mangleEntityContext(node->begin()[0], ctx); - Out << entityKind; + Buffer << entityKind; mangleChildNode(node, 1); // decl name / index if (node->begin()[2]->getKind() == Node::Kind::LabelList) { @@ -1285,7 +1014,7 @@ void Remangler::mangleEntityType(Node *node, EntityContext &ctx) { case Node::Kind::NoEscapeFunctionType: case Node::Kind::FunctionType: case Node::Kind::UncurriedFunctionType: { - Out << ((node->getKind() == Node::Kind::FunctionType || + Buffer << ((node->getKind() == Node::Kind::FunctionType || node->getKind() == Node::Kind::NoEscapeFunctionType) ? 'F' : 'f'); @@ -1306,12 +1035,12 @@ void Remangler::mangleEntityType(Node *node, EntityContext &ctx) { } void Remangler::mangleLocalDeclName(Node *node) { - Out << 'L'; + Buffer << 'L'; mangleChildNodes(node); // index, identifier } void Remangler::manglePrivateDeclName(Node *node) { - Out << 'P'; + Buffer << 'P'; mangleChildNodes(node); // identifier, identifier } @@ -1319,12 +1048,12 @@ void Remangler::mangleRelatedEntityDeclName(Node *node) { // Non-round-trip mangling: pretend we have a private discriminator "$A" for a // related entity "A". NodePointer kindNode = node->getFirstChild(); - Out << 'P' << (kindNode->getText().size() + 1) << '$' << kindNode->getText(); + Buffer << 'P' << (kindNode->getText().size() + 1) << '$' << kindNode->getText(); mangleChildNode(node, 1); } void Remangler::mangleTypeMangling(Node *node) { - Out << 't'; + Buffer << 't'; mangleSingleChildNode(node); // type } @@ -1342,37 +1071,37 @@ static bool stripPrefix(StringRef &string, const char (&data)[N]) { } void Remangler::mangleBuiltinTypeName(Node *node) { - Out << 'B'; + Buffer << 'B'; StringRef text = node->getText(); if (text == "Builtin.BridgeObject") { - Out << 'b'; + Buffer << 'b'; } else if (text == "Builtin.UnsafeValueBuffer") { - Out << 'B'; + Buffer << 'B'; } else if (text == "Builtin.UnknownObject") { - Out << 'O'; + Buffer << 'O'; } else if (text == "Builtin.NativeObject") { - Out << 'o'; + Buffer << 'o'; } else if (text == "Builtin.RawPointer") { - Out << 'p'; + Buffer << 'p'; } else if (text == "Builtin.Word") { - Out << 'w'; + Buffer << 'w'; } else if (stripPrefix(text, "Builtin.Int")) { - Out << 'i' << text << '_'; + Buffer << 'i' << text << '_'; } else if (stripPrefix(text, "Builtin.FPIEEE")) { - Out << 'f' << text << '_'; + Buffer << 'f' << text << '_'; } else if (stripPrefix(text, "Builtin.Vec")) { // Avoid using StringRef::split because its definition is not // provided in the header so that it requires linking with libSupport.a. size_t splitIdx = text.find('x'); - Out << 'v' << text.substr(0, splitIdx) << 'B'; + Buffer << 'v' << text.substr(0, splitIdx) << 'B'; auto element = text.substr(splitIdx).substr(1); if (element == "RawPointer") { - Out << 'p'; + Buffer << 'p'; } else if (stripPrefix(element, "Float")) { - Out << 'f' << element << '_'; + Buffer << 'f' << element << '_'; } else if (stripPrefix(element, "Int")) { - Out << 'i' << element << '_'; + Buffer << 'i' << element << '_'; } else { unreachable("unexpected builtin vector type"); } @@ -1386,42 +1115,42 @@ void Remangler::mangleTypeAlias(Node *node, EntityContext &ctx) { } void Remangler::mangleFunctionType(Node *node) { - Out << 'F'; + Buffer << 'F'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleUncurriedFunctionType(Node *node) { - Out << 'f'; + Buffer << 'f'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleObjCBlock(Node *node) { - Out << 'b'; + Buffer << 'b'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleCFunctionPointer(Node *node) { - Out << 'c'; + Buffer << 'c'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleAutoClosureType(Node *node) { - Out << 'K'; + Buffer << 'K'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleNoEscapeFunctionType(Node *node) { - Out << 'F'; + Buffer << 'F'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleEscapingAutoClosureType(Node *node) { - Out << 'K'; + Buffer << 'K'; mangleChildNodes(node); // argument tuple, result type } void Remangler::mangleThinFunctionType(Node *node) { - Out << "Xf"; + Buffer << "Xf"; mangleChildNodes(node); // argument tuple, result type } @@ -1434,22 +1163,22 @@ void Remangler::mangleReturnType(Node *node) { } void Remangler::mangleImplFunctionType(Node *node) { - Out << "XF"; + Buffer << "XF"; auto i = node->begin(), e = node->end(); if (i != e && (*i)->getKind() == Node::Kind::ImplConvention) { StringRef text = (*i)->getText(); i++; if (text == "@callee_unowned") { - Out << 'd'; + Buffer << 'd'; } else if (text == "@callee_guaranteed") { - Out << 'g'; + Buffer << 'g'; } else if (text == "@callee_owned") { - Out << 'o'; + Buffer << 'o'; } else { unreachable("bad callee convention"); } } else { - Out << 't'; + Buffer << 't'; } for (; i != e && (*i)->getKind() == Node::Kind::ImplFunctionAttribute; ++i) { @@ -1458,32 +1187,32 @@ void Remangler::mangleImplFunctionType(Node *node) { if (i != e && ((*i)->getKind() == Node::Kind::DependentGenericSignature || (*i)->getKind() == Node::Kind::DependentPseudogenericSignature)) { - Out << ((*i)->getKind() == Node::Kind::DependentGenericSignature + Buffer << ((*i)->getKind() == Node::Kind::DependentGenericSignature ? 'G' : 'g'); mangleDependentGenericSignature((*i)); i++; } - Out << '_'; + Buffer << '_'; for (; i != e && (*i)->getKind() == Node::Kind::ImplParameter; ++i) { mangleImplParameter(*i); } - Out << '_'; + Buffer << '_'; mangleNodes(i, e); // impl results - Out << '_'; + Buffer << '_'; } void Remangler::mangleImplFunctionAttribute(Node *node) { StringRef text = node->getText(); if (text == "@convention(block)") { - Out << "Cb"; + Buffer << "Cb"; } else if (text == "@convention(c)") { - Out << "Cc"; + Buffer << "Cc"; } else if (text == "@convention(method)") { - Out << "Cm"; + Buffer << "Cm"; } else if (text == "@convention(objc_method)") { - Out << "CO"; + Buffer << "CO"; } else if (text == "@convention(witness_method)") { - Out << "Cw"; + Buffer << "Cw"; } else { unreachable("bad impl-function-attribute"); } @@ -1496,7 +1225,7 @@ void Remangler::mangleImplParameter(Node *node) { void Remangler::mangleImplErrorResult(Node *node) { assert(node->getNumChildren() == 2); - Out << 'z'; + Buffer << 'z'; mangleChildNodes(node); // impl convention, type } @@ -1513,60 +1242,60 @@ void Remangler::mangleImplConvention(Node *node) { assert(node->getKind() == Node::Kind::ImplConvention); StringRef text = node->getText(); if (text == "@autoreleased") { - Out << 'a'; + Buffer << 'a'; } else if (text == "@unowned") { - Out << 'd'; + Buffer << 'd'; } else if (text == "@unowned_inner_pointer") { - Out << 'D'; // only in results + Buffer << 'D'; // only in results } else if (text == "@guaranteed") { - Out << 'g'; + Buffer << 'g'; } else if (text == "@deallocating") { - Out << 'e'; + Buffer << 'e'; } else if (text == "@in") { - Out << 'i'; // only in parameters + Buffer << 'i'; // only in parameters } else if (text == "@out") { - Out << 'i'; // only in results + Buffer << 'i'; // only in results } else if (text == "@inout") { - Out << 'l'; + Buffer << 'l'; } else if (text == "@owned") { - Out << 'o'; + Buffer << 'o'; } else { unreachable("invalid impl convention"); } } void Remangler::mangleDynamicSelf(Node *node) { - Out << 'D'; + Buffer << 'D'; mangleSingleChildNode(node); // type } void Remangler::mangleErrorType(Node *node) { - Out << "ERR"; + Buffer << "ERR"; } void Remangler::mangleSILBoxType(Node *node) { - Out << 'X' << 'b'; + Buffer << 'X' << 'b'; mangleSingleChildNode(node); } void Remangler::mangleMetatype(Node *node) { if (node->getNumChildren() == 1) { - Out << 'M'; + Buffer << 'M'; mangleSingleChildNode(node); // type } else { assert(node->getNumChildren() == 2); - Out << "XM"; + Buffer << "XM"; mangleChildNodes(node); // metatype representation, type } } void Remangler::mangleExistentialMetatype(Node *node) { if (node->getNumChildren() == 1) { - Out << "PM"; + Buffer << "PM"; mangleSingleChildNode(node); // type } else { assert(node->getNumChildren() == 2); - Out << "XPM"; + Buffer << "XPM"; mangleChildNodes(node); // metatype representation, type } } @@ -1574,11 +1303,11 @@ void Remangler::mangleExistentialMetatype(Node *node) { void Remangler::mangleMetatypeRepresentation(Node *node) { StringRef text = node->getText(); if (text == "@thin") { - Out << 't'; + Buffer << 't'; } else if (text == "@thick") { - Out << 'T'; + Buffer << 'T'; } else if (text == "@objc_metatype") { - Out << 'o'; + Buffer << 'o'; } else { unreachable("bad metatype representation"); } @@ -1586,7 +1315,7 @@ void Remangler::mangleMetatypeRepresentation(Node *node) { void Remangler::mangleProtocolList(Node *node) { // In its usual use as a type, this gets a prefix 'P'. - Out << 'P'; + Buffer << 'P'; mangleProtocolListWithoutPrefix(node); } @@ -1602,28 +1331,28 @@ void Remangler::mangleProtocolListWithoutPrefix(Node *node, if (additionalProto) { mangleProtocolWithoutPrefix(additionalProto); } - Out << '_'; + Buffer << '_'; } #define REF_STORAGE(Name, ...) \ void Remangler::mangle##Name(Node *node) { \ - Out << manglingOf(ReferenceOwnership::Name); \ + Buffer << manglingOf(ReferenceOwnership::Name); \ mangleSingleChildNode(node); /* type */ \ } #include "swift/AST/ReferenceStorage.def" void Remangler::mangleShared(Node *node) { - Out << 'h'; + Buffer << 'h'; mangleSingleChildNode(node); // type } void Remangler::mangleOwned(Node *node) { - Out << 'n'; + Buffer << 'n'; mangleSingleChildNode(node); // type } void Remangler::mangleInOut(Node *node) { - Out << 'R'; + Buffer << 'R'; mangleSingleChildNode(node); // type } @@ -1632,12 +1361,12 @@ void Remangler::mangleTuple(Node *node) { if (NumElems > 0 && node->getChild(NumElems - 1)->getFirstChild()->getKind() == Node::Kind::VariadicMarker) { - Out << 't'; + Buffer << 't'; } else { - Out << 'T'; + Buffer << 'T'; } mangleChildNodes(node); // tuple elements - Out << '_'; + Buffer << '_'; } void Remangler::mangleTupleElement(Node *node) { @@ -1649,7 +1378,7 @@ void Remangler::mangleTupleElementName(Node *node) { } void Remangler::mangleDependentGenericType(Node *node) { - Out << 'u'; + Buffer << 'u'; mangleChildNodes(node); // generic signature, type } @@ -1678,18 +1407,18 @@ void Remangler::mangleDependentGenericSignature(Node *node) { if (count->getIndex() > 0) mangleIndex(count->getIndex() - 1); else - Out << 'z'; + Buffer << 'z'; } mangle_requirements: if (i == e) { // no generic requirements - Out << 'r'; + Buffer << 'r'; return; } - Out << 'R'; + Buffer << 'R'; mangleNodes(i, e); // generic requirements - Out << 'r'; + Buffer << 'r'; } void Remangler::mangleDependentGenericParamCount(Node *node) { @@ -1712,13 +1441,13 @@ void Remangler::mangleDependentGenericConformanceRequirement(Node *node) { void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) { mangleConstrainedType(node->getChild(0)); - Out << 'z'; + Buffer << 'z'; mangle(node->getChild(1)); } void Remangler::mangleDependentGenericLayoutRequirement(Node *node) { mangleConstrainedType(node->getChild(0)); - Out << 'l'; + Buffer << 'l'; auto id = node->getChild(1)->getText(); auto size = -1; if (node->getNumChildren() > 2) { @@ -1728,11 +1457,11 @@ void Remangler::mangleDependentGenericLayoutRequirement(Node *node) { if (node->getNumChildren() > 3) { alignment = node->getChild(3)->getIndex(); } - Out << id; + Buffer << id; if (size >= 0) - Out << size; + Buffer << size; if (alignment >= 0) { - Out << "_" << alignment; + Buffer << "_" << alignment; } } @@ -1751,7 +1480,7 @@ void Remangler::mangleAssociatedType(Node *node) { assert(node->getNumChildren() == 1); mangleProtocolListWithoutPrefix(*node->begin()); } else { - Out << '_'; + Buffer << '_'; } } @@ -1762,9 +1491,9 @@ void Remangler::mangleDeclContext(Node *node) { void Remangler::mangleExtension(Node *node, EntityContext &ctx) { assert(node->getNumChildren() == 2 || node->getNumChildren() == 3); if (node->getNumChildren() == 3) { - Out << 'e'; + Buffer << 'e'; } else { - Out << 'E'; + Buffer << 'E'; } mangleEntityContext(node->begin()[0], ctx); // module if (node->getNumChildren() == 3) { @@ -1787,7 +1516,7 @@ void Remangler::mangleModule(Node *node, EntityContext &ctx) { if (trySubstitution(node, entry)) return; // Module types get an M prefix, but module contexts don't. - if (!ctx.isAsContext()) Out << 'M'; + if (!ctx.isAsContext()) Buffer << 'M'; mangleIdentifier(node->getText(), OperatorKind::NotOperator); addSubstitution(entry); } @@ -1795,16 +1524,16 @@ void Remangler::mangleModule(Node *node, EntityContext &ctx) { void Remangler::mangleAssociatedTypeRef(Node *node) { SubstitutionEntry entry; if (trySubstitution(node, entry)) return; - Out << "Q"; + Buffer << "Q"; mangleChildNodes(node); // type, identifier addSubstitution(entry); } void Remangler::mangleDependentMemberType(Node *node) { - std::vector members; + Vector members; Node *base = node; do { - members.push_back(base); + members.push_back(base, Factory); base = base->getFirstChild()->getFirstChild(); } while (base->getKind() == Node::Kind::DependentMemberType); @@ -1813,18 +1542,18 @@ void Remangler::mangleDependentMemberType(Node *node) { " and shouldn't need remangling"); assert(members.size() >= 1); if (members.size() == 1) { - Out << 'w'; + Buffer << 'w'; mangleDependentGenericParamIndex(base); mangle(members[0]->getChild(1)); } else { - Out << 'W'; + Buffer << 'W'; mangleDependentGenericParamIndex(base); for (unsigned i = 1, n = members.size(); i <= n; ++i) { Node *member = members[n - i]; mangle(member->getChild(1)); } - Out << '_'; + Buffer << '_'; } } @@ -1833,7 +1562,7 @@ void Remangler::mangleDependentAssociatedTypeRef(Node *node) { if (trySubstitution(node, entry)) return; if (node->getNumChildren() > 1) { - Out << 'P'; + Buffer << 'P'; mangleProtocolWithoutPrefix(node->getChild(1)); } mangleIdentifier(node->getFirstChild()); @@ -1846,7 +1575,7 @@ void Remangler::mangleDependentGenericParamIndex(Node *node) { auto index = node->getChild(1)->getIndex(); if (depth != 0) { - Out << 'd'; + Buffer << 'd'; mangleIndex(depth - 1); mangleIndex(index); return; @@ -1857,17 +1586,17 @@ void Remangler::mangleDependentGenericParamIndex(Node *node) { } // depth == index == 0 - Out << 'x'; + Buffer << 'x'; } void Remangler::mangleDependentGenericParamType(Node *node) { if (node->getChild(0)->getIndex() == 0 && node->getChild(1)->getIndex() == 0) { - Out << 'x'; + Buffer << 'x'; return; } - Out << 'q'; + Buffer << 'q'; mangleDependentGenericParamIndex(node); } @@ -1902,7 +1631,7 @@ void Remangler::mangleGenericArgs(Node *node, EntityContext &ctx) { mangleGenericArgs(parentOrModule, ctx); // No generic arguments at this level - Out << '_'; + Buffer << '_'; break; } @@ -1932,7 +1661,7 @@ void Remangler::mangleGenericArgs(Node *node, EntityContext &ctx) { void Remangler::mangleAnyNominalType(Node *node, EntityContext &ctx) { if (isSpecialized(node)) { - Out << 'G'; + Buffer << 'G'; NodePointer unboundType = getUnspecialized(node, Factory); @@ -2028,30 +1757,30 @@ void Remangler::mangleBoundGenericFunction(Node *node) { void Remangler::mangleTypeList(Node *node) { mangleChildNodes(node); // all types - Out << '_'; + Buffer << '_'; } void Remangler::mangleLabelList(Node *node) { if (node->getNumChildren() == 0) - Out << 'y'; + Buffer << 'y'; else mangleChildNodes(node); } void Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node) { - Out << "MRb"; + Buffer << "MRb"; } void Remangler::mangleReflectionMetadataFieldDescriptor(Node *node) { - Out << "MRf"; + Buffer << "MRf"; } void Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node) { - Out << "MRa"; + Buffer << "MRa"; } void Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node) { - Out << "MRc"; + Buffer << "MRc"; } void Remangler::mangleGenericTypeParamDecl(Node *node) { @@ -2059,31 +1788,31 @@ void Remangler::mangleGenericTypeParamDecl(Node *node) { } void Remangler::mangleCurryThunk(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleDispatchThunk(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleMethodDescriptor(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleMethodLookupFunction(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleObjCMetadataUpdateFunction(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleEmptyList(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleFirstElementMarker(Node *node) { - Out << ""; + Buffer << ""; } void Remangler::mangleVariadicMarker(Node *node) { @@ -2091,87 +1820,87 @@ void Remangler::mangleVariadicMarker(Node *node) { } void Remangler::mangleOutlinedCopy(Node *node) { - Out << "Wy"; + Buffer << "Wy"; mangleChildNodes(node); } void Remangler::mangleOutlinedConsume(Node *node) { - Out << "We"; + Buffer << "We"; mangleChildNodes(node); } void Remangler::mangleOutlinedRetain(Node *node) { - Out << "Wr"; + Buffer << "Wr"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedRelease(Node *node) { - Out << "Ws"; + Buffer << "Ws"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedInitializeWithTake(Node *node) { - Out << "Wb"; + Buffer << "Wb"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedInitializeWithCopy(Node *node) { - Out << "Wc"; + Buffer << "Wc"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedAssignWithTake(Node *node) { - Out << "Wd"; + Buffer << "Wd"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedAssignWithCopy(Node *node) { - Out << "Wf"; + Buffer << "Wf"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedDestroy(Node *node) { - Out << "Wh"; + Buffer << "Wh"; mangleSingleChildNode(node); } void Remangler::mangleOutlinedVariable(Node *node) { - Out << "Tv" << node->getIndex(); + Buffer << "Tv" << node->getIndex(); mangleSingleChildNode(node); } void Remangler::mangleOutlinedBridgedMethod(Node *node) { - Out << "Te" << node->getText(); + Buffer << "Te" << node->getText(); mangleSingleChildNode(node); } void Remangler::mangleCoroutineContinuationPrototype(Node *node) { - Out << "TC"; + Buffer << "TC"; mangleChildNodes(node); } void Remangler::mangleKeyPathGetterThunkHelper(Node *node) { - Out << "TK"; + Buffer << "TK"; mangleChildNodes(node); } void Remangler::mangleKeyPathSetterThunkHelper(Node *node) { - Out << "Tk"; + Buffer << "Tk"; mangleChildNodes(node); } void Remangler::mangleKeyPathEqualsThunkHelper(Node *node) { - Out << "TH"; + Buffer << "TH"; mangleChildNodes(node); } void Remangler::mangleKeyPathHashThunkHelper(Node *node) { - Out << "Th"; + Buffer << "Th"; mangleChildNodes(node); } void Remangler::mangleProtocolListWithClass(Node *node) { - Out << "Xc"; + Buffer << "Xc"; mangleChildNode(node, 1); mangleProtocolListWithoutPrefix(node->getChild(0)); } @@ -2180,19 +1909,19 @@ void Remangler::mangleProtocolListWithAnyObject(Node *node) { Node *P = Factory.createNode(Node::Kind::Protocol); P->addChild(Factory.createNode(Node::Kind::Module, "Swift"), Factory); P->addChild(Factory.createNode(Node::Kind::Identifier, "AnyObject"), Factory); - Out << "P"; + Buffer << "P"; mangleProtocolListWithoutPrefix(node->getChild(0), /*additionalProto*/ P); } void Remangler::mangleVTableThunk(Node *node) { - Out << "TV"; + Buffer << "TV"; mangleChildNodes(node); } void Remangler::mangleSILBoxTypeWithLayout(Node *node) { assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout); assert(node->getNumChildren() == 1 || node->getNumChildren() == 3); - Out << "XB"; + Buffer << "XB"; auto layout = node->getChild(0); assert(layout->getKind() == Node::Kind::SILBoxLayout); NodePointer genericArgs = nullptr; @@ -2202,7 +1931,7 @@ void Remangler::mangleSILBoxTypeWithLayout(Node *node) { genericArgs = node->getChild(2); assert(genericArgs->getKind() == Node::Kind::TypeList); - Out << 'G'; + Buffer << 'G'; mangleDependentGenericSignature(signature); } mangleSILBoxLayout(layout); @@ -2212,7 +1941,7 @@ void Remangler::mangleSILBoxTypeWithLayout(Node *node) { assert(genericArgs->getKind() == Node::Kind::Type); mangleType(type); } - Out << '_'; + Buffer << '_'; } } @@ -2224,18 +1953,18 @@ void Remangler::mangleSILBoxLayout(Node *node) { mangle(node->getChild(i)); } - Out << '_'; + Buffer << '_'; } void Remangler::mangleSILBoxMutableField(Node *node) { - Out << 'm'; + Buffer << 'm'; assert(node->getNumChildren() == 1 && node->getChild(0)->getKind() == Node::Kind::Type); mangleType(node->getChild(0)); } void Remangler::mangleSILBoxImmutableField(Node *node) { - Out << 'i'; + Buffer << 'i'; assert(node->getNumChildren() == 1 && node->getChild(0)->getKind() == Node::Kind::Type); mangleType(node->getChild(0)); @@ -2286,10 +2015,33 @@ void Remangler::mangleSugaredParen(Node *node) { } /// The top-level interface to the remangler. -std::string Demangle::mangleNodeOld(NodePointer node, NodeFactory *BorrowFrom) { +std::string Demangle::mangleNodeOld(NodePointer node) { + if (!node) return ""; + + NodeFactory Factory; + Remangler remangler(Factory); + remangler.mangle(node); + + return remangler.str(); +} + +llvm::StringRef Demangle::mangleNodeOld(NodePointer node, NodeFactory &Factory) { if (!node) return ""; - DemanglerPrinter printer; - Remangler(printer, BorrowFrom).mangle(node); - return std::move(printer).str(); + Remangler remangler(Factory); + remangler.mangle(node); + + return remangler.getBufferStr(); +} + +const char *Demangle::mangleNodeAsObjcCString(NodePointer node, + NodeFactory &Factory) { + assert(node); + + Remangler remangler(Factory); + remangler.append("_Tt"); + remangler.mangle(node); + remangler.append(StringRef("_", 2)); // Include the trailing 0 char. + + return remangler.getBufferStr().data(); } diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 23e28d0a7dd18..6f1170976ea09 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -24,10 +24,9 @@ #include "swift/Strings.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include +#include "RemanglerBase.h" #include #include -#include using namespace swift; using namespace Demangle; @@ -39,83 +38,61 @@ static void unreachable(const char *Message) { std::abort(); } -static StringRef getTextForSubstitution(Node *node, std::string &tmp) { +static char getCharOfNodeText(Node *node, unsigned idx) { switch (node->getKind()) { - case Node::Kind::InfixOperator: - case Node::Kind::PrefixOperator: - case Node::Kind::PostfixOperator: - tmp = Mangle::translateOperator(node->getText()); - return tmp; - default: - return node->getText(); + case Node::Kind::InfixOperator: + case Node::Kind::PrefixOperator: + case Node::Kind::PostfixOperator: + return Mangle::translateOperatorChar(node->getText()[idx]); + default: + return node->getText()[idx]; } } -namespace { - -class SubstitutionEntry { - Node *TheNode = nullptr; - size_t StoredHash = 0; - bool treatAsIdentifier = false; - -public: - void setNode(Node *node, bool treatAsIdentifier) { - this->treatAsIdentifier = treatAsIdentifier; - TheNode = node; - deepHash(node); - } - - struct Hasher { - size_t operator()(const SubstitutionEntry &entry) const { - return entry.StoredHash; - } - }; - -private: - friend bool operator==(const SubstitutionEntry &lhs, - const SubstitutionEntry &rhs) { - if (lhs.StoredHash != rhs.StoredHash) - return false; - if (lhs.treatAsIdentifier != rhs.treatAsIdentifier) +bool SubstitutionEntry::identifierEquals(Node *lhs, Node *rhs) { + unsigned length = lhs->getText().size(); + if (rhs->getText().size() != length) + return false; + // The fast path. + if (lhs->getKind() == rhs->getKind()) + return lhs->getText() == rhs->getText(); + // The slow path. + for (unsigned i = 0; i < length; ++i) { + if (getCharOfNodeText(lhs, i) != getCharOfNodeText(rhs, i)) return false; - if (lhs.treatAsIdentifier) { - std::string tmp1, tmp2; - return (getTextForSubstitution(lhs.TheNode, tmp1) == - getTextForSubstitution(rhs.TheNode, tmp2)); - } - return lhs.deepEquals(lhs.TheNode, rhs.TheNode); - } - - void combineHash(size_t newValue) { - StoredHash = 33 * StoredHash + newValue; - } - - void combineHash(StringRef Text) { - for (char c : Text) { - combineHash((unsigned char) c); - } } + return true; +} - void deepHash(Node *node) { - if (treatAsIdentifier) { - combineHash((size_t) Node::Kind::Identifier); - std::string tmp; - combineHash(getTextForSubstitution(node, tmp)); +void SubstitutionEntry::deepHash(Node *node) { + if (treatAsIdentifier) { + combineHash((size_t) Node::Kind::Identifier); + assert(node->hasText()); + switch (node->getKind()) { + case Node::Kind::InfixOperator: + case Node::Kind::PrefixOperator: + case Node::Kind::PostfixOperator: + for (char c : node->getText()) { + combineHash((unsigned char)translateOperatorChar(c)); + } return; + default: + break; } + } else { combineHash((size_t) node->getKind()); - if (node->hasIndex()) { - combineHash(node->getIndex()); - } else if (node->hasText()) { - combineHash(node->getText()); - } - for (Node *child : *node) { - deepHash(child); + } + if (node->hasIndex()) { + combineHash(node->getIndex()); + } else if (node->hasText()) { + for (char c : node->getText()) { + combineHash((unsigned char) c); } } - - bool deepEquals(Node *lhs, Node *rhs) const; -}; + for (Node *child : *node) { + deepHash(child); + } +} bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const { if (lhs->getKind() != rhs->getKind()) @@ -146,49 +123,42 @@ bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const { return true; } -/// The output string of the Demangler. -/// -/// It's allocating the string with the provided Factory. -struct RemanglerBuffer { - CharVector Stream; - NodeFactory &Factory; - - RemanglerBuffer(NodeFactory &Factory) : Factory(Factory) { - Stream.init(Factory, 32); - } - - RemanglerBuffer &operator<<(char c) & { - Stream.push_back(c, Factory); - return *this; - } - - RemanglerBuffer &operator<<(llvm::StringRef Value) & { - Stream.append(Value, Factory); - return *this; - } +// Find a substitution and return its index. +// Returns -1 if no substitution is found. +int RemanglerBase::findSubstitution(const SubstitutionEntry &entry) { + // First search in InlineSubstitutions. + SubstitutionEntry *result + = std::find(InlineSubstitutions, InlineSubstitutions + NumInlineSubsts, + entry); + if (result != InlineSubstitutions + NumInlineSubsts) + return result - InlineSubstitutions; - RemanglerBuffer &operator<<(int n) & { - Stream.append(n, Factory); - return *this; - } + // Then search in OverflowSubstitutions. + auto it = OverflowSubstitutions.find(entry); + if (it == OverflowSubstitutions.end()) + return -1; - RemanglerBuffer &operator<<(unsigned n) & { - Stream.append((unsigned long long)n, Factory); - return *this; - } + return it->second; +} - RemanglerBuffer &operator<<(unsigned long n) & { - Stream.append((unsigned long long)n, Factory); - return *this; +void RemanglerBase::addSubstitution(const SubstitutionEntry &entry) { + assert(findSubstitution(entry) < 0); + if (NumInlineSubsts < InlineSubstCapacity) { + // There is still free space in NumInlineSubsts. + assert(OverflowSubstitutions.empty()); + InlineSubstitutions[NumInlineSubsts++] = entry; + return; } + // We have to add the entry to OverflowSubstitutions. + unsigned Idx = OverflowSubstitutions.size() + InlineSubstCapacity; + auto result = OverflowSubstitutions.insert({entry, Idx}); + assert(result.second); + (void) result; +} - RemanglerBuffer &operator<<(unsigned long long n) & { - Stream.append(n, Factory); - return *this; - } -}; +namespace { -class Remangler { +class Remangler : public RemanglerBase { template friend void Mangle::mangleIdentifier(Mangler &M, StringRef ident); friend class Mangle::SubstitutionMerging; @@ -200,28 +170,8 @@ class Remangler { static const size_t MaxNumWords = 26; - // An efficient hash-map implementation in the spirit of llvm's SmallPtrSet: - // The first 16 substitutions are stored in an inline-allocated array to avoid - // malloc calls in the common case. - // Lookup is still reasonable fast because there are max 16 elements in the - // array. - static const size_t InlineSubstCapacity = 16; - SubstitutionEntry InlineSubstitutions[InlineSubstCapacity]; - size_t NumInlineSubsts = 0; - - // The "overflow" for InlineSubstitutions. Only if InlineSubstitutions is - // full, new substitutions are stored in OverflowSubstitutions. - std::unordered_map OverflowSubstitutions; - SubstitutionMerging SubstMerging; - // We have to cons up temporary nodes sometimes when remangling - // nested generics. This factory owns them. - NodeFactory &Factory; - - RemanglerBuffer Buffer; - // A callback for resolving symbolic references. SymbolicResolver Resolver; @@ -233,28 +183,6 @@ class Remangler { Words.push_back(word, Factory); } - // Find a substitution and return its index. - // Returns -1 if no substitution is found. - int findSubstitution(const SubstitutionEntry &entry) { - // First search in InlineSubstitutions. - SubstitutionEntry *result - = std::find(InlineSubstitutions, InlineSubstitutions + NumInlineSubsts, - entry); - if (result != InlineSubstitutions + NumInlineSubsts) - return result - InlineSubstitutions; - - // Then search in OverflowSubstitutions. - auto it = OverflowSubstitutions.find(entry); - if (it == OverflowSubstitutions.end()) - return -1; - - return it->second; - } - - StringRef getBufferStr() const { return Buffer.Stream.str(); } - - void resetBuffer(size_t toPos) { Buffer.Stream.resetSize(toPos); } - template friend void mangleIdentifier(Mangler &M, StringRef ident); @@ -356,7 +284,6 @@ class Remangler { bool trySubstitution(Node *node, SubstitutionEntry &entry, bool treatAsIdentifier = false); - void addSubstitution(const SubstitutionEntry &entry); void mangleIdentifierImpl(Node *node, bool isOperator); @@ -391,7 +318,7 @@ class Remangler { public: Remangler(SymbolicResolver Resolver, NodeFactory &Factory) - : Factory(Factory), Buffer(Factory), Resolver(Resolver) { } + : RemanglerBase(Factory), Resolver(Resolver) { } void mangle(Node *node) { switch (node->getKind()) { @@ -400,14 +327,6 @@ class Remangler { } unreachable("bad demangling tree node"); } - - StringRef strRef() { - return Buffer.Stream.str(); - } - - std::string str() { - return strRef().str(); - } }; bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry, @@ -434,21 +353,6 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry, return true; } -void Remangler::addSubstitution(const SubstitutionEntry &entry) { - assert(findSubstitution(entry) < 0); - if (NumInlineSubsts < InlineSubstCapacity) { - // There is still free space in NumInlineSubsts. - assert(OverflowSubstitutions.empty()); - InlineSubstitutions[NumInlineSubsts++] = entry; - return; - } - // We have to add the entry to OverflowSubstitutions. - unsigned Idx = OverflowSubstitutions.size() + InlineSubstCapacity; - auto result = OverflowSubstitutions.insert({entry, Idx}); - assert(result.second); - (void) result; -} - void Remangler::mangleIdentifierImpl(Node *node, bool isOperator) { SubstitutionEntry entry; if (trySubstitution(node, entry, /*treatAsIdentifier*/ true)) return; @@ -514,9 +418,9 @@ std::pair Remangler::mangleConstrainedType(Node *node) { if (trySubstitution(node, entry)) return {-1, nullptr}; - std::vector Chain; + Vector Chain; while (node->getKind() == Node::Kind::DependentMemberType) { - Chain.push_back(node->getChild(1)); + Chain.push_back(node->getChild(1), Factory); node = getChildOfType(node->getFirstChild()); } assert(node->getKind() == Node::Kind::DependentGenericParamType); @@ -2446,7 +2350,7 @@ Demangle::mangleNode(NodePointer node, SymbolicResolver resolver, Remangler remangler(resolver, Factory); remangler.mangle(node); - return remangler.strRef(); + return remangler.getBufferStr(); } bool Demangle::isSpecialized(Node *node) { diff --git a/lib/Demangling/RemanglerBase.h b/lib/Demangling/RemanglerBase.h new file mode 100644 index 0000000000000..d0f9fc3f56bc2 --- /dev/null +++ b/lib/Demangling/RemanglerBase.h @@ -0,0 +1,169 @@ +//===--- Demangler.h - String to Node-Tree Demangling -----------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file contains shared code between the old and new remanglers. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_DEMANGLING_BASEREMANGLER_H +#define SWIFT_DEMANGLING_BASEREMANGLER_H + +#include "swift/Demangling/Demangler.h" +#include + +using namespace swift::Demangle; +using llvm::StringRef; + +namespace swift { +namespace Demangle { + +// An entry in the remangler's substitution map. +class SubstitutionEntry { + Node *TheNode = nullptr; + size_t StoredHash = 0; + bool treatAsIdentifier = false; + +public: + void setNode(Node *node, bool treatAsIdentifier) { + this->treatAsIdentifier = treatAsIdentifier; + TheNode = node; + deepHash(node); + } + + struct Hasher { + size_t operator()(const SubstitutionEntry &entry) const { + return entry.StoredHash; + } + }; + +private: + friend bool operator==(const SubstitutionEntry &lhs, + const SubstitutionEntry &rhs) { + if (lhs.StoredHash != rhs.StoredHash) + return false; + if (lhs.treatAsIdentifier != rhs.treatAsIdentifier) + return false; + if (lhs.treatAsIdentifier) { + return identifierEquals(lhs.TheNode, rhs.TheNode); + } + return lhs.deepEquals(lhs.TheNode, rhs.TheNode); + } + + static bool identifierEquals(Node *lhs, Node *rhs); + + void combineHash(size_t newValue) { + StoredHash = 33 * StoredHash + newValue; + } + + void deepHash(Node *node); + + bool deepEquals(Node *lhs, Node *rhs) const; +}; + +/// The output string for the Remangler. +/// +/// It's allocating the string with the provided Factory. +class RemanglerBuffer { + CharVector Stream; + NodeFactory &Factory; + +public: + RemanglerBuffer(NodeFactory &Factory) : Factory(Factory) { + Stream.init(Factory, 32); + } + + void reset(size_t toPos) { Stream.resetSize(toPos); } + + StringRef strRef() const { return Stream.str(); } + + RemanglerBuffer &operator<<(char c) & { + Stream.push_back(c, Factory); + return *this; + } + + RemanglerBuffer &operator<<(llvm::StringRef Value) & { + Stream.append(Value, Factory); + return *this; + } + + RemanglerBuffer &operator<<(int n) & { + Stream.append(n, Factory); + return *this; + } + + RemanglerBuffer &operator<<(unsigned n) & { + Stream.append((unsigned long long)n, Factory); + return *this; + } + + RemanglerBuffer &operator<<(unsigned long n) & { + Stream.append((unsigned long long)n, Factory); + return *this; + } + + RemanglerBuffer &operator<<(unsigned long long n) & { + Stream.append(n, Factory); + return *this; + } +}; + +/// The base class for the old and new remangler. +class RemanglerBase { +protected: + // Used to allocate temporary nodes and the output string (in Buffer). + NodeFactory &Factory; + + // An efficient hash-map implementation in the spirit of llvm's SmallPtrSet: + // The first 16 substitutions are stored in an inline-allocated array to avoid + // malloc calls in the common case. + // Lookup is still reasonable fast because there are max 16 elements in the + // array. + static const size_t InlineSubstCapacity = 16; + SubstitutionEntry InlineSubstitutions[InlineSubstCapacity]; + size_t NumInlineSubsts = 0; + + // The "overflow" for InlineSubstitutions. Only if InlineSubstitutions is + // full, new substitutions are stored in OverflowSubstitutions. + std::unordered_map + OverflowSubstitutions; + + RemanglerBuffer Buffer; + +protected: + RemanglerBase(NodeFactory &Factory) : Factory(Factory), Buffer(Factory) { } + + /// Find a substitution and return its index. + /// Returns -1 if no substitution is found. + int findSubstitution(const SubstitutionEntry &entry); + + /// Adds a substitution. + void addSubstitution(const SubstitutionEntry &entry); + + /// Resets the output string buffer to \p toPos. + void resetBuffer(size_t toPos) { Buffer.reset(toPos); } + +public: + + /// Append a custom string to the output buffer. + void append(StringRef str) { Buffer << str; } + + StringRef getBufferStr() const { return Buffer.strRef(); } + + std::string str() { + return getBufferStr().str(); + } +}; + +} // end namespace Demangle +} // end namespace swift + +#endif // SWIFT_DEMANGLING_BASEREMANGLER_H diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 95a1f2bdb09a5..3c596df75ceb5 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -601,11 +601,9 @@ MetadataResponse swift::swift_getGenericMetadata(MetadataRequest request, const void * const *arguments, const TypeContextDescriptor *description) { - auto &generics = description->getFullGenericContextHeader(); - size_t numGenericArgs = generics.Base.NumKeyArguments; - auto &cache = getCache(*description); - assert(numGenericArgs == cache.NumKeyParameters + cache.NumWitnessTables); + assert(description->getFullGenericContextHeader().Base.NumKeyArguments == + cache.NumKeyParameters + cache.NumWitnessTables); auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, arguments); auto result = cache.getOrInsert(key, request, description, arguments); @@ -2210,24 +2208,26 @@ static void initGenericClassObjCName(ClassMetadata *theClass) { auto globalNode = Dem.createNode(Demangle::Node::Kind::Global); globalNode->addChild(typeNode, Dem); - auto string = Demangle::mangleNodeOld(globalNode, &Dem); + llvm::StringRef string = Demangle::mangleNodeOld(globalNode, Dem); // If the class is in the Swift module, add a $ to the end of the ObjC // name. The old and new Swift libraries must be able to coexist in // the same process, and this avoids warnings due to the ObjC names // colliding. - bool addSuffix = strncmp(string.c_str(), "_TtGCs", 6) == 0; + bool addSuffix = string.startswith("_TtGCs"); size_t allocationSize = string.size() + 1; if (addSuffix) allocationSize += 1; auto fullNameBuf = (char*)swift_slowAlloc(allocationSize, 0); - memcpy(fullNameBuf, string.c_str(), string.size() + 1); + memcpy(fullNameBuf, string.data(), string.size()); if (addSuffix) { fullNameBuf[string.size()] = '$'; fullNameBuf[string.size() + 1] = '\0'; + } else { + fullNameBuf[string.size()] = '\0'; } auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass); @@ -4740,20 +4740,38 @@ areAllTransitiveMetadataComplete_cheap(const Metadata *type) { /// dependencies actually hold, and we can keep going. static MetadataDependency checkTransitiveCompleteness(const Metadata *initialType) { - // TODO: it would nice to avoid allocating memory in common cases here. - // In particular, we don't usually add *anything* to the worklist, and we - // usually only add a handful of types to the map. - std::vector worklist; - std::unordered_set presumedCompleteTypes; + llvm::SmallVector worklist; + + // An efficient hash-set implementation in the spirit of llvm's SmallPtrSet: + // The first 8 elements are stored in an inline-allocated array to avoid + // malloc calls in the common case. Lookup is still reasonable fast because + // there are max 8 elements in the array. + const int InlineCapacity = 8; + const Metadata *inlinedPresumedCompleteTypes[InlineCapacity]; + int numInlinedTypes = 0; + std::unordered_set overflowPresumedCompleteTypes; MetadataDependency dependency; auto isIncomplete = [&](const Metadata *type) -> bool { // Add the type to the presumed-complete-types set. If this doesn't // succeed, we've already inserted it, which means we must have already // decided it was complete. - if (!presumedCompleteTypes.insert(type).second) + // First, try to find the type in the inline-storage of the set. + const Metadata **end = inlinedPresumedCompleteTypes + numInlinedTypes; + if (std::find(inlinedPresumedCompleteTypes, end, type) != end) return false; + // We didn't find the type in the inline-storage. + if (numInlinedTypes < InlineCapacity) { + assert(overflowPresumedCompleteTypes.size() == 0); + inlinedPresumedCompleteTypes[numInlinedTypes++] = type; + } else { + // The inline-storage is full. So try to insert the type into the + // overflow set. + if (!overflowPresumedCompleteTypes.insert(type).second) + return false; + } + // Check the metadata's current state with a non-blocking request. auto request = MetadataRequest(MetadataState::Complete, /*non-blocking*/ true); @@ -4780,7 +4798,9 @@ checkTransitiveCompleteness(const Metadata *initialType) { // Consider the type itself to be presumed-complete. We're looking for // a greatest fixed point. - presumedCompleteTypes.insert(initialType); + assert(numInlinedTypes == 0 && overflowPresumedCompleteTypes.size() == 0); + inlinedPresumedCompleteTypes[0] = initialType; + numInlinedTypes = 1; if (findAnyTransitiveMetadata(initialType, isIncomplete)) return dependency; diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index 30022eeed8cb3..9ea8a9edccdf0 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -965,8 +965,8 @@ class DecodedMetadataBuilder { #if SWIFT_OBJC_INTEROP // Look for a Swift-defined @objc protocol with the Swift 3 mangling that // is used for Objective-C entities. - std::string objcMangledName = "_Tt" + mangleNodeOld(node, &demangler) + "_"; - if (auto protocol = objc_getProtocol(objcMangledName.c_str())) + const char *objcMangledName = mangleNodeAsObjcCString(node, demangler); + if (auto protocol = objc_getProtocol(objcMangledName)) return ProtocolDescriptorRef::forObjC(protocol); #endif