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
@@ -465,16 +468,26 @@ class Context {
465468 // / The lifetime of the returned node tree ends with the lifetime of the
466469 // / context or with a call of clear().
467470 NodePointer demangleTypeAsNode (llvm::StringRef MangledName);
468-
471+
469472 // / Demangle the given symbol and return the readable name.
470473 // /
471474 // / \param MangledName The mangled symbol string, which start a mangling
472475 // / prefix: _T, _T0, $S, _$S.
473476 // /
474477 // / \returns The demangled string.
475- std::string demangleSymbolAsString (
476- llvm::StringRef MangledName,
477- const DemangleOptions &Options = DemangleOptions());
478+ std::string
479+ demangleSymbolAsString (llvm::StringRef MangledName,
480+ const DemangleOptions &Options = DemangleOptions());
481+
482+ // / Demangle the given symbol and store the result in the `printer`.
483+ // /
484+ // / \param MangledName The mangled symbol string, which start a mangling
485+ // / prefix: _T, _T0, $S, _$S.
486+ // / \param Printer The NodePrinter that will be used to demangle the symbol.
487+ // /
488+ // / \returns The demangled string.
489+ void demangleSymbolAsString (llvm::StringRef MangledName,
490+ NodePrinter &Printer);
478491
479492 // / Demangle the given type and return the readable name.
480493 // /
@@ -533,6 +546,16 @@ std::string
533546demangleSymbolAsString (const char *mangledName, size_t mangledNameLength,
534547 const DemangleOptions &options = DemangleOptions());
535548
549+ // / Standalone utility function to demangle the given symbol as string. The
550+ // / demangled string is stored in the `printer`.
551+ // /
552+ // / If performance is an issue when demangling multiple symbols,
553+ // / \param mangledName The mangled name string pointer.
554+ // / \param mangledNameLength The length of the mangledName string.
555+ // / \param printer The NodePrinter that will be used to demangle the symbol.
556+ void demangleSymbolAsString (const llvm::StringRef mangledName,
557+ NodePrinter &printer);
558+
536559// / Standalone utility function to demangle the given symbol as string.
537560// /
538561// / If performance is an issue when demangling multiple symbols,
@@ -545,7 +568,7 @@ demangleSymbolAsString(const std::string &mangledName,
545568 return demangleSymbolAsString (mangledName.data (), mangledName.size (),
546569 options);
547570}
548-
571+
549572// / Standalone utility function to demangle the given symbol as string.
550573// /
551574// / If performance is an issue when demangling multiple symbols,
@@ -725,13 +748,19 @@ ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
725748// / \endcode
726749// /
727750// / \param Root A pointer to a parse tree generated by the demangler.
728- // / \param Options An object encapsulating options to use to perform this demangling.
751+ // / \param Options An object encapsulating options to use to perform this
752+ // / demangling.
729753// /
730754// / \returns A string representing the demangled name.
731- // /
732755std::string nodeToString (NodePointer Root,
733756 const DemangleOptions &Options = DemangleOptions());
734757
758+ // / Transform the node structure to a string, which is stored in the `Printer`.
759+ // /
760+ // / \param Root A pointer to a parse tree generated by the demangler.
761+ // / \param Printer A NodePrinter used to pretty print the demangled Node.
762+ void nodeToString (NodePointer Root, NodePrinter &Printer);
763+
735764// / Transforms a mangled key path accessor thunk helper
736765// / into the identfier/subscript that would be used to invoke it in swift code.
737766std::string keyPathSourceString (const char *MangledName,
@@ -777,11 +806,14 @@ class DemanglerPrinter {
777806
778807 llvm::StringRef getStringRef () const { return Stream; }
779808
809+ size_t getStreamLength () { return Stream.length (); }
810+
780811 // / Shrinks the buffer.
781812 void resetSize (size_t toPos) {
782813 assert (toPos <= Stream.size ());
783814 Stream.resize (toPos);
784815 }
816+
785817private:
786818 std::string Stream;
787819};
@@ -818,6 +850,159 @@ std::string mangledNameForTypeMetadataAccessor(
818850 llvm::StringRef moduleName, llvm::StringRef typeName, Node::Kind typeKind,
819851 Mangle::ManglingFlavor Flavor = Mangle::ManglingFlavor::Default);
820852
853+ // / Base class for printing a Swift demangled node tree.
854+ // /
855+ // / NodePrinter is used to convert demangled Swift symbol nodes into
856+ // / human-readable string representations. It handles formatting, indentation,
857+ // / and Swift-specific syntax.
858+ // /
859+ // / The virtual methods in this class are meant to be overriden to allow
860+ // / external consumers (e.g lldb) to track the ranges of components of the
861+ // / demangled name.
862+ class NodePrinter {
863+ protected:
864+ DemanglerPrinter Printer;
865+ DemangleOptions Options;
866+ bool SpecializationPrefixPrinted = false ;
867+ bool isValid = true ;
868+
869+ public:
870+ NodePrinter (DemangleOptions options) : Options(options) {}
871+
872+ virtual ~NodePrinter () = default ;
873+
874+ void printRoot (NodePointer root) {
875+ isValid = true ;
876+ print (root, 0 );
877+ }
878+
879+ std::string takeString () {
880+ if (isValid)
881+ return std::move (Printer).str ();
882+ return " " ;
883+ }
884+
885+ protected:
886+ static const unsigned MaxDepth = 768 ;
887+
888+ size_t getStreamLength () { return Printer.getStreamLength (); }
889+
890+ // / Called when the node tree in valid.
891+ // /
892+ // / The demangler already catches most error cases and mostly produces valid
893+ // / node trees. But some cases are difficult to catch in the demangler and
894+ // / instead the NodePrinter bails.
895+ void setInvalid () { isValid = false ; }
896+
897+ void printChildren (Node::iterator begin, Node::iterator end, unsigned depth,
898+ const char *sep = nullptr );
899+
900+ void printChildren (NodePointer Node, unsigned depth,
901+ const char *sep = nullptr );
902+
903+ NodePointer getFirstChildOfKind (NodePointer Node, Node::Kind kind);
904+
905+ void printBoundGenericNoSugar (NodePointer Node, unsigned depth);
906+
907+ void printOptionalIndex (NodePointer node);
908+
909+ static bool isSwiftModule (NodePointer node) {
910+ return (node->getKind () == Node::Kind::Module &&
911+ node->getText () == STDLIB_NAME);
912+ }
913+
914+ static bool isIdentifier (NodePointer node, StringRef desired) {
915+ return (node->getKind () == Node::Kind::Identifier &&
916+ node->getText () == desired);
917+ }
918+
919+ bool printContext (NodePointer Context);
920+
921+ enum class SugarType {
922+ None,
923+ Optional,
924+ ImplicitlyUnwrappedOptional,
925+ Array,
926+ Dictionary
927+ };
928+
929+ enum class TypePrinting { NoType, WithColon, FunctionStyle };
930+
931+ // / Determine whether this is a "simple" type, from the type-simple
932+ // / production.
933+ bool isSimpleType (NodePointer Node);
934+
935+ void printWithParens (NodePointer type, unsigned depth);
936+
937+ SugarType findSugar (NodePointer Node);
938+
939+ void printBoundGeneric (NodePointer Node, unsigned depth);
940+
941+ NodePointer getChildIf (NodePointer Node, Node::Kind Kind);
942+
943+ virtual void printFunctionParameters (NodePointer LabelList,
944+ NodePointer ParameterType,
945+ unsigned depth, bool showTypes);
946+
947+ void printFunctionType (NodePointer LabelList, NodePointer node,
948+ unsigned depth);
949+
950+ void printImplFunctionType (NodePointer fn, unsigned depth);
951+
952+ void printGenericSignature (NodePointer Node, unsigned depth);
953+
954+ void printFunctionSigSpecializationParams (NodePointer Node, unsigned depth);
955+
956+ void printSpecializationPrefix (NodePointer node, StringRef Description,
957+ unsigned depth,
958+ StringRef ParamPrefix = StringRef());
959+
960+ // / The main big print function.
961+ NodePointer print (NodePointer Node, unsigned depth,
962+ bool asPrefixContext = false );
963+
964+ NodePointer printAbstractStorage (NodePointer Node, unsigned depth,
965+ bool asPrefixContent, StringRef ExtraName);
966+
967+ // / Utility function to print entities.
968+ // /
969+ // / \param Entity The entity node to print
970+ // / \param depth The depth in the print() call tree.
971+ // / \param asPrefixContext Should the entity printed as a context which as a
972+ // / prefix to another entity, e.g. the Abc in Abc.def()
973+ // / \param TypePr How should the type of the entity be printed, if at all.
974+ // / E.g. with a colon for properties or as a function type.
975+ // / \param hasName Does the entity has a name, e.g. a function in contrast to
976+ // / an initializer.
977+ // / \param ExtraName An extra name added to the entity name (if any).
978+ // / \param ExtraIndex An extra index added to the entity name (if any),
979+ // / e.g. closure #1
980+ // / \param OverwriteName If non-empty, print this name instead of the one
981+ // / provided by the node. Gets printed even if hasName is false.
982+ // / \return If a non-null node is returned it's a context which must be
983+ // / printed in postfix-form after the entity: "<entity> in <context>".
984+ NodePointer printEntity (NodePointer Entity, unsigned depth,
985+ bool asPrefixContext, TypePrinting TypePr,
986+ bool hasName, StringRef ExtraName = " " ,
987+ int ExtraIndex = -1 , StringRef OverwriteName = " " );
988+
989+ virtual void printFunctionName (bool hasName, llvm::StringRef &OverwriteName,
990+ llvm::StringRef &ExtraName, bool MultiWordName,
991+ int &ExtraIndex,
992+ swift::Demangle::NodePointer Entity,
993+ unsigned int depth);
994+
995+ // / Print the type of an entity.
996+ // /
997+ // / \param Entity The entity.
998+ // / \param type The type of the entity.
999+ // / \param genericFunctionTypeList If not null, the generic argument types
1000+ // / which is printed in the generic signature.
1001+ // / \param depth The depth in the print() call tree.
1002+ void printEntityType (NodePointer Entity, NodePointer type,
1003+ NodePointer genericFunctionTypeList, unsigned depth);
1004+ };
1005+
8211006SWIFT_END_INLINE_NAMESPACE
8221007} // end namespace Demangle
8231008} // end namespace swift
0 commit comments