Skip to content

Commit 0245da0

Browse files
add range tracking when demangling a name
1 parent 7ce06dd commit 0245da0

File tree

6 files changed

+330
-217
lines changed

6 files changed

+330
-217
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 100 additions & 12 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"
@@ -234,6 +235,18 @@ class Node {
234235
public:
235236
Kind getKind() const { return NodeKind; }
236237

238+
bool shouldTrackNameRange() const {
239+
switch (getKind()) {
240+
case Kind::Function:
241+
case Kind::Constructor:
242+
case Kind::Allocator:
243+
case Kind::ExplicitClosure:
244+
return true;
245+
default:
246+
return false;
247+
}
248+
}
249+
237250
bool isSimilarTo(const Node *other) const {
238251
if (NodeKind != other->NodeKind
239252
|| NodePayloadKind != other->NodePayloadKind)
@@ -417,6 +430,10 @@ bool isOldFunctionTypeMangling(llvm::StringRef mangledName);
417430

418431
class Demangler;
419432

433+
class DemanglerPrinter;
434+
435+
class TrackingDemanglerPrinter;
436+
420437
/// The demangler context.
421438
///
422439
/// It owns the allocated nodes which are created during demangling.
@@ -472,9 +489,10 @@ class Context {
472489
/// prefix: _T, _T0, $S, _$S.
473490
///
474491
/// \returns The demangled string.
475-
std::string demangleSymbolAsString(
476-
llvm::StringRef MangledName,
477-
const DemangleOptions &Options = DemangleOptions());
492+
std::string
493+
demangleSymbolAsString(llvm::StringRef MangledName,
494+
const DemangleOptions &Options = DemangleOptions(),
495+
DemanglerPrinter *printer = nullptr);
478496

479497
/// Demangle the given type and return the readable name.
480498
///
@@ -531,7 +549,8 @@ class Context {
531549
/// \returns The demangled string.
532550
std::string
533551
demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
534-
const DemangleOptions &options = DemangleOptions());
552+
const DemangleOptions &options = DemangleOptions(),
553+
DemanglerPrinter *printer = nullptr);
535554

536555
/// Standalone utility function to demangle the given symbol as string.
537556
///
@@ -541,11 +560,12 @@ demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
541560
/// \returns The demangled string.
542561
inline std::string
543562
demangleSymbolAsString(const std::string &mangledName,
544-
const DemangleOptions &options = DemangleOptions()) {
545-
return demangleSymbolAsString(mangledName.data(), mangledName.size(),
546-
options);
563+
const DemangleOptions &options = DemangleOptions(),
564+
DemanglerPrinter *printer = nullptr) {
565+
return demangleSymbolAsString(mangledName.data(), mangledName.size(), options,
566+
printer);
547567
}
548-
568+
549569
/// Standalone utility function to demangle the given symbol as string.
550570
///
551571
/// If performance is an issue when demangling multiple symbols,
@@ -554,9 +574,10 @@ demangleSymbolAsString(const std::string &mangledName,
554574
/// \returns The demangled string.
555575
inline std::string
556576
demangleSymbolAsString(llvm::StringRef MangledName,
557-
const DemangleOptions &Options = DemangleOptions()) {
558-
return demangleSymbolAsString(MangledName.data(),
559-
MangledName.size(), Options);
577+
const DemangleOptions &Options = DemangleOptions(),
578+
DemanglerPrinter *printer = nullptr) {
579+
return demangleSymbolAsString(MangledName.data(), MangledName.size(), Options,
580+
printer);
560581
}
561582

562583
/// Standalone utility function to demangle the given type as string.
@@ -730,7 +751,8 @@ ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
730751
/// \returns A string representing the demangled name.
731752
///
732753
std::string nodeToString(NodePointer Root,
733-
const DemangleOptions &Options = DemangleOptions());
754+
const DemangleOptions &Options = DemangleOptions(),
755+
DemanglerPrinter *printer = nullptr);
734756

735757
/// Transforms a mangled key path accessor thunk helper
736758
/// into the identfier/subscript that would be used to invoke it in swift code.
@@ -777,15 +799,81 @@ class DemanglerPrinter {
777799

778800
llvm::StringRef getStringRef() const { return Stream; }
779801

802+
size_t getStreamLength() { return Stream.length(); }
803+
780804
/// Shrinks the buffer.
781805
void resetSize(size_t toPos) {
782806
assert(toPos <= Stream.size());
783807
Stream.resize(toPos);
784808
}
809+
810+
/// Mark the start of the name of a function.
811+
virtual void startName() {}
812+
813+
/// Mark the end of the name of a function.
814+
virtual void endName() {}
815+
816+
/// Mark the start of the parameters of a function.
817+
///
818+
/// \param depth Current depth of the parameters that are being printed.
819+
virtual void startParameters(unsigned depth) {}
820+
821+
/// Mark the end of the parameters of a function.
822+
///
823+
/// \param depth Current depth of the parameters that are being printed.
824+
virtual void endParameters(unsigned depth) {}
825+
826+
virtual ~DemanglerPrinter() {}
827+
785828
private:
786829
std::string Stream;
787830
};
788831

832+
/// A class for printing to a std::string while tracking ranges.
833+
class TrackingDemanglerPrinter : public swift::Demangle::DemanglerPrinter {
834+
public:
835+
size_t getNameStart() { return baseNameRange.first; }
836+
size_t getNameEnd() { return baseNameRange.second; }
837+
size_t getParametersStart() { return parametersRange.first; }
838+
size_t getParametersEnd() { return parametersRange.second; }
839+
bool hasBaseName() { return baseNameRange.first < baseNameRange.second; }
840+
bool hasParameters() {
841+
return parametersRange.first < parametersRange.second;
842+
}
843+
844+
void startName() override {
845+
if (!hasBaseName())
846+
baseNameRange.first = getStreamLength();
847+
}
848+
849+
void endName() override {
850+
if (!hasBaseName())
851+
baseNameRange.second = getStreamLength();
852+
}
853+
854+
void startParameters(unsigned depth) override {
855+
if (parametersDepth || !hasBaseName() || hasParameters()) {
856+
return;
857+
}
858+
parametersRange.first = getStreamLength();
859+
parametersDepth = depth;
860+
}
861+
862+
void endParameters(unsigned depth) override {
863+
if (!parametersDepth || *parametersDepth != depth || hasParameters()) {
864+
return;
865+
}
866+
parametersRange.second = getStreamLength();
867+
}
868+
869+
private:
870+
std::pair<size_t, size_t> baseNameRange;
871+
872+
std::pair<size_t, size_t> parametersRange;
873+
874+
std::optional<unsigned> parametersDepth;
875+
};
876+
789877
/// Returns a the node kind \p k as string.
790878
const char *getNodeKindString(swift::Demangle::Node::Kind k);
791879

lib/Demangling/Context.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ NodePointer Context::demangleTypeAsNode(llvm::StringRef MangledName) {
5656
#if SWIFT_STDLIB_HAS_TYPE_PRINTING
5757

5858
std::string Context::demangleSymbolAsString(llvm::StringRef MangledName,
59-
const DemangleOptions &Options) {
59+
const DemangleOptions &Options,
60+
DemanglerPrinter *printer) {
6061
NodePointer root = demangleSymbolAsNode(MangledName);
6162
if (!root) return MangledName.str();
6263

63-
std::string demangling = nodeToString(root, Options);
64+
std::string demangling = nodeToString(root, Options, printer);
6465
if (demangling.empty())
6566
return MangledName.str();
6667
return demangling;
@@ -269,10 +270,11 @@ std::string Context::getModuleName(llvm::StringRef mangledName) {
269270

270271
std::string demangleSymbolAsString(const char *MangledName,
271272
size_t MangledNameLength,
272-
const DemangleOptions &Options) {
273+
const DemangleOptions &Options,
274+
DemanglerPrinter *printer) {
273275
Context Ctx;
274276
return Ctx.demangleSymbolAsString(StringRef(MangledName, MangledNameLength),
275-
Options);
277+
Options, printer);
276278
}
277279

278280
std::string demangleTypeAsString(const char *MangledName,

lib/Demangling/NodePrinter.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,19 @@ static StringRef toString(ValueWitnessKind k) {
169169

170170
class NodePrinter {
171171
private:
172-
DemanglerPrinter Printer;
172+
std::unique_ptr<DemanglerPrinter> PrinterStorage;
173+
DemanglerPrinter &Printer;
173174
DemangleOptions Options;
174175
bool SpecializationPrefixPrinted = false;
175176
bool isValid = true;
176177

177178
public:
178-
NodePrinter(DemangleOptions options) : Options(options) {}
179+
NodePrinter(DemangleOptions options, DemanglerPrinter *printer = nullptr)
180+
: PrinterStorage(),
181+
Printer(printer
182+
? *printer
183+
: *(PrinterStorage = std::make_unique<DemanglerPrinter>())),
184+
Options(options) {}
179185

180186
std::string printRoot(NodePointer root) {
181187
isValid = true;
@@ -802,6 +808,7 @@ class NodePrinter {
802808
return;
803809
}
804810

811+
Printer.startParameters(depth);
805812
NodePointer Parameters = ParameterType->getFirstChild();
806813
assert(Parameters->getKind() == Node::Kind::Type);
807814
Parameters = Parameters->getFirstChild();
@@ -814,6 +821,7 @@ class NodePrinter {
814821
} else {
815822
Printer << "(_:)";
816823
}
824+
Printer.endParameters(depth);
817825
return;
818826
}
819827

@@ -853,6 +861,7 @@ class NodePrinter {
853861
},
854862
[&]() { Printer << (showTypes ? ", " : ""); });
855863
Printer << ')';
864+
Printer.endParameters(depth);
856865
}
857866

858867
void printFunctionType(NodePointer LabelList, NodePointer node,
@@ -3576,7 +3585,9 @@ NodePointer NodePrinter::printEntity(NodePointer Entity, unsigned depth,
35763585
Printer << '.';
35773586
}
35783587
}
3579-
3588+
if (Entity->shouldTrackNameRange()) {
3589+
Printer.startName();
3590+
}
35803591
if (hasName || !OverwriteName.empty()) {
35813592
if (!ExtraName.empty() && MultiWordName) {
35823593
Printer << ExtraName;
@@ -3606,6 +3617,9 @@ NodePointer NodePrinter::printEntity(NodePointer Entity, unsigned depth,
36063617
if (ExtraIndex >= 0)
36073618
Printer << ExtraIndex;
36083619
}
3620+
if (Entity->shouldTrackNameRange()) {
3621+
Printer.endName();
3622+
}
36093623
if (TypePr != TypePrinting::NoType) {
36103624
NodePointer type = getChildIf(Entity, Node::Kind::Type);
36113625
assert(type && "malformed entity");
@@ -3836,11 +3850,12 @@ std::string Demangle::keyPathSourceString(const char *MangledName,
38363850
}
38373851

38383852
std::string Demangle::nodeToString(NodePointer root,
3839-
const DemangleOptions &options) {
3853+
const DemangleOptions &options,
3854+
DemanglerPrinter *printer) {
38403855
if (!root)
38413856
return "";
38423857

3843-
return NodePrinter(options).printRoot(root);
3858+
return NodePrinter(options, printer).printRoot(root);
38443859
}
38453860

38463861
#endif

0 commit comments

Comments
 (0)