Files
swift-mirror/lib/Basic/Demangler.cpp
Erik Eckstein 684092d7d1 Mangling: mangler, demangler and remangler classes for the new mangling scheme.
Following classes provide symbol mangling for specific purposes:
*) Mangler: the base mangler class, just providing some basic utilities
*) ASTMangler: for mangling AST declarations
*) SpecializationMangler: to be used in the optimizer for mangling specialized function names
*) IRGenMangler: mangling all kind of symbols in IRGen

All those classes are not used yet, so it’s basically a NFC.

Another change is that some demangler node types are added (either because they were missing or the new demangler needs them).
Those new nodes also need to be handled in the old demangler, but this should also be a NFC as those nodes are not created by the old demangler.

My plan is to keep the old and new mangling implementation in parallel for some time. After that we can remove the old mangler.
Currently the new implementation is scoped in the NewMangling namespace. This namespace should be renamed after the old mangler is removed.
2016-12-02 15:55:30 -08:00

1532 lines
51 KiB
C++

//===--- Demangler.cpp - String to Node-Tree Demangling -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 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 new Swift de-mangler.
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/Demangler.h"
#include "swift/Basic/ManglingUtils.h"
#include "swift/Basic/ManglingMacros.h"
#include "swift/Basic/Punycode.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/Basic/Range.h"
#include "swift/Strings.h"
#include "llvm/Support/ErrorHandling.h"
using namespace swift;
using swift::Demangle::FunctionSigSpecializationParamKind;
namespace {
static bool isDeclName(Node::Kind kind) {
switch (kind) {
case Node::Kind::Identifier:
case Node::Kind::LocalDeclName:
case Node::Kind::PrivateDeclName:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
case Node::Kind::InfixOperator:
return true;
default:
return false;
}
}
static bool isContext(Node::Kind kind) {
switch (kind) {
#define NODE(ID)
#define CONTEXT_NODE(ID) \
case Node::Kind::ID:
#include "swift/Basic/DemangleNodes.def"
return true;
default:
return false;
}
}
static bool isNominal(Node::Kind kind) {
switch (kind) {
case Node::Kind::Structure:
case Node::Kind::Class:
case Node::Kind::Enum:
case Node::Kind::Protocol:
return true;
default:
return false;
}
}
static bool isEntity(Node::Kind kind) {
// Also accepts some kind which are not entities.
if (kind == Node::Kind::Type)
return true;
return isContext(kind);
}
static bool isRequirement(Node::Kind kind) {
switch (kind) {
case Node::Kind::DependentGenericSameTypeRequirement:
case Node::Kind::DependentGenericConformanceRequirement:
return true;
default:
return false;
}
}
} // anonymous namespace
namespace swift {
namespace NewMangling {
NodePointer Demangler::demangleTopLevel() {
if (!nextIf(MANGLING_PREFIX_STR))
return nullptr;
NodePointer topLevel = NodeFactory::create(Node::Kind::Global);
int Idx = 0;
while (!Text.empty()) {
NodePointer Node = demangleOperator();
if (!Node)
break;
pushNode(Node);
Idx++;
}
bool beforeSpecializtions = false;
for (const NodeWithPos &NWP : reversed(NodeStack)) {
switch (NWP.Node->getKind()) {
case Node::Kind::FunctionSignatureSpecialization:
case Node::Kind::GenericSpecialization:
case Node::Kind::GenericSpecializationNotReAbstracted:
topLevel->addChild(NWP.Node);
beforeSpecializtions = true;
break;
default:
break;
}
}
for (const NodeWithPos &NWP : NodeStack) {
NodePointer Nd = NWP.Node;
switch (Nd->getKind()) {
case Node::Kind::FunctionSignatureSpecialization:
case Node::Kind::GenericSpecialization:
case Node::Kind::GenericSpecializationNotReAbstracted:
beforeSpecializtions = false;
break;
case Node::Kind::Type:
topLevel->addChild(Nd->getFirstChild());
break;
case Node::Kind::Identifier:
if (beforeSpecializtions &&
StringRef(Nd->getText()).startswith("_T")) {
NodePointer Global = demangleSymbolAsNode(Nd->getText());
if (Global && Global->getKind() == Node::Kind::Global) {
for (NodePointer Child : *Global) {
topLevel->addChild(Child);
}
break;
}
}
SWIFT_FALLTHROUGH;
default:
topLevel->addChild(Nd);
break;
}
}
size_t EndPos = (NodeStack.empty() ? 0 : NodeStack.back().Pos);
if (EndPos < Text.size()) {
topLevel->addChild(NodeFactory::create(Node::Kind::Suffix,
Text.substr(EndPos)));
}
return topLevel;
}
NodePointer Demangler::changeKind(NodePointer Node, Node::Kind NewKind) {
if (!Node)
return nullptr;
NodePointer NewNode;
if (Node->hasText()) {
NewNode = NodeFactory::create(NewKind, Node->getText());
} else if (Node->hasIndex()) {
NewNode = NodeFactory::create(NewKind, Node->getIndex());
} else {
NewNode = NodeFactory::create(NewKind);
}
for (NodePointer Child : *Node) {
NewNode->addChild(Child);
}
return NewNode;
}
NodePointer Demangler::demangleOperator() {
switch (char c = nextChar()) {
case 'A': return demangleMultiSubstitutions();
case 'B': return demangleBuiltinType();
case 'C': return demangleNominalType(Node::Kind::Class);
case 'E': return demangleExtensionContext();
case 'F': return demanglePlainFunction();
case 'G': return demangleBoundGenericType();
case 'I': return demangleImplFunctionType();
case 'K': return NodeFactory::create(Node::Kind::ThrowsAnnotation);
case 'L': return demangleLocalIdentifier();
case 'M': return demangleMetatype();
case 'N': return createWithChild(Node::Kind::TypeMetadata,
popNode(Node::Kind::Type));
case 'O': return demangleNominalType(Node::Kind::Enum);
case 'P': return demangleNominalType(Node::Kind::Protocol);
case 'Q': return demangleArchetype();
case 'R': return demangleGenericRequirement();
case 'S': return demangleKnownType();
case 'T': return demangleThunkOrSpecialization();
case 'V': return demangleNominalType(Node::Kind::Structure);
case 'W': return demangleWitness();
case 'X': return demangleSpecialType();
case 'Z': return createWithChild(Node::Kind::Static, popNode(isEntity));
case 'a': return demangleTypeAlias();
case 'c': return popFunctionType(Node::Kind::FunctionType);
case 'd': return NodeFactory::create(Node::Kind::VariadicMarker);
case 'f': return demangleFunctionEntity();
case 'i': return demangleEntity(Node::Kind::Subscript);
case 'l': return demangleGenericSignature(/*hasParamCounts*/ false);
case 'm': return createType(createWithChild(Node::Kind::Metatype,
popNode(Node::Kind::Type)));
case 'o': return demangleOperatorIdentifier();
case 'p': return demangleProtocolListType();
case 'q': return createType(demangleGenericParamIndex());
case 'r': return demangleGenericSignature(/*hasParamCounts*/ true);
case 's': return NodeFactory::create(Node::Kind::Module, STDLIB_NAME);
case 't': return popTuple();
case 'u': return demangleGenericType();
case 'v': return demangleEntity(Node::Kind::Variable);
case 'w': return demangleValueWitness();
case 'x': return createType(getDependentGenericParamType(0, 0));
case 'y': return NodeFactory::create(Node::Kind::EmptyList);
case 'z': return createType(createWithChild(Node::Kind::InOut,
popTypeAndGetChild()));
case '_': return NodeFactory::create(Node::Kind::FirstElementMarker);
default:
pushBack();
return demangleIdentifier();
}
}
int Demangler::demangleNatural() {
if (!isDigit(peekChar()))
return -1000;
int num = 0;
while (true) {
char c = peekChar();
if (!isDigit(c))
return num;
int newNum = (10 * num) + (c - '0');
if (newNum < num)
return -1000;
num = newNum;
nextChar();
}
}
int Demangler::demangleIndex() {
if (nextIf('_'))
return 0;
int num = demangleNatural();
if (num >= 0 && nextIf('_'))
return num + 1;
return -1000;
}
NodePointer Demangler::demangleIndexAsNode() {
int Idx = demangleIndex();
if (Idx >= 0)
return NodeFactory::create(Node::Kind::Number, Idx);
return nullptr;
}
NodePointer Demangler::demangleMultiSubstitutions() {
while (true) {
char c = nextChar();
if (isLowerLetter(c)) {
unsigned Idx = c - 'a';
if (Idx >= Substitutions.size())
return nullptr;
pushNode(Substitutions[Idx]);
continue;
}
if (isUpperLetter(c)) {
unsigned Idx = c - 'A';
if (Idx >= Substitutions.size())
return nullptr;
return Substitutions[Idx];
}
pushBack();
unsigned Idx = demangleIndex() + 26;
if (Idx >= Substitutions.size())
return nullptr;
return Substitutions[Idx];
}
}
NodePointer Demangler::createSwiftType(Node::Kind typeKind, StringRef name) {
return createType(createWithChildren(typeKind,
NodeFactory::create(Node::Kind::Module, STDLIB_NAME),
NodeFactory::create(Node::Kind::Identifier, name)));
}
NodePointer Demangler::demangleKnownType() {
switch (nextChar()) {
case 'o':
return NodeFactory::create(Node::Kind::Module, MANGLING_MODULE_OBJC);
case 'C':
return NodeFactory::create(Node::Kind::Module, MANGLING_MODULE_C);
case 'a':
return createSwiftType(Node::Kind::Structure, "Array");
case 'b':
return createSwiftType(Node::Kind::Structure, "Bool");
case 'c':
return createSwiftType(Node::Kind::Structure, "UnicodeScalar");
case 'd':
return createSwiftType(Node::Kind::Structure, "Double");
case 'f':
return createSwiftType(Node::Kind::Structure, "Float");
case 'i':
return createSwiftType(Node::Kind::Structure, "Int");
case 'V':
return createSwiftType(Node::Kind::Structure, "UnsafeRawPointer");
case 'v':
return createSwiftType(Node::Kind::Structure, "UnsafeMutableRawPointer");
case 'P':
return createSwiftType(Node::Kind::Structure, "UnsafePointer");
case 'p':
return createSwiftType(Node::Kind::Structure, "UnsafeMutablePointer");
case 'q':
return createSwiftType(Node::Kind::Enum, "Optional");
case 'Q':
return createSwiftType(Node::Kind::Enum, "ImplicitlyUnwrappedOptional");
case 'R':
return createSwiftType(Node::Kind::Structure, "UnsafeBufferPointer");
case 'r':
return createSwiftType(Node::Kind::Structure, "UnsafeMutableBufferPointer");
case 'S':
return createSwiftType(Node::Kind::Structure, "String");
case 'u':
return createSwiftType(Node::Kind::Structure, "UInt");
default:
return nullptr;
}
}
NodePointer Demangler::demangleIdentifier() {
bool hasWordSubsts = false;
bool isPunycoded = false;
char c = peekChar();
if (!isDigit(c))
return nullptr;
if (c == '0') {
nextChar();
if (peekChar() == '0') {
nextChar();
isPunycoded = true;
} else {
hasWordSubsts = true;
}
}
std::string Identifier;
do {
while (hasWordSubsts && isLetter(peekChar())) {
char c = nextChar();
int WordIdx = 0;
if (isLowerLetter(c)) {
WordIdx = c - 'a';
} else {
assert(isUpperLetter(c));
WordIdx = c - 'A';
hasWordSubsts = false;
}
if (WordIdx >= (int)Words.size())
return nullptr;
StringRef Slice = Words[WordIdx];
Identifier.append(Slice.data(), Slice.size());
}
if (nextIf('0'))
break;
int numChars = demangleNatural();
if (numChars <= 0)
return nullptr;
if (Pos + numChars >= Text.size())
return nullptr;
StringRef Slice = StringRef(Text.data() + Pos, numChars);
if (isPunycoded) {
nextIf('_');
if (!Punycode::decodePunycodeUTF8(Slice, Identifier))
return nullptr;
} else {
Identifier.append(Slice.data(), Slice.size());
int wordStartPos = -1;
for (int Idx = 0, End = (int)Slice.size(); Idx <= End; ++Idx) {
char c = (Idx < End ? Slice[Idx] : 0);
if (wordStartPos >= 0 && isWordEnd(c, Slice[Idx - 1])) {
if (Idx - wordStartPos >= 2) {
StringRef word(Slice.begin() + wordStartPos, Idx - wordStartPos);
Words.push_back(word);
}
wordStartPos = -1;
}
if (wordStartPos < 0 && isWordStart(c)) {
wordStartPos = Idx;
}
}
}
Pos += numChars;
} while (hasWordSubsts);
if (Identifier.empty())
return nullptr;
NodePointer Ident = NodeFactory::create(Node::Kind::Identifier, Identifier);
addSubstitution(Ident);
return Ident;
}
NodePointer Demangler::demangleOperatorIdentifier() {
NodePointer Ident = popNode(Node::Kind::Identifier);
static const char op_char_table[] = "& @/= > <*!|+?%-~ ^ .";
std::string OpStr;
OpStr.reserve(Ident->getText().size());
for (signed char c : Ident->getText()) {
if (c < 0) {
// Pass through Unicode characters.
OpStr.push_back(c);
continue;
}
if (!isLowerLetter(c))
return nullptr;
char o = op_char_table[c - 'a'];
if (o == ' ')
return nullptr;
OpStr.push_back(o);
}
switch (nextChar()) {
case 'i': return NodeFactory::create(Node::Kind::InfixOperator, OpStr);
case 'p': return NodeFactory::create(Node::Kind::PrefixOperator, OpStr);
case 'P': return NodeFactory::create(Node::Kind::PostfixOperator, OpStr);
default: return nullptr;
}
}
NodePointer Demangler::demangleLocalIdentifier() {
if (nextIf('L')) {
NodePointer discriminator = popNode(Node::Kind::Identifier);
NodePointer name = popNode(Node::Kind::Identifier);
return createWithChildren(Node::Kind::PrivateDeclName, discriminator, name);
}
NodePointer discriminator = demangleIndexAsNode();
NodePointer name = popNode(Node::Kind::Identifier);
return createWithChildren(Node::Kind::LocalDeclName, discriminator, name);
}
NodePointer Demangler::popModule() {
if (NodePointer Ident = popNode(Node::Kind::Identifier))
return changeKind(Ident, Node::Kind::Module);
return popNode(Node::Kind::Module);
}
NodePointer Demangler::popContext() {
if (NodePointer Mod = popModule())
return Mod;
if (NodePointer Ty = popNode(Node::Kind::Type)) {
if (Ty->getNumChildren() != 1)
return nullptr;
NodePointer Child = Ty->getFirstChild();
if (!isContext(Child->getKind()))
return nullptr;
return Child;
}
return popNode(isContext);
}
NodePointer Demangler::popTypeAndGetChild() {
NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty || Ty->getNumChildren() != 1)
return nullptr;
return Ty->getFirstChild();
}
NodePointer Demangler::popTypeAndGetNominal() {
NodePointer Child = popTypeAndGetChild();
if (Child && isNominal(Child->getKind()))
return Child;
return nullptr;
}
NodePointer Demangler::demangleBuiltinType() {
NodePointer Ty;
switch (nextChar()) {
case 'b':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.BridgeObject");
break;
case 'B':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.UnsafeValueBuffer");
break;
case 'f': {
int size = demangleIndex() - 1;
if (size <= 0)
return nullptr;
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
std::move(DemanglerPrinter() << "Builtin.Float" << size).str());
break;
}
case 'i': {
int size = demangleIndex() - 1;
if (size <= 0)
return nullptr;
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Int" << size).str());
break;
}
case 'v': {
int elts = demangleIndex() - 1;
if (elts <= 0)
return nullptr;
NodePointer EltType = popTypeAndGetChild();
if (!EltType || EltType->getKind() != Node::Kind::BuiltinTypeName ||
EltType->getText().find("Builtin.") != 0)
return nullptr;
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
(DemanglerPrinter() << "Builtin.Vec" << elts << "x" <<
EltType->getText().substr(sizeof("Builtin.") - 1)).str());
break;
}
case 'O':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.UnknownObject");
break;
case 'o':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.NativeObject");
break;
case 'p':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.RawPointer");
break;
case 'w':
Ty = NodeFactory::create(Node::Kind::BuiltinTypeName,
"Builtin.Word");
break;
default:
return nullptr;
}
return createType(Ty);
}
NodePointer Demangler::demangleNominalType(Node::Kind kind) {
NodePointer Name = popNode(isDeclName);
NodePointer Ctx = popContext();
NodePointer NTy = createType(createWithChildren(kind, Ctx, Name));
addSubstitution(NTy);
return NTy;
}
NodePointer Demangler::demangleTypeAlias() {
NodePointer Name = popNode(isDeclName);
NodePointer Ctx = popContext();
return createWithChildren(Node::Kind::TypeAlias, Ctx, Name);
}
NodePointer Demangler::demangleExtensionContext() {
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
NodePointer Module = popModule();
NodePointer Type = popTypeAndGetNominal();
NodePointer Ext = createWithChildren(Node::Kind::Extension, Module, Type);
if (GenSig)
Ext = addChild(Ext, GenSig);
return Ext;
}
NodePointer Demangler::demanglePlainFunction() {
NodePointer Func = NodeFactory::create(Node::Kind::Function);
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
NodePointer Type = popFunctionType(Node::Kind::FunctionType);
if (GenSig) {
Type = createType(createWithChildren(Node::Kind::DependentGenericType,
GenSig, Type));
}
NodePointer Name = popNode(isDeclName);
NodePointer Ctx = popContext();
return createWithChildren(Node::Kind::Function, Ctx, Name, Type);
}
NodePointer Demangler::popFunctionType(Node::Kind kind) {
NodePointer FuncType = NodeFactory::create(kind);
addChild(FuncType, popNode(Node::Kind::ThrowsAnnotation));
FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ArgumentTuple));
FuncType = addChild(FuncType, popFunctionParams(Node::Kind::ReturnType));
return createType(FuncType);
}
NodePointer Demangler::popFunctionParams(Node::Kind kind) {
NodePointer ParamsType;
if (popNode(Node::Kind::EmptyList)) {
ParamsType = createType(NodeFactory::create(Node::Kind::NonVariadicTuple));
} else {
ParamsType = popNode(Node::Kind::Type);
}
return createWithChild(kind, ParamsType);
}
NodePointer Demangler::popTuple() {
NodePointer Root = NodeFactory::create(popNode(Node::Kind::VariadicMarker) ?
Node::Kind::VariadicTuple :
Node::Kind::NonVariadicTuple);
if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> Nodes;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer TupleElmt = NodeFactory::create(Node::Kind::TupleElement);
if (NodePointer Ident = popNode(Node::Kind::Identifier)) {
TupleElmt->addChild(NodeFactory::create(Node::Kind::TupleElementName,
Ident->getText()));
}
NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty)
return nullptr;
TupleElmt->addChild(Ty);
Nodes.push_back(TupleElmt);
} while (!firstElem);
while (NodePointer TupleElmt = pop_back_val(Nodes)) {
Root->addChild(TupleElmt);
}
}
return createType(Root);
}
NodePointer Demangler::popTypeList() {
NodePointer Root = NodeFactory::create(Node::Kind::TypeList);
if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> Nodes;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty)
return nullptr;
Nodes.push_back(Ty);
} while (!firstElem);
while (NodePointer Ty = pop_back_val(Nodes)) {
Root->addChild(Ty);
}
}
return Root;
}
NodePointer Demangler::popProtocol() {
NodePointer Name = popNode(isDeclName);
NodePointer Ctx = popContext();
NodePointer Proto = createWithChildren(Node::Kind::Protocol, Ctx, Name);
return createType(Proto);
}
NodePointer Demangler::demangleBoundGenericType() {
NodePointer Nominal = popTypeAndGetNominal();
return createType(demangleBoundGenericArgs(Nominal));
}
NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal) {
if (!Nominal || Nominal->getNumChildren() < 2)
return nullptr;
NodePointer args = popTypeList();
if (!args)
return nullptr;
// Generic arguments for the outermost type come first.
NodePointer Context = Nominal->getFirstChild();
if (Context->getKind() != Node::Kind::Module &&
Context->getKind() != Node::Kind::Function &&
Context->getKind() != Node::Kind::Extension) {
NodePointer BoundParent = demangleBoundGenericArgs(Context);
// Rebuild this type with the new parent type, which may have
// had its generic arguments applied.
Nominal = createWithChildren(Nominal->getKind(), BoundParent,
Nominal->getChild(1));
if (!Nominal)
return nullptr;
}
// If there were no arguments at this level there is nothing left
// to do.
if (args->getNumChildren() == 0)
return Nominal;
Node::Kind kind;
switch (Nominal->getKind()) {
case Node::Kind::Class:
kind = Node::Kind::BoundGenericClass;
break;
case Node::Kind::Structure:
kind = Node::Kind::BoundGenericStructure;
break;
case Node::Kind::Enum:
kind = Node::Kind::BoundGenericEnum;
break;
default:
return nullptr;
}
return createWithChildren(kind, createType(Nominal), args);
}
NodePointer Demangler::demangleImplParamConvention() {
StringRef attr;
switch (nextChar()) {
case 'i': attr = "@in"; break;
case 'l': attr = "@inout"; break;
case 'b': attr = "@inout_aliasable"; break;
case 'n': attr = "@in_guaranteed"; break;
case 'x': attr = "@owned"; break;
case 'g': attr = "@guaranteed"; break;
case 'e': attr = "@deallocating"; break;
case 'y': attr = "@unowned"; break;
default:
pushBack();
return nullptr;
}
return createWithChild(Node::Kind::ImplParameter,
NodeFactory::create(Node::Kind::ImplConvention, attr));
}
NodePointer Demangler::demangleImplResultConvention(Node::Kind ConvKind) {
StringRef attr;
switch (nextChar()) {
case 'r': attr = "@out"; break;
case 'o': attr = "@owned"; break;
case 'd': attr = "@unowned"; break;
case 'u': attr = "@unowned_inner_pointer"; break;
case 'a': attr = "@autoreleased"; break;
default:
pushBack();
return nullptr;
}
return createWithChild(ConvKind,
NodeFactory::create(Node::Kind::ImplConvention, attr));
}
NodePointer Demangler::demangleImplFunctionType() {
NodePointer type = NodeFactory::create(Node::Kind::ImplFunctionType);
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
if (GenSig && nextIf('P'))
GenSig = changeKind(GenSig, Node::Kind::DependentPseudogenericSignature);
StringRef CAttr;
switch (nextChar()) {
case 'y': CAttr = "@callee_unowned"; break;
case 'g': CAttr = "@callee_guaranteed"; break;
case 'x': CAttr = "@callee_owned"; break;
case 't': CAttr = "@convention(thin)"; break;
default: return nullptr;
}
type->addChild(NodeFactory::create(Node::Kind::ImplConvention, CAttr));
StringRef FAttr;
switch (nextChar()) {
case 'B': FAttr = "@convention(block)"; break;
case 'C': FAttr = "@convention(c)"; break;
case 'M': FAttr = "@convention(method)"; break;
case 'O': FAttr = "@convention(objc_method)"; break;
case 'K': FAttr = "@convention(closure)"; break;
case 'W': FAttr = "@convention(witness_method)"; break;
default:
pushBack();
break;
}
if (!FAttr.empty())
type->addChild(NodeFactory::create(Node::Kind::ImplFunctionAttribute, FAttr));
addChild(type, GenSig);
int NumTypesToAdd = 0;
while (NodePointer Param = demangleImplParamConvention()) {
type = addChild(type, Param);
NumTypesToAdd++;
}
while (NodePointer Result = demangleImplResultConvention(
Node::Kind::ImplResult)) {
type = addChild(type, Result);
NumTypesToAdd++;
}
if (nextIf('z')) {
NodePointer ErrorResult = demangleImplResultConvention(
Node::Kind::ImplErrorResult);
if (!ErrorResult)
return nullptr;
type = addChild(type, ErrorResult);
NumTypesToAdd++;
}
if (!nextIf('_'))
return nullptr;
for (int Idx = 0; Idx < NumTypesToAdd; ++Idx) {
NodePointer ConvTy = popNode(Node::Kind::Type);
if (!ConvTy)
return nullptr;
type->getChild(type->getNumChildren() - Idx - 1)->addChild(ConvTy);
}
return createType(type);
}
NodePointer Demangler::demangleMetatype() {
switch (nextChar()) {
case 'f':
return createWithPoppedType(Node::Kind::FullTypeMetadata);
case 'P':
return createWithPoppedType(Node::Kind::GenericTypeMetadataPattern);
case 'a':
return createWithPoppedType(Node::Kind::TypeMetadataAccessFunction);
case 'L':
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
case 'm':
return createWithPoppedType(Node::Kind::Metaclass);
case 'n':
return createWithPoppedType(Node::Kind::NominalTypeDescriptor);
case 'p':
return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
case 'B':
return createWithChild(Node::Kind::ReflectionMetadataBuiltinDescriptor,
popNode(Node::Kind::Type));
case 'F':
return createWithChild(Node::Kind::ReflectionMetadataFieldDescriptor,
popNode(Node::Kind::Type));
case 'A':
return createWithChild(Node::Kind::ReflectionMetadataAssocTypeDescriptor,
popProtocolConformance());
case 'C':
return createWithChild(Node::Kind::ReflectionMetadataSuperclassDescriptor,
popNode(isNominal));
default:
return nullptr;
}
}
static std::string getArchetypeName(Node::IndexType index,
Node::IndexType depth) {
DemanglerPrinter name;
do {
name << (char)('A' + (index % 26));
index /= 26;
} while (index);
if (depth != 0)
name << depth;
return std::move(name).str();
}
NodePointer Demangler::createArchetypeRef(int depth, int i) {
if (depth < 0 || i < 0)
return nullptr;
// FIXME: Name won't match demangled context generic signatures correctly.
auto ref = NodeFactory::create(Node::Kind::ArchetypeRef,
getArchetypeName(i, depth));
ref->addChild(NodeFactory::create(Node::Kind::Index, depth));
ref->addChild(NodeFactory::create(Node::Kind::Index, i));
return createType(ref);
}
NodePointer Demangler::demangleArchetype() {
int index = demangleIndex();
if (index >= 0)
return createArchetypeRef(0, index);
switch (nextChar()) {
case 'a': {
NodePointer Ident = popNode(Node::Kind::Identifier);
NodePointer ArcheTy = popTypeAndGetChild();
NodePointer AssocTy = createType(
createWithChildren(Node::Kind::AssociatedTypeRef, ArcheTy, Ident));
addSubstitution(AssocTy);
return AssocTy;
}
case 'd': {
int depth = demangleIndex() + 1;
int index = demangleIndex();
return createArchetypeRef(depth, index);
}
case 'q': {
NodePointer Idx = demangleIndexAsNode();
NodePointer Ctx = popContext();
NodePointer DeclCtx = createWithChild(Node::Kind::DeclContext, Ctx);
return createType(createWithChildren(Node::Kind::QualifiedArchetype,
Idx, DeclCtx));
}
case 'P':
// TODO: self type of protocol
return nullptr;
case 'y': {
NodePointer T = demangleAssociatedTypeSimple(demangleGenericParamIndex());
addSubstitution(T);
return T;
}
case 'z': {
NodePointer T = demangleAssociatedTypeSimple(getDependentGenericParamType(0, 0));
addSubstitution(T);
return T;
}
case 'Y': {
NodePointer T = demangleAssociatedTypeCompound(demangleGenericParamIndex());
addSubstitution(T);
return T;
}
case 'Z': {
NodePointer T = demangleAssociatedTypeCompound(getDependentGenericParamType(0, 0));
addSubstitution(T);
return T;
}
default:
return nullptr;
}
}
NodePointer Demangler::demangleAssociatedTypeSimple(
NodePointer GenericParamIdx) {
NodePointer GPI = createType(GenericParamIdx);
NodePointer ATName = popAssocTypeName();
return createType(createWithChildren(Node::Kind::DependentMemberType,
GPI, ATName));
}
NodePointer Demangler::demangleAssociatedTypeCompound(
NodePointer GenericParamIdx) {
std::vector<NodePointer> AssocTyNames;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer AssocTyName = popAssocTypeName();
if (!AssocTyName)
return nullptr;
AssocTyNames.push_back(AssocTyName);
} while (!firstElem);
NodePointer Base = GenericParamIdx;
while (NodePointer AssocTy = pop_back_val(AssocTyNames)) {
NodePointer depTy = NodeFactory::create(Node::Kind::DependentMemberType);
depTy = addChild(depTy, createType(Base));
Base = addChild(depTy, AssocTy);
}
return createType(Base);
}
NodePointer Demangler::popAssocTypeName() {
NodePointer Proto = popNode(Node::Kind::Type);
if (Proto && Proto->getFirstChild()->getKind() != Node::Kind::Protocol)
return nullptr;
NodePointer Id = popNode(Node::Kind::Identifier);
NodePointer AssocTy = changeKind(Id, Node::Kind::DependentAssociatedTypeRef);
addChild(AssocTy, Proto);
return AssocTy;
}
NodePointer Demangler::getDependentGenericParamType(int depth, int index) {
if (depth < 0 || index < 0)
return nullptr;
DemanglerPrinter PrintName;
PrintName << getArchetypeName(index, depth);
auto paramTy = NodeFactory::create(Node::Kind::DependentGenericParamType,
std::move(PrintName).str());
paramTy->addChild(NodeFactory::create(Node::Kind::Index, depth));
paramTy->addChild(NodeFactory::create(Node::Kind::Index, index));
return paramTy;
}
NodePointer Demangler::demangleGenericParamIndex() {
if (nextIf('d')) {
int depth = demangleIndex() + 1;
int index = demangleIndex();
return getDependentGenericParamType(depth, index);
}
if (nextIf('z')) {
return getDependentGenericParamType(0, 0);
}
return getDependentGenericParamType(0, demangleIndex() + 1);
}
NodePointer Demangler::popProtocolConformance() {
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
NodePointer Module = popModule();
NodePointer Proto = popProtocol();
NodePointer Type = popNode(Node::Kind::Type);
if (GenSig) {
Type = createType(createWithChildren(Node::Kind::DependentGenericType,
GenSig, Type));
}
return createWithChildren(Node::Kind::ProtocolConformance,
Type, Proto, Module);
}
NodePointer Demangler::demangleThunkOrSpecialization() {
switch (char c = nextChar()) {
case 'c': return createWithChild(Node::Kind::CurryThunk, popNode(isEntity));
case 'o': return swapWith(Node::Kind::ObjCAttribute);
case 'O': return swapWith(Node::Kind::NonObjCAttribute);
case 'D': return swapWith(Node::Kind::DynamicAttribute);
case 'd': return swapWith(Node::Kind::DirectMethodReferenceAttribute);
case 'V': return swapWith(Node::Kind::VTableAttribute);
case 'W': {
NodePointer Entity = popNode(isEntity);
NodePointer Conf = popProtocolConformance();
return createWithChildren(Node::Kind::ProtocolWitness, Conf, Entity);
}
case 'R':
case 'r': {
NodePointer Thunk = NodeFactory::create(c == 'R' ?
Node::Kind::ReabstractionThunkHelper :
Node::Kind::ReabstractionThunk);
if (NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature))
addChild(Thunk, GenSig);
NodePointer Ty2 = popNode(Node::Kind::Type);
Thunk = addChild(Thunk, popNode(Node::Kind::Type));
return addChild(Thunk, Ty2);
}
case 'A':
return createWithChild(Node::Kind::PartialApplyForwarder, popNode());
case 'a':
return createWithChild(Node::Kind::PartialApplyObjCForwarder, popNode());
case'g':
return demangleGenericSpecialization(Node::Kind::GenericSpecialization);
case'G':
return demangleGenericSpecialization(Node::Kind::
GenericSpecializationNotReAbstracted);
case'f':
return demangleFunctionSpecialization();
default:
return nullptr;
}
}
NodePointer Demangler::demangleGenericSpecialization(Node::Kind SpecKind) {
NodePointer Spec = demangleSpecAttributes(SpecKind);
NodePointer TyList = popTypeList();
if (!TyList)
return nullptr;
for (NodePointer Ty : *TyList) {
Spec->addChild(createWithChild(Node::Kind::GenericSpecializationParam, Ty));
}
return Spec;
}
NodePointer Demangler::demangleFunctionSpecialization() {
NodePointer Spec = demangleSpecAttributes(
Node::Kind::FunctionSignatureSpecialization);
unsigned ParamIdx = 0;
while (Spec && !nextIf('_')) {
Spec = addChild(Spec, demangleFuncSpecParam(ParamIdx));
ParamIdx++;
}
if (!nextIf('n'))
Spec = addChild(Spec, demangleFuncSpecParam(Node::IndexType(~0)));
return Spec;
}
NodePointer Demangler::demangleFuncSpecParam(Node::IndexType ParamIdx) {
NodePointer Param = NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParam, ParamIdx);
switch (nextChar()) {
case 'n':
return Param;
case 'c': {
std::vector<NodePointer> Types;
while (NodePointer Ty = popNode(Node::Kind::Type)) {
Types.push_back(Ty);
}
Param = addFuncSpecParamIdentifier(Param,
swift::Demangle::FunctionSigSpecializationParamKind::ClosureProp);
while (NodePointer Ty = pop_back_val(Types)) {
Param = addChild(Param, Ty);
}
return Param;
}
case 'p': {
switch (nextChar()) {
case 'f':
return addFuncSpecParamIdentifier(Param,
FunctionSigSpecializationParamKind::ConstantPropFunction);
case 'g':
return addFuncSpecParamIdentifier(Param,
FunctionSigSpecializationParamKind::ConstantPropGlobal);
case 'i':
return addFuncSpecParamNumber(Param,
FunctionSigSpecializationParamKind::ConstantPropInteger);
case 'd':
return addFuncSpecParamNumber(Param,
FunctionSigSpecializationParamKind::ConstantPropFloat);
case 's': {
StringRef Encoding;
switch (nextChar()) {
case 'b': Encoding = "u8"; break;
case 'w': Encoding = "u16"; break;
case 'c': Encoding = "objc"; break;
default: return nullptr;
}
NodePointer Str = popNode(Node::Kind::Identifier);
if (!Str)
return nullptr;
StringRef Text = Str->getText();
if (Text.size() > 0 && Text[0] == '_')
Text = Text.drop_front(1);
Param->addChild(NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind,
unsigned(swift::Demangle::FunctionSigSpecializationParamKind::
ConstantPropString)));
Param->addChild(NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamPayload,
Encoding));
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamPayload,
Text));
}
default:
return nullptr;
}
}
case 'd': {
unsigned Value = unsigned(FunctionSigSpecializationParamKind::Dead);
if (nextIf('G'))
Value |= unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed);
if (nextIf('X'))
Value |= unsigned(FunctionSigSpecializationParamKind::SROA);
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind, Value));
}
case 'g': {
unsigned Value = unsigned(FunctionSigSpecializationParamKind::
OwnedToGuaranteed);
if (nextIf('X'))
Value |= unsigned(FunctionSigSpecializationParamKind::SROA);
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind, Value));
}
case 'x':
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind,
unsigned(FunctionSigSpecializationParamKind::SROA)));
case 'i':
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind,
unsigned(FunctionSigSpecializationParamKind::BoxToValue)));
case 's':
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind,
unsigned(FunctionSigSpecializationParamKind::BoxToStack)));
default:
return nullptr;
}
}
NodePointer Demangler::addFuncSpecParamIdentifier(NodePointer Param,
FunctionSigSpecializationParamKind Kind,
StringRef FirstParam) {
NodePointer Name = popNode(Node::Kind::Identifier);
if (!Name)
return nullptr;
Param->addChild(NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind, unsigned(Kind)));
if (!FirstParam.empty()) {
Param->addChild(NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamPayload, FirstParam));
}
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamPayload, Name->getText()));
}
NodePointer Demangler::addFuncSpecParamNumber(NodePointer Param,
FunctionSigSpecializationParamKind Kind) {
Param->addChild(NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamKind, unsigned(Kind)));
std::string Str;
while (isDigit(peekChar())) {
Str += nextChar();
}
if (Str.empty())
return nullptr;
return addChild(Param, NodeFactory::create(
Node::Kind::FunctionSignatureSpecializationParamPayload, Str));
}
NodePointer Demangler::demangleSpecAttributes(Node::Kind SpecKind) {
NodePointer SpecNd = NodeFactory::create(SpecKind);
if (nextIf('q'))
SpecNd->addChild(NodeFactory::create(Node::Kind::SpecializationIsFragile));
int PassID = (int)nextChar() - '0';
if (PassID < 0 || PassID > 9)
return nullptr;
SpecNd->addChild(NodeFactory::create(Node::Kind::SpecializationPassID,
PassID));
return SpecNd;
}
NodePointer Demangler::demangleWitness() {
switch (nextChar()) {
case 'V':
return createWithChild(Node::Kind::ValueWitnessTable,
popNode(Node::Kind::Type));
case 'o':
return createWithChild(Node::Kind::WitnessTableOffset, popNode(isEntity));
case 'v': {
unsigned Directness;
switch (nextChar()) {
case 'd': Directness = unsigned(Directness::Direct); break;
case 'i': Directness = unsigned(Directness::Indirect); break;
default: return nullptr;
}
return createWithChildren(Node::Kind::FieldOffset,
NodeFactory::create(Node::Kind::Directness, Directness),
popNode(isEntity));
}
case 'P':
return createWithChild(Node::Kind::ProtocolWitnessTable,
popProtocolConformance());
case 'G':
return createWithChild(Node::Kind::GenericProtocolWitnessTable,
popProtocolConformance());
case 'I':
return createWithChild(
Node::Kind::GenericProtocolWitnessTableInstantiationFunction,
popProtocolConformance());
case 'l': {
NodePointer Conf = popProtocolConformance();
NodePointer Type = popNode(Node::Kind::Type);
return createWithChildren(Node::Kind::LazyProtocolWitnessTableAccessor,
Type, Conf);
}
case 'L': {
NodePointer Conf = popProtocolConformance();
NodePointer Type = popNode(Node::Kind::Type);
return createWithChildren(
Node::Kind::LazyProtocolWitnessTableCacheVariable, Type, Conf);
}
case 'a':
return createWithChild(Node::Kind::ProtocolWitnessTableAccessor,
popProtocolConformance());
case 't': {
NodePointer Name = popNode(isDeclName);
NodePointer Conf = popProtocolConformance();
return createWithChildren(Node::Kind::AssociatedTypeMetadataAccessor,
Conf, Name);
}
case 'T': {
NodePointer ProtoTy = createWithChild(Node::Kind::Type, popProtocol());
NodePointer Name = popNode(isDeclName);
NodePointer Conf = popProtocolConformance();
return createWithChildren(Node::Kind::AssociatedTypeMetadataAccessor,
Conf, Name, ProtoTy);
}
default:
return nullptr;
}
}
NodePointer Demangler::demangleSpecialType() {
switch (nextChar()) {
case 'f':
return popFunctionType(Node::Kind::ThinFunctionType);
case 'K':
return popFunctionType(Node::Kind::AutoClosureType);
case 'U':
return popFunctionType(Node::Kind::UncurriedFunctionType);
case 'B':
return popFunctionType(Node::Kind::ObjCBlock);
case 'C':
return popFunctionType(Node::Kind::CFunctionPointer);
case 'o':
return createType(createWithChild(Node::Kind::Unowned,
popNode(Node::Kind::Type)));
case 'u':
return createType(createWithChild(Node::Kind::Unmanaged,
popNode(Node::Kind::Type)));
case 'w':
return createType(createWithChild(Node::Kind::Weak,
popNode(Node::Kind::Type)));
case 'b':
return createType(createWithChild(Node::Kind::SILBoxType,
popNode(Node::Kind::Type)));
case 'D':
return createType(createWithChild(Node::Kind::DynamicSelf,
popNode(Node::Kind::Type)));
case 'M': {
NodePointer MTR = demangleMetatypeRepresentation();
NodePointer Type = popNode(Node::Kind::Type);
return createType(createWithChildren(Node::Kind::Metatype, MTR, Type));
}
case 'm': {
NodePointer MTR = demangleMetatypeRepresentation();
NodePointer Type = popNode(Node::Kind::Type);
return createType(createWithChildren(Node::Kind::ExistentialMetatype,
MTR, Type));
}
case 'p':
return createType(createWithChild(Node::Kind::ExistentialMetatype,
popNode(Node::Kind::Type)));
default:
return nullptr;
}
}
NodePointer Demangler::demangleMetatypeRepresentation() {
switch (nextChar()) {
case 't':
return NodeFactory::create(Node::Kind::MetatypeRepresentation, "@thin");
case 'T':
return NodeFactory::create(Node::Kind::MetatypeRepresentation, "@thick");
case 'o':
return NodeFactory::create(Node::Kind::MetatypeRepresentation,
"@objc_metatype");
default:
return nullptr;
}
}
NodePointer Demangler::demangleFunctionEntity() {
enum { None, Type, TypeAndName, TypeAndIndex, Index } Args;
Node::Kind Kind = Node::Kind::EmptyList;
switch (nextChar()) {
case 'D': Args = None; Kind = Node::Kind::Deallocator; break;
case 'd': Args = None; Kind = Node::Kind::Destructor; break;
case 'E': Args = None; Kind = Node::Kind::IVarDestroyer; break;
case 'e': Args = None; Kind = Node::Kind::IVarInitializer; break;
case 'i': Args = None; Kind = Node::Kind::Initializer; break;
case 'C': Args = Type; Kind = Node::Kind::Allocator; break;
case 'c': Args = Type; Kind = Node::Kind::Constructor; break;
case 'g': Args = TypeAndName; Kind = Node::Kind::Getter; break;
case 'G': Args = TypeAndName; Kind = Node::Kind::GlobalGetter; break;
case 's': Args = TypeAndName; Kind = Node::Kind::Setter; break;
case 'm': Args = TypeAndName; Kind = Node::Kind::MaterializeForSet; break;
case 'w': Args = TypeAndName; Kind = Node::Kind::WillSet; break;
case 'W': Args = TypeAndName; Kind = Node::Kind::DidSet; break;
case 'a':
Args = TypeAndName;
switch (nextChar()) {
case 'O': Kind = Node::Kind::OwningMutableAddressor; break;
case 'o': Kind = Node::Kind::NativeOwningMutableAddressor; break;
case 'P': Kind = Node::Kind::NativePinningMutableAddressor; break;
case 'u': Kind = Node::Kind::UnsafeMutableAddressor; break;
default: return nullptr;
}
break;
case 'l':
Args = TypeAndName;
switch (nextChar()) {
case 'O': Kind = Node::Kind::OwningAddressor; break;
case 'o': Kind = Node::Kind::NativeOwningAddressor; break;
case 'p': Kind = Node::Kind::NativePinningAddressor; break;
case 'u': Kind = Node::Kind::UnsafeAddressor; break;
default: return nullptr;
}
break;
case 'U': Args = TypeAndIndex; Kind = Node::Kind::ExplicitClosure; break;
case 'u': Args = TypeAndIndex; Kind = Node::Kind::ImplicitClosure; break;
case 'A': Args = Index; Kind = Node::Kind::DefaultArgumentInitializer; break;
default: return nullptr;
}
NodePointer Child1, Child2;
switch (Args) {
case None:
break;
case Type:
Child1 = popNode(Node::Kind::Type);
break;
case TypeAndName:
Child2 = popNode(Node::Kind::Type);
Child1 = popNode(isDeclName);
break;
case TypeAndIndex:
Child1 = demangleIndexAsNode();
Child2 = popNode(Node::Kind::Type);
break;
case Index:
Child1 = demangleIndexAsNode();
break;
}
NodePointer Entity = createWithChild(Kind, popContext());
switch (Args) {
case None:
break;
case Type:
case Index:
Entity = addChild(Entity, Child1);
break;
case TypeAndName:
case TypeAndIndex:
Entity = addChild(Entity, Child1);
Entity = addChild(Entity, Child2);
break;
}
return Entity;
}
NodePointer Demangler::demangleEntity(Node::Kind Kind) {
NodePointer Type = popNode(Node::Kind::Type);
NodePointer Name = popNode(isDeclName);
NodePointer Context = popContext();
return createWithChildren(Kind, Context, Name, Type);
}
NodePointer Demangler::demangleProtocolListType() {
NodePointer TypeList = NodeFactory::create(Node::Kind::TypeList);
NodePointer ProtoList = createWithChild(Node::Kind::ProtocolList, TypeList);
if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> ProtoNames;
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Proto = popProtocol();
if (!Proto)
return nullptr;
ProtoNames.push_back(Proto);
} while (!firstElem);
while (NodePointer Proto = pop_back_val(ProtoNames)) {
TypeList->addChild(Proto);
}
}
return createType(ProtoList);
}
NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) {
std::vector<NodePointer> Requirements;
while (NodePointer Req = popNode(isRequirement)) {
Requirements.push_back(Req);
}
NodePointer Sig = NodeFactory::create(Node::Kind::DependentGenericSignature);
if (hasParamCounts) {
while (!nextIf('l')) {
int count = 0;
if (!nextIf('z'))
count = demangleIndex() + 1;
if (count < 0)
return nullptr;
Sig->addChild(NodeFactory::create(Node::Kind::DependentGenericParamCount,
count));
}
} else {
Sig->addChild(NodeFactory::create(Node::Kind::DependentGenericParamCount,
1));
}
if (Sig->getNumChildren() == 0)
return nullptr;
while (NodePointer Req = pop_back_val(Requirements)) {
Sig->addChild(Req);
}
return Sig;
}
NodePointer Demangler::demangleGenericRequirement() {
enum { Generic, Assoc, CompoundAssoc, Substitution } TypeKind;
enum { Protocol, BaseClass, SameType } ConstraintKind;
switch (nextChar()) {
case 'c': ConstraintKind = BaseClass; TypeKind = Assoc; break;
case 'C': ConstraintKind = BaseClass; TypeKind = CompoundAssoc; break;
case 'b': ConstraintKind = BaseClass; TypeKind = Generic; break;
case 'B': ConstraintKind = BaseClass; TypeKind = Substitution; break;
case 't': ConstraintKind = SameType; TypeKind = Assoc; break;
case 'T': ConstraintKind = SameType; TypeKind = CompoundAssoc; break;
case 's': ConstraintKind = SameType; TypeKind = Generic; break;
case 'S': ConstraintKind = SameType; TypeKind = Substitution; break;
case 'p': ConstraintKind = Protocol; TypeKind = Assoc; break;
case 'P': ConstraintKind = Protocol; TypeKind = CompoundAssoc; break;
case 'Q': ConstraintKind = Protocol; TypeKind = Substitution; break;
default: ConstraintKind = Protocol; TypeKind = Generic; pushBack(); break;
}
NodePointer ConstrTy;
switch (TypeKind) {
case Generic:
ConstrTy = createType(demangleGenericParamIndex());
break;
case Assoc:
ConstrTy = demangleAssociatedTypeSimple(demangleGenericParamIndex());
addSubstitution(ConstrTy);
break;
case CompoundAssoc:
ConstrTy = demangleAssociatedTypeCompound(demangleGenericParamIndex());
addSubstitution(ConstrTy);
break;
case Substitution:
ConstrTy = popNode(Node::Kind::Type);
break;
}
switch (ConstraintKind) {
case Protocol:
return createWithChildren(
Node::Kind::DependentGenericConformanceRequirement,
ConstrTy, popProtocol());
case BaseClass:
return createWithChildren(
Node::Kind::DependentGenericConformanceRequirement,
ConstrTy, popNode(Node::Kind::Type));
case SameType:
return createWithChildren(Node::Kind::DependentGenericSameTypeRequirement,
ConstrTy, popNode(Node::Kind::Type));
}
}
NodePointer Demangler::demangleGenericType() {
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
NodePointer Ty = popNode(Node::Kind::Type);
return createType(createWithChildren(Node::Kind::DependentGenericType,
GenSig, Ty));
}
static int decodeValueWitnessKind(StringRef CodeStr) {
#define VALUE_WITNESS(MANGLING, NAME) \
if (CodeStr == #MANGLING) return (int)ValueWitnessKind::NAME;
#include "swift/Basic/ValueWitnessMangling.def"
return -1;
}
NodePointer Demangler::demangleValueWitness() {
char Code[2];
Code[0] = nextChar();
Code[1] = nextChar();
int Kind = decodeValueWitnessKind(StringRef(Code, 2));
if (Kind < 0)
return nullptr;
NodePointer VW = NodeFactory::create(Node::Kind::ValueWitness, unsigned(Kind));
return addChild(VW, popNode(Node::Kind::Type));
}
} // namespace NewMangler
} // namespace swift