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"
26+ #include " swift/Strings.h"
2527#include " llvm/ADT/StringRef.h"
2628#include " llvm/Support/Compiler.h"
2729
@@ -99,6 +101,7 @@ struct DemangleOptions {
99101
100102class Node ;
101103using NodePointer = Node *;
104+ class NodePrinter ;
102105
103106enum class FunctionSigSpecializationParamKind : unsigned {
104107 // Option Flags use bits 0-5. This give us 6 bits implying 64 entries to
@@ -234,6 +237,18 @@ class Node {
234237public:
235238 Kind getKind () const { return NodeKind; }
236239
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+
237252 bool isSimilarTo (const Node *other) const {
238253 if (NodeKind != other->NodeKind
239254 || NodePayloadKind != other->NodePayloadKind )
@@ -417,6 +432,10 @@ bool isOldFunctionTypeMangling(llvm::StringRef mangledName);
417432
418433class Demangler ;
419434
435+ class DemanglerPrinter ;
436+
437+ class TrackingDemanglerPrinter ;
438+
420439// / The demangler context.
421440// /
422441// / It owns the allocated nodes which are created during demangling.
@@ -465,16 +484,26 @@ class Context {
465484 // / The lifetime of the returned node tree ends with the lifetime of the
466485 // / context or with a call of clear().
467486 NodePointer demangleTypeAsNode (llvm::StringRef MangledName);
468-
487+
469488 // / Demangle the given symbol and return the readable name.
470489 // /
471490 // / \param MangledName The mangled symbol string, which start a mangling
472491 // / prefix: _T, _T0, $S, _$S.
473492 // /
474493 // / \returns The demangled string.
475- std::string demangleSymbolAsString (
476- llvm::StringRef MangledName,
477- 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);
478507
479508 // / Demangle the given type and return the readable name.
480509 // /
@@ -533,6 +562,18 @@ std::string
533562demangleSymbolAsString (const char *mangledName, size_t mangledNameLength,
534563 const DemangleOptions &options = DemangleOptions());
535564
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+
536577// / Standalone utility function to demangle the given symbol as string.
537578// /
538579// / If performance is an issue when demangling multiple symbols,
@@ -545,7 +586,7 @@ demangleSymbolAsString(const std::string &mangledName,
545586 return demangleSymbolAsString (mangledName.data (), mangledName.size (),
546587 options);
547588}
548-
589+
549590// / Standalone utility function to demangle the given symbol as string.
550591// /
551592// / If performance is an issue when demangling multiple symbols,
@@ -555,8 +596,20 @@ demangleSymbolAsString(const std::string &mangledName,
555596inline std::string
556597demangleSymbolAsString (llvm::StringRef MangledName,
557598 const DemangleOptions &Options = DemangleOptions()) {
558- return demangleSymbolAsString (MangledName.data (),
559- 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);
560613}
561614
562615// / Standalone utility function to demangle the given type as string.
@@ -732,6 +785,15 @@ ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
732785std::string nodeToString (NodePointer Root,
733786 const DemangleOptions &Options = DemangleOptions());
734787
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+
735797// / Transforms a mangled key path accessor thunk helper
736798// / into the identfier/subscript that would be used to invoke it in swift code.
737799std::string keyPathSourceString (const char *MangledName,
@@ -777,11 +839,14 @@ class DemanglerPrinter {
777839
778840 llvm::StringRef getStringRef () const { return Stream; }
779841
842+ size_t getStreamLength () { return Stream.length (); }
843+
780844 // / Shrinks the buffer.
781845 void resetSize (size_t toPos) {
782846 assert (toPos <= Stream.size ());
783847 Stream.resize (toPos);
784848 }
849+
785850private:
786851 std::string Stream;
787852};
@@ -818,6 +883,159 @@ std::string mangledNameForTypeMetadataAccessor(
818883 llvm::StringRef moduleName, llvm::StringRef typeName, Node::Kind typeKind,
819884 Mangle::ManglingFlavor Flavor = Mangle::ManglingFlavor::Default);
820885
886+ // / Base class for printing a Swift demangled node tree.
887+ // /
888+ // / NodePrinter is used to convert demangled Swift symbol nodes into
889+ // / human-readable string representations. It handles formatting, indentation,
890+ // / 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.
895+ class NodePrinter {
896+ protected:
897+ DemanglerPrinter Printer;
898+ DemangleOptions Options;
899+ bool SpecializationPrefixPrinted = false ;
900+ bool isValid = true ;
901+
902+ public:
903+ NodePrinter (DemangleOptions options) : Options(options) {}
904+
905+ virtual ~NodePrinter () {}
906+
907+ void printRoot (NodePointer root) {
908+ isValid = true ;
909+ print (root, 0 );
910+ }
911+
912+ std::string takeString () {
913+ if (isValid)
914+ return std::move (Printer).str ();
915+ return " " ;
916+ }
917+
918+ protected:
919+ static const unsigned MaxDepth = 768 ;
920+
921+ size_t getStreamLength () { return Printer.getStreamLength (); }
922+
923+ // / Called when the node tree in valid.
924+ // /
925+ // / The demangler already catches most error cases and mostly produces valid
926+ // / node trees. But some cases are difficult to catch in the demangler and
927+ // / instead the NodePrinter bails.
928+ void setInvalid () { isValid = false ; }
929+
930+ void printChildren (Node::iterator begin, Node::iterator end, unsigned depth,
931+ const char *sep = nullptr );
932+
933+ void printChildren (NodePointer Node, unsigned depth,
934+ const char *sep = nullptr );
935+
936+ NodePointer getFirstChildOfKind (NodePointer Node, Node::Kind kind);
937+
938+ void printBoundGenericNoSugar (NodePointer Node, unsigned depth);
939+
940+ void printOptionalIndex (NodePointer node);
941+
942+ static bool isSwiftModule (NodePointer node) {
943+ return (node->getKind () == Node::Kind::Module &&
944+ node->getText () == STDLIB_NAME);
945+ }
946+
947+ static bool isIdentifier (NodePointer node, StringRef desired) {
948+ return (node->getKind () == Node::Kind::Identifier &&
949+ node->getText () == desired);
950+ }
951+
952+ bool printContext (NodePointer Context);
953+
954+ enum class SugarType {
955+ None,
956+ Optional,
957+ ImplicitlyUnwrappedOptional,
958+ Array,
959+ Dictionary
960+ };
961+
962+ enum class TypePrinting { NoType, WithColon, FunctionStyle };
963+
964+ // / Determine whether this is a "simple" type, from the type-simple
965+ // / production.
966+ bool isSimpleType (NodePointer Node);
967+
968+ void printWithParens (NodePointer type, unsigned depth);
969+
970+ SugarType findSugar (NodePointer Node);
971+
972+ void printBoundGeneric (NodePointer Node, unsigned depth);
973+
974+ NodePointer getChildIf (NodePointer Node, Node::Kind Kind);
975+
976+ virtual void printFunctionParameters (NodePointer LabelList,
977+ NodePointer ParameterType,
978+ unsigned depth, bool showTypes);
979+
980+ void printFunctionType (NodePointer LabelList, NodePointer node,
981+ unsigned depth);
982+
983+ void printImplFunctionType (NodePointer fn, unsigned depth);
984+
985+ void printGenericSignature (NodePointer Node, unsigned depth);
986+
987+ void printFunctionSigSpecializationParams (NodePointer Node, unsigned depth);
988+
989+ void printSpecializationPrefix (NodePointer node, StringRef Description,
990+ unsigned depth,
991+ StringRef ParamPrefix = StringRef());
992+
993+ // / The main big print function.
994+ NodePointer print (NodePointer Node, unsigned depth,
995+ bool asPrefixContext = false );
996+
997+ NodePointer printAbstractStorage (NodePointer Node, unsigned depth,
998+ bool asPrefixContent, StringRef ExtraName);
999+
1000+ // / Utility function to print entities.
1001+ // /
1002+ // / \param Entity The entity node to print
1003+ // / \param depth The depth in the print() call tree.
1004+ // / \param asPrefixContext Should the entity printed as a context which as a
1005+ // / prefix to another entity, e.g. the Abc in Abc.def()
1006+ // / \param TypePr How should the type of the entity be printed, if at all.
1007+ // / E.g. with a colon for properties or as a function type.
1008+ // / \param hasName Does the entity has a name, e.g. a function in contrast to
1009+ // / an initializer.
1010+ // / \param ExtraName An extra name added to the entity name (if any).
1011+ // / \param ExtraIndex An extra index added to the entity name (if any),
1012+ // / e.g. closure #1
1013+ // / \param OverwriteName If non-empty, print this name instead of the one
1014+ // / provided by the node. Gets printed even if hasName is false.
1015+ // / \return If a non-null node is returned it's a context which must be
1016+ // / printed in postfix-form after the entity: "<entity> in <context>".
1017+ NodePointer printEntity (NodePointer Entity, unsigned depth,
1018+ bool asPrefixContext, TypePrinting TypePr,
1019+ bool hasName, StringRef ExtraName = " " ,
1020+ int ExtraIndex = -1 , StringRef OverwriteName = " " );
1021+
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+
1028+ // / Print the type of an entity.
1029+ // /
1030+ // / \param Entity The entity.
1031+ // / \param type The type of the entity.
1032+ // / \param genericFunctionTypeList If not null, the generic argument types
1033+ // / which is printed in the generic signature.
1034+ // / \param depth The depth in the print() call tree.
1035+ void printEntityType (NodePointer Entity, NodePointer type,
1036+ NodePointer genericFunctionTypeList, unsigned depth);
1037+ };
1038+
8211039SWIFT_END_INLINE_NAMESPACE
8221040} // end namespace Demangle
8231041} // end namespace swift
0 commit comments