Skip to content

Commit 51fd790

Browse files
add range tracking when demangling a name
1 parent 11212b7 commit 51fd790

File tree

3 files changed

+150
-11
lines changed

3 files changed

+150
-11
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct DemangleOptions {
101101

102102
class Node;
103103
using NodePointer = Node *;
104+
class NodePrinter;
104105

105106
enum class FunctionSigSpecializationParamKind : unsigned {
106107
// Option Flags use bits 0-5. This give us 6 bits implying 64 entries to
@@ -236,6 +237,18 @@ class Node {
236237
public:
237238
Kind getKind() const { return NodeKind; }
238239

240+
bool shouldTrackNameRange() const {
241+
switch (getKind()) {
242+
case Kind::Function:
243+
case Kind::Constructor:
244+
case Kind::Allocator:
245+
case Kind::ExplicitClosure:
246+
return true;
247+
default:
248+
return false;
249+
}
250+
}
251+
239252
bool isSimilarTo(const Node *other) const {
240253
if (NodeKind != other->NodeKind
241254
|| NodePayloadKind != other->NodePayloadKind)
@@ -419,6 +432,10 @@ bool isOldFunctionTypeMangling(llvm::StringRef mangledName);
419432

420433
class Demangler;
421434

435+
class DemanglerPrinter;
436+
437+
class TrackingDemanglerPrinter;
438+
422439
/// The demangler context.
423440
///
424441
/// It owns the allocated nodes which are created during demangling.
@@ -467,16 +484,26 @@ class Context {
467484
/// The lifetime of the returned node tree ends with the lifetime of the
468485
/// context or with a call of clear().
469486
NodePointer demangleTypeAsNode(llvm::StringRef MangledName);
470-
487+
471488
/// Demangle the given symbol and return the readable name.
472489
///
473490
/// \param MangledName The mangled symbol string, which start a mangling
474491
/// prefix: _T, _T0, $S, _$S.
475492
///
476493
/// \returns The demangled string.
477-
std::string demangleSymbolAsString(
478-
llvm::StringRef MangledName,
479-
const DemangleOptions &Options = DemangleOptions());
494+
std::string
495+
demangleSymbolAsString(llvm::StringRef MangledName,
496+
const DemangleOptions &Options = DemangleOptions());
497+
498+
/// Demangle the given symbol.
499+
///
500+
/// \param MangledName The mangled symbol string, which start a mangling
501+
/// prefix: _T, _T0, $S, _$S.
502+
/// \param printer The NodePrinter that will be used to demangle the symbol.
503+
///
504+
/// \returns The demangled string.
505+
void demangleSymbolAsString(llvm::StringRef MangledName,
506+
NodePrinter *printer);
480507

481508
/// Demangle the given type and return the readable name.
482509
///
@@ -535,6 +562,18 @@ std::string
535562
demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
536563
const DemangleOptions &options = DemangleOptions());
537564

565+
/// Standalone utility function to demangle the given symbol as string.
566+
///
567+
/// If performance is an issue when demangling multiple symbols,
568+
/// Context::demangleSymbolAsString should be used instead.
569+
/// \param mangledName The mangled name string pointer.
570+
/// \param mangledNameLength The length of the mangledName string.
571+
/// \param printer The NodePrinter that will be used to demangle the symbol.
572+
///
573+
/// \returns The demangled string.
574+
void demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
575+
NodePrinter *printer);
576+
538577
/// Standalone utility function to demangle the given symbol as string.
539578
///
540579
/// If performance is an issue when demangling multiple symbols,
@@ -547,7 +586,7 @@ demangleSymbolAsString(const std::string &mangledName,
547586
return demangleSymbolAsString(mangledName.data(), mangledName.size(),
548587
options);
549588
}
550-
589+
551590
/// Standalone utility function to demangle the given symbol as string.
552591
///
553592
/// If performance is an issue when demangling multiple symbols,
@@ -557,8 +596,20 @@ demangleSymbolAsString(const std::string &mangledName,
557596
inline std::string
558597
demangleSymbolAsString(llvm::StringRef MangledName,
559598
const DemangleOptions &Options = DemangleOptions()) {
560-
return demangleSymbolAsString(MangledName.data(),
561-
MangledName.size(), Options);
599+
return demangleSymbolAsString(MangledName.data(), MangledName.size(),
600+
Options);
601+
}
602+
603+
/// Standalone utility function to demangle the given symbol as string.
604+
///
605+
/// If performance is an issue when demangling multiple symbols,
606+
/// Context::demangleSymbolAsString should be used instead.
607+
/// \param MangledName The mangled name string.
608+
///
609+
/// \returns The demangled string.
610+
inline void demangleSymbolAsString(llvm::StringRef MangledName,
611+
NodePrinter *printer) {
612+
demangleSymbolAsString(MangledName.data(), MangledName.size(), printer);
562613
}
563614

564615
/// Standalone utility function to demangle the given type as string.
@@ -734,6 +785,15 @@ ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
734785
std::string nodeToString(NodePointer Root,
735786
const DemangleOptions &Options = DemangleOptions());
736787

788+
/// Transform the node structure to a string.
789+
///
790+
/// \endcode
791+
///
792+
/// \param Root A pointer to a parse tree generated by the demangler.
793+
/// \param Printer A NodePrinter used to pretty print the demangled Node.
794+
///
795+
void nodeToString(NodePointer Root, NodePrinter *Printer);
796+
737797
/// Transforms a mangled key path accessor thunk helper
738798
/// into the identfier/subscript that would be used to invoke it in swift code.
739799
std::string keyPathSourceString(const char *MangledName,
@@ -779,11 +839,14 @@ class DemanglerPrinter {
779839

780840
llvm::StringRef getStringRef() const { return Stream; }
781841

842+
size_t getStreamLength() { return Stream.length(); }
843+
782844
/// Shrinks the buffer.
783845
void resetSize(size_t toPos) {
784846
assert(toPos <= Stream.size());
785847
Stream.resize(toPos);
786848
}
849+
787850
private:
788851
std::string Stream;
789852
};
@@ -825,6 +888,10 @@ std::string mangledNameForTypeMetadataAccessor(
825888
/// NodePrinter is used to convert demangled Swift symbol nodes into
826889
/// human-readable string representations. It handles formatting, indentation,
827890
/// and Swift-specific syntax.
891+
///
892+
/// The virtual methods in this class are meant to be overriden to allow
893+
/// external consumers (e.g lldb) to track the ranges of components of the
894+
/// demangled name.
828895
class NodePrinter {
829896
protected:
830897
DemanglerPrinter Printer;
@@ -835,9 +902,14 @@ class NodePrinter {
835902
public:
836903
NodePrinter(DemangleOptions options) : Options(options) {}
837904

838-
std::string printRoot(NodePointer root) {
905+
virtual ~NodePrinter() {}
906+
907+
void printRoot(NodePointer root) {
839908
isValid = true;
840909
print(root, 0);
910+
}
911+
912+
std::string takeString() {
841913
if (isValid)
842914
return std::move(Printer).str();
843915
return "";
@@ -846,6 +918,8 @@ class NodePrinter {
846918
protected:
847919
static const unsigned MaxDepth = 768;
848920

921+
size_t getStreamLength() { return Printer.getStreamLength(); }
922+
849923
/// Called when the node tree in valid.
850924
///
851925
/// The demangler already catches most error cases and mostly produces valid
@@ -899,8 +973,9 @@ class NodePrinter {
899973

900974
NodePointer getChildIf(NodePointer Node, Node::Kind Kind);
901975

902-
void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
903-
unsigned depth, bool showTypes);
976+
virtual void printFunctionParameters(NodePointer LabelList,
977+
NodePointer ParameterType,
978+
unsigned depth, bool showTypes);
904979

905980
void printFunctionType(NodePointer LabelList, NodePointer node,
906981
unsigned depth);
@@ -944,6 +1019,12 @@ class NodePrinter {
9441019
bool hasName, StringRef ExtraName = "",
9451020
int ExtraIndex = -1, StringRef OverwriteName = "");
9461021

1022+
virtual void printFunctionName(bool hasName, llvm::StringRef &OverwriteName,
1023+
llvm::StringRef &ExtraName, bool MultiWordName,
1024+
int &ExtraIndex,
1025+
swift::Demangle::NodePointer Entity,
1026+
unsigned int depth);
1027+
9471028
/// Print the type of an entity.
9481029
///
9491030
/// \param Entity The entity.

lib/Demangling/Context.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ std::string Context::demangleSymbolAsString(llvm::StringRef MangledName,
6666
return demangling;
6767
}
6868

69+
void Context::demangleSymbolAsString(llvm::StringRef MangledName,
70+
NodePrinter *printer) {
71+
NodePointer root = demangleSymbolAsNode(MangledName);
72+
nodeToString(root, printer);
73+
}
74+
6975
std::string Context::demangleTypeAsString(llvm::StringRef MangledName,
7076
const DemangleOptions &Options) {
7177
NodePointer root = demangleTypeAsNode(MangledName);
@@ -275,6 +281,13 @@ std::string demangleSymbolAsString(const char *MangledName,
275281
Options);
276282
}
277283

284+
void demangleSymbolAsString(const char *MangledName, size_t MangledNameLength,
285+
NodePrinter *printer) {
286+
Context Ctx;
287+
return Ctx.demangleSymbolAsString(StringRef(MangledName, MangledNameLength),
288+
printer);
289+
}
290+
278291
std::string demangleTypeAsString(const char *MangledName,
279292
size_t MangledNameLength,
280293
const DemangleOptions &Options) {

lib/Demangling/NodePrinter.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3568,6 +3568,43 @@ NodePointer NodePrinter::printEntity(NodePointer Entity, unsigned depth,
35683568
return PostfixContext;
35693569
}
35703570

3571+
void NodePrinter::printFunctionName(bool hasName,
3572+
llvm::StringRef &OverwriteName,
3573+
llvm::StringRef &ExtraName,
3574+
bool MultiWordName, int &ExtraIndex,
3575+
swift::Demangle::NodePointer Entity,
3576+
unsigned int depth) {
3577+
if (hasName || !OverwriteName.empty()) {
3578+
if (!ExtraName.empty() && MultiWordName) {
3579+
Printer << ExtraName;
3580+
if (ExtraIndex >= 0)
3581+
Printer << ExtraIndex;
3582+
3583+
Printer << " of ";
3584+
ExtraName = "";
3585+
ExtraIndex = -1;
3586+
}
3587+
size_t CurrentPos = Printer.getStringRef().size();
3588+
if (!OverwriteName.empty()) {
3589+
Printer << OverwriteName;
3590+
} else {
3591+
auto Name = Entity->getChild(1);
3592+
if (Name->getKind() != Node::Kind::PrivateDeclName)
3593+
print(Name, depth + 1);
3594+
3595+
if (auto PrivateName = getChildIf(Entity, Node::Kind::PrivateDeclName))
3596+
print(PrivateName, depth + 1);
3597+
}
3598+
if (Printer.getStringRef().size() != CurrentPos && !ExtraName.empty())
3599+
Printer << '.';
3600+
}
3601+
if (!ExtraName.empty()) {
3602+
Printer << ExtraName;
3603+
if (ExtraIndex >= 0)
3604+
Printer << ExtraIndex;
3605+
}
3606+
}
3607+
35713608
void NodePrinter::printEntityType(NodePointer Entity, NodePointer type,
35723609
NodePointer genericFunctionTypeList,
35733610
unsigned depth) {
@@ -3751,7 +3788,15 @@ std::string Demangle::nodeToString(NodePointer root,
37513788
if (!root)
37523789
return "";
37533790

3754-
return NodePrinter(options).printRoot(root);
3791+
NodePrinter printer = NodePrinter(options);
3792+
nodeToString(root, &printer);
3793+
return printer.takeString();
3794+
}
3795+
3796+
void Demangle::nodeToString(NodePointer root, NodePrinter *printer) {
3797+
if (!root)
3798+
return;
3799+
printer->printRoot(root);
37553800
}
37563801

37573802
#endif

0 commit comments

Comments
 (0)