Files
swift-mirror/lib/Demangling/Remangler.cpp
Nate Chandler bdef1cef23 [metadata prespecialization] Support for classes.
When generic metadata for a class is requested in the same module where
the class is defined, rather than a call to the generic metadata
accessor or to a variant of typeForMangledNode, a call to a new
accessor--a canonical specialized generic metadata accessor--is emitted.
The new function is defined schematically as follows:

    MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) {
      (void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete)
      (void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete)
      ...
      (void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete)
      auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`);
      return {metadata, MetadataState::Complete};
    }

where generic_argument_class(C<K>, N) denotes the Nth generic argument
which is both (1) itself a specialized generic type and is also (2) a
class.  These calls to the specialized metadata accessors for these
related types ensure that all generic class types are registered with
the Objective-C runtime.

To enable these new canonical specialized generic metadata accessors,
metadata for generic classes is prespecialized as needed. So are the
metaclasses and the corresponding rodata.

Previously, the lazy objc naming hook was registered during process
execution when the first generic class metadata was instantiated. Since
that instantiation may occur "before process launch" (i.e. if the
generic metadata is prespecialized), the lazy naming hook is now
installed at process launch.
2020-05-29 13:20:33 -07:00

2706 lines
75 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 "swift/Demangling/Demangler.h"
#include "swift/Demangling/Punycode.h"
#include "swift/Demangling/ManglingUtils.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/AST/Ownership.h"
#include "swift/Strings.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "RemanglerBase.h"
#include <cstdio>
#include <cstdlib>
using namespace swift;
using namespace Demangle;
using namespace Mangle;
[[noreturn]]
static void unreachable(const char *Message) {
fprintf(stderr, "fatal error: %s\n", Message);
std::abort();
}
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;
}
void SubstitutionEntry::deepHash(Node *node) {
if (treatAsIdentifier) {
combineHash((size_t) Node::Kind::Identifier);
assert(node->hasText());
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
for (char c : node->getText()) {
combineHash((unsigned char)translateOperatorChar(c));
}
return;
default:
break;
}
} else {
combineHash((size_t) node->getKind());
}
if (node->hasIndex()) {
combineHash(node->getIndex());
} else if (node->hasText()) {
for (char c : node->getText()) {
combineHash((unsigned char) c);
}
}
for (Node *child : *node) {
deepHash(child);
}
}
bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const {
if (lhs->getKind() != rhs->getKind())
return false;
if (lhs->hasIndex()) {
if (!rhs->hasIndex())
return false;
if (lhs->getIndex() != rhs->getIndex())
return false;
} else if (lhs->hasText()) {
if (!rhs->hasText())
return false;
if (lhs->getText() != rhs->getText())
return false;
} else if (rhs->hasIndex() || rhs->hasText()) {
return false;
}
if (lhs->getNumChildren() != rhs->getNumChildren())
return false;
for (auto li = lhs->begin(), ri = rhs->begin(), le = lhs->end();
li != le; ++li, ++ri) {
if (!deepEquals(*li, *ri))
return false;
}
return true;
}
// 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 bool UsePunycode = true;
Vector<SubstitutionWord> Words;
Vector<WordReplacement> SubstWordsInIdent;
static const size_t MaxNumWords = 26;
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;
}
};
};
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);
}
void mangleIndex(Node::IndexType value) {
if (value == 0) {
Buffer << '_';
} else {
Buffer << (value - 1) << '_';
}
}
void mangleDependentConformanceIndex(Node *node);
void mangleChildNodes(Node *node) {
mangleNodes(node->begin(), node->end());
}
void mangleChildNodesReversed(Node *node) {
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
mangleChildNode(node, Num - Idx - 1);
}
}
void mangleListSeparator(bool &isFirstListItem) {
if (isFirstListItem) {
Buffer << '_';
isFirstListItem = false;
}
}
void mangleEndOfList(bool isFirstListItem) {
if (isFirstListItem)
Buffer << 'y';
}
void mangleNodes(Node::iterator i, Node::iterator e) {
for (; i != e; ++i) {
mangle(*i);
}
}
void mangleSingleChildNode(Node *node) {
assert(node->getNumChildren() == 1);
mangle(*node->begin());
}
void mangleChildNode(Node *node, unsigned index) {
assert(index < node->getNumChildren());
mangle(node->begin()[index]);
}
void manglePureProtocol(Node *Proto) {
Proto = skipType(Proto);
if (mangleStandardSubstitution(Proto))
return;
mangleChildNodes(Proto);
}
void mangleProtocolList(Node *protocols, Node *superclass,
bool hasExplicitAnyObject);
bool trySubstitution(Node *node, SubstitutionEntry &entry,
bool treatAsIdentifier = false);
void mangleIdentifierImpl(Node *node, bool isOperator);
bool mangleStandardSubstitution(Node *node);
void mangleDependentGenericParamIndex(Node *node,
const char *nonZeroPrefix = "",
char zeroOp = 'z');
std::pair<int, Node *> mangleConstrainedType(Node *node);
void mangleFunctionSignature(Node *FuncType) {
mangleChildNodesReversed(FuncType);
}
void mangleAnyNominalType(Node *node);
void mangleAnyGenericType(Node *node, StringRef TypeOp);
void mangleGenericArgs(Node *node, char &Separator,
bool fullSubstitutionMap=false);
void mangleAnyConstructor(Node *node, char kindOp);
void mangleAbstractStorage(Node *node, StringRef accessorCode);
void mangleAnyProtocolConformance(Node *node);
void mangleKeyPathThunkHelper(Node *node, StringRef op);
#define NODE(ID) \
void mangle##ID(Node *node);
#define CONTEXT_NODE(ID) \
void mangle##ID(Node *node); \
// void mangle##ID(Node *node, EntityContext &ctx);
#include "swift/Demangling/DemangleNodes.def"
public:
Remangler(SymbolicResolver Resolver, NodeFactory &Factory)
: RemanglerBase(Factory), Resolver(Resolver) { }
void mangle(Node *node) {
switch (node->getKind()) {
#define NODE(ID) case Node::Kind::ID: return mangle##ID(node);
#include "swift/Demangling/DemangleNodes.def"
}
unreachable("bad demangling tree node");
}
};
bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
bool treatAsIdentifier) {
if (mangleStandardSubstitution(node))
return true;
// Go ahead and initialize the substitution entry.
entry.setNode(node, treatAsIdentifier);
int Idx = findSubstitution(entry);
if (Idx < 0)
return false;
if (Idx >= 26) {
Buffer << 'A';
mangleIndex(Idx - 26);
return true;
}
char Subst = Idx + 'A';
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::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 (char Subst = getStandardTypeSubst(node->getChild(1)->getText())) {
if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ true)) {
Buffer << 'S' << Subst;
}
return true;
}
return false;
}
void Remangler::mangleDependentGenericParamIndex(Node *node,
const char *nonZeroPrefix,
char zeroOp) {
auto depth = node->getChild(0)->getIndex();
auto index = node->getChild(1)->getIndex();
if (depth != 0) {
Buffer << nonZeroPrefix << 'd';
mangleIndex(depth - 1);
mangleIndex(index);
return;
}
if (index != 0) {
Buffer << nonZeroPrefix;
mangleIndex(index - 1);
return;
}
// depth == index == 0
Buffer << zeroOp;
}
std::pair<int, Node *> Remangler::mangleConstrainedType(Node *node) {
if (node->getKind() == Node::Kind::Type)
node = getChildOfType(node);
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return {-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) {
mangle(node);
node = nullptr;
}
const char *ListSeparator = (Chain.size() > 1 ? "_" : "");
for (unsigned i = 1, n = Chain.size(); i <= n; ++i) {
Node *DepAssocTyRef = Chain[n - i];
mangle(DepAssocTyRef);
Buffer << ListSeparator;
ListSeparator = "";
}
if (!Chain.empty())
addSubstitution(entry);
return {(int)Chain.size(), node};
}
void Remangler::mangleAnyGenericType(Node *node, StringRef TypeOp) {
SubstitutionEntry entry;
if (trySubstitution(node, entry)) return;
mangleChildNodes(node);
Buffer << TypeOp;
addSubstitution(entry);
}
void Remangler::mangleAnyNominalType(Node *node) {
if (isSpecialized(node)) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return;
NodePointer unboundType = getUnspecialized(node, Factory);
mangleAnyNominalType(unboundType);
char Separator = 'y';
mangleGenericArgs(node, Separator);
if (node->getNumChildren() == 3) {
// Retroactive conformances.
auto listNode = node->getChild(2);
for (size_t Idx = 0, Num = listNode->getNumChildren(); Idx < Num; ++Idx) {
mangle(listNode->getChild(Idx));
}
}
Buffer << 'G';
addSubstitution(entry);
return;
}
switch (node->getKind()) {
case Node::Kind::Structure: return mangleAnyGenericType(node, "V");
case Node::Kind::Enum: return mangleAnyGenericType(node, "O");
case Node::Kind::Class: return mangleAnyGenericType(node, "C");
case Node::Kind::OtherNominalType: return mangleAnyGenericType(node, "XY");
case Node::Kind::TypeAlias: return mangleAnyGenericType(node, "a");
default:
unreachable("bad nominal type kind");
}
}
void Remangler::mangleGenericArgs(Node *node, char &Separator,
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;
mangleGenericArgs(node->getChild(0), Separator,
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:
if (!fullSubstitutionMap)
break;
mangleGenericArgs(node->getChild(0), Separator,
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);
assert(unboundType->getKind() == Node::Kind::Type);
NodePointer nominalType = unboundType->getChild(0);
NodePointer parentOrModule = nominalType->getChild(0);
mangleGenericArgs(parentOrModule, Separator,
fullSubstitutionMap);
Buffer << Separator;
Separator = '_';
mangleChildNodes(node->getChild(1));
break;
}
case Node::Kind::BoundGenericFunction: {
fullSubstitutionMap = true;
NodePointer unboundFunction = node->getChild(0);
assert(unboundFunction->getKind() == Node::Kind::Function ||
unboundFunction->getKind() == Node::Kind::Constructor);
NodePointer parentOrModule = unboundFunction->getChild(0);
mangleGenericArgs(parentOrModule, Separator,
fullSubstitutionMap);
Buffer << Separator;
Separator = '_';
mangleChildNodes(node->getChild(1));
break;
}
case Node::Kind::Extension:
mangleGenericArgs(node->getChild(1), Separator,
fullSubstitutionMap);
break;
default:
break;
}
}
void Remangler::mangleAbstractStorage(Node *node, StringRef accessorCode) {
mangleChildNodes(node);
switch (node->getKind()) {
case Node::Kind::Subscript: Buffer << "i"; break;
case Node::Kind::Variable: Buffer << "v"; break;
default: unreachable("Not a storage node");
}
Buffer << accessorCode;
}
void Remangler::mangleAllocator(Node *node) {
mangleAnyConstructor(node, 'C');
}
void Remangler::mangleArgumentTuple(Node *node) {
Node *Child = skipType(getSingleChild(node));
if (Child->getKind() == Node::Kind::Tuple &&
Child->getNumChildren() == 0) {
Buffer << 'y';
return;
}
mangle(Child);
}
void Remangler::mangleAssociatedType(Node *node) {
unreachable("unsupported node");
}
void Remangler::mangleAssociatedTypeRef(Node *node) {
SubstitutionEntry entry;
if (trySubstitution(node, entry)) return;
mangleChildNodes(node);
Buffer << "Qa";
addSubstitution(entry);
}
void Remangler::mangleAssociatedTypeDescriptor(Node *node) {
mangleChildNodes(node);
Buffer << "Tl";
}
void Remangler::mangleAssociatedConformanceDescriptor(Node *node) {
mangle(node->getChild(0));
mangle(node->getChild(1));
manglePureProtocol(node->getChild(2));
Buffer << "Tn";
}
void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) {
mangle(node->getChild(0));
mangle(node->getChild(1));
manglePureProtocol(node->getChild(2));
Buffer << "TN";
}
void Remangler::mangleBaseConformanceDescriptor(Node *node) {
mangle(node->getChild(0));
manglePureProtocol(node->getChild(1));
Buffer << "Tb";
}
void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
mangleChildNodes(node); // protocol conformance, identifier
Buffer << "Wt";
}
void Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node) {
mangleChildNodes(node); // protocol conformance, identifier
Buffer << "TM";
}
void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
mangleChildNodes(node); // protocol conformance, type, protocol
Buffer << "WT";
}
void Remangler::mangleBaseWitnessTableAccessor(Node *node) {
mangleChildNodes(node); // protocol conformance, protocol
Buffer << "Wb";
}
void Remangler::mangleAutoClosureType(Node *node) {
mangleChildNodesReversed(node); // argument tuple, result type
Buffer << "XK";
}
void Remangler::mangleEscapingAutoClosureType(Node *node) {
mangleChildNodesReversed(node); // argument tuple, result type
Buffer << "XA";
}
void Remangler::mangleNoEscapeFunctionType(Node *node) {
mangleChildNodesReversed(node); // argument tuple, result type
Buffer << "XE";
}
void Remangler::mangleBoundGenericClass(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericEnum(Node *node) {
Node *Enum = node->getChild(0)->getChild(0);
assert(Enum->getKind() == Node::Kind::Enum);
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;
mangleSingleChildNode(node->getChild(1));
Buffer << "Sg";
addSubstitution(entry);
return;
}
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericStructure(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericOtherNominalType(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericProtocol(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericTypeAlias(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleBoundGenericFunction(Node *node) {
SubstitutionEntry entry;
if (trySubstitution(node, entry))
return;
NodePointer unboundFunction = getUnspecialized(node, Factory);
mangleFunction(unboundFunction);
char Separator = 'y';
mangleGenericArgs(node, Separator);
Buffer << 'G';
addSubstitution(entry);
}
void Remangler::mangleBuiltinTypeName(Node *node) {
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_SILTOKEN) {
Buffer << 't';
} else if (text == BUILTIN_TYPE_NAME_INTLITERAL) {
Buffer << 'I';
} else if (text == BUILTIN_TYPE_NAME_WORD) {
Buffer << 'w';
} 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 {
unreachable("unexpected builtin vector type");
}
Buffer << "Bv" << text.substr(0, splitIdx) << '_';
} else {
unreachable("unexpected builtin type");
}
}
void Remangler::mangleCFunctionPointer(Node *node) {
mangleChildNodesReversed(node); // argument tuple, result type
Buffer << "XC";
}
void Remangler::mangleClass(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleAnyConstructor(Node *node, char kindOp) {
mangleChildNodes(node);
Buffer << "f" << kindOp;
}
void Remangler::mangleConstructor(Node *node) {
mangleAnyConstructor(node, 'c');
}
void Remangler::mangleCoroutineContinuationPrototype(Node *node) {
mangleChildNodes(node);
Buffer << "TC";
}
void Remangler::mangleDeallocator(Node *node) {
mangleChildNodes(node);
Buffer << "fD";
}
void Remangler::mangleDeclContext(Node *node) {
mangleSingleChildNode(node);
}
void Remangler::mangleDefaultArgumentInitializer(Node *node) {
mangleChildNode(node, 0);
Buffer << "fA";
mangleChildNode(node, 1);
}
void Remangler::mangleDependentAssociatedTypeRef(Node *node) {
mangleIdentifier(node->getFirstChild());
if (node->getNumChildren() > 1)
mangleChildNode(node, 1);
}
void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
Node *ProtoOrClass = node->getChild(1);
if (ProtoOrClass->getFirstChild()->getKind() == Node::Kind::Protocol) {
manglePureProtocol(ProtoOrClass);
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
switch (NumMembersAndParamIdx.first) {
case -1: Buffer << "RQ"; return; // substitution
case 0: Buffer << "R"; break;
case 1: Buffer << "Rp"; break;
default: Buffer << "RP"; break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return;
}
mangle(ProtoOrClass);
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
switch (NumMembersAndParamIdx.first) {
case -1: Buffer << "RB"; return; // substitution
case 0: Buffer << "Rb"; break;
case 1: Buffer << "Rc"; break;
default: Buffer << "RC"; break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
return;
}
void Remangler::mangleDependentGenericParamCount(Node *node) {
unreachable("handled inline in DependentGenericSignature");
}
void Remangler::mangleDependentGenericParamType(Node *node) {
if (node->getChild(0)->getIndex() == 0
&& node->getChild(1)->getIndex() == 0) {
Buffer << 'x';
return;
}
Buffer << 'q';
mangleDependentGenericParamIndex(node);
}
void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
mangleChildNode(node, 1);
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
switch (NumMembersAndParamIdx.first) {
case -1: Buffer << "RS"; return; // substitution
case 0: Buffer << "Rs"; break;
case 1: Buffer << "Rt"; break;
default: Buffer << "RT"; break;
}
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second);
}
void Remangler::mangleDependentGenericLayoutRequirement(Node *node) {
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
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);
assert(node->getChild(1)->getKind() == Node::Kind::Identifier);
assert(node->getChild(1)->getText().size() == 1);
Buffer << node->getChild(1)->getText()[0];
if (node->getNumChildren() >=3)
mangleChildNode(node, 2);
if (node->getNumChildren() >=4)
mangleChildNode(node, 3);
}
void Remangler::mangleDependentGenericSignature(Node *node) {
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
mangleChildNode(node, Idx);
}
}
// If there's only one generic param, mangle nothing.
if (ParamCountEnd == 1 && node->getChild(0)->getIndex() == 1) {
Buffer << 'l';
return;
}
// 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';
}
void Remangler::mangleDependentGenericType(Node *node) {
mangleChildNodesReversed(node); // type, generic signature
Buffer << 'u';
}
void Remangler::mangleDependentMemberType(Node *node) {
auto NumMembersAndParamIdx = mangleConstrainedType(node);
switch (NumMembersAndParamIdx.first) {
case -1:
break; // substitution
case 0:
unreachable("wrong dependent member type");
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;
}
}
void Remangler::mangleDependentPseudogenericSignature(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleDestructor(Node *node) {
mangleChildNodes(node);
Buffer << "fd";
}
void Remangler::mangleDidSet(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "W");
}
void Remangler::mangleDirectness(Node *node) {
if (node->getIndex() == unsigned(Directness::Direct)) {
Buffer << 'd';
} else {
assert(node->getIndex() == unsigned(Directness::Indirect));
Buffer << 'i';
}
}
void Remangler::mangleDynamicAttribute(Node *node) {
Buffer << "TD";
}
void Remangler::mangleDirectMethodReferenceAttribute(Node *node) {
Buffer << "Td";
}
void Remangler::mangleDynamicSelf(Node *node) {
mangleSingleChildNode(node); // type
Buffer << "XD";
}
void Remangler::mangleEnum(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleErrorType(Node *node) {
Buffer << "Xe";
}
void Remangler::mangleExistentialMetatype(Node *node) {
if (node->getFirstChild()->getKind() == Node::Kind::MetatypeRepresentation) {
mangleChildNode(node, 1);
Buffer << "Xm";
mangleChildNode(node, 0);
} else {
mangleSingleChildNode(node);
Buffer << "Xp";
}
}
void Remangler::mangleExplicitClosure(Node *node) {
mangleChildNode(node, 0); // context
mangleChildNode(node, 2); // type
Buffer << "fU";
mangleChildNode(node, 1); // index
}
void Remangler::mangleExtension(Node *node) {
mangleChildNode(node, 1);
mangleChildNode(node, 0);
if (node->getNumChildren() == 3)
mangleChildNode(node, 2); // generic signature
Buffer << 'E';
}
void Remangler::mangleAnonymousContext(Node *node) {
mangleChildNode(node, 1);
mangleChildNode(node, 0);
if (node->getNumChildren() >= 3)
mangleTypeList(node->getChild(2));
Buffer << "XZ";
}
void Remangler::mangleFieldOffset(Node *node) {
mangleChildNode(node, 1); // variable
Buffer << "Wv";
mangleChildNode(node, 0); // directness
}
void Remangler::mangleEnumCase(Node *node) {
mangleSingleChildNode(node); // enum case
Buffer << "WC";
}
void Remangler::mangleFullTypeMetadata(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mf";
}
void Remangler::mangleFunction(Node *node) {
mangleChildNode(node, 0); // context
mangleChildNode(node, 1); // name
bool hasLabels = node->getChild(2)->getKind() == Node::Kind::LabelList;
Node *FuncType = getSingleChild(node->getChild(hasLabels ? 3 : 2));
if (hasLabels)
mangleChildNode(node, 2); // parameter labels
if (FuncType->getKind() == Node::Kind::DependentGenericType) {
mangleFunctionSignature(getSingleChild(FuncType->getChild(1)));
mangleChildNode(FuncType, 0); // generic signature
} else {
mangleFunctionSignature(FuncType);
}
Buffer << "F";
}
void Remangler::mangleFunctionSignatureSpecialization(Node *node) {
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:
mangleIdentifier(Param->getChild(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);
}
mangleIdentifier(TextNd);
break;
}
case FunctionSigSpecializationParamKind::ClosureProp:
mangleIdentifier(Param->getChild(1));
for (unsigned i = 2, e = Param->getNumChildren(); i != e; ++i) {
mangleType(Param->getChild(i));
}
break;
default:
break;
}
}
}
Buffer << "Tf";
bool returnValMangled = false;
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::FunctionSignatureSpecializationReturn) {
Buffer << '_';
returnValMangled = true;
}
mangle(Child);
if (Child->getKind() == Node::Kind::SpecializationPassID &&
node->hasIndex()) {
Buffer << node->getIndex();
}
}
if (!returnValMangled)
Buffer << "_n";
}
void Remangler::mangleFunctionSignatureSpecializationReturn(Node *node) {
mangleFunctionSignatureSpecializationParam(node);
}
void Remangler::mangleFunctionSignatureSpecializationParam(Node *node) {
if (!node->hasChildren()) {
Buffer << 'n';
return;
}
// 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";
return;
case FunctionSigSpecializationParamKind::ConstantPropGlobal:
Buffer << "pg";
return;
case FunctionSigSpecializationParamKind::ConstantPropInteger:
Buffer << "pi" << node->getChild(1)->getText();
return;
case FunctionSigSpecializationParamKind::ConstantPropFloat:
Buffer << "pd" << node->getChild(1)->getText();
return;
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 {
unreachable("Unknown encoding");
}
return;
}
case FunctionSigSpecializationParamKind::ClosureProp:
Buffer << 'c';
return;
case FunctionSigSpecializationParamKind::BoxToValue:
Buffer << 'i';
return;
case FunctionSigSpecializationParamKind::BoxToStack:
Buffer << 's';
return;
case FunctionSigSpecializationParamKind::SROA:
Buffer << 'x';
return;
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';
return;
}
}
void Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << 'c';
}
void Remangler::mangleDifferentiableFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << "XF";
}
void Remangler::mangleEscapingDifferentiableFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << "XG";
}
void Remangler::mangleLinearFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << "XH";
}
void Remangler::mangleEscapingLinearFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << "XI";
}
void Remangler::mangleGenericProtocolWitnessTable(Node *node) {
mangleSingleChildNode(node);
Buffer << "WG";
}
void Remangler::mangleGenericProtocolWitnessTableInstantiationFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "WI";
}
void Remangler::mangleResilientProtocolWitnessTable(Node *node) {
mangleSingleChildNode(node);
Buffer << "Wr";
}
void Remangler::mangleGenericPartialSpecialization(Node *node) {
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::GenericSpecializationParam) {
mangleChildNode(Child, 0);
break;
}
}
Buffer << (node->getKind() ==
Node::Kind::GenericPartialSpecializationNotReAbstracted ? "TP" : "Tp");
for (NodePointer Child : *node) {
if (Child->getKind() != Node::Kind::GenericSpecializationParam)
mangle(Child);
}
}
void Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node) {
mangleGenericPartialSpecialization(node);
}
void Remangler::mangleGenericSpecialization(Node *node) {
bool FirstParam = true;
for (NodePointer Child : *node) {
if (Child->getKind() == Node::Kind::GenericSpecializationParam) {
mangleChildNode(Child, 0);
mangleListSeparator(FirstParam);
}
}
assert(!FirstParam && "generic specialization with no substitutions");
switch (node->getKind()) {
case Node::Kind::GenericSpecialization:
Buffer << "Tg";
break;
case Node::Kind::GenericSpecializationNotReAbstracted:
Buffer << "TG";
break;
case Node::Kind::InlinedGenericFunction:
Buffer << "Ti";
break;
default:
unreachable("unsupported node");
}
for (NodePointer Child : *node) {
if (Child->getKind() != Node::Kind::GenericSpecializationParam)
mangle(Child);
}
}
void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
mangleGenericSpecialization(node);
}
void Remangler::mangleInlinedGenericFunction(Node *node) {
mangleGenericSpecialization(node);
}
void Remangler::mangleGenericSpecializationParam(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleGenericTypeMetadataPattern(Node *node) {
mangleSingleChildNode(node);
Buffer << "MP";
}
void Remangler::mangleGenericTypeParamDecl(Node *node) {
mangleChildNodes(node);
Buffer << "fp";
}
void Remangler::mangleGetter(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "g");
}
void Remangler::mangleGlobal(Node *node) {
Buffer << MANGLING_PREFIX_STR;
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::GenericSpecializationNotReAbstracted:
case Node::Kind::InlinedGenericFunction:
case Node::Kind::GenericPartialSpecialization:
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
case Node::Kind::OutlinedBridgedMethod:
case Node::Kind::OutlinedVariable:
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::DynamicallyReplaceableFunctionKey:
case Node::Kind::DynamicallyReplaceableFunctionImpl:
case Node::Kind::DynamicallyReplaceableFunctionVar:
mangleInReverseOrder = true;
break;
default:
mangle(Child);
if (mangleInReverseOrder) {
auto ReverseIter = Iter;
while (ReverseIter != node->begin()) {
--ReverseIter;
mangle(*ReverseIter);
}
mangleInReverseOrder = false;
}
break;
}
}
}
void Remangler::mangleGlobalGetter(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "G");
}
void Remangler::mangleIdentifier(Node *node) {
mangleIdentifierImpl(node, /*isOperator*/ false);
}
void Remangler::mangleIndex(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleUnknownIndex(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleIVarInitializer(Node *node) {
mangleSingleChildNode(node);
Buffer << "fe";
}
void Remangler::mangleIVarDestroyer(Node *node) {
mangleSingleChildNode(node);
Buffer << "fE";
}
void Remangler::mangleImplDifferentiable(Node *node) {
Buffer << 'd';
}
void Remangler::mangleImplLinear(Node *node) {
Buffer << 'l';
}
void Remangler::mangleImplEscaping(Node *node) {
Buffer << 'e';
}
void Remangler::mangleImplConvention(Node *node) {
char ConvCh = llvm::StringSwitch<char>(node->getText())
.Case("@callee_unowned", 'y')
.Case("@callee_guaranteed", 'g')
.Case("@callee_owned", 'x')
.Default(0);
assert(ConvCh && "invalid impl callee convention");
Buffer << ConvCh;
}
void Remangler::mangleImplDifferentiability(Node *node) {
assert(node->hasText());
// Empty string represents default differentiability.
if (node->getText().empty())
return;
char diffChar = llvm::StringSwitch<char>(node->getText())
.Case("@noDerivative", 'w')
.Default(0);
assert(diffChar && "Invalid impl differentiability");
Buffer << diffChar;
}
void Remangler::mangleImplFunctionAttribute(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplInvocationSubstitutions(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplPatternSubstitutions(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplFunctionType(Node *node) {
const char *PseudoGeneric = "";
Node *GenSig = nullptr;
Node *PatternSubs = nullptr;
Node *InvocationSubs = nullptr;
for (NodePointer Child : *node) {
switch (auto kind = 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.
assert(Child->getNumChildren() == 2 || Child->getNumChildren() == 3);
mangle(Child->getLastChild());
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)
mangle(GenSig);
if (InvocationSubs) {
Buffer << 'y';
mangleChildNodes(InvocationSubs->getChild(0));
if (InvocationSubs->getNumChildren() >= 2)
mangleRetroactiveConformance(InvocationSubs->getChild(1));
}
if (PatternSubs) {
mangle(PatternSubs->getChild(0));
Buffer << 'y';
mangleChildNodes(PatternSubs->getChild(1));
if (PatternSubs->getNumChildren() >= 3)
mangleRetroactiveConformance(PatternSubs->getChild(2));
}
Buffer << 'I';
if (PatternSubs)
Buffer << 's';
if (InvocationSubs)
Buffer << 'I';
Buffer << PseudoGeneric;
for (NodePointer Child : *node) {
switch (Child->getKind()) {
case Node::Kind::ImplDifferentiable:
Buffer << 'd';
break;
case Node::Kind::ImplLinear:
Buffer << 'l';
break;
case Node::Kind::ImplEscaping:
Buffer << 'e';
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);
assert(ConvCh && "invalid impl callee convention");
Buffer << ConvCh;
break;
}
case Node::Kind::ImplFunctionAttribute: {
char FuncAttr = llvm::StringSwitch<char>(Child->getText())
.Case("@convention(block)", 'B')
.Case("@convention(c)", 'C')
.Case("@convention(method)", 'M')
.Case("@convention(objc_method)", 'O')
.Case("@convention(closure)", 'K')
.Case("@convention(witness_method)", 'W')
.Case("@yield_once", 'A')
.Case("@yield_many", 'G')
.Default(0);
assert(FuncAttr && "invalid impl function attribute");
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_constant", 'c')
.Case("@owned", 'x')
.Case("@guaranteed", 'g')
.Case("@deallocating", 'e')
.Case("@unowned", 'y')
.Default(0);
assert(ConvCh && "invalid impl parameter convention");
Buffer << ConvCh;
// Mangle parameter differentiability, if it exists.
if (Child->getNumChildren() == 3)
mangleImplDifferentiability(Child->getChild(1));
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')
.Default(0);
assert(ConvCh && "invalid impl parameter convention");
Buffer << ConvCh;
break;
}
default:
break;
}
}
Buffer << '_';
}
void Remangler::mangleImplicitClosure(Node *node) {
mangleChildNode(node, 0); // context
mangleChildNode(node, 2); // type
Buffer << "fu";
mangleChildNode(node, 1); // index
}
void Remangler::mangleImplParameter(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplResult(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplYield(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleImplErrorResult(Node *node) {
unreachable("handled inline");
}
void Remangler::mangleInOut(Node *node) {
mangleSingleChildNode(node);
Buffer << 'z';
}
void Remangler::mangleShared(Node *node) {
mangleSingleChildNode(node);
Buffer << 'h';
}
void Remangler::mangleOwned(Node *node) {
mangleSingleChildNode(node);
Buffer << 'n';
}
void Remangler::mangleInfixOperator(Node *node) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "oi";
}
void Remangler::mangleInitializer(Node *node) {
mangleChildNodes(node);
Buffer << "fi";
}
void Remangler::manglePropertyWrapperBackingInitializer(Node *node) {
mangleChildNodes(node);
Buffer << "fP";
}
void Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node) {
mangleChildNodes(node);
Buffer << "Wl";
}
void Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node) {
mangleChildNodes(node);
Buffer << "WL";
}
void Remangler::mangleLocalDeclName(Node *node) {
mangleChildNode(node, 1); // identifier
Buffer << 'L';
mangleChildNode(node, 0); // index
}
void Remangler::mangleMaterializeForSet(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "m");
}
void Remangler::mangleMetatype(Node *node) {
if (node->getFirstChild()->getKind() == Node::Kind::MetatypeRepresentation) {
mangleChildNode(node, 1);
Buffer << "XM";
mangleChildNode(node, 0);
} else {
mangleSingleChildNode(node);
Buffer << 'm';
}
}
void Remangler::mangleMetatypeRepresentation(Node *node) {
if (node->getText() == "@thin") {
Buffer << 't';
} else if (node->getText() == "@thick") {
Buffer << 'T';
} else if (node->getText() == "@objc_metatype") {
Buffer << 'o';
} else {
unreachable("wrong metatype representation");
}
}
void Remangler::mangleMetaclass(Node *node) {
mangleChildNodes(node);
Buffer << "Mm";
}
void Remangler::mangleModifyAccessor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "M");
}
void Remangler::mangleModule(Node *node) {
if (node->getText() == STDLIB_NAME) {
Buffer << 's';
} else if (node->getText() == MANGLING_MODULE_OBJC) {
Buffer << "So";
} else if (node->getText() == MANGLING_MODULE_CLANG_IMPORTER) {
Buffer << "SC";
} else {
mangleIdentifier(node);
}
}
void Remangler::mangleNativeOwningAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "lo");
}
void Remangler::mangleNativeOwningMutableAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "ao");
}
void Remangler::mangleNativePinningAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "lp");
}
void Remangler::mangleNativePinningMutableAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "aP");
}
void Remangler::mangleClassMetadataBaseOffset(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mo";
}
void Remangler::mangleNominalTypeDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mn";
}
void Remangler::mangleOpaqueTypeDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "MQ";
}
void Remangler::mangleOpaqueTypeDescriptorAccessor(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mg";
}
void Remangler::mangleOpaqueTypeDescriptorAccessorImpl(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mh";
}
void Remangler::mangleOpaqueTypeDescriptorAccessorKey(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mj";
}
void Remangler::mangleOpaqueTypeDescriptorAccessorVar(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mk";
}
void Remangler::manglePropertyDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "MV";
}
void Remangler::mangleNonObjCAttribute(Node *node) {
Buffer << "TO";
}
void Remangler::mangleTuple(Node *node) {
mangleTypeList(node);
Buffer << 't';
}
void Remangler::mangleNumber(Node *node) {
mangleIndex(node->getIndex());
}
void Remangler::mangleObjCAttribute(Node *node) {
Buffer << "To";
}
void Remangler::mangleObjCBlock(Node *node) {
mangleChildNodesReversed(node);
Buffer << "XB";
}
void Remangler::mangleEscapingObjCBlock(Node *node) {
mangleChildNodesReversed(node);
Buffer << "XL";
}
void Remangler::mangleOwningAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "lO");
}
void Remangler::mangleOwningMutableAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "aO");
}
void Remangler::manglePartialApplyForwarder(Node *node) {
mangleChildNodesReversed(node);
Buffer << "TA";
}
void Remangler::manglePartialApplyObjCForwarder(Node *node) {
mangleChildNodesReversed(node);
Buffer << "Ta";
}
void Remangler::mangleMergedFunction(Node *node) {
Buffer << "Tm";
}
void Remangler::mangleDynamicallyReplaceableFunctionImpl(Node *node) {
Buffer << "TI";
}
void Remangler::mangleDynamicallyReplaceableFunctionKey(Node *node) {
Buffer << "Tx";
}
void Remangler::mangleDynamicallyReplaceableFunctionVar(Node *node) {
Buffer << "TX";
}
void Remangler::manglePostfixOperator(Node *node) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "oP";
}
void Remangler::manglePrefixOperator(Node *node) {
mangleIdentifierImpl(node, /*isOperator*/ true);
Buffer << "op";
}
void Remangler::manglePrivateDeclName(Node *node) {
mangleChildNodesReversed(node);
Buffer << (node->getNumChildren() == 1 ? "Ll" : "LL");
}
void Remangler::mangleProtocol(Node *node) {
mangleAnyGenericType(node, "P");
}
void Remangler::mangleRetroactiveConformance(Node *node) {
mangleAnyProtocolConformance(node->getChild(1));
Buffer << 'g';
mangleIndex(node->getChild(0)->getIndex());
}
void Remangler::mangleProtocolConformance(Node *node) {
Node *Ty = getChildOfType(node->getChild(0));
Node *GenSig = nullptr;
if (Ty->getKind() == Node::Kind::DependentGenericType) {
GenSig = Ty->getFirstChild();
Ty = Ty->getChild(1);
}
mangle(Ty);
if (node->getNumChildren() == 4)
mangleChildNode(node, 3);
manglePureProtocol(node->getChild(1));
mangleChildNode(node, 2);
if (GenSig)
mangle(GenSig);
}
void Remangler::mangleProtocolConformanceRefInTypeModule(Node *node) {
manglePureProtocol(node->getChild(0));
Buffer << "HP";
}
void Remangler::mangleProtocolConformanceRefInProtocolModule(Node *node) {
manglePureProtocol(node->getChild(0));
Buffer << "Hp";
}
void Remangler::mangleProtocolConformanceRefInOtherModule(Node *node) {
manglePureProtocol(node->getChild(0));
mangleChildNode(node, 1);
}
void Remangler::mangleConcreteProtocolConformance(Node *node) {
mangleType(node->getChild(0));
mangle(node->getChild(1));
if (node->getNumChildren() > 2)
mangleAnyProtocolConformanceList(node->getChild(2));
else
Buffer << "y";
Buffer << "HC";
}
void Remangler::mangleDependentProtocolConformanceRoot(Node *node) {
mangleType(node->getChild(0));
manglePureProtocol(node->getChild(1));
Buffer << "HD";
mangleDependentConformanceIndex(node->getChild(2));
}
void Remangler::mangleDependentProtocolConformanceInherited(Node *node) {
mangleAnyProtocolConformance(node->getChild(0));
manglePureProtocol(node->getChild(1));
Buffer << "HI";
mangleDependentConformanceIndex(node->getChild(2));
}
void Remangler::mangleDependentAssociatedConformance(Node *node) {
mangleType(node->getChild(0));
manglePureProtocol(node->getChild(1));
}
void Remangler::mangleDependentProtocolConformanceAssociated(Node *node) {
mangleAnyProtocolConformance(node->getChild(0));
mangleDependentAssociatedConformance(node->getChild(1));
Buffer << "HA";
mangleDependentConformanceIndex(node->getChild(2));
}
void Remangler::mangleDependentConformanceIndex(Node *node) {
assert(node->getKind() == Node::Kind::Index ||
node->getKind() == Node::Kind::UnknownIndex);
assert(node->hasIndex() == (node->getKind() == Node::Kind::Index));
mangleIndex(node->hasIndex() ? node->getIndex() + 2 : 1);
}
void Remangler::mangleAnyProtocolConformance(Node *node) {
switch (node->getKind()) {
case Node::Kind::ConcreteProtocolConformance:
return mangleConcreteProtocolConformance(node);
case Node::Kind::DependentProtocolConformanceRoot:
return mangleDependentProtocolConformanceRoot(node);
case Node::Kind::DependentProtocolConformanceInherited:
return mangleDependentProtocolConformanceInherited(node);
case Node::Kind::DependentProtocolConformanceAssociated:
return mangleDependentProtocolConformanceAssociated(node);
default:
break;
}
}
void Remangler::mangleAnyProtocolConformanceList(Node *node) {
bool firstElem = true;
for (NodePointer child : *node) {
mangleAnyProtocolConformance(child);
mangleListSeparator(firstElem);
}
mangleEndOfList(firstElem);
}
void Remangler::mangleProtocolDescriptor(Node *node) {
manglePureProtocol(getSingleChild(node));
Buffer << "Mp";
}
void Remangler::mangleProtocolRequirementsBaseDescriptor(Node *node) {
manglePureProtocol(getSingleChild(node));
Buffer << "TL";
}
void Remangler::mangleProtocolSelfConformanceDescriptor(Node *node) {
manglePureProtocol(node->getChild(0));
Buffer << "MS";
}
void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
mangleProtocolConformance(node->getChild(0));
Buffer << "Mc";
}
void Remangler::mangleProtocolList(Node *node, Node *superclass,
bool hasExplicitAnyObject) {
auto *protocols = getSingleChild(node, Node::Kind::TypeList);
bool FirstElem = true;
for (NodePointer Child : *protocols) {
manglePureProtocol(Child);
mangleListSeparator(FirstElem);
}
mangleEndOfList(FirstElem);
if (superclass) {
mangleType(superclass);
Buffer << "Xc";
return;
} else if (hasExplicitAnyObject) {
Buffer << "Xl";
return;
}
Buffer << 'p';
}
void Remangler::mangleProtocolList(Node *node) {
mangleProtocolList(node, nullptr, false);
}
void Remangler::mangleProtocolListWithClass(Node *node) {
mangleProtocolList(node->getChild(0),
node->getChild(1),
false);
}
void Remangler::mangleProtocolListWithAnyObject(Node *node) {
mangleProtocolList(node->getChild(0), nullptr, true);
}
void Remangler::mangleProtocolSelfConformanceWitness(Node *node) {
mangleSingleChildNode(node);
Buffer << "TS";
}
void Remangler::mangleProtocolWitness(Node *node) {
mangleChildNodes(node);
Buffer << "TW";
}
void Remangler::mangleProtocolSelfConformanceWitnessTable(Node *node) {
manglePureProtocol(node->getChild(0));
Buffer << "WS";
}
void Remangler::mangleProtocolWitnessTable(Node *node) {
mangleSingleChildNode(node);
Buffer << "WP";
}
void Remangler::mangleProtocolWitnessTablePattern(Node *node) {
mangleSingleChildNode(node);
Buffer << "Wp";
}
void Remangler::mangleProtocolWitnessTableAccessor(Node *node) {
mangleSingleChildNode(node);
Buffer << "Wa";
}
void Remangler::mangleReabstractionThunk(Node *node) {
mangleChildNodesReversed(node);
Buffer << "Tr";
}
void Remangler::mangleReabstractionThunkHelper(Node *node) {
mangleChildNodesReversed(node);
Buffer << "TR";
}
void Remangler::mangleReabstractionThunkHelperWithSelf(Node *node) {
mangleChildNodesReversed(node);
Buffer << "Ty";
}
void Remangler::mangleReadAccessor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "r");
}
void Remangler::mangleKeyPathThunkHelper(Node *node, StringRef op) {
for (NodePointer Child : *node)
if (Child->getKind() != Node::Kind::IsSerialized)
mangle(Child);
Buffer << op;
for (NodePointer Child : *node)
if (Child->getKind() == Node::Kind::IsSerialized)
mangle(Child);
}
void Remangler::mangleKeyPathGetterThunkHelper(Node *node) {
mangleKeyPathThunkHelper(node, "TK");
}
void Remangler::mangleKeyPathSetterThunkHelper(Node *node) {
mangleKeyPathThunkHelper(node, "Tk");
}
void Remangler::mangleKeyPathEqualsThunkHelper(Node *node) {
mangleKeyPathThunkHelper(node, "TH");
}
void Remangler::mangleKeyPathHashThunkHelper(Node *node) {
mangleKeyPathThunkHelper(node, "Th");
}
void Remangler::mangleReturnType(Node *node) {
mangleArgumentTuple(node);
}
void Remangler::mangleRelatedEntityDeclName(Node *node) {
mangleChildNode(node, 1);
NodePointer kindNode = node->getFirstChild();
if (kindNode->getText().size() != 1)
unreachable("cannot handle multi-byte related entities");
Buffer << "L" << kindNode->getText();
}
void Remangler::mangleSILBoxType(Node *node) {
mangleSingleChildNode(node);
Buffer << "Xb";
}
void Remangler::mangleSetter(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "s");
}
void Remangler::mangleSpecializationPassID(Node *node) {
Buffer << node->getIndex();
}
void Remangler::mangleIsSerialized(Node *node) {
Buffer << 'q';
}
void Remangler::mangleStatic(Node *node) {
mangleSingleChildNode(node);
Buffer << 'Z';
}
void Remangler::mangleOtherNominalType(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleStructure(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleSubscript(Node *node) {
mangleAbstractStorage(node, "p");
}
void Remangler::mangleSuffix(Node *node) {
// Just add the suffix back on.
Buffer << node->getText();
}
void Remangler::mangleThinFunctionType(Node *node) {
mangleFunctionSignature(node);
Buffer << "Xf";
}
void Remangler::mangleTupleElement(Node *node) {
mangleChildNodesReversed(node); // tuple type, element name?
}
void Remangler::mangleTupleElementName(Node *node) {
mangleIdentifier(node);
}
void Remangler::mangleType(Node *node) {
mangleSingleChildNode(node);
}
void Remangler::mangleTypeAlias(Node *node) {
mangleAnyNominalType(node);
}
void Remangler::mangleTypeList(Node *node) {
bool FirstElem = true;
for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) {
mangleChildNode(node, Idx);
mangleListSeparator(FirstElem);
}
mangleEndOfList(FirstElem);
}
void Remangler::mangleLabelList(Node *node) {
if (node->getNumChildren() == 0)
Buffer << 'y';
else
mangleChildNodes(node);
}
void Remangler::mangleTypeMangling(Node *node) {
mangleChildNodes(node);
Buffer << 'D';
}
void Remangler::mangleTypeMetadata(Node *node) {
mangleSingleChildNode(node);
Buffer << "N";
}
void Remangler::mangleTypeMetadataAccessFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "Ma";
}
void Remangler::mangleTypeMetadataInstantiationCache(Node *node) {
mangleSingleChildNode(node);
Buffer << "MI";
}
void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mi";
}
void Remangler::mangleTypeMetadataSingletonInitializationCache(Node *node) {
mangleSingleChildNode(node);
Buffer << "Ml";
}
void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mr";
}
void Remangler::mangleTypeMetadataDemanglingCache(Node *node) {
mangleChildNodes(node);
Buffer << "MD";
}
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
mangleChildNodes(node);
Buffer << "ML";
}
void Remangler::mangleUncurriedFunctionType(Node *node) {
mangleFunctionSignature(node);
// Mangle as regular function type (there is no "uncurried function type"
// in the new mangling scheme).
Buffer << 'c';
}
void Remangler::mangleUnsafeAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "lu");
}
void Remangler::mangleUnsafeMutableAddressor(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "au");
}
void Remangler::mangleValueWitness(Node *node) {
mangleChildNode(node, 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;
}
void Remangler::mangleValueWitnessTable(Node *node) {
mangleSingleChildNode(node);
Buffer << "WV";
}
void Remangler::mangleVariable(Node *node) {
mangleAbstractStorage(node, "p");
}
void Remangler::mangleVTableAttribute(Node *node) {
unreachable("Old-fashioned vtable thunk in new mangling format");
}
void Remangler::mangleVTableThunk(Node *node) {
mangleChildNodes(node);
Buffer << "TV";
}
#define REF_STORAGE(Name, ...) \
void Remangler::mangle##Name(Node *node) { \
mangleSingleChildNode(node); \
Buffer << manglingOf(ReferenceOwnership::Name); \
}
#include "swift/AST/ReferenceStorage.def"
void Remangler::mangleWillSet(Node *node) {
mangleAbstractStorage(node->getFirstChild(), "w");
}
void Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "MB";
}
void Remangler::mangleReflectionMetadataFieldDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "MF";
}
void Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node) {
mangleSingleChildNode(node); // protocol-conformance
Buffer << "MA";
}
void Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node) {
mangleSingleChildNode(node); // protocol-conformance
Buffer << "MC";
}
void Remangler::mangleCurryThunk(Node *node) {
mangleSingleChildNode(node);
Buffer << "Tc";
}
void Remangler::mangleDispatchThunk(Node *node) {
mangleSingleChildNode(node);
Buffer << "Tj";
}
void Remangler::mangleMethodDescriptor(Node *node) {
mangleSingleChildNode(node);
Buffer << "Tq";
}
void Remangler::mangleMethodLookupFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mu";
}
void Remangler::mangleObjCMetadataUpdateFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "MU";
}
void Remangler::mangleObjCResilientClassStub(Node *node) {
mangleSingleChildNode(node);
Buffer << "Ms";
}
void Remangler::mangleFullObjCResilientClassStub(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mt";
}
void Remangler::mangleThrowsAnnotation(Node *node) {
Buffer << 'K';
}
void Remangler::mangleEmptyList(Node *node) {
Buffer << 'y';
}
void Remangler::mangleFirstElementMarker(Node *node) {
Buffer << '_';
}
void Remangler::mangleVariadicMarker(Node *node) {
Buffer << 'd';
}
void Remangler::mangleOutlinedCopy(Node *node) {
mangleChildNodes(node);
Buffer << "WOy";
}
void Remangler::mangleOutlinedConsume(Node *node) {
mangleChildNodes(node);
Buffer << "WOe";
}
void Remangler::mangleOutlinedRetain(Node *node) {
mangleChildNodes(node);
Buffer << "WOr";
}
void Remangler::mangleOutlinedRelease(Node *node) {
mangleChildNodes(node);
Buffer << "WOs";
}
void Remangler::mangleOutlinedInitializeWithTake(Node *node) {
mangleChildNodes(node);
Buffer << "WOb";
}
void Remangler::mangleOutlinedInitializeWithCopy(Node *node) {
mangleChildNodes(node);
Buffer << "WOc";
}
void Remangler::mangleOutlinedAssignWithTake(Node *node) {
mangleChildNodes(node);
Buffer << "WOd";
}
void Remangler::mangleOutlinedAssignWithCopy(Node *node) {
mangleChildNodes(node);
Buffer << "WOf";
}
void Remangler::mangleOutlinedDestroy(Node *node) {
mangleChildNodes(node);
Buffer << "WOh";
}
void Remangler::mangleOutlinedVariable(Node *node) {
Buffer << "Tv";
mangleIndex(node->getIndex());
}
void Remangler::mangleOutlinedBridgedMethod(Node *node) {
Buffer << "Te";
Buffer << node->getText();
Buffer << "_";
}
void Remangler::mangleSILBoxTypeWithLayout(Node *node) {
assert(node->getNumChildren() == 1 || node->getNumChildren() == 3);
assert(node->getChild(0)->getKind() == Node::Kind::SILBoxLayout);
auto layout = node->getChild(0);
auto layoutTypeList = Factory.createNode(Node::Kind::TypeList);
for (unsigned i = 0, e = layout->getNumChildren(); i < e; ++i) {
assert(layout->getChild(i)->getKind() == Node::Kind::SILBoxImmutableField
|| layout->getChild(i)->getKind() == Node::Kind::SILBoxMutableField);
auto field = layout->getChild(i);
assert(field->getNumChildren() == 1
&& field->getChild(0)->getKind() == Node::Kind::Type);
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);
}
mangleTypeList(layoutTypeList);
if (node->getNumChildren() == 3) {
auto signature = node->getChild(1);
auto genericArgs = node->getChild(2);
assert(signature->getKind() == Node::Kind::DependentGenericSignature);
assert(genericArgs->getKind() == Node::Kind::TypeList);
mangleTypeList(genericArgs);
mangleDependentGenericSignature(signature);
Buffer << "XX";
} else {
Buffer << "Xx";
}
}
void Remangler::mangleSILBoxLayout(Node *node) {
unreachable("should be part of SILBoxTypeWithLayout");
}
void Remangler::mangleSILBoxMutableField(Node *node) {
unreachable("should be part of SILBoxTypeWithLayout");
}
void Remangler::mangleSILBoxImmutableField(Node *node) {
unreachable("should be part of SILBoxTypeWithLayout");
}
void Remangler::mangleAssocTypePath(Node *node) {
bool FirstElem = true;
for (NodePointer Child : *node) {
mangle(Child);
mangleListSeparator(FirstElem);
}
}
void Remangler::mangleModuleDescriptor(Node *node) {
mangle(node->getChild(0));
Buffer << "MXM";
}
void Remangler::mangleExtensionDescriptor(Node *node) {
mangle(node->getChild(0));
Buffer << "MXE";
}
void Remangler::mangleAnonymousDescriptor(Node *node) {
mangle(node->getChild(0));
if (node->getNumChildren() == 1) {
Buffer << "MXX";
} else {
mangleIdentifier(node->getChild(1));
Buffer << "MXY";
}
}
void Remangler::mangleAssociatedTypeGenericParamRef(Node *node) {
mangleType(node->getChild(0));
mangleAssocTypePath(node->getChild(1));
Buffer << "MXA";
}
void Remangler::mangleTypeSymbolicReference(Node *node) {
return mangle(Resolver(SymbolicReferenceKind::Context,
(const void *)node->getIndex()));
}
void Remangler::mangleProtocolSymbolicReference(Node *node) {
return mangle(Resolver(SymbolicReferenceKind::Context,
(const void *)node->getIndex()));
}
void Remangler::mangleOpaqueTypeDescriptorSymbolicReference(Node *node) {
return mangle(Resolver(SymbolicReferenceKind::Context,
(const void *)node->getIndex()));
}
void Remangler::mangleSugaredOptional(Node *node) {
mangleType(node->getChild(0));
Buffer << "XSq";
}
void Remangler::mangleSugaredArray(Node *node) {
mangleType(node->getChild(0));
Buffer << "XSa";
}
void Remangler::mangleSugaredDictionary(Node *node) {
mangleType(node->getChild(0));
mangleType(node->getChild(1));
Buffer << "XSD";
}
void Remangler::mangleSugaredParen(Node *node) {
mangleType(node->getChild(0));
Buffer << "XSp";
}
void Remangler::mangleOpaqueReturnType(Node *node) {
Buffer << "Qr";
}
void Remangler::mangleOpaqueReturnTypeOf(Node *node) {
mangle(node->getChild(0));
Buffer << "QO";
}
void Remangler::mangleOpaqueType(Node *node) {
SubstitutionEntry entry;
if (trySubstitution(node, entry)) return;
mangle(node->getChild(0));
auto boundGenerics = node->getChild(2);
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
Buffer << (i == 0 ? 'y' : '_');
mangleChildNodes(boundGenerics->getChild(i));
}
if (node->getNumChildren() >= 4) {
auto retroactiveConformances = node->getChild(3);
for (unsigned i = 0; i < retroactiveConformances->getNumChildren(); ++i) {
mangle(retroactiveConformances->getChild(i));
}
}
Buffer << "Qo";
mangleIndex(node->getChild(1)->getIndex());
addSubstitution(entry);
}
void Remangler::mangleAccessorFunctionReference(Node *node) {
unreachable("can't remangle");
}
void Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node) {
mangleChildNodes(node);
Buffer << "MM";
}
void Remangler::mangleCanonicalSpecializedGenericTypeMetadataAccessFunction(
Node *node) {
mangleSingleChildNode(node);
Buffer << "Mb";
}
} // anonymous namespace
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(NodePointer node) {
return mangleNode(node, [](SymbolicReferenceKind, const void *) -> NodePointer {
unreachable("should not try to mangle a symbolic reference; "
"resolve it to a non-symbolic demangling tree instead");
});
}
std::string
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver) {
if (!node) return "";
NodeFactory Factory;
Remangler remangler(resolver, Factory);
remangler.mangle(node);
return remangler.str();
}
llvm::StringRef
Demangle::mangleNode(NodePointer node, SymbolicResolver resolver,
NodeFactory &Factory) {
if (!node)
return StringRef();
Remangler remangler(resolver, Factory);
remangler.mangle(node);
return remangler.getBufferStr();
}
bool Demangle::isSpecialized(Node *node) {
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:
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::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:
return isSpecialized(node->getChild(0));
case Node::Kind::Extension:
return isSpecialized(node->getChild(1));
default:
return false;
}
}
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::DefaultArgumentInitializer:
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());
NodePointer parentOrModule = node->getChild(0);
if (isSpecialized(parentOrModule))
parentOrModule = getUnspecialized(parentOrModule, Factory);
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: {
NodePointer unboundType = node->getChild(0);
assert(unboundType->getKind() == Node::Kind::Type);
NodePointer nominalType = unboundType->getChild(0);
if (isSpecialized(nominalType))
return getUnspecialized(nominalType, Factory);
return nominalType;
}
case Node::Kind::BoundGenericFunction: {
NodePointer unboundFunction = node->getChild(0);
assert(unboundFunction->getKind() == Node::Kind::Function ||
unboundFunction->getKind() == Node::Kind::Constructor);
if (isSpecialized(unboundFunction))
return getUnspecialized(unboundFunction, Factory);
return unboundFunction;
}
case Node::Kind::Extension: {
NodePointer parent = node->getChild(1);
if (!isSpecialized(parent))
return node;
NodePointer result = Factory.createNode(Node::Kind::Extension);
result->addChild(node->getFirstChild(), Factory);
result->addChild(getUnspecialized(parent, Factory), Factory);
if (node->getNumChildren() == 3) {
// Add the generic signature of the extension.
result->addChild(node->getChild(2), Factory);
}
return result;
}
default:
unreachable("bad nominal type kind");
}
}