Files
swift-mirror/lib/Demangling/Remangler.cpp
Slava Pestov 7ed5d2bfc2 ASTDemangler: Round-trip @isolated @sil_implicit_leading_param parameter attributes
We sometimes mangle SILFunctionTypes when generating debug info
for reabstraction thunks, and these can have various exotic
parameter and result attributes. Two recent additions were
never plumbed through the mangler, causing assertion failures
when emitting debug info.

Fixes rdar://153730847.
2025-06-26 15:00:44 -04:00

4328 lines
147 KiB
C++

//===--- Remangler.cpp - Swift re-mangling from a demangling tree ---------===//
//
// 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/ManglingMacros.h"
#include "swift/Demangling/ManglingUtils.h"
#include "swift/Demangling/Punycode.h"
#include "swift/Strings.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include <cstdio>
#include <cstdlib>
using namespace swift;
using namespace Demangle;
using namespace Mangle;
static char getCharOfNodeText(Node *node, unsigned idx) {
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
return Mangle::translateOperatorChar(node->getText()[idx]);
default:
return node->getText()[idx];
}
}
bool SubstitutionEntry::identifierEquals(Node *lhs, Node *rhs) {
unsigned length = lhs->getText().size();
if (rhs->getText().size() != length)
return false;
// The fast path.
if (lhs->getKind() == rhs->getKind())
return lhs->getText() == rhs->getText();
// The slow path.
for (unsigned i = 0; i < length; ++i) {
if (getCharOfNodeText(lhs, i) != getCharOfNodeText(rhs, i))
return false;
}
return true;
}
bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const {
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;
}
static inline size_t combineHash(size_t currentHash, size_t newValue) {
return 33 * currentHash + newValue;
}
/// Calculate the hash for a node.
size_t RemanglerBase::hashForNode(Node *node,
bool treatAsIdentifier) {
size_t hash = 0;
if (treatAsIdentifier) {
hash = combineHash(hash, (size_t)Node::Kind::Identifier);
assert(node->hasText());
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
for (char c : node->getText()) {
hash = combineHash(hash, (unsigned char)translateOperatorChar(c));
}
return hash;
default:
break;
}
} else {
hash = combineHash(hash, (size_t) node->getKind());
}
if (node->hasIndex()) {
hash = combineHash(hash, node->getIndex());
} else if (node->hasText()) {
for (char c : node->getText()) {
hash = combineHash(hash, (unsigned char) c);
}
}
for (Node *child : *node) {
SubstitutionEntry entry = entryForNode(child, treatAsIdentifier);
hash = combineHash(hash, entry.hash());
}
return hash;
}
/// Rotate a size_t by N bits
static inline size_t rotate(size_t value, size_t shift) {
const size_t bits = sizeof(size_t) * 8;
return (value >> shift) | (value << (bits - shift));
}
/// Compute a hash value from a node *pointer*.
/// Used for look-ups in HashHash. The numbers in here were determined
/// experimentally.
static inline size_t nodeHash(Node *node) {
// Multiply by a magic number
const size_t nodePrime = ((size_t)node) * 2043;
// We rotate by a different amount because the alignment of Node
// changes depending on the machine's pointer size
switch (sizeof(size_t)) {
case 4:
return rotate(nodePrime, 11);
case 8:
return rotate(nodePrime, 12);
case 16:
return rotate(nodePrime, 13);
default:
return rotate(nodePrime, 12);
}
}
/// Construct a SubstitutionEntry for a given node.
/// This will look in the HashHash to see if we already know the hash
/// (which avoids recursive hashing on the Node tree).
SubstitutionEntry RemanglerBase::entryForNode(Node *node,
bool treatAsIdentifier) {
const size_t ident = treatAsIdentifier ? 4 : 0;
const size_t hash = nodeHash(node) + ident;
// Use linear probing with a limit
for (size_t n = 0; n < HashHashMaxProbes; ++n) {
const size_t ndx = (hash + n) & (HashHashCapacity - 1);
SubstitutionEntry entry = HashHash[ndx];
if (entry.isEmpty()) {
size_t entryHash = hashForNode(node, treatAsIdentifier);
entry.setNode(node, treatAsIdentifier, entryHash);
HashHash[ndx] = entry;
return entry;
} else if (entry.matches(node, treatAsIdentifier)) {
return entry;
}
}
// Hash table is full at this hash value
SubstitutionEntry entry;
size_t entryHash = hashForNode(node, treatAsIdentifier);
entry.setNode(node, treatAsIdentifier, entryHash);
return entry;
}
// Find a substitution and return its index.
// Returns -1 if no substitution is found.
int RemanglerBase::findSubstitution(const SubstitutionEntry &entry) {
// First search in InlineSubstitutions.
SubstitutionEntry *result
= std::find(InlineSubstitutions, InlineSubstitutions + NumInlineSubsts,
entry);
if (result != InlineSubstitutions + NumInlineSubsts)
return result - InlineSubstitutions;
// Then search in OverflowSubstitutions.
auto it = OverflowSubstitutions.find(entry);
if (it == OverflowSubstitutions.end())
return -1;
return it->second;
}
void RemanglerBase::addSubstitution(const SubstitutionEntry &entry) {
assert(findSubstitution(entry) < 0);
if (NumInlineSubsts < InlineSubstCapacity) {
// There is still free space in NumInlineSubsts.
assert(OverflowSubstitutions.empty());
InlineSubstitutions[NumInlineSubsts++] = entry;
return;
}
// We have to add the entry to OverflowSubstitutions.
unsigned Idx = OverflowSubstitutions.size() + InlineSubstCapacity;
auto result = OverflowSubstitutions.insert({entry, Idx});
assert(result.second);
(void) result;
}
namespace {
class Remangler : public RemanglerBase {
template <typename Mangler>
friend void Mangle::mangleIdentifier(Mangler &M, StringRef ident);
friend class Mangle::SubstitutionMerging;
const ManglingFlavor Flavor = ManglingFlavor::Default;
const bool UsePunycode = true;
Vector<SubstitutionWord> Words;
Vector<WordReplacement> SubstWordsInIdent;
static const size_t MaxNumWords = 26;
static const unsigned MaxDepth = 1024;
SubstitutionMerging SubstMerging;
// A callback for resolving symbolic references.
SymbolicResolver Resolver;
void addSubstWordsInIdent(const WordReplacement &repl) {
SubstWordsInIdent.push_back(repl, Factory);
}
void addWord(const SubstitutionWord &word) {
Words.push_back(word, Factory);
}
template <typename Mangler>
friend void mangleIdentifier(Mangler &M, StringRef ident);
class EntityContext {
bool AsContext = false;
public:
class ManglingContextRAII {
EntityContext &Ctx;
bool SavedValue;
public:
ManglingContextRAII(EntityContext &ctx)
: Ctx(ctx), SavedValue(ctx.AsContext) {
ctx.AsContext = true;
}
~ManglingContextRAII() {
Ctx.AsContext = SavedValue;
}
};
};
// ###TODO: Consider fixing some of these asserts() to return errors somehow
Node *getSingleChild(Node *node) {
assert(node->getNumChildren() == 1);
return node->getFirstChild();
}
Node *getSingleChild(Node *node, Node::Kind kind) {
Node *Child = getSingleChild(node);
assert(Child->getKind() == kind);
return Child;
}
Node *skipType(Node *node) {
if (node->getKind() == Node::Kind::Type)
return getSingleChild(node);
return node;
}
Node *getChildOfType(Node *node) {
assert(node->getKind() == Node::Kind::Type);
return getSingleChild(node);
}
// Cannot fail
void mangleIndex(Node::IndexType value) {
if (value == 0) {
Buffer << '_';
} else {
Buffer << (value - 1) << '_';
}
}
ManglingError mangleDependentConformanceIndex(Node *node, unsigned depth);
ManglingError mangleChildNodes(Node *node, unsigned depth) {
return mangleNodes(node->begin(), node->end(), depth);
}
ManglingError mangleChildNodesReversed(Node *node, unsigned depth) {
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
RETURN_IF_ERROR(mangleChildNode(node, Num - Idx - 1, depth));
}
return ManglingError::Success;
}
void mangleListSeparator(bool &isFirstListItem) {
if (isFirstListItem) {
Buffer << '_';
isFirstListItem = false;
}
}
void mangleEndOfList(bool isFirstListItem) {
if (isFirstListItem)
Buffer << 'y';
}
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) {
if (index < node->getNumChildren())
return mangle(node->begin()[index], depth);
return ManglingError::Success;
}
ManglingError manglePureProtocol(Node *Proto, unsigned depth) {
Proto = skipType(Proto);
if (mangleStandardSubstitution(Proto))
return ManglingError::Success;
return mangleChildNodes(Proto, depth);
}
ManglingError mangleProtocolList(Node *protocols, Node *superclass,
bool hasExplicitAnyObject, unsigned depth);
bool trySubstitution(Node *node, SubstitutionEntry &entry,
bool treatAsIdentifier = false);
void mangleIdentifierImpl(Node *node, bool isOperator);
bool mangleStandardSubstitution(Node *node);
// Cannot fail
void mangleDependentGenericParamIndex(Node *node,
const char *nonZeroPrefix = "",
char zeroOp = 'z');
ManglingErrorOr<std::pair<int, Node *>> mangleConstrainedType(Node *node,
unsigned depth);
ManglingError mangleFunctionSignature(Node *FuncType, unsigned depth) {
return mangleChildNodesReversed(FuncType, depth);
}
ManglingError mangleGenericSpecializationNode(Node *node,
char specKind,
unsigned depth);
ManglingError mangleAnyNominalType(Node *node, unsigned depth);
ManglingError mangleAnyGenericType(Node *node, StringRef TypeOp,
unsigned depth);
ManglingError mangleGenericArgs(Node *node, char &Separator, unsigned depth,
bool fullSubstitutionMap = false);
ManglingError mangleAnyConstructor(Node *node, char kindOp, unsigned depth);
ManglingError mangleAbstractStorage(Node *node, StringRef accessorCode,
unsigned depth);
ManglingError mangleAnyProtocolConformance(Node *node, unsigned depth);
ManglingError mangleKeyPathThunkHelper(Node *node, StringRef op,
unsigned depth);
ManglingError mangleSILThunkIdentity(Node *node, StringRef op,
unsigned depth);
ManglingError mangleAutoDiffFunctionOrSimpleThunk(Node *node, StringRef op,
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, unsigned depth, EntityContext &ctx);
#include "swift/Demangling/DemangleNodes.def"
public:
Remangler(SymbolicResolver Resolver, NodeFactory &Factory,
ManglingFlavor Flavor)
: RemanglerBase(Factory), Flavor(Flavor), Resolver(Resolver) {}
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);
}
};
bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
bool treatAsIdentifier) {
if (mangleStandardSubstitution(node))
return true;
// Go ahead and initialize the substitution entry.
entry = entryForNode(node, treatAsIdentifier);
int Idx = findSubstitution(entry);
if (Idx < 0)
return false;
if (Idx >= 26) {
Buffer << 'A';
mangleIndex(Idx - 26);
return true;
}
char SubstChar = Idx + 'A';
StringRef Subst(&SubstChar, 1);
if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ false)) {
Buffer << 'A' << Subst;
}
return true;
}
void Remangler::mangleIdentifierImpl(Node *node, bool isOperator) {
SubstitutionEntry entry;
if (trySubstitution(node, entry, /*treatAsIdentifier*/ true)) return;
if (isOperator) {
Mangle::mangleIdentifier(*this,
Mangle::translateOperator(node->getText()));
} else {
Mangle::mangleIdentifier(*this, node->getText());
}
addSubstitution(entry);
}
bool Remangler::mangleStandardSubstitution(Node *node) {
if (node->getKind() != Node::Kind::Structure
&& node->getKind() != Node::Kind::Class
&& node->getKind() != Node::Kind::Enum
&& node->getKind() != Node::Kind::Protocol)
return false;
Node *context = node->getFirstChild();
if (context->getKind() != Node::Kind::Module
|| context->getText() != STDLIB_NAME)
return false;
// Ignore private stdlib names
if (node->getChild(1)->getKind() != Node::Kind::Identifier)
return false;
if (auto Subst = getStandardTypeSubst(
node->getChild(1)->getText(), /*allowConcurrencyManglings=*/true)) {
if (!SubstMerging.tryMergeSubst(*this, *Subst, /*isStandardSubst*/ true)) {
Buffer << 'S' << *Subst;
}
return true;
}
return false;
}
void Remangler::mangleDependentGenericParamIndex(Node *node,
const char *nonZeroPrefix,
char zeroOp) {
if (node->getKind() == Node::Kind::ConstrainedExistentialSelf) {
Buffer << 's';
return;
}
auto paramDepth = node->getChild(0)->getIndex();
auto index = node->getChild(1)->getIndex();
if (paramDepth != 0) {
Buffer << nonZeroPrefix << 'd';
mangleIndex(paramDepth - 1);
mangleIndex(index);
return;
}
if (index != 0) {
Buffer << nonZeroPrefix;
mangleIndex(index - 1);
return;
}
// depth == index == 0
Buffer << zeroOp;
}
ManglingErrorOr<std::pair<int, Node *>>
Remangler::mangleConstrainedType(Node *node, unsigned depth) {
if (node->getKind() == Node::Kind::Type)
node = getChildOfType(node);
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return std::pair<int, Node *>{-1, nullptr};
Vector<Node *> Chain;
while (node->getKind() == Node::Kind::DependentMemberType) {
Chain.push_back(node->getChild(1), Factory);
node = getChildOfType(node->getFirstChild());
}
if (node->getKind() != Node::Kind::DependentGenericParamType &&
node->getKind() != Node::Kind::ConstrainedExistentialSelf) {
RETURN_IF_ERROR(mangle(node, depth + 1));
if (!Chain.size())
return std::pair<int, Node *>{-1, nullptr};
node = nullptr;
}
const char *ListSeparator = (Chain.size() > 1 ? "_" : "");
for (unsigned i = 1, n = Chain.size(); i <= n; ++i) {
Node *DepAssocTyRef = Chain[n - i];
RETURN_IF_ERROR(mangle(DepAssocTyRef, depth + 1));
Buffer << ListSeparator;
ListSeparator = "";
}
if (!Chain.empty())
addSubstitution(entry);
return std::pair<int, Node *>{(int)Chain.size(), node};
}
ManglingError Remangler::mangleAnyGenericType(Node *node, StringRef TypeOp,
unsigned depth) {
SubstitutionEntry entry;
if (!trySubstitution(node, entry)) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << TypeOp;
addSubstitution(entry);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleAnyNominalType(Node *node, unsigned depth) {
if (depth > Remangler::MaxDepth) {
return MANGLING_ERROR(ManglingError::TooComplex, node);
}
if (isSpecialized(node)) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return ManglingError::Success;
auto unspec = getUnspecialized(node, Factory);
if (!unspec.isSuccess())
return unspec.error();
NodePointer unboundType = unspec.result();
RETURN_IF_ERROR(mangleAnyNominalType(unboundType, depth + 1));
char Separator = 'y';
RETURN_IF_ERROR(mangleGenericArgs(node, Separator, depth + 1));
if (node->getNumChildren() == 3) {
// Retroactive conformances.
auto listNode = node->getChild(2);
for (size_t Idx = 0, Num = listNode->getNumChildren(); Idx < Num; ++Idx) {
RETURN_IF_ERROR(mangle(listNode->getChild(Idx), depth + 1));
}
}
Buffer << 'G';
addSubstitution(entry);
return ManglingError::Success;
}
switch (node->getKind()) {
case Node::Kind::Structure:
return mangleAnyGenericType(node, "V", depth);
case Node::Kind::Enum:
return mangleAnyGenericType(node, "O", depth);
case Node::Kind::Class:
return mangleAnyGenericType(node, "C", depth);
case Node::Kind::OtherNominalType:
return mangleAnyGenericType(node, "XY", depth);
case Node::Kind::TypeAlias:
return mangleAnyGenericType(node, "a", depth);
case Node::Kind::TypeSymbolicReference:
return mangleTypeSymbolicReference(node, depth);
default:
return MANGLING_ERROR(ManglingError::BadNominalTypeKind, node);
}
}
ManglingError Remangler::mangleGenericArgs(Node *node, char &Separator,
unsigned depth,
bool fullSubstitutionMap) {
switch (node->getKind()) {
case Node::Kind::Protocol:
// A protocol cannot be the parent of a nominal type, so this case should
// never be hit by valid swift code. But the indexer might generate a URL
// from invalid swift code, which has a bound generic inside a protocol.
// The ASTMangler treats a protocol like any other nominal type in this
// case, so we also support it in the remangler.
case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Class:
case Node::Kind::TypeAlias:
if (node->getKind() == Node::Kind::TypeAlias)
fullSubstitutionMap = true;
RETURN_IF_ERROR(mangleGenericArgs(node->getChild(0), Separator, depth + 1,
fullSubstitutionMap));
Buffer << Separator;
Separator = '_';
break;
case Node::Kind::Function:
case Node::Kind::Getter:
case Node::Kind::Setter:
case Node::Kind::WillSet:
case Node::Kind::DidSet:
case Node::Kind::ReadAccessor:
case Node::Kind::ModifyAccessor:
case Node::Kind::UnsafeAddressor:
case Node::Kind::UnsafeMutableAddressor:
case Node::Kind::Allocator:
case Node::Kind::Constructor:
case Node::Kind::Destructor:
case Node::Kind::Variable:
case Node::Kind::Subscript:
case Node::Kind::ExplicitClosure:
case Node::Kind::ImplicitClosure:
case Node::Kind::DefaultArgumentInitializer:
case Node::Kind::Initializer:
case Node::Kind::PropertyWrapperBackingInitializer:
case Node::Kind::PropertyWrapperInitFromProjectedValue:
case Node::Kind::Static:
if (!fullSubstitutionMap)
break;
RETURN_IF_ERROR(mangleGenericArgs(node->getChild(0), Separator, depth + 1,
fullSubstitutionMap));
if (Demangle::nodeConsumesGenericArgs(node)) {
Buffer << Separator;
Separator = '_';
}
break;
case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericProtocol:
case Node::Kind::BoundGenericTypeAlias: {
if (node->getKind() == Node::Kind::BoundGenericTypeAlias)
fullSubstitutionMap = true;
NodePointer unboundType = node->getChild(0);
DEMANGLER_ASSERT(unboundType->getKind() == Node::Kind::Type, node);
NodePointer nominalType = unboundType->getChild(0);
if (nominalType->getKind() == Node::Kind::TypeSymbolicReference) {
NodePointer resolvedUnboundType = Resolver(SymbolicReferenceKind::Context, (const void *)nominalType->getIndex());
nominalType = resolvedUnboundType->getChild(0);
}
NodePointer parentOrModule = nominalType->getChild(0);
RETURN_IF_ERROR(mangleGenericArgs(parentOrModule, Separator, depth + 1,
fullSubstitutionMap));
Buffer << Separator;
Separator = '_';
RETURN_IF_ERROR(mangleChildNodes(node->getChild(1), depth + 1));
break;
}
case Node::Kind::ConstrainedExistential: {
Buffer << Separator;
Separator = '_';
RETURN_IF_ERROR(mangleChildNodes(node->getChild(1), depth + 1));
break;
}
case Node::Kind::BoundGenericFunction: {
fullSubstitutionMap = true;
NodePointer unboundFunction = node->getChild(0);
DEMANGLER_ASSERT(unboundFunction->getKind() == Node::Kind::Function ||
unboundFunction->getKind() ==
Node::Kind::Constructor,
node);
NodePointer parentOrModule = unboundFunction->getChild(0);
RETURN_IF_ERROR(mangleGenericArgs(parentOrModule, Separator, depth + 1,
fullSubstitutionMap));
Buffer << Separator;
Separator = '_';
RETURN_IF_ERROR(mangleChildNodes(node->getChild(1), depth + 1));
break;
}
case Node::Kind::Extension:
RETURN_IF_ERROR(mangleGenericArgs(node->getChild(1), Separator, depth + 1,
fullSubstitutionMap));
break;
default:
break;
}
return ManglingError::Success;
}
ManglingError Remangler::mangleAbstractStorage(Node *node,
StringRef accessorCode,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
switch (node->getKind()) {
case Node::Kind::Subscript: Buffer << "i"; break;
case Node::Kind::Variable: Buffer << "v"; break;
default:
return MANGLING_ERROR(ManglingError::NotAStorageNode, node);
}
Buffer << accessorCode;
return ManglingError::Success;
}
ManglingError Remangler::mangleAllocator(Node *node, unsigned depth) {
return mangleAnyConstructor(node, 'C', depth + 1);
}
ManglingError Remangler::mangleArgumentTuple(Node *node, unsigned depth) {
Node *Child = skipType(node->getChild(0));
if (Child->getKind() == Node::Kind::Tuple &&
Child->getNumChildren() == 0) {
Buffer << 'y';
return ManglingError::Success;
}
return mangle(Child, depth + 1);
}
ManglingError Remangler::mangleAssociatedType(Node *node, unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleAssociatedTypeRef(Node *node, unsigned depth) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return ManglingError::Success;
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Qa";
addSubstitution(entry);
return ManglingError::Success;
}
ManglingError Remangler::mangleAssociatedTypeDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Tl";
return ManglingError::Success;
}
ManglingError Remangler::mangleAssociatedConformanceDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangle(node->getChild(1), depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(2), depth + 1));
Buffer << "Tn";
return ManglingError::Success;
}
ManglingError
Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangle(node->getChild(1), depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(2), depth + 1));
Buffer << "TN";
return ManglingError::Success;
}
ManglingError Remangler::mangleBaseConformanceDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(1), depth + 1));
Buffer << "Tb";
return ManglingError::Success;
}
ManglingError Remangler::mangleAssociatedTypeMetadataAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodes(node, depth + 1)); // protocol conformance, identifier
Buffer << "Wt";
return ManglingError::Success;
}
ManglingError
Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodes(node, depth + 1)); // protocol conformance, identifier
Buffer << "TM";
return ManglingError::Success;
}
ManglingError
Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(
node, depth + 1)); // protocol conformance, type, protocol
Buffer << "WT";
return ManglingError::Success;
}
ManglingError Remangler::mangleBaseWitnessTableAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodes(node, depth + 1)); // protocol conformance, protocol
Buffer << "Wb";
return ManglingError::Success;
}
ManglingError Remangler::mangleAutoClosureType(Node *node, unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodesReversed(node, depth + 1)); // argument tuple, result type
Buffer << "XK";
return ManglingError::Success;
}
ManglingError Remangler::mangleEscapingAutoClosureType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodesReversed(node, depth + 1)); // argument tuple, result type
Buffer << "XA";
return ManglingError::Success;
}
ManglingError Remangler::mangleNoEscapeFunctionType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodesReversed(node, depth + 1)); // argument tuple, result type
Buffer << "XE";
return ManglingError::Success;
}
ManglingError Remangler::mangleBoundGenericClass(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericEnum(Node *node, unsigned depth) {
Node *Enum = node->getChild(0)->getChild(0);
DEMANGLER_ASSERT(Enum->getKind() == Node::Kind::Enum, node);
Node *Mod = Enum->getChild(0);
Node *Id = Enum->getChild(1);
if (Mod->getKind() == Node::Kind::Module && Mod->getText() == STDLIB_NAME &&
Id->getKind() == Node::Kind::Identifier && Id->getText() == "Optional") {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return ManglingError::Success;
RETURN_IF_ERROR(mangleSingleChildNode(node->getChild(1), depth + 1));
Buffer << "Sg";
addSubstitution(entry);
return ManglingError::Success;
}
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericStructure(Node *node,
unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericOtherNominalType(Node *node,
unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericProtocol(Node *node,
unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericTypeAlias(Node *node,
unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleBoundGenericFunction(Node *node,
unsigned depth) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return ManglingError::Success;
auto unspec = getUnspecialized(node, Factory);
if (!unspec.isSuccess())
return unspec.error();
NodePointer unboundFunction = unspec.result();
RETURN_IF_ERROR(mangleFunction(unboundFunction, depth + 1));
char Separator = 'y';
RETURN_IF_ERROR(mangleGenericArgs(node, Separator, depth + 1));
Buffer << 'G';
addSubstitution(entry);
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();
if (text == BUILTIN_TYPE_NAME_BRIDGEOBJECT) {
Buffer << 'b';
} else if (text == BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER) {
Buffer << 'B';
} else if (text == BUILTIN_TYPE_NAME_UNKNOWNOBJECT) {
Buffer << 'O';
} else if (text == BUILTIN_TYPE_NAME_NATIVEOBJECT) {
Buffer << 'o';
} else if (text == BUILTIN_TYPE_NAME_RAWPOINTER) {
Buffer << 'p';
} else if (text == BUILTIN_TYPE_NAME_RAWUNSAFECONTINUATION) {
Buffer << 'c';
} else if (text == BUILTIN_TYPE_NAME_JOB) {
Buffer << 'j';
} else if (text == BUILTIN_TYPE_NAME_DEFAULTACTORSTORAGE) {
Buffer << 'D';
} else if (text == BUILTIN_TYPE_NAME_NONDEFAULTDISTRIBUTEDACTORSTORAGE) {
Buffer << 'd';
} else if (text == BUILTIN_TYPE_NAME_EXECUTOR) {
Buffer << 'e';
} else if (text == BUILTIN_TYPE_NAME_SILTOKEN) {
Buffer << 't';
} else if (text == BUILTIN_TYPE_NAME_INTLITERAL) {
Buffer << 'I';
} else if (text == BUILTIN_TYPE_NAME_WORD) {
Buffer << 'w';
} else if (text == BUILTIN_TYPE_NAME_PACKINDEX) {
Buffer << 'P';
} else if (text.consume_front(BUILTIN_TYPE_NAME_INT)) {
Buffer << 'i' << text << '_';
} else if (text.consume_front(BUILTIN_TYPE_NAME_FLOAT)) {
Buffer << 'f' << text << '_';
} else if (text.consume_front(BUILTIN_TYPE_NAME_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');
auto element = text.substr(splitIdx).substr(1);
if (element == "RawPointer") {
Buffer << 'p';
} else if (element.consume_front("FPIEEE")) {
Buffer << 'f' << element << '_';
} else if (element.consume_front("Int")) {
Buffer << 'i' << element << '_';
} else {
return MANGLING_ERROR(ManglingError::UnexpectedBuiltinVectorType, node);
}
Buffer << "Bv" << text.substr(0, splitIdx) << '_';
} else {
return MANGLING_ERROR(ManglingError::UnexpectedBuiltinType, node);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleBuiltinTupleType(Node *node, unsigned depth) {
Buffer << "BT";
return ManglingError::Success;
}
ManglingError Remangler::mangleCFunctionPointer(Node *node, unsigned depth) {
if (node->getNumChildren() > 0 &&
node->getFirstChild()->getKind() == Node::Kind::ClangType) {
for (size_t Idx = node->getNumChildren() - 1; Idx >= 1; --Idx) {
RETURN_IF_ERROR(mangleChildNode(node, Idx, depth + 1));
}
Buffer << "XzC";
return mangleClangType(node->getFirstChild(), depth + 1);
}
RETURN_IF_ERROR(
mangleChildNodesReversed(node, depth + 1)); // argument tuple, result type
Buffer << "XC";
return ManglingError::Success;
}
ManglingError Remangler::mangleClass(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleAnyConstructor(Node *node, char kindOp,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "f" << kindOp;
return ManglingError::Success;
}
ManglingError Remangler::mangleConstructor(Node *node, unsigned depth) {
return mangleAnyConstructor(node, 'c', depth);
}
ManglingError Remangler::mangleCoroutineContinuationPrototype(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "TC";
return ManglingError::Success;
}
ManglingError
Remangler::manglePredefinedObjCAsyncCompletionHandlerImpl(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "TZ";
return ManglingError::Success;
}
ManglingError Remangler::mangleObjCAsyncCompletionHandlerImpl(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
if (node->getNumChildren() == 4)
RETURN_IF_ERROR(mangleChildNode(node, 3, depth + 1));
Buffer << "Tz";
return mangleChildNode(node, 2, depth + 1);
}
ManglingError Remangler::mangleDeallocator(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fD";
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);
}
ManglingError Remangler::mangleDefaultArgumentInitializer(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
Buffer << "fA";
return mangleChildNode(node, 1, depth + 1);
}
ManglingError Remangler::mangleAsyncFunctionPointer(Node *node,
unsigned depth) {
Buffer << "Tu";
return ManglingError::Success;
}
ManglingError Remangler::mangleCoroFunctionPointer(Node *node, unsigned depth) {
Buffer << "Twc";
return ManglingError::Success;
}
ManglingError Remangler::mangleDefaultOverride(Node *node, unsigned depth) {
Buffer << "Twd";
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentAssociatedTypeRef(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleIdentifier(node->getFirstChild(), depth));
if (node->getNumChildren() > 1)
return mangleChildNode(node, 1, depth + 1);
return ManglingError::Success;
}
ManglingError
Remangler::mangleDependentGenericConformanceRequirement(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getNumChildren() == 2, node);
Node *ProtoOrClass = node->getChild(1);
DEMANGLER_ASSERT(ProtoOrClass->hasChildren(), ProtoOrClass);
if (ProtoOrClass->getFirstChild()->getKind() == Node::Kind::Protocol) {
RETURN_IF_ERROR(manglePureProtocol(ProtoOrClass, depth + 1));
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case -1:
Buffer << "RQ";
return ManglingError::Success; // substitution
case 0:
Buffer << "R";
break;
case 1:
Buffer << "Rp";
break;
default:
Buffer << "RP";
break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return ManglingError::Success;
}
RETURN_IF_ERROR(mangle(ProtoOrClass, depth + 1));
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case -1:
Buffer << "RB";
return ManglingError::Success; // substitution
case 0:
Buffer << "Rb";
break;
case 1:
Buffer << "Rc";
break;
default:
Buffer << "RC";
break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentGenericInverseConformanceRequirement(
Node *node, unsigned depth) {
DEMANGLER_ASSERT(node->getNumChildren() == 2, node);
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess()) {
return Mangling.error();
}
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case -1:
Buffer << "RI";
mangleIndex(node->getChild(1)->getIndex());
return ManglingError::Success; // substitution
case 0:
Buffer << "Ri";
break;
case 1:
Buffer << "Rj";
break;
default:
Buffer << "RJ";
break;
}
mangleIndex(node->getChild(1)->getIndex());
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentGenericParamCount(Node *node,
unsigned depth) {
// handled inline in DependentGenericSignature
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
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';
mangleDependentGenericParamIndex(node);
return ManglingError::Success;
}
ManglingError
Remangler::mangleDependentGenericSameTypeRequirement(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case -1:
Buffer << "RS";
return ManglingError::Success; // substitution
case 0:
Buffer << "Rs";
break;
case 1:
Buffer << "Rt";
break;
default:
Buffer << "RT";
break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return ManglingError::Success;
}
ManglingError
Remangler::mangleDependentGenericSameShapeRequirement(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case 0:
Buffer << "Rh";
break;
default:
assert(false && "Invalid same-shape requirement");
return ManglingError::AssertionFailed;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return ManglingError::Success;
}
ManglingError
Remangler::mangleDependentGenericLayoutRequirement(Node *node, unsigned depth) {
auto Mangling = mangleConstrainedType(node->getChild(0), depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
DEMANGLER_ASSERT(
NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second, node);
switch (NumMembersAndParamIdx.first) {
case -1: Buffer << "RL"; break; // substitution
case 0: Buffer << "Rl"; break;
case 1: Buffer << "Rm"; break;
default: Buffer << "RM"; break;
}
// If not a substitution, mangle the dependent generic param index.
if (NumMembersAndParamIdx.first != -1)
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
DEMANGLER_ASSERT(node->getChild(1)->getKind() == Node::Kind::Identifier,
node);
DEMANGLER_ASSERT(node->getChild(1)->getText().size() == 1, node);
Buffer << node->getChild(1)->getText()[0];
if (node->getNumChildren() >= 3)
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
if (node->getNumChildren() >= 4)
RETURN_IF_ERROR(mangleChildNode(node, 3, depth + 1));
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentGenericSignature(Node *node,
unsigned depth) {
size_t ParamCountEnd = 0;
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
Node *Child = node->getChild(Idx);
if (Child->getKind() == Node::Kind::DependentGenericParamCount) {
ParamCountEnd = Idx + 1;
} else {
// requirement
RETURN_IF_ERROR(mangleChildNode(node, Idx, depth + 1));
}
}
// If there's only one generic param, mangle nothing.
if (ParamCountEnd == 1 && node->getChild(0)->getIndex() == 1) {
Buffer << 'l';
return ManglingError::Success;
}
// Remangle generic params.
Buffer << 'r';
for (size_t Idx = 0; Idx < ParamCountEnd; ++Idx) {
Node *Count = node->getChild(Idx);
if (Count->getIndex() > 0) {
mangleIndex(Count->getIndex() - 1);
} else {
Buffer << 'z';
}
}
Buffer << 'l';
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentGenericParamPackMarker(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getNumChildren() == 1, node);
DEMANGLER_ASSERT(node->getChild(0)->getKind() == Node::Kind::Type, node);
Buffer << "Rv";
mangleDependentGenericParamIndex(node->getChild(0)->getChild(0));
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentGenericType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleChildNodesReversed(node, depth + 1)); // type, generic signature
Buffer << 'u';
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentMemberType(Node *node, unsigned depth) {
auto Mangling = mangleConstrainedType(node, depth + 1);
if (!Mangling.isSuccess())
return Mangling.error();
auto NumMembersAndParamIdx = Mangling.result();
switch (NumMembersAndParamIdx.first) {
case -1:
break; // substitution
case 0:
return MANGLING_ERROR(ManglingError::WrongDependentMemberType, node);
case 1:
Buffer << 'Q';
if (auto dependentBase = NumMembersAndParamIdx.second) {
mangleDependentGenericParamIndex(dependentBase, "y", 'z');
} else {
Buffer << 'x';
}
break;
default:
Buffer << 'Q';
if (auto dependentBase = NumMembersAndParamIdx.second) {
mangleDependentGenericParamIndex(dependentBase, "Y", 'Z');
} else {
Buffer << 'X';
}
break;
}
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentPseudogenericSignature(Node *node,
unsigned depth) {
return mangleDependentGenericSignature(node, depth + 1);
}
ManglingError Remangler::mangleDestructor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fd";
return ManglingError::Success;
}
ManglingError Remangler::mangleDidSet(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "W", depth + 1);
}
ManglingError Remangler::mangleDirectness(Node *node, unsigned depth) {
switch (node->getIndex()) {
case unsigned(Directness::Direct):
Buffer << 'd';
break;
case unsigned(Directness::Indirect):
Buffer << 'i';
break;
default:
return MANGLING_ERROR(ManglingError::BadDirectness, node);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleDynamicAttribute(Node *node, unsigned depth) {
Buffer << "TD";
return ManglingError::Success;
}
ManglingError Remangler::mangleDirectMethodReferenceAttribute(Node *node,
unsigned depth) {
Buffer << "Td";
return ManglingError::Success;
}
ManglingError Remangler::mangleDynamicSelf(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // type
Buffer << "XD";
return ManglingError::Success;
}
ManglingError Remangler::mangleEnum(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleErrorType(Node *node, unsigned depth) {
Buffer << "Xe";
return ManglingError::Success;
}
ManglingError Remangler::mangleConstrainedExistential(Node *node,
unsigned int depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
Buffer << "XP";
return ManglingError::Success;
}
ManglingError
Remangler::mangleConstrainedExistentialRequirementList(Node *node,
unsigned int depth) {
assert(node->getNumChildren() > 0);
bool FirstElem = true;
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
RETURN_IF_ERROR(mangleChildNode(node, Idx, depth + 1));
mangleListSeparator(FirstElem);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleConstrainedExistentialSelf(Node *node,
unsigned int depth) {
Buffer << "s";
return ManglingError::Success;
}
ManglingError Remangler::mangleExistentialMetatype(Node *node, unsigned depth) {
if (node->getFirstChild()->getKind() == Node::Kind::MetatypeRepresentation) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
Buffer << "Xm";
return mangleChildNode(node, 0, depth + 1);
} else {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Xp";
}
return ManglingError::Success;
}
ManglingError Remangler::mangleExplicitClosure(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); // context
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1)); // type
Buffer << "fU";
return mangleChildNode(node, 1, depth + 1); // index
}
ManglingError Remangler::mangleExtension(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (node->getNumChildren() == 3)
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1)); // generic signature
Buffer << 'E';
return ManglingError::Success;
}
ManglingError Remangler::mangleAnonymousContext(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (node->getNumChildren() >= 3)
RETURN_IF_ERROR(mangleTypeList(node->getChild(2), depth + 1));
else
Buffer << 'y';
Buffer << "XZ";
return ManglingError::Success;
}
ManglingError Remangler::mangleFieldOffset(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // variable
Buffer << "Wv";
return mangleChildNode(node, 0, depth + 1); // directness
}
ManglingError Remangler::mangleEnumCase(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); // enum case
Buffer << "WC";
return ManglingError::Success;
}
ManglingError Remangler::mangleFullTypeMetadata(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mf";
return ManglingError::Success;
}
ManglingError Remangler::mangleFunction(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); // context
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // name
bool hasLabels = node->getChild(2)->getKind() == Node::Kind::LabelList;
Node *FuncType = getSingleChild(node->getChild(hasLabels ? 3 : 2));
if (hasLabels)
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1)); // parameter labels
if (FuncType->getKind() == Node::Kind::DependentGenericType) {
RETURN_IF_ERROR(mangleFunctionSignature(
getSingleChild(FuncType->getChild(1)), depth + 1));
RETURN_IF_ERROR(
mangleChildNode(FuncType, 0, depth + 1)); // generic signature
} else {
RETURN_IF_ERROR(mangleFunctionSignature(FuncType, depth + 1));
}
Buffer << "F";
return ManglingError::Success;
}
ManglingError Remangler::mangleFunctionSignatureSpecialization(Node *node,
unsigned depth) {
for (NodePointer Param : *node) {
if (Param->getKind() == Node::Kind::FunctionSignatureSpecializationParam &&
Param->getNumChildren() > 0) {
Node *KindNd = Param->getChild(0);
switch (FunctionSigSpecializationParamKind(KindNd->getIndex())) {
case FunctionSigSpecializationParamKind::ConstantPropFunction:
case FunctionSigSpecializationParamKind::ConstantPropGlobal:
RETURN_IF_ERROR(mangleIdentifier(Param->getChild(1), depth + 1));
break;
case FunctionSigSpecializationParamKind::ConstantPropString: {
NodePointer TextNd = Param->getChild(2);
StringRef Text = TextNd->getText();
if (!Text.empty() && (isDigit(Text[0]) || Text[0] == '_')) {
std::string Buffer = "_";
Buffer.append(Text.data(), Text.size());
TextNd = Factory.createNode(Node::Kind::Identifier, Buffer);
}
RETURN_IF_ERROR(mangleIdentifier(TextNd, depth + 1));
break;
}
case FunctionSigSpecializationParamKind::ClosureProp:
case FunctionSigSpecializationParamKind::ConstantPropKeyPath:
RETURN_IF_ERROR(mangleIdentifier(Param->getChild(1), depth + 1));
for (unsigned i = 2, e = Param->getNumChildren(); i != e; ++i) {
RETURN_IF_ERROR(mangleType(Param->getChild(i), depth + 1));
}
break;
default:
break;
}
}
}
Buffer << "Tf";
bool returnValMangled = false;
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::FunctionSignatureSpecializationReturn) {
Buffer << '_';
returnValMangled = true;
}
RETURN_IF_ERROR(mangle(Child, depth + 1));
if (Child->getKind() == Node::Kind::SpecializationPassID &&
node->hasIndex()) {
Buffer << node->getIndex();
}
}
if (!returnValMangled)
Buffer << "_n";
return ManglingError::Success;
}
ManglingError
Remangler::mangleFunctionSignatureSpecializationReturn(Node *node,
unsigned depth) {
return mangleFunctionSignatureSpecializationParam(node, depth + 1);
}
ManglingError
Remangler::mangleFunctionSignatureSpecializationParam(Node *node,
unsigned depth) {
if (!node->hasChildren()) {
Buffer << 'n';
return ManglingError::Success;
}
// The first child is always a kind that specifies the type of param that we
// have.
Node *KindNd = node->getChild(0);
unsigned kindValue = KindNd->getIndex();
auto kind = FunctionSigSpecializationParamKind(kindValue);
switch (kind) {
case FunctionSigSpecializationParamKind::ConstantPropFunction:
Buffer << "pf";
break;
case FunctionSigSpecializationParamKind::ConstantPropGlobal:
Buffer << "pg";
break;
case FunctionSigSpecializationParamKind::ConstantPropInteger:
Buffer << "pi" << node->getChild(1)->getText();
break;
case FunctionSigSpecializationParamKind::ConstantPropFloat:
Buffer << "pd" << node->getChild(1)->getText();
break;
case FunctionSigSpecializationParamKind::ConstantPropString: {
Buffer << "ps";
StringRef encodingStr = node->getChild(1)->getText();
if (encodingStr == "u8") {
Buffer << 'b';
} else if (encodingStr == "u16") {
Buffer << 'w';
} else if (encodingStr == "objc") {
Buffer << 'c';
} else {
return MANGLING_ERROR(ManglingError::UnknownEncoding, node);
}
break;
}
case FunctionSigSpecializationParamKind::ConstantPropKeyPath:
Buffer << "pk";
break;
case FunctionSigSpecializationParamKind::ClosureProp:
Buffer << 'c';
break;
case FunctionSigSpecializationParamKind::BoxToValue:
Buffer << 'i';
break;
case FunctionSigSpecializationParamKind::BoxToStack:
Buffer << 's';
break;
case FunctionSigSpecializationParamKind::InOutToOut:
Buffer << 'r';
break;
case FunctionSigSpecializationParamKind::SROA:
Buffer << 'x';
break;
default:
if (kindValue &
unsigned(
FunctionSigSpecializationParamKind::ExistentialToGeneric)) {
Buffer << 'e';
if (kindValue & unsigned(FunctionSigSpecializationParamKind::Dead))
Buffer << 'D';
if (kindValue &
unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed))
Buffer << 'G';
if (kindValue &
unsigned(FunctionSigSpecializationParamKind::GuaranteedToOwned))
Buffer << 'O';
} else if (kindValue &
unsigned(FunctionSigSpecializationParamKind::Dead)) {
Buffer << 'd';
if (kindValue &
unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed))
Buffer << 'G';
if (kindValue &
unsigned(FunctionSigSpecializationParamKind::GuaranteedToOwned))
Buffer << 'O';
} else if (kindValue &
unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed)) {
Buffer << 'g';
} else if (kindValue &
unsigned(
FunctionSigSpecializationParamKind::GuaranteedToOwned)) {
Buffer << 'o';
}
if (kindValue & unsigned(FunctionSigSpecializationParamKind::SROA))
Buffer << 'X';
break;
}
return ManglingError::Success;
}
ManglingError
Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError
Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleFunctionType(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleFunctionSignature(node, depth + 1));
Buffer << 'c';
return ManglingError::Success;
}
ManglingError Remangler::mangleGenericProtocolWitnessTable(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "WG";
return ManglingError::Success;
}
ManglingError Remangler::mangleGenericProtocolWitnessTableInstantiationFunction(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "WI";
return ManglingError::Success;
}
ManglingError Remangler::mangleResilientProtocolWitnessTable(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Wr";
return ManglingError::Success;
}
ManglingError Remangler::mangleGenericPartialSpecialization(Node *node,
unsigned depth) {
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::GenericSpecializationParam) {
RETURN_IF_ERROR(mangleChildNode(Child, 0, depth + 1));
break;
}
}
Buffer << (node->getKind() ==
Node::Kind::GenericPartialSpecializationNotReAbstracted ? "TP" : "Tp");
for (NodePointer Child : *node) {
if (Child->getKind() != Node::Kind::GenericSpecializationParam)
RETURN_IF_ERROR(mangle(Child, depth + 1));
}
return ManglingError::Success;
}
ManglingError
Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node,
unsigned depth) {
return mangleGenericPartialSpecialization(node, depth + 1);
}
ManglingError
Remangler::mangleGenericSpecializationNode(Node *node, char specKind,
unsigned depth) {
bool FirstParam = true;
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::GenericSpecializationParam) {
RETURN_IF_ERROR(mangleChildNode(Child, 0, depth + 1));
mangleListSeparator(FirstParam);
}
}
DEMANGLER_ASSERT(
!FirstParam && "generic specialization with no substitutions", node);
Buffer << 'T';
for (NodePointer Child : *node) {
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;
}
ManglingError Remangler::mangleGenericSpecialization(Node *node,
unsigned depth) {
return mangleGenericSpecializationNode(node, 'g', depth + 1);
}
ManglingError
Remangler::mangleGenericSpecializationPrespecialized(Node *node,
unsigned depth) {
return mangleGenericSpecializationNode(node, 's', depth + 1);
}
ManglingError
Remangler::mangleGenericSpecializationNotReAbstracted(Node *node,
unsigned depth) {
return mangleGenericSpecializationNode(node, 'G', depth + 1);
}
ManglingError
Remangler::mangleGenericSpecializationInResilienceDomain(Node *node,
unsigned depth) {
return mangleGenericSpecializationNode(node, 'B', depth + 1);
}
ManglingError Remangler::mangleInlinedGenericFunction(Node *node,
unsigned depth) {
return mangleGenericSpecializationNode(node, 'i', depth + 1);
}
ManglingError Remangler::mangleGenericSpecializationParam(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleGenericTypeMetadataPattern(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MP";
return ManglingError::Success;
}
ManglingError Remangler::mangleGenericTypeParamDecl(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fp";
return ManglingError::Success;
}
ManglingError Remangler::mangleGetter(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "g", depth + 1);
}
ManglingError Remangler::mangleGlobal(Node *node, unsigned depth) {
switch (Flavor) {
case ManglingFlavor::Default:
Buffer << MANGLING_PREFIX_STR;
break;
case ManglingFlavor::Embedded:
Buffer << MANGLING_PREFIX_EMBEDDED_STR;
break;
}
bool mangleInReverseOrder = false;
for (auto Iter = node->begin(), End = node->end(); Iter != End; ++Iter) {
Node *Child = *Iter;
switch (Child->getKind()) {
case Node::Kind::FunctionSignatureSpecialization:
case Node::Kind::GenericSpecialization:
case Node::Kind::GenericSpecializationPrespecialized:
case Node::Kind::GenericSpecializationNotReAbstracted:
case Node::Kind::GenericSpecializationInResilienceDomain:
case Node::Kind::InlinedGenericFunction:
case Node::Kind::GenericPartialSpecialization:
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
case Node::Kind::OutlinedBridgedMethod:
case Node::Kind::OutlinedVariable:
case Node::Kind::OutlinedReadOnlyObject:
case Node::Kind::ObjCAttribute:
case Node::Kind::NonObjCAttribute:
case Node::Kind::DynamicAttribute:
case Node::Kind::VTableAttribute:
case Node::Kind::DirectMethodReferenceAttribute:
case Node::Kind::MergedFunction:
case Node::Kind::DistributedThunk:
case Node::Kind::DistributedAccessor:
case Node::Kind::DynamicallyReplaceableFunctionKey:
case Node::Kind::DynamicallyReplaceableFunctionImpl:
case Node::Kind::DynamicallyReplaceableFunctionVar:
case Node::Kind::AsyncFunctionPointer:
case Node::Kind::AsyncAwaitResumePartialFunction:
case Node::Kind::AsyncSuspendResumePartialFunction:
case Node::Kind::AccessibleFunctionRecord:
case Node::Kind::BackDeploymentThunk:
case Node::Kind::BackDeploymentFallback:
case Node::Kind::HasSymbolQuery:
case Node::Kind::CoroFunctionPointer:
case Node::Kind::DefaultOverride:
mangleInReverseOrder = true;
break;
default:
RETURN_IF_ERROR(mangle(Child, depth + 1));
if (mangleInReverseOrder) {
auto ReverseIter = Iter;
while (ReverseIter != node->begin()) {
--ReverseIter;
RETURN_IF_ERROR(mangle(*ReverseIter, depth + 1));
}
mangleInReverseOrder = false;
}
break;
}
}
return ManglingError::Success;
}
ManglingError Remangler::mangleGlobalGetter(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "G", depth + 1);
}
ManglingError Remangler::mangleIdentifier(Node *node, unsigned depth) {
mangleIdentifierImpl(node, /*isOperator*/ false);
return ManglingError::Success;
}
ManglingError Remangler::mangleIndex(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleUnknownIndex(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleIVarInitializer(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "fe";
return ManglingError::Success;
}
ManglingError Remangler::mangleIVarDestroyer(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "fE";
return ManglingError::Success;
}
ManglingError Remangler::mangleImplDifferentiabilityKind(Node *node,
unsigned depth) {
Buffer << (char)node->getIndex();
return ManglingError::Success;
}
ManglingError Remangler::mangleImplEscaping(Node *node, unsigned depth) {
Buffer << 'e';
return ManglingError::Success;
}
ManglingError Remangler::mangleImplErasedIsolation(Node *node, unsigned depth) {
Buffer << 'A';
return ManglingError::Success;
}
ManglingError Remangler::mangleImplSendingResult(Node *node, unsigned depth) {
Buffer << 'T';
return ManglingError::Success;
}
ManglingError Remangler::mangleImplConvention(Node *node, unsigned depth) {
char ConvCh = llvm::StringSwitch<char>(node->getText())
.Case("@callee_unowned", 'y')
.Case("@callee_guaranteed", 'g')
.Case("@callee_owned", 'x')
.Default(0);
if (!ConvCh)
return MANGLING_ERROR(ManglingError::InvalidImplCalleeConvention, node);
Buffer << ConvCh;
return ManglingError::Success;
}
ManglingError
Remangler::mangleImplParameterResultDifferentiability(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->hasText(), node);
// Empty string represents default differentiability.
if (node->getText().empty())
return ManglingError::Success;
char diffChar = llvm::StringSwitch<char>(node->getText())
.Case("@noDerivative", 'w')
.Default(0);
if (!diffChar)
return MANGLING_ERROR(ManglingError::InvalidImplDifferentiability, node);
Buffer << diffChar;
return ManglingError::Success;
}
ManglingError Remangler::mangleImplParameterSending(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->hasText(), node);
char diffChar =
llvm::StringSwitch<char>(node->getText()).Case("sending", 'T').Default(0);
if (!diffChar)
return MANGLING_ERROR(ManglingError::InvalidImplParameterAttr, node);
Buffer << diffChar;
return ManglingError::Success;
}
ManglingError Remangler::mangleImplParameterIsolated(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->hasText(), node);
char diffChar =
llvm::StringSwitch<char>(node->getText()).Case("isolated", 'I').Default(0);
if (!diffChar)
return MANGLING_ERROR(ManglingError::InvalidImplParameterAttr, node);
Buffer << diffChar;
return ManglingError::Success;
}
ManglingError Remangler::mangleImplParameterImplicitLeading(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->hasText(), node);
char diffChar =
llvm::StringSwitch<char>(node->getText()).Case("sil_implicit_leading_param", 'L').Default(0);
if (!diffChar)
return MANGLING_ERROR(ManglingError::InvalidImplParameterAttr, node);
Buffer << diffChar;
return ManglingError::Success;
}
ManglingError Remangler::mangleImplFunctionAttribute(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleImplFunctionConvention(Node *node,
unsigned depth) {
StringRef text =
(node->getNumChildren() > 0 && node->getFirstChild()->hasText())
? node->getFirstChild()->getText()
: "";
char FuncAttr = llvm::StringSwitch<char>(text)
.Case("block", 'B')
.Case("c", 'C')
.Case("method", 'M')
.Case("objc_method", 'O')
.Case("closure", 'K')
.Case("witness_method", 'W')
.Default(0);
DEMANGLER_ASSERT(FuncAttr && "invalid impl function convention", node);
if ((FuncAttr == 'B' || FuncAttr == 'C') && node->getNumChildren() > 1 &&
node->getChild(1)->getKind() == Node::Kind::ClangType) {
Buffer << 'z' << FuncAttr;
return mangleClangType(node->getChild(1), depth + 1);
}
Buffer << FuncAttr;
return ManglingError::Success;
}
ManglingError Remangler::mangleImplFunctionConventionName(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleClangType(Node *node, unsigned depth) {
Buffer << node->getText().size() << node->getText();
return ManglingError::Success;
}
ManglingError Remangler::mangleImplInvocationSubstitutions(Node *node,
unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleImplPatternSubstitutions(Node *node,
unsigned depth) {
// handled inline
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 (Child->getKind()) {
case Node::Kind::ImplParameter:
case Node::Kind::ImplResult:
case Node::Kind::ImplYield:
case Node::Kind::ImplErrorResult:
// Mangle type. Type should be the last child.
DEMANGLER_ASSERT(Child->getNumChildren() >= 2, Child);
RETURN_IF_ERROR(mangle(Child->getLastChild(), depth + 1));
break;
case Node::Kind::DependentPseudogenericSignature:
PseudoGeneric = "P";
LLVM_FALLTHROUGH;
case Node::Kind::DependentGenericSignature:
GenSig = Child;
break;
case Node::Kind::ImplPatternSubstitutions:
PatternSubs = Child;
break;
case Node::Kind::ImplInvocationSubstitutions:
InvocationSubs = Child;
break;
default:
break;
}
}
if (GenSig)
RETURN_IF_ERROR(mangle(GenSig, depth + 1));
if (InvocationSubs) {
Buffer << 'y';
RETURN_IF_ERROR(mangleChildNodes(InvocationSubs->getChild(0), depth + 1));
if (InvocationSubs->getNumChildren() >= 2) {
RETURN_IF_ERROR(
mangleRetroactiveConformance(InvocationSubs->getChild(1), depth + 1));
}
}
if (PatternSubs) {
RETURN_IF_ERROR(mangle(PatternSubs->getChild(0), depth + 1));
Buffer << 'y';
RETURN_IF_ERROR(mangleChildNodes(PatternSubs->getChild(1), depth + 1));
if (PatternSubs->getNumChildren() >= 3) {
NodePointer retroactiveConf = PatternSubs->getChild(2);
if (retroactiveConf->getKind() == Node::Kind::TypeList) {
RETURN_IF_ERROR(mangleChildNodes(retroactiveConf, depth + 1));
} else {
RETURN_IF_ERROR(
mangleRetroactiveConformance(retroactiveConf, depth + 1));
}
}
}
Buffer << 'I';
if (PatternSubs)
Buffer << 's';
if (InvocationSubs)
Buffer << 'I';
Buffer << PseudoGeneric;
for (NodePointer Child : *node) {
switch (Child->getKind()) {
case Node::Kind::ImplDifferentiabilityKind:
Buffer << (char)Child->getIndex();
break;
case Node::Kind::ImplEscaping:
Buffer << 'e';
break;
case Node::Kind::ImplErasedIsolation:
Buffer << 'A';
break;
case Node::Kind::ImplSendingResult:
Buffer << 'T';
break;
case Node::Kind::ImplConvention: {
char ConvCh = llvm::StringSwitch<char>(Child->getText())
.Case("@callee_unowned", 'y')
.Case("@callee_guaranteed", 'g')
.Case("@callee_owned", 'x')
.Case("@convention(thin)", 't')
.Default(0);
if (!ConvCh)
return MANGLING_ERROR(ManglingError::InvalidImplCalleeConvention,
Child);
Buffer << ConvCh;
break;
}
case Node::Kind::ImplFunctionConvention: {
RETURN_IF_ERROR(mangleImplFunctionConvention(Child, depth + 1));
break;
}
case Node::Kind::ImplCoroutineKind: {
char CoroAttr = llvm::StringSwitch<char>(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<char>(Child->getText())
.Case("@Sendable", 'h')
.Case("@async", 'H')
.Default(0);
if (!FuncAttr) {
return MANGLING_ERROR(ManglingError::InvalidImplFunctionAttribute,
Child);
}
Buffer << FuncAttr;
break;
}
case Node::Kind::ImplYield:
Buffer << 'Y';
LLVM_FALLTHROUGH;
case Node::Kind::ImplParameter: {
// Mangle parameter convention.
char ConvCh =
llvm::StringSwitch<char>(Child->getFirstChild()->getText())
.Case("@in", 'i')
.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')
.Case("@deallocating", 'e')
.Case("@unowned", 'y')
.Case("@pack_guaranteed", 'p')
.Case("@pack_owned", 'v')
.Case("@pack_inout", 'm')
.Default(0);
if (!ConvCh) {
return MANGLING_ERROR(ManglingError::InvalidImplParameterConvention,
Child->getFirstChild());
}
Buffer << ConvCh;
for (unsigned i = 1; i < Child->getNumChildren() - 1; ++i) {
auto *Grandchild = Child->getChild(i);
switch (Grandchild->getKind()) {
case Node::Kind::ImplParameterResultDifferentiability:
RETURN_IF_ERROR(mangleImplParameterResultDifferentiability(
Grandchild, depth + 1));
break;
case Node::Kind::ImplParameterSending:
RETURN_IF_ERROR(mangleImplParameterSending(
Grandchild, depth + 1));
break;
case Node::Kind::ImplParameterIsolated:
RETURN_IF_ERROR(mangleImplParameterIsolated(
Grandchild, depth + 1));
break;
case Node::Kind::ImplParameterImplicitLeading:
RETURN_IF_ERROR(mangleImplParameterImplicitLeading(
Grandchild, depth + 1));
break;
default:
Child->dump();
abort();
return MANGLING_ERROR(ManglingError::InvalidImplParameterAttr,
Grandchild);
}
}
break;
}
case Node::Kind::ImplErrorResult:
Buffer << 'z';
LLVM_FALLTHROUGH;
case Node::Kind::ImplResult: {
char ConvCh = llvm::StringSwitch<char>(Child->getFirstChild()->getText())
.Case("@out", 'r')
.Case("@owned", 'o')
.Case("@unowned", 'd')
.Case("@unowned_inner_pointer", 'u')
.Case("@autoreleased", 'a')
.Case("@pack_out", 'k')
.Default(0);
if (!ConvCh) {
return MANGLING_ERROR(ManglingError::InvalidImplParameterConvention,
Child->getFirstChild());
}
Buffer << ConvCh;
// Mangle result differentiability, if it exists.
if (Child->getNumChildren() == 3) {
RETURN_IF_ERROR(mangleImplParameterResultDifferentiability(
Child->getChild(1), depth + 1));
} else if (Child->getNumChildren() == 4) {
RETURN_IF_ERROR(mangleImplParameterResultDifferentiability(
Child->getChild(1), depth + 1));
RETURN_IF_ERROR(
mangleImplParameterSending(Child->getChild(2), depth + 1));
}
break;
}
default:
break;
}
}
Buffer << '_';
return ManglingError::Success;
}
ManglingError Remangler::mangleImplicitClosure(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); // context
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1)); // type
Buffer << "fu";
return mangleChildNode(node, 1, depth + 1); // index
}
ManglingError Remangler::mangleImplParameter(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleImplResult(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleImplYield(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleImplErrorResult(Node *node, unsigned depth) {
// handled inline
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleInOut(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << 'z';
return ManglingError::Success;
}
ManglingError Remangler::mangleIsolated(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Yi";
return ManglingError::Success;
}
ManglingError Remangler::mangleSending(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Yu";
return ManglingError::Success;
}
ManglingError Remangler::mangleCompileTimeLiteral(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Yt";
return ManglingError::Success;
}
ManglingError Remangler::mangleConstValue(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Yg";
return ManglingError::Success;
}
ManglingError Remangler::mangleShared(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << 'h';
return ManglingError::Success;
}
ManglingError Remangler::mangleOwned(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << 'n';
return ManglingError::Success;
}
ManglingError Remangler::mangleNoDerivative(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Yk";
return ManglingError::Success;
}
ManglingError Remangler::mangleInfixOperator(Node *node, unsigned depth) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "oi";
return ManglingError::Success;
}
ManglingError Remangler::mangleInitializer(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fi";
return ManglingError::Success;
}
ManglingError Remangler::mangleInitAccessor(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "i", depth + 1);
}
ManglingError
Remangler::manglePropertyWrapperBackingInitializer(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fP";
return ManglingError::Success;
}
ManglingError
Remangler::manglePropertyWrapperInitFromProjectedValue(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fW";
return ManglingError::Success;
}
ManglingError
Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Wl";
return ManglingError::Success;
}
ManglingError
Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WL";
return ManglingError::Success;
}
ManglingError Remangler::mangleLocalDeclName(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // identifier
Buffer << 'L';
return mangleChildNode(node, 0, depth + 1); // index
}
ManglingError Remangler::mangleMaterializeForSet(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "m", depth + 1);
}
ManglingError Remangler::mangleMetatype(Node *node, unsigned depth) {
if (node->getFirstChild()->getKind() == Node::Kind::MetatypeRepresentation) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
Buffer << "XM";
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
} else {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << 'm';
}
return ManglingError::Success;
}
ManglingError Remangler::mangleMetatypeRepresentation(Node *node,
unsigned depth) {
auto 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::mangleMetaclass(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Mm";
return ManglingError::Success;
}
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) {
Buffer << 's';
} else if (text == MANGLING_MODULE_OBJC) {
Buffer << "So";
} else if (text == MANGLING_MODULE_CLANG_IMPORTER) {
Buffer << "SC";
} else {
return mangleIdentifier(node, depth);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleNativeOwningAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "lo", depth + 1);
}
ManglingError Remangler::mangleNativeOwningMutableAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "ao", depth + 1);
}
ManglingError Remangler::mangleNativePinningAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "lp", depth + 1);
}
ManglingError Remangler::mangleNativePinningMutableAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "aP", depth + 1);
}
ManglingError Remangler::mangleClassMetadataBaseOffset(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mo";
return ManglingError::Success;
}
ManglingError Remangler::mangleNominalTypeDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mn";
return ManglingError::Success;
}
ManglingError Remangler::mangleNominalTypeDescriptorRecord(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Hn";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueTypeDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MQ";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueTypeDescriptorRecord(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Ho";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueTypeDescriptorAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mg";
return ManglingError::Success;
}
ManglingError
Remangler::mangleOpaqueTypeDescriptorAccessorImpl(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mh";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueTypeDescriptorAccessorKey(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mj";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueTypeDescriptorAccessorVar(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mk";
return ManglingError::Success;
}
ManglingError Remangler::manglePropertyDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MV";
return ManglingError::Success;
}
ManglingError Remangler::mangleNonObjCAttribute(Node *node, unsigned depth) {
Buffer << "TO";
return ManglingError::Success;
}
ManglingError Remangler::mangleTuple(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << 't';
return ManglingError::Success;
}
ManglingError Remangler::manglePack(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << "QP";
return ManglingError::Success;
}
ManglingError Remangler::mangleSILPackDirect(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << "QSd";
return ManglingError::Success;
}
ManglingError Remangler::mangleSILPackIndirect(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << "QSi";
return ManglingError::Success;
}
ManglingError Remangler::manglePackExpansion(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Qp";
return ManglingError::Success;
}
ManglingError Remangler::manglePackElement(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
Buffer << "Qe";
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
return ManglingError::Success;
}
ManglingError Remangler::manglePackElementLevel(Node *node, unsigned depth) {
mangleIndex(node->getIndex());
return ManglingError::Success;
}
ManglingError Remangler::mangleNumber(Node *node, unsigned depth) {
mangleIndex(node->getIndex());
return ManglingError::Success;
}
ManglingError Remangler::mangleObjCAttribute(Node *node, unsigned depth) {
Buffer << "To";
return ManglingError::Success;
}
ManglingError Remangler::mangleObjCBlock(Node *node, unsigned depth) {
if (node->getNumChildren() > 0 &&
node->getFirstChild()->getKind() == Node::Kind::ClangType) {
for (size_t Idx = node->getNumChildren() - 1; Idx >= 1; --Idx) {
RETURN_IF_ERROR(mangleChildNode(node, Idx, depth + 1));
}
Buffer << "XzB";
return mangleClangType(node->getFirstChild(), depth + 1);
}
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "XB";
return ManglingError::Success;
}
ManglingError Remangler::mangleEscapingObjCBlock(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "XL";
return ManglingError::Success;
}
ManglingError Remangler::mangleOwningAddressor(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "lO", depth + 1);
}
ManglingError Remangler::mangleOwningMutableAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "aO", depth + 1);
}
ManglingError Remangler::manglePartialApplyForwarder(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "TA";
return ManglingError::Success;
}
ManglingError Remangler::manglePartialApplyObjCForwarder(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "Ta";
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) {
Buffer << "TQ";
return mangleChildNode(node, 0, depth + 1);
}
ManglingError
Remangler::mangleAsyncSuspendResumePartialFunction(Node *node, unsigned depth) {
Buffer << "TY";
return mangleChildNode(node, 0, depth + 1);
}
ManglingError Remangler::manglePostfixOperator(Node *node, unsigned depth) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "oP";
return ManglingError::Success;
}
ManglingError Remangler::manglePrefixOperator(Node *node, unsigned depth) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "op";
return ManglingError::Success;
}
ManglingError Remangler::manglePrivateDeclName(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << (node->getNumChildren() == 1 ? "Ll" : "LL");
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocol(Node *node, unsigned depth) {
return mangleAnyGenericType(node, "P", depth + 1);
}
ManglingError Remangler::mangleRetroactiveConformance(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleAnyProtocolConformance(node->getChild(1), depth + 1));
Buffer << 'g';
mangleIndex(node->getChild(0)->getIndex());
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolConformance(Node *node, unsigned depth) {
Node *Ty = getChildOfType(node->getChild(0));
Node *GenSig = nullptr;
if (Ty->getKind() == Node::Kind::DependentGenericType) {
GenSig = Ty->getFirstChild();
Ty = Ty->getChild(1);
}
RETURN_IF_ERROR(mangle(Ty, depth + 1));
if (node->getNumChildren() == 4)
RETURN_IF_ERROR(mangleChildNode(node, 3, depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(1), depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
if (GenSig)
RETURN_IF_ERROR(mangle(GenSig, depth + 1));
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolConformanceRefInTypeModule(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(node->getChild(0), depth + 1));
Buffer << "HP";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolConformanceRefInProtocolModule(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(node->getChild(0), depth + 1));
Buffer << "Hp";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolConformanceRefInOtherModule(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(node->getChild(0), depth + 1));
return mangleChildNode(node, 1, depth + 1);
}
ManglingError Remangler::mangleConcreteProtocolConformance(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangle(node->getChild(1), depth + 1));
if (node->getNumChildren() > 2) {
RETURN_IF_ERROR(
mangleAnyProtocolConformanceList(node->getChild(2), depth + 1));
} else {
Buffer << "y";
}
Buffer << "HC";
return ManglingError::Success;
}
ManglingError Remangler::manglePackProtocolConformance(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleAnyProtocolConformanceList(node->getChild(0), depth + 1));
Buffer << "HX";
return ManglingError::Success;
}
ManglingError
Remangler::mangleDependentProtocolConformanceRoot(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(1), depth + 1));
Buffer << "HD";
return mangleDependentConformanceIndex(node->getChild(2), depth + 1);
}
ManglingError
Remangler::mangleDependentProtocolConformanceInherited(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleAnyProtocolConformance(node->getChild(0), depth + 1));
RETURN_IF_ERROR(manglePureProtocol(node->getChild(1), depth + 1));
Buffer << "HI";
return mangleDependentConformanceIndex(node->getChild(2), depth + 1);
}
ManglingError Remangler::mangleDependentAssociatedConformance(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
return manglePureProtocol(node->getChild(1), depth + 1);
}
ManglingError
Remangler::mangleDependentProtocolConformanceAssociated(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleAnyProtocolConformance(node->getChild(0), depth + 1));
RETURN_IF_ERROR(
mangleDependentAssociatedConformance(node->getChild(1), depth + 1));
Buffer << "HA";
return mangleDependentConformanceIndex(node->getChild(2), depth + 1);
}
ManglingError Remangler::mangleDependentConformanceIndex(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getKind() == Node::Kind::Index ||
node->getKind() == Node::Kind::UnknownIndex,
node);
DEMANGLER_ASSERT(node->hasIndex() == (node->getKind() == Node::Kind::Index),
node);
mangleIndex(node->hasIndex() ? node->getIndex() + 2 : 1);
return ManglingError::Success;
}
ManglingError Remangler::mangleDependentProtocolConformanceOpaque(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getKind() == Node::Kind::DependentProtocolConformanceOpaque,
node);
mangleAnyProtocolConformance(node->getChild(0), depth + 1);
mangleType(node->getChild(1), depth + 1);
Buffer << "HO";
return ManglingError::Success;
}
ManglingError Remangler::mangleAnyProtocolConformance(Node *node,
unsigned depth) {
switch (node->getKind()) {
case Node::Kind::ConcreteProtocolConformance:
return mangleConcreteProtocolConformance(node, depth + 1);
case Node::Kind::PackProtocolConformance:
return manglePackProtocolConformance(node, depth + 1);
case Node::Kind::DependentProtocolConformanceRoot:
return mangleDependentProtocolConformanceRoot(node, depth + 1);
case Node::Kind::DependentProtocolConformanceInherited:
return mangleDependentProtocolConformanceInherited(node, depth + 1);
case Node::Kind::DependentProtocolConformanceAssociated:
return mangleDependentProtocolConformanceAssociated(node, depth + 1);
case Node::Kind::DependentProtocolConformanceOpaque:
return mangleDependentProtocolConformanceOpaque(node, depth + 1);
default:
// Should this really succeed?!
return ManglingError::Success;
}
}
ManglingError Remangler::mangleAnyProtocolConformanceList(Node *node,
unsigned depth) {
bool firstElem = true;
for (NodePointer child : *node) {
RETURN_IF_ERROR(mangleAnyProtocolConformance(child, depth + 1));
mangleListSeparator(firstElem);
}
mangleEndOfList(firstElem);
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(getSingleChild(node), depth + 1));
Buffer << "Mp";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolDescriptorRecord(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(getSingleChild(node), depth + 1));
Buffer << "Hr";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolRequirementsBaseDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(getSingleChild(node), depth + 1));
Buffer << "TL";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolSelfConformanceDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(node->getChild(0), depth + 1));
Buffer << "MS";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolConformanceDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleProtocolConformance(node->getChild(0), depth + 1));
Buffer << "Mc";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolConformanceDescriptorRecord(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleProtocolConformance(node->getChild(0), depth + 1));
Buffer << "Hc";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolList(Node *node, Node *superclass,
bool hasExplicitAnyObject,
unsigned depth) {
auto *protocols = getSingleChild(node, Node::Kind::TypeList);
bool FirstElem = true;
for (NodePointer Child : *protocols) {
RETURN_IF_ERROR(manglePureProtocol(Child, depth + 1));
mangleListSeparator(FirstElem);
}
mangleEndOfList(FirstElem);
if (superclass) {
RETURN_IF_ERROR(mangleType(superclass, depth + 1));
Buffer << "Xc";
return ManglingError::Success;
} else if (hasExplicitAnyObject) {
Buffer << "Xl";
return ManglingError::Success;
}
Buffer << 'p';
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolList(Node *node, unsigned depth) {
return mangleProtocolList(node, nullptr, false, depth + 1);
}
ManglingError Remangler::mangleProtocolListWithClass(Node *node,
unsigned depth) {
return mangleProtocolList(node->getChild(0), node->getChild(1), false,
depth + 1);
}
ManglingError Remangler::mangleProtocolListWithAnyObject(Node *node,
unsigned depth) {
return mangleProtocolList(node->getChild(0), nullptr, true, depth + 1);
}
ManglingError Remangler::mangleProtocolSelfConformanceWitness(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "TS";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolWitness(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "TW";
return ManglingError::Success;
}
ManglingError
Remangler::mangleProtocolSelfConformanceWitnessTable(Node *node,
unsigned depth) {
RETURN_IF_ERROR(manglePureProtocol(node->getChild(0), depth + 1));
Buffer << "WS";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolWitnessTable(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "WP";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolWitnessTablePattern(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Wp";
return ManglingError::Success;
}
ManglingError Remangler::mangleProtocolWitnessTableAccessor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Wa";
return ManglingError::Success;
}
ManglingError Remangler::mangleReabstractionThunk(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "Tr";
return ManglingError::Success;
}
ManglingError Remangler::mangleReabstractionThunkHelper(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "TR";
return ManglingError::Success;
}
ManglingError
Remangler::mangleReabstractionThunkHelperWithSelf(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodesReversed(node, depth + 1));
Buffer << "Ty";
return ManglingError::Success;
}
ManglingError
Remangler::mangleReabstractionThunkHelperWithGlobalActor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "TU";
return ManglingError::Success;
}
ManglingError Remangler::mangleAutoDiffFunctionOrSimpleThunk(Node *node,
StringRef op,
unsigned depth) {
auto childIt = node->begin();
while (childIt != node->end() &&
(*childIt)->getKind() != Node::Kind::AutoDiffFunctionKind)
RETURN_IF_ERROR(mangle(*childIt++, depth + 1));
Buffer << op;
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // kind
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // parameter indices
Buffer << 'p';
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // result indices
Buffer << 'r';
return ManglingError::Success;
}
ManglingError Remangler::mangleAutoDiffFunction(Node *node, unsigned depth) {
return mangleAutoDiffFunctionOrSimpleThunk(node, "TJ", depth + 1);
}
ManglingError Remangler::mangleAutoDiffDerivativeVTableThunk(Node *node,
unsigned depth) {
return mangleAutoDiffFunctionOrSimpleThunk(node, "TJV", depth + 1);
}
ManglingError
Remangler::mangleAutoDiffSelfReorderingReabstractionThunk(Node *node,
unsigned depth) {
auto childIt = node->begin();
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // from type
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // to type
if ((*childIt)->getKind() == Node::Kind::DependentGenericSignature)
RETURN_IF_ERROR(mangleDependentGenericSignature(*childIt++, depth + 1));
Buffer << "TJO";
return mangle(*childIt++, depth + 1); // kind
}
ManglingError Remangler::mangleAutoDiffSubsetParametersThunk(Node *node,
unsigned depth) {
auto childIt = node->begin();
while (childIt != node->end() &&
(*childIt)->getKind() != Node::Kind::AutoDiffFunctionKind)
RETURN_IF_ERROR(mangle(*childIt++, depth + 1));
Buffer << "TJS";
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // kind
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // parameter indices
Buffer << 'p';
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // result indices
Buffer << 'r';
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // to parameter indices
Buffer << 'P';
return ManglingError::Success;
}
ManglingError Remangler::mangleAutoDiffFunctionKind(Node *node,
unsigned depth) {
Buffer << (char)node->getIndex();
return ManglingError::Success;
}
ManglingError Remangler::mangleDifferentiabilityWitness(Node *node,
unsigned depth) {
auto childIt = node->begin();
while (childIt != node->end() && (*childIt)->getKind() != Node::Kind::Index)
RETURN_IF_ERROR(mangle(*childIt++, depth + 1));
if (node->getLastChild()->getKind() ==
Node::Kind::DependentGenericSignature)
RETURN_IF_ERROR(mangle(node->getLastChild(), depth + 1));
Buffer << "WJ" << (char)(*childIt++)->getIndex();
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // parameter indices
Buffer << 'p';
RETURN_IF_ERROR(mangle(*childIt++, depth + 1)); // result indices
Buffer << 'r';
return ManglingError::Success;
}
ManglingError Remangler::mangleIndexSubset(Node *node, unsigned depth) {
Buffer << node->getText();
return ManglingError::Success;
}
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)
if (Child->getKind() != Node::Kind::IsSerialized)
RETURN_IF_ERROR(mangle(Child, depth + 1));
Buffer << op;
for (NodePointer Child : *node)
if (Child->getKind() == Node::Kind::IsSerialized)
RETURN_IF_ERROR(mangle(Child, depth + 1));
return ManglingError::Success;
}
ManglingError Remangler::mangleKeyPathGetterThunkHelper(Node *node,
unsigned depth) {
return mangleKeyPathThunkHelper(node, "TK", depth + 1);
}
ManglingError Remangler::mangleKeyPathSetterThunkHelper(Node *node,
unsigned depth) {
return mangleKeyPathThunkHelper(node, "Tk", depth + 1);
}
ManglingError
Remangler::mangleKeyPathUnappliedMethodThunkHelper(Node *node, unsigned depth) {
return mangleKeyPathThunkHelper(node, "Tkmu", depth + 1);
}
ManglingError Remangler::mangleKeyPathAppliedMethodThunkHelper(Node *node,
unsigned depth) {
return mangleKeyPathThunkHelper(node, "TkMA", depth + 1);
}
ManglingError Remangler::mangleKeyPathEqualsThunkHelper(Node *node,
unsigned depth) {
return mangleKeyPathThunkHelper(node, "TH", depth + 1);
}
ManglingError Remangler::mangleKeyPathHashThunkHelper(Node *node,
unsigned depth) {
return mangleKeyPathThunkHelper(node, "Th", depth + 1);
}
ManglingError Remangler::mangleReturnType(Node *node, unsigned depth) {
return mangleArgumentTuple(node, depth + 1);
}
ManglingError Remangler::mangleRelatedEntityDeclName(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
NodePointer kindNode = node->getFirstChild();
if (kindNode->getText().size() != 1)
return MANGLING_ERROR(ManglingError::MultiByteRelatedEntity, kindNode);
Buffer << "L" << kindNode->getText();
return ManglingError::Success;
}
ManglingError Remangler::mangleSILBoxType(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Xb";
return ManglingError::Success;
}
ManglingError Remangler::mangleSetter(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "s", depth + 1);
}
ManglingError Remangler::mangleSpecializationPassID(Node *node,
unsigned depth) {
Buffer << node->getIndex();
return ManglingError::Success;
}
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";
int n = node->getIndex();
if (n > 0)
Buffer << (n-1);
return ManglingError::Success;
}
ManglingError Remangler::mangleStatic(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << 'Z';
return ManglingError::Success;
}
ManglingError Remangler::mangleOtherNominalType(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleStructure(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleSubscript(Node *node, unsigned depth) {
return mangleAbstractStorage(node, "p", depth + 1);
}
ManglingError Remangler::mangleMacro(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "fm";
return ManglingError::Success;
}
ManglingError Remangler::mangleFreestandingMacroExpansion(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
Buffer << "fMf";
return mangleChildNode(node, 2, depth + 1);
}
#define FREESTANDING_MACRO_ROLE(Name, Description)
#define ATTACHED_MACRO_ROLE(Name, Description, MangledChar) \
ManglingError Remangler::mangle##Name##AttachedMacroExpansion( \
Node *node, unsigned depth) { \
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1)); \
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); \
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1)); \
Buffer << "fM" MangledChar; \
return mangleChildNode(node, 3, depth + 1); \
}
#include "swift/Basic/MacroRoles.def"
ManglingError Remangler::mangleMacroExpansionLoc(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
auto line = node->getChild(2)->getIndex();
auto col = node->getChild(3)->getIndex();
Buffer << "fMX";
mangleIndex(line);
mangleIndex(col);
return ManglingError::Success;
}
ManglingError Remangler::mangleMacroExpansionUniqueName(
Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
if (auto privateDiscriminator = node->getChild(3))
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
Buffer << "fMu";
return mangleChildNode(node, 2, depth + 1);
}
ManglingError Remangler::mangleSuffix(Node *node, unsigned depth) {
// Just add the suffix back on.
Buffer << node->getText();
return ManglingError::Success;
}
ManglingError Remangler::mangleThinFunctionType(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleFunctionSignature(node, depth + 1));
Buffer << "Xf";
return ManglingError::Success;
}
ManglingError Remangler::mangleTupleElement(Node *node, unsigned depth) {
return mangleChildNodesReversed(node, depth + 1); // tuple type, element name?
}
ManglingError Remangler::mangleTupleElementName(Node *node, unsigned depth) {
return mangleIdentifier(node, depth + 1);
}
ManglingError Remangler::mangleType(Node *node, unsigned depth) {
return mangleSingleChildNode(node, depth + 1);
}
ManglingError Remangler::mangleTypeAlias(Node *node, unsigned depth) {
return mangleAnyNominalType(node, depth + 1);
}
ManglingError Remangler::mangleTypeList(Node *node, unsigned depth) {
bool FirstElem = true;
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
RETURN_IF_ERROR(mangleChildNode(node, Idx, depth + 1));
mangleListSeparator(FirstElem);
}
mangleEndOfList(FirstElem);
return ManglingError::Success;
}
ManglingError Remangler::mangleLabelList(Node *node, unsigned depth) {
if (node->getNumChildren() == 0)
Buffer << 'y';
else
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMangling(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << 'D';
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadata(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "N";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadataAccessFunction(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Ma";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadataInstantiationCache(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MI";
return ManglingError::Success;
}
ManglingError
Remangler::mangleTypeMetadataInstantiationFunction(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mi";
return ManglingError::Success;
}
ManglingError
Remangler::mangleTypeMetadataSingletonInitializationCache(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Ml";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadataCompletionFunction(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mr";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadataDemanglingCache(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "MD";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeMetadataLazyCache(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "ML";
return ManglingError::Success;
}
ManglingError Remangler::mangleUncurriedFunctionType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleFunctionSignature(node, depth + 1));
// Mangle as regular function type (there is no "uncurried function type"
// in the new mangling scheme).
Buffer << 'c';
return ManglingError::Success;
}
ManglingError Remangler::mangleUnsafeAddressor(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "lu", depth + 1);
}
ManglingError Remangler::mangleUnsafeMutableAddressor(Node *node,
unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "au", depth + 1);
}
ManglingError Remangler::mangleValueWitness(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1)); // type
const char *Code = nullptr;
switch (ValueWitnessKind(node->getFirstChild()->getIndex())) {
#define VALUE_WITNESS(MANGLING, NAME) \
case ValueWitnessKind::NAME: Code = #MANGLING; break;
#include "swift/Demangling/ValueWitnessMangling.def"
}
Buffer << 'w' << Code;
return ManglingError::Success;
}
ManglingError Remangler::mangleValueWitnessTable(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "WV";
return ManglingError::Success;
}
ManglingError Remangler::mangleVariable(Node *node, unsigned depth) {
return mangleAbstractStorage(node, "p", depth + 1);
}
ManglingError Remangler::mangleVTableAttribute(Node *node, unsigned depth) {
// Old-fashioned vtable thunk in new mangling format
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleVTableThunk(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "TV";
return ManglingError::Success;
}
#define REF_STORAGE(Name, ...) \
ManglingError Remangler::mangle##Name(Node *node, unsigned depth) { \
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1)); \
Buffer << manglingOf(ReferenceOwnership::Name); \
return ManglingError::Success; \
}
#include "swift/AST/ReferenceStorage.def"
ManglingError Remangler::mangleWillSet(Node *node, unsigned depth) {
return mangleAbstractStorage(node->getFirstChild(), "w", depth + 1);
}
ManglingError
Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MB";
return ManglingError::Success;
}
ManglingError
Remangler::mangleReflectionMetadataFieldDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MF";
return ManglingError::Success;
}
ManglingError
Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleSingleChildNode(node, depth + 1)); // protocol-conformance
Buffer << "MA";
return ManglingError::Success;
}
ManglingError
Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node,
unsigned depth) {
RETURN_IF_ERROR(
mangleSingleChildNode(node, depth + 1)); // protocol-conformance
Buffer << "MC";
return ManglingError::Success;
}
ManglingError Remangler::mangleCurryThunk(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Tc";
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::mangleDispatchThunk(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Tj";
return ManglingError::Success;
}
ManglingError Remangler::mangleMethodDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Tq";
return ManglingError::Success;
}
ManglingError Remangler::mangleMethodLookupFunction(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mu";
return ManglingError::Success;
}
ManglingError Remangler::mangleObjCMetadataUpdateFunction(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MU";
return ManglingError::Success;
}
ManglingError Remangler::mangleObjCResilientClassStub(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Ms";
return ManglingError::Success;
}
ManglingError Remangler::mangleFullObjCResilientClassStub(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "Mt";
return ManglingError::Success;
}
ManglingError Remangler::mangleConcurrentFunctionType(Node *node,
unsigned depth) {
Buffer << "Yb";
return ManglingError::Success;
}
ManglingError Remangler::mangleAsyncAnnotation(Node *node, unsigned depth) {
Buffer << "Ya";
return ManglingError::Success;
}
ManglingError Remangler::mangleDifferentiableFunctionType(Node *node,
unsigned depth) {
Buffer << "Yj" << (char)node->getIndex(); // differentiability kind
return ManglingError::Success;
}
ManglingError Remangler::mangleGlobalActorFunctionType(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Yc";
return ManglingError::Success;
}
ManglingError Remangler::mangleIsolatedAnyFunctionType(Node *node,
unsigned depth) {
Buffer << "YA";
return ManglingError::Success;
}
ManglingError Remangler::mangleNonIsolatedCallerFunctionType(Node *node,
unsigned depth) {
Buffer << "YC";
return ManglingError::Success;
}
ManglingError Remangler::mangleSendingResultFunctionType(Node *node,
unsigned depth) {
Buffer << "YT";
return ManglingError::Success;
}
ManglingError Remangler::mangleThrowsAnnotation(Node *node, unsigned depth) {
Buffer << 'K';
return ManglingError::Success;
}
ManglingError Remangler::mangleTypedThrowsAnnotation(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "YK";
return ManglingError::Success;
}
ManglingError Remangler::mangleEmptyList(Node *node, unsigned depth) {
Buffer << 'y';
return ManglingError::Success;
}
ManglingError Remangler::mangleFirstElementMarker(Node *node, unsigned depth) {
Buffer << '_';
return ManglingError::Success;
}
ManglingError Remangler::mangleVariadicMarker(Node *node, unsigned depth) {
Buffer << 'd';
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedCopy(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOy";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedConsume(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOe";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedRetain(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOr";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedRelease(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOs";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedInitializeWithTake(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOb";
return ManglingError::Success;
}
ManglingError
Remangler::mangleOutlinedInitializeWithTakeNoValueWitness(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOB";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedInitializeWithCopy(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOc";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedAssignWithTake(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOd";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedAssignWithCopy(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOf";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedDestroy(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOh";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedInitializeWithCopyNoValueWitness(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOC";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedAssignWithTakeNoValueWitness(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOD";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedAssignWithCopyNoValueWitness(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOF";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedDestroyNoValueWitness(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOH";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedEnumGetTag(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WOg";
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedEnumProjectDataForLoad(Node *node, unsigned depth) {
if (node->getNumChildren() == 2) {
auto ty = node->getChild(0);
RETURN_IF_ERROR(mangle(ty, depth + 1));
Buffer << "WOj";
mangleIndex(node->getChild(1)->getIndex());
return ManglingError::Success;
} else {
auto ty = node->getChild(0);
RETURN_IF_ERROR(mangle(ty, depth + 1));
auto sig = node->getChild(1);
RETURN_IF_ERROR(mangle(sig, depth + 1));
Buffer << "WOj";
mangleIndex(node->getChild(2)->getIndex());
return ManglingError::Success;
}
}
ManglingError Remangler::mangleOutlinedEnumTagStore(Node *node, unsigned depth) {
if (node->getNumChildren() == 2) {
auto ty = node->getChild(0);
RETURN_IF_ERROR(mangle(ty, depth + 1));
Buffer << "WOi";
mangleIndex(node->getChild(1)->getIndex());
return ManglingError::Success;
} else {
auto ty = node->getChild(0);
RETURN_IF_ERROR(mangle(ty, depth + 1));
auto sig = node->getChild(1);
RETURN_IF_ERROR(mangle(sig, depth + 1));
Buffer << "WOi";
mangleIndex(node->getChild(2)->getIndex());
return ManglingError::Success;
}
}
ManglingError Remangler::mangleOutlinedVariable(Node *node, unsigned depth) {
Buffer << "Tv";
mangleIndex(node->getIndex());
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedReadOnlyObject(Node *node, unsigned depth) {
Buffer << "Tv";
mangleIndex(node->getIndex());
Buffer << 'r';
return ManglingError::Success;
}
ManglingError Remangler::mangleOutlinedBridgedMethod(Node *node,
unsigned depth) {
Buffer << "Te";
Buffer << node->getText();
Buffer << "_";
return ManglingError::Success;
}
ManglingError Remangler::mangleSILBoxTypeWithLayout(Node *node,
unsigned depth) {
DEMANGLER_ASSERT(node->getNumChildren() == 1 || node->getNumChildren() == 3,
node);
DEMANGLER_ASSERT(node->getChild(0)->getKind() == Node::Kind::SILBoxLayout,
node);
auto layout = node->getChild(0);
auto layoutTypeList = Factory.createNode(Node::Kind::TypeList);
for (unsigned i = 0, e = layout->getNumChildren(); i < e; ++i) {
DEMANGLER_ASSERT(
layout->getChild(i)->getKind() == Node::Kind::SILBoxImmutableField ||
layout->getChild(i)->getKind() == Node::Kind::SILBoxMutableField,
layout->getChild(i));
auto field = layout->getChild(i);
DEMANGLER_ASSERT(field->getNumChildren() == 1 &&
field->getChild(0)->getKind() == Node::Kind::Type,
field);
auto fieldType = field->getChild(0);
// 'inout' mangling is used to represent mutable fields.
if (field->getKind() == Node::Kind::SILBoxMutableField) {
auto inout = Factory.createNode(Node::Kind::InOut);
inout->addChild(fieldType->getChild(0), Factory);
fieldType = Factory.createNode(Node::Kind::Type);
fieldType->addChild(inout, Factory);
}
layoutTypeList->addChild(fieldType, Factory);
}
RETURN_IF_ERROR(mangleTypeList(layoutTypeList, depth + 1));
if (node->getNumChildren() == 3) {
auto signature = node->getChild(1);
auto genericArgs = node->getChild(2);
DEMANGLER_ASSERT(
signature->getKind() == Node::Kind::DependentGenericSignature, node);
DEMANGLER_ASSERT(genericArgs->getKind() == Node::Kind::TypeList, node);
RETURN_IF_ERROR(mangleTypeList(genericArgs, depth + 1));
RETURN_IF_ERROR(mangleDependentGenericSignature(signature, depth + 1));
Buffer << "XX";
} else {
Buffer << "Xx";
}
return ManglingError::Success;
}
ManglingError Remangler::mangleSILBoxLayout(Node *node, unsigned depth) {
// should be part of SILBoxTypeWithLayout
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleSILBoxMutableField(Node *node, unsigned depth) {
// should be part of SILBoxTypeWithLayout
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleSILBoxImmutableField(Node *node,
unsigned depth) {
// should be part of SILBoxTypeWithLayout
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::mangleAssocTypePath(Node *node, unsigned depth) {
bool FirstElem = true;
for (NodePointer Child : *node) {
RETURN_IF_ERROR(mangle(Child, depth + 1));
mangleListSeparator(FirstElem);
}
return ManglingError::Success;
}
ManglingError Remangler::mangleModuleDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
Buffer << "MXM";
return ManglingError::Success;
}
ManglingError Remangler::mangleExtensionDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
Buffer << "MXE";
return ManglingError::Success;
}
ManglingError Remangler::mangleAnonymousDescriptor(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
if (node->getNumChildren() == 1) {
Buffer << "MXX";
} else {
RETURN_IF_ERROR(mangleIdentifier(node->getChild(1), depth + 1));
Buffer << "MXY";
}
return ManglingError::Success;
}
ManglingError Remangler::mangleAssociatedTypeGenericParamRef(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangleAssocTypePath(node->getChild(1), depth + 1));
Buffer << "MXA";
return ManglingError::Success;
}
ManglingError Remangler::mangleTypeSymbolicReference(Node *node,
unsigned depth) {
return mangle(
Resolver(SymbolicReferenceKind::Context, (const void *)node->getIndex()),
depth + 1);
}
ManglingError
Remangler::mangleObjectiveCProtocolSymbolicReference(Node *node,
unsigned depth) {
return mangle(Resolver(SymbolicReferenceKind::ObjectiveCProtocol,
(const void *)node->getIndex()),
depth + 1);
}
ManglingError Remangler::mangleProtocolSymbolicReference(Node *node,
unsigned depth) {
return mangle(
Resolver(SymbolicReferenceKind::Context, (const void *)node->getIndex()),
depth + 1);
}
ManglingError
Remangler::mangleOpaqueTypeDescriptorSymbolicReference(Node *node,
unsigned depth) {
return mangle(
Resolver(SymbolicReferenceKind::Context, (const void *)node->getIndex()),
depth + 1);
}
ManglingError Remangler::mangleSugaredOptional(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
Buffer << "XSq";
return ManglingError::Success;
}
ManglingError Remangler::mangleSugaredArray(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
Buffer << "XSa";
return ManglingError::Success;
}
ManglingError
Remangler::mangleSugaredInlineArray(Node *node, unsigned int depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangleType(node->getChild(1), depth + 1));
Buffer << "XSA";
return ManglingError::Success;
}
ManglingError Remangler::mangleSugaredDictionary(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
RETURN_IF_ERROR(mangleType(node->getChild(1), depth + 1));
Buffer << "XSD";
return ManglingError::Success;
}
ManglingError Remangler::mangleSugaredParen(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
Buffer << "XSp";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueReturnType(Node *node, unsigned depth) {
if (node->hasChildren()
&& node->getFirstChild()->getKind() == Node::Kind::OpaqueReturnTypeIndex) {
Buffer << "QR";
mangleIndex(node->getFirstChild()->getIndex());
return ManglingError::Success;
}
Buffer << "Qr";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueReturnTypeIndex(Node *node, unsigned depth) {
// Cannot appear unparented to an OpaqueReturnType.
return ManglingError::WrongNodeType;
}
ManglingError Remangler::mangleOpaqueReturnTypeParent(Node *node, unsigned depth) {
// Cannot appear unparented to an OpaqueReturnType.
return ManglingError::WrongNodeType;
}
ManglingError Remangler::mangleOpaqueReturnTypeOf(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
Buffer << "QO";
return ManglingError::Success;
}
ManglingError Remangler::mangleOpaqueType(Node *node, unsigned depth) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return ManglingError::Success;
DEMANGLER_ASSERT(node->getNumChildren() >= 3, node);
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
auto boundGenerics = node->getChild(2);
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
Buffer << (i == 0 ? 'y' : '_');
RETURN_IF_ERROR(mangleChildNodes(boundGenerics->getChild(i), depth + 1));
}
if (node->getNumChildren() >= 4) {
auto retroactiveConformances = node->getChild(3);
for (unsigned i = 0; i < retroactiveConformances->getNumChildren(); ++i) {
RETURN_IF_ERROR(mangle(retroactiveConformances->getChild(i), depth + 1));
}
}
Buffer << "Qo";
mangleIndex(node->getChild(1)->getIndex());
addSubstitution(entry);
return ManglingError::Success;
}
ManglingError Remangler::mangleAccessorFunctionReference(Node *node,
unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError
Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
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::mangleMetadataInstantiationCache(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleSingleChildNode(node, depth + 1));
Buffer << "MK";
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;
}
ManglingError Remangler::mangleGlobalVariableOnceToken(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Wz";
return ManglingError::Success;
}
ManglingError Remangler::mangleGlobalVariableOnceFunction(Node *node,
unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "WZ";
return ManglingError::Success;
}
ManglingError Remangler::mangleGlobalVariableOnceDeclList(Node *node,
unsigned depth) {
for (unsigned i = 0, e = node->getNumChildren(); i < e; ++i) {
RETURN_IF_ERROR(mangle(node->getChild(i), depth + 1));
Buffer << '_';
}
return ManglingError::Success;
}
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::mangleUniquable(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
Buffer << "Mq";
return ManglingError::Success;
}
ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
unsigned depth) {
NodePointer genSig, type;
if (node->getNumChildren() == 1) {
genSig = nullptr;
type = node->getChild(0);
} else {
genSig = node->getChild(0);
type = node->getChild(1);
}
if (genSig) {
RETURN_IF_ERROR(mangle(genSig, depth + 1));
}
RETURN_IF_ERROR(mangle(type, depth + 1));
if (genSig)
Buffer << "XG";
else
Buffer << "Xg";
return ManglingError::Success;
}
ManglingError Remangler::mangleHasSymbolQuery(Node *node, unsigned depth) {
Buffer << "TwS";
return ManglingError::Success;
}
ManglingError Remangler::mangleSymbolicExtendedExistentialType(Node *node,
unsigned int depth) {
RETURN_IF_ERROR(mangle(node->getChild(0), depth+1));
for (auto arg: *node->getChild(1))
RETURN_IF_ERROR(mangle(arg, depth+1));
if (node->getNumChildren() > 2)
for (auto conf: *node->getChild(2))
RETURN_IF_ERROR(mangle(conf, depth+1));
return ManglingError::Success;
}
ManglingError Remangler::
mangleUniqueExtendedExistentialTypeShapeSymbolicReference(Node *node,
unsigned int depth) {
// We don't support absolute references in the mangling of these
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
ManglingError Remangler::
mangleNonUniqueExtendedExistentialTypeShapeSymbolicReference(Node *node,
unsigned int depth) {
// 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.
ManglingErrorOr<std::string> Demangle::mangleNode(NodePointer node,
ManglingFlavor Flavor) {
return mangleNode(node, [](SymbolicReferenceKind, const void *) -> NodePointer {
return nullptr;
}, Flavor);
// unreachable("should not try to mangle a symbolic reference; "
// "resolve it to a non-symbolic demangling tree instead");
}
ManglingErrorOr<std::string> Demangle::mangleNode(NodePointer node,
SymbolicResolver resolver,
ManglingFlavor Flavor) {
if (!node) return std::string();
NodeFactory Factory;
Remangler remangler(resolver, Factory, Flavor);
ManglingError err = remangler.mangle(node, 0);
if (!err.isSuccess())
return err;
return remangler.str();
}
ManglingErrorOr<llvm::StringRef> Demangle::mangleNode(NodePointer node,
SymbolicResolver resolver,
NodeFactory &Factory,
ManglingFlavor Flavor) {
if (!node)
return StringRef();
Remangler remangler(resolver, Factory, Flavor);
ManglingError err = remangler.mangle(node, 0);
if (!err.isSuccess())
return err;
return remangler.getBufferStr();
}
bool Demangle::isSpecialized(Node *node) {
// We shouldn't get here with node being NULL; if we do, assert in debug,
// or return false at runtime (which should at least help diagnose things
// further if it happens).
assert(node);
if (!node)
return false;
switch (node->getKind()) {
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericTypeAlias:
case Node::Kind::BoundGenericProtocol:
case Node::Kind::BoundGenericFunction:
case Node::Kind::ConstrainedExistential:
return true;
case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Class:
case Node::Kind::TypeAlias:
case Node::Kind::OtherNominalType:
case Node::Kind::Protocol:
case Node::Kind::Function:
case Node::Kind::Allocator:
case Node::Kind::Constructor:
case Node::Kind::Destructor:
case Node::Kind::Variable:
case Node::Kind::Subscript:
case Node::Kind::ExplicitClosure:
case Node::Kind::ImplicitClosure:
case Node::Kind::Initializer:
case Node::Kind::PropertyWrapperBackingInitializer:
case Node::Kind::PropertyWrapperInitFromProjectedValue:
case Node::Kind::DefaultArgumentInitializer:
case Node::Kind::Getter:
case Node::Kind::Setter:
case Node::Kind::WillSet:
case Node::Kind::DidSet:
case Node::Kind::ReadAccessor:
case Node::Kind::ModifyAccessor:
case Node::Kind::UnsafeAddressor:
case Node::Kind::UnsafeMutableAddressor:
case Node::Kind::Static:
assert(node->getNumChildren() > 0);
return node->getNumChildren() > 0 && isSpecialized(node->getChild(0));
case Node::Kind::Extension:
assert(node->getNumChildren() > 1);
return node->getNumChildren() > 1 && isSpecialized(node->getChild(1));
default:
return false;
}
}
ManglingErrorOr<NodePointer> Demangle::getUnspecialized(Node *node,
NodeFactory &Factory) {
unsigned NumToCopy = 2;
switch (node->getKind()) {
case Node::Kind::Function:
case Node::Kind::Getter:
case Node::Kind::Setter:
case Node::Kind::WillSet:
case Node::Kind::DidSet:
case Node::Kind::ReadAccessor:
case Node::Kind::ModifyAccessor:
case Node::Kind::UnsafeAddressor:
case Node::Kind::UnsafeMutableAddressor:
case Node::Kind::Allocator:
case Node::Kind::Constructor:
case Node::Kind::Destructor:
case Node::Kind::Variable:
case Node::Kind::Subscript:
case Node::Kind::ExplicitClosure:
case Node::Kind::ImplicitClosure:
case Node::Kind::Initializer:
case Node::Kind::PropertyWrapperBackingInitializer:
case Node::Kind::PropertyWrapperInitFromProjectedValue:
case Node::Kind::DefaultArgumentInitializer:
case Node::Kind::Static:
NumToCopy = node->getNumChildren();
LLVM_FALLTHROUGH;
case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Class:
case Node::Kind::TypeAlias:
case Node::Kind::OtherNominalType: {
NodePointer result = Factory.createNode(node->getKind());
DEMANGLER_ASSERT(node->hasChildren(), node);
NodePointer parentOrModule = node->getChild(0);
if (isSpecialized(parentOrModule)) {
auto unspec = getUnspecialized(parentOrModule, Factory);
if (!unspec.isSuccess())
return unspec;
parentOrModule = unspec.result();
}
result->addChild(parentOrModule, Factory);
for (unsigned Idx = 1; Idx < NumToCopy; ++Idx) {
result->addChild(node->getChild(Idx), Factory);
}
return result;
}
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericProtocol:
case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericTypeAlias: {
DEMANGLER_ASSERT(node->hasChildren(), node);
NodePointer unboundType = node->getChild(0);
DEMANGLER_ASSERT(unboundType->getKind() == Node::Kind::Type, unboundType);
DEMANGLER_ASSERT(unboundType->hasChildren(), unboundType);
NodePointer nominalType = unboundType->getChild(0);
if (isSpecialized(nominalType))
return getUnspecialized(nominalType, Factory);
return nominalType;
}
case Node::Kind::ConstrainedExistential: {
DEMANGLER_ASSERT(node->hasChildren(), node);
NodePointer unboundType = node->getChild(0);
DEMANGLER_ASSERT(unboundType->getKind() == Node::Kind::Type, unboundType);
return unboundType;
}
case Node::Kind::BoundGenericFunction: {
DEMANGLER_ASSERT(node->hasChildren(), node);
NodePointer unboundFunction = node->getChild(0);
DEMANGLER_ASSERT(unboundFunction->getKind() == Node::Kind::Function ||
unboundFunction->getKind() ==
Node::Kind::Constructor,
unboundFunction);
if (isSpecialized(unboundFunction))
return getUnspecialized(unboundFunction, Factory);
return unboundFunction;
}
case Node::Kind::Extension: {
DEMANGLER_ASSERT(node->getNumChildren() >= 2, node);
NodePointer parent = node->getChild(1);
if (!isSpecialized(parent))
return node;
auto unspec = getUnspecialized(parent, Factory);
if (!unspec.isSuccess())
return unspec.error();
NodePointer result = Factory.createNode(Node::Kind::Extension);
result->addChild(node->getFirstChild(), Factory);
result->addChild(unspec.result(), Factory);
if (node->getNumChildren() == 3) {
// Add the generic signature of the extension.
result->addChild(node->getChild(2), Factory);
}
return result;
}
default:
return MANGLING_ERROR(ManglingError::BadNominalTypeKind, node);
}
}