Skip to content

Commit a98b2e6

Browse files
add new methods to the NodePrinter to enable range tracking possibilities when demangling a name
1 parent fdde2a3 commit a98b2e6

File tree

3 files changed

+163
-15
lines changed

3 files changed

+163
-15
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef SWIFT_DEMANGLING_DEMANGLE_H
2020
#define SWIFT_DEMANGLING_DEMANGLE_H
2121

22+
#include "swift/Demangling/Demangle.h"
2223
#include "swift/Demangling/Errors.h"
2324
#include "swift/Demangling/ManglingFlavor.h"
2425
#include "swift/Demangling/NamespaceMacros.h"
@@ -100,6 +101,7 @@ struct DemangleOptions {
100101

101102
class Node;
102103
using NodePointer = Node *;
104+
class NodePrinter;
103105

104106
enum class FunctionSigSpecializationParamKind : unsigned {
105107
// Option Flags use bits 0-5. This give us 6 bits implying 64 entries to
@@ -235,6 +237,18 @@ class Node {
235237
public:
236238
Kind getKind() const { return NodeKind; }
237239

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+
238252
bool isSimilarTo(const Node *other) const {
239253
if (NodeKind != other->NodeKind
240254
|| NodePayloadKind != other->NodePayloadKind)
@@ -466,16 +480,26 @@ class Context {
466480
/// The lifetime of the returned node tree ends with the lifetime of the
467481
/// context or with a call of clear().
468482
NodePointer demangleTypeAsNode(llvm::StringRef MangledName);
469-
483+
470484
/// Demangle the given symbol and return the readable name.
471485
///
472486
/// \param MangledName The mangled symbol string, which start a mangling
473487
/// prefix: _T, _T0, $S, _$S.
474488
///
475489
/// \returns The demangled string.
476-
std::string demangleSymbolAsString(
477-
llvm::StringRef MangledName,
478-
const DemangleOptions &Options = DemangleOptions());
490+
std::string
491+
demangleSymbolAsString(llvm::StringRef MangledName,
492+
const DemangleOptions &Options = DemangleOptions());
493+
494+
/// Demangle the given symbol and store the result in the `printer`.
495+
///
496+
/// \param MangledName The mangled symbol string, which start a mangling
497+
/// prefix: _T, _T0, $S, _$S.
498+
/// \param printer The NodePrinter that will be used to demangle the symbol.
499+
///
500+
/// \returns The demangled string.
501+
void demangleSymbolAsString(llvm::StringRef MangledName,
502+
NodePrinter *printer);
479503

480504
/// Demangle the given type and return the readable name.
481505
///
@@ -534,6 +558,17 @@ std::string
534558
demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
535559
const DemangleOptions &options = DemangleOptions());
536560

561+
/// Standalone utility function to demangle the given symbol as string. The
562+
/// demangled string is stored in the `printer`.
563+
///
564+
/// If performance is an issue when demangling multiple symbols,
565+
/// `Context::demangleSymbolAsString` should be used instead.
566+
/// \param mangledName The mangled name string pointer.
567+
/// \param mangledNameLength The length of the mangledName string.
568+
/// \param printer The NodePrinter that will be used to demangle the symbol.
569+
void demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
570+
NodePrinter *printer);
571+
537572
/// Standalone utility function to demangle the given symbol as string.
538573
///
539574
/// If performance is an issue when demangling multiple symbols,
@@ -546,7 +581,7 @@ demangleSymbolAsString(const std::string &mangledName,
546581
return demangleSymbolAsString(mangledName.data(), mangledName.size(),
547582
options);
548583
}
549-
584+
550585
/// Standalone utility function to demangle the given symbol as string.
551586
///
552587
/// If performance is an issue when demangling multiple symbols,
@@ -560,6 +595,17 @@ demangleSymbolAsString(llvm::StringRef MangledName,
560595
MangledName.size(), Options);
561596
}
562597

598+
/// Standalone utility function to demangle the given symbol as string. The
599+
/// result is stored in the `printer`.
600+
///
601+
/// If performance is an issue when demangling multiple symbols,
602+
/// Context::demangleSymbolAsString should be used instead.
603+
/// \param MangledName The mangled name string.
604+
inline void demangleSymbolAsString(llvm::StringRef MangledName,
605+
NodePrinter *printer) {
606+
demangleSymbolAsString(MangledName.data(), MangledName.size(), printer);
607+
}
608+
563609
/// Standalone utility function to demangle the given type as string.
564610
///
565611
/// If performance is an issue when demangling multiple symbols,
@@ -726,13 +772,19 @@ ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
726772
/// \endcode
727773
///
728774
/// \param Root A pointer to a parse tree generated by the demangler.
729-
/// \param Options An object encapsulating options to use to perform this demangling.
775+
/// \param Options An object encapsulating options to use to perform this
776+
/// demangling.
730777
///
731778
/// \returns A string representing the demangled name.
732-
///
733779
std::string nodeToString(NodePointer Root,
734780
const DemangleOptions &Options = DemangleOptions());
735781

782+
/// Transform the node structure to a string, which is stored in the `Printer`.
783+
///
784+
/// \param Root A pointer to a parse tree generated by the demangler.
785+
/// \param Printer A NodePrinter used to pretty print the demangled Node.
786+
void nodeToString(NodePointer Root, NodePrinter *Printer);
787+
736788
/// Transforms a mangled key path accessor thunk helper
737789
/// into the identfier/subscript that would be used to invoke it in swift code.
738790
std::string keyPathSourceString(const char *MangledName,
@@ -778,11 +830,14 @@ class DemanglerPrinter {
778830

779831
llvm::StringRef getStringRef() const { return Stream; }
780832

833+
size_t getStreamLength() { return Stream.length(); }
834+
781835
/// Shrinks the buffer.
782836
void resetSize(size_t toPos) {
783837
assert(toPos <= Stream.size());
784838
Stream.resize(toPos);
785839
}
840+
786841
private:
787842
std::string Stream;
788843
};
@@ -819,8 +874,17 @@ std::string mangledNameForTypeMetadataAccessor(
819874
llvm::StringRef moduleName, llvm::StringRef typeName, Node::Kind typeKind,
820875
Mangle::ManglingFlavor Flavor = Mangle::ManglingFlavor::Default);
821876

877+
/// Base class for printing a Swift demangled node tree.
878+
///
879+
/// NodePrinter is used to convert demangled Swift symbol nodes into
880+
/// human-readable string representations. It handles formatting, indentation,
881+
/// and Swift-specific syntax.
882+
///
883+
/// The virtual methods in this class are meant to be overriden to allow
884+
/// external consumers (e.g lldb) to track the ranges of components of the
885+
/// demangled name.
822886
class NodePrinter {
823-
private:
887+
protected:
824888
DemanglerPrinter Printer;
825889
DemangleOptions Options;
826890
bool SpecializationPrefixPrinted = false;
@@ -829,17 +893,24 @@ class NodePrinter {
829893
public:
830894
NodePrinter(DemangleOptions options) : Options(options) {}
831895

832-
std::string printRoot(NodePointer root) {
896+
virtual ~NodePrinter() = default;
897+
898+
void printRoot(NodePointer root) {
833899
isValid = true;
834900
print(root, 0);
901+
}
902+
903+
std::string takeString() {
835904
if (isValid)
836905
return std::move(Printer).str();
837906
return "";
838907
}
839908

840-
private:
909+
protected:
841910
static const unsigned MaxDepth = 768;
842911

912+
size_t getStreamLength() { return Printer.getStreamLength(); }
913+
843914
/// Called when the node tree in valid.
844915
///
845916
/// The demangler already catches most error cases and mostly produces valid
@@ -864,13 +935,13 @@ class NodePrinter {
864935
node->getText() == STDLIB_NAME);
865936
}
866937

867-
bool printContext(NodePointer Context);
868-
869938
static bool isIdentifier(NodePointer node, StringRef desired) {
870939
return (node->getKind() == Node::Kind::Identifier &&
871940
node->getText() == desired);
872941
}
873942

943+
bool printContext(NodePointer Context);
944+
874945
enum class SugarType {
875946
None,
876947
Optional,
@@ -893,8 +964,9 @@ class NodePrinter {
893964

894965
NodePointer getChildIf(NodePointer Node, Node::Kind Kind);
895966

896-
void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
897-
unsigned depth, bool showTypes);
967+
virtual void printFunctionParameters(NodePointer LabelList,
968+
NodePointer ParameterType,
969+
unsigned depth, bool showTypes);
898970

899971
void printFunctionType(NodePointer LabelList, NodePointer node,
900972
unsigned depth);
@@ -938,6 +1010,12 @@ class NodePrinter {
9381010
bool hasName, StringRef ExtraName = "",
9391011
int ExtraIndex = -1, StringRef OverwriteName = "");
9401012

1013+
virtual void printFunctionName(bool hasName, llvm::StringRef &OverwriteName,
1014+
llvm::StringRef &ExtraName, bool MultiWordName,
1015+
int &ExtraIndex,
1016+
swift::Demangle::NodePointer Entity,
1017+
unsigned int depth);
1018+
9411019
/// Print the type of an entity.
9421020
///
9431021
/// \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: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3569,6 +3569,43 @@ NodePointer NodePrinter::printEntity(NodePointer Entity, unsigned depth,
35693569
return PostfixContext;
35703570
}
35713571

3572+
void NodePrinter::printFunctionName(bool hasName,
3573+
llvm::StringRef &OverwriteName,
3574+
llvm::StringRef &ExtraName,
3575+
bool MultiWordName, int &ExtraIndex,
3576+
swift::Demangle::NodePointer Entity,
3577+
unsigned int depth) {
3578+
if (hasName || !OverwriteName.empty()) {
3579+
if (!ExtraName.empty() && MultiWordName) {
3580+
Printer << ExtraName;
3581+
if (ExtraIndex >= 0)
3582+
Printer << ExtraIndex;
3583+
3584+
Printer << " of ";
3585+
ExtraName = "";
3586+
ExtraIndex = -1;
3587+
}
3588+
size_t CurrentPos = Printer.getStringRef().size();
3589+
if (!OverwriteName.empty()) {
3590+
Printer << OverwriteName;
3591+
} else {
3592+
auto Name = Entity->getChild(1);
3593+
if (Name->getKind() != Node::Kind::PrivateDeclName)
3594+
print(Name, depth + 1);
3595+
3596+
if (auto PrivateName = getChildIf(Entity, Node::Kind::PrivateDeclName))
3597+
print(PrivateName, depth + 1);
3598+
}
3599+
if (Printer.getStringRef().size() != CurrentPos && !ExtraName.empty())
3600+
Printer << '.';
3601+
}
3602+
if (!ExtraName.empty()) {
3603+
Printer << ExtraName;
3604+
if (ExtraIndex >= 0)
3605+
Printer << ExtraIndex;
3606+
}
3607+
}
3608+
35723609
void NodePrinter::printEntityType(NodePointer Entity, NodePointer type,
35733610
NodePointer genericFunctionTypeList,
35743611
unsigned depth) {
@@ -3747,12 +3784,32 @@ std::string Demangle::keyPathSourceString(const char *MangledName,
37473784
return invalid;
37483785
}
37493786

3787+
/// Converts a demangled node to a string.
3788+
///
3789+
/// \param root The root of the AST to demangle.
3790+
/// @param options The `DemangleOptions` which will be used to create the
3791+
/// NodePrinter.
3792+
///
3793+
/// \return The demangled node as a string.
37503794
std::string Demangle::nodeToString(NodePointer root,
37513795
const DemangleOptions &options) {
37523796
if (!root)
37533797
return "";
37543798

3755-
return NodePrinter(options).printRoot(root);
3799+
NodePrinter printer = NodePrinter(options);
3800+
nodeToString(root, &printer);
3801+
return printer.takeString();
3802+
}
3803+
3804+
/// Converts a demangled node to a string, which is stored in the `printer`.
3805+
///
3806+
/// \param root The root of the AST to demangle.
3807+
/// @param printer The `NodePrinter` which will be used to print the AST to a
3808+
/// string.
3809+
void Demangle::nodeToString(NodePointer root, NodePrinter *printer) {
3810+
if (!root)
3811+
return;
3812+
printer->printRoot(root);
37563813
}
37573814

37583815
#endif

0 commit comments

Comments
 (0)