mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
* initial * it works demangling mostly works fix dots printing works add tests add conformance to AnyKeyPath implement SPI subscripts fully work comments use cross platform image inspection remove unnecessary comment fix fix issues add conditional conformance add types try to fix the api-digester test cr feedback: move impls behind flag, remove addChain(), switch statement, fallthrough instead of if-elses, move import cr feedback: refactor switch statement fix #ifdef reindent, cr feedback: removes manual memory management fix missing whitespace fix typo fix indentation issues switch to regexes checks should test in on all platforms print types in subscripts add test for empty subscript Update test/api-digester/stability-stdlib-abi-without-asserts.test Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com> add commas fix failing test fix stdlib annotation cr feedback: remove global, refactor ifdef cr feedback: switch back to manual memory management switch to 5.8 macro add new weakly linked functions to the allowlist fix one more failing test more cr feedback more cr feedback * fix invisible unicode
737 lines
23 KiB
C++
737 lines
23 KiB
C++
//===--- Demangle.h - Interface to Swift symbol demangling ------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file is the public API of the demangler library.
|
|
// Tools which use the demangler library (like lldb) must include this - and
|
|
// only this - header file.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_DEMANGLING_DEMANGLE_H
|
|
#define SWIFT_DEMANGLING_DEMANGLE_H
|
|
|
|
#include "swift/Demangling/Errors.h"
|
|
#include "swift/Demangling/NamespaceMacros.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
}
|
|
|
|
namespace swift {
|
|
namespace Demangle {
|
|
SWIFT_BEGIN_INLINE_NAMESPACE
|
|
|
|
enum class SymbolicReferenceKind : uint8_t;
|
|
|
|
/// A simple default implementation that assigns letters to type parameters in
|
|
/// alphabetic order.
|
|
std::string genericParameterName(uint64_t depth, uint64_t index);
|
|
|
|
/// Display style options for the demangler.
|
|
struct DemangleOptions {
|
|
bool SynthesizeSugarOnTypes = false;
|
|
bool QualifyEntities = true;
|
|
bool DisplayExtensionContexts = true;
|
|
bool DisplayUnmangledSuffix = true;
|
|
bool DisplayModuleNames = true;
|
|
bool DisplayGenericSpecializations = true;
|
|
bool DisplayProtocolConformances = true;
|
|
bool DisplayWhereClauses = true;
|
|
bool DisplayEntityTypes = true;
|
|
bool DisplayLocalNameContexts = true;
|
|
bool ShortenPartialApply = false;
|
|
bool ShortenThunk = false;
|
|
bool ShortenValueWitness = false;
|
|
bool ShortenArchetype = false;
|
|
bool ShowPrivateDiscriminators = true;
|
|
bool ShowFunctionArgumentTypes = true;
|
|
bool DisplayDebuggerGeneratedModule = true;
|
|
bool DisplayStdlibModule = true;
|
|
bool DisplayObjCModule = true;
|
|
bool PrintForTypeName = false;
|
|
bool ShowAsyncResumePartial = true;
|
|
|
|
/// If this is nonempty, entities in this module name will not be qualified.
|
|
llvm::StringRef HidingCurrentModule;
|
|
/// A function to render generic parameter names.
|
|
std::function<std::string(uint64_t, uint64_t)> GenericParameterName =
|
|
genericParameterName;
|
|
|
|
DemangleOptions() {}
|
|
|
|
static DemangleOptions SimplifiedUIDemangleOptions() {
|
|
auto Opt = DemangleOptions();
|
|
Opt.SynthesizeSugarOnTypes = true;
|
|
Opt.QualifyEntities = true;
|
|
Opt.DisplayExtensionContexts = false;
|
|
Opt.DisplayUnmangledSuffix = false;
|
|
Opt.DisplayModuleNames = false;
|
|
Opt.DisplayGenericSpecializations = false;
|
|
Opt.DisplayProtocolConformances = false;
|
|
Opt.DisplayWhereClauses = false;
|
|
Opt.DisplayEntityTypes = false;
|
|
Opt.ShortenPartialApply = true;
|
|
Opt.ShortenThunk = true;
|
|
Opt.ShortenValueWitness = true;
|
|
Opt.ShortenArchetype = true;
|
|
Opt.ShowPrivateDiscriminators = false;
|
|
Opt.ShowFunctionArgumentTypes = false;
|
|
Opt.ShowAsyncResumePartial = false;
|
|
return Opt;
|
|
};
|
|
};
|
|
|
|
class Node;
|
|
using NodePointer = Node *;
|
|
|
|
enum class FunctionSigSpecializationParamKind : unsigned {
|
|
// Option Flags use bits 0-5. This give us 6 bits implying 64 entries to
|
|
// work with.
|
|
ConstantPropFunction = 0,
|
|
ConstantPropGlobal = 1,
|
|
ConstantPropInteger = 2,
|
|
ConstantPropFloat = 3,
|
|
ConstantPropString = 4,
|
|
ClosureProp = 5,
|
|
BoxToValue = 6,
|
|
BoxToStack = 7,
|
|
InOutToOut = 8,
|
|
ConstantPropKeyPath = 9,
|
|
|
|
// Option Set Flags use bits 6-31. This gives us 26 bits to use for option
|
|
// flags.
|
|
Dead = 1 << 6,
|
|
OwnedToGuaranteed = 1 << 7,
|
|
SROA = 1 << 8,
|
|
GuaranteedToOwned = 1 << 9,
|
|
ExistentialToGeneric = 1 << 10,
|
|
};
|
|
|
|
enum class AutoDiffFunctionKind : char {
|
|
JVP = 'f',
|
|
VJP = 'r',
|
|
Differential = 'd',
|
|
Pullback = 'p',
|
|
};
|
|
|
|
enum class MangledDifferentiabilityKind : char {
|
|
NonDifferentiable = 0,
|
|
Forward = 'f',
|
|
Reverse = 'r',
|
|
Normal = 'd',
|
|
Linear = 'l',
|
|
};
|
|
|
|
/// The pass that caused the specialization to occur. We use this to make sure
|
|
/// that two passes that generate similar changes do not yield the same
|
|
/// mangling. This currently cannot happen, so this is just a safety measure
|
|
/// that creates separate name spaces.
|
|
enum class SpecializationPass : uint8_t {
|
|
AllocBoxToStack,
|
|
ClosureSpecializer,
|
|
CapturePromotion,
|
|
CapturePropagation,
|
|
FunctionSignatureOpts,
|
|
GenericSpecializer,
|
|
MoveDiagnosticInOutToOut,
|
|
};
|
|
|
|
static inline char encodeSpecializationPass(SpecializationPass Pass) {
|
|
return char(uint8_t(Pass)) + '0';
|
|
}
|
|
|
|
enum class ValueWitnessKind {
|
|
#define VALUE_WITNESS(MANGLING, NAME) \
|
|
NAME,
|
|
#include "swift/Demangling/ValueWitnessMangling.def"
|
|
};
|
|
|
|
enum class Directness {
|
|
Direct, Indirect
|
|
};
|
|
|
|
class NodeFactory;
|
|
class Context;
|
|
|
|
class Node {
|
|
public:
|
|
enum class Kind : uint16_t {
|
|
#define NODE(ID) ID,
|
|
#include "swift/Demangling/DemangleNodes.def"
|
|
};
|
|
|
|
using IndexType = uint64_t;
|
|
|
|
friend class NodeFactory;
|
|
|
|
private:
|
|
|
|
struct NodeVector {
|
|
NodePointer *Nodes;
|
|
uint32_t Number = 0;
|
|
uint32_t Capacity = 0;
|
|
};
|
|
|
|
union {
|
|
llvm::StringRef Text;
|
|
IndexType Index;
|
|
NodePointer InlineChildren[2];
|
|
NodeVector Children;
|
|
};
|
|
|
|
|
|
Kind NodeKind;
|
|
|
|
enum class PayloadKind : uint8_t {
|
|
None, Text, Index, OneChild, TwoChildren, ManyChildren
|
|
};
|
|
PayloadKind NodePayloadKind;
|
|
|
|
Node(Kind k)
|
|
: NodeKind(k), NodePayloadKind(PayloadKind::None) {
|
|
}
|
|
Node(Kind k, llvm::StringRef t)
|
|
: NodeKind(k), NodePayloadKind(PayloadKind::Text) {
|
|
Text = t;
|
|
}
|
|
Node(Kind k, IndexType index)
|
|
: NodeKind(k), NodePayloadKind(PayloadKind::Index) {
|
|
Index = index;
|
|
}
|
|
Node(const Node &) = delete;
|
|
Node &operator=(const Node &) = delete;
|
|
|
|
public:
|
|
Kind getKind() const { return NodeKind; }
|
|
|
|
bool hasText() const { return NodePayloadKind == PayloadKind::Text; }
|
|
llvm::StringRef getText() const {
|
|
assert(hasText());
|
|
return Text;
|
|
}
|
|
|
|
bool hasIndex() const { return NodePayloadKind == PayloadKind::Index; }
|
|
uint64_t getIndex() const {
|
|
assert(hasIndex());
|
|
return Index;
|
|
}
|
|
|
|
using iterator = const NodePointer *;
|
|
|
|
size_t getNumChildren() const;
|
|
|
|
bool hasChildren() const { return getNumChildren() != 0; }
|
|
|
|
iterator begin() const;
|
|
|
|
iterator end() const;
|
|
|
|
NodePointer getFirstChild() const {
|
|
return getChild(0);
|
|
}
|
|
NodePointer getLastChild() const {
|
|
return getChild(getNumChildren() - 1);
|
|
}
|
|
NodePointer getChild(size_t index) const {
|
|
if (index >= getNumChildren())
|
|
return nullptr;
|
|
return begin()[index];
|
|
}
|
|
|
|
// Only to be used by the demangler parsers.
|
|
void addChild(NodePointer Child, NodeFactory &Factory);
|
|
// Only to be used by the demangler parsers.
|
|
void removeChildAt(unsigned Pos);
|
|
|
|
// Reverses the order of children.
|
|
void reverseChildren(size_t StartingAt = 0);
|
|
|
|
// Find a node by its kind, traversing the node depth-first,
|
|
// and bailing out early if not found at the 'maxDepth'.
|
|
NodePointer findByKind(Node::Kind kind, int maxDepth);
|
|
|
|
/// Prints the whole node tree in readable form to stderr.
|
|
///
|
|
/// Useful to be called from the debugger.
|
|
void dump();
|
|
};
|
|
|
|
/// Returns the length of the swift mangling prefix of the \p SymbolName.
|
|
///
|
|
/// Returns 0 if \p SymbolName is not a mangled swift (>= swift 4.x) name.
|
|
int getManglingPrefixLength(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if \p SymbolName is a mangled swift name.
|
|
///
|
|
/// This does not include the old (<= swift 3.x) mangling prefix "_T".
|
|
inline bool isMangledName(llvm::StringRef mangledName) {
|
|
return getManglingPrefixLength(mangledName) != 0;
|
|
}
|
|
|
|
/// Returns true if the mangledName starts with the swift mangling prefix.
|
|
///
|
|
/// This includes the old (<= swift 3.x) mangling prefix "_T".
|
|
bool isSwiftSymbol(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangledName starts with the swift mangling prefix.
|
|
///
|
|
/// This includes the old (<= swift 3.x) mangling prefix "_T".
|
|
bool isSwiftSymbol(const char *mangledName);
|
|
|
|
/// Drops the Swift mangling prefix from the given mangled name, if there is
|
|
/// one.
|
|
///
|
|
/// This does not include the old (<= swift 3.x) mangling prefix "_T".
|
|
llvm::StringRef dropSwiftManglingPrefix(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is an alias type name.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isAlias(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is a class type name.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isClass(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is an enum type name.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isEnum(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is a protocol type name.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isProtocol(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is a structure type name.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isStruct(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name is an Objective-C symbol.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isObjCSymbol(llvm::StringRef mangledName);
|
|
|
|
/// Returns true if the mangled name has the old scheme of function type
|
|
/// mangling where labels are part of the type.
|
|
///
|
|
/// \param mangledName A null-terminated string containing a mangled name.
|
|
bool isOldFunctionTypeMangling(llvm::StringRef mangledName);
|
|
|
|
class Demangler;
|
|
|
|
/// The demangler context.
|
|
///
|
|
/// It owns the allocated nodes which are created during demangling.
|
|
/// It is always preferable to use the demangling via this context class as it
|
|
/// ensures efficient memory management. Especially if demangling is done for
|
|
/// multiple symbols. Typical usage:
|
|
/// \code
|
|
/// Context Ctx;
|
|
/// for (...) {
|
|
/// NodePointer Root = Ctx.demangleSymbolAsNode(MangledName);
|
|
/// // Do something with Root
|
|
/// Ctx.clear(); // deallocates Root
|
|
/// }
|
|
/// \endcode
|
|
/// Declaring the context out of the loop minimizes the amount of needed memory
|
|
/// allocations.
|
|
///
|
|
class Context {
|
|
Demangler *D;
|
|
|
|
friend class Node;
|
|
|
|
public:
|
|
Context();
|
|
|
|
~Context();
|
|
|
|
/// Demangle the given symbol and return the parse tree.
|
|
///
|
|
/// \param MangledName The mangled symbol string, which start a mangling
|
|
/// prefix: _T, _T0, $S, _$S.
|
|
///
|
|
/// \returns A parse tree for the demangled string - or a null pointer
|
|
/// on failure.
|
|
/// The lifetime of the returned node tree ends with the lifetime of the
|
|
/// context or with a call of clear().
|
|
NodePointer demangleSymbolAsNode(llvm::StringRef MangledName);
|
|
|
|
/// Demangle the given type and return the parse tree.
|
|
///
|
|
/// \param MangledName The mangled symbol string, which start a mangling
|
|
/// prefix: _T, _T0, $S, _$S.
|
|
///
|
|
/// \returns A parse tree for the demangled string - or a null pointer
|
|
/// on failure.
|
|
/// The lifetime of the returned node tree ends with the lifetime of the
|
|
/// context or with a call of clear().
|
|
NodePointer demangleTypeAsNode(llvm::StringRef MangledName);
|
|
|
|
/// Demangle the given symbol and return the readable name.
|
|
///
|
|
/// \param MangledName The mangled symbol string, which start a mangling
|
|
/// prefix: _T, _T0, $S, _$S.
|
|
///
|
|
/// \returns The demangled string.
|
|
std::string demangleSymbolAsString(
|
|
llvm::StringRef MangledName,
|
|
const DemangleOptions &Options = DemangleOptions());
|
|
|
|
/// Demangle the given type and return the readable name.
|
|
///
|
|
/// \param MangledName The mangled type string, which does _not_ start with
|
|
/// a mangling prefix.
|
|
///
|
|
/// \returns The demangled string.
|
|
std::string
|
|
demangleTypeAsString(llvm::StringRef MangledName,
|
|
const DemangleOptions &Options = DemangleOptions());
|
|
|
|
/// Returns true if the mangledName refers to a thunk function.
|
|
///
|
|
/// Thunk functions are either (ObjC) partial apply forwarder, swift-as-ObjC
|
|
/// or ObjC-as-swift thunks or allocating init functions.
|
|
bool isThunkSymbol(llvm::StringRef MangledName);
|
|
|
|
/// Returns the mangled name of the target of a thunk.
|
|
///
|
|
/// \returns Returns the remaining name after removing the thunk mangling
|
|
/// characters from \p MangledName. If \p MangledName is not a thunk symbol
|
|
/// or the thunk target cannot be derived from the mangling, an empty string
|
|
/// is returned.
|
|
std::string getThunkTarget(llvm::StringRef MangledName);
|
|
|
|
/// Returns true if the \p mangledName refers to a function which conforms to
|
|
/// the Swift calling convention.
|
|
///
|
|
/// The return value is unspecified if the \p MangledName does not refer to a
|
|
/// function symbol.
|
|
bool hasSwiftCallingConvention(llvm::StringRef MangledName);
|
|
|
|
/// Demangle the given symbol and return the module name of the symbol.
|
|
///
|
|
/// \param mangledName The mangled symbol string, which start a mangling
|
|
/// prefix: _T, _T0, $S, _$S.
|
|
///
|
|
/// \returns The module name.
|
|
std::string getModuleName(llvm::StringRef mangledName);
|
|
|
|
/// Deallocates all nodes.
|
|
///
|
|
/// The memory which is used for nodes is not freed but recycled for the next
|
|
/// demangling operation.
|
|
void clear();
|
|
};
|
|
|
|
/// Standalone utility function to demangle the given symbol as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleSymbolAsString should be used instead.
|
|
/// \param mangledName The mangled name string pointer.
|
|
/// \param mangledNameLength The length of the mangledName string.
|
|
/// \returns The demangled string.
|
|
std::string
|
|
demangleSymbolAsString(const char *mangledName, size_t mangledNameLength,
|
|
const DemangleOptions &options = DemangleOptions());
|
|
|
|
/// Standalone utility function to demangle the given symbol as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleSymbolAsString should be used instead.
|
|
/// \param mangledName The mangled name string.
|
|
/// \returns The demangled string.
|
|
inline std::string
|
|
demangleSymbolAsString(const std::string &mangledName,
|
|
const DemangleOptions &options = DemangleOptions()) {
|
|
return demangleSymbolAsString(mangledName.data(), mangledName.size(),
|
|
options);
|
|
}
|
|
|
|
/// Standalone utility function to demangle the given symbol as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleSymbolAsString should be used instead.
|
|
/// \param MangledName The mangled name string.
|
|
/// \returns The demangled string.
|
|
inline std::string
|
|
demangleSymbolAsString(llvm::StringRef MangledName,
|
|
const DemangleOptions &Options = DemangleOptions()) {
|
|
return demangleSymbolAsString(MangledName.data(),
|
|
MangledName.size(), Options);
|
|
}
|
|
|
|
/// Standalone utility function to demangle the given type as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleTypeAsString should be used instead.
|
|
/// \param mangledName The mangled name string pointer.
|
|
/// \param mangledNameLength The length of the mangledName string.
|
|
/// \returns The demangled string.
|
|
std::string
|
|
demangleTypeAsString(const char *mangledName, size_t mangledNameLength,
|
|
const DemangleOptions &options = DemangleOptions());
|
|
|
|
/// Standalone utility function to demangle the given type as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleTypeAsString should be used instead.
|
|
/// \param mangledName The mangled name string.
|
|
/// \returns The demangled string.
|
|
inline std::string
|
|
demangleTypeAsString(const std::string &mangledName,
|
|
const DemangleOptions &options = DemangleOptions()) {
|
|
return demangleTypeAsString(mangledName.data(), mangledName.size(), options);
|
|
}
|
|
|
|
/// Standalone utility function to demangle the given type as string.
|
|
///
|
|
/// If performance is an issue when demangling multiple symbols,
|
|
/// Context::demangleTypeAsString should be used instead.
|
|
/// \param MangledName The mangled name string.
|
|
/// \returns The demangled string.
|
|
inline std::string
|
|
demangleTypeAsString(llvm::StringRef MangledName,
|
|
const DemangleOptions &Options = DemangleOptions()) {
|
|
return demangleTypeAsString(MangledName.data(),
|
|
MangledName.size(), Options);
|
|
}
|
|
|
|
|
|
enum class OperatorKind {
|
|
NotOperator,
|
|
Prefix,
|
|
Postfix,
|
|
Infix,
|
|
};
|
|
|
|
/// A mangling error, which consists of an error code and a Node pointer
|
|
struct LLVM_NODISCARD ManglingError {
|
|
enum Code {
|
|
Success = 0,
|
|
AssertionFailed,
|
|
Uninitialized,
|
|
TooComplex,
|
|
BadNodeKind,
|
|
BadNominalTypeKind,
|
|
NotAStorageNode,
|
|
UnsupportedNodeKind,
|
|
UnexpectedBuiltinVectorType,
|
|
UnexpectedBuiltinType,
|
|
MultipleChildNodes,
|
|
WrongNodeType,
|
|
WrongDependentMemberType,
|
|
BadDirectness,
|
|
UnknownEncoding,
|
|
InvalidImplCalleeConvention,
|
|
InvalidImplDifferentiability,
|
|
InvalidImplFunctionAttribute,
|
|
InvalidImplParameterConvention,
|
|
InvalidMetatypeRepresentation,
|
|
MultiByteRelatedEntity,
|
|
BadValueWitnessKind,
|
|
NotAContextNode,
|
|
};
|
|
|
|
Code code;
|
|
NodePointer node;
|
|
unsigned line;
|
|
|
|
ManglingError() : code(Uninitialized), node(nullptr) {}
|
|
ManglingError(Code c) : code(c), node(nullptr), line(0) {}
|
|
ManglingError(Code c, NodePointer n, unsigned l) : code(c), node(n), line(l) {}
|
|
|
|
bool isSuccess() const { return code == Success; }
|
|
};
|
|
|
|
#define MANGLING_ERROR(c,n) ManglingError((c), (n), __LINE__)
|
|
|
|
/// Used as a return type for mangling functions that may fail
|
|
template <typename T>
|
|
class LLVM_NODISCARD ManglingErrorOr {
|
|
private:
|
|
ManglingError err_;
|
|
T value_;
|
|
|
|
public:
|
|
ManglingErrorOr() : err_() {}
|
|
ManglingErrorOr(ManglingError::Code code,
|
|
NodePointer node = nullptr,
|
|
unsigned line = 0)
|
|
: err_(code, node, line) {}
|
|
ManglingErrorOr(const ManglingError &err) : err_(err) {}
|
|
ManglingErrorOr(const T &t) : err_(ManglingError::Success), value_(t) {}
|
|
ManglingErrorOr(T &&t) : err_(ManglingError::Success), value_(std::move(t)) {}
|
|
|
|
bool isSuccess() const { return err_.code == ManglingError::Success; }
|
|
|
|
const ManglingError &error() const { return err_; }
|
|
|
|
const T &result() const {
|
|
assert(isSuccess());
|
|
return value_;
|
|
}
|
|
};
|
|
|
|
/// Remangle a demangled parse tree.
|
|
ManglingErrorOr<std::string> mangleNode(NodePointer root);
|
|
|
|
using SymbolicResolver =
|
|
llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
|
|
const void *)>;
|
|
|
|
/// Remangle a demangled parse tree, using a callback to resolve
|
|
/// symbolic references.
|
|
ManglingErrorOr<std::string> mangleNode(NodePointer root, SymbolicResolver resolver);
|
|
|
|
/// Remangle a demangled parse tree, using a callback to resolve
|
|
/// symbolic references.
|
|
///
|
|
/// The returned string is owned by \p Factory. This means \p Factory must stay
|
|
/// alive as long as the returned string is used.
|
|
ManglingErrorOr<llvm::StringRef> mangleNode(NodePointer root,
|
|
SymbolicResolver resolver,
|
|
NodeFactory &Factory);
|
|
|
|
/// Remangle in the old mangling scheme.
|
|
///
|
|
/// This is only used for objc-runtime names.
|
|
ManglingErrorOr<std::string> mangleNodeOld(NodePointer root);
|
|
|
|
/// Remangle in the old mangling scheme.
|
|
///
|
|
/// This is only used for objc-runtime names.
|
|
/// The returned string is owned by \p Factory. This means \p Factory must stay
|
|
/// alive as long as the returned string is used.
|
|
ManglingErrorOr<llvm::StringRef> mangleNodeOld(NodePointer node,
|
|
NodeFactory &Factory);
|
|
|
|
/// Remangle in the old mangling scheme and embed the name in "_Tt<name>_".
|
|
///
|
|
/// The returned string is null terminated and owned by \p Factory. This means
|
|
/// \p Factory must stay alive as long as the returned string is used.
|
|
ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
|
|
NodeFactory &Factory);
|
|
|
|
/// Transform the node structure to a string.
|
|
///
|
|
/// Typical usage:
|
|
/// \code
|
|
/// std::string aDemangledName =
|
|
/// swift::Demangler::nodeToString(aNode)
|
|
/// \endcode
|
|
///
|
|
/// \param Root A pointer to a parse tree generated by the demangler.
|
|
/// \param Options An object encapsulating options to use to perform this demangling.
|
|
///
|
|
/// \returns A string representing the demangled name.
|
|
///
|
|
std::string nodeToString(NodePointer Root,
|
|
const DemangleOptions &Options = DemangleOptions());
|
|
|
|
/// Transforms a mangled key path accessor thunk helper
|
|
/// into the identfier/subscript that would be used to invoke it in swift code.
|
|
std::string keyPathSourceString(const char *MangledName,
|
|
size_t MangledNameLength);
|
|
|
|
/// A class for printing to a std::string.
|
|
class DemanglerPrinter {
|
|
public:
|
|
DemanglerPrinter() = default;
|
|
|
|
DemanglerPrinter &operator<<(llvm::StringRef Value) & {
|
|
Stream.append(Value.data(), Value.size());
|
|
return *this;
|
|
}
|
|
|
|
DemanglerPrinter &operator<<(char c) & {
|
|
Stream.push_back(c);
|
|
return *this;
|
|
}
|
|
DemanglerPrinter &operator<<(unsigned long long n) &;
|
|
DemanglerPrinter &operator<<(long long n) &;
|
|
DemanglerPrinter &operator<<(unsigned long n) & {
|
|
return *this << (unsigned long long)n;
|
|
}
|
|
DemanglerPrinter &operator<<(long n) & {
|
|
return *this << (long long)n;
|
|
}
|
|
DemanglerPrinter &operator<<(unsigned n) & {
|
|
return *this << (unsigned long long)n;
|
|
}
|
|
DemanglerPrinter &operator<<(int n) & {
|
|
return *this << (long long)n;
|
|
}
|
|
|
|
template<typename T>
|
|
DemanglerPrinter &&operator<<(T &&x) && {
|
|
return std::move(*this << std::forward<T>(x));
|
|
}
|
|
|
|
DemanglerPrinter &writeHex(unsigned long long n) &;
|
|
|
|
std::string &&str() && { return std::move(Stream); }
|
|
|
|
llvm::StringRef getStringRef() const { return Stream; }
|
|
|
|
/// Shrinks the buffer.
|
|
void resetSize(size_t toPos) {
|
|
assert(toPos <= Stream.size());
|
|
Stream.resize(toPos);
|
|
}
|
|
private:
|
|
std::string Stream;
|
|
};
|
|
|
|
/// Returns a the node kind \p k as string.
|
|
const char *getNodeKindString(swift::Demangle::Node::Kind k);
|
|
|
|
/// Prints the whole node tree \p Root in readable form into a std::string.
|
|
///
|
|
/// Useful for debugging.
|
|
std::string getNodeTreeAsString(NodePointer Root);
|
|
|
|
bool nodeConsumesGenericArgs(Node *node);
|
|
|
|
bool isSpecialized(Node *node);
|
|
|
|
ManglingErrorOr<NodePointer> getUnspecialized(Node *node, NodeFactory &Factory);
|
|
|
|
/// Returns true if the node \p kind refers to a context node, e.g. a nominal
|
|
/// type or a function.
|
|
bool isContext(Node::Kind kind);
|
|
|
|
/// Returns true if the node \p kind refers to a node which is placed before a
|
|
/// function node, e.g. a specialization attribute.
|
|
bool isFunctionAttr(Node::Kind kind);
|
|
|
|
/// Form a StringRef around the mangled name starting at base, if the name may
|
|
/// contain symbolic references.
|
|
llvm::StringRef makeSymbolicMangledNameStringRef(const char *base);
|
|
|
|
SWIFT_END_INLINE_NAMESPACE
|
|
} // end namespace Demangle
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_DEMANGLING_DEMANGLE_H
|