diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b56647c..c9ac1b4cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +**Features** + +- Updated libswift demangle to v6.1.0. ([#913](https://github.com/getsentry/symbolic/pull/913)) + ## 12.15.3 **Features** diff --git a/symbolic-demangle/tests/test_swift.rs b/symbolic-demangle/tests/test_swift.rs index 0e58568f8..47709a0ee 100644 --- a/symbolic-demangle/tests/test_swift.rs +++ b/symbolic-demangle/tests/test_swift.rs @@ -295,5 +295,8 @@ fn test_demangle_swift_no_args() { // Swift 6.0.3 "$ss27withTaskCancellationHandler9operation8onCancel9isolationxxyYaKXE_yyYbXEScA_pSgYitYaKlFTwb" => "withTaskCancellationHandler", "$s11Supercharge2AXO7ElementPAAE8elements33_35EDDAA799FBB5B74D2F426690B0D99DLL3for2asSayqd__GSo28NSAccessibilityAttributeNamea_qd__mtSo7AXErrorVYKAcDRd__lFAC3AppC_AC6WindowCTgm5" => "specialized AX.Element.elements", + + // Swift 6.1.0 + "$sTB" => "$sTB", }); } diff --git a/symbolic-demangle/vendor/swift/1-arguments.patch b/symbolic-demangle/vendor/swift/1-arguments.patch index 2d5340b27..b5b3df924 100644 --- a/symbolic-demangle/vendor/swift/1-arguments.patch +++ b/symbolic-demangle/vendor/swift/1-arguments.patch @@ -1,11 +1,11 @@ -commit 80e772078494a73f2fbb5e385de2092e6057d913 -Author: David Herberth -Date: Thu Jan 9 10:54:28 2025 +0100 +commit 688c78af45dc197ce0ef8a0ea520d77592905394 +Author: Sebastian Zivota +Date: Wed Apr 16 18:43:43 2025 +0200 - apply patch + Apply patch diff --git a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h -index f66dd7fd..940c3652 100644 +index 3e029a9b..da18a09a 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h +++ b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h @@ -58,6 +58,7 @@ struct DemangleOptions { @@ -25,10 +25,10 @@ index f66dd7fd..940c3652 100644 return Opt; }; diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp -index 6c309bbf..5b251e8d 100644 +index d9098192..5e8ae258 100644 --- a/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp +++ b/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp -@@ -955,10 +955,11 @@ private: +@@ -966,10 +966,11 @@ private: if (isSendable) Printer << "@Sendable "; diff --git a/symbolic-demangle/vendor/swift/README.md b/symbolic-demangle/vendor/swift/README.md index 4bd7fddaf..e536fc9e2 100644 --- a/symbolic-demangle/vendor/swift/README.md +++ b/symbolic-demangle/vendor/swift/README.md @@ -3,7 +3,7 @@ This folder contains a vendored subset of the [Swift Programming Language]. The Swift library is reduced to the demangler only to reduce the size of this package. -The current version is **Swift 5.5.1**. +The current version is **Swift 6.1.0**. ## Sentry Modifications @@ -28,7 +28,7 @@ patch is maintained in `1-arguments.patch`. 4. Check out the release branch of the latest release: ``` $ cd swift - $ git checkout swift-5.5.1-RELEASE + $ git checkout swift-x.x.x-RELEASE ``` 5. Build the complete swift project (be very patient, this may take long): ``` @@ -40,14 +40,16 @@ patch is maintained in `1-arguments.patch`. $ ./update.py swift-source ``` 2. Check for modifications. - 3. Commit _"feat(demangle): Import libswift demangle x.x.x"_ before proceeding. + 3. **BUG**: If the file `./include/swift/ABI/InvertibleProtocols.def` is not automatically + copied, copy it manually from `swift-source/swift/include/swift/ABI/InvertibleProtocols.def`. + 4. Commit _"feat(demangle): Import libswift demangle x.x.x"_ before proceeding. 3. **Apply the patch:** 1. Apply `1-arguments.patch`. 2. Build the Rust library and ensure tests work. 3. Commit the changes. 4. **Add tests for new mangling schemes:** 1. Identify new mangling schemes. Skip if there are no known changes. - 2. Add test cases to `tests/swift.rs` + 2. Add test cases to `tests/test_swift.rs` 5. **Update Repository metadata**: 1. Bump the Swift version number in this README. 2. Check for changes in the license and update the files. diff --git a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h index 940c36520..da18a09a2 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h +++ b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangle.h @@ -138,7 +138,11 @@ enum class MangledDifferentiabilityKind : char { Linear = 'l', }; -enum class MangledLifetimeDependenceKind : char { Inherit = 'i', Scope = 's' }; +enum class MangledSILThunkKind : char { + Invalid = 0, + Identity = 'I', + HopToMainActorIfNeeded = 'H', +}; /// The pass that caused the specialization to occur. We use this to make sure /// that two passes that generate similar changes do not yield the same @@ -247,6 +251,25 @@ class Node { } } + static bool deepEquals(const Node *lhs, const Node *rhs) { + if (lhs == rhs) + return true; + if ((!lhs && rhs) || (lhs && !rhs)) + return false; + if (!lhs->isSimilarTo(rhs)) + return false; + for (auto li = lhs->begin(), ri = rhs->begin(), le = lhs->end(); li != le; + ++li, ++ri) { + if (!deepEquals(*li, *ri)) + return false; + } + return true; + } + + bool isDeepEqualTo(const Node *other) const { + return deepEquals(this, other); + } + bool hasText() const { return NodePayloadKind == PayloadKind::Text; } llvm::StringRef getText() const { assert(hasText()); @@ -601,6 +624,7 @@ struct [[nodiscard]] ManglingError { UnknownEncoding, InvalidImplCalleeConvention, InvalidImplDifferentiability, + InvalidImplCoroutineKind, InvalidImplFunctionAttribute, InvalidImplParameterConvention, InvalidImplParameterSending, diff --git a/symbolic-demangle/vendor/swift/include/swift/Demangling/DemangleNodes.def b/symbolic-demangle/vendor/swift/include/swift/Demangling/DemangleNodes.def index c872f1be9..201b770b0 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Demangling/DemangleNodes.def +++ b/symbolic-demangle/vendor/swift/include/swift/Demangling/DemangleNodes.def @@ -46,6 +46,7 @@ NODE(BoundGenericTypeAlias) NODE(BoundGenericFunction) NODE(BuiltinTypeName) NODE(BuiltinTupleType) +NODE(BuiltinFixedArray) NODE(CFunctionPointer) NODE(ClangType) CONTEXT_NODE(Class) @@ -140,6 +141,7 @@ NODE(ImplFunctionAttribute) NODE(ImplFunctionConvention) NODE(ImplFunctionConventionName) NODE(ImplFunctionType) +NODE(ImplCoroutineKind) NODE(ImplInvocationSubstitutions) CONTEXT_NODE(ImplicitClosure) NODE(ImplParameter) @@ -152,6 +154,7 @@ NODE(InfixOperator) CONTEXT_NODE(Initializer) CONTEXT_NODE(InitAccessor) NODE(Isolated) +CONTEXT_NODE(IsolatedDeallocator) NODE(Sending) NODE(IsolatedAnyFunctionType) NODE(SendingResultFunctionType) @@ -177,6 +180,7 @@ NODE(ObjCMetadataUpdateFunction) NODE(ObjCResilientClassStub) NODE(FullObjCResilientClassStub) CONTEXT_NODE(ModifyAccessor) +CONTEXT_NODE(Modify2Accessor) CONTEXT_NODE(Module) CONTEXT_NODE(NativeOwningAddressor) CONTEXT_NODE(NativeOwningMutableAddressor) @@ -229,6 +233,7 @@ NODE(ReabstractionThunkHelper) NODE(ReabstractionThunkHelperWithSelf) NODE(ReabstractionThunkHelperWithGlobalActor) CONTEXT_NODE(ReadAccessor) +CONTEXT_NODE(Read2Accessor) NODE(RelatedEntityDeclName) NODE(RetroactiveConformance) NODE(ReturnType) @@ -287,6 +292,8 @@ NODE(ReflectionMetadataAssocTypeDescriptor) NODE(ReflectionMetadataSuperclassDescriptor) NODE(GenericTypeParamDecl) NODE(CurryThunk) +NODE(SILThunkIdentity) +NODE(SILThunkHopToMainActorIfNeeded) NODE(DispatchThunk) NODE(MethodDescriptor) NODE(ProtocolRequirementsBaseDescriptor) @@ -321,7 +328,7 @@ NODE(AssociatedTypeGenericParamRef) NODE(SugaredOptional) NODE(SugaredArray) NODE(SugaredDictionary) -NODE(SugaredParen) +NODE(SugaredParen) // Removed in Swift 6.TBD // Added in Swift 5.1 NODE(AccessorFunctionReference) @@ -374,7 +381,7 @@ NODE(NonUniqueExtendedExistentialTypeShapeSymbolicReference) NODE(SymbolicExtendedExistentialType) // Added in Swift 5.8 -NODE(MetatypeParamsRemoved) +NODE(DroppedArgument) NODE(HasSymbolQuery) NODE(OpaqueReturnTypeIndex) NODE(OpaqueReturnTypeParent) @@ -388,8 +395,6 @@ NODE(AsyncRemoved) // Added in Swift 5.TBD NODE(ObjectiveCProtocolSymbolicReference) -NODE(ParamLifetimeDependence) -NODE(SelfLifetimeDependence) NODE(OutlinedInitializeWithCopyNoValueWitness) NODE(OutlinedAssignWithTakeNoValueWitness) @@ -398,5 +403,10 @@ NODE(OutlinedDestroyNoValueWitness) NODE(DependentGenericInverseConformanceRequirement) +// Added in Swift 6.TBD +NODE(Integer) +NODE(NegativeInteger) +NODE(DependentGenericParamValueMarker) + #undef CONTEXT_NODE #undef NODE diff --git a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangler.h b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangler.h index a3b62f2c0..e6d76bccf 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangler.h +++ b/symbolic-demangle/vendor/swift/include/swift/Demangling/Demangler.h @@ -44,14 +44,14 @@ class NodeFactory { /// The end of the current slab. char *End = nullptr; - struct Slab { + struct AllocatedSlab { // The previously allocated slab. - Slab *Previous; + AllocatedSlab *Previous; // Tail allocated memory starts here. }; /// The head of the single-linked slab list. - Slab *CurrentSlab = nullptr; + AllocatedSlab *CurrentSlab = nullptr; /// The size of the previously allocated slab. This may NOT be the size of /// CurrentSlab, in the case where a checkpoint has been popped. @@ -66,7 +66,7 @@ class NodeFactory { & ~((uintptr_t)Alignment - 1)); } - static void freeSlabs(Slab *slab); + static void freeSlabs(AllocatedSlab *slab); /// If not null, the NodeFactory from which this factory borrowed free memory. NodeFactory *BorrowedFrom = nullptr; @@ -149,8 +149,8 @@ class NodeFactory { // No. We have to malloc a new slab. // We double the slab size for each allocated slab. SlabSize = std::max(SlabSize * 2, ObjectSize + alignof(T)); - size_t AllocSize = sizeof(Slab) + SlabSize; - Slab *newSlab = (Slab *)malloc(AllocSize); + size_t AllocSize = sizeof(AllocatedSlab) + SlabSize; + AllocatedSlab *newSlab = (AllocatedSlab *)malloc(AllocSize); // Insert the new slab in the single-linked list of slabs. newSlab->Previous = CurrentSlab; @@ -225,7 +225,7 @@ class NodeFactory { /// A checkpoint which captures the allocator's state at any given time. A /// checkpoint can be popped to free all allocations made since it was made. struct Checkpoint { - Slab *Slab; + AllocatedSlab *Slab; char *CurPtr; char *End; }; @@ -594,7 +594,9 @@ class Demangler : public NodeFactory { NodePointer popDependentAssociatedConformance(); NodePointer demangleDependentProtocolConformanceAssociated(); NodePointer demangleThunkOrSpecialization(); - NodePointer demangleGenericSpecialization(Node::Kind SpecKind); + NodePointer demangleGenericSpecialization(Node::Kind SpecKind, + NodePointer droppedArguments); + NodePointer demangleGenericSpecializationWithDroppedArguments(); NodePointer demangleFunctionSpecialization(); NodePointer demangleFuncSpecParam(Node::Kind Kind); NodePointer addFuncSpecParamNumber(NodePointer Param, @@ -635,7 +637,7 @@ class Demangler : public NodeFactory { bool demangleBoundGenerics(Vector &TypeListList, NodePointer &RetroactiveConformances); - NodePointer demangleLifetimeDependenceKind(bool isSelfDependence); + NodePointer demangleIntegerType(); void dump(); diff --git a/symbolic-demangle/vendor/swift/include/swift/Demangling/ManglingMacros.h b/symbolic-demangle/vendor/swift/include/swift/Demangling/ManglingMacros.h index 5cf386314..c93f4508e 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Demangling/ManglingMacros.h +++ b/symbolic-demangle/vendor/swift/include/swift/Demangling/ManglingMacros.h @@ -17,12 +17,12 @@ #define MANGLE_AS_STRING(M) STRINGIFY_MANGLING(M) /// The mangling prefix for the new mangling. -#if !defined(_MSC_VER) || _MSC_VER-0 >= 1926 +#if defined(__clang__) _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wdollar-in-identifier-extension\"") #endif #define MANGLING_PREFIX $s -#if !defined(_MSC_VER) || _MSC_VER-0 >= 1926 +#if defined(__clang__) _Pragma("clang diagnostic pop") #endif diff --git a/symbolic-demangle/vendor/swift/include/swift/Strings.h b/symbolic-demangle/vendor/swift/include/swift/Strings.h index 8538e6931..be4791f9a 100644 --- a/symbolic-demangle/vendor/swift/include/swift/Strings.h +++ b/symbolic-demangle/vendor/swift/include/swift/Strings.h @@ -85,6 +85,10 @@ constexpr static const StringLiteral CLANG_MODULE_DEFAULT_SPI_GROUP_NAME = constexpr static const StringLiteral SPI_AVAILABLE_ATTRNAME = "_spi_available"; +/// The attribute name for @_unavailableInEmbedded +constexpr static const StringLiteral UNAVAILABLE_IN_EMBEDDED_ATTRNAME = + "_unavailableInEmbedded"; + /// A composition class containing a StringLiteral for the names of /// Swift builtins. The reason we use this is to ensure that we when /// necessary slice off the "Builtin." prefix from these names in a @@ -172,6 +176,8 @@ constexpr static BuiltinNameStringLiteral BUILTIN_TYPE_NAME_UNKNOWNOBJECT = { /// The name of the Builtin type for Vector constexpr static BuiltinNameStringLiteral BUILTIN_TYPE_NAME_VEC = { "Builtin.Vec"}; +constexpr static BuiltinNameStringLiteral BUILTIN_TYPE_NAME_FIXEDARRAY = { + "Builtin.FixedArray"}; /// The name of the Builtin type for SILToken constexpr static BuiltinNameStringLiteral BUILTIN_TYPE_NAME_SILTOKEN = { "Builtin.SILToken"}; diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/Context.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/Context.cpp index 69f366140..c762ea193 100644 --- a/symbolic-demangle/vendor/swift/lib/Demangling/Context.cpp +++ b/symbolic-demangle/vendor/swift/lib/Demangling/Context.cpp @@ -70,7 +70,7 @@ std::string Context::demangleTypeAsString(llvm::StringRef MangledName, const DemangleOptions &Options) { NodePointer root = demangleTypeAsNode(MangledName); if (!root) return MangledName.str(); - + std::string demangling = nodeToString(root, Options); if (demangling.empty()) return MangledName.str(); diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/Demangler.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/Demangler.cpp index 704fbcadb..d2b5d4682 100644 --- a/symbolic-demangle/vendor/swift/lib/Demangling/Demangler.cpp +++ b/symbolic-demangle/vendor/swift/lib/Demangling/Demangler.cpp @@ -80,6 +80,7 @@ static bool isEntity(Node::Kind kind) { static bool isRequirement(Node::Kind kind) { switch (kind) { case Node::Kind::DependentGenericParamPackMarker: + case Node::Kind::DependentGenericParamValueMarker: case Node::Kind::DependentGenericSameTypeRequirement: case Node::Kind::DependentGenericSameShapeRequirement: case Node::Kind::DependentGenericLayoutRequirement: @@ -223,6 +224,8 @@ llvm::StringRef swift::Demangle::dropSwiftManglingPrefix(StringRef mangledName){ } static bool isAliasNode(Demangle::NodePointer Node) { + if (!Node) + return false; switch (Node->getKind()) { case Demangle::Node::Kind::Type: return isAliasNode(Node->getChild(0)); @@ -240,6 +243,8 @@ bool swift::Demangle::isAlias(llvm::StringRef mangledName) { } static bool isClassNode(Demangle::NodePointer Node) { + if (!Node) + return false; switch (Node->getKind()) { case Demangle::Node::Kind::Type: return isClassNode(Node->getChild(0)); @@ -258,6 +263,8 @@ bool swift::Demangle::isClass(llvm::StringRef mangledName) { } static bool isEnumNode(Demangle::NodePointer Node) { + if (!Node) + return false; switch (Node->getKind()) { case Demangle::Node::Kind::Type: return isEnumNode(Node->getChild(0)); @@ -276,6 +283,8 @@ bool swift::Demangle::isEnum(llvm::StringRef mangledName) { } static bool isProtocolNode(Demangle::NodePointer Node) { + if (!Node) + return false; switch (Node->getKind()) { case Demangle::Node::Kind::Type: return isProtocolNode(Node->getChild(0)); @@ -295,6 +304,8 @@ bool swift::Demangle::isProtocol(llvm::StringRef mangledName) { } static bool isStructNode(Demangle::NodePointer Node) { + if (!Node) + return false; switch (Node->getKind()) { case Demangle::Node::Kind::Type: return isStructNode(Node->getChild(0)); @@ -470,9 +481,9 @@ Node* Node::findByKind(Node::Kind kind, int maxDepth) { // NodeFactory member functions // ////////////////////////////////// -void NodeFactory::freeSlabs(Slab *slab) { +void NodeFactory::freeSlabs(AllocatedSlab *slab) { while (slab) { - Slab *prev = slab->Previous; + AllocatedSlab *prev = slab->Previous; free(slab); slab = prev; } @@ -532,7 +543,7 @@ void NodeFactory::popCheckpoint(NodeFactory::Checkpoint checkpoint) { // checkpoint's slab is less than 1/16th of the current slab's space. We // won't repeatedly allocate and deallocate the current slab. The size // doubles each time so we'll quickly pass the threshold. - Slab *savedSlab = nullptr; + AllocatedSlab *savedSlab = nullptr; if (CurrentSlab) { size_t checkpointSlabFreeSpace = checkpoint.End - checkpoint.CurPtr; size_t currentSlabSize = End - (char *)(CurrentSlab + 1); @@ -746,6 +757,8 @@ NodePointer Demangler::demangleSymbol(StringRef MangledName, NodePointer topLevel = createNode(Node::Kind::Global); + NodePointer suffix = popNode(Node::Kind::Suffix); + NodePointer Parent = topLevel; while (NodePointer FuncAttr = popNode(isFunctionAttr)) { Parent->addChild(FuncAttr, *this); @@ -763,6 +776,9 @@ NodePointer Demangler::demangleSymbol(StringRef MangledName, break; } } + if (suffix) + topLevel->addChild(suffix, *this); + if (topLevel->getNumChildren() == 0) return nullptr; @@ -773,17 +789,27 @@ NodePointer Demangler::demangleType(StringRef MangledName, std::function Resolver) { DemangleInitRAII state(*this, MangledName, std::move(Resolver)); - parseAndPushNodes(); + if (!parseAndPushNodes()) + return nullptr; - if (NodePointer Result = popNode()) - return Result; + NodePointer Result = popNode(); - return createNode(Node::Kind::Suffix, Text); + // The result is only valid if it was the only node on the stack. + if (popNode()) + return nullptr; + + return Result; } bool Demangler::parseAndPushNodes() { const auto textSize = Text.size(); while (Pos < textSize) { + // Programs may look up a type by NUL-terminated name with an excessive + // length. Keep them working by returning success if we encounter a NUL in + // the middle of the string where an operator is expected. + if (peekChar() == '\0') + return true; + NodePointer Node = demangleOperator(); if (!Node) return false; @@ -947,7 +973,7 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind) { } NodePointer Demangler::demangleTypeAnnotation() { - switch (char c2 = nextChar()) { + switch (nextChar()) { case 'a': return createNode(Node::Kind::AsyncAnnotation); case 'A': @@ -975,10 +1001,6 @@ NodePointer Demangler::demangleTypeAnnotation() { case 'u': return createType( createWithChild(Node::Kind::Sending, popTypeAndGetChild())); - case 'l': - return demangleLifetimeDependenceKind(/*isSelfDependence*/ false); - case 'L': - return demangleLifetimeDependenceKind(/*isSelfDependence*/ true); default: return nullptr; } @@ -1003,7 +1025,7 @@ NodePointer Demangler::demangleOperator() { case 'F': return demanglePlainFunction(); case 'G': return demangleBoundGenericType(); case 'H': - switch (char c2 = nextChar()) { + switch (nextChar()) { case 'A': return demangleDependentProtocolConformanceAssociated(); case 'C': return demangleConcreteProtocolConformance(); case 'D': return demangleDependentProtocolConformanceRoot(); @@ -1085,6 +1107,7 @@ NodePointer Demangler::demangleOperator() { // outlined copy functions. We treat such a suffix as "unmangled suffix". pushBack(); return createNode(Node::Kind::Suffix, consumeAll()); + case '$': return demangleIntegerType(); default: pushBack(); return demangleIdentifier(); @@ -1184,7 +1207,7 @@ NodePointer Demangler::createSwiftType(Node::Kind typeKind, const char *name) { } NodePointer Demangler::demangleStandardSubstitution() { - switch (char c = nextChar()) { + switch (nextChar()) { case 'o': return createNode(Node::Kind::Module, MANGLING_MODULE_OBJC); case 'C': @@ -1452,6 +1475,18 @@ NodePointer Demangler::demangleBuiltinType() { Ty = createNode(Node::Kind::BuiltinTypeName, name); break; } + case 'V': { + NodePointer element = popNode(Node::Kind::Type); + if (!element) + return nullptr; + NodePointer size = popNode(Node::Kind::Type); + if (!size) + return nullptr; + Ty = createNode(Node::Kind::BuiltinFixedArray); + Ty->addChild(size, *this); + Ty->addChild(element, *this); + break; + } case 'O': Ty = createNode(Node::Kind::BuiltinTypeName, BUILTIN_TYPE_NAME_UNKNOWNOBJECT); @@ -1520,34 +1555,53 @@ NodePointer Demangler::demangleExtensionContext() { /// Associate any \c OpaqueReturnType nodes with the declaration whose opaque /// return type they refer back to. -static Node *setParentForOpaqueReturnTypeNodes(Demangler &D, - Node *parent, - Node *visitedNode) { - if (!parent || !visitedNode) - return nullptr; - if (visitedNode->getKind() == Node::Kind::OpaqueReturnType) { +/// Implementation for \c setParentForOpaqueReturnTypeNodes. Don't invoke +/// directly. +static void setParentForOpaqueReturnTypeNodesImpl( + Demangler &D, Node &visitedNode, + llvm::function_ref getParentID) { + if (visitedNode.getKind() == Node::Kind::OpaqueReturnType) { // If this node is not already parented, parent it. - if (visitedNode->hasChildren() - && visitedNode->getLastChild()->getKind() == Node::Kind::OpaqueReturnTypeParent) { - return parent; + if (visitedNode.hasChildren() && visitedNode.getLastChild()->getKind() == + Node::Kind::OpaqueReturnTypeParent) { + return; } - visitedNode->addChild(D.createNode(Node::Kind::OpaqueReturnTypeParent, - (Node::IndexType)parent), D); - return parent; + visitedNode.addChild(D.createNode(Node::Kind::OpaqueReturnTypeParent, + StringRef(getParentID())), + D); + return; } - + // If this node is one that may in turn define its own opaque return type, // stop recursion, since any opaque return type nodes underneath would refer // to the nested declaration rather than the one we're looking at. - if (visitedNode->getKind() == Node::Kind::Function - || visitedNode->getKind() == Node::Kind::Variable - || visitedNode->getKind() == Node::Kind::Subscript) { - return parent; + if (visitedNode.getKind() == Node::Kind::Function || + visitedNode.getKind() == Node::Kind::Variable || + visitedNode.getKind() == Node::Kind::Subscript) { + return; } - - for (size_t i = 0, e = visitedNode->getNumChildren(); i < e; ++i) { - setParentForOpaqueReturnTypeNodes(D, parent, visitedNode->getChild(i)); + + for (Node *child : visitedNode) { + assert(child); + setParentForOpaqueReturnTypeNodesImpl(D, *child, getParentID); } +} + +/// Associate any \c OpaqueReturnType nodes with the declaration whose opaque +/// return type they refer back to. +static Node *setParentForOpaqueReturnTypeNodes(Demangler &D, Node *parent, + Node *visitedNode) { + if (!parent || !visitedNode) + return nullptr; + std::string parentID; + setParentForOpaqueReturnTypeNodesImpl(D, *visitedNode, [&] { + if (!parentID.empty()) + return StringRef(parentID); + const auto mangleResult = mangleNode(parent); + assert(mangleResult.isSuccess()); + parentID = mangleResult.result(); + return StringRef(parentID); + }); return parent; } @@ -1574,25 +1628,51 @@ NodePointer Demangler::demanglePlainFunction() { NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) { NodePointer FuncType = createNode(kind); + + // Demangle a C function type if the function node kind says that + // one follows. NodePointer ClangType = nullptr; if (hasClangType) { ClangType = demangleClangType(); } addChild(FuncType, ClangType); - addChild(FuncType, popNode(Node::Kind::SelfLifetimeDependence)); - addChild(FuncType, popNode(Node::Kind::GlobalActorFunctionType)); - addChild(FuncType, popNode(Node::Kind::IsolatedAnyFunctionType)); + + // The components of function-signature. Note that these need to be + // popped in the reverse of the order they're mangled. If you add a + // new component, be sure to add a demangling test case for combinations + // of specifiers. + + // sending-result? addChild(FuncType, popNode(Node::Kind::SendingResultFunctionType)); + + // function-isolation? + auto isFunctionIsolation = [](Node::Kind kind) { + return kind == Node::Kind::GlobalActorFunctionType || + kind == Node::Kind::IsolatedAnyFunctionType; + }; + addChild(FuncType, popNode(isFunctionIsolation)); + + // differentiable? addChild(FuncType, popNode(Node::Kind::DifferentiableFunctionType)); + + // throws? addChild(FuncType, popNode([](Node::Kind kind) { return kind == Node::Kind::ThrowsAnnotation || kind == Node::Kind::TypedThrowsAnnotation; })); + + // sendable? addChild(FuncType, popNode(Node::Kind::ConcurrentFunctionType)); + + // async? addChild(FuncType, popNode(Node::Kind::AsyncAnnotation)); + // params-type FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ArgumentTuple)); + + // result-type FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ReturnType)); + return createType(FuncType); } @@ -1623,7 +1703,7 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) { unsigned FirstChildIdx = 0; if (FuncType->getChild(FirstChildIdx)->getKind() == - Node::Kind::SelfLifetimeDependence) + Node::Kind::SendingResultFunctionType) ++FirstChildIdx; if (FuncType->getChild(FirstChildIdx)->getKind() == Node::Kind::GlobalActorFunctionType) @@ -1631,9 +1711,6 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) { if (FuncType->getChild(FirstChildIdx)->getKind() == Node::Kind::IsolatedAnyFunctionType) ++FirstChildIdx; - if (FuncType->getChild(FirstChildIdx)->getKind() == - Node::Kind::SendingResultFunctionType) - ++FirstChildIdx; if (FuncType->getChild(FirstChildIdx)->getKind() == Node::Kind::DifferentiableFunctionType) ++FirstChildIdx; @@ -1648,9 +1725,6 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) { if (FuncType->getChild(FirstChildIdx)->getKind() == Node::Kind::AsyncAnnotation) ++FirstChildIdx; - if (FuncType->getChild(FirstChildIdx)->getKind() == - Node::Kind::ParamLifetimeDependence) - ++FirstChildIdx; auto ParameterType = FuncType->getChild(FirstChildIdx); assert(ParameterType->getKind() == Node::Kind::ArgumentTuple); @@ -2160,6 +2234,7 @@ NodePointer Demangler::demangleImplParamConvention(Node::Kind ConvKind) { case 'l': attr = "@inout"; break; case 'b': attr = "@inout_aliasable"; break; case 'n': attr = "@in_guaranteed"; break; + case 'X': attr = "@in_cxx"; break; case 'x': attr = "@owned"; break; case 'g': attr = "@guaranteed"; break; case 'e': attr = "@deallocating"; break; @@ -2319,11 +2394,13 @@ NodePointer Demangler::demangleImplFunctionType() { const char *CoroAttr = nullptr; if (nextIf('A')) - CoroAttr = "@yield_once"; + CoroAttr = "yield_once"; + else if (nextIf('I')) + CoroAttr = "yield_once_2"; else if (nextIf('G')) - CoroAttr = "@yield_many"; + CoroAttr = "yield_many"; if (CoroAttr) - type->addChild(createNode(Node::Kind::ImplFunctionAttribute, CoroAttr), *this); + type->addChild(createNode(Node::Kind::ImplCoroutineKind, CoroAttr), *this); if (nextIf('h')) { type->addChild(createNode(Node::Kind::ImplFunctionAttribute, "@Sendable"), @@ -2335,6 +2412,10 @@ NodePointer Demangler::demangleImplFunctionType() { *this); } + if (nextIf('T')) { + type->addChild(createNode(Node::Kind::ImplSendingResult), *this); + } + addChild(type, GenSig); int NumTypesToAdd = 0; @@ -2348,10 +2429,6 @@ NodePointer Demangler::demangleImplFunctionType() { ++NumTypesToAdd; } - if (nextIf('T')) { - type->addChild(createNode(Node::Kind::ImplSendingResult), *this); - } - while (NodePointer Result = demangleImplResultConvention( Node::Kind::ImplResult)) { type = addChild(type, Result); @@ -2384,7 +2461,7 @@ NodePointer Demangler::demangleImplFunctionType() { return nullptr; type->getChild(type->getNumChildren() - Idx - 1)->addChild(ConvTy, *this); } - + return createType(type); } @@ -2764,6 +2841,18 @@ NodePointer Demangler::popProtocolConformance() { NodePointer Demangler::demangleThunkOrSpecialization() { switch (char c = nextChar()) { + // Thunks that are from a thunk inst. We take the TT namespace. + case 'T': { + switch (nextChar()) { + case 'I': + return createWithChild(Node::Kind::SILThunkIdentity, popNode(isEntity)); + case 'H': + return createWithChild(Node::Kind::SILThunkHopToMainActorIfNeeded, + popNode(isEntity)); + default: + return nullptr; + } + } case 'c': return createWithChild(Node::Kind::CurryThunk, popNode(isEntity)); case 'j': return createWithChild(Node::Kind::DispatchThunk, popNode(isEntity)); case 'q': return createWithChild(Node::Kind::MethodDescriptor, popNode(isEntity)); @@ -2835,18 +2924,20 @@ NodePointer Demangler::demangleThunkOrSpecialization() { return Thunk; } case 'g': - return demangleGenericSpecialization(Node::Kind::GenericSpecialization); + return demangleGenericSpecialization(Node::Kind::GenericSpecialization, nullptr); case 'G': return demangleGenericSpecialization(Node::Kind:: - GenericSpecializationNotReAbstracted); + GenericSpecializationNotReAbstracted, nullptr); case 'B': return demangleGenericSpecialization(Node::Kind:: - GenericSpecializationInResilienceDomain); + GenericSpecializationInResilienceDomain, nullptr); + case 't': + return demangleGenericSpecializationWithDroppedArguments(); case 's': return demangleGenericSpecialization( - Node::Kind::GenericSpecializationPrespecialized); + Node::Kind::GenericSpecializationPrespecialized, nullptr); case 'i': - return demangleGenericSpecialization(Node::Kind::InlinedGenericFunction); + return demangleGenericSpecialization(Node::Kind::InlinedGenericFunction, nullptr); case 'p': { NodePointer Spec = demangleSpecAttributes(Node::Kind:: GenericPartialSpecialization); @@ -3102,7 +3193,7 @@ NodePointer Demangler::demangleDifferentiabilityWitness() { result = addChild(result, node); result->reverseChildren(); MangledDifferentiabilityKind kind; - switch (auto c = nextChar()) { + switch (nextChar()) { case 'f': kind = MangledDifferentiabilityKind::Forward; break; case 'r': kind = MangledDifferentiabilityKind::Reverse; break; case 'd': kind = MangledDifferentiabilityKind::Normal; break; @@ -3134,7 +3225,7 @@ NodePointer Demangler::demangleIndexSubset() { NodePointer Demangler::demangleDifferentiableFunctionType() { MangledDifferentiabilityKind kind; - switch (auto c = nextChar()) { + switch (nextChar()) { case 'f': kind = MangledDifferentiabilityKind::Forward; break; case 'r': kind = MangledDifferentiabilityKind::Reverse; break; case 'd': kind = MangledDifferentiabilityKind::Normal; break; @@ -3145,28 +3236,6 @@ NodePointer Demangler::demangleDifferentiableFunctionType() { Node::Kind::DifferentiableFunctionType, (Node::IndexType)kind); } -NodePointer Demangler::demangleLifetimeDependenceKind(bool isSelfDependence) { - MangledLifetimeDependenceKind kind; - switch (auto c = nextChar()) { - case 's': - kind = MangledLifetimeDependenceKind::Scope; - break; - case 'i': - kind = MangledLifetimeDependenceKind::Inherit; - break; - default: - return nullptr; - } - if (isSelfDependence) { - return createNode(Node::Kind::SelfLifetimeDependence, - (Node::IndexType)kind); - } - auto node = createWithChildren(Node::Kind::ParamLifetimeDependence, - createNode(Node::Kind::Index, unsigned(kind)), - popTypeAndGetChild()); - return createType(node); -} - std::string Demangler::demangleBridgedMethodParams() { if (nextIf('_')) return std::string(); @@ -3190,10 +3259,18 @@ std::string Demangler::demangleBridgedMethodParams() { return Str; } -NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind) { +NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind, + NodePointer droppedArguments) { NodePointer Spec = demangleSpecAttributes(SpecKind); if (!Spec) return nullptr; + + if (droppedArguments) { + for (NodePointer a : *droppedArguments) { + Spec->addChild(a, *this); + } + } + NodePointer TyList = popTypeList(); if (!TyList) return nullptr; @@ -3204,6 +3281,24 @@ NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind) { return Spec; } +NodePointer Demangler::demangleGenericSpecializationWithDroppedArguments() { + pushBack(); + NodePointer tmp = createNode(Node::Kind::GenericSpecialization); + while (nextIf('t')) { + int n = demangleNatural(); + addChild(tmp, createNode(Node::Kind::DroppedArgument, n < 0 ? 0 : n + 1)); + } + Node::Kind specKind; + switch (nextChar()) { + case 'g': specKind = Node::Kind::GenericSpecialization; break; + case 'G': specKind = Node::Kind::GenericSpecializationNotReAbstracted; break; + case 'B': specKind = Node::Kind::GenericSpecializationInResilienceDomain; break; + default: + return nullptr; + } + return demangleGenericSpecialization(specKind, tmp); +} + NodePointer Demangler::demangleFunctionSpecialization() { NodePointer Spec = demangleSpecAttributes( Node::Kind::FunctionSignatureSpecialization); @@ -3417,21 +3512,16 @@ NodePointer Demangler::addFuncSpecParamNumber(NodePointer Param, } NodePointer Demangler::demangleSpecAttributes(Node::Kind SpecKind) { - bool metatypeParamsRemoved = nextIf('m'); bool isSerialized = nextIf('q'); bool asyncRemoved = nextIf('a'); int PassID = (int)nextChar() - '0'; if (PassID < 0 || PassID >= MAX_SPECIALIZATION_PASS) { - assert(false && "unexpected pass id"); return nullptr; } NodePointer SpecNd = createNode(SpecKind); - if (metatypeParamsRemoved) - SpecNd->addChild(createNode(Node::Kind::MetatypeParamsRemoved), *this); - if (isSerialized) SpecNd->addChild(createNode(Node::Kind::IsSerialized), *this); @@ -3647,7 +3737,7 @@ NodePointer Demangler::demangleWitness() { case 'z': { auto declList = createNode(Node::Kind::GlobalVariableOnceDeclList); std::vector vars; - while (auto sig = popNode(Node::Kind::FirstElementMarker)) { + while (popNode(Node::Kind::FirstElementMarker)) { auto identifier = popNode(isDeclName); if (!identifier) return nullptr; @@ -3698,7 +3788,7 @@ NodePointer Demangler::demangleSpecialType() { case 'j': return demangleSymbolicExtendedExistentialType(); case 'z': - switch (auto cchar = nextChar()) { + switch (nextChar()) { case 'B': return popFunctionType(Node::Kind::ObjCBlock, true); case 'C': @@ -3906,7 +3996,9 @@ NodePointer Demangler::demangleAccessor(NodePointer ChildNode) { case 'w': Kind = Node::Kind::WillSet; break; case 'W': Kind = Node::Kind::DidSet; break; case 'r': Kind = Node::Kind::ReadAccessor; break; + case 'y': Kind = Node::Kind::Read2Accessor; break; case 'M': Kind = Node::Kind::ModifyAccessor; break; + case 'x': Kind = Node::Kind::Modify2Accessor; break; case 'i': Kind = Node::Kind::InitAccessor; break; case 'a': switch (nextChar()) { @@ -3947,6 +4039,10 @@ NodePointer Demangler::demangleFunctionEntity() { switch (nextChar()) { case 'D': Args = None; Kind = Node::Kind::Deallocator; break; case 'd': Args = None; Kind = Node::Kind::Destructor; break; + case 'Z': + Args = None; + Kind = Node::Kind::IsolatedDeallocator; + break; case 'E': Args = None; Kind = Node::Kind::IVarDestroyer; break; case 'e': Args = None; Kind = Node::Kind::IVarInitializer; break; case 'i': Args = None; Kind = Node::Kind::Initializer; break; @@ -4118,10 +4214,21 @@ NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) { NodePointer Demangler::demangleGenericRequirement() { enum { Generic, Assoc, CompoundAssoc, Substitution } TypeKind; - enum { Protocol, BaseClass, SameType, SameShape, Layout, PackMarker, Inverse } ConstraintKind; + + enum { + Protocol, + BaseClass, + SameType, + SameShape, + Layout, + PackMarker, + Inverse, + ValueMarker + } ConstraintKind; NodePointer inverseKind = nullptr; switch (nextChar()) { + case 'V': ConstraintKind = ValueMarker; TypeKind = Generic; break; case 'v': ConstraintKind = PackMarker; TypeKind = Generic; break; case 'c': ConstraintKind = BaseClass; TypeKind = Assoc; break; case 'C': ConstraintKind = BaseClass; TypeKind = CompoundAssoc; break; @@ -4176,6 +4283,10 @@ NodePointer Demangler::demangleGenericRequirement() { } switch (ConstraintKind) { + case ValueMarker: + return createWithChildren( + Node::Kind::DependentGenericParamValueMarker, ConstrTy, + popNode(Node::Kind::Type)); case PackMarker: return createWithChild( Node::Kind::DependentGenericParamPackMarker, ConstrTy); @@ -4365,3 +4476,20 @@ NodePointer Demangler::demangleMacroExpansion() { result->addChild(privateDiscriminator, *this); return result; } + +NodePointer Demangler::demangleIntegerType() { + NodePointer integer = nullptr; + + switch (peekChar()) { + case 'n': + nextChar(); + integer = createNode(Node::Kind::NegativeInteger, -demangleIndex()); + break; + + default: + integer = createNode(Node::Kind::Integer, demangleIndex()); + break; + } + + return createType(integer); +} diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp index 5b251e8da..5e8ae2587 100644 --- a/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp +++ b/symbolic-demangle/vendor/swift/lib/Demangling/NodePrinter.cpp @@ -296,6 +296,7 @@ class NodePrinter { case Node::Kind::BoundGenericFunction: case Node::Kind::BuiltinTypeName: case Node::Kind::BuiltinTupleType: + case Node::Kind::BuiltinFixedArray: case Node::Kind::Class: case Node::Kind::DependentGenericType: case Node::Kind::DependentMemberType: @@ -329,6 +330,8 @@ class NodePrinter { case Node::Kind::SugaredArray: case Node::Kind::SugaredDictionary: case Node::Kind::SugaredParen: + case Node::Kind::Integer: + case Node::Kind::NegativeInteger: return true; case Node::Kind::Type: @@ -365,8 +368,11 @@ class NodePrinter { case Node::Kind::Constructor: case Node::Kind::CoroutineContinuationPrototype: case Node::Kind::CurryThunk: + case Node::Kind::SILThunkIdentity: + case Node::Kind::SILThunkHopToMainActorIfNeeded: case Node::Kind::DispatchThunk: case Node::Kind::Deallocator: + case Node::Kind::IsolatedDeallocator: case Node::Kind::DeclContext: case Node::Kind::DefaultArgumentInitializer: case Node::Kind::DefaultAssociatedTypeMetadataAccessor: @@ -433,6 +439,7 @@ class NodePrinter { case Node::Kind::ImplFunctionConvention: case Node::Kind::ImplFunctionConventionName: case Node::Kind::ImplFunctionType: + case Node::Kind::ImplCoroutineKind: case Node::Kind::ImplInvocationSubstitutions: case Node::Kind::ImplPatternSubstitutions: case Node::Kind::ImplicitClosure: @@ -466,6 +473,7 @@ class NodePrinter { case Node::Kind::MethodDescriptor: case Node::Kind::MethodLookupFunction: case Node::Kind::ModifyAccessor: + case Node::Kind::Modify2Accessor: case Node::Kind::NativeOwningAddressor: case Node::Kind::NativeOwningMutableAddressor: case Node::Kind::NativePinningAddressor: @@ -516,6 +524,7 @@ class NodePrinter { case Node::Kind::ReabstractionThunkHelperWithSelf: case Node::Kind::ReabstractionThunkHelperWithGlobalActor: case Node::Kind::ReadAccessor: + case Node::Kind::Read2Accessor: case Node::Kind::RelatedEntityDeclName: case Node::Kind::RetroactiveConformance: case Node::Kind::Setter: @@ -524,7 +533,7 @@ class NodePrinter { case Node::Kind::SILBoxMutableField: case Node::Kind::SILBoxImmutableField: case Node::Kind::IsSerialized: - case Node::Kind::MetatypeParamsRemoved: + case Node::Kind::DroppedArgument: case Node::Kind::SpecializationPassID: case Node::Kind::Static: case Node::Kind::Subscript: @@ -645,9 +654,8 @@ class NodePrinter { case Node::Kind::SymbolicExtendedExistentialType: case Node::Kind::HasSymbolQuery: case Node::Kind::ObjectiveCProtocolSymbolicReference: - case Node::Kind::ParamLifetimeDependence: - case Node::Kind::SelfLifetimeDependence: case Node::Kind::DependentGenericInverseConformanceRequirement: + case Node::Kind::DependentGenericParamValueMarker: return false; } printer_unreachable("bad node kind"); @@ -890,6 +898,18 @@ class NodePrinter { // handled earlier ++startIndex; } + + // Be sure to check for function signature components in the same + // order that they're added by the demangler, which is the reverse + // of the order that they appear in the mangling grammar. + + if (node->getChild(startIndex)->getKind() == + Node::Kind::SendingResultFunctionType) { + ++startIndex; + hasSendingResult = true; + } + + // function-isolation; note that these can't actually both appear. if (node->getChild(startIndex)->getKind() == Node::Kind::IsolatedAnyFunctionType) { print(node->getChild(startIndex), depth + 1); @@ -900,17 +920,13 @@ class NodePrinter { print(node->getChild(startIndex), depth + 1); ++startIndex; } + if (node->getChild(startIndex)->getKind() == Node::Kind::DifferentiableFunctionType) { diffKind = (MangledDifferentiabilityKind)node->getChild(startIndex)->getIndex(); ++startIndex; } - if (node->getChild(startIndex)->getKind() == - Node::Kind::SelfLifetimeDependence) { - print(node->getChild(startIndex), depth + 1); - ++startIndex; - } Node *thrownErrorNode = nullptr; if (node->getChild(startIndex)->getKind() == Node::Kind::ThrowsAnnotation || @@ -929,11 +945,6 @@ class NodePrinter { ++startIndex; isAsync = true; } - if (node->getChild(startIndex)->getKind() == - Node::Kind::SendingResultFunctionType) { - ++startIndex; - hasSendingResult = true; - } switch (diffKind) { case MangledDifferentiabilityKind::Forward: @@ -1064,7 +1075,8 @@ class NodePrinter { auto child = Node->getChild(firstRequirement); if (child->getKind() == Node::Kind::Type) child = child->getChild(0); - if (child->getKind() != Node::Kind::DependentGenericParamPackMarker) { + if (child->getKind() != Node::Kind::DependentGenericParamPackMarker && + child->getKind() != Node::Kind::DependentGenericParamValueMarker) { break; } } @@ -1092,6 +1104,30 @@ class NodePrinter { return false; }; + auto isGenericParamValue = [&](unsigned depth, unsigned index) { + for (unsigned i = numGenericParams; i < firstRequirement; ++i) { + auto child = Node->getChild(i); + if (child->getKind() != Node::Kind::DependentGenericParamValueMarker) + continue; + child = child->getChild(0); + + if (child->getKind() != Node::Kind::Type) + continue; + + auto param = child->getChild(0); + auto type = child->getChild(1); + if (param->getKind() != Node::Kind::DependentGenericParamType) + continue; + + if (index == param->getChild(0)->getIndex() && + depth == param->getChild(1)->getIndex()) { + return std::make_pair(true, type); + } + } + + return std::make_pair(false, NodePointer()); + }; + unsigned gpDepth = 0; for (; gpDepth < numGenericParams; ++gpDepth) { if (gpDepth != 0) @@ -1113,9 +1149,19 @@ class NodePrinter { if (isGenericParamPack(gpDepth, index)) Printer << "each "; + auto value = isGenericParamValue(gpDepth, index); + + if (value.first) + Printer << "let "; + // FIXME: Depth won't match when a generic signature applies to a // method in generic type context. Printer << Options.GenericParameterName(gpDepth, index); + + if (value.second) { + Printer << ": "; + print(value.second, depth + 1); + } } } @@ -1296,7 +1342,7 @@ void NodePrinter::printSpecializationPrefix(NodePointer node, for (NodePointer child : *node) { switch (child->getKind()) { case Node::Kind::SpecializationPassID: - case Node::Kind::MetatypeParamsRemoved: + case Node::Kind::DroppedArgument: // We skip those nodes since it does not contain any // information that is useful to our users. break; @@ -1356,11 +1402,11 @@ static bool shouldShowEntityType(Node::Kind EntityKind, switch (EntityKind) { case Node::Kind::ExplicitClosure: case Node::Kind::ImplicitClosure: - // The signature of a closure (its `Type` node) can optionally be omitted. - // Unlike functions which can have overloads, the signature of a closure is - // not needed to be uniquely identified. A closure is uniquely identified by - // its index and parent. Omitting the signature improves the readability - // when long type names are in use. + /// The signature of a closure (its `Type` node) can optionally be omitted. + /// Unlike functions which can have overloads, the signature of a closure is + /// not needed to be uniquely identified. A closure is uniquely identified + /// by its index and parent. Omitting the signature improves the readability + /// when long type names are in use. return Options.ShowClosureSignature; default: return true; @@ -1392,6 +1438,14 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, Printer << "curry thunk of "; print(Node->getChild(0), depth + 1); return nullptr; + case Node::Kind::SILThunkIdentity: + Printer << "identity thunk of "; + print(Node->getChild(0), depth + 1); + return nullptr; + case Node::Kind::SILThunkHopToMainActorIfNeeded: + Printer << "hop to main actor thunk of "; + print(Node->getChild(0), depth + 1); + return nullptr; case Node::Kind::DispatchThunk: Printer << "dispatch thunk of "; print(Node->getChild(0), depth + 1); @@ -1783,33 +1837,6 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, Printer << "@noDerivative "; print(Node->getChild(0), depth + 1); return nullptr; - case Node::Kind::ParamLifetimeDependence: { - Printer << "lifetime dependence: "; - auto kind = (MangledLifetimeDependenceKind)Node->getChild(0)->getIndex(); - switch (kind) { - case MangledLifetimeDependenceKind::Inherit: - Printer << "inherit "; - break; - case MangledLifetimeDependenceKind::Scope: - Printer << "scope "; - break; - } - print(Node->getChild(1), depth + 1); - return nullptr; - } - case Node::Kind::SelfLifetimeDependence: { - Printer << "(self lifetime dependence: "; - auto kind = (MangledLifetimeDependenceKind)Node->getIndex(); - switch (kind) { - case MangledLifetimeDependenceKind::Inherit: - Printer << "inherit) "; - break; - case MangledLifetimeDependenceKind::Scope: - Printer << "scope) "; - break; - } - return nullptr; - } case Node::Kind::NonObjCAttribute: Printer << "@nonobjc "; return nullptr; @@ -1854,8 +1881,8 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, case Node::Kind::IsSerialized: Printer << "serialized"; return nullptr; - case Node::Kind::MetatypeParamsRemoved: - Printer << "metatypes-removed"; + case Node::Kind::DroppedArgument: + Printer << "param" << Node->getIndex() << "-removed"; return nullptr; case Node::Kind::GenericSpecializationParam: print(Node->getChild(0), depth + 1); @@ -1968,6 +1995,13 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, case Node::Kind::BuiltinTupleType: Printer << "Builtin.TheTupleType"; return nullptr; + case Node::Kind::BuiltinFixedArray: + Printer << "Builtin.FixedArray<"; + print(Node->getChild(0), depth + 1); + Printer << ", "; + print(Node->getChild(1), depth + 1); + Printer << ">"; + return nullptr; case Node::Kind::Number: Printer << Node->getIndex(); return nullptr; @@ -2717,9 +2751,15 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, case Node::Kind::ReadAccessor: return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext, "read"); + case Node::Kind::Read2Accessor: + return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext, + "read2"); case Node::Kind::ModifyAccessor: return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext, "modify"); + case Node::Kind::Modify2Accessor: + return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext, + "modify2"); case Node::Kind::InitAccessor: return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext, "init"); @@ -2740,6 +2780,12 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, /*hasName*/ false, isClassType(Node->getChild(0)) ? "__deallocating_deinit" : "deinit"); + case Node::Kind::IsolatedDeallocator: + return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType, + /*hasName*/ false, + isClassType(Node->getChild(0)) + ? "__isolated_deallocating_deinit" + : "deinit"); case Node::Kind::IVarInitializer: return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType, /*hasName*/ false, "__ivar_initializer"); @@ -2797,6 +2843,13 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, return nullptr; case Node::Kind::ImplErasedIsolation: Printer << "@isolated(any)"; + return nullptr; + case Node::Kind::ImplCoroutineKind: + // Skip if text is empty. + if (Node->getText().empty()) + return nullptr; + // Otherwise, print with leading @. + Printer << '@' << Node->getText(); return nullptr; case Node::Kind::ImplSendingResult: Printer << "sending"; @@ -2891,6 +2944,7 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, } case Node::Kind::DependentGenericParamCount: case Node::Kind::DependentGenericParamPackMarker: + case Node::Kind::DependentGenericParamValueMarker: printer_unreachable("should be printed as a child of a " "DependentGenericSignature"); case Node::Kind::DependentGenericConformanceRequirement: { @@ -3401,6 +3455,15 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, case Node::Kind::OpaqueReturnTypeIndex: case Node::Kind::OpaqueReturnTypeParent: return nullptr; + case Node::Kind::Integer: + Printer << Node->getIndex(); + return nullptr; + case Node::Kind::NegativeInteger: { + intptr_t signedValue = Node->getIndex(); + + Printer << signedValue; + return nullptr; + } } printer_unreachable("bad node kind!"); diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/OldDemangler.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/OldDemangler.cpp new file mode 100644 index 000000000..2a4b5f659 --- /dev/null +++ b/symbolic-demangle/vendor/swift/lib/Demangling/OldDemangler.cpp @@ -0,0 +1,2408 @@ +//===--- OldDemangler.cpp - Old Swift Demangling --------------------------===// +// +// 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 implements Swift symbol demangling with the old scheme. +// +//===----------------------------------------------------------------------===// + +#include "swift/Demangling/Demangle.h" +#include "swift/Demangling/Demangler.h" +#include "swift/Demangling/ManglingMacros.h" +#include "swift/Demangling/ManglingUtils.h" +#include "swift/Demangling/Punycode.h" +#include "swift/Strings.h" +#include +#include +#include +#include +#include + +using namespace swift; +using namespace Demangle; + +namespace { + struct FindPtr { + FindPtr(Node *v) : Target(v) {} + bool operator()(NodePointer sp) const { + return sp == Target; + } + private: + Node *Target; + }; +} // end anonymous namespace + +static bool isStartOfIdentifier(char c) { + if (c >= '0' && c <= '9') + return true; + return c == 'o'; +} + +static bool isStartOfNominalType(char c) { + switch (c) { + case 'C': + case 'V': + case 'O': + return true; + default: + return false; + } +} + +static bool isStartOfEntity(char c) { + switch (c) { + case 'F': + case 'I': + case 'v': + case 'P': + case 's': + case 'Z': + return true; + default: + return isStartOfNominalType(c); + } +} + +static Node::Kind nominalTypeMarkerToNodeKind(char c) { + if (c == 'C') + return Node::Kind::Class; + if (c == 'V') + return Node::Kind::Structure; + if (c == 'O') + return Node::Kind::Enum; + return Node::Kind::Identifier; +} + +namespace { + +/// A convenient class for parsing characters out of a string. +class NameSource { + StringRef Text; +public: + NameSource(StringRef text) : Text(text) {} + + /// Return whether there are at least len characters remaining. + bool hasAtLeast(size_t len) { return (len <= Text.size()); } + + bool isEmpty() { return Text.empty(); } + explicit operator bool() { return !isEmpty(); } + + /// Return the next character without claiming it. Asserts that + /// there is at least one remaining character. + char peek() { + if (isEmpty()) { + // Return an otherwise unused character to prevent crashes for malformed + // symbols. + return '.'; + } + return Text.front(); + } + + /// Claim and return the next character. Asserts that there is at + /// least one remaining character. + char next() { + char c = peek(); + if (!isEmpty()) + advanceOffset(1); + return c; + } + + /// Claim the next character if it exists and equals the given + /// character. + bool nextIf(char c) { + if (isEmpty() || peek() != c) return false; + advanceOffset(1); + return true; + } + + /// Claim the next few characters if they exactly match the given string. + bool nextIf(StringRef str) { + if (!Text.starts_with(str)) return false; + advanceOffset(str.size()); + return true; + } + + /// Return the next len characters without claiming them. Asserts + /// that there are at least so many characters. + StringRef slice(size_t len) { return Text.substr(0, len); } + + /// Return the current string ref without claiming any characters. + StringRef str() { return Text; } + + /// Claim the next len characters. + void advanceOffset(size_t len) { + Text = Text.substr(len); + } + + /// Claim and return all the rest of the characters. + StringRef getString() { + auto result = Text; + advanceOffset(Text.size()); + return result; + } + + bool readUntil(char c, std::string &result) { + std::optional c2; + while (!isEmpty() && (c2 = peek()).value() != c) { + result.push_back(c2.value()); + advanceOffset(1); + } + return c2.has_value() && c2.value() == c; + } +}; + +/// The main class for parsing a demangling tree out of a mangled string. +class OldDemangler { + std::vector Substitutions; + NameSource Mangled; + NodeFactory &Factory; + + static const unsigned MaxDepth = 1024; + +public: + OldDemangler(llvm::StringRef mangled, NodeFactory &Factory) + : Mangled(mangled), Factory(Factory) {} + +/// Try to demangle a child node of the given kind. If that fails, +/// return; otherwise add it to the parent. +#define DEMANGLE_CHILD_OR_RETURN(PARENT, CHILD_KIND, DEPTH) \ + do { \ + auto _node = demangle##CHILD_KIND(DEPTH); \ + if (!_node) \ + return nullptr; \ + addChild(PARENT, _node); \ + } while (false) + +/// Try to demangle a child node of the given kind. If that fails, +/// return; otherwise add it to the parent. +#define DEMANGLE_CHILD_AS_NODE_OR_RETURN(PARENT, CHILD_KIND, DEPTH) \ + do { \ + auto _kind = demangle##CHILD_KIND(DEPTH); \ + if (!_kind.has_value()) \ + return nullptr; \ + addChild(PARENT, \ + Factory.createNode(Node::Kind::CHILD_KIND, unsigned(*_kind))); \ + } while (false) + + /// Attempt to demangle the source string. The root node will + /// always be a Global. Extra characters at the end will be + /// tolerated (and included as a Suffix node as a child of the + /// Global). + /// + /// \return true if the mangling succeeded + NodePointer demangleTopLevel() { + if (!Mangled.nextIf("_T")) + return nullptr; + + NodePointer topLevel = Factory.createNode(Node::Kind::Global); + + // First demangle any specialization prefixes. + if (Mangled.nextIf("TS")) { + do { + DEMANGLE_CHILD_OR_RETURN(topLevel, SpecializedAttribute, 0); + + // The Substitution header does not share state with the rest + // of the mangling. + Substitutions.clear(); + } while (Mangled.nextIf("_TTS")); + + // Then check that we have a global. + if (!Mangled.nextIf("_T")) + return nullptr; + + } else if (Mangled.nextIf("To")) { + addChild(topLevel, Factory.createNode(Node::Kind::ObjCAttribute)); + } else if (Mangled.nextIf("TO")) { + addChild(topLevel, Factory.createNode(Node::Kind::NonObjCAttribute)); + } else if (Mangled.nextIf("TD")) { + addChild(topLevel, Factory.createNode(Node::Kind::DynamicAttribute)); + } else if (Mangled.nextIf("Td")) { + addChild(topLevel, Factory.createNode( + Node::Kind::DirectMethodReferenceAttribute)); + } else if (Mangled.nextIf("TV")) { + addChild(topLevel, Factory.createNode(Node::Kind::VTableAttribute)); + } + + DEMANGLE_CHILD_OR_RETURN(topLevel, Global, 0); + + // Add a suffix node if there's anything left unmangled. + if (!Mangled.isEmpty()) { + addChild(topLevel, Factory.createNode(Node::Kind::Suffix, + Mangled.getString())); + } + + return topLevel; + } + + NodePointer demangleTypeName(unsigned depth) { return demangleType(depth); } + +private: + enum class IsVariadic { + yes = true, no = false + }; + + void addChild(NodePointer Parent, NodePointer Child) { + Parent->addChild(Child, Factory); + } + + std::optional demangleDirectness(unsigned depth) { + if (Mangled.nextIf('d')) + return Directness::Direct; + if (Mangled.nextIf('i')) + return Directness::Indirect; + return std::nullopt; + } + + bool demangleNatural(Node::IndexType &num, unsigned depth) { + if (!Mangled) + return false; + char c = Mangled.next(); + if (c < '0' || c > '9') + return false; + num = (c - '0'); + while (true) { + if (!Mangled) { + return true; + } + c = Mangled.peek(); + if (c < '0' || c > '9') { + return true; + } else { + num = (10 * num) + (c - '0'); + } + Mangled.next(); + } + } + + bool demangleBuiltinSize(Node::IndexType &num, unsigned depth) { + if (!demangleNatural(num, depth + 1)) + return false; + if (Mangled.nextIf('_')) + return true; + return false; + } + + std::optional demangleValueWitnessKind(unsigned depth) { + char Code[2]; + if (!Mangled) + return std::nullopt; + Code[0] = Mangled.next(); + if (!Mangled) + return std::nullopt; + Code[1] = Mangled.next(); + + StringRef CodeStr(Code, 2); +#define VALUE_WITNESS(MANGLING, NAME) \ + if (CodeStr == #MANGLING) return ValueWitnessKind::NAME; +#include "swift/Demangling/ValueWitnessMangling.def" + + return std::nullopt; + } + + NodePointer demangleGlobal(unsigned depth) { + if (depth > OldDemangler::MaxDepth || !Mangled) + return nullptr; + + // Type metadata. + if (Mangled.nextIf('M')) { + if (Mangled.nextIf('P')) { + auto pattern = + Factory.createNode(Node::Kind::GenericTypeMetadataPattern); + DEMANGLE_CHILD_OR_RETURN(pattern, Type, depth + 1); + return pattern; + } + if (Mangled.nextIf('a')) { + auto accessor = + Factory.createNode(Node::Kind::TypeMetadataAccessFunction); + DEMANGLE_CHILD_OR_RETURN(accessor, Type, depth + 1); + return accessor; + } + if (Mangled.nextIf('L')) { + auto cache = Factory.createNode(Node::Kind::TypeMetadataLazyCache); + DEMANGLE_CHILD_OR_RETURN(cache, Type, depth + 1); + return cache; + } + if (Mangled.nextIf('m')) { + auto metaclass = Factory.createNode(Node::Kind::Metaclass); + DEMANGLE_CHILD_OR_RETURN(metaclass, Type, depth + 1); + return metaclass; + } + if (Mangled.nextIf('n')) { + auto nominalType = + Factory.createNode(Node::Kind::NominalTypeDescriptor); + DEMANGLE_CHILD_OR_RETURN(nominalType, Type, depth + 1); + return nominalType; + } + if (Mangled.nextIf('f')) { + auto metadata = Factory.createNode(Node::Kind::FullTypeMetadata); + DEMANGLE_CHILD_OR_RETURN(metadata, Type, depth + 1); + return metadata; + } + if (Mangled.nextIf('p')) { + auto metadata = Factory.createNode(Node::Kind::ProtocolDescriptor); + DEMANGLE_CHILD_OR_RETURN(metadata, ProtocolName, depth + 1); + return metadata; + } + auto metadata = Factory.createNode(Node::Kind::TypeMetadata); + DEMANGLE_CHILD_OR_RETURN(metadata, Type, depth + 1); + return metadata; + } + + // Partial application thunks. + if (Mangled.nextIf("PA")) { + Node::Kind kind = Node::Kind::PartialApplyForwarder; + if (Mangled.nextIf('o')) + kind = Node::Kind::PartialApplyObjCForwarder; + auto forwarder = Factory.createNode(kind); + if (Mangled.nextIf("__T")) + DEMANGLE_CHILD_OR_RETURN(forwarder, Global, depth + 1); + return forwarder; + } + + // Top-level types, for various consumers. + if (Mangled.nextIf('t')) { + auto type = Factory.createNode(Node::Kind::TypeMangling); + DEMANGLE_CHILD_OR_RETURN(type, Type, depth + 1); + return type; + } + + // Value witnesses. + if (Mangled.nextIf('w')) { + std::optional w = demangleValueWitnessKind(depth + 1); + if (!w.has_value()) + return nullptr; + auto witness = + Factory.createNode(Node::Kind::ValueWitness); + NodePointer Idx = Factory.createNode(Node::Kind::Index, + unsigned(w.value())); + witness->addChild(Idx, Factory); + DEMANGLE_CHILD_OR_RETURN(witness, Type, depth + 1); + return witness; + } + + // Offsets, value witness tables, and protocol witnesses. + if (Mangled.nextIf('W')) { + if (Mangled.nextIf('V')) { + auto witnessTable = Factory.createNode(Node::Kind::ValueWitnessTable); + DEMANGLE_CHILD_OR_RETURN(witnessTable, Type, depth + 1); + return witnessTable; + } + if (Mangled.nextIf('v')) { + auto fieldOffset = Factory.createNode(Node::Kind::FieldOffset); + DEMANGLE_CHILD_AS_NODE_OR_RETURN(fieldOffset, Directness, depth + 1); + DEMANGLE_CHILD_OR_RETURN(fieldOffset, Entity, depth + 1); + return fieldOffset; + } + if (Mangled.nextIf('P')) { + auto witnessTable = + Factory.createNode(Node::Kind::ProtocolWitnessTable); + DEMANGLE_CHILD_OR_RETURN(witnessTable, ProtocolConformance, depth + 1); + return witnessTable; + } + if (Mangled.nextIf('G')) { + auto witnessTable = + Factory.createNode(Node::Kind::GenericProtocolWitnessTable); + DEMANGLE_CHILD_OR_RETURN(witnessTable, ProtocolConformance, depth + 1); + return witnessTable; + } + if (Mangled.nextIf('I')) { + auto witnessTable = Factory.createNode( + Node::Kind::GenericProtocolWitnessTableInstantiationFunction); + DEMANGLE_CHILD_OR_RETURN(witnessTable, ProtocolConformance, depth + 1); + return witnessTable; + } + if (Mangled.nextIf('l')) { + auto accessor = + Factory.createNode(Node::Kind::LazyProtocolWitnessTableAccessor); + DEMANGLE_CHILD_OR_RETURN(accessor, Type, depth + 1); + DEMANGLE_CHILD_OR_RETURN(accessor, ProtocolConformance, depth + 1); + return accessor; + } + if (Mangled.nextIf('L')) { + auto accessor = + Factory.createNode(Node::Kind::LazyProtocolWitnessTableCacheVariable); + DEMANGLE_CHILD_OR_RETURN(accessor, Type, depth + 1); + DEMANGLE_CHILD_OR_RETURN(accessor, ProtocolConformance, depth + 1); + return accessor; + } + if (Mangled.nextIf('a')) { + auto tableTemplate = + Factory.createNode(Node::Kind::ProtocolWitnessTableAccessor); + DEMANGLE_CHILD_OR_RETURN(tableTemplate, ProtocolConformance, depth + 1); + return tableTemplate; + } + if (Mangled.nextIf('t')) { + auto accessor = Factory.createNode( + Node::Kind::AssociatedTypeMetadataAccessor); + DEMANGLE_CHILD_OR_RETURN(accessor, ProtocolConformance, depth + 1); + DEMANGLE_CHILD_OR_RETURN(accessor, DeclName, depth + 1); + return accessor; + } + if (Mangled.nextIf('T')) { + auto accessor = Factory.createNode( + Node::Kind::AssociatedTypeWitnessTableAccessor); + DEMANGLE_CHILD_OR_RETURN(accessor, ProtocolConformance, depth + 1); + DEMANGLE_CHILD_OR_RETURN(accessor, DeclName, depth + 1); + DEMANGLE_CHILD_OR_RETURN(accessor, ProtocolName, depth + 1); + return accessor; + } + return nullptr; + } + + // Other thunks. + if (Mangled.nextIf('T')) { + if (Mangled.nextIf('R')) { + auto thunk = Factory.createNode(Node::Kind::ReabstractionThunkHelper); + if (!demangleReabstractSignature(thunk, depth + 1)) + return nullptr; + return thunk; + } + if (Mangled.nextIf('r')) { + auto thunk = Factory.createNode(Node::Kind::ReabstractionThunk); + if (!demangleReabstractSignature(thunk, depth + 1)) + return nullptr; + return thunk; + } + if (Mangled.nextIf('W')) { + NodePointer thunk = Factory.createNode(Node::Kind::ProtocolWitness); + DEMANGLE_CHILD_OR_RETURN(thunk, ProtocolConformance, depth + 1); + // The entity is mangled in its own generic context. + DEMANGLE_CHILD_OR_RETURN(thunk, Entity, depth + 1); + return thunk; + } + return nullptr; + } + + // Everything else is just an entity. + return demangleEntity(depth + 1); + } + + NodePointer demangleGenericSpecialization(NodePointer specialization, + unsigned depth) { + if (depth > OldDemangler::MaxDepth) + return nullptr; + + while (!Mangled.nextIf('_')) { + // Otherwise, we have another parameter. Demangle the type. + NodePointer param = Factory.createNode(Node::Kind::GenericSpecializationParam); + DEMANGLE_CHILD_OR_RETURN(param, Type, depth + 1); + + // Then parse any conformances until we find an underscore. Pop off the + // underscore since it serves as the end of our mangling list. + while (!Mangled.nextIf('_')) { + DEMANGLE_CHILD_OR_RETURN(param, ProtocolConformance, depth + 1); + } + + // Add the parameter to our specialization list. + specialization->addChild(param, Factory); + } + + return specialization; + } + +/// TODO: This is an atrocity. Come up with a shorter name. +#define FUNCSIGSPEC_CREATE_PARAM_KIND(kind) \ + Factory.createNode( \ + Node::Kind::FunctionSignatureSpecializationParamKind, \ + Node::IndexType(FunctionSigSpecializationParamKind::kind)) + +#define FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(payload) \ + Factory.createNode(Node::Kind::FunctionSignatureSpecializationParamPayload, \ + payload) + + bool demangleFuncSigSpecializationConstantProp(NodePointer parent, + unsigned depth) { + // Then figure out what was actually constant propagated. First check if + // we have a function. + if (Mangled.nextIf("fr")) { + // Demangle the identifier + NodePointer name = demangleIdentifier(depth + 1); + if (!name || !Mangled.nextIf('_')) + return false; + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ConstantPropFunction), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(name->getText()), Factory); + return true; + } + + if (Mangled.nextIf('g')) { + NodePointer name = demangleIdentifier(depth + 1); + if (!name || !Mangled.nextIf('_')) + return false; + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ConstantPropGlobal), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(name->getText()), Factory); + return true; + } + + if (Mangled.nextIf('i')) { + std::string Str; + if (!Mangled.readUntil('_', Str) || !Mangled.nextIf('_')) + return false; + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ConstantPropInteger), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(Str), Factory); + return true; + } + + if (Mangled.nextIf("fl")) { + std::string Str; + if (!Mangled.readUntil('_', Str) || !Mangled.nextIf('_')) + return false; + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ConstantPropFloat), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(Str), Factory); + return true; + } + + if (Mangled.nextIf("s")) { + // Skip: 'e' encoding 'v' str. encoding is a 0 or 1 and str is a string of + // length less than or equal to 32. We do not specialize strings with a + // length greater than 32. + if (!Mangled.nextIf('e')) + return false; + char encoding = Mangled.peek(); + if (encoding != '0' && encoding != '1') + return false; + std::string encodingStr; + if (encoding == '0') + encodingStr += "u8"; + else + encodingStr += "u16"; + Mangled.advanceOffset(1); + + if (!Mangled.nextIf('v')) + return false; + NodePointer str = demangleIdentifier(depth + 1); + if (!str || !Mangled.nextIf('_')) + return false; + + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ConstantPropString), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(encodingStr), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(str->getText()), Factory); + return true; + } + + // Unknown constant prop specialization + return false; + } + + bool demangleFuncSigSpecializationClosureProp(NodePointer parent, + unsigned depth) { + // We don't actually demangle the function or types for now. But we do want + // to signal that we specialized a closure. + + NodePointer name = demangleIdentifier(depth + 1); + if (!name) { + return false; + } + + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_KIND(ClosureProp), Factory); + parent->addChild(FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(name->getText()), Factory); + + // Then demangle types until we fail. + NodePointer type = nullptr; + while (Mangled.peek() != '_' && (type = demangleType(depth + 1))) { + parent->addChild(type, Factory); + } + + // Eat last '_' + if (!Mangled.nextIf('_')) + return false; + + return true; + } + + NodePointer + demangleFunctionSignatureSpecialization(NodePointer specialization, + unsigned depth) { + // Until we hit the last '_' in our specialization info... + while (!Mangled.nextIf('_')) { + // Create the parameter. + NodePointer param = + Factory.createNode(Node::Kind::FunctionSignatureSpecializationParam); + + // First handle options. + if (Mangled.nextIf("n_")) { + // Leave the parameter empty. + } else if (Mangled.nextIf("cp")) { + if (!demangleFuncSigSpecializationConstantProp(param, depth + 1)) + return nullptr; + } else if (Mangled.nextIf("cl")) { + if (!demangleFuncSigSpecializationClosureProp(param, depth + 1)) + return nullptr; + } else if (Mangled.nextIf("i_")) { + auto result = FUNCSIGSPEC_CREATE_PARAM_KIND(BoxToValue); + if (!result) + return nullptr; + param->addChild(result, Factory); + } else if (Mangled.nextIf("k_")) { + auto result = FUNCSIGSPEC_CREATE_PARAM_KIND(BoxToStack); + if (!result) + return nullptr; + param->addChild(result, Factory); + } else if (Mangled.nextIf("r_")) { + auto result = FUNCSIGSPEC_CREATE_PARAM_KIND(InOutToOut); + if (!result) + return nullptr; + param->addChild(result, Factory); + } else { + // Otherwise handle option sets. + unsigned Value = 0; + if (Mangled.nextIf('d')) { + Value |= + unsigned(FunctionSigSpecializationParamKind::Dead); + } + + if (Mangled.nextIf('g')) { + Value |= + unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed); + } + + if (Mangled.nextIf('o')) { + Value |= + unsigned(FunctionSigSpecializationParamKind::GuaranteedToOwned); + } + + if (Mangled.nextIf('s')) { + Value |= unsigned(FunctionSigSpecializationParamKind::SROA); + } + + if (!Mangled.nextIf('_')) + return nullptr; + + if (!Value) + return nullptr; + + auto result = Factory.createNode( + Node::Kind::FunctionSignatureSpecializationParamKind, Value); + if (!result) + return nullptr; + param->addChild(result, Factory); + } + + specialization->addChild(param, Factory); + } + + return specialization; + } + +#undef FUNCSIGSPEC_CREATE_PARAM_KIND +#undef FUNCSIGSPEC_CREATE_PARAM_PAYLOAD + + NodePointer demangleSpecializedAttribute(unsigned depth) { + bool isNotReAbstracted = false; + if (Mangled.nextIf("g") || (isNotReAbstracted = Mangled.nextIf("r"))) { + auto spec = Factory.createNode(isNotReAbstracted ? + Node::Kind::GenericSpecializationNotReAbstracted : + Node::Kind::GenericSpecialization); + + // Create a node if the specialization is serialized. + if (Mangled.nextIf("q")) { + auto kind = Node::Kind::IsSerialized; + spec->addChild(Factory.createNode(kind), Factory); + } + + // Create a node for the pass id. + spec->addChild(Factory.createNode(Node::Kind::SpecializationPassID, + unsigned(Mangled.next() - 48)), Factory); + + // And then mangle the generic specialization. + return demangleGenericSpecialization(spec, depth + 1); + } + if (Mangled.nextIf("f")) { + auto spec = + Factory.createNode(Node::Kind::FunctionSignatureSpecialization); + + // Create a node if the specialization is serialized. + if (Mangled.nextIf("q")) { + auto kind = Node::Kind::IsSerialized; + spec->addChild(Factory.createNode(kind), Factory); + } + + // Add the pass id. + spec->addChild(Factory.createNode(Node::Kind::SpecializationPassID, + unsigned(Mangled.next() - 48)), Factory); + + // Then perform the function signature specialization. + return demangleFunctionSignatureSpecialization(spec, depth + 1); + } + + // We don't know how to handle this specialization. + return nullptr; + } + + NodePointer demangleDeclName(unsigned depth) { + // decl-name ::= local-decl-name + // local-decl-name ::= 'L' index identifier + if (Mangled.nextIf('L')) { + NodePointer discriminator = demangleIndexAsNode(depth + 1); + if (!discriminator) return nullptr; + + NodePointer name = demangleIdentifier(depth + 1); + if (!name) return nullptr; + + NodePointer localName = Factory.createNode(Node::Kind::LocalDeclName); + localName->addChild(discriminator, Factory); + localName->addChild(name, Factory); + return localName; + + } else if (Mangled.nextIf('P')) { + NodePointer discriminator = demangleIdentifier(depth + 1); + if (!discriminator) return nullptr; + + NodePointer name = demangleIdentifier(depth + 1); + if (!name) return nullptr; + + auto privateName = Factory.createNode(Node::Kind::PrivateDeclName); + privateName->addChild(discriminator, Factory); + privateName->addChild(name, Factory); + return privateName; + } + + // decl-name ::= identifier + return demangleIdentifier(depth + 1); + } + + NodePointer + demangleIdentifier(unsigned depth, + std::optional kind = std::nullopt) { + if (!Mangled) + return nullptr; + + bool isPunycoded = Mangled.nextIf('X'); + std::string decodeBuffer; + + auto decode = [&](StringRef s) -> StringRef { + if (!isPunycoded) + return s; + if (!Punycode::decodePunycodeUTF8(s, decodeBuffer)) + return {}; + return decodeBuffer; + }; + + bool isOperator = false; + if (Mangled.nextIf('o')) { + isOperator = true; + // Operator identifiers aren't valid in the contexts that are + // building more specific identifiers. + if (kind.has_value()) return nullptr; + + char op_mode = Mangled.next(); + switch (op_mode) { + case 'p': + kind = Node::Kind::PrefixOperator; + break; + case 'P': + kind = Node::Kind::PostfixOperator; + break; + case 'i': + kind = Node::Kind::InfixOperator; + break; + default: + return nullptr; + } + } + + if (!kind.has_value()) kind = Node::Kind::Identifier; + + Node::IndexType length; + if (!demangleNatural(length, depth + 1)) + return nullptr; + if (!Mangled.hasAtLeast(length)) + return nullptr; + + StringRef identifier = Mangled.slice(length); + Mangled.advanceOffset(length); + + // Decode Unicode identifiers. + identifier = decode(identifier); + if (identifier.empty()) + return nullptr; + + // Decode operator names. + std::string opDecodeBuffer; + if (isOperator) { + // abcdefghijklmnopqrstuvwxyz + static const char op_char_table[] = "& @/= > <*!|+?%-~ ^ ."; + + opDecodeBuffer.reserve(identifier.size()); + for (signed char c : identifier) { + if (c < 0) { + // Pass through Unicode characters. + opDecodeBuffer.push_back(c); + continue; + } + if (c < 'a' || c > 'z') + return nullptr; + char o = op_char_table[c - 'a']; + if (o == ' ') + return nullptr; + opDecodeBuffer.push_back(o); + } + identifier = opDecodeBuffer; + } + + return Factory.createNode(*kind, identifier); + } + + bool demangleIndex(Node::IndexType &natural, unsigned depth) { + if (Mangled.nextIf('_')) { + natural = 0; + return true; + } + if (demangleNatural(natural, depth + 1)) { + if (!Mangled.nextIf('_')) + return false; + ++natural; + return true; + } + return false; + } + + /// Demangle an and package it as a node of some kind. + NodePointer demangleIndexAsNode(unsigned depth, + Node::Kind kind = Node::Kind::Number) { + Node::IndexType index; + if (!demangleIndex(index, depth)) + return nullptr; + return Factory.createNode(kind, index); + } + + NodePointer createSwiftType(Node::Kind typeKind, StringRef name) { + NodePointer type = Factory.createNode(typeKind); + type->addChild(Factory.createNode(Node::Kind::Module, STDLIB_NAME), Factory); + type->addChild(Factory.createNode(Node::Kind::Identifier, name), Factory); + return type; + } + + /// Demangle a , given that we've already consumed the 'S'. + NodePointer demangleSubstitutionIndex(unsigned depth) { + if (!Mangled) + return nullptr; + if (Mangled.nextIf('o')) + return Factory.createNode(Node::Kind::Module, MANGLING_MODULE_OBJC); + if (Mangled.nextIf('C')) + return Factory.createNode(Node::Kind::Module, + MANGLING_MODULE_CLANG_IMPORTER); + if (Mangled.nextIf('a')) + return createSwiftType(Node::Kind::Structure, "Array"); + if (Mangled.nextIf('b')) + return createSwiftType(Node::Kind::Structure, "Bool"); + if (Mangled.nextIf('c')) + return createSwiftType(Node::Kind::Structure, "UnicodeScalar"); + if (Mangled.nextIf('d')) + return createSwiftType(Node::Kind::Structure, "Double"); + if (Mangled.nextIf('f')) + return createSwiftType(Node::Kind::Structure, "Float"); + if (Mangled.nextIf('i')) + return createSwiftType(Node::Kind::Structure, "Int"); + if (Mangled.nextIf('V')) + return createSwiftType(Node::Kind::Structure, "UnsafeRawPointer"); + if (Mangled.nextIf('v')) + return createSwiftType(Node::Kind::Structure, "UnsafeMutableRawPointer"); + if (Mangled.nextIf('P')) + return createSwiftType(Node::Kind::Structure, "UnsafePointer"); + if (Mangled.nextIf('p')) + return createSwiftType(Node::Kind::Structure, "UnsafeMutablePointer"); + if (Mangled.nextIf('q')) + return createSwiftType(Node::Kind::Enum, "Optional"); + if (Mangled.nextIf('Q')) + return createSwiftType(Node::Kind::Enum, "ImplicitlyUnwrappedOptional"); + if (Mangled.nextIf('R')) + return createSwiftType(Node::Kind::Structure, "UnsafeBufferPointer"); + if (Mangled.nextIf('r')) + return createSwiftType(Node::Kind::Structure, "UnsafeMutableBufferPointer"); + if (Mangled.nextIf('S')) + return createSwiftType(Node::Kind::Structure, "String"); + if (Mangled.nextIf('u')) + return createSwiftType(Node::Kind::Structure, "UInt"); + Node::IndexType index_sub; + if (!demangleIndex(index_sub, depth)) + return nullptr; + if (index_sub >= Substitutions.size()) + return nullptr; + return Substitutions[index_sub]; + } + + NodePointer demangleModule(unsigned depth) { + if (Mangled.nextIf('s')) { + return Factory.createNode(Node::Kind::Module, STDLIB_NAME); + } + if (Mangled.nextIf('S')) { + NodePointer module = demangleSubstitutionIndex(depth + 1); + if (!module) + return nullptr; + if (module->getKind() != Node::Kind::Module) + return nullptr; + return module; + } + + NodePointer module = demangleIdentifier(depth + 1, Node::Kind::Module); + if (!module) return nullptr; + Substitutions.push_back(module); + return module; + } + + NodePointer demangleDeclarationName(Node::Kind kind, unsigned depth) { + NodePointer context = demangleContext(depth + 1); + if (!context) return nullptr; + + auto name = demangleDeclName(depth + 1); + if (!name) return nullptr; + + auto decl = Factory.createNode(kind); + decl->addChild(context, Factory); + decl->addChild(name, Factory); + Substitutions.push_back(decl); + return decl; + } + + NodePointer demangleProtocolName(unsigned depth) { + NodePointer proto = demangleProtocolNameImpl(depth); + if (!proto) return nullptr; + + NodePointer type = Factory.createNode(Node::Kind::Type); + type->addChild(proto, Factory); + return type; + } + + NodePointer demangleProtocolNameGivenContext(NodePointer context, + unsigned depth) { + NodePointer name = demangleDeclName(depth + 1); + if (!name) return nullptr; + + auto proto = Factory.createNode(Node::Kind::Protocol); + proto->addChild(context, Factory); + proto->addChild(name, Factory); + Substitutions.push_back(proto); + return proto; + } + + NodePointer demangleProtocolNameImpl(unsigned depth) { + if (depth > OldDemangler::MaxDepth) + return nullptr; + + // There's an ambiguity in between a substitution of + // the protocol and a substitution of the protocol's context, so + // we have to duplicate some of the logic from + // demangleDeclarationName. + if (Mangled.nextIf('S')) { + NodePointer sub = demangleSubstitutionIndex(depth + 1); + if (!sub) return nullptr; + if (sub->getKind() == Node::Kind::Protocol) + return sub; + + if (sub->getKind() != Node::Kind::Module) + return nullptr; + + return demangleProtocolNameGivenContext(sub, depth + 1); + } + + if (Mangled.nextIf('s')) { + NodePointer stdlib = Factory.createNode(Node::Kind::Module, STDLIB_NAME); + + return demangleProtocolNameGivenContext(stdlib, depth + 1); + } + + return demangleDeclarationName(Node::Kind::Protocol, depth + 1); + } + + NodePointer demangleNominalType(unsigned depth) { + if (Mangled.nextIf('S')) + return demangleSubstitutionIndex(depth + 1); + if (Mangled.nextIf('V')) + return demangleDeclarationName(Node::Kind::Structure, depth + 1); + if (Mangled.nextIf('O')) + return demangleDeclarationName(Node::Kind::Enum, depth + 1); + if (Mangled.nextIf('C')) + return demangleDeclarationName(Node::Kind::Class, depth + 1); + if (Mangled.nextIf('P')) + return demangleDeclarationName(Node::Kind::Protocol, depth + 1); + return nullptr; + } + + NodePointer demangleBoundGenericArgs(NodePointer nominalType, + unsigned depth) { + if (nominalType->getNumChildren() == 0) + return nullptr; + + // Generic arguments for the outermost type come first. + NodePointer parentOrModule = nominalType->getChild(0); + + if (parentOrModule->getKind() != Node::Kind::Module && + parentOrModule->getKind() != Node::Kind::Function && + parentOrModule->getKind() != Node::Kind::Extension) { + parentOrModule = demangleBoundGenericArgs(parentOrModule, depth + 1); + if (!parentOrModule) + return nullptr; + + // Rebuild this type with the new parent type, which may have + // had its generic arguments applied. + NodePointer result = Factory.createNode(nominalType->getKind()); + result->addChild(parentOrModule, Factory); + for (unsigned ndx = 1; ndx < nominalType->getNumChildren(); ++ndx) + result->addChild(nominalType->getChild(ndx), Factory); + + nominalType = result; + } + + NodePointer args = Factory.createNode(Node::Kind::TypeList); + while (!Mangled.nextIf('_')) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + args->addChild(type, Factory); + if (Mangled.isEmpty()) + return nullptr; + } + + // If there were no arguments at this level there is nothing left + // to do. + if (args->getNumChildren() == 0) + return nominalType; + + // Otherwise, build a bound generic type node from the unbound + // type and arguments. + NodePointer unboundType = Factory.createNode(Node::Kind::Type); + unboundType->addChild(nominalType, Factory); + + Node::Kind kind; + switch (nominalType->getKind()) { // look through Type node + case Node::Kind::Class: + kind = Node::Kind::BoundGenericClass; + break; + case Node::Kind::Structure: + kind = Node::Kind::BoundGenericStructure; + break; + case Node::Kind::Enum: + kind = Node::Kind::BoundGenericEnum; + break; + default: + return nullptr; + } + NodePointer result = Factory.createNode(kind); + result->addChild(unboundType, Factory); + result->addChild(args, Factory); + return result; + } + + NodePointer demangleBoundGenericType(unsigned depth) { + // bound-generic-type ::= 'G' nominal-type (args+ '_')+ + // + // Each level of nominal type nesting has its own list of arguments. + + NodePointer nominalType = demangleNominalType(depth + 1); + if (!nominalType) + return nullptr; + + return demangleBoundGenericArgs(nominalType, depth + 1); + } + + NodePointer demangleContext(unsigned depth) { + // context ::= module + // context ::= entity + // context ::= 'E' module context (extension defined in a different module) + // context ::= 'e' module context generic-signature (constrained extension) + if (!Mangled) return nullptr; + if (Mangled.nextIf('E')) { + NodePointer ext = Factory.createNode(Node::Kind::Extension); + NodePointer def_module = demangleModule(depth + 1); + if (!def_module) return nullptr; + NodePointer type = demangleContext(depth + 1); + if (!type) return nullptr; + ext->addChild(def_module, Factory); + ext->addChild(type, Factory); + return ext; + } + if (Mangled.nextIf('e')) { + NodePointer ext = Factory.createNode(Node::Kind::Extension); + NodePointer def_module = demangleModule(depth + 1); + if (!def_module) return nullptr; + NodePointer sig = demangleGenericSignature(depth + 1); + // The generic context is currently re-specified by the type mangling. + // If we ever remove 'self' from manglings, we should stop resetting the + // context here. + if (!sig) return nullptr; + NodePointer type = demangleContext(depth + 1); + if (!type) return nullptr; + + ext->addChild(def_module, Factory); + ext->addChild(type, Factory); + ext->addChild(sig, Factory); + return ext; + } + if (Mangled.nextIf('S')) + return demangleSubstitutionIndex(depth + 1); + if (Mangled.nextIf('s')) + return Factory.createNode(Node::Kind::Module, STDLIB_NAME); + if (Mangled.nextIf('G')) + return demangleBoundGenericType(depth + 1); + if (isStartOfEntity(Mangled.peek())) + return demangleEntity(depth + 1); + return demangleModule(depth + 1); + } + + NodePointer demangleProtocolList(unsigned depth) { + NodePointer proto_list = Factory.createNode(Node::Kind::ProtocolList); + NodePointer type_list = Factory.createNode(Node::Kind::TypeList); + proto_list->addChild(type_list, Factory); + while (!Mangled.nextIf('_')) { + NodePointer proto = demangleProtocolName(depth + 1); + if (!proto) + return nullptr; + type_list->addChild(proto, Factory); + } + return proto_list; + } + + NodePointer demangleProtocolConformance(unsigned depth) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer protocol = demangleProtocolName(depth + 1); + if (!protocol) + return nullptr; + NodePointer context = demangleContext(depth + 1); + if (!context) + return nullptr; + NodePointer proto_conformance = + Factory.createNode(Node::Kind::ProtocolConformance); + proto_conformance->addChild(type, Factory); + proto_conformance->addChild(protocol, Factory); + proto_conformance->addChild(context, Factory); + return proto_conformance; + } + + // entity ::= entity-kind context entity-name + // entity ::= nominal-type + NodePointer demangleEntity(unsigned depth) { + if (depth > OldDemangler::MaxDepth) + return nullptr; + + // static? + bool isStatic = Mangled.nextIf('Z'); + + // entity-kind + Node::Kind entityBasicKind; + if (Mangled.nextIf('F')) { + entityBasicKind = Node::Kind::Function; + } else if (Mangled.nextIf('v')) { + entityBasicKind = Node::Kind::Variable; + } else if (Mangled.nextIf('I')) { + entityBasicKind = Node::Kind::Initializer; + } else if (Mangled.nextIf('i')) { + entityBasicKind = Node::Kind::Subscript; + } else { + return demangleNominalType(depth + 1); + } + + NodePointer context = demangleContext(depth + 1); + if (!context) return nullptr; + + // entity-name + Node::Kind entityKind; + bool hasType = true; + // Wrap the enclosed entity in a variable or subscript node + bool wrapEntity = false; + NodePointer name = nullptr; + if (Mangled.nextIf('D')) { + entityKind = Node::Kind::Deallocator; + hasType = false; + } else if (Mangled.nextIf('Z')) { + entityKind = Node::Kind::IsolatedDeallocator; + hasType = false; + } else if (Mangled.nextIf('d')) { + entityKind = Node::Kind::Destructor; + hasType = false; + } else if (Mangled.nextIf('e')) { + entityKind = Node::Kind::IVarInitializer; + hasType = false; + } else if (Mangled.nextIf('E')) { + entityKind = Node::Kind::IVarDestroyer; + hasType = false; + } else if (Mangled.nextIf('C')) { + entityKind = Node::Kind::Allocator; + } else if (Mangled.nextIf('c')) { + entityKind = Node::Kind::Constructor; + } else if (Mangled.nextIf('a')) { + wrapEntity = true; + if (Mangled.nextIf('O')) { + entityKind = Node::Kind::OwningMutableAddressor; + } else if (Mangled.nextIf('o')) { + entityKind = Node::Kind::NativeOwningMutableAddressor; + } else if (Mangled.nextIf('p')) { + entityKind = Node::Kind::NativePinningMutableAddressor; + } else if (Mangled.nextIf('u')) { + entityKind = Node::Kind::UnsafeMutableAddressor; + } else { + return nullptr; + } + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('l')) { + wrapEntity = true; + if (Mangled.nextIf('O')) { + entityKind = Node::Kind::OwningAddressor; + } else if (Mangled.nextIf('o')) { + entityKind = Node::Kind::NativeOwningAddressor; + } else if (Mangled.nextIf('p')) { + entityKind = Node::Kind::NativePinningAddressor; + } else if (Mangled.nextIf('u')) { + entityKind = Node::Kind::UnsafeAddressor; + } else { + return nullptr; + } + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('g')) { + wrapEntity = true; + entityKind = Node::Kind::Getter; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('G')) { + wrapEntity = true; + entityKind = Node::Kind::GlobalGetter; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('s')) { + wrapEntity = true; + entityKind = Node::Kind::Setter; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('m')) { + wrapEntity = true; + entityKind = Node::Kind::MaterializeForSet; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('w')) { + wrapEntity = true; + entityKind = Node::Kind::WillSet; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('W')) { + wrapEntity = true; + entityKind = Node::Kind::DidSet; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('r')) { + wrapEntity = true; + entityKind = Node::Kind::ReadAccessor; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('M')) { + wrapEntity = true; + entityKind = Node::Kind::ModifyAccessor; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('U')) { + entityKind = Node::Kind::ExplicitClosure; + name = demangleIndexAsNode(depth + 1); + if (!name) return nullptr; + } else if (Mangled.nextIf('u')) { + entityKind = Node::Kind::ImplicitClosure; + name = demangleIndexAsNode(depth + 1); + if (!name) return nullptr; + } else if (entityBasicKind == Node::Kind::Initializer) { + // entity-name ::= 'A' index + if (Mangled.nextIf('A')) { + entityKind = Node::Kind::DefaultArgumentInitializer; + name = demangleIndexAsNode(depth + 1); + if (!name) return nullptr; + // entity-name ::= 'i' + } else if (Mangled.nextIf('i')) { + entityKind = Node::Kind::Initializer; + } else { + return nullptr; + } + hasType = false; + } else { + entityKind = entityBasicKind; + name = demangleDeclName(depth + 1); + if (!name) return nullptr; + } + + NodePointer entity = Factory.createNode(entityKind); + if (wrapEntity) { + // Create a subscript or variable node and make it the accessor's child + NodePointer wrappedEntity; + bool isSubscript = false; + + // Rewrite the subscript's name to match the new mangling scheme + switch (name->getKind()) { + case Node::Kind::Identifier: + if (name->getText() == "subscript") { + isSubscript = true; + // Subscripts have no 'subscript' identifier name + name = nullptr; + } + break; + case Node::Kind::PrivateDeclName: // identifier file-discriminator? + if (name->getNumChildren() > 1 && + name->getChild(1)->getText() == "subscript") { + isSubscript = true; + + auto discriminator = name->getChild(0); + + // Create new PrivateDeclName with no 'subscript' identifier child + name = Factory.createNode(Node::Kind::PrivateDeclName); + name->addChild(discriminator, Factory); + } + break; + default: + break; + } + + // Create wrapped entity node + if (isSubscript) { + wrappedEntity = Factory.createNode(Node::Kind::Subscript); + } else { + wrappedEntity = Factory.createNode(Node::Kind::Variable); + } + wrappedEntity->addChild(context, Factory); + + // Variables mangle their name before their type + if (!isSubscript) + wrappedEntity->addChild(name, Factory); + + if (hasType) { + auto type = demangleType(depth + 1); + if (!type) return nullptr; + wrappedEntity->addChild(type, Factory); + } + + // Subscripts mangle their file-discriminator after the type + if (isSubscript && name) + wrappedEntity->addChild(name, Factory); + + entity->addChild(wrappedEntity, Factory); + } else { + entity->addChild(context, Factory); + + if (name) entity->addChild(name, Factory); + + if (hasType) { + auto type = demangleType(depth + 1); + if (!type) return nullptr; + entity->addChild(type, Factory); + } + } + + if (isStatic) { + auto staticNode = Factory.createNode(Node::Kind::Static); + staticNode->addChild(entity, Factory); + return staticNode; + } + + return entity; + } + + NodePointer getDependentGenericParamType(unsigned depth, unsigned index) { + DemanglerPrinter PrintName; + PrintName << genericParameterName(depth, index); + + auto paramTy = Factory.createNode(Node::Kind::DependentGenericParamType); + paramTy->addChild(Factory.createNode(Node::Kind::Index, depth), Factory); + paramTy->addChild(Factory.createNode(Node::Kind::Index, index), Factory); + + return paramTy; + } + + NodePointer demangleGenericParamIndex(unsigned depth) { + Node::IndexType paramDepth, index; + + if (Mangled.nextIf('d')) { + if (!demangleIndex(paramDepth, depth + 1)) + return nullptr; + paramDepth += 1; + if (!demangleIndex(index, depth + 1)) + return nullptr; + } else if (Mangled.nextIf('x')) { + paramDepth = 0; + index = 0; + } else { + if (!demangleIndex(index, depth + 1)) + return nullptr; + paramDepth = 0; + index += 1; + } + return getDependentGenericParamType(paramDepth, index); + } + + NodePointer demangleDependentMemberTypeName(NodePointer base, + unsigned depth) { + assert(base->getKind() == Node::Kind::Type + && "base should be a type"); + NodePointer assocTy = nullptr; + + if (Mangled.nextIf('S')) { + assocTy = demangleSubstitutionIndex(depth + 1); + if (!assocTy) + return nullptr; + if (assocTy->getKind() != Node::Kind::DependentAssociatedTypeRef) + return nullptr; + } else { + NodePointer protocol = nullptr; + if (Mangled.nextIf('P')) { + protocol = demangleProtocolName(depth + 1); + if (!protocol) return nullptr; + } + + // TODO: If the protocol name was elided from the assoc type mangling, + // we could try to fish it out of the generic signature constraints on the + // base. + NodePointer ID = demangleIdentifier(depth + 1); + if (!ID) return nullptr; + assocTy = Factory.createNode(Node::Kind::DependentAssociatedTypeRef); + if (!assocTy) return nullptr; + assocTy->addChild(ID, Factory); + if (protocol) + assocTy->addChild(protocol, Factory); + + Substitutions.push_back(assocTy); + } + + NodePointer depTy = Factory.createNode(Node::Kind::DependentMemberType); + depTy->addChild(base, Factory); + depTy->addChild(assocTy, Factory); + return depTy; + } + + NodePointer demangleAssociatedTypeSimple(unsigned depth) { + // Demangle the base type. + auto base = demangleGenericParamIndex(depth + 1); + if (!base) + return nullptr; + + NodePointer nodeType = Factory.createNode(Node::Kind::Type); + nodeType->addChild(base, Factory); + + // Demangle the associated type name. + return demangleDependentMemberTypeName(nodeType, depth + 1); + } + + NodePointer demangleAssociatedTypeCompound(unsigned depth) { + // Demangle the base type. + auto base = demangleGenericParamIndex(depth + 1); + if (!base) + return nullptr; + + // Demangle the associated type chain. + while (!Mangled.nextIf('_')) { + NodePointer nodeType = Factory.createNode(Node::Kind::Type); + nodeType->addChild(base, Factory); + + base = demangleDependentMemberTypeName(nodeType, depth + 1); + if (!base) + return nullptr; + } + + return base; + } + + NodePointer demangleDependentType(unsigned depth) { + if (!Mangled) + return nullptr; + + // A dependent member type begins with a non-index, non-'d' character. + auto c = Mangled.peek(); + if (c != 'd' && c != '_' && !Mangle::isDigit(c)) { + NodePointer baseType = demangleType(depth + 1); + if (!baseType) return nullptr; + return demangleDependentMemberTypeName(baseType, depth + 1); + } + + // Otherwise, we have a generic parameter. + return demangleGenericParamIndex(depth + 1); + } + + NodePointer demangleConstrainedTypeImpl(unsigned depth) { + // The constrained type can only be a generic parameter or an associated + // type thereof. The 'q' introducer is thus left off of generic params. + if (Mangled.nextIf('w')) { + return demangleAssociatedTypeSimple(depth + 1); + } + if (Mangled.nextIf('W')) { + return demangleAssociatedTypeCompound(depth + 1); + } + return demangleGenericParamIndex(depth + 1); + } + + NodePointer demangleConstrainedType(unsigned depth) { + auto type = demangleConstrainedTypeImpl(depth); + if (!type) + return nullptr; + + NodePointer nodeType = Factory.createNode(Node::Kind::Type); + nodeType->addChild(type, Factory); + return nodeType; + } + + NodePointer demangleGenericSignature(unsigned depth, + bool isPseudogeneric = false) { + auto sig = + Factory.createNode(isPseudogeneric + ? Node::Kind::DependentPseudogenericSignature + : Node::Kind::DependentGenericSignature); + // First read in the parameter counts at each depth. + Node::IndexType count = ~(Node::IndexType)0; + + auto addCount = [&]{ + auto countNode = + Factory.createNode(Node::Kind::DependentGenericParamCount, count); + sig->addChild(countNode, Factory); + }; + + while (Mangled.peek() != 'R' && Mangled.peek() != 'r') { + if (Mangled.nextIf('z')) { + count = 0; + } else if (demangleIndex(count, depth + 1)) { + count += 1; + } else { + return nullptr; + } + addCount(); + } + + // No mangled parameters means we have exactly one. + if (count == ~(Node::IndexType)0) { + count = 1; + addCount(); + } + + // Next read in the generic requirements, if any. + if (Mangled.nextIf('r')) + return sig; + + if (!Mangled.nextIf('R')) + return nullptr; + + while (!Mangled.nextIf('r')) { + NodePointer reqt = demangleGenericRequirement(depth + 1); + if (!reqt) return nullptr; + sig->addChild(reqt, Factory); + } + + return sig; + } + + NodePointer demangleMetatypeRepresentation(unsigned depth) { + if (Mangled.nextIf('t')) + return Factory.createNode(Node::Kind::MetatypeRepresentation, "@thin"); + + if (Mangled.nextIf('T')) + return Factory.createNode(Node::Kind::MetatypeRepresentation, "@thick"); + + if (Mangled.nextIf('o')) + return Factory.createNode(Node::Kind::MetatypeRepresentation, + "@objc_metatype"); + + // Unknown metatype representation + return nullptr; + } + + NodePointer demangleGenericRequirement(unsigned depth) { + NodePointer constrainedType = demangleConstrainedType(depth + 1); + if (!constrainedType) + return nullptr; + if (Mangled.nextIf('z')) { + NodePointer second = demangleType(depth + 1); + if (!second) return nullptr; + auto reqt = Factory.createNode( + Node::Kind::DependentGenericSameTypeRequirement); + reqt->addChild(constrainedType, Factory); + reqt->addChild(second, Factory); + return reqt; + } + + if (Mangled.nextIf('l')) { + StringRef name; + Node::Kind kind; + Node::IndexType size = SIZE_MAX; + Node::IndexType alignment = SIZE_MAX; + if (Mangled.nextIf('U')) { + kind = Node::Kind::Identifier; + name = "U"; + } else if (Mangled.nextIf('R')) { + kind = Node::Kind::Identifier; + name = "R"; + } else if (Mangled.nextIf('N')) { + kind = Node::Kind::Identifier; + name = "N"; + } else if (Mangled.nextIf('T')) { + kind = Node::Kind::Identifier; + name = "T"; + } else if (Mangled.nextIf('B')) { + kind = Node::Kind::Identifier; + name = "B"; + } else if (Mangled.nextIf('E')) { + kind = Node::Kind::Identifier; + if (!demangleNatural(size, depth + 1)) + return nullptr; + if (!Mangled.nextIf('_')) + return nullptr; + if (!demangleNatural(alignment, depth + 1)) + return nullptr; + name = "E"; + } else if (Mangled.nextIf('e')) { + kind = Node::Kind::Identifier; + if (!demangleNatural(size, depth + 1)) + return nullptr; + name = "e"; + } else if (Mangled.nextIf('M')) { + kind = Node::Kind::Identifier; + if (!demangleNatural(size, depth + 1)) + return nullptr; + if (!Mangled.nextIf('_')) + return nullptr; + if (!demangleNatural(alignment, depth + 1)) + return nullptr; + name = "M"; + } else if (Mangled.nextIf('m')) { + kind = Node::Kind::Identifier; + if (!demangleNatural(size, depth + 1)) + return nullptr; + name = "m"; + } else if (Mangled.nextIf('S')) { + kind = Node::Kind::Identifier; + if (!demangleNatural(size, depth + 1)) + return nullptr; + name = "S"; + } else { + return nullptr; + } + + NodePointer second = Factory.createNode(kind, name); + if (!second) return nullptr; + auto reqt = Factory.createNode( + Node::Kind::DependentGenericLayoutRequirement); + reqt->addChild(constrainedType, Factory); + reqt->addChild(second, Factory); + if (size != SIZE_MAX) { + reqt->addChild(Factory.createNode(Node::Kind::Number, size), Factory); + if (alignment != SIZE_MAX) + reqt->addChild(Factory.createNode(Node::Kind::Number, alignment), Factory); + } + return reqt; + } + + // Base class constraints are introduced by a class type mangling, which + // will begin with either 'C' or 'S'. + if (!Mangled) + return nullptr; + NodePointer constraint = nullptr; + + auto next = Mangled.peek(); + + if (next == 'C') { + constraint = demangleType(depth + 1); + if (!constraint) return nullptr; + } else if (next == 'S') { + // A substitution may be either the module name of a protocol or a full + // type name. + NodePointer typeName = nullptr; + Mangled.next(); + NodePointer sub = demangleSubstitutionIndex(depth + 1); + if (!sub) return nullptr; + if (sub->getKind() == Node::Kind::Protocol + || sub->getKind() == Node::Kind::Class) { + typeName = sub; + } else if (sub->getKind() == Node::Kind::Module) { + typeName = demangleProtocolNameGivenContext(sub, depth + 1); + if (!typeName) + return nullptr; + } else { + return nullptr; + } + constraint = Factory.createNode(Node::Kind::Type); + constraint->addChild(typeName, Factory); + } else { + constraint = demangleProtocolName(depth + 1); + if (!constraint) + return nullptr; + } + auto reqt = Factory.createNode( + Node::Kind::DependentGenericConformanceRequirement); + reqt->addChild(constrainedType, Factory); + reqt->addChild(constraint, Factory); + return reqt; + } + + NodePointer demangleArchetypeType(unsigned depth) { + auto makeAssociatedType = [&](NodePointer root) -> NodePointer { + NodePointer name = demangleIdentifier(depth + 1); + if (!name) + return nullptr; + auto assocType = Factory.createNode(Node::Kind::AssociatedTypeRef); + assocType->addChild(root, Factory); + assocType->addChild(name, Factory); + Substitutions.push_back(assocType); + return assocType; + }; + + if (Mangled.nextIf('Q')) { + NodePointer root = demangleArchetypeType(depth + 1); + if (!root) return nullptr; + return makeAssociatedType(root); + } + if (Mangled.nextIf('S')) { + NodePointer sub = demangleSubstitutionIndex(depth + 1); + if (!sub) return nullptr; + return makeAssociatedType(sub); + } + if (Mangled.nextIf('s')) { + NodePointer stdlib = Factory.createNode(Node::Kind::Module, STDLIB_NAME); + return makeAssociatedType(stdlib); + } + return nullptr; + } + + NodePointer demangleTuple(IsVariadic isV, unsigned depth) { + NodePointer tuple = Factory.createNode(Node::Kind::Tuple); + NodePointer elt = nullptr; + while (!Mangled.nextIf('_')) { + if (!Mangled) + return nullptr; + elt = Factory.createNode(Node::Kind::TupleElement); + + if (isStartOfIdentifier(Mangled.peek())) { + NodePointer label = + demangleIdentifier(depth + 1, Node::Kind::TupleElementName); + if (!label) + return nullptr; + elt->addChild(label, Factory); + } + + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + elt->addChild(type, Factory); + + tuple->addChild(elt, Factory); + } + if (isV == IsVariadic::yes && elt) { + elt->reverseChildren(); + NodePointer marker = Factory.createNode(Node::Kind::VariadicMarker); + elt->addChild(marker, Factory); + elt->reverseChildren(); + } + return tuple; + } + + NodePointer postProcessReturnTypeNode (NodePointer out_args) { + NodePointer out_node = Factory.createNode(Node::Kind::ReturnType); + out_node->addChild(out_args, Factory); + return out_node; + } + + NodePointer demangleType(unsigned depth) { + NodePointer type = demangleTypeImpl(depth); + if (!type) + return nullptr; + NodePointer nodeType = Factory.createNode(Node::Kind::Type); + nodeType->addChild(type, Factory); + return nodeType; + } + + NodePointer demangleFunctionType(Node::Kind kind, unsigned depth) { + bool throws = false, concurrent = false, async = false; + auto diffKind = MangledDifferentiabilityKind::NonDifferentiable; + NodePointer globalActorType = nullptr; + if (Mangled) { + throws = Mangled.nextIf('z'); + concurrent = Mangled.nextIf('y'); + async = Mangled.nextIf('Z'); + if (Mangled.nextIf('D')) { + switch (auto kind = (MangledDifferentiabilityKind)Mangled.next()) { + case MangledDifferentiabilityKind::Forward: + case MangledDifferentiabilityKind::Reverse: + case MangledDifferentiabilityKind::Normal: + case MangledDifferentiabilityKind::Linear: + diffKind = kind; + break; + case MangledDifferentiabilityKind::NonDifferentiable: + assert(false && "Impossible case 'NonDifferentiable'"); + } + } + if (Mangled.nextIf('Y')) { + globalActorType = demangleType(depth + 1); + if (!globalActorType) + return nullptr; + } + } + NodePointer in_args = demangleType(depth + 1); + if (!in_args) + return nullptr; + NodePointer out_args = demangleType(depth + 1); + if (!out_args) + return nullptr; + NodePointer block = Factory.createNode(kind); + + if (throws) { + block->addChild(Factory.createNode(Node::Kind::ThrowsAnnotation), Factory); + } + if (async) { + block->addChild(Factory.createNode(Node::Kind::AsyncAnnotation), Factory); + } + if (concurrent) { + block->addChild( + Factory.createNode(Node::Kind::ConcurrentFunctionType), Factory); + } + if (diffKind != MangledDifferentiabilityKind::NonDifferentiable) { + block->addChild( + Factory.createNode( + Node::Kind::DifferentiableFunctionType, (char)diffKind), Factory); + } + if (globalActorType) { + auto globalActorNode = + Factory.createNode(Node::Kind::GlobalActorFunctionType); + globalActorNode->addChild(globalActorType, Factory); + block->addChild(globalActorNode, Factory); + } + // Is there any need to handle isolated(any) function types here? + + NodePointer in_node = Factory.createNode(Node::Kind::ArgumentTuple); + block->addChild(in_node, Factory); + in_node->addChild(in_args, Factory); + block->addChild(postProcessReturnTypeNode(out_args), Factory); + return block; + } + + NodePointer demangleTypeImpl(unsigned depth) { + if (depth > OldDemangler::MaxDepth || !Mangled) + return nullptr; + char c = Mangled.next(); + if (c == 'B') { + if (!Mangled) + return nullptr; + c = Mangled.next(); + if (c == 'b') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.BridgeObject"); + if (c == 'B') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.UnsafeValueBuffer"); + if (c == 'f') { + Node::IndexType size; + if (demangleBuiltinSize(size, depth + 1)) { + return Factory.createNode( + Node::Kind::BuiltinTypeName, + std::move(DemanglerPrinter() << "Builtin.FPIEEE" << size).str()); + } + } + if (c == 'i') { + Node::IndexType size; + if (demangleBuiltinSize(size, depth + 1)) { + return Factory.createNode( + Node::Kind::BuiltinTypeName, + (DemanglerPrinter() << "Builtin.Int" << size).str()); + } + } + if (c == 'v') { + Node::IndexType elts; + if (demangleNatural(elts, depth + 1)) { + if (!Mangled.nextIf('B')) + return nullptr; + if (Mangled.nextIf('i')) { + Node::IndexType size; + if (!demangleBuiltinSize(size, depth + 1)) + return nullptr; + return Factory.createNode( + Node::Kind::BuiltinTypeName, + (DemanglerPrinter() << "Builtin.Vec" << elts << "xInt" << size) + .str()); + } + if (Mangled.nextIf('f')) { + Node::IndexType size; + if (!demangleBuiltinSize(size, depth + 1)) + return nullptr; + return Factory.createNode( + Node::Kind::BuiltinTypeName, + (DemanglerPrinter() << "Builtin.Vec" << elts << "xFPIEEE" + << size).str()); + } + if (Mangled.nextIf('p')) + return Factory.createNode( + Node::Kind::BuiltinTypeName, + (DemanglerPrinter() << "Builtin.Vec" << elts << "xRawPointer") + .str()); + } + } + if (c == 'O') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.UnknownObject"); + if (c == 'o') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.NativeObject"); + if (c == 'p') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.RawPointer"); + if (c == 't') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.SILToken"); + if (c == 'w') + return Factory.createNode(Node::Kind::BuiltinTypeName, + "Builtin.Word"); + return nullptr; + } + if (c == 'a') + return demangleDeclarationName(Node::Kind::TypeAlias, depth + 1); + + if (c == 'b') { + return demangleFunctionType(Node::Kind::ObjCBlock, depth + 1); + } + if (c == 'c') { + return demangleFunctionType(Node::Kind::CFunctionPointer, depth + 1); + } + if (c == 'D') { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + + NodePointer dynamicSelf = Factory.createNode(Node::Kind::DynamicSelf); + dynamicSelf->addChild(type, Factory); + return dynamicSelf; + } + if (c == 'E') { + if (!Mangled.nextIf('R')) + return nullptr; + if (!Mangled.nextIf('R')) + return nullptr; + return Factory.createNode(Node::Kind::ErrorType, std::string()); + } + if (c == 'F') { + return demangleFunctionType(Node::Kind::FunctionType, depth + 1); + } + if (c == 'f') { + return demangleFunctionType(Node::Kind::UncurriedFunctionType, depth + 1); + } + if (c == 'G') { + return demangleBoundGenericType(depth + 1); + } + if (c == 'X') { + if (Mangled.nextIf('b')) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer boxType = Factory.createNode(Node::Kind::SILBoxType); + boxType->addChild(type, Factory); + return boxType; + } + if (Mangled.nextIf('B')) { + NodePointer signature = nullptr; + if (Mangled.nextIf('G')) { + signature = demangleGenericSignature(depth, /*pseudogeneric*/ false); + if (!signature) + return nullptr; + } + NodePointer layout = Factory.createNode(Node::Kind::SILBoxLayout); + while (!Mangled.nextIf('_')) { + Node::Kind kind; + if (Mangled.nextIf('m')) + kind = Node::Kind::SILBoxMutableField; + else if (Mangled.nextIf('i')) + kind = Node::Kind::SILBoxImmutableField; + else + return nullptr; + + auto type = demangleType(depth + 1); + if (!type) + return nullptr; + auto field = Factory.createNode(kind); + field->addChild(type, Factory); + layout->addChild(field, Factory); + } + NodePointer genericArgs = nullptr; + if (signature) { + genericArgs = Factory.createNode(Node::Kind::TypeList); + while (!Mangled.nextIf('_')) { + auto type = demangleType(depth + 1); + if (!type) + return nullptr; + genericArgs->addChild(type, Factory); + } + } + NodePointer boxType = + Factory.createNode(Node::Kind::SILBoxTypeWithLayout); + boxType->addChild(layout, Factory); + if (signature) { + boxType->addChild(signature, Factory); + assert(genericArgs); + boxType->addChild(genericArgs, Factory); + } + return boxType; + } + } + if (c == 'K') { + return demangleFunctionType(Node::Kind::AutoClosureType, depth + 1); + } + if (c == 'M') { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer metatype = Factory.createNode(Node::Kind::Metatype); + metatype->addChild(type, Factory); + return metatype; + } + if (c == 'X') { + if (Mangled.nextIf('M')) { + NodePointer metatypeRepr = demangleMetatypeRepresentation(depth + 1); + if (!metatypeRepr) return nullptr; + + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer metatype = Factory.createNode(Node::Kind::Metatype); + metatype->addChild(metatypeRepr, Factory); + metatype->addChild(type, Factory); + return metatype; + } + } + if (c == 'P') { + if (Mangled.nextIf('M')) { + NodePointer type = demangleType(depth + 1); + if (!type) return nullptr; + auto metatype = Factory.createNode(Node::Kind::ExistentialMetatype); + metatype->addChild(type, Factory); + return metatype; + } + + return demangleProtocolList(depth + 1); + } + + if (c == 'X') { + if (Mangled.nextIf('P')) { + if (Mangled.nextIf('M')) { + NodePointer metatypeRepr = demangleMetatypeRepresentation(depth + 1); + if (!metatypeRepr) return nullptr; + + NodePointer type = demangleType(depth + 1); + if (!type) return nullptr; + + auto metatype = Factory.createNode(Node::Kind::ExistentialMetatype); + metatype->addChild(metatypeRepr, Factory); + metatype->addChild(type, Factory); + return metatype; + } + + return demangleProtocolList(depth + 1); + } + } + if (c == 'Q') { + if (Mangled.nextIf('u')) { + // Special mangling for opaque return type. + return Factory.createNode(Node::Kind::OpaqueReturnType); + } + if (Mangled.nextIf('U')) { + // Special mangling for opaque return type. + Node::IndexType ordinal; + if (!demangleIndex(ordinal, depth)) + return nullptr; + auto result = Factory.createNode(Node::Kind::OpaqueReturnType); + result->addChild( + Factory.createNode(Node::Kind::OpaqueReturnTypeIndex, ordinal), Factory); + return result; + } + return demangleArchetypeType(depth + 1); + } + if (c == 'q') { + return demangleDependentType(depth + 1); + } + if (c == 'x') { + // Special mangling for the first generic param. + return getDependentGenericParamType(0, 0); + } + if (c == 'w') { + return demangleAssociatedTypeSimple(depth + 1); + } + if (c == 'W') { + return demangleAssociatedTypeCompound(depth + 1); + } + if (c == 'R') { + NodePointer inout = Factory.createNode(Node::Kind::InOut); + NodePointer type = demangleTypeImpl(depth + 1); + if (!type) + return nullptr; + inout->addChild(type, Factory); + return inout; + } + if (c == 'k') { + auto noDerivative = Factory.createNode(Node::Kind::NoDerivative); + auto type = demangleTypeImpl(depth + 1); + if (!type) + return nullptr; + noDerivative->addChild(type, Factory); + return noDerivative; + } + if (c == 'S') { + return demangleSubstitutionIndex(depth + 1); + } + if (c == 'T') { + return demangleTuple(IsVariadic::no, depth + 1); + } + if (c == 't') { + return demangleTuple(IsVariadic::yes, depth + 1); + } + if (c == 'u') { + NodePointer sig = demangleGenericSignature(depth + 1); + if (!sig) return nullptr; + NodePointer sub = demangleType(depth + 1); + if (!sub) return nullptr; + NodePointer dependentGenericType + = Factory.createNode(Node::Kind::DependentGenericType); + dependentGenericType->addChild(sig, Factory); + dependentGenericType->addChild(sub, Factory); + return dependentGenericType; + } + if (c == 'X') { + if (Mangled.nextIf('f')) { + return demangleFunctionType(Node::Kind::ThinFunctionType, depth + 1); + } + if (Mangled.nextIf('o')) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer unowned = Factory.createNode(Node::Kind::Unowned); + unowned->addChild(type, Factory); + return unowned; + } + if (Mangled.nextIf('u')) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer unowned = Factory.createNode(Node::Kind::Unmanaged); + unowned->addChild(type, Factory); + return unowned; + } + if (Mangled.nextIf('w')) { + NodePointer type = demangleType(depth + 1); + if (!type) + return nullptr; + NodePointer weak = Factory.createNode(Node::Kind::Weak); + weak->addChild(type, Factory); + return weak; + } + + // type ::= 'XF' impl-function-type + if (Mangled.nextIf('F')) { + return demangleImplFunctionType(depth + 1); + } + + return nullptr; + } + if (isStartOfNominalType(c)) + return demangleDeclarationName(nominalTypeMarkerToNodeKind(c), depth + 1); + return nullptr; + } + + bool demangleReabstractSignature(NodePointer signature, unsigned depth) { + if (Mangled.nextIf('G')) { + NodePointer generics = demangleGenericSignature(depth + 1); + if (!generics) return false; + signature->addChild(generics, Factory); + } + + NodePointer srcType = demangleType(depth + 1); + if (!srcType) return false; + signature->addChild(srcType, Factory); + + NodePointer destType = demangleType(depth + 1); + if (!destType) return false; + signature->addChild(destType, Factory); + + return true; + } + + // impl-function-type ::= impl-callee-convention impl-function-attribute* + // generics? '_' impl-parameter* '_' impl-result* '_' + // impl-function-attribute ::= 'Cb' // compatible with C block invocation function + // impl-function-attribute ::= 'Cc' // compatible with C global function + // impl-function-attribute ::= 'Cm' // compatible with Swift method + // impl-function-attribute ::= 'CO' // compatible with ObjC method + // impl-function-attribute ::= 'Cw' // compatible with protocol witness + // impl-function-attribute ::= 'G' // generic + NodePointer demangleImplFunctionType(unsigned depth) { + NodePointer type = Factory.createNode(Node::Kind::ImplFunctionType); + + if (!demangleImplCalleeConvention(type, depth + 1)) + return nullptr; + + if (Mangled.nextIf('C')) { + if (Mangled.nextIf('b')) + addImplFunctionConvention(type, "block"); + else if (Mangled.nextIf('c')) + addImplFunctionConvention(type, "c"); + else if (Mangled.nextIf('m')) + addImplFunctionConvention(type, "method"); + else if (Mangled.nextIf('O')) + addImplFunctionConvention(type, "objc_method"); + else if (Mangled.nextIf('w')) + addImplFunctionConvention(type, "witness_method"); + else + return nullptr; + } + + if (Mangled.nextIf('h')) + addImplFunctionAttribute(type, "@Sendable"); + + if (Mangled.nextIf('H')) + addImplFunctionAttribute(type, "@async"); + + // Enter a new generic context if this type is generic. + // FIXME: replace with std::optional, when we have it. + bool isPseudogeneric = false; + if (Mangled.nextIf('G') || + (isPseudogeneric = Mangled.nextIf('g'))) { + NodePointer generics = + demangleGenericSignature(depth + 1, isPseudogeneric); + if (!generics) + return nullptr; + type->addChild(generics, Factory); + } + + // Expect the attribute terminator. + if (!Mangled.nextIf('_')) + return nullptr; + + // Demangle the parameters. + if (!demangleImplParameters(type, depth + 1)) + return nullptr; + + // Demangle the result type. + if (!demangleImplResults(type, depth + 1)) + return nullptr; + + return type; + } + + enum class ImplConventionContext { Callee, Parameter, Result }; + + /// impl-convention ::= 'a' // direct, autoreleased + /// impl-convention ::= 'd' // direct, no ownership transfer + /// impl-convention ::= 'D' // direct, no ownership transfer, + /// // dependent on self + /// impl-convention ::= 'g' // direct, guaranteed + /// impl-convention ::= 'e' // direct, deallocating + /// impl-convention ::= 'i' // indirect, ownership transfer + /// impl-convention ::= 'l' // indirect, inout + /// impl-convention ::= 'o' // direct, ownership transfer + /// + /// Returns an empty string otherwise. + StringRef demangleImplConvention(ImplConventionContext ctxt, unsigned depth) { +#define CASE(CHAR, FOR_CALLEE, FOR_PARAMETER, FOR_RESULT) \ + if (Mangled.nextIf(CHAR)) { \ + switch (ctxt) { \ + case ImplConventionContext::Callee: return (FOR_CALLEE); \ + case ImplConventionContext::Parameter: return (FOR_PARAMETER); \ + case ImplConventionContext::Result: return (FOR_RESULT); \ + } \ + return StringRef(); \ + } + auto Nothing = StringRef(); + CASE('a', Nothing, Nothing, "@autoreleased") + CASE('d', "@callee_unowned", "@unowned", "@unowned") + CASE('D', Nothing, Nothing, "@unowned_inner_pointer") + CASE('g', "@callee_guaranteed", "@guaranteed", Nothing) + CASE('e', Nothing, "@deallocating", Nothing) + CASE('i', Nothing, "@in", "@out") + CASE('l', Nothing, "@inout", Nothing) + CASE('o', "@callee_owned", "@owned", "@owned") + return Nothing; +#undef CASE + } + + // impl-callee-convention ::= 't' + // impl-callee-convention ::= impl-convention + bool demangleImplCalleeConvention(NodePointer type, unsigned depth) { + StringRef attr; + if (Mangled.nextIf('t')) { + attr = "@convention(thin)"; + } else { + attr = demangleImplConvention(ImplConventionContext::Callee, depth + 1); + } + if (attr.empty()) { + return false; + } + type->addChild(Factory.createNode(Node::Kind::ImplConvention, attr), Factory); + return true; + } + + void addImplFunctionAttribute(NodePointer parent, StringRef attr, + Node::Kind kind = Node::Kind::ImplFunctionAttribute) { + parent->addChild(Factory.createNode(kind, attr), Factory); + } + + void addImplFunctionConvention(NodePointer parent, StringRef attr) { + auto attrNode = Factory.createNode(Node::Kind::ImplFunctionConvention); + attrNode->addChild( + Factory.createNode(Node::Kind::ImplFunctionConventionName, attr), + Factory); + parent->addChild(attrNode, Factory); + } + + // impl-parameter ::= impl-convention type + bool demangleImplParameters(NodePointer parent, unsigned depth) { + while (!Mangled.nextIf('_')) { + auto input = + demangleImplParameterOrResult(Node::Kind::ImplParameter, depth + 1); + if (!input) return false; + parent->addChild(input, Factory); + } + return true; + } + + // impl-result ::= impl-convention type + bool demangleImplResults(NodePointer parent, unsigned depth) { + while (!Mangled.nextIf('_')) { + auto res = + demangleImplParameterOrResult(Node::Kind::ImplResult, depth + 1); + if (!res) return false; + parent->addChild(res, Factory); + } + return true; + } + + NodePointer demangleImplParameterOrResult(Node::Kind kind, unsigned depth) { + if (Mangled.nextIf('z')) { + // Only valid for a result. + if (kind != Node::Kind::ImplResult) + return nullptr; + kind = Node::Kind::ImplErrorResult; + } + + ImplConventionContext ConvCtx; + if (kind == Node::Kind::ImplParameter) { + ConvCtx = ImplConventionContext::Parameter; + } else if (kind == Node::Kind::ImplResult + || kind == Node::Kind::ImplErrorResult) { + ConvCtx = ImplConventionContext::Result; + } else { + return nullptr; + } + + auto convention = demangleImplConvention(ConvCtx, depth + 1); + if (convention.empty()) return nullptr; + auto type = demangleType(depth + 1); + if (!type) return nullptr; + + NodePointer node = Factory.createNode(kind); + node->addChild(Factory.createNode(Node::Kind::ImplConvention, convention), + Factory); + node->addChild(type, Factory); + + return node; + } +}; +} // end anonymous namespace + +NodePointer +swift::Demangle::demangleOldSymbolAsNode(StringRef MangledName, + NodeFactory &Factory) { + OldDemangler demangler(MangledName, Factory); + return demangler.demangleTopLevel(); +} + diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/OldRemangler.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/OldRemangler.cpp new file mode 100644 index 000000000..86d8d1f7f --- /dev/null +++ b/symbolic-demangle/vendor/swift/lib/Demangling/OldRemangler.cpp @@ -0,0 +1,3099 @@ +//===--- OldRemangler.cpp - Old Swift Re-mangler --------------------------===// +// +// 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 implements the remangler, which turns a demangling parse +// tree back into a mangled string. This is useful for tools which +// want to extract subtrees from mangled strings. +// +//===----------------------------------------------------------------------===// + +#include "DemanglerAssert.h" +#include "RemanglerBase.h" +#include "swift/AST/Ownership.h" +#include "swift/Demangling/Demangler.h" +#include "swift/Demangling/ManglingUtils.h" +#include "swift/Demangling/Punycode.h" +#include "swift/Strings.h" +#include +#include + +using namespace swift; +using namespace Demangle; + +namespace { + class Remangler : public RemanglerBase { + static const unsigned MaxDepth = 1024; + + public: + Remangler(NodeFactory &Factory) : RemanglerBase(Factory) { } + + class EntityContext { + bool AsContext = false; + std::string AnonymousContextDiscriminator; + public: + bool isAsContext() const { + return AsContext; + } + + void setAnonymousContextDiscriminator(StringRef discriminator) { + AnonymousContextDiscriminator = discriminator.str(); + } + + std::string takeAnonymousContextDiscriminator() { + auto r = std::move(AnonymousContextDiscriminator); + AnonymousContextDiscriminator.clear(); + return r; + } + + class ManglingContextRAII { + EntityContext &Ctx; + bool SavedValue; + public: + ManglingContextRAII(EntityContext &ctx) + : Ctx(ctx), SavedValue(ctx.AsContext) { + ctx.AsContext = true; + } + + ~ManglingContextRAII() { + Ctx.AsContext = SavedValue; + } + }; + }; + + ManglingError mangle(Node *node, unsigned depth) { + if (depth > Remangler::MaxDepth) { + return MANGLING_ERROR(ManglingError::TooComplex, node); + } + + switch (node->getKind()) { +#define NODE(ID) \ + case Node::Kind::ID: \ + return mangle##ID(node, depth); +#include "swift/Demangling/DemangleNodes.def" + } + return MANGLING_ERROR(ManglingError::BadNodeKind, node); + } + + ManglingError mangleGenericArgs(Node *node, EntityContext &ctx, + unsigned depth); + ManglingError mangleAnyNominalType(Node *node, EntityContext &ctx, + unsigned depth); + +#define NODE(ID) ManglingError mangle##ID(Node *node, unsigned depth); +#define CONTEXT_NODE(ID) \ + ManglingError mangle##ID(Node *node, unsigned depth); \ + ManglingError mangle##ID(Node *node, EntityContext &ctx, unsigned depth); +#include "swift/Demangling/DemangleNodes.def" + + void mangleIndex(Node::IndexType index); + ManglingError mangleIdentifier(StringRef name, OperatorKind operatorKind); + ManglingError mangleAccessor(Node *storageNode, StringRef accessorCode, + EntityContext &ctx, unsigned depth); + + ManglingError mangleChildNodes(Node *node, unsigned depth) { + return mangleNodes(node->begin(), node->end(), depth); + } + ManglingError mangleNodes(Node::iterator i, Node::iterator e, + unsigned depth) { + for (; i != e; ++i) { + RETURN_IF_ERROR(mangle(*i, depth)); + } + return ManglingError::Success; + } + ManglingError mangleSingleChildNode(Node *node, unsigned depth) { + if (node->getNumChildren() != 1) + return MANGLING_ERROR(ManglingError::MultipleChildNodes, node); + + return mangle(*node->begin(), depth); + } + ManglingError mangleChildNode(Node *node, unsigned index, unsigned depth) { + DEMANGLER_ASSERT(index < node->getNumChildren(), node); + return mangle(node->begin()[index], depth); + } + + ManglingError mangleSimpleEntity(Node *node, char basicKind, + StringRef entityKind, EntityContext &ctx, + unsigned depth); + ManglingError + mangleNamedEntity(Node *node, char basicKind, StringRef entityKind, + EntityContext &ctx, unsigned depth, + StringRef ArtificialPrivateDiscriminator = {}); + ManglingError mangleTypedEntity(Node *node, char basicKind, + StringRef entityKind, EntityContext &ctx, + unsigned depth); + ManglingError mangleNamedAndTypedEntity(Node *node, char basicKind, + StringRef entityKind, + EntityContext &ctx, unsigned depth); + ManglingError + mangleNominalType(Node *node, char basicKind, EntityContext &ctx, + unsigned depth, + StringRef ArtificialPrivateDiscriminator = {}); + + ManglingError mangleProtocolWithoutPrefix(Node *node, unsigned depth); + ManglingError + mangleProtocolListWithoutPrefix(Node *node, unsigned depth, + Node *additionalProto = nullptr); + + ManglingError mangleEntityContext(Node *node, EntityContext &ctx, + unsigned depth); + ManglingError mangleEntityType(Node *node, EntityContext &ctx, + unsigned depth); + ManglingError mangleEntityGenericType(Node *node, EntityContext &ctx); + + bool trySubstitution(Node *node, SubstitutionEntry &entry); + bool mangleStandardSubstitution(Node *node); + + ManglingError mangleDependentGenericParamIndex(Node *node, unsigned depth); + ManglingError mangleConstrainedType(Node *node, unsigned depth); + }; +} // end anonymous namespace + +#define NODE(ID) +#define CONTEXT_NODE(ID) \ + ManglingError Remangler::mangle##ID(Node *node, unsigned depth) { \ + EntityContext ctx; \ + return mangle##ID(node, ctx, depth); \ + } +#include "swift/Demangling/DemangleNodes.def" + +/// Re-apply labels from the function to its parameter type +/// to preserve old mangling style. +/// +/// \param LabelList The list of labels to apply. +/// \param OrigType The function parameter type to apply labels to. +/// \param Factory The node factory to use to allocate new nodes. +static NodePointer applyParamLabels(NodePointer LabelList, NodePointer OrigType, + NodeFactory &Factory) { + if (LabelList->getNumChildren() == 0) + return OrigType; + + auto applyParamLabels = [&](NodePointer ArgTuple) -> NodePointer { + assert(ArgTuple->getKind() == Node::Kind::ArgumentTuple); + + auto ParamsType = Factory.createNode(Node::Kind::ArgumentTuple); + auto Tuple = Factory.createNode(Node::Kind::Tuple); + + auto processParameter = [&](NodePointer Label, NodePointer Param) { + if (Label->getKind() == Node::Kind::FirstElementMarker) { + Tuple->addChild(Param, Factory); + return; + } + + auto NewParam = Factory.createNode(Node::Kind::TupleElement); + NewParam->addChild(Factory.createNodeWithAllocatedText( + Node::Kind::TupleElementName, Label->getText()), + Factory); + + for (auto &Child : *Param) + NewParam->addChild(Child, Factory); + + Tuple->addChild(NewParam, Factory); + }; + + auto OrigTuple = ArgTuple->getFirstChild()->getFirstChild(); + + if (OrigTuple->getKind() != Node::Kind::Tuple) { + processParameter(LabelList->getChild(0), OrigTuple); + } else { + for (unsigned i = 0, n = OrigTuple->getNumChildren(); i != n; ++i) { + processParameter(LabelList->getChild(i), OrigTuple->getChild(i)); + } + } + + auto Type = Factory.createNode(Node::Kind::Type); + Type->addChild(Tuple, Factory); + ParamsType->addChild(Type, Factory); + return ParamsType; + }; + + auto visitTypeChild = [&](NodePointer Child) -> NodePointer { + if (Child->getKind() != Node::Kind::FunctionType && + Child->getKind() != Node::Kind::NoEscapeFunctionType) + return Child; + + auto FuncType = Factory.createNode(Node::Kind::FunctionType); + for (unsigned i = 0, n = Child->getNumChildren(); i != n; ++i) { + NodePointer FuncChild = Child->getChild(i); + if (FuncChild->getKind() == Node::Kind::ArgumentTuple) + FuncChild = applyParamLabels(FuncChild); + FuncType->addChild(FuncChild, Factory); + } + return FuncType; + }; + + auto Type = Factory.createNode(OrigType->getKind()); + for (auto &Child : *OrigType) + Type->addChild(visitTypeChild(Child), Factory); + + return Type; +} + +bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) { + if (mangleStandardSubstitution(node)) + return true; + + // Go ahead and initialize the substitution entry. + entry = entryForNode(node); + + int Idx = findSubstitution(entry); + if (Idx < 0) + return false; + + Buffer << 'S'; + mangleIndex(Idx); + return true; +} + +static bool isInSwiftModule(Node *node) { + Node *context = node->getFirstChild(); + return (context->getKind() == Node::Kind::Module && + context->getText() == STDLIB_NAME && + // Check for private declarations in Swift + node->getChild(1)->getKind() == Node::Kind::Identifier); +} + +bool Remangler::mangleStandardSubstitution(Node *node) { + // Look for known substitutions. + switch (node->getKind()) { +#define SUCCESS_IF_IS(VALUE, EXPECTED, SUBSTITUTION) \ + do { \ + if ((VALUE) == (EXPECTED)) { \ + Buffer << SUBSTITUTION; \ + return true; \ + } \ + } while (0) +#define SUCCESS_IF_TEXT_IS(EXPECTED, SUBSTITUTION) \ + SUCCESS_IF_IS(node->getText(), EXPECTED, SUBSTITUTION) +#define SUCCESS_IF_DECLNAME_IS(EXPECTED, SUBSTITUTION) \ + SUCCESS_IF_IS(node->getChild(1)->getText(), EXPECTED, SUBSTITUTION) + + case Node::Kind::Module: + SUCCESS_IF_TEXT_IS(STDLIB_NAME, "s"); + SUCCESS_IF_TEXT_IS(MANGLING_MODULE_OBJC, "So"); + SUCCESS_IF_TEXT_IS(MANGLING_MODULE_CLANG_IMPORTER, "SC"); + break; + case Node::Kind::Structure: + if (isInSwiftModule(node)) { + SUCCESS_IF_DECLNAME_IS("Array", "Sa"); + SUCCESS_IF_DECLNAME_IS("Bool", "Sb"); + SUCCESS_IF_DECLNAME_IS("UnicodeScalar", "Sc"); + SUCCESS_IF_DECLNAME_IS("Double", "Sd"); + SUCCESS_IF_DECLNAME_IS("Float", "Sf"); + SUCCESS_IF_DECLNAME_IS("Int", "Si"); + SUCCESS_IF_DECLNAME_IS("UnsafeRawPointer", "SV"); + SUCCESS_IF_DECLNAME_IS("UnsafeMutableRawPointer", "Sv"); + SUCCESS_IF_DECLNAME_IS("UnsafePointer", "SP"); + SUCCESS_IF_DECLNAME_IS("UnsafeMutablePointer", "Sp"); + SUCCESS_IF_DECLNAME_IS("UnsafeBufferPointer", "SR"); + SUCCESS_IF_DECLNAME_IS("UnsafeMutableBufferPointer", "Sr"); + SUCCESS_IF_DECLNAME_IS("String", "SS"); + SUCCESS_IF_DECLNAME_IS("UInt", "Su"); + } + break; + case Node::Kind::Enum: + if (isInSwiftModule(node)) { + SUCCESS_IF_DECLNAME_IS("Optional", "Sq"); + SUCCESS_IF_DECLNAME_IS("ImplicitlyUnwrappedOptional", "SQ"); + } + break; + + default: + break; + +#undef SUCCESS_IF_DECLNAME_IS +#undef SUCCESS_IF_TEXT_IS +#undef SUCCESS_IF_IS + } + return false; +} + +ManglingError Remangler::mangleIdentifier(Node *node, unsigned depth) { + return mangleIdentifier(node->getText(), OperatorKind::NotOperator); +} +ManglingError Remangler::manglePrefixOperator(Node *node, unsigned depth) { + return mangleIdentifier(node->getText(), OperatorKind::Prefix); +} +ManglingError Remangler::manglePostfixOperator(Node *node, unsigned depth) { + return mangleIdentifier(node->getText(), OperatorKind::Postfix); +} +ManglingError Remangler::mangleInfixOperator(Node *node, unsigned depth) { + return mangleIdentifier(node->getText(), OperatorKind::Infix); +} +ManglingError Remangler::mangleIdentifier(StringRef ident, + OperatorKind operatorKind) { + // 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. + + // 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. + switch (operatorKind) { + case OperatorKind::NotOperator: + Buffer << ident.size() << ident; + return ManglingError::Success; + case OperatorKind::Infix: + Buffer << "oi"; + break; + case OperatorKind::Prefix: + Buffer << "op"; + break; + case OperatorKind::Postfix: + Buffer << "oP"; + break; + } + + // Mangle ASCII operators directly. + Buffer << ident.size(); + for (char ch : ident) { + Buffer << Mangle::translateOperatorChar(ch); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleNumber(Node *node, unsigned depth) { + mangleIndex(node->getIndex()); + return ManglingError::Success; +} + +void Remangler::mangleIndex(Node::IndexType value) { + if (value == 0) { + Buffer << '_'; + } else { + Buffer << (value - 1) << '_'; + } +} + +ManglingError Remangler::mangleGlobal(Node *node, unsigned depth) { + Buffer << "_T"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleSuffix(Node *node, unsigned depth) { + // Just add the suffix back on. + Buffer << node->getText(); + return ManglingError::Success; +} + +ManglingError Remangler::mangleGenericSpecialization(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleGenericSpecializationPrespecialized(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleGenericSpecializationNotReAbstracted(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleGenericSpecializationInResilienceDomain(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleInlinedGenericFunction(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleGenericPartialSpecialization(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleGenericSpecializationParam(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleFunctionSignatureSpecialization(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSpecializationPassID(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleIsSerialized(Node *node, unsigned depth) { + Buffer << "q"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAsyncRemoved(Node *node, unsigned depth) { + Buffer << "a"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDroppedArgument(Node *node, unsigned depth) { + Buffer << "t" << node->getIndex(); + return ManglingError::Success; +} + +ManglingError +Remangler::mangleFunctionSignatureSpecializationReturn(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleFunctionSignatureSpecializationParam(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node, + unsigned depth) { + // This should never be called since mangling parameter payloads require + // knowing what the parameter kind is. + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node, + unsigned depth) { + // This should never be called since mangling parameter kinds have influence + // on the payloads. + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleRetroactiveConformance(Node *node, + unsigned depth) { + // Retroactive conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleProtocolConformanceRefInTypeModule(Node *node, + unsigned depth) { + // Protocol conformance references aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleProtocolConformanceRefInProtocolModule(Node *node, + unsigned depth) { + // Protocol conformance references aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleProtocolConformanceRefInOtherModule(Node *node, + unsigned depth) { + // Protocol conformance references aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleConcreteProtocolConformance(Node *node, + unsigned depth) { + // Concrete conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::manglePackProtocolConformance(Node *node, + unsigned depth) { + // Pack conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleAnyProtocolConformanceList(Node *node, + unsigned depth) { + // Conformance lists aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleDependentAssociatedConformance(Node *node, + unsigned depth) { + // Dependent associated conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleDependentProtocolConformanceRoot(Node *node, unsigned depth) { + // Dependent conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleDependentProtocolConformanceInherited(Node *node, + unsigned depth) { + // Dependent conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleDependentProtocolConformanceAssociated(Node *node, + unsigned depth) { + // Dependent conformances aren't in the old mangling + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleProtocolConformance(Node *node, unsigned depth) { + // type, protocol name, context + DEMANGLER_ASSERT(node->getNumChildren() == 3, node); + RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); + RETURN_IF_ERROR(mangleProtocolWithoutPrefix(node->begin()[1], depth + 1)); + return mangleChildNode(node, 2, depth + 1); +} + +ManglingError Remangler::mangleObjCAttribute(Node *node, unsigned depth) { + Buffer << "To"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleNonObjCAttribute(Node *node, unsigned depth) { + Buffer << "TO"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDirectMethodReferenceAttribute(Node *node, + unsigned depth) { + Buffer << "Td"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDynamicAttribute(Node *node, unsigned depth) { + Buffer << "TD"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleVTableAttribute(Node *node, unsigned depth) { + Buffer << "TV"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleGenericTypeMetadataPattern(Node *node, + unsigned depth) { + Buffer << "MP"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleTypeMetadataAccessFunction(Node *node, + unsigned depth) { + Buffer << "Ma"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleTypeMetadataInstantiationCache(Node *node, + unsigned depth) { + Buffer << "MI"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError +Remangler::mangleTypeMetadataInstantiationFunction(Node *node, unsigned depth) { + Buffer << "Mi"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError +Remangler::mangleTypeMetadataSingletonInitializationCache(Node *node, + unsigned depth) { + Buffer << "Ml"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleTypeMetadataCompletionFunction(Node *node, + unsigned depth) { + Buffer << "Mr"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleTypeMetadataDemanglingCache(Node *node, + unsigned depth) { + // not supported + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleTypeMetadataLazyCache(Node *node, + unsigned depth) { + Buffer << "ML"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleMetaclass(Node *node, unsigned depth) { + Buffer << "Mm"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleClassMetadataBaseOffset(Node *node, + unsigned depth) { + Buffer << "Mo"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleNominalTypeDescriptor(Node *node, + unsigned depth) { + Buffer << "Mn"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleNominalTypeDescriptorRecord(Node *node, + unsigned depth) { + Buffer << "Hn"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::manglePropertyDescriptor(Node *node, unsigned depth) { + // not supported + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleTypeMetadata(Node *node, unsigned depth) { + Buffer << "M"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleFullTypeMetadata(Node *node, unsigned depth) { + Buffer << "Mf"; + return mangleChildNodes(node, depth + 1); // type +} + +ManglingError Remangler::mangleProtocolDescriptor(Node *node, unsigned depth) { + Buffer << "Mp"; + return mangleProtocolWithoutPrefix(node->begin()[0], depth + 1); +} + +ManglingError Remangler::mangleProtocolDescriptorRecord(Node *node, + unsigned depth) { + Buffer << "Hr"; + return mangleProtocolWithoutPrefix(node->begin()[0], depth + 1); +} + +ManglingError +Remangler::mangleProtocolRequirementsBaseDescriptor(Node *node, + unsigned depth) { + // ###TODO: Is this an error? + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleProtocolWitnessTablePattern(Node *node, + unsigned depth) { + // todo + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleProtocolConformanceDescriptor(Node *node, + unsigned depth) { + Buffer << "Mc"; + return mangleProtocolConformance(node->begin()[0], depth + 1); +} + +ManglingError +Remangler::mangleProtocolConformanceDescriptorRecord(Node *node, + unsigned depth) { + Buffer << "Hc"; + return mangleProtocolConformance(node->begin()[0], depth + 1); +} + +ManglingError +Remangler::mangleProtocolSelfConformanceDescriptor(Node *node, unsigned depth) { + Buffer << "MS"; + return mangleProtocol(node->begin()[0], depth + 1); +} + +ManglingError Remangler::manglePartialApplyForwarder(Node *node, + unsigned depth) { + Buffer << "PA"; + if (node->getNumChildren() == 1) { + Buffer << "__T"; + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // global + } + return ManglingError::Success; +} + +ManglingError Remangler::manglePartialApplyObjCForwarder(Node *node, + unsigned depth) { + Buffer << "PAo"; + if (node->getNumChildren() == 1) { + Buffer << "__T"; + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // global + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleMergedFunction(Node *node, unsigned depth) { + Buffer << "Tm"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDistributedThunk(Node *node, unsigned depth) { + Buffer << "TE"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDistributedAccessor(Node *node, unsigned depth) { + Buffer << "TF"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDynamicallyReplaceableFunctionImpl(Node *node, + unsigned depth) { + Buffer << "TI"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDynamicallyReplaceableFunctionKey(Node *node, unsigned depth) { + Buffer << "Tx"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDynamicallyReplaceableFunctionVar(Node *node, unsigned depth) { + Buffer << "TX"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAsyncAwaitResumePartialFunction(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleAsyncSuspendResumePartialFunction(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleDirectness(Node *node, unsigned depth) { + switch (node->getIndex()) { + case uint64_t(Directness::Direct): + Buffer << 'd'; + break; + case uint64_t(Directness::Indirect): + Buffer << 'i'; + break; + default: + return MANGLING_ERROR(ManglingError::BadDirectness, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleValueWitness(Node *node, unsigned depth) { + const char *Code = nullptr; + switch (node->getFirstChild()->getIndex()) { +#define VALUE_WITNESS(MANGLING, NAME) \ + case uint64_t(ValueWitnessKind::NAME): \ + Code = #MANGLING; \ + break; +#include "swift/Demangling/ValueWitnessMangling.def" + default: + return MANGLING_ERROR(ManglingError::BadValueWitnessKind, node); + } + Buffer << 'w' << Code; + return mangleChildNode(node, 1, depth + 1); // type +} + +ManglingError Remangler::mangleValueWitnessTable(Node *node, unsigned depth) { + Buffer << "WV"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleConcurrentFunctionType(Node *node, + unsigned depth) { + Buffer << "y"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAsyncAnnotation(Node *node, unsigned depth) { + Buffer << "Z"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleThrowsAnnotation(Node *node, unsigned depth) { + Buffer << "z"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleTypedThrowsAnnotation(Node *node, unsigned depth) { + Buffer << "z"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDifferentiableFunctionType(Node *node, + unsigned depth) { + Buffer << "D"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleGlobalActorFunctionType(Node *node, + unsigned depth) { + Buffer << "Y" << (char)node->getIndex(); // differentiability kind + return ManglingError::Success; +} + +ManglingError Remangler::mangleIsolatedAnyFunctionType(Node *node, + unsigned depth) { + Buffer << "YA"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleSendingResultFunctionType(Node *node, + unsigned depth) { + Buffer << "YT"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleFieldOffset(Node *node, unsigned depth) { + Buffer << "Wv"; + return mangleChildNodes(node, depth + 1); // directness, entity +} + +ManglingError Remangler::mangleEnumCase(Node *node, unsigned depth) { + Buffer << "WC"; + return mangleSingleChildNode(node, depth + 1); // enum case +} + +ManglingError +Remangler::mangleProtocolSelfConformanceWitnessTable(Node *node, + unsigned depth) { + Buffer << "WS"; + return mangleSingleChildNode(node, depth + 1); // protocol +} + +ManglingError Remangler::mangleProtocolWitnessTable(Node *node, + unsigned depth) { + Buffer << "WP"; + return mangleSingleChildNode(node, depth + 1); // protocol conformance +} + +ManglingError Remangler::mangleGenericProtocolWitnessTable(Node *node, + unsigned depth) { + Buffer << "WG"; + return mangleSingleChildNode(node, depth + 1); // protocol conformance +} + +ManglingError Remangler::mangleResilientProtocolWitnessTable(Node *node, + unsigned depth) { + // todo + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleGenericProtocolWitnessTableInstantiationFunction( + Node *node, unsigned depth) { + Buffer << "WI"; + return mangleSingleChildNode(node, depth + 1); // protocol conformance +} + +ManglingError Remangler::mangleProtocolWitnessTableAccessor(Node *node, + unsigned depth) { + Buffer << "Wa"; + return mangleSingleChildNode(node, depth + 1); // protocol conformance +} + +ManglingError +Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node, unsigned depth) { + Buffer << "Wl"; + return mangleChildNodes(node, depth + 1); // type, protocol conformance +} + +ManglingError +Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node, + unsigned depth) { + Buffer << "WL"; + return mangleChildNodes(node, depth + 1); // type, protocol conformance +} + +ManglingError Remangler::mangleAssociatedTypeDescriptor(Node *node, + unsigned depth) { + // ###TODO: Check this (and similar ones below). Should this be a failure? + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAssociatedConformanceDescriptor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleBaseConformanceDescriptor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAssociatedTypeMetadataAccessor(Node *node, + unsigned depth) { + Buffer << "Wt"; + return mangleChildNodes(node, depth + 1); // protocol conformance, identifier +} + +ManglingError +Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node, + unsigned depth) { + Buffer << "WT"; + DEMANGLER_ASSERT(node->getNumChildren() == 3, node); + RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); // protocol conformance + RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // type + return mangleProtocolWithoutPrefix(node->begin()[2], depth + 1); // type +} + +ManglingError Remangler::mangleBaseWitnessTableAccessor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleReabstractionThunkHelper(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleReabstractionThunkHelperWithSelf(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleReabstractionThunk(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleReabstractionThunkHelperWithGlobalActor(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAutoDiffFunction(Node *node, EntityContext &ctx, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAutoDiffDerivativeVTableThunk(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleAutoDiffSelfReorderingReabstractionThunk(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAutoDiffSubsetParametersThunk(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleAutoDiffFunctionKind(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDifferentiabilityWitness(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleIndexSubset(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleProtocolSelfConformanceWitness(Node *node, + unsigned depth) { + Buffer << "TS"; + return mangleSingleChildNode(node, depth + 1); // entity +} + +ManglingError Remangler::mangleProtocolWitness(Node *node, unsigned depth) { + Buffer << "TW"; + return mangleChildNodes(node, depth + 1); // protocol conformance, entity +} + +ManglingError Remangler::mangleFunction(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleNamedAndTypedEntity(node, 'F', "", ctx, depth + 1); +} + +ManglingError Remangler::mangleVariable(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleNamedAndTypedEntity(node, 'v', "", ctx, depth + 1); +} + +ManglingError Remangler::mangleSubscript(Node *node, EntityContext &ctx, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() >= 2, node); + Buffer << 'i'; + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + if (node->getLastChild()->getKind() == Node::Kind::PrivateDeclName) + RETURN_IF_ERROR(mangle(node->getLastChild(), depth + 1)); + + if (node->getNumChildren() >= 3 + && node->begin()[1]->getKind() == Node::Kind::LabelList) { + auto LabelList = node->begin()[1]; + auto Type = node->begin()[2]; + RETURN_IF_ERROR(mangleEntityType(applyParamLabels(LabelList, Type, Factory), + ctx, depth + 1)); + } else { + RETURN_IF_ERROR(mangleEntityType(node->begin()[1], ctx, depth + 1)); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleMacro(Node *node, unsigned depth) { + Buffer << "fm"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleFreestandingMacroExpansion( + Node *node, unsigned depth) { + Buffer << "fMf"; + RETURN_IF_ERROR(mangleIndex(node, depth + 1)); + return mangleChildNodes(node, depth + 1); +} + +#define FREESTANDING_MACRO_ROLE(Name, Description) +#define ATTACHED_MACRO_ROLE(Name, Description, MangledChar) \ +ManglingError Remangler::mangle##Name##AttachedMacroExpansion( \ + Node *node, unsigned depth) { \ + Buffer << "fM" MangledChar; \ + RETURN_IF_ERROR(mangleIndex(node, depth + 1)); \ + return mangleChildNodes(node, depth + 1); \ +} +#include "swift/Basic/MacroRoles.def" + +ManglingError Remangler::mangleMacroExpansionUniqueName( + Node *node, unsigned depth) { + Buffer << "fMu"; + RETURN_IF_ERROR(mangleIndex(node, depth + 1)); + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleMacroExpansionLoc( + Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleAccessor(Node *storageNode, + StringRef accessorCode, + EntityContext &ctx, unsigned depth) { + Buffer << 'F'; + RETURN_IF_ERROR( + mangleEntityContext(storageNode->getChild(0), ctx, depth + 1)); + Buffer << accessorCode; + + auto mangleAccessorType = [&](unsigned TypeIndex) { + auto LabelList = storageNode->getChild(TypeIndex); + if (LabelList->getKind() == Node::Kind::LabelList) { + auto Type = storageNode->getChild(TypeIndex + 1); + return mangleEntityType(applyParamLabels(LabelList, Type, Factory), ctx, + depth + 1); + } else { + return mangleEntityType(storageNode->getChild(TypeIndex), ctx, depth + 1); + } + }; + + switch (storageNode->getKind()) { + case Demangle::Node::Kind::Variable: { + RETURN_IF_ERROR(mangleChildNode(storageNode, 1, depth + 1)); + RETURN_IF_ERROR(mangleAccessorType(2)); + break; + } + + case Demangle::Node::Kind::Subscript: { + auto NumChildren = storageNode->getNumChildren(); + DEMANGLER_ASSERT(NumChildren <= 4, storageNode); + + auto PrivateName = storageNode->getChild(NumChildren - 1); + if (PrivateName->getKind() == Node::Kind::PrivateDeclName) + RETURN_IF_ERROR(mangle(PrivateName, depth + 1)); + + RETURN_IF_ERROR(mangleIdentifier("subscript", OperatorKind::NotOperator)); + RETURN_IF_ERROR(mangleAccessorType(1)); + break; + } + default: + return MANGLING_ERROR(ManglingError::NotAStorageNode, storageNode); + } + + return ManglingError::Success; +} + +ManglingError Remangler::mangleInitializer(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'I', "i", ctx, depth + 1); +} + +ManglingError Remangler::manglePropertyWrapperBackingInitializer( + Node *node, EntityContext &ctx, unsigned depth) { + return mangleSimpleEntity(node, 'I', "P", ctx, depth + 1); +} + +ManglingError Remangler::manglePropertyWrapperInitFromProjectedValue( + Node *node, EntityContext &ctx, unsigned depth) { + return mangleSimpleEntity(node, 'I', "W", ctx, depth + 1); +} + +ManglingError Remangler::mangleDefaultArgumentInitializer(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleNamedEntity(node, 'I', "A", ctx, depth + 1); +} + +ManglingError Remangler::mangleAsyncFunctionPointer(Node *node, + unsigned depth) { + Buffer << "Tu"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDeallocator(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'F', "D", ctx, depth + 1); +} + +ManglingError Remangler::mangleIsolatedDeallocator(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'F', "Z", ctx, depth + 1); +} + +ManglingError Remangler::mangleDestructor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'F', "d", ctx, depth + 1); +} + +ManglingError Remangler::mangleAllocator(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleTypedEntity(node, 'F', "C", ctx, depth + 1); +} + +ManglingError Remangler::mangleConstructor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleTypedEntity(node, 'F', "c", ctx, depth + 1); +} + +ManglingError Remangler::mangleIVarInitializer(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'F', "e", ctx, depth + 1); +} + +ManglingError Remangler::mangleIVarDestroyer(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleSimpleEntity(node, 'F', "E", ctx, depth + 1); +} + +ManglingError Remangler::mangleGetter(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "g", ctx, depth + 1); +} + +ManglingError Remangler::mangleGlobalGetter(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "G", ctx, depth + 1); +} + +ManglingError Remangler::mangleSetter(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "s", ctx, depth + 1); +} + +ManglingError Remangler::mangleMaterializeForSet(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "m", ctx, depth + 1); +} + +ManglingError Remangler::mangleWillSet(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "w", ctx, depth + 1); +} + +ManglingError Remangler::mangleDidSet(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "W", ctx, depth + 1); +} + +ManglingError Remangler::mangleInitAccessor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "i", ctx, depth + 1); +} + +ManglingError Remangler::mangleOwningMutableAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "aO", ctx, depth + 1); +} + +ManglingError Remangler::mangleNativeOwningMutableAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "ao", ctx, depth + 1); +} + +ManglingError Remangler::mangleNativePinningMutableAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "ap", ctx, depth + 1); +} + +ManglingError Remangler::mangleUnsafeMutableAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "au", ctx, depth + 1); +} + +ManglingError Remangler::mangleOwningAddressor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "lO", ctx, depth + 1); +} + +ManglingError Remangler::mangleNativeOwningAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "lo", ctx, depth + 1); +} + +ManglingError Remangler::mangleNativePinningAddressor(Node *node, + EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "lp", ctx, depth + 1); +} + +ManglingError Remangler::mangleUnsafeAddressor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "lu", ctx, depth + 1); +} + +ManglingError Remangler::mangleReadAccessor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "r", ctx, depth + 1); +} + +ManglingError Remangler::mangleRead2Accessor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "y", ctx, depth + 1); +} + +ManglingError Remangler::mangleModifyAccessor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "M", ctx, depth + 1); +} + +ManglingError Remangler::mangleModify2Accessor(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAccessor(node->getFirstChild(), "x", ctx, depth + 1); +} + +ManglingError Remangler::mangleExplicitClosure(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleNamedAndTypedEntity(node, 'F', "U", ctx, + depth + 1); // name is index +} + +ManglingError Remangler::mangleImplicitClosure(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleNamedAndTypedEntity(node, 'F', "u", ctx, + depth + 1); // name is index +} + +ManglingError Remangler::mangleStatic(Node *node, EntityContext &ctx, + unsigned depth) { + Buffer << 'Z'; + return mangleEntityContext(node->getChild(0), ctx, depth + 1); +} + +ManglingError Remangler::mangleSimpleEntity(Node *node, char basicKind, + StringRef entityKind, + EntityContext &ctx, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 1, node); + Buffer << basicKind; + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + Buffer << entityKind; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleNamedEntity(Node *node, char basicKind, StringRef entityKind, + EntityContext &ctx, unsigned depth, + StringRef artificialPrivateDiscriminator) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + if (basicKind != '\0') Buffer << basicKind; + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + Buffer << entityKind; + + auto privateDiscriminator = ctx.takeAnonymousContextDiscriminator(); + if (!privateDiscriminator.empty() && + swift::Mangle::isDigit(privateDiscriminator[0])) + privateDiscriminator = "_" + privateDiscriminator; + if (!artificialPrivateDiscriminator.empty()) + privateDiscriminator.append(artificialPrivateDiscriminator.data(), + artificialPrivateDiscriminator.size()); + + // Include the artificial private discriminator if one was given. + auto name = node->getChild(1); + if (!privateDiscriminator.empty() + && name->getKind() == Node::Kind::Identifier) { + Buffer << 'P'; + RETURN_IF_ERROR( + mangleIdentifier(privateDiscriminator, OperatorKind::NotOperator)); + } + return mangle(name, depth + 1); +} + +ManglingError Remangler::mangleTypedEntity(Node *node, char basicKind, + StringRef entityKind, + EntityContext &ctx, unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2 || node->getNumChildren() == 3, + node); + Buffer << basicKind; + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + Buffer << entityKind; + + if (node->begin()[1]->getKind() == Node::Kind::LabelList) { + auto LabelList = node->begin()[1]; + auto Type = node->begin()[2]; + RETURN_IF_ERROR(mangleEntityType(applyParamLabels(LabelList, Type, Factory), + ctx, depth + 1)); + } else { + RETURN_IF_ERROR(mangleEntityType(node->begin()[1], ctx, depth + 1)); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleNamedAndTypedEntity(Node *node, char basicKind, + StringRef entityKind, + EntityContext &ctx, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 3 || node->getNumChildren() == 4, + node); + Buffer << basicKind; + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + Buffer << entityKind; + RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // decl name / index + + if (node->begin()[2]->getKind() == Node::Kind::LabelList) { + auto LabelList = node->begin()[2]; + auto Type = node->begin()[3]; + RETURN_IF_ERROR(mangleEntityType(applyParamLabels(LabelList, Type, Factory), + ctx, depth + 1)); + } else { + RETURN_IF_ERROR(mangleEntityType(node->begin()[2], ctx, depth + 1)); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleEntityContext(Node *node, EntityContext &ctx, + unsigned depth) { + // Remember that we're mangling a context. + EntityContext::ManglingContextRAII raii(ctx); + + // Deal with bound generic types. + switch (node->getKind()) { + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericOtherNominalType: + case Node::Kind::BoundGenericTypeAlias: + return mangleAnyNominalType(node, ctx, depth + 1); + + default: + break; + } + + switch (node->getKind()) { +#define NODE(ID) \ + case Node::Kind::ID: +#define CONTEXT_NODE(ID) +#include "swift/Demangling/DemangleNodes.def" + return MANGLING_ERROR(ManglingError::NotAContextNode, node); + +#define NODE(ID) +#define CONTEXT_NODE(ID) \ + case Node::Kind::ID: \ + return mangle##ID(node, ctx, depth + 1); +#include "swift/Demangling/DemangleNodes.def" + } + + return MANGLING_ERROR(ManglingError::BadNodeKind, node); +} + +ManglingError Remangler::mangleEntityType(Node *node, EntityContext &ctx, + unsigned depth) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::Type, node); + DEMANGLER_ASSERT(node->getNumChildren() == 1, node); + node = node->begin()[0]; + + // Expand certain kinds of type within the entity context. + switch (node->getKind()) { + case Node::Kind::NoEscapeFunctionType: + case Node::Kind::FunctionType: + case Node::Kind::UncurriedFunctionType: { + Buffer << ((node->getKind() == Node::Kind::FunctionType || + node->getKind() == Node::Kind::NoEscapeFunctionType) + ? 'F' + : 'f'); + DEMANGLER_ASSERT(node->getNumChildren() >= 2, node); + unsigned inputIndex = node->getNumChildren() - 2; + for (unsigned i = 0; i <= inputIndex; ++i) + RETURN_IF_ERROR(mangle(node->begin()[i], depth + 1)); + auto returnType = node->begin()[inputIndex+1]; + DEMANGLER_ASSERT(returnType->getKind() == Node::Kind::ReturnType, + returnType); + DEMANGLER_ASSERT(returnType->getNumChildren() == 1, returnType); + return mangleEntityType(returnType->begin()[0], ctx, depth + 1); + } + default: + return mangle(node, depth + 1); + } +} + +ManglingError Remangler::mangleLocalDeclName(Node *node, unsigned depth) { + Buffer << 'L'; + return mangleChildNodes(node, depth + 1); // index, identifier +} + +ManglingError Remangler::manglePrivateDeclName(Node *node, unsigned depth) { + Buffer << 'P'; + return mangleChildNodes(node, depth + 1); // identifier, identifier +} + +ManglingError Remangler::mangleRelatedEntityDeclName(Node *node, + unsigned depth) { + // Non-round-trip mangling: pretend we have a private discriminator "$A" for a + // related entity "A". + NodePointer kindNode = node->getFirstChild(); + Buffer << 'P' << (kindNode->getText().size() + 1) << '$' << kindNode->getText(); + return mangleChildNode(node, 1, depth + 1); +} + +ManglingError Remangler::mangleTypeMangling(Node *node, unsigned depth) { + Buffer << 't'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleType(Node *node, unsigned depth) { + return mangleSingleChildNode(node, depth + 1); +} + +template +static bool stripPrefix(StringRef &string, const char (&data)[N]) { + constexpr size_t prefixLength = N - 1; + if (!string.starts_with(StringRef(data, prefixLength))) + return false; + string = string.drop_front(prefixLength); + return true; +} + +ManglingError Remangler::mangleBuiltinFixedArray(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnexpectedBuiltinType, node); +} + +ManglingError Remangler::mangleBuiltinTypeName(Node *node, unsigned depth) { + Buffer << 'B'; + StringRef text = node->getText(); + + if (text == "Builtin.BridgeObject") { + Buffer << 'b'; + } else if (text == "Builtin.UnsafeValueBuffer") { + Buffer << 'B'; + } else if (text == "Builtin.UnknownObject") { + Buffer << 'O'; + } else if (text == "Builtin.NativeObject") { + Buffer << 'o'; + } else if (text == "Builtin.RawPointer") { + Buffer << 'p'; + } else if (text == "Builtin.Word") { + Buffer << 'w'; + } else if (stripPrefix(text, "Builtin.Int")) { + Buffer << 'i' << text << '_'; + } else if (stripPrefix(text, "Builtin.FPIEEE")) { + 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'); + Buffer << 'v' << text.substr(0, splitIdx) << 'B'; + auto element = text.substr(splitIdx).substr(1); + if (element == "RawPointer") { + Buffer << 'p'; + } else if (stripPrefix(element, "FPIEEE")) { + Buffer << 'f' << element << '_'; + } else if (stripPrefix(element, "Int")) { + Buffer << 'i' << element << '_'; + } else { + return MANGLING_ERROR(ManglingError::UnexpectedBuiltinVectorType, node); + } + } else { + return MANGLING_ERROR(ManglingError::UnexpectedBuiltinType, node); + } + + return ManglingError::Success; +} + +ManglingError Remangler::mangleBuiltinTupleType(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnexpectedBuiltinType, node); +} + +ManglingError Remangler::mangleTypeAlias(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleFunctionType(Node *node, unsigned depth) { + Buffer << 'F'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleUncurriedFunctionType(Node *node, + unsigned depth) { + Buffer << 'f'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleObjCBlock(Node *node, unsigned depth) { + Buffer << 'b'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleEscapingObjCBlock(Node *node, unsigned depth) { + // ###TODO: Is this right? Should this be an error? + // We shouldn't ever be remangling anything with a DWARF-only mangling. + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleCFunctionPointer(Node *node, unsigned depth) { + Buffer << 'c'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleAutoClosureType(Node *node, unsigned depth) { + Buffer << 'K'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleNoEscapeFunctionType(Node *node, + unsigned depth) { + Buffer << 'F'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleEscapingAutoClosureType(Node *node, + unsigned depth) { + Buffer << 'K'; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleThinFunctionType(Node *node, unsigned depth) { + Buffer << "Xf"; + return mangleChildNodes(node, depth + 1); // argument tuple, result type +} + +ManglingError Remangler::mangleArgumentTuple(Node *node, unsigned depth) { + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleReturnType(Node *node, unsigned depth) { + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) { + 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") { + Buffer << 'd'; + } else if (text == "@callee_guaranteed") { + Buffer << 'g'; + } else if (text == "@callee_owned") { + Buffer << 'o'; + } else { + return MANGLING_ERROR(ManglingError::InvalidImplCalleeConvention, *i); + } + } else { + Buffer << 't'; + } + for (; i != e && + (*i)->getKind() == Node::Kind::ImplFunctionAttribute; ++i) { + RETURN_IF_ERROR(mangle(*i, depth + 1)); // impl function attribute + } + if (i != e && + ((*i)->getKind() == Node::Kind::DependentGenericSignature || + (*i)->getKind() == Node::Kind::DependentPseudogenericSignature)) { + Buffer << ((*i)->getKind() == Node::Kind::DependentGenericSignature + ? 'G' : 'g'); + RETURN_IF_ERROR(mangleDependentGenericSignature((*i), depth + 1)); + ++i; + } + Buffer << '_'; + for (; i != e && (*i)->getKind() == Node::Kind::ImplParameter; ++i) { + RETURN_IF_ERROR(mangleImplParameter(*i, depth + 1)); + } + Buffer << '_'; + RETURN_IF_ERROR(mangleNodes(i, e, depth + 1)); // impl results + Buffer << '_'; + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplCoroutineKind(Node *node, + unsigned depth) { + StringRef text = node->getText(); + if (text == "yield_once") { + Buffer << "A"; + } else if (text == "yield_once_2") { + Buffer << "I"; + } else if (text == "yield_many") { + Buffer << "G"; + } else { + return MANGLING_ERROR(ManglingError::InvalidImplCoroutineKind, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplFunctionAttribute(Node *node, + unsigned depth) { + StringRef text = node->getText(); + if (text == "@Sendable") { + Buffer << "h"; + } else if (text == "@async") { + Buffer << "H"; + } else { + return MANGLING_ERROR(ManglingError::InvalidImplFunctionAttribute, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplFunctionConvention(Node *node, + unsigned depth) { + return mangle(node->getChild(0), depth + 1); +} + +ManglingError Remangler::mangleImplFunctionConventionName(Node *node, + unsigned depth) { + StringRef text = node->getText(); + if (text == "block") { + Buffer << "Cb"; + } else if (text == "c") { + Buffer << "Cc"; + } else if (text == "method") { + Buffer << "Cm"; + } else if (text == "objc_method") { + Buffer << "CO"; + } else if (text == "witness_method") { + Buffer << "Cw"; + } else { + return MANGLING_ERROR(ManglingError::InvalidImplCalleeConvention, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleClangType(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleImplParameter(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + return mangleChildNodes(node, depth + 1); // impl convention, type +} + +ManglingError Remangler::mangleImplErrorResult(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + Buffer << 'z'; + return mangleChildNodes(node, depth + 1); // impl convention, type +} + +ManglingError Remangler::mangleImplResult(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + return mangleChildNodes(node, depth + 1); // impl convention, type +} + +ManglingError Remangler::mangleImplYield(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + Buffer << 'Y'; + return mangleChildNodes(node, depth + 1); // impl convention, type +} + +ManglingError Remangler::mangleImplDifferentiabilityKind(Node *node, + unsigned depth) { + // TODO(TF-750): Check if this code path actually triggers and add a test. + Buffer << (char)node->getIndex(); + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplEscaping(Node *node, unsigned depth) { + // The old mangler does not encode escaping. + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplErasedIsolation(Node *node, unsigned depth) { + // The old mangler does not encode @isolated(any). + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplSendingResult(Node *node, unsigned depth) { + // The old mangler does not encode sending result + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplPatternSubstitutions(Node *node, + unsigned depth) { + // The old mangler does not encode substituted function types. + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplInvocationSubstitutions(Node *node, + unsigned depth) { + // The old mangler does not encode substituted function types. + return ManglingError::Success; +} + +ManglingError Remangler::mangleImplConvention(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::ImplConvention, node); + StringRef text = node->getText(); + if (text == "@autoreleased") { + Buffer << 'a'; + } else if (text == "@unowned") { + Buffer << 'd'; + } else if (text == "@unowned_inner_pointer") { + Buffer << 'D'; // only in results + } else if (text == "@guaranteed") { + Buffer << 'g'; + } else if (text == "@deallocating") { + Buffer << 'e'; + } else if (text == "@in") { + Buffer << 'i'; // only in parameters + } else if (text == "@out") { + Buffer << 'i'; // only in results + } else if (text == "@inout") { + Buffer << 'l'; + } else if (text == "@owned") { + Buffer << 'o'; + } else { + return MANGLING_ERROR(ManglingError::InvalidImplParameterConvention, node); + } + return ManglingError::Success; +} + +ManglingError +Remangler::mangleImplParameterResultDifferentiability(Node *node, + unsigned depth) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::ImplDifferentiabilityKind, + node); + StringRef text = node->getText(); + // Empty string represents default differentiability. + if (text.empty()) + return ManglingError::Success; + if (text == "@noDerivative") { + Buffer << 'w'; + return ManglingError::Success; + } + return MANGLING_ERROR(ManglingError::InvalidImplDifferentiability, node); +} + +ManglingError Remangler::mangleImplParameterSending(Node *node, + unsigned depth) { + StringRef text = node->getText(); + if (text == "sending") { + Buffer << 'T'; + return ManglingError::Success; + } + return MANGLING_ERROR(ManglingError::InvalidImplParameterSending, node); +} + +ManglingError Remangler::mangleDynamicSelf(Node *node, unsigned depth) { + Buffer << 'D'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleErrorType(Node *node, unsigned depth) { + Buffer << "ERR"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILBoxType(Node *node, unsigned depth) { + Buffer << 'X' << 'b'; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleMetatype(Node *node, unsigned depth) { + if (node->getNumChildren() == 1) { + Buffer << 'M'; + return mangleSingleChildNode(node, depth + 1); // type + } else { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + Buffer << "XM"; + return mangleChildNodes(node, depth + 1); // metatype representation, type + } +} + +ManglingError Remangler::mangleExistentialMetatype(Node *node, unsigned depth) { + if (node->getNumChildren() == 1) { + Buffer << "PM"; + return mangleSingleChildNode(node, depth + 1); // type + } else { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + Buffer << "XPM"; + return mangleChildNodes(node, depth + 1); // metatype representation, type + } +} + +ManglingError Remangler::mangleMetatypeRepresentation(Node *node, + unsigned depth) { + StringRef text = node->getText(); + if (text == "@thin") { + Buffer << 't'; + } else if (text == "@thick") { + Buffer << 'T'; + } else if (text == "@objc_metatype") { + Buffer << 'o'; + } else { + return MANGLING_ERROR(ManglingError::InvalidMetatypeRepresentation, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleProtocolList(Node *node, unsigned depth) { + // In its usual use as a type, this gets a prefix 'P'. + Buffer << 'P'; + return mangleProtocolListWithoutPrefix(node, depth + 1); +} + +ManglingError +Remangler::mangleProtocolListWithoutPrefix(Node *node, unsigned depth, + Node *additionalProto) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::ProtocolList, node); + DEMANGLER_ASSERT(node->getNumChildren() == 1, node); + auto typeList = node->begin()[0]; + DEMANGLER_ASSERT(typeList->getKind() == Node::Kind::TypeList, typeList); + for (auto &child : *typeList) { + RETURN_IF_ERROR(mangleProtocolWithoutPrefix(child, depth + 1)); + } + if (additionalProto) { + RETURN_IF_ERROR(mangleProtocolWithoutPrefix(additionalProto, depth + 1)); + } + Buffer << '_'; + return ManglingError::Success; +} + +#define REF_STORAGE(Name, ...) \ + ManglingError Remangler::mangle##Name(Node *node, unsigned depth) { \ + Buffer << manglingOf(ReferenceOwnership::Name); \ + return mangleSingleChildNode(node, depth + 1); /* type */ \ + } +#include "swift/AST/ReferenceStorage.def" + +ManglingError Remangler::mangleShared(Node *node, unsigned depth) { + Buffer << 'h'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleOwned(Node *node, unsigned depth) { + Buffer << 'n'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleInOut(Node *node, unsigned depth) { + Buffer << 'R'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleIsolated(Node *node, unsigned depth) { + Buffer << "Yi"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleSending(Node *node, unsigned depth) { + Buffer << "Yu"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleCompileTimeConst(Node *node, unsigned depth) { + Buffer << "Yt"; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleNoDerivative(Node *node, unsigned depth) { + Buffer << 'k'; + return mangleSingleChildNode(node, depth + 1); // type +} + +ManglingError Remangler::mangleTuple(Node *node, unsigned depth) { + size_t NumElems = node->getNumChildren(); + if (NumElems > 0 && + node->getChild(NumElems - 1)->getFirstChild()->getKind() == + Node::Kind::VariadicMarker) { + Buffer << 't'; + } else { + Buffer << 'T'; + } + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); // tuple elements + Buffer << '_'; + return ManglingError::Success; +} + +ManglingError Remangler::mangleTupleElement(Node *node, unsigned depth) { + return mangleChildNodes(node, depth + 1); // tuple element name?, type +} + +ManglingError Remangler::mangleTupleElementName(Node *node, unsigned depth) { + return mangleIdentifier(node->getText(), OperatorKind::NotOperator); +} + +ManglingError Remangler::manglePack(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSILPackDirect(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSILPackIndirect(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::manglePackExpansion(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::manglePackElement(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::manglePackElementLevel(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleDependentGenericType(Node *node, + unsigned depth) { + Buffer << 'u'; + return mangleChildNodes(node, depth + 1); // generic signature, type +} + +ManglingError Remangler::mangleDependentPseudogenericSignature(Node *node, + unsigned depth) { + return mangleDependentGenericSignature(node, depth + 1); +} + +ManglingError Remangler::mangleDependentGenericParamPackMarker(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleDependentGenericSignature(Node *node, + unsigned depth) { + auto i = node->begin(), e = node->end(); + + // If there's only one generic param, mangle nothing. + if (node->getNumChildren() >= 1 + && node->getChild(0)->getKind() == Node::Kind::DependentGenericParamCount + && node->getChild(0)->getIndex() == 1 + && (node->getNumChildren() == 1 + || node->getChild(1)->getKind() != Node::Kind::DependentGenericParamCount)) + { + ++i; + goto mangle_requirements; + } + + // Remangle generic params. + for (; i != e && + (*i)->getKind() == Node::Kind::DependentGenericParamCount; ++i) { + auto count = *i; + if (count->getIndex() > 0) + mangleIndex(count->getIndex() - 1); + else + Buffer << 'z'; + } + +mangle_requirements: + if (i == e) { // no generic requirements + Buffer << 'r'; + return ManglingError::Success; + } + + Buffer << 'R'; + RETURN_IF_ERROR(mangleNodes(i, e, depth + 1)); // generic requirements + Buffer << 'r'; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentGenericParamCount(Node *node, + unsigned depth) { + // handled inline in DependentGenericSignature + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleDependentGenericConformanceRequirement(Node *node, + unsigned depth) { + RETURN_IF_ERROR(mangleConstrainedType(node->getChild(0), depth + 1)); + // If the constraint represents a protocol, use the shorter mangling. + if (node->getNumChildren() == 2 + && node->getChild(1)->getKind() == Node::Kind::Type + && node->getChild(1)->getNumChildren() == 1 + && node->getChild(1)->getChild(0)->getKind() == Node::Kind::Protocol) { + return mangleProtocolWithoutPrefix(node->getChild(1)->getChild(0), + depth + 1); + } + + return mangle(node->getChild(1), depth + 1); +} + +ManglingError +Remangler::mangleDependentGenericSameTypeRequirement(Node *node, + unsigned depth) { + RETURN_IF_ERROR(mangleConstrainedType(node->getChild(0), depth + 1)); + Buffer << 'z'; + return mangle(node->getChild(1), depth + 1); +} + +ManglingError +Remangler::mangleDependentGenericSameShapeRequirement(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleDependentGenericLayoutRequirement(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleConstrainedType(node->getChild(0), depth + 1)); + Buffer << 'l'; + auto id = node->getChild(1)->getText(); + auto size = -1; + if (node->getNumChildren() > 2) { + size = node->getChild(2)->getIndex(); + } + int alignment = -1; + if (node->getNumChildren() > 3) { + alignment = node->getChild(3)->getIndex(); + } + Buffer << id; + if (size >= 0) + Buffer << size; + if (alignment >= 0) { + Buffer << "_" << alignment; + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleConstrainedType(Node *node, unsigned depth) { + if (node->getFirstChild()->getKind() + == Node::Kind::DependentGenericParamType) { + // Can be mangled without an introducer. + return mangleDependentGenericParamIndex(node->getFirstChild(), depth + 1); + } else { + return mangle(node, depth + 1); + } +} + +ManglingError Remangler::mangleAssociatedType(Node *node, unsigned depth) { + if (node->hasChildren()) { + DEMANGLER_ASSERT(node->getNumChildren() == 1, node); + return mangleProtocolListWithoutPrefix(*node->begin(), depth + 1); + } else { + Buffer << '_'; + return ManglingError::Success; + } +} + +ManglingError Remangler::mangleDeclContext(Node *node, unsigned depth) { + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleExtension(Node *node, EntityContext &ctx, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2 || node->getNumChildren() == 3, + node); + if (node->getNumChildren() == 3) { + Buffer << 'e'; + } else { + Buffer << 'E'; + } + // module + RETURN_IF_ERROR(mangleEntityContext(node->begin()[0], ctx, depth + 1)); + if (node->getNumChildren() == 3) { + // generic sig + RETURN_IF_ERROR( + mangleDependentGenericSignature(node->begin()[2], depth + 1)); + } + + // context + return mangleEntityContext(node->begin()[1], ctx, depth + 1); +} + +ManglingError Remangler::mangleAnonymousContext(Node *node, EntityContext &ctx, + unsigned depth) { + RETURN_IF_ERROR(mangleEntityContext(node->getChild(1), ctx, depth + 1)); + + // Since we can't change the old mangling, mangle an anonymous context by + // introducing a private discriminator onto its child contexts. + ctx.setAnonymousContextDiscriminator(node->getChild(0)->getText()); + + return ManglingError::Success; +} + +ManglingError Remangler::mangleModule(Node *node, EntityContext &ctx, + unsigned depth) { + SubstitutionEntry entry; + if (trySubstitution(node, entry)) + return ManglingError::Success; + + // Module types get an M prefix, but module contexts don't. + if (!ctx.isAsContext()) Buffer << 'M'; + RETURN_IF_ERROR(mangleIdentifier(node->getText(), OperatorKind::NotOperator)); + addSubstitution(entry); + return ManglingError::Success; +} + +ManglingError Remangler::mangleAssociatedTypeRef(Node *node, unsigned depth) { + SubstitutionEntry entry; + if (trySubstitution(node, entry)) + return ManglingError::Success; + Buffer << "Q"; + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); // type, identifier + addSubstitution(entry); + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentMemberType(Node *node, unsigned depth) { + Vector members; + Node *base = node; + do { + members.push_back(base, Factory); + base = base->getFirstChild()->getFirstChild(); + } while (base->getKind() == Node::Kind::DependentMemberType); + + DEMANGLER_ASSERT(base->getKind() == Node::Kind::DependentGenericParamType && + "dependent members not based on a generic param are " + "non-canonical and shouldn't need remangling", + base); + DEMANGLER_ASSERT(members.size() >= 1, node); + if (members.size() == 1) { + Buffer << 'w'; + RETURN_IF_ERROR(mangleDependentGenericParamIndex(base, depth + 1)); + RETURN_IF_ERROR(mangle(members[0]->getChild(1), depth + 1)); + } else { + Buffer << 'W'; + RETURN_IF_ERROR(mangleDependentGenericParamIndex(base, depth + 1)); + + for (unsigned i = 1, n = members.size(); i <= n; ++i) { + Node *member = members[n - i]; + RETURN_IF_ERROR(mangle(member->getChild(1), depth + 1)); + } + Buffer << '_'; + } + + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentAssociatedTypeRef(Node *node, + unsigned depth) { + SubstitutionEntry entry; + if (trySubstitution(node, entry)) + return ManglingError::Success; + + if (node->getNumChildren() > 1) { + Buffer << 'P'; + RETURN_IF_ERROR(mangleProtocolWithoutPrefix(node->getChild(1), depth + 1)); + } + RETURN_IF_ERROR(mangleIdentifier(node->getFirstChild(), depth + 1)); + + addSubstitution(entry); + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentGenericParamIndex(Node *node, + unsigned depth) { + auto paramDepth = node->getChild(0)->getIndex(); + auto index = node->getChild(1)->getIndex(); + + if (paramDepth != 0) { + Buffer << 'd'; + mangleIndex(paramDepth - 1); + mangleIndex(index); + return ManglingError::Success; + } + if (index != 0) { + mangleIndex(index - 1); + return ManglingError::Success; + } + + // paramDepth == index == 0 + Buffer << 'x'; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentGenericParamType(Node *node, + unsigned depth) { + if (node->getChild(0)->getIndex() == 0 + && node->getChild(1)->getIndex() == 0) { + Buffer << 'x'; + return ManglingError::Success; + } + + Buffer << 'q'; + return mangleDependentGenericParamIndex(node, depth + 1); +} + +ManglingError Remangler::mangleIndex(Node *node, unsigned depth) { + mangleIndex(node->getIndex()); + return ManglingError::Success; +} + +ManglingError Remangler::mangleUnknownIndex(Node *node, unsigned depth) { + // should not be reached in an arbitrary context + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleProtocol(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleNominalType(node, 'P', ctx, depth + 1); +} + +ManglingError Remangler::mangleProtocolWithoutPrefix(Node *node, + unsigned depth) { + if (mangleStandardSubstitution(node)) + return ManglingError::Success; + + if (node->getKind() == Node::Kind::Type) { + DEMANGLER_ASSERT(node->getNumChildren() == 1, node); + node = node->begin()[0]; + } + + DEMANGLER_ASSERT(node->getKind() == Node::Kind::Protocol, node); + EntityContext ctx; + return mangleNominalType(node, '\0', ctx, depth + 1); +} + +ManglingError Remangler::mangleGenericArgs(Node *node, EntityContext &ctx, + unsigned depth) { + switch (node->getKind()) { + case Node::Kind::Structure: + case Node::Kind::Enum: + case Node::Kind::Class: { + NodePointer parentOrModule = node->getChild(0); + RETURN_IF_ERROR(mangleGenericArgs(parentOrModule, ctx, depth + 1)); + + // No generic arguments at this level + Buffer << '_'; + break; + } + + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericClass: { + NodePointer unboundType = node->getChild(0); + DEMANGLER_ASSERT(unboundType->getKind() == Node::Kind::Type, unboundType); + NodePointer nominalType = unboundType->getChild(0); + NodePointer parentOrModule = nominalType->getChild(0); + RETURN_IF_ERROR(mangleGenericArgs(parentOrModule, ctx, depth + 1)); + + RETURN_IF_ERROR(mangleTypeList(node->getChild(1), depth + 1)); + break; + } + + case Node::Kind::AnonymousContext: + case Node::Kind::Extension: { + RETURN_IF_ERROR(mangleGenericArgs(node->getChild(1), ctx, depth + 1)); + break; + } + + default: + break; + } + + return ManglingError::Success; +} + +ManglingError Remangler::mangleAnyNominalType(Node *node, EntityContext &ctx, + unsigned depth) { + if (depth > Remangler::MaxDepth) + return MANGLING_ERROR(ManglingError::TooComplex, node); + + if (isSpecialized(node)) { + Buffer << 'G'; + + auto unspec = getUnspecialized(node, Factory); + if (!unspec.isSuccess()) + return unspec.error(); + NodePointer unboundType = unspec.result(); + + RETURN_IF_ERROR(mangleAnyNominalType(unboundType, ctx, depth + 1)); + return mangleGenericArgs(node, ctx, depth + 1); + } + + switch (node->getKind()) { + case Node::Kind::Type: + RETURN_IF_ERROR(mangleAnyNominalType(node->getChild(0), ctx, depth + 1)); + break; + case Node::Kind::OtherNominalType: + // Mangle unknown type kinds as structures since we can't change the old + // mangling. Give the mangling an artificial "private discriminator" so that + // clients who understand the old mangling know this is an unstable + // mangled name. + RETURN_IF_ERROR( + mangleNominalType(node, 'V', ctx, depth + 1, "_UnknownTypeKind")); + break; + case Node::Kind::Structure: + RETURN_IF_ERROR(mangleNominalType(node, 'V', ctx, depth + 1)); + break; + case Node::Kind::Enum: + RETURN_IF_ERROR(mangleNominalType(node, 'O', ctx, depth + 1)); + break; + case Node::Kind::Class: + RETURN_IF_ERROR(mangleNominalType(node, 'C', ctx, depth + 1)); + break; + case Node::Kind::TypeAlias: + RETURN_IF_ERROR(mangleNominalType(node, 'a', ctx, depth + 1)); + break; + default: + return MANGLING_ERROR(ManglingError::BadNominalTypeKind, node); + } + return ManglingError::Success; +} + +ManglingError Remangler::mangleStructure(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleEnum(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleClass(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleOtherNominalType(Node *node, EntityContext &ctx, + unsigned depth) { + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError +Remangler::mangleNominalType(Node *node, char kind, EntityContext &ctx, + unsigned depth, + StringRef artificialPrivateDiscriminator) { + SubstitutionEntry entry; + if (node->getKind() == Node::Kind::Type) { + node = node->getChild(0); + } + if (trySubstitution(node, entry)) + return ManglingError::Success; + RETURN_IF_ERROR(mangleNamedEntity(node, kind, "", ctx, depth + 1, + artificialPrivateDiscriminator)); + addSubstitution(entry); + return ManglingError::Success; +} + +ManglingError Remangler::mangleBoundGenericClass(Node *node, unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericStructure(Node *node, + unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericEnum(Node *node, unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericOtherNominalType(Node *node, + unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericProtocol(Node *node, + unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericTypeAlias(Node *node, + unsigned depth) { + EntityContext ctx; + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleBoundGenericFunction(Node *node, + unsigned depth) { + EntityContext ctx; + // Not really a nominal type, but it works for functions, too. + return mangleAnyNominalType(node, ctx, depth + 1); +} + +ManglingError Remangler::mangleTypeList(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); // all types + Buffer << '_'; + return ManglingError::Success; +} + +ManglingError Remangler::mangleLabelList(Node *node, unsigned depth) { + if (node->getNumChildren() == 0) { + Buffer << 'y'; + return ManglingError::Success; + } else { + return mangleChildNodes(node, depth + 1); + } +} + +ManglingError +Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node, + unsigned depth) { + Buffer << "MRb"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleReflectionMetadataFieldDescriptor(Node *node, unsigned depth) { + Buffer << "MRf"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node, + unsigned depth) { + Buffer << "MRa"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node, + unsigned depth) { + Buffer << "MRc"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleGenericTypeParamDecl(Node *node, + unsigned depth) { + // todo + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleCurryThunk(Node *node, unsigned depth) { + // ###TODO: Are these errors?! + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILThunkIdentity(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILThunkHopToMainActorIfNeeded(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleDispatchThunk(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleMethodDescriptor(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleMethodLookupFunction(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleObjCMetadataUpdateFunction(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleObjCResilientClassStub(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleFullObjCResilientClassStub(Node *node, + unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleEmptyList(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleFirstElementMarker(Node *node, unsigned depth) { + Buffer << ""; + return ManglingError::Success; +} + +ManglingError Remangler::mangleVariadicMarker(Node *node, unsigned depth) { + // Handled in mangleTuple + + // ###TODO: Is this an error? + return ManglingError::Success; +} + +ManglingError Remangler::mangleOutlinedCopy(Node *node, unsigned depth) { + Buffer << "Wy"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedConsume(Node *node, unsigned depth) { + Buffer << "We"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedRetain(Node *node, unsigned depth) { + Buffer << "Wr"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedRelease(Node *node, unsigned depth) { + Buffer << "Ws"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedInitializeWithTake(Node *node, + unsigned depth) { + Buffer << "Wb"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedInitializeWithCopy(Node *node, + unsigned depth) { + Buffer << "Wc"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedAssignWithTake(Node *node, + unsigned depth) { + Buffer << "Wd"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedAssignWithCopy(Node *node, + unsigned depth) { + Buffer << "Wf"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedDestroy(Node *node, unsigned depth) { + Buffer << "Wh"; + return mangleSingleChildNode(node, depth + 1); +} +ManglingError Remangler::mangleOutlinedInitializeWithCopyNoValueWitness(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleOutlinedAssignWithTakeNoValueWitness(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleOutlinedAssignWithCopyNoValueWitness(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleOutlinedDestroyNoValueWitness(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOutlinedEnumTagStore(Node *node, unsigned depth) { + Buffer << "Wi"; + return mangleSingleChildNode(node, depth + 1); +} +ManglingError Remangler::mangleOutlinedEnumGetTag(Node *node, unsigned depth) { + Buffer << "Wg"; + return mangleSingleChildNode(node, depth + 1); +} +ManglingError Remangler::mangleOutlinedEnumProjectDataForLoad(Node *node, unsigned depth) { + Buffer << "Wj"; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedVariable(Node *node, unsigned depth) { + Buffer << "Tv" << node->getIndex(); + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedReadOnlyObject(Node *node, unsigned depth) { + Buffer << "Tv" << node->getIndex() << 'r'; + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleOutlinedBridgedMethod(Node *node, + unsigned depth) { + Buffer << "Te" << node->getText(); + return mangleSingleChildNode(node, depth + 1); +} + +ManglingError Remangler::mangleCoroutineContinuationPrototype(Node *node, + unsigned depth) { + Buffer << "TC"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleKeyPathGetterThunkHelper(Node *node, + unsigned depth) { + Buffer << "TK"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleKeyPathSetterThunkHelper(Node *node, + unsigned depth) { + Buffer << "Tk"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleKeyPathEqualsThunkHelper(Node *node, + unsigned depth) { + Buffer << "TH"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleKeyPathHashThunkHelper(Node *node, + unsigned depth) { + Buffer << "Th"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleProtocolListWithClass(Node *node, + unsigned depth) { + Buffer << "Xc"; + RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); + return mangleProtocolListWithoutPrefix(node->getChild(0), depth + 1); +} + +ManglingError Remangler::mangleProtocolListWithAnyObject(Node *node, + unsigned depth) { + 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); + Buffer << "P"; + return mangleProtocolListWithoutPrefix(node->getChild(0), depth + 1, + /*additionalProto*/ P); +} + +ManglingError Remangler::mangleVTableThunk(Node *node, unsigned depth) { + Buffer << "TV"; + return mangleChildNodes(node, depth + 1); +} + +ManglingError Remangler::mangleSILBoxTypeWithLayout(Node *node, + unsigned depth) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::SILBoxTypeWithLayout, node); + DEMANGLER_ASSERT(node->getNumChildren() == 1 || node->getNumChildren() == 3, + node); + Buffer << "XB"; + auto layout = node->getChild(0); + DEMANGLER_ASSERT(layout->getKind() == Node::Kind::SILBoxLayout, layout); + NodePointer genericArgs = nullptr; + if (node->getNumChildren() == 3) { + NodePointer signature = node->getChild(1); + DEMANGLER_ASSERT(signature->getKind() == + Node::Kind::DependentGenericSignature, + signature); + genericArgs = node->getChild(2); + DEMANGLER_ASSERT(genericArgs->getKind() == Node::Kind::TypeList, + genericArgs); + + Buffer << 'G'; + RETURN_IF_ERROR(mangleDependentGenericSignature(signature, depth + 1)); + } + RETURN_IF_ERROR(mangleSILBoxLayout(layout, depth + 1)); + if (genericArgs) { + for (unsigned i = 0; i < genericArgs->getNumChildren(); ++i) { + auto type = genericArgs->getChild(i); + DEMANGLER_ASSERT(genericArgs->getKind() == Node::Kind::Type, genericArgs); + RETURN_IF_ERROR(mangleType(type, depth + 1)); + } + Buffer << '_'; + } + + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILBoxLayout(Node *node, unsigned depth) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::SILBoxLayout, node); + for (unsigned i = 0; i < node->getNumChildren(); ++i) { + DEMANGLER_ASSERT(node->getKind() == Node::Kind::SILBoxImmutableField || + node->getKind() == Node::Kind::SILBoxMutableField, + node); + RETURN_IF_ERROR(mangle(node->getChild(i), depth + 1)); + } + Buffer << '_'; + + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILBoxMutableField(Node *node, unsigned depth) { + Buffer << 'm'; + DEMANGLER_ASSERT(node->getNumChildren() == 1 && + node->getChild(0)->getKind() == Node::Kind::Type, + node); + return mangleType(node->getChild(0), depth + 1); +} + +ManglingError Remangler::mangleSILBoxImmutableField(Node *node, + unsigned depth) { + Buffer << 'i'; + DEMANGLER_ASSERT(node->getNumChildren() == 1 && + node->getChild(0)->getKind() == Node::Kind::Type, + node); + return mangleType(node->getChild(0), depth + 1); +} + +ManglingError Remangler::mangleAssocTypePath(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleModuleDescriptor(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleExtensionDescriptor(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleAnonymousDescriptor(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleAssociatedTypeGenericParamRef(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleTypeSymbolicReference(Node *node, + EntityContext &, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleProtocolSymbolicReference(Node *node, + EntityContext &, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleOpaqueTypeDescriptorSymbolicReference(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSugaredOptional(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSugaredArray(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSugaredDictionary(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleSugaredParen(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleOpaqueReturnType(Node *node, unsigned depth) { + if (node->hasChildren() + && node->getFirstChild()->getKind() == Node::Kind::OpaqueReturnTypeIndex){ + Buffer << "QU"; + mangleIndex(node->getFirstChild()->getIndex()); + return ManglingError::Success; + } + + Buffer << "Qu"; + return ManglingError::Success; +} +ManglingError Remangler::mangleOpaqueReturnTypeIndex(Node *node, unsigned depth) { + return ManglingError::WrongNodeType; +} +ManglingError Remangler::mangleOpaqueReturnTypeParent(Node *node, unsigned depth) { + return ManglingError::WrongNodeType; +} +ManglingError Remangler::mangleOpaqueReturnTypeOf(Node *node, + EntityContext &ctx, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueType(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueTypeDescriptor(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueTypeDescriptorRecord(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueTypeDescriptorAccessor(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleOpaqueTypeDescriptorAccessorImpl(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueTypeDescriptorAccessorKey(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleOpaqueTypeDescriptorAccessorVar(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleAccessorFunctionReference(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleMetadataInstantiationCache(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleGlobalVariableOnceToken(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleGlobalVariableOnceFunction(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleGlobalVariableOnceDeclList(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::manglePredefinedObjCAsyncCompletionHandlerImpl(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleObjCAsyncCompletionHandlerImpl(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleConstrainedExistential(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleConstrainedExistentialRequirementList(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleConstrainedExistentialSelf(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleUniquable(Node *node, unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler::mangleSymbolicExtendedExistentialType(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler:: +mangleUniqueExtendedExistentialTypeShapeSymbolicReference(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError Remangler:: +mangleNonUniqueExtendedExistentialTypeShapeSymbolicReference(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} +ManglingError +Remangler::mangleObjectiveCProtocolSymbolicReference(Node *node, + unsigned int depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError +Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node, + unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // type + Buffer << "MM"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleCanonicalSpecializedGenericTypeMetadataAccessFunction( + Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); + Buffer << "Mb"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleNoncanonicalSpecializedGenericTypeMetadata(Node *node, + unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); + Buffer << "MN"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache( + Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); + Buffer << "MJ"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleCanonicalPrespecializedGenericTypeCachingOnceToken( + Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); + Buffer << "Mz"; + return ManglingError::Success; +} + +/// The top-level interface to the remangler. +ManglingErrorOr +Demangle::mangleNodeOld(NodePointer node) { + if (!node) return std::string(); + + NodeFactory Factory; + Remangler remangler(Factory); + ManglingError err = remangler.mangle(node, 0); + if (!err.isSuccess()) + return err; + + return remangler.str(); +} + +ManglingErrorOr +Demangle::mangleNodeOld(NodePointer node, NodeFactory &Factory) { + if (!node) return llvm::StringRef(); + + Remangler remangler(Factory); + ManglingError err = remangler.mangle(node, 0); + if (!err.isSuccess()) + return err; + + return remangler.getBufferStr(); +} + +ManglingErrorOr +Demangle::mangleNodeAsObjcCString(NodePointer node, + NodeFactory &Factory) { + DEMANGLER_ASSERT(node, node); + + Remangler remangler(Factory); + remangler.append("_Tt"); + ManglingError err = remangler.mangle(node, 0); + if (!err.isSuccess()) + return err; + remangler.append(StringRef("_", 2)); // Include the trailing 0 char. + + return remangler.getBufferStr().data(); +} + +ManglingError Remangler::mangleAccessibleFunctionRecord(Node *node, + unsigned depth) { + Buffer << "HF"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleBackDeploymentThunk(Node *node, unsigned depth) { + Buffer << "Twb"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleBackDeploymentFallback(Node *node, + unsigned depth) { + Buffer << "TwB"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleHasSymbolQuery(Node *node, unsigned depth) { + Buffer << "TwS"; + return ManglingError::Success; +} + +ManglingError +Remangler::mangleDependentGenericInverseConformanceRequirement(Node *node, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + RETURN_IF_ERROR(mangleConstrainedType(node->getChild(0), depth + 1)); + return mangle(node->getChild(1), depth + 1); +} + +ManglingError Remangler::mangleInteger(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleNegativeInteger(Node *node, unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + +ManglingError Remangler::mangleDependentGenericParamValueMarker(Node *node, + unsigned depth) { + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} diff --git a/symbolic-demangle/vendor/swift/lib/Demangling/Remangler.cpp b/symbolic-demangle/vendor/swift/lib/Demangling/Remangler.cpp index be1bca1d7..ab51452a5 100644 --- a/symbolic-demangle/vendor/swift/lib/Demangling/Remangler.cpp +++ b/symbolic-demangle/vendor/swift/lib/Demangling/Remangler.cpp @@ -359,7 +359,7 @@ class Remangler : public RemanglerBase { } ManglingError mangleGenericSpecializationNode(Node *node, - const char *operatorStr, + char specKind, unsigned depth); ManglingError mangleAnyNominalType(Node *node, unsigned depth); ManglingError mangleAnyGenericType(Node *node, StringRef TypeOp, @@ -374,6 +374,9 @@ class Remangler : public RemanglerBase { ManglingError mangleKeyPathThunkHelper(Node *node, StringRef op, unsigned depth); + ManglingError mangleSILThunkIdentity(Node *node, StringRef op, + unsigned depth); + ManglingError mangleAutoDiffFunctionOrSimpleThunk(Node *node, StringRef op, unsigned depth); @@ -720,7 +723,7 @@ ManglingError Remangler::mangleAllocator(Node *node, unsigned depth) { } ManglingError Remangler::mangleArgumentTuple(Node *node, unsigned depth) { - Node *Child = skipType(getSingleChild(node)); + Node *Child = skipType(node->getChild(0)); if (Child->getKind() == Node::Kind::Tuple && Child->getNumChildren() == 0) { Buffer << 'y'; @@ -894,6 +897,12 @@ ManglingError Remangler::mangleBoundGenericFunction(Node *node, return ManglingError::Success; } +ManglingError Remangler::mangleBuiltinFixedArray(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); + Buffer << "BV"; + return ManglingError::Success; +} + ManglingError Remangler::mangleBuiltinTypeName(Node *node, unsigned depth) { Buffer << 'B'; StringRef text = node->getText(); @@ -1017,6 +1026,12 @@ ManglingError Remangler::mangleDeallocator(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleIsolatedDeallocator(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); + Buffer << "fZ"; + return ManglingError::Success; +} + ManglingError Remangler::mangleDeclContext(Node *node, unsigned depth) { return mangleSingleChildNode(node, depth + 1); } @@ -1693,7 +1708,7 @@ Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node, } ManglingError -Remangler::mangleGenericSpecializationNode(Node *node, const char *operatorStr, +Remangler::mangleGenericSpecializationNode(Node *node, char specKind, unsigned depth) { bool FirstParam = true; for (NodePointer Child : *node) { @@ -1705,11 +1720,21 @@ Remangler::mangleGenericSpecializationNode(Node *node, const char *operatorStr, DEMANGLER_ASSERT( !FirstParam && "generic specialization with no substitutions", node); - Buffer << operatorStr; + Buffer << 'T'; for (NodePointer Child : *node) { - if (Child->getKind() != Node::Kind::GenericSpecializationParam) + if (Child->getKind() == Node::Kind::DroppedArgument) + RETURN_IF_ERROR(mangle(Child, depth + 1)); + } + + + Buffer << specKind; + + for (NodePointer Child : *node) { + if (Child->getKind() != Node::Kind::GenericSpecializationParam && + Child->getKind() != Node::Kind::DroppedArgument) { RETURN_IF_ERROR(mangle(Child, depth + 1)); + } } return ManglingError::Success; @@ -1717,30 +1742,30 @@ Remangler::mangleGenericSpecializationNode(Node *node, const char *operatorStr, ManglingError Remangler::mangleGenericSpecialization(Node *node, unsigned depth) { - return mangleGenericSpecializationNode(node, "Tg", depth + 1); + return mangleGenericSpecializationNode(node, 'g', depth + 1); } ManglingError Remangler::mangleGenericSpecializationPrespecialized(Node *node, unsigned depth) { - return mangleGenericSpecializationNode(node, "Ts", depth + 1); + return mangleGenericSpecializationNode(node, 's', depth + 1); } ManglingError Remangler::mangleGenericSpecializationNotReAbstracted(Node *node, unsigned depth) { - return mangleGenericSpecializationNode(node, "TG", depth + 1); + return mangleGenericSpecializationNode(node, 'G', depth + 1); } ManglingError Remangler::mangleGenericSpecializationInResilienceDomain(Node *node, unsigned depth) { - return mangleGenericSpecializationNode(node, "TB", depth + 1); + return mangleGenericSpecializationNode(node, 'B', depth + 1); } ManglingError Remangler::mangleInlinedGenericFunction(Node *node, unsigned depth) { - return mangleGenericSpecializationNode(node, "Ti", depth + 1); + return mangleGenericSpecializationNode(node, 'i', depth + 1); } ManglingError Remangler::mangleGenericSpecializationParam(Node *node, @@ -1966,13 +1991,19 @@ ManglingError Remangler::mangleImplPatternSubstitutions(Node *node, return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); } +ManglingError Remangler::mangleImplCoroutineKind(Node *node, + unsigned depth) { + // handled inline + return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); +} + ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) { const char *PseudoGeneric = ""; Node *GenSig = nullptr; Node *PatternSubs = nullptr; Node *InvocationSubs = nullptr; for (NodePointer Child : *node) { - switch (auto kind = Child->getKind()) { + switch (Child->getKind()) { case Node::Kind::ImplParameter: case Node::Kind::ImplResult: case Node::Kind::ImplYield: @@ -2064,13 +2095,25 @@ ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) { RETURN_IF_ERROR(mangleImplFunctionConvention(Child, depth + 1)); break; } + case Node::Kind::ImplCoroutineKind: { + char CoroAttr = llvm::StringSwitch(Child->getText()) + .Case("yield_once", 'A') + .Case("yield_once_2", 'I') + .Case("yield_many", 'G') + .Default(0); + + if (!CoroAttr) { + return MANGLING_ERROR(ManglingError::InvalidImplCoroutineKind, + Child); + } + Buffer << CoroAttr; + break; + } case Node::Kind::ImplFunctionAttribute: { char FuncAttr = llvm::StringSwitch(Child->getText()) - .Case("@yield_once", 'A') - .Case("@yield_many", 'G') - .Case("@Sendable", 'h') - .Case("@async", 'H') - .Default(0); + .Case("@Sendable", 'h') + .Case("@async", 'H') + .Default(0); if (!FuncAttr) { return MANGLING_ERROR(ManglingError::InvalidImplFunctionAttribute, Child); @@ -2089,6 +2132,7 @@ ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) { .Case("@inout", 'l') .Case("@inout_aliasable", 'b') .Case("@in_guaranteed", 'n') + .Case("@in_cxx", 'X') .Case("@in_constant", 'c') .Case("@owned", 'x') .Case("@guaranteed", 'g') @@ -2222,19 +2266,6 @@ ManglingError Remangler::mangleNoDerivative(Node *node, unsigned depth) { return ManglingError::Success; } -ManglingError Remangler::mangleParamLifetimeDependence(Node *node, - unsigned depth) { - RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); - Buffer << "Yl" << (char)node->getFirstChild()->getIndex(); - return ManglingError::Success; -} - -ManglingError Remangler::mangleSelfLifetimeDependence(Node *node, - unsigned depth) { - Buffer << "YL" << (char)node->getIndex(); - return ManglingError::Success; -} - ManglingError Remangler::mangleInfixOperator(Node *node, unsigned depth) { mangleIdentifierImpl(node, /*isOperator*/ true); Buffer << "oi"; @@ -2328,6 +2359,10 @@ ManglingError Remangler::mangleModifyAccessor(Node *node, unsigned depth) { return mangleAbstractStorage(node->getFirstChild(), "M", depth + 1); } +ManglingError Remangler::mangleModify2Accessor(Node *node, unsigned depth) { + return mangleAbstractStorage(node->getFirstChild(), "x", depth + 1); +} + ManglingError Remangler::mangleModule(Node *node, unsigned depth) { auto text = node->getText(); if (text == STDLIB_NAME) { @@ -2980,6 +3015,10 @@ ManglingError Remangler::mangleReadAccessor(Node *node, unsigned depth) { return mangleAbstractStorage(node->getFirstChild(), "r", depth + 1); } +ManglingError Remangler::mangleRead2Accessor(Node *node, unsigned depth) { + return mangleAbstractStorage(node->getFirstChild(), "y", depth + 1); +} + ManglingError Remangler::mangleKeyPathThunkHelper(Node *node, StringRef op, unsigned depth) { for (NodePointer Child : *node) @@ -3052,8 +3091,11 @@ ManglingError Remangler::mangleAsyncRemoved(Node *node, unsigned depth) { return ManglingError::Success; } -ManglingError Remangler::mangleMetatypeParamsRemoved(Node *node, unsigned depth) { - Buffer << 'm'; +ManglingError Remangler::mangleDroppedArgument(Node *node, unsigned depth) { + Buffer << "t"; + int n = node->getIndex(); + if (n > 0) + Buffer << (n-1); return ManglingError::Success; } @@ -3338,6 +3380,22 @@ ManglingError Remangler::mangleCurryThunk(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleSILThunkIdentity(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // type + // TT is for a thunk that is for a thunk inst... I is for identity. + Buffer << "TT" + << "I"; + return ManglingError::Success; +} + +ManglingError Remangler::mangleSILThunkHopToMainActorIfNeeded(Node *node, + unsigned depth) { + RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // type + Buffer << "TT" + << "H"; + return ManglingError::Success; +} + ManglingError Remangler::mangleDispatchThunk(Node *node, unsigned depth) { RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); Buffer << "Tj"; @@ -3936,6 +3994,32 @@ mangleNonUniqueExtendedExistentialTypeShapeSymbolicReference(Node *node, // We don't support absolute references in the mangling of these return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node); } + +ManglingError Remangler::mangleInteger(Node *node, unsigned int depth) { + Buffer << "$"; + mangleIndex(node->getIndex()); + + return ManglingError::Success; +} + +ManglingError Remangler::mangleNegativeInteger(Node *node, unsigned int depth) { + Buffer << "$n"; + mangleIndex(-node->getIndex()); + + return ManglingError::Success; +} + +ManglingError Remangler::mangleDependentGenericParamValueMarker(Node *node, + unsigned depth) { + DEMANGLER_ASSERT(node->getNumChildren() == 2, node); + DEMANGLER_ASSERT(node->getChild(0)->getChild(0)->getKind() == Node::Kind::DependentGenericParamType, node); + DEMANGLER_ASSERT(node->getChild(1)->getKind() == Node::Kind::Type, node); + RETURN_IF_ERROR(mangleType(node->getChild(1), depth + 1)); + Buffer << "RV"; + mangleDependentGenericParamIndex(node->getChild(0)->getChild(0)); + return ManglingError::Success; +} + } // anonymous namespace /// The top-level interface to the remangler.