Demangler: further speed improvements.

Avoid using std::string and std::vector in the demangler. Instead use vectors/strings with storage allocated by the NodeFactory’s bump pointer allocator.
This brings another 35% speedup. Especially in the case the Demangle::Context is not reused for subsequent demanglings.
This commit is contained in:
Erik Eckstein
2017-03-03 14:37:26 -08:00
parent 3456d04925
commit f220a3b727
3 changed files with 208 additions and 99 deletions

View File

@@ -207,6 +207,9 @@ public:
// Only to be used by the demangler parsers. // Only to be used by the demangler parsers.
void addChild(NodePointer Child, NodeFactory &Factory); void addChild(NodePointer Child, NodeFactory &Factory);
// Reverses the order of children.
void reverseChildren(size_t StartingAt = 0);
}; };
/// Returns true if the mangledName starts with the swift mangling prefix. /// Returns true if the mangledName starts with the swift mangling prefix.

View File

@@ -35,6 +35,8 @@ using llvm::StringRef;
namespace swift { namespace swift {
namespace Demangle { namespace Demangle {
class CharVector;
/// The allocator for demangling nodes and other demangling-internal stuff. /// The allocator for demangling nodes and other demangling-internal stuff.
/// ///
/// It implements a simple bump-pointer allocator. /// It implements a simple bump-pointer allocator.
@@ -77,14 +79,14 @@ public:
#endif #endif
} }
~NodeFactory() { virtual ~NodeFactory() {
freeSlabs(CurrentSlab); freeSlabs(CurrentSlab);
#ifdef NODE_FACTORY_DEBUGGING #ifdef NODE_FACTORY_DEBUGGING
std::cerr << "Delete NodeFactory " << this << "\n"; std::cerr << "Delete NodeFactory " << this << "\n";
#endif #endif
} }
void clear(); virtual void clear();
/// Allocates an object of type T or an array of objects of type T. /// Allocates an object of type T or an array of objects of type T.
template<typename T> T *Allocate(size_t NumObjects = 1) { template<typename T> T *Allocate(size_t NumObjects = 1) {
@@ -173,6 +175,12 @@ public:
/// The \p Text string is copied. /// The \p Text string is copied.
NodePointer createNode(Node::Kind K, llvm::StringRef Text); NodePointer createNode(Node::Kind K, llvm::StringRef Text);
/// Creates a node of kind \p K with a \p Text payload.
///
/// The \p Text string is already allocted with the Factory and therefore
/// it is _not_ copied.
NodePointer createNode(Node::Kind K, const CharVector &Text);
/// Creates a node of kind \p K with a \p Text payload, which must be a C /// Creates a node of kind \p K with a \p Text payload, which must be a C
/// string literal. /// string literal.
/// ///
@@ -180,6 +188,92 @@ public:
NodePointer createNode(Node::Kind K, const char *Text); NodePointer createNode(Node::Kind K, const char *Text);
}; };
/// A vector with a storage managed by a NodeFactory.
///
/// This Vector class only provides the minimal functionality needed by the
/// Demangler.
template<typename T> class Vector {
protected:
T *Elems = nullptr;
size_t NumElems = 0;
size_t Capacity = 0;
public:
typedef T *iterator;
Vector() { }
/// Construct a vector with an inital capacity.
explicit Vector(NodeFactory &Factory, size_t InitialCapacity) {
init(Factory, InitialCapacity);
}
/// Clears the content and re-allocates the buffer with an initial capacity.
void init(NodeFactory &Factory, size_t InitialCapacity) {
Elems = Factory.Allocate<T>(InitialCapacity);
NumElems = 0;
Capacity = InitialCapacity;
}
void free() {
Capacity = 0;
Elems = 0;
}
iterator begin() { return Elems; }
iterator end() { return Elems + NumElems; }
T &operator[](size_t Idx) {
assert(Idx < NumElems);
return Elems[Idx];
}
const T &operator[](size_t Idx) const {
assert(Idx < NumElems);
return Elems[Idx];
}
size_t size() const { return NumElems; }
bool empty() const { return NumElems == 0; }
T &back() { return (*this)[NumElems - 1]; }
void push_back(const T &NewElem, NodeFactory &Factory) {
if (NumElems >= Capacity)
Factory.Reallocate(Elems, Capacity, /*Growth*/ 1);
assert(NumElems < Capacity);
Elems[NumElems++] = NewElem;
}
T pop_back_val() {
if (empty())
return T();
T Val = (*this)[NumElems - 1];
NumElems--;
return Val;
}
};
/// A vector of chars (a string) with a storage managed by a NodeFactory.
///
/// This CharVector class only provides the minimal functionality needed by the
/// Demangler.
class CharVector : public Vector<char> {
public:
// Append another string.
void append(StringRef Rhs, NodeFactory &Factory);
// Append an integer as readable number.
void append(int Number, NodeFactory &Factory);
StringRef str() const {
return StringRef(Elems, NumElems);
}
};
/// The demangler. /// The demangler.
/// ///
/// It de-mangles a string and it also ownes the returned node-tree. This means /// It de-mangles a string and it also ownes the returned node-tree. This means
@@ -194,22 +288,14 @@ private:
size_t Pos; size_t Pos;
}; };
std::vector<NodeWithPos> NodeStack; Vector<NodeWithPos> NodeStack;
std::vector<NodePointer> Substitutions; Vector<NodePointer> Substitutions;
std::vector<unsigned> PendingSubstitutions; Vector<unsigned> PendingSubstitutions;
static const int MaxNumWords = 26; static const int MaxNumWords = 26;
StringRef Words[MaxNumWords]; StringRef Words[MaxNumWords];
int NumWords = 0; int NumWords = 0;
static NodePointer pop_back_val(std::vector<NodePointer> &NodeVector) {
if (NodeVector.empty())
return nullptr;
NodePointer Val = NodeVector.back();
NodeVector.pop_back();
return Val;
}
bool nextIf(StringRef str) { bool nextIf(StringRef str) {
if (!Text.substr(Pos).startswith(str)) return false; if (!Text.substr(Pos).startswith(str)) return false;
Pos += str.size(); Pos += str.size();
@@ -241,16 +327,11 @@ private:
} }
void pushNode(NodePointer Nd) { void pushNode(NodePointer Nd) {
NodeStack.push_back({ Nd, Pos }); NodeStack.push_back({ Nd, Pos }, *this);
} }
NodePointer popNode() { NodePointer popNode() {
if (!NodeStack.empty()) { return NodeStack.pop_back_val().Node;
NodePointer Val = NodeStack.back().Node;
NodeStack.pop_back();
return Val;
}
return nullptr;
} }
NodePointer popNode(Node::Kind kind) { NodePointer popNode(Node::Kind kind) {
@@ -279,7 +360,7 @@ private:
void addSubstitution(NodePointer Nd) { void addSubstitution(NodePointer Nd) {
if (Nd) if (Nd)
Substitutions.push_back(Nd); Substitutions.push_back(Nd, *this);
} }
NodePointer addChild(NodePointer Parent, NodePointer Child); NodePointer addChild(NodePointer Parent, NodePointer Child);
@@ -326,7 +407,7 @@ private:
NodePointer popProtocol(); NodePointer popProtocol();
NodePointer demangleBoundGenericType(); NodePointer demangleBoundGenericType();
NodePointer demangleBoundGenericArgs(NodePointer nominalType, NodePointer demangleBoundGenericArgs(NodePointer nominalType,
const std::vector<NodePointer> &TypeLists, const Vector<NodePointer> &TypeLists,
size_t TypeListIdx); size_t TypeListIdx);
NodePointer demangleInitializer(); NodePointer demangleInitializer();
NodePointer demangleImplParamConvention(); NodePointer demangleImplParamConvention();
@@ -368,6 +449,8 @@ private:
public: public:
Demangler() {} Demangler() {}
void clear() override;
/// Demangle the given symbol and return the parse tree. /// Demangle the given symbol and return the parse tree.
/// ///
/// \param MangledName The mangled symbol string, which start with the /// \param MangledName The mangled symbol string, which start with the

View File

@@ -310,6 +310,11 @@ void Node::addChild(NodePointer Child, Context &Ctx) {
addChild(Child, *Ctx.D); addChild(Child, *Ctx.D);
} }
void Node::reverseChildren(size_t StartingAt) {
assert(StartingAt <= NumChildren);
std::reverse(Children + StartingAt, Children + NumChildren);
}
////////////////////////////////// //////////////////////////////////
// NodeFactory member functions // // NodeFactory member functions //
////////////////////////////////// //////////////////////////////////
@@ -350,18 +355,49 @@ NodePointer NodeFactory::createNode(Node::Kind K, Node::IndexType Index) {
NodePointer NodeFactory::createNode(Node::Kind K, llvm::StringRef Text) { NodePointer NodeFactory::createNode(Node::Kind K, llvm::StringRef Text) {
return new (Allocate<Node>()) Node(K, Text.copy(*this)); return new (Allocate<Node>()) Node(K, Text.copy(*this));
} }
NodePointer NodeFactory::createNode(Node::Kind K, const CharVector &Text) {
return new (Allocate<Node>()) Node(K, Text.str());
}
NodePointer NodeFactory::createNode(Node::Kind K, const char *Text) { NodePointer NodeFactory::createNode(Node::Kind K, const char *Text) {
return new (Allocate<Node>()) Node(K, llvm::StringRef(Text)); return new (Allocate<Node>()) Node(K, llvm::StringRef(Text));
} }
//////////////////////////////////
// CharVector member functions //
//////////////////////////////////
void CharVector::append(StringRef Rhs, NodeFactory &Factory) {
if (NumElems + Rhs.size() > Capacity)
Factory.Reallocate(Elems, Capacity, /*Growth*/ Rhs.size());
memcpy(Elems + NumElems, Rhs.data(), Rhs.size());
NumElems += Rhs.size();
assert(NumElems <= Capacity);
}
void CharVector::append(int Number, NodeFactory &Factory) {
const int MaxIntPrintSize = 8;
if (NumElems + MaxIntPrintSize > Capacity)
Factory.Reallocate(Elems, Capacity, /*Growth*/ MaxIntPrintSize);
int Length = snprintf(Elems + NumElems, MaxIntPrintSize, "%d", Number);
assert(Length > 0 && Length < MaxIntPrintSize);
NumElems += Length;
}
////////////////////////////////// //////////////////////////////////
// Demangler member functions // // Demangler member functions //
////////////////////////////////// //////////////////////////////////
void Demangler::clear() {
NodeStack.free();
Substitutions.free();
PendingSubstitutions.free();
NodeFactory::clear();
}
void Demangler::init(StringRef MangledName) { void Demangler::init(StringRef MangledName) {
NodeStack.clear(); NodeStack.init(*this, 16);
Substitutions.clear(); Substitutions.init(*this, 16);
PendingSubstitutions.clear(); PendingSubstitutions.init(*this, 4);
NumWords = 0; NumWords = 0;
Text = MangledName; Text = MangledName;
Pos = 0; Pos = 0;
@@ -681,7 +717,7 @@ NodePointer Demangler::demangleIdentifier() {
hasWordSubsts = true; hasWordSubsts = true;
} }
} }
std::string Identifier; CharVector Identifier;
do { do {
while (hasWordSubsts && isLetter(peekChar())) { while (hasWordSubsts && isLetter(peekChar())) {
char c = nextChar(); char c = nextChar();
@@ -697,7 +733,7 @@ NodePointer Demangler::demangleIdentifier() {
return nullptr; return nullptr;
assert(WordIdx < MaxNumWords); assert(WordIdx < MaxNumWords);
StringRef Slice = Words[WordIdx]; StringRef Slice = Words[WordIdx];
Identifier.append(Slice.data(), Slice.size()); Identifier.append(Slice, *this);
} }
if (nextIf('0')) if (nextIf('0'))
break; break;
@@ -710,10 +746,12 @@ NodePointer Demangler::demangleIdentifier() {
return nullptr; return nullptr;
StringRef Slice = StringRef(Text.data() + Pos, numChars); StringRef Slice = StringRef(Text.data() + Pos, numChars);
if (isPunycoded) { if (isPunycoded) {
if (!Punycode::decodePunycodeUTF8(Slice, Identifier)) std::string PunycodedString;
if (!Punycode::decodePunycodeUTF8(Slice, PunycodedString))
return nullptr; return nullptr;
Identifier.append(StringRef(PunycodedString), *this);
} else { } else {
Identifier.append(Slice.data(), Slice.size()); Identifier.append(Slice, *this);
int wordStartPos = -1; int wordStartPos = -1;
for (int Idx = 0, End = (int)Slice.size(); Idx <= End; ++Idx) { for (int Idx = 0, End = (int)Slice.size(); Idx <= End; ++Idx) {
char c = (Idx < End ? Slice[Idx] : 0); char c = (Idx < End ? Slice[Idx] : 0);
@@ -744,12 +782,11 @@ NodePointer Demangler::demangleOperatorIdentifier() {
static const char op_char_table[] = "& @/= > <*!|+?%-~ ^ ."; static const char op_char_table[] = "& @/= > <*!|+?%-~ ^ .";
std::string OpStr; CharVector OpStr;
OpStr.reserve(Ident->getText().size());
for (signed char c : Ident->getText()) { for (signed char c : Ident->getText()) {
if (c < 0) { if (c < 0) {
// Pass through Unicode characters. // Pass through Unicode characters.
OpStr.push_back(c); OpStr.push_back(c, *this);
continue; continue;
} }
if (!isLowerLetter(c)) if (!isLowerLetter(c))
@@ -757,7 +794,7 @@ NodePointer Demangler::demangleOperatorIdentifier() {
char o = op_char_table[c - 'a']; char o = op_char_table[c - 'a'];
if (o == ' ') if (o == ' ')
return nullptr; return nullptr;
OpStr.push_back(o); OpStr.push_back(o, *this);
} }
switch (nextChar()) { switch (nextChar()) {
case 'i': return createNode(Node::Kind::InfixOperator, OpStr); case 'i': return createNode(Node::Kind::InfixOperator, OpStr);
@@ -828,16 +865,20 @@ NodePointer Demangler::demangleBuiltinType() {
int size = demangleIndex() - 1; int size = demangleIndex() - 1;
if (size <= 0) if (size <= 0)
return nullptr; return nullptr;
Ty = createNode(Node::Kind::BuiltinTypeName, CharVector name;
std::move(DemanglerPrinter() << "Builtin.Float" << size).str()); name.append("Builtin.Float", *this);
name.append(size, *this);
Ty = createNode(Node::Kind::BuiltinTypeName, name);
break; break;
} }
case 'i': { case 'i': {
int size = demangleIndex() - 1; int size = demangleIndex() - 1;
if (size <= 0) if (size <= 0)
return nullptr; return nullptr;
Ty = createNode(Node::Kind::BuiltinTypeName, CharVector name;
(DemanglerPrinter() << "Builtin.Int" << size).str()); name.append("Builtin.Int", *this);
name.append(size, *this);
Ty = createNode(Node::Kind::BuiltinTypeName, name);
break; break;
} }
case 'v': { case 'v': {
@@ -848,9 +889,12 @@ NodePointer Demangler::demangleBuiltinType() {
if (!EltType || EltType->getKind() != Node::Kind::BuiltinTypeName || if (!EltType || EltType->getKind() != Node::Kind::BuiltinTypeName ||
!EltType->getText().startswith("Builtin.")) !EltType->getText().startswith("Builtin."))
return nullptr; return nullptr;
Ty = createNode(Node::Kind::BuiltinTypeName, CharVector name;
(DemanglerPrinter() << "Builtin.Vec" << elts << "x" << name.append("Builtin.Vec", *this);
EltType->getText().substr(sizeof("Builtin.") - 1)).str()); name.append(elts, *this);
name.push_back('x', *this);
name.append(EltType->getText().substr(sizeof("Builtin.") - 1), *this);
Ty = createNode(Node::Kind::BuiltinTypeName, name);
break; break;
} }
case 'O': case 'O':
@@ -936,7 +980,6 @@ NodePointer Demangler::popTuple() {
Node::Kind::NonVariadicTuple); Node::Kind::NonVariadicTuple);
if (!popNode(Node::Kind::EmptyList)) { if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> Nodes;
bool firstElem = false; bool firstElem = false;
do { do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr); firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
@@ -949,12 +992,10 @@ NodePointer Demangler::popTuple() {
if (!Ty) if (!Ty)
return nullptr; return nullptr;
TupleElmt->addChild(Ty, *this); TupleElmt->addChild(Ty, *this);
Nodes.push_back(TupleElmt); Root->addChild(TupleElmt, *this);
} while (!firstElem); } while (!firstElem);
while (NodePointer TupleElmt = pop_back_val(Nodes)) { Root->reverseChildren();
Root->addChild(TupleElmt, *this);
}
} }
return createType(Root); return createType(Root);
} }
@@ -963,18 +1004,16 @@ NodePointer Demangler::popTypeList() {
NodePointer Root = createNode(Node::Kind::TypeList); NodePointer Root = createNode(Node::Kind::TypeList);
if (!popNode(Node::Kind::EmptyList)) { if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> Nodes;
bool firstElem = false; bool firstElem = false;
do { do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr); firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Ty = popNode(Node::Kind::Type); NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty) if (!Ty)
return nullptr; return nullptr;
Nodes.push_back(Ty);
} while (!firstElem);
while (NodePointer Ty = pop_back_val(Nodes)) {
Root->addChild(Ty, *this); Root->addChild(Ty, *this);
} } while (!firstElem);
Root->reverseChildren();
} }
return Root; return Root;
} }
@@ -987,17 +1026,15 @@ NodePointer Demangler::popProtocol() {
} }
NodePointer Demangler::demangleBoundGenericType() { NodePointer Demangler::demangleBoundGenericType() {
std::vector<NodePointer> TypeListList; Vector<NodePointer> TypeListList(*this, 4);
std::vector<NodePointer> Types;
for (;;) { for (;;) {
NodePointer TList = createNode(Node::Kind::TypeList); NodePointer TList = createNode(Node::Kind::TypeList);
TypeListList.push_back(TList); TypeListList.push_back(TList, *this);
while (NodePointer Ty = popNode(Node::Kind::Type)) { while (NodePointer Ty = popNode(Node::Kind::Type)) {
Types.push_back(Ty);
}
while (NodePointer Ty = pop_back_val(Types)) {
TList->addChild(Ty, *this); TList->addChild(Ty, *this);
} }
TList->reverseChildren();
if (popNode(Node::Kind::EmptyList)) if (popNode(Node::Kind::EmptyList))
break; break;
if (!popNode(Node::Kind::FirstElementMarker)) if (!popNode(Node::Kind::FirstElementMarker))
@@ -1008,7 +1045,7 @@ NodePointer Demangler::demangleBoundGenericType() {
} }
NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal, NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
const std::vector<NodePointer> &TypeLists, const Vector<NodePointer> &TypeLists,
size_t TypeListIdx) { size_t TypeListIdx) {
if (!Nominal || Nominal->getNumChildren() < 2) if (!Nominal || Nominal->getNumChildren() < 2)
return nullptr; return nullptr;
@@ -1057,7 +1094,7 @@ NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
} }
NodePointer Demangler::demangleImplParamConvention() { NodePointer Demangler::demangleImplParamConvention() {
StringRef attr; const char *attr = nullptr;
switch (nextChar()) { switch (nextChar()) {
case 'i': attr = "@in"; break; case 'i': attr = "@in"; break;
case 'l': attr = "@inout"; break; case 'l': attr = "@inout"; break;
@@ -1076,7 +1113,7 @@ NodePointer Demangler::demangleImplParamConvention() {
} }
NodePointer Demangler::demangleImplResultConvention(Node::Kind ConvKind) { NodePointer Demangler::demangleImplResultConvention(Node::Kind ConvKind) {
StringRef attr; const char *attr = nullptr;
switch (nextChar()) { switch (nextChar()) {
case 'r': attr = "@out"; break; case 'r': attr = "@out"; break;
case 'o': attr = "@owned"; break; case 'o': attr = "@owned"; break;
@@ -1192,19 +1229,6 @@ NodePointer Demangler::demangleMetatype() {
} }
} }
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::demangleArchetype() { NodePointer Demangler::demangleArchetype() {
switch (nextChar()) { switch (nextChar()) {
case 'a': { case 'a': {
@@ -1257,19 +1281,19 @@ NodePointer Demangler::demangleAssociatedTypeSimple(
NodePointer Demangler::demangleAssociatedTypeCompound( NodePointer Demangler::demangleAssociatedTypeCompound(
NodePointer GenericParamIdx) { NodePointer GenericParamIdx) {
std::vector<NodePointer> AssocTyNames; Vector<NodePointer> AssocTyNames(*this, 4);
bool firstElem = false; bool firstElem = false;
do { do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr); firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer AssocTyName = popAssocTypeName(); NodePointer AssocTyName = popAssocTypeName();
if (!AssocTyName) if (!AssocTyName)
return nullptr; return nullptr;
AssocTyNames.push_back(AssocTyName); AssocTyNames.push_back(AssocTyName, *this);
} while (!firstElem); } while (!firstElem);
NodePointer Base = GenericParamIdx; NodePointer Base = GenericParamIdx;
while (NodePointer AssocTy = pop_back_val(AssocTyNames)) { while (NodePointer AssocTy = AssocTyNames.pop_back_val()) {
NodePointer depTy = createNode(Node::Kind::DependentMemberType); NodePointer depTy = createNode(Node::Kind::DependentMemberType);
depTy = addChild(depTy, createType(Base)); depTy = addChild(depTy, createType(Base));
Base = addChild(depTy, AssocTy); Base = addChild(depTy, AssocTy);
@@ -1291,11 +1315,17 @@ NodePointer Demangler::popAssocTypeName() {
NodePointer Demangler::getDependentGenericParamType(int depth, int index) { NodePointer Demangler::getDependentGenericParamType(int depth, int index) {
if (depth < 0 || index < 0) if (depth < 0 || index < 0)
return nullptr; return nullptr;
DemanglerPrinter PrintName;
PrintName << getArchetypeName(index, depth);
auto paramTy = createNode(Node::Kind::DependentGenericParamType, CharVector name;
std::move(PrintName).str()); int idxChar = index;
do {
name.push_back((char)('A' + (idxChar % 26)), *this);
idxChar /= 26;
} while (idxChar);
if (depth != 0)
name.append(depth, *this);
auto paramTy = createNode(Node::Kind::DependentGenericParamType, name);
paramTy->addChild(createNode(Node::Kind::Index, depth), *this); paramTy->addChild(createNode(Node::Kind::Index, depth), *this);
paramTy->addChild(createNode(Node::Kind::Index, index), *this); paramTy->addChild(createNode(Node::Kind::Index, index), *this);
return paramTy; return paramTy;
@@ -1428,10 +1458,10 @@ NodePointer Demangler::demangleFunctionSpecialization() {
case FunctionSigSpecializationParamKind::ConstantPropGlobal: case FunctionSigSpecializationParamKind::ConstantPropGlobal:
case FunctionSigSpecializationParamKind::ConstantPropString: case FunctionSigSpecializationParamKind::ConstantPropString:
case FunctionSigSpecializationParamKind::ClosureProp: { case FunctionSigSpecializationParamKind::ClosureProp: {
std::vector<NodePointer> Types; size_t FixedChildren = Param->getNumChildren();
while (NodePointer Ty = popNode(Node::Kind::Type)) { while (NodePointer Ty = popNode(Node::Kind::Type)) {
assert(ParamKind == FunctionSigSpecializationParamKind::ClosureProp); assert(ParamKind == FunctionSigSpecializationParamKind::ClosureProp);
Types.push_back(Ty); Param = addChild(Param, Ty);
} }
NodePointer Name = popNode(Node::Kind::Identifier); NodePointer Name = popNode(Node::Kind::Identifier);
if (!Name) if (!Name)
@@ -1445,9 +1475,7 @@ NodePointer Demangler::demangleFunctionSpecialization() {
} }
addChild(Param, createNode( addChild(Param, createNode(
Node::Kind::FunctionSignatureSpecializationParamPayload, Text)); Node::Kind::FunctionSignatureSpecializationParamPayload, Text));
while (NodePointer Ty = pop_back_val(Types)) { Param->reverseChildren(FixedChildren);
Param = addChild(Param, Ty);
}
break; break;
} }
default: default:
@@ -1555,9 +1583,9 @@ NodePointer Demangler::addFuncSpecParamNumber(NodePointer Param,
Param->addChild(createNode( Param->addChild(createNode(
Node::Kind::FunctionSignatureSpecializationParamKind, unsigned(Kind)), Node::Kind::FunctionSignatureSpecializationParamKind, unsigned(Kind)),
*this); *this);
std::string Str; CharVector Str;
while (isDigit(peekChar())) { while (isDigit(peekChar())) {
Str += nextChar(); Str.push_back(nextChar(), *this);
} }
if (Str.empty()) if (Str.empty())
return nullptr; return nullptr;
@@ -1857,28 +1885,21 @@ NodePointer Demangler::demangleProtocolListType() {
NodePointer TypeList = createNode(Node::Kind::TypeList); NodePointer TypeList = createNode(Node::Kind::TypeList);
NodePointer ProtoList = createWithChild(Node::Kind::ProtocolList, TypeList); NodePointer ProtoList = createWithChild(Node::Kind::ProtocolList, TypeList);
if (!popNode(Node::Kind::EmptyList)) { if (!popNode(Node::Kind::EmptyList)) {
std::vector<NodePointer> ProtoNames;
bool firstElem = false; bool firstElem = false;
do { do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr); firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Proto = popProtocol(); NodePointer Proto = popProtocol();
if (!Proto) if (!Proto)
return nullptr; return nullptr;
ProtoNames.push_back(Proto); TypeList->addChild(Proto, *this);
} while (!firstElem); } while (!firstElem);
while (NodePointer Proto = pop_back_val(ProtoNames)) { TypeList->reverseChildren();
TypeList->addChild(Proto, *this);
}
} }
return createType(ProtoList); return createType(ProtoList);
} }
NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) { NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) {
std::vector<NodePointer> Requirements;
while (NodePointer Req = popNode(isRequirement)) {
Requirements.push_back(Req);
}
NodePointer Sig = createNode(Node::Kind::DependentGenericSignature); NodePointer Sig = createNode(Node::Kind::DependentGenericSignature);
if (hasParamCounts) { if (hasParamCounts) {
while (!nextIf('l')) { while (!nextIf('l')) {
@@ -1896,9 +1917,11 @@ NodePointer Demangler::demangleGenericSignature(bool hasParamCounts) {
} }
if (Sig->getNumChildren() == 0) if (Sig->getNumChildren() == 0)
return nullptr; return nullptr;
while (NodePointer Req = pop_back_val(Requirements)) { size_t NumCounts = Sig->getNumChildren();
while (NodePointer Req = popNode(isRequirement)) {
Sig->addChild(Req, *this); Sig->addChild(Req, *this);
} }
Sig->reverseChildren(NumCounts);
return Sig; return Sig;
} }
@@ -1961,7 +1984,7 @@ NodePointer Demangler::demangleGenericRequirement() {
auto c = nextChar(); auto c = nextChar();
NodePointer size = nullptr; NodePointer size = nullptr;
NodePointer alignment = nullptr; NodePointer alignment = nullptr;
StringRef name; const char *name = nullptr;
if (c == 'U') { if (c == 'U') {
name = "U"; name = "U";
} else if (c == 'R') { } else if (c == 'R') {