Files
swift-mirror/lib/Basic/Demangle.cpp
Enrico Granata 80278dfedc Simplifying the demangling for UncurriedFunctionType objects, from:
k = UncurriedFunctionType
  k = UncurriedFunctionMetaType
    k = Type
      k = MetaType

to:
k = UncurriedFunctionType
  k = MetaType

This should help Greg parse uncurried functions with greater ease



Swift SVN r7964
2013-09-05 23:09:10 +00:00

1887 lines
58 KiB
C++

//===--- Demangle.cpp - Swift Name Demangling -----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===---------------------------------------------------------------------===//
//
// This file implements declaration name demangling in Swift.
//
//===---------------------------------------------------------------------===//
#include "swift/Basic/Demangle.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/Basic/LLVM.h"
#include "llvm/Support/raw_ostream.h"
#include <functional>
#include <tuple>
#include <vector>
using namespace swift;
using namespace Demangle;
Node::size_type Node::size () {
return Children.size();
}
Node::iterator Node::begin () {
return Children.begin();
}
Node::iterator Node::end () {
return Children.end();
}
Node::const_iterator Node::begin () const {
return Children.begin();
}
Node::const_iterator Node::end () const {
return Children.end();
}
NodePointer Node::front () {
return Children.front();
}
NodePointer Node::back () {
return Children.back();
}
NodePointer Node::child_at (Node::size_type idx) {
return Children[idx];
}
Node::Node (Node::Kind k, std::string t) : NodeKind(k), NodeText(t), Successor(nullptr), Children(), Parent(nullptr), Predecessor(nullptr) {}
Node::Node (const Node& other) : NodeKind(other.NodeKind), NodeText(other.NodeText), Successor(), Children(), Parent(), Predecessor() {
for (NodePointer child : other)
push_back_child(NodePointer(new Node(*child)));
}
Node* Node::getParent () {
return Parent;
}
NodePointer Node::getNextNode () {
return Successor;
}
Node* Node::getPreviousNode () {
return Predecessor;
}
NodePointer Node::push_back_child (NodePointer child) {
NodePointer ret(child);
while (child) {
if (size())
back()->setSuccessorImpl(child);
push_back_childImpl(child);
child->setParent(this);
child = child->getNextNode();
}
return ret;
}
void Node::setParent (Node *parent) {
Node* ptr = this;
while (ptr) {
ptr->setParentImpl(parent);
ptr = ptr->getNextNode().getPtr();
}
}
void Node::setNextNode (NodePointer successor) {
if (getParent())
insertSiblingImpl(successor);
else
setSuccessorImpl(successor);
}
Node::Kind Node::getKind() {
return NodeKind;
}
void Node::setKind (Node::Kind k) {
NodeKind = k;
}
std::string Node::getText() {
return NodeText;
}
void Node::setText (const std::string &t) {
NodeText.assign(t);
}
void Node::setParentImpl (Node *parent) {
Parent = parent;
}
void Node::setSuccessorImpl (NodePointer successor) {
Successor = successor;
successor->Predecessor = this;
}
void Node::push_back_childImpl (NodePointer child) {
Children.push_back(child);
}
void Node::insertSiblingImpl (NodePointer child) {
iterator pBegin = getParent()->begin();
iterator pEnd = getParent()->end();
iterator prev_pos = std::find_if(pBegin,pEnd,FindPtr(this));
if (prev_pos == pEnd) {
getParent()->push_back_child(child);
}
else {
prev_pos++;
if (prev_pos == pEnd) {
getParent()->push_back_child(child);
}
else {
child->setParentImpl(getParent());
NodePointer old_next = getNextNode();
getParent()->Children.insert(prev_pos,child);
if (old_next) {
NodePointer end_of_chain = child;
while (end_of_chain->getNextNode())
end_of_chain = end_of_chain->getNextNode();
end_of_chain->setSuccessorImpl(old_next);
}
setSuccessorImpl(child);
}
}
}
class DemanglerPrinter {
public:
DemanglerPrinter() : Buffer(), BackendPrinter(Buffer) {}
DemanglerPrinter &operator<<(std::string s) {
BackendPrinter << s;
return *this;
}
DemanglerPrinter &operator<<(const char *cstr) {
BackendPrinter << cstr;
return *this;
}
DemanglerPrinter &operator<<(char c) {
BackendPrinter << c;
return *this;
}
DemanglerPrinter &operator<<(size_t sz) {
BackendPrinter << sz;
return *this;
}
std::string &str() { return BackendPrinter.str(); }
private:
std::string Buffer;
llvm::raw_string_ostream BackendPrinter;
};
static bool isStartOfIdentifier(char c) {
if (c >= '0' && c <= '9')
return true;
return c == 'o';
}
static bool isStartOfNominalType(char c) {
switch (c) {
case 'C':
case 'V':
case 'O':
return true;
default:
return false;
}
}
static Node::Kind nominalTypeMarkerToNodeKind(char c) {
if (c == 'C')
return Node::Kind::Class;
if (c == 'V')
return Node::Kind::Structure;
if (c == 'O')
return Node::Kind::Union;
return Node::Kind::Identifier;
}
static std::string archetypeName(size_t i) {
DemanglerPrinter name;
do {
name << (char)('A' + (i % 26));
i /= 26;
} while (i);
return name.str();
}
NodePointer Node::makeNodePointer(Kind k, std::string t) {
return NodePointer(new Node(k, t));
}
class Demangler {
public:
Demangler(llvm::StringRef mangled)
: Substitutions(), ArchetypeCounts(), ArchetypeCount(), Mangled(mangled),
RootNode(), CurrentNode() {}
~Demangler() {}
NodePointer appendNode(NodePointer n) {
if (!RootNode) {
RootNode = n;
CurrentNode = RootNode;
} else {
CurrentNode->setNextNode(n);
CurrentNode = n;
}
return CurrentNode;
}
NodePointer appendNode(Node::Kind k, std::string t = "") {
if (!RootNode) {
RootNode = NodePointer(new Node(k, t));
CurrentNode = RootNode;
} else {
CurrentNode->setNextNode(NodePointer(new Node(k, t)));
CurrentNode = CurrentNode->getNextNode();
}
return CurrentNode;
}
void insertChildNode(Node::Kind k, std::string t = "") {
assert(CurrentNode.getPtr() && "Need a current node");
CurrentNode->push_back_child(NodePointer(new Node(k, t)));
}
bool demangle() {
if (!Mangled.hasAtLeast(2))
return failure();
if (Mangled.slice(2) != "_T")
return failure();
if (Mangled.hasAtLeast(4)) {
if (Mangled.slice(4) == "_TTo") {
Mangled.advanceOffset(4);
appendNode(Node::Kind::ObjCAttribute);
if (!demangleGlobal())
return false;
return true;
}
}
Mangled.advanceOffset(2);
if (!demangleGlobal())
return false;
return true;
}
NodePointer getDemangled() { return RootNode; }
private:
enum class IsProtocol {
yes = true, no = false
};
enum class IsVariadic {
yes = true, no = false
};
typedef std::pair<NodePointer, IsProtocol> Substitution;
enum class Directness {
Direct, Indirect, Unkown
};
const char *toString(Directness d) {
switch (d) {
case Directness::Direct:
return "direct";
case Directness::Indirect:
return "indirect";
default:
return "unknown";
}
}
bool failure() {
RootNode = NodePointer(new Node(Node::Kind::Failure, ""));
CurrentNode = RootNode;
return false;
}
Directness demangleDirectness() {
if (Mangled.nextIf('d'))
return Directness::Direct;
if (Mangled.nextIf('i'))
return Directness::Indirect;
return Directness::Unkown;
}
bool demangleNatural(size_t &num) {
if (!Mangled)
return false;
char c = Mangled.next();
if (c < '0' || c > '9')
return false;
num = (c - '0');
while (true) {
if (!Mangled) {
return true;
}
c = Mangled.peek();
if (c < '0' || c > '9') {
return true;
} else {
num = (10 * num) + (c - '0');
}
Mangled.next();
}
}
bool demangleBuiltinSize(size_t &num) {
if (!demangleNatural(num))
return false;
if (Mangled.nextIf('_'))
return true;
return false;
}
enum class ValueWitnessKind {
AllocateBuffer,
AssignWithCopy,
AssignWithTake,
DeallocateBuffer,
Destroy,
DestroyBuffer,
InitializeBufferWithCopyOfBuffer,
InitializeBufferWithCopy,
InitializeWithCopy,
InitializeBufferWithTake,
InitializeWithTake,
ProjectBuffer,
Typeof,
StoreExtraInhabitant,
GetExtraInhabitantIndex,
GetUnionTag,
InplaceProjectUnionData,
Unknown
};
const char *toString(ValueWitnessKind k) {
switch (k) {
case ValueWitnessKind::AllocateBuffer:
return "allocateBuffer";
case ValueWitnessKind::AssignWithCopy:
return "assignWithCopy";
case ValueWitnessKind::AssignWithTake:
return "assignWithTake";
case ValueWitnessKind::DeallocateBuffer:
return "deallocateBuffer";
case ValueWitnessKind::Destroy:
return "destroy";
case ValueWitnessKind::DestroyBuffer:
return "destroyBuffer";
case ValueWitnessKind::InitializeBufferWithCopyOfBuffer:
return "initializeBufferWithCopyOfBuffer";
case ValueWitnessKind::InitializeBufferWithCopy:
return "initializeBufferWithCopy";
case ValueWitnessKind::InitializeWithCopy:
return "initializeWithCopy";
case ValueWitnessKind::InitializeBufferWithTake:
return "initializeBufferWithTake";
case ValueWitnessKind::InitializeWithTake:
return "initializeWithTake";
case ValueWitnessKind::ProjectBuffer:
return "projectBuffer";
case ValueWitnessKind::Typeof:
return "typeof";
case ValueWitnessKind::StoreExtraInhabitant:
return "storeExtraInhabitant";
case ValueWitnessKind::GetExtraInhabitantIndex:
return "getExtraInhabitantIndex";
case ValueWitnessKind::GetUnionTag:
return "getUnionTag";
case ValueWitnessKind::InplaceProjectUnionData:
return "inplaceProjectUnionData";
default:
return "unknown";
}
}
ValueWitnessKind demangleValueWitnessKind() {
if (!Mangled)
return ValueWitnessKind::Unknown;
char c1 = Mangled.next();
if (!Mangled)
return ValueWitnessKind::Unknown;
char c2 = Mangled.next();
if (c1 == 'a' && c2 == 'l')
return ValueWitnessKind::AllocateBuffer;
if (c1 == 'c' && c2 == 'a')
return ValueWitnessKind::AssignWithCopy;
if (c1 == 't' && c2 == 'a')
return ValueWitnessKind::AssignWithTake;
if (c1 == 'd' && c2 == 'e')
return ValueWitnessKind::DeallocateBuffer;
if (c1 == 'x' && c2 == 'x')
return ValueWitnessKind::Destroy;
if (c1 == 'X' && c2 == 'X')
return ValueWitnessKind::DestroyBuffer;
if (c1 == 'C' && c2 == 'P')
return ValueWitnessKind::InitializeBufferWithCopyOfBuffer;
if (c1 == 'C' && c2 == 'p')
return ValueWitnessKind::InitializeBufferWithCopy;
if (c1 == 'c' && c2 == 'p')
return ValueWitnessKind::InitializeWithCopy;
if (c1 == 'T' && c2 == 'k')
return ValueWitnessKind::InitializeBufferWithTake;
if (c1 == 't' && c2 == 'k')
return ValueWitnessKind::InitializeWithTake;
if (c1 == 'p' && c2 == 'r')
return ValueWitnessKind::ProjectBuffer;
if (c1 == 't' && c2 == 'y')
return ValueWitnessKind::Typeof;
if (c1 == 'x' && c2 == 's')
return ValueWitnessKind::StoreExtraInhabitant;
if (c1 == 'x' && c2 == 'g')
return ValueWitnessKind::GetExtraInhabitantIndex;
if (c1 == 'u' && c2 == 'g')
return ValueWitnessKind::GetUnionTag;
if (c1 == 'u' && c2 == 'p')
return ValueWitnessKind::InplaceProjectUnionData;
return ValueWitnessKind::Unknown;
}
bool demangleGlobal() {
if (!Mangled)
return failure();
if (Mangled.nextIf('M')) {
if (Mangled.nextIf('P')) {
Directness d = demangleDirectness();
if (d == Directness::Unkown)
return failure();
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::Directness, toString(d));
appendNode(Node::Kind::GenericTypeMetadataPattern)->push_back_child(type);
return true;
}
if (Mangled.nextIf('m')) {
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::Metaclass)->push_back_child(type);
return true;
}
Directness d = demangleDirectness();
appendNode(Node::Kind::Directness, toString(d));
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::TypeMetadata)->push_back_child(type);
return true;
}
if (Mangled.nextIf('n')) {
if (Mangled.nextIf('k') && Mangled.nextIf('_')) {
bool entity_ok = demangleEntity(appendNode(Node::Kind::ProtocolWitness));
if (!entity_ok)
return failure();
return true;
} else
return failure();
}
if (Mangled.nextIf('t')) {
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(type);
return true;
}
if (Mangled.nextIf('w')) {
ValueWitnessKind w = demangleValueWitnessKind();
if (w == ValueWitnessKind::Unknown)
return failure();
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::ValueWitnessKind, toString(w))->push_back_child(type);
return true;
}
if (Mangled.nextIf('W')) {
if (Mangled.nextIf('V')) {
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::ValueWitnessTable)->push_back_child(type);
return true;
}
if (Mangled.nextIf('o')) {
bool entity_ok = demangleEntity(appendNode(Node::Kind::WitnessTableOffset));
if (!entity_ok)
return failure();
return true;
}
if (Mangled.nextIf('v')) {
Directness d = demangleDirectness();
appendNode(Node::Kind::Directness, toString(d));
bool entity_ok = demangleEntity(appendNode(Node::Kind::FieldOffset));
if (!entity_ok)
return failure();
return true;
}
if (Mangled.nextIf('P')) {
NodePointer conformance = demangleProtocolConformance();
if (!conformance)
return failure();
appendNode(Node::makeNodePointer(Node::Kind::ProtocolWitnessTable))->push_back_child(conformance);
return true;
}
if (Mangled.nextIf('Z')) {
NodePointer conformance = demangleProtocolConformance();
if (!conformance)
return failure();
appendNode(Node::makeNodePointer(Node::Kind::LazyProtocolWitnessTableAccessor))->push_back_child(conformance);
return true;
}
if (Mangled.nextIf('z')) {
NodePointer conformance = demangleProtocolConformance();
if (!conformance)
return failure();
appendNode(Node::makeNodePointer(Node::Kind::LazyProtocolWitnessTableTemplate))->push_back_child(conformance);
return true;
}
if (Mangled.nextIf('D')) {
NodePointer conformance = demangleProtocolConformance();
if (!conformance)
return failure();
appendNode(Node::makeNodePointer(Node::Kind::DependentProtocolWitnessTableGenerator))->push_back_child(conformance);
return true;
}
if (Mangled.nextIf('d')) {
NodePointer conformance = demangleProtocolConformance();
if (!conformance)
return failure();
appendNode(Node::makeNodePointer(Node::Kind::DependentProtocolWitnessTableTemplate))->push_back_child(conformance);
return true;
}
return failure();
}
if (Mangled.nextIf('T')) {
if (Mangled.nextIf('b')) {
NodePointer type = demangleType();
if (!type)
return failure();
appendNode(Node::Kind::BridgeToBlockFunction)->push_back_child(type);
return true;
}
return failure();
}
if (Mangled.nextIf('L')) {
bool entity_ok = demangleEntity(appendNode(Node::Kind::LocalEntity));
if (!entity_ok)
return failure();
return true;
}
NodePointer decl = Node::makeNodePointer(Node::Kind::Declaration);
appendNode(decl);
if (!demangleEntity(decl))
return failure();
return true;
}
std::string demangleOperator() {
static const char op_char_table[] = "& @/= > <*!|+ %-~ ^ .";
size_t length;
if (demangleNatural(length)) {
if (Mangled.hasAtLeast(length)) {
std::string op_base = Mangled.slice(length);
Mangled.advanceOffset(length);
DemanglerPrinter op;
size_t op_base_size = op_base.size();
for (size_t idx = 0; idx < op_base_size; ++idx) {
char c = op_base[idx];
if (c < 'a' || c > 'z')
return "";
char o = op_char_table[c - 'a'];
if (o == ' ')
return "";
op << o;
}
return op.str();
} else
return "";
}
return "";
}
NodePointer demangleIdentifier() {
if (!Mangled)
return nullptr;
if (Mangled.nextIf('o')) {
char op_mode = Mangled.next();
if (op_mode != 'p' && op_mode != 'P' && op_mode != 'i')
return nullptr;
std::string operatr = demangleOperator();
if (operatr.size()) {
switch (op_mode) {
case 'p':
return Node::makeNodePointer(Node::Kind::PrefixOperator, operatr);
case 'P':
return Node::makeNodePointer(Node::Kind::PostfixOperator, operatr);
case 'i':
return Node::makeNodePointer(Node::Kind::InfixOperator, operatr);
default:
return nullptr;
}
}
}
size_t length;
if (demangleNatural(length)) {
if (Mangled.hasAtLeast(length)) {
auto identifier = Mangled.slice(length);
Mangled.advanceOffset(length);
return Node::makeNodePointer(Node::Kind::Identifier, identifier);
}
}
return nullptr;
}
bool demangleIndex(size_t &natural) {
if (Mangled.nextIf('_')) {
natural = 0;
return true;
}
if (demangleNatural(natural)) {
if (!Mangled.nextIf('_'))
return false;
natural++;
return true;
}
return false;
}
NodePointer compactNode(NodePointer head, Node::Kind outputKind,
char separator = '.') {
DemanglerPrinter printer;
while (head) {
printer << head->getText();
head = head->getNextNode();
if (head)
printer << separator;
}
return Node::makeNodePointer(outputKind, printer.str());
}
Substitution demangleSubstitutionIndexWithProtocol() {
if (!Mangled)
return { Node::makeNodePointer(Node::Kind::Failure), IsProtocol::no };
if (Mangled.nextIf('o'))
return { Node::makeNodePointer(Node::Kind::Module,"ObjectiveC"), IsProtocol::no };
if (Mangled.nextIf('C'))
return { Node::makeNodePointer(Node::Kind::Module,"C"), IsProtocol::no };
if (Mangled.nextIf('s'))
return { Node::makeNodePointer(Node::Kind::Module,"swift"), IsProtocol::no };
if (Mangled.nextIf('a')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Slice"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('b')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Bool"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('c')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Char"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('d')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Float64"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('f')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Float32"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('i')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Int64"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('q')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"Optional"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('S')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"String"));
return { type, IsProtocol::no };
}
if (Mangled.nextIf('u')) {
NodePointer type = Node::makeNodePointer(Node::Kind::Path);
type->push_back_child(Node::makeNodePointer(Node::Kind::Module,"swift"))->setNextNode(
Node::makeNodePointer(Node::Kind::Structure,"UInt64"));
return { type, IsProtocol::no };
}
size_t index_sub;
if (!demangleIndex(index_sub))
return { Node::makeNodePointer(Node::Kind::Failure), IsProtocol::no };
if (index_sub >= Substitutions.size())
return { Node::makeNodePointer(Node::Kind::Failure), IsProtocol::no };
return Substitutions[index_sub];
}
NodePointer demangleSubstitutionIndex() {
Substitution sub = demangleSubstitutionIndexWithProtocol();
if (!sub.first)
return nullptr;
return NodePointer(new Node(*sub.first.getPtr()));
}
NodePointer demangleSubstitution() {
if (Mangled.nextIf('S'))
return demangleSubstitutionIndex();
return nullptr;
}
NodePointer demangleModule() {
char c = Mangled.peek();
if (isStartOfIdentifier(c)) {
NodePointer identifier = demangleIdentifier();
if (!identifier)
return nullptr;
if (identifier->getKind() == Node::Kind::Identifier)
identifier->setKind(Node::Kind::Module);
NodePointer copy_identifier = Node::makeNodePointer(identifier->getKind(),identifier->getText());
Substitutions.push_back( { copy_identifier, IsProtocol::no });
return identifier;
}
if (c == 'S') {
NodePointer identifier = demangleSubstitution();
if (!identifier)
return nullptr;
if (identifier->getKind() != Node::Kind::Path)
identifier->setKind(Node::Kind::Module);
return identifier;
}
return nullptr;
}
NodePointer demangleDeclarationName(Node::Kind identifier_type) {
Node::Kind context_type = Node::Kind::Unknown;
NodePointer context;
NodePointer identifier;
context = demangleContextImpl(&context_type);
if (!context)
return nullptr;
identifier = demangleIdentifier();
if (!identifier)
return nullptr;
IsProtocol is_proto = IsProtocol::no;
if (identifier_type != Node::Kind::Unknown) {
identifier->setKind(identifier_type);
if (identifier_type == Node::Kind::Protocol)
is_proto = IsProtocol::yes;
}
else if (context_type != Node::Kind::Unknown) {
identifier->setKind(context_type);
if (context_type == Node::Kind::Protocol)
is_proto = IsProtocol::yes;
}
if (context->getKind() == Node::Kind::Path) {
context->push_back_child(identifier);
NodePointer path = Node::makeNodePointer(Node::Kind::Path);
straightenNestedDeclContext(context, path);
context = path;
}
else {
context->setNextNode(identifier);
NodePointer path = Node::makeNodePointer(Node::Kind::Path);
path->push_back_child(context);
context = path;
}
NodePointer nominaltype = NodePointer(new Node(*context));
Substitutions.push_back({ nominaltype, is_proto });
return context;
}
NodePointer demangleProtocolName() {
if (Mangled.nextIf('S')) {
Substitution sub = demangleSubstitutionIndexWithProtocol();
if (!sub.first)
return nullptr;
if (sub.second == IsProtocol::yes) {
NodePointer subProto = Node::makeNodePointer(sub.first->getKind(),sub.first->getText());
for (NodePointer child : *sub.first) {
subProto->push_back_child(Node::makeNodePointer(child->getKind(),child->getText()));
}
return subProto;
}
NodePointer identifier = demangleIdentifier();
if (!identifier)
return nullptr;
NodePointer nominaltype = Node::makeNodePointer(Node::Kind::Path);
NodePointer copy_context = NodePointer(new Node(*sub.first.getPtr()));
identifier->setKind(Node::Kind::Protocol);
NodePointer copy_identifier = Node::makeNodePointer(identifier->getKind(),identifier->getText());
nominaltype->push_back_child(copy_context)->setNextNode(copy_identifier);
Substitutions.push_back({ nominaltype, IsProtocol::yes });
return nominaltype;
}
NodePointer result;
if ((result = demangleDeclarationName(Node::Kind::Protocol))) {
return result;
}
return nullptr;
}
NodePointer demangleNominalType() {
if (!Mangled)
return nullptr;
char c = Mangled.next();
if (c == 'S')
return demangleSubstitutionIndex();
if (!isStartOfNominalType(c))
return nullptr;
NodePointer nominalType;
if ((nominalType = demangleDeclarationName(nominalTypeMarkerToNodeKind(c))))
return nominalType;
return nullptr;
}
NodePointer demangleContextImpl(Node::Kind *inferred_context_type = nullptr) {
if (!Mangled)
return nullptr;
NodePointer demangled_ctx(nullptr);
char c = Mangled.peek();
if (isStartOfIdentifier(c) || c == 'S') {
demangled_ctx = demangleModule();
}
if (isStartOfNominalType(c)) {
if (inferred_context_type) {
*inferred_context_type = nominalTypeMarkerToNodeKind(c);
}
demangled_ctx = demangleNominalType();
}
if (c == 'P') {
Mangled.next();
demangled_ctx = demangleProtocolName();
}
return demangled_ctx;
}
void straightenNestedDeclContext (NodePointer src, NodePointer& dest) {
Node::Kind srcKind = src->getKind();
switch (srcKind) {
case swift::Demangle::Node::Kind::Class:
case swift::Demangle::Node::Kind::Structure:
case swift::Demangle::Node::Kind::Union:
case swift::Demangle::Node::Kind::Module:
dest->push_back_child(Node::makeNodePointer(srcKind,src->getText()));
break;
case swift::Demangle::Node::Kind::Path:
for (NodePointer child : *src) {
straightenNestedDeclContext(child, dest);
}
break;
default:
break;
}
}
NodePointer demangleContext(Node::Kind *inferred_context_type = nullptr) {
if (!Mangled)
return nullptr;
NodePointer demangled_ctx(demangleContextImpl(inferred_context_type));
if (!demangled_ctx)
return nullptr;
NodePointer ret(Node::makeNodePointer(Node::Kind::Path));
straightenNestedDeclContext(demangled_ctx, ret);
return ret;
}
std::pair<NodePointer,NodePointer> demangleDecl() {
std::pair<NodePointer,NodePointer> ret;
NodePointer identifier = demangleIdentifier();
if (!identifier)
return ret;
NodePointer type = demangleType();
if (!type)
return ret;
ret.first = identifier;
ret.second = type;
return ret;
}
NodePointer demangleProtocolList() {
NodePointer proto_list = Node::makeNodePointer(Node::Kind::ProtocolList);
if (Mangled.nextIf('_')) {
return proto_list;
}
NodePointer proto = demangleProtocolName();
if (!proto)
return nullptr;
proto_list->push_back_child(proto);
while (Mangled.nextIf('_') == false) {
proto = demangleProtocolName();
if (!proto)
return nullptr;
proto_list->push_back_child(proto);
}
return proto_list;
}
NodePointer demangleProtocolConformance() {
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer protocol = demangleProtocolName();
if (!protocol)
return nullptr;
NodePointer context = demangleContext();
if (!context)
return nullptr;
NodePointer proto_conformance =
Node::makeNodePointer(Node::Kind::ProtocolConformance);
proto_conformance->push_back_child(type);
proto_conformance->push_back_child(protocol);
proto_conformance->push_back_child(context);
return proto_conformance;
}
Node::Kind getDeclContextType (NodePointer declContext) {
if (declContext->getKind() != Node::Kind::Path)
return Node::Kind::Unknown;
for (NodePointer child : *declContext) {
Node::Kind childKind = child->getKind();
switch (childKind) {
case Node::Kind::Class:
case Node::Kind::Structure:
case Node::Kind::Union:
case Node::Kind::Protocol:
return childKind;
default:
continue;
}
}
return Node::Kind::Unknown;
}
bool demangleEntity(NodePointer decl) {
NodePointer context = demangleContext();
if (!context)
return failure();
Node::Kind idKind = getDeclContextType(context);
if (Mangled.nextIf('D')) {
if (idKind == Node::Kind::Class)
context->push_back_child(Node::makeNodePointer(Node::Kind::Deallocator));
else
context->push_back_child(Node::makeNodePointer(Node::Kind::Destructor));
decl->push_back_child(context);
return true;
}
if (Mangled.nextIf('d')) {
context->push_back_child(Node::makeNodePointer(Node::Kind::Destructor));
decl->push_back_child(context);
return true;
}
if (Mangled.nextIf('C')) {
NodePointer type = demangleType();
if (!type)
return failure();
if (idKind == Node::Kind::Class)
context->push_back_child(Node::makeNodePointer(Node::Kind::Allocator));
else
context->push_back_child(Node::makeNodePointer(Node::Kind::Constructor));
decl->push_back_child(context);
decl->push_back_child(type);
return true;
}
if (Mangled.nextIf('c')) {
NodePointer type = demangleType();
if (!type)
return failure();
context->push_back_child(Node::makeNodePointer(Node::Kind::Constructor));
decl->push_back_child(context);
decl->push_back_child(type);
return true;
}
std::pair<NodePointer,NodePointer> demangledDecl = demangleDecl();
if (demangledDecl.first.getPtr() == nullptr || demangledDecl.second.getPtr() == nullptr)
return nullptr;
if (Mangled.nextIf('a')) {
context->push_back_child(demangledDecl.first);
context->push_back_child(Node::makeNodePointer(Node::Kind::Addressor));
decl->push_back_child(context);
decl->push_back_child(demangledDecl.second);
} else if (Mangled.nextIf('g')) {
context->push_back_child(demangledDecl.first);
context->push_back_child(Node::makeNodePointer(Node::Kind::Getter));
decl->push_back_child(context);
decl->push_back_child(demangledDecl.second);
} else if (Mangled.nextIf('s')) {
context->push_back_child(demangledDecl.first);
context->push_back_child(Node::makeNodePointer(Node::Kind::Setter));
decl->push_back_child(context);
decl->push_back_child(demangledDecl.second);
} else {
context->push_back_child(demangledDecl.first);
decl->push_back_child(context);
decl->push_back_child(demangledDecl.second);
}
return true;
}
NodePointer demangleArchetypes() {
DemanglerPrinter result_printer;
NodePointer archetypes = Node::makeNodePointer(Node::Kind::ArchetypeList);
while (true) {
if (Mangled.nextIf('_')) {
if (!Mangled)
return nullptr;
char c = Mangled.peek();
if (c != '_' && c != 'S' && !isStartOfIdentifier(c))
break;
archetypes->push_back_child(Node::makeNodePointer(
Node::Kind::ArchetypeRef, archetypeName(ArchetypeCount)));
} else {
NodePointer proto_list = demangleProtocolList();
if (!proto_list)
return nullptr;
NodePointer arch_and_proto =
Node::makeNodePointer(Node::Kind::ArchetypeAndProtocol);
arch_and_proto->push_back_child(Node::makeNodePointer(
Node::Kind::ArchetypeRef, archetypeName(ArchetypeCount)));
arch_and_proto->push_back_child(proto_list);
archetypes->push_back_child(arch_and_proto);
}
++ArchetypeCount;
}
return archetypes;
}
NodePointer demangleArchetypeRef(size_t depth, size_t i) {
if (depth == 0 && ArchetypeCount == 0)
return Node::makeNodePointer(Node::Kind::ArchetypeRef, archetypeName(i));
size_t length = ArchetypeCounts.size();
if (depth >= length)
return nullptr;
size_t index = ArchetypeCounts[length - 1 - depth] + i;
size_t max =
(depth == 0) ? ArchetypeCount : ArchetypeCounts[length - depth];
if (index >= max)
return nullptr;
return Node::makeNodePointer(Node::Kind::ArchetypeRef,
archetypeName(index));
}
NodePointer demangleTuple(IsVariadic isV) {
NodePointer tuple = Node::makeNodePointer(
isV == IsVariadic::yes ? Node::Kind::VariadicTuple
: Node::Kind::NonVariadicTuple);
while (Mangled.nextIf('_') == false) {
if (!Mangled)
return nullptr;
NodePointer tuple_element =
Node::makeNodePointer(Node::Kind::TupleElement);
NodePointer identifier;
NodePointer type;
if (isStartOfIdentifier(Mangled.peek())) {
identifier = demangleIdentifier();
if (!identifier)
return nullptr;
identifier->setKind(Node::Kind::TupleElementName);
}
type = demangleType();
if (!type)
return nullptr;
if (type->getNextNode() && type->getKind() != Node::Kind::ProtocolList)
type = compactNode(type, Node::Kind::TupleElementType);
if (identifier)
tuple_element->push_back_child(identifier);
tuple_element->push_back_child(type);
tuple->push_back_child(tuple_element);
}
return tuple;
}
NodePointer postProcessReturnTypeNode (NodePointer out_args) {
NodePointer out_node = Node::makeNodePointer(Node::Kind::ReturnType);
out_node->push_back_child(out_args);
return out_node;
}
NodePointer demangleType() {
NodePointer type = demangleTypeImpl();
if (!type)
return nullptr;
NodePointer nodeType = Node::makeNodePointer(Node::Kind::Type);
nodeType->push_back_child(type);
return nodeType;
}
NodePointer demangleTypeImpl() {
if (!Mangled)
return nullptr;
char c = Mangled.next();
if (c == 'A') {
size_t size;
if (demangleNatural(size)) {
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer array = Node::makeNodePointer(Node::Kind::ArrayType);
array->push_back_child(type);
array->push_back_child(Node::makeNodePointer(
Node::Kind::Number, (DemanglerPrinter() << size).str()));
return array;
}
return nullptr;
}
if (c == 'B') {
if (!Mangled)
return nullptr;
c = Mangled.next();
if (c == 'f') {
size_t size;
if (demangleBuiltinSize(size)) {
return Node::makeNodePointer(
Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Float" << size).str());
}
}
if (c == 'i') {
size_t size;
if (demangleBuiltinSize(size)) {
return Node::makeNodePointer(
Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Int" << size).str());
}
}
if (c == 'v') {
size_t elts;
if (demangleNatural(elts)) {
if (!Mangled.nextIf('B'))
return nullptr;
if (Mangled.nextIf('i')) {
size_t size;
if (!demangleBuiltinSize(size))
return nullptr;
return Node::makeNodePointer(
Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Vec" << elts << "xInt" << size)
.str());
}
if (Mangled.nextIf('f')) {
size_t size;
if (!demangleBuiltinSize(size))
return nullptr;
return Node::makeNodePointer(
Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Vec" << elts << "xFloat"
<< size).str());
}
if (Mangled.nextIf('p'))
return Node::makeNodePointer(
Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Vec" << elts << "xRawPointer")
.str());
}
}
if (c == 'O')
return Node::makeNodePointer(Node::Kind::BuiltinTypeName,
"Builtin.ObjCPointer");
if (c == 'o')
return Node::makeNodePointer(Node::Kind::BuiltinTypeName,
"Builtin.ObjectPointer");
if (c == 'p')
return Node::makeNodePointer(Node::Kind::BuiltinTypeName,
"Builtin.RawPointer");
return nullptr;
}
if (c == 'b') {
NodePointer in_args = demangleType();
if (!in_args)
return nullptr;
NodePointer out_args = demangleType();
if (!out_args)
return nullptr;
NodePointer block = Node::makeNodePointer(Node::Kind::ObjCBlock);
NodePointer in_node = Node::makeNodePointer(Node::Kind::ArgumentTuple);
block->push_back_child(in_node);
in_node->push_back_child(in_args);
block->push_back_child(postProcessReturnTypeNode(out_args));
return block;
}
if (c == 'F') {
NodePointer in_args = demangleType();
if (!in_args)
return nullptr;
NodePointer out_args = demangleType();
if (!out_args)
return nullptr;
NodePointer block = Node::makeNodePointer(Node::Kind::FunctionType);
NodePointer in_node = Node::makeNodePointer(Node::Kind::ArgumentTuple);
block->push_back_child(in_node);
in_node->push_back_child(in_args);
block->push_back_child(postProcessReturnTypeNode(out_args));
return block;
}
if (c == 'f') {
NodePointer in_args = demangleTypeImpl();
if (!in_args)
return nullptr;
NodePointer out_args = demangleType();
if (!out_args)
return nullptr;
NodePointer block =
Node::makeNodePointer(Node::Kind::UncurriedFunctionType);
block->push_back_child(in_args);
block->push_back_child(postProcessReturnTypeNode(out_args));
return block;
}
if (c == 'G') {
NodePointer type_list = Node::makeNodePointer(Node::Kind::TypeList);
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer type_list_entry =
Node::makeNodePointer(Node::Kind::TypeListEntry);
type_list_entry->push_back_child(type);
type_list->push_back_child(type_list_entry);
while (Mangled.peek() != '_') {
type = demangleType();
if (!type)
return nullptr;
type_list_entry = Node::makeNodePointer(Node::Kind::TypeListEntry);
type_list_entry->push_back_child(type);
type_list->push_back_child(type_list_entry);
}
Mangled.next();
NodePointer type_application =
Node::makeNodePointer(Node::Kind::GenericTypeApplication);
type_application->push_back_child(type_list);
return type_application;
}
if (c == 'M') {
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer metatype = Node::makeNodePointer(Node::Kind::MetaType);
metatype->push_back_child(type);
return metatype;
}
if (c == 'P') {
return demangleProtocolList();
}
if (c == 'Q') {
if (Mangled.nextIf('d')) {
size_t depth, index;
if (!demangleIndex(depth))
return nullptr;
if (!demangleIndex(index))
return nullptr;
return demangleArchetypeRef(depth + 1, index);
}
size_t index;
if (!demangleIndex(index))
return nullptr;
return demangleArchetypeRef(0, index);
}
if (c == 'R') {
NodePointer byref = Node::makeNodePointer(Node::Kind::ByRef);
NodePointer type = demangleTypeImpl();
if (!type)
return nullptr;
byref->push_back_child(type);
return byref;
}
if (c == 'S') {
return demangleSubstitutionIndex();
}
if (c == 'T') {
return demangleTuple(IsVariadic::no);
}
if (c == 't') {
return demangleTuple(IsVariadic::yes);
}
if (c == 'U') {
ArchetypeCounts.push_back(ArchetypeCount);
NodePointer archetypes = demangleArchetypes();
if (!archetypes)
return nullptr;
NodePointer base = demangleType();
if (!base)
return nullptr;
ArchetypeCount = ArchetypeCounts.back();
ArchetypeCounts.pop_back();
NodePointer generics = Node::makeNodePointer(Node::Kind::GenericType);
generics->push_back_child(archetypes);
generics->push_back_child(base);
return generics;
}
if (c == 'X') {
if (c == 'o') {
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer unowned = Node::makeNodePointer(Node::Kind::Unowned);
unowned->setNextNode(type);
return unowned;
}
if (c == 'w') {
NodePointer type = demangleType();
if (!type)
return nullptr;
NodePointer unowned = Node::makeNodePointer(Node::Kind::Weak);
unowned->setNextNode(type);
return unowned;
}
return nullptr;
}
if (isStartOfNominalType(c)) {
NodePointer nominal_type = demangleDeclarationName(nominalTypeMarkerToNodeKind(c));
return nominal_type;
}
return nullptr;
}
class MangledNameSource {
public:
MangledNameSource(StringRef mangled);
char peek();
bool nextIf(char c);
char next();
bool isEmpty();
explicit operator bool();
std::string slice(size_t size);
std::string getString();
size_t getOffset();
size_t getSize();
bool hasAtLeast(size_t n);
void advanceOffset(size_t by);
private:
StringRef Mangled;
size_t Offset;
};
std::vector<Substitution> Substitutions;
std::vector<int> ArchetypeCounts;
int ArchetypeCount;
MangledNameSource Mangled;
NodePointer RootNode;
NodePointer CurrentNode;
};
Demangler::MangledNameSource::MangledNameSource(StringRef Mangled)
: Mangled(Mangled), Offset(0) {}
char Demangler::MangledNameSource::peek() { return Mangled.front(); }
bool Demangler::MangledNameSource::nextIf(char c) {
if (isEmpty())
return false;
char real_c = peek();
if (real_c == c) {
advanceOffset(1);
return true;
}
return false;
}
char Demangler::MangledNameSource::next() {
char c = peek();
advanceOffset(1);
return c;
}
bool Demangler::MangledNameSource::isEmpty() { return Mangled.empty(); }
Demangler::MangledNameSource::operator bool() { return isEmpty() == false; }
std::string Demangler::MangledNameSource::slice(size_t size) {
return Mangled.substr(0, size);
}
std::string Demangler::MangledNameSource::getString() { return Mangled.data(); }
size_t Demangler::MangledNameSource::getOffset() { return Offset; }
size_t Demangler::MangledNameSource::getSize() { return Mangled.size(); }
bool Demangler::MangledNameSource::hasAtLeast(size_t n) {
if (n > getSize())
return false;
return true;
}
void Demangler::MangledNameSource::advanceOffset(size_t by) {
Offset += by;
Mangled = Mangled.substr(by);
}
NodePointer swift::Demangle::demangleSymbolAsNode(llvm::StringRef mangled) {
Demangler demangler(mangled);
demangler.demangle();
return demangler.getDemangled();
}
void toString(NodePointer pointer, DemanglerPrinter &printer);
void toStringChildren (Node::iterator begin, Node::iterator end, DemanglerPrinter &printer, const char *sep = nullptr) {
for (; begin != end;) {
toString(*begin, printer);
++begin;
if (sep && begin != end)
printer << sep;
}
}
void toStringChildren (NodePointer pointer, DemanglerPrinter &printer, const char *sep = nullptr) {
if (!pointer)
return;
Node::iterator begin = pointer->begin(), end = pointer->end();
toStringChildren(begin, end, printer, sep);
}
void toStringLifeCycleEntity (NodePointer pointer, DemanglerPrinter &printer, const char* name) {
NodePointer child = pointer->child_at(0);
if (child->getKind() == Node::Kind::Path) {
toString(child, printer);
printer << ".";
}
else {
while (child) {
printer << child->getText();
child = child->getNextNode();
if (child)
printer << ".";
}
}
printer << name;
if (pointer->size() > 1) {
child = pointer->child_at(1);
if (child) {
printer << " : ";
toString(child, printer);
}
}
}
NodePointer getFirstChildOfKind (NodePointer pointer, Node::Kind kind) {
if (!pointer)
return nullptr;
for (NodePointer child : *pointer) {
if (child && child->getKind() == kind)
return child;
}
return nullptr;
}
bool typeNeedsColonForDecl (NodePointer type) {
if (!type)
return false;
if (type->size() == 0)
return false;
NodePointer child = type->child_at(0);
if (!child)
return false;
Node::Kind child_kind = child->getKind();
switch (child_kind) {
case Node::Kind::UncurriedFunctionType:
case Node::Kind::FunctionType:
return false;
case Node::Kind::GenericType:
return typeNeedsColonForDecl(getFirstChildOfKind(type, Node::Kind::UncurriedFunctionType));
default:
return true;
}
}
void toString(NodePointer pointer, DemanglerPrinter &printer) {
while (pointer) {
Node::Kind kind = pointer->getKind();
switch (kind) {
case swift::Demangle::Node::Kind::Failure:
return;
case swift::Demangle::Node::Kind::Directness:
printer << pointer->getText() << " ";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::LocalEntity:
printer << "local ";
SWIFT_FALLTHROUGH;
case swift::Demangle::Node::Kind::Declaration:
{
NodePointer path = getFirstChildOfKind(pointer, Node::Kind::Path);
NodePointer type = getFirstChildOfKind(pointer, Node::Kind::Type);
toString(path, printer);
if (typeNeedsColonForDecl(type))
printer << " : ";
else
printer << " ";
toString(type, printer);
break;
}
case swift::Demangle::Node::Kind::Path:
{
toStringChildren(pointer, printer, ".");
break;
}
case swift::Demangle::Node::Kind::Type:
{
toString(pointer->child_at(0), printer);
break;
}
case swift::Demangle::Node::Kind::Module:
case swift::Demangle::Node::Kind::Class:
case swift::Demangle::Node::Kind::Structure:
case swift::Demangle::Node::Kind::Union:
printer << pointer->getText();
break;
case swift::Demangle::Node::Kind::Identifier:
printer << pointer->getText();
break;
case swift::Demangle::Node::Kind::FunctionName:
break;
case swift::Demangle::Node::Kind::FunctionType:
toStringChildren(pointer, printer);
break;
case swift::Demangle::Node::Kind::DeclarationName:
break;
case swift::Demangle::Node::Kind::DeclarationType:
toStringChildren(pointer, printer, ".");
break;
case swift::Demangle::Node::Kind::UncurriedFunctionType: {
NodePointer metatype = pointer->child_at(0);
if (!metatype)
break;
printer << "(";
toString(metatype, printer);
printer << ")";
NodePointer real_func = pointer->child_at(1);
if (!real_func)
break;
real_func = real_func->child_at(0);
toStringChildren(real_func, printer);
break;
}
case swift::Demangle::Node::Kind::ArgumentTuple: {
bool need_parens = false;
if (pointer->size() > 1)
need_parens = true;
else {
if (pointer->size() == 0)
need_parens = true;
else {
Node::Kind child0_kind = pointer->child_at(0)->child_at(0)->getKind();
if (child0_kind != Node::Kind::VariadicTuple &&
child0_kind != Node::Kind::NonVariadicTuple)
need_parens = true;
}
}
if (need_parens)
printer << "(";
toStringChildren(pointer, printer);
if (need_parens)
printer << ")";
break;
}
case swift::Demangle::Node::Kind::NonVariadicTuple:
case swift::Demangle::Node::Kind::VariadicTuple: {
printer << "(";
toStringChildren(pointer, printer, ", ");
if (pointer->getKind() == swift::Demangle::Node::Kind::VariadicTuple)
printer << "...";
printer << ")";
break;
}
case swift::Demangle::Node::Kind::TupleElement: {
if (pointer->size() == 1) {
NodePointer type = pointer->child_at(0);
toString(type, printer);
} else if (pointer->size() == 2) {
NodePointer id = pointer->child_at(0);
NodePointer type = pointer->child_at(1);
toString(id, printer);
toString(type, printer);
}
break;
}
case swift::Demangle::Node::Kind::TupleElementName:
printer << pointer->getText() << " : ";
break;
case swift::Demangle::Node::Kind::TupleElementType:
printer << pointer->getText();
break;
case swift::Demangle::Node::Kind::ReturnType: {
if (pointer->size() == 0)
printer << " -> " << pointer->getText();
else {
printer << " -> ";
toStringChildren(pointer, printer);
}
break;
}
case swift::Demangle::Node::Kind::Weak:
printer << "[weak] ";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::Unowned:
printer << "[unowned] ";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::ByRef:
printer << "[byref] ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::ObjCAttribute:
printer << "[objc] ";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::BuiltinTypeName:
case swift::Demangle::Node::Kind::BaseName:
case swift::Demangle::Node::Kind::Number:
printer << pointer->getText();
break;
case swift::Demangle::Node::Kind::ArrayType: {
NodePointer type = pointer->child_at(0);
NodePointer size = pointer->child_at(1);
toString(type, printer);
printer << "[";
toString(size, printer);
printer << "]";
break;
}
case swift::Demangle::Node::Kind::InfixOperator:
printer << pointer->getText() << " [infix]";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::PrefixOperator:
printer << pointer->getText() << " [prefix]";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::PostfixOperator:
printer << pointer->getText() << " [postfix]";
pointer = pointer->getNextNode(); continue;
case swift::Demangle::Node::Kind::DependentProtocolWitnessTableGenerator:
printer << "dependent protocol witness table generator for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::DependentProtocolWitnessTableTemplate:
printer << "dependent protocol witness table template for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::LazyProtocolWitnessTableAccessor:
printer << "lazy protocol witness table accessor for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::LazyProtocolWitnessTableTemplate:
printer << "lazy protocol witness table template for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::ProtocolWitnessTable:
printer << "protocol witness table for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::ProtocolWitness:
printer << "protocol witness for ";
{
NodePointer path = getFirstChildOfKind(pointer, Node::Kind::Path);
NodePointer type = getFirstChildOfKind(pointer, Node::Kind::Type);
toString(path,printer);
if (typeNeedsColonForDecl(type))
printer << " : ";
else
printer << " ";
toString(type, printer);
break;
}
case swift::Demangle::Node::Kind::FieldOffset:
printer << "field offset for ";
{
NodePointer path = getFirstChildOfKind(pointer, Node::Kind::Path);
NodePointer type = getFirstChildOfKind(pointer, Node::Kind::Type);
toString(path,printer);
if (typeNeedsColonForDecl(type))
printer << " : ";
else
printer << " ";
toString(type, printer);
break;
}
case swift::Demangle::Node::Kind::BridgeToBlockFunction:
printer << "bridge-to-block function for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::GenericTypeMetadataPattern:
printer << "generic type metadata pattern for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::Metaclass:
printer << "metaclass for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::TypeMetadata:
printer << "type metadata for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::ValueWitnessKind:
printer << pointer->getText() << " value witness for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::ValueWitnessTable:
printer << "value witness table for ";
pointer = pointer->child_at(0); continue;
case swift::Demangle::Node::Kind::WitnessTableOffset:
printer << "witness table offset for ";
{
NodePointer path = getFirstChildOfKind(pointer, Node::Kind::Path);
NodePointer type = getFirstChildOfKind(pointer, Node::Kind::Type);
toString(path,printer);
if (typeNeedsColonForDecl(type))
printer << " : ";
else
printer << " ";
toString(type, printer);
break;
}
case swift::Demangle::Node::Kind::GenericTypeApplication: {
NodePointer typelist = pointer->child_at(0);
if (!typelist)
break;
NodePointer type0 = typelist->child_at(0);
toString(type0, printer);
printer << "<";
Node::size_type count = typelist->size();
for (Node::size_type i = 1; i < count;) {
toString(typelist->child_at(i), printer);
if (++i < count)
printer << ", ";
}
printer << ">";
break;
}
case swift::Demangle::Node::Kind::TypeListEntry:
toStringChildren(pointer, printer);
break;
case swift::Demangle::Node::Kind::ObjCBlock: {
printer << "[objc_block] ";
NodePointer tuple = pointer->child_at(0);
NodePointer rettype = pointer->child_at(1);
toString(tuple, printer);
toString(rettype, printer);
break;
}
case swift::Demangle::Node::Kind::MetaType: {
NodePointer type = pointer->child_at(0);
toString(type, printer);
printer << ".metatype";
break;
}
case swift::Demangle::Node::Kind::Protocol:
case swift::Demangle::Node::Kind::ArchetypeRef:
printer << pointer->getText();
break;
case swift::Demangle::Node::Kind::ProtocolList: {
if (pointer->size() == 1) {
toString(pointer->child_at(0), printer);
break;
}
printer << "protocol<";
toStringChildren(pointer, printer, ", ");
printer << ">";
break;
}
case swift::Demangle::Node::Kind::ArchetypeList: {
if (pointer->size() == 0)
break;
printer << "<";
toStringChildren(pointer, printer, ", ");
printer << ">";
break;
}
case swift::Demangle::Node::Kind::GenericType: {
NodePointer atype_list = pointer->child_at(0);
NodePointer fct_type = pointer->child_at(1)->child_at(0);
toString(atype_list, printer);
toString(fct_type, printer);
break;
}
case swift::Demangle::Node::Kind::Addressor: {
printer << "addressor";
break;
}
case swift::Demangle::Node::Kind::Getter: {
printer << "getter";
break;
}
case swift::Demangle::Node::Kind::Setter: {
printer << "setter";
break;
}
case swift::Demangle::Node::Kind::Allocator:
printer << "__allocating_constructor";
break;
case swift::Demangle::Node::Kind::Constructor:
printer << "constructor";
break;
case swift::Demangle::Node::Kind::Destructor:
printer << "destructor";
break;
case swift::Demangle::Node::Kind::Deallocator:
printer << "__deallocating_destructor";
break;
case swift::Demangle::Node::Kind::ProtocolConformance: {
NodePointer child0 = pointer->child_at(0);
NodePointer child1 = pointer->child_at(1);
NodePointer child2 = pointer->child_at(2);
if (!child0 || !child1 || !child2)
break;
toString(child0, printer);
printer << " : ";
toString(child1, printer);
printer << " in ";
toString(child2, printer);
break;
}
case swift::Demangle::Node::Kind::Substitution:
case swift::Demangle::Node::Kind::TypeName:
case swift::Demangle::Node::Kind::TypeList:
case swift::Demangle::Node::Kind::ArchetypeAndProtocol: {
NodePointer child0 = pointer->child_at(0);
NodePointer child1 = pointer->child_at(1);
toString(child0, printer);
printer << " : ";
toString(child1, printer);
break;
}
case swift::Demangle::Node::Kind::Unknown:
break;
}
pointer.reset();
}
}
std::string swift::Demangle::nodeToString(NodePointer pointer) {
if (!pointer)
return "";
DemanglerPrinter printer;
toString(pointer, printer);
return printer.str();
}
std::string swift::Demangle::demangleSymbolAsString(llvm::StringRef mangled) {
std::string demangling = nodeToString(demangleSymbolAsNode(mangled));
if (demangling.empty())
return mangled.str();
return demangling;
}