Files
swift-mirror/lib/Demangling/NodePrinter.cpp

3794 lines
131 KiB
C++

//===--- NodePrinter.cpp - Swift Demangling Node Printer ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 implements the node printer for demangle node trees.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/Ownership.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Strings.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace swift;
using namespace Demangle;
using llvm::StringRef;
DemanglerPrinter &DemanglerPrinter::operator<<(unsigned long long n) & {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%llu", n);
Stream.append(buffer);
return *this;
}
DemanglerPrinter &DemanglerPrinter::writeHex(unsigned long long n) & {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%llX", n);
Stream.append(buffer);
return *this;
}
DemanglerPrinter &DemanglerPrinter::operator<<(long long n) & {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%lld",n);
Stream.append(buffer);
return *this;
}
#if SWIFT_STDLIB_HAS_TYPE_PRINTING
[[noreturn]]
static void printer_unreachable(const char *Message) {
fprintf(stderr, "fatal error: %s\n", Message);
std::abort();
}
std::string Demangle::genericParameterName(uint64_t depth, uint64_t index) {
DemanglerPrinter name;
do {
name << (char)('A' + (index % 26));
index /= 26;
} while (index);
if (depth != 0)
name << depth;
return std::move(name).str();
}
namespace {
struct QuotedString {
std::string Value;
explicit QuotedString(std::string Value) : Value(Value) {}
};
static DemanglerPrinter &operator<<(DemanglerPrinter &printer,
const QuotedString &QS) {
printer << '"';
for (auto C : QS.Value) {
switch (C) {
case '\\': printer << "\\\\"; break;
case '\t': printer << "\\t"; break;
case '\n': printer << "\\n"; break;
case '\r': printer << "\\r"; break;
case '"': printer << "\\\""; break;
case '\0': printer << "\\0"; break;
default:
auto c = static_cast<unsigned char>(C);
// Other control or high-bit characters should get escaped.
if (c < 0x20 || c >= 0x7F) {
static const char Hexdigit[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
printer << "\\x" << Hexdigit[c >> 4] << Hexdigit[c & 0xF];
} else {
printer << (char)c;
}
break;
}
}
printer << '"';
return printer;
}
static StringRef toString(Directness d) {
switch (d) {
case Directness::Direct:
return "direct";
case Directness::Indirect:
return "indirect";
}
printer_unreachable("bad directness");
}
static StringRef toString(ValueWitnessKind k) {
switch (k) {
case ValueWitnessKind::AllocateBuffer:
return "allocateBuffer";
case ValueWitnessKind::AssignWithCopy:
return "assignWithCopy";
case ValueWitnessKind::AssignWithTake:
return "assignWithTake";
case ValueWitnessKind::DeallocateBuffer:
return "deallocateBuffer";
case ValueWitnessKind::Destroy:
return "destroy";
case ValueWitnessKind::DestroyBuffer:
return "destroyBuffer";
case ValueWitnessKind::InitializeBufferWithCopyOfBuffer:
return "initializeBufferWithCopyOfBuffer";
case ValueWitnessKind::InitializeBufferWithCopy:
return "initializeBufferWithCopy";
case ValueWitnessKind::InitializeWithCopy:
return "initializeWithCopy";
case ValueWitnessKind::InitializeBufferWithTake:
return "initializeBufferWithTake";
case ValueWitnessKind::InitializeWithTake:
return "initializeWithTake";
case ValueWitnessKind::ProjectBuffer:
return "projectBuffer";
case ValueWitnessKind::InitializeBufferWithTakeOfBuffer:
return "initializeBufferWithTakeOfBuffer";
case ValueWitnessKind::DestroyArray:
return "destroyArray";
case ValueWitnessKind::InitializeArrayWithCopy:
return "initializeArrayWithCopy";
case ValueWitnessKind::InitializeArrayWithTakeFrontToBack:
return "initializeArrayWithTakeFrontToBack";
case ValueWitnessKind::InitializeArrayWithTakeBackToFront:
return "initializeArrayWithTakeBackToFront";
case ValueWitnessKind::StoreExtraInhabitant:
return "storeExtraInhabitant";
case ValueWitnessKind::GetExtraInhabitantIndex:
return "getExtraInhabitantIndex";
case ValueWitnessKind::GetEnumTag:
return "getEnumTag";
case ValueWitnessKind::DestructiveProjectEnumData:
return "destructiveProjectEnumData";
case ValueWitnessKind::DestructiveInjectEnumTag:
return "destructiveInjectEnumTag";
case ValueWitnessKind::GetEnumTagSinglePayload:
return "getEnumTagSinglePayload";
case ValueWitnessKind::StoreEnumTagSinglePayload:
return "storeEnumTagSinglePayload";
}
printer_unreachable("bad value witness kind");
}
} // end anonymous namespace
void NodePrinter::printChildren(Node::iterator begin, Node::iterator end,
unsigned depth, const char *sep) {
for (; begin != end;) {
print(*begin, depth + 1);
++begin;
if (sep && begin != end)
Printer << sep;
}
}
void NodePrinter::printChildren(NodePointer Node, unsigned depth,
const char *sep) {
if (!Node)
return;
Node::iterator begin = Node->begin(), end = Node->end();
printChildren(begin, end, depth, sep);
}
NodePointer NodePrinter::getFirstChildOfKind(NodePointer Node,
Node::Kind kind) {
if (!Node)
return nullptr;
for (NodePointer child : *Node) {
if (child && child->getKind() == kind)
return child;
}
return nullptr;
}
void NodePrinter::printBoundGenericNoSugar(NodePointer Node, unsigned depth) {
if (Node->getNumChildren() < 2)
return;
NodePointer typelist = Node->getChild(1);
print(Node->getChild(0), depth + 1);
Printer << "<";
printChildren(typelist, depth, ", ");
Printer << ">";
}
static bool isExistentialType(NodePointer node) {
return (node->getKind() == Node::Kind::ExistentialMetatype ||
node->getKind() == Node::Kind::ProtocolList ||
node->getKind() == Node::Kind::ProtocolListWithClass ||
node->getKind() == Node::Kind::ProtocolListWithAnyObject);
}
void NodePrinter::printOptionalIndex(NodePointer node) {
assert(node->getKind() == Node::Kind::Index ||
node->getKind() == Node::Kind::UnknownIndex);
if (node->hasIndex())
Printer << "#" << node->getIndex() << " ";
}
bool NodePrinter::printContext(NodePointer Context) {
if (!Options.QualifyEntities)
return false;
if (Context->getKind() == Node::Kind::Module) {
if (Context->getText() == swift::STDLIB_NAME)
return Options.DisplayStdlibModule;
if (Context->getText() == swift::MANGLING_MODULE_OBJC)
return Options.DisplayObjCModule;
if (Context->getText() == Options.HidingCurrentModule)
return false;
if (Context->getText().starts_with(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX))
return Options.DisplayDebuggerGeneratedModule;
}
return true;
}
bool NodePrinter::isSimpleType(NodePointer Node) {
switch (Node->getKind()) {
case Node::Kind::AssociatedType:
case Node::Kind::AssociatedTypeRef:
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericProtocol:
case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericTypeAlias:
case Node::Kind::BoundGenericFunction:
case Node::Kind::BuiltinTypeName:
case Node::Kind::BuiltinTupleType:
case Node::Kind::BuiltinFixedArray:
case Node::Kind::Class:
case Node::Kind::DependentGenericType:
case Node::Kind::DependentMemberType:
case Node::Kind::DependentGenericParamType:
case Node::Kind::DynamicSelf:
case Node::Kind::Enum:
case Node::Kind::ErrorType:
case Node::Kind::ExistentialMetatype:
case Node::Kind::Metatype:
case Node::Kind::MetatypeRepresentation:
case Node::Kind::Module:
case Node::Kind::Tuple:
case Node::Kind::Pack:
case Node::Kind::SILPackDirect:
case Node::Kind::SILPackIndirect:
case Node::Kind::ConstrainedExistentialRequirementList:
case Node::Kind::ConstrainedExistentialSelf:
case Node::Kind::Protocol:
case Node::Kind::ProtocolSymbolicReference:
case Node::Kind::ReturnType:
case Node::Kind::SILBoxType:
case Node::Kind::SILBoxTypeWithLayout:
case Node::Kind::Structure:
case Node::Kind::OtherNominalType:
case Node::Kind::TupleElementName:
case Node::Kind::TypeAlias:
case Node::Kind::TypeList:
case Node::Kind::LabelList:
case Node::Kind::TypeSymbolicReference:
case Node::Kind::SugaredOptional:
case Node::Kind::SugaredArray:
case Node::Kind::SugaredInlineArray:
case Node::Kind::SugaredDictionary:
case Node::Kind::SugaredParen:
case Node::Kind::Integer:
case Node::Kind::NegativeInteger:
return true;
case Node::Kind::Type:
return isSimpleType(Node->getChild(0));
case Node::Kind::ProtocolList:
return Node->getChild(0)->getNumChildren() <= 1;
case Node::Kind::ProtocolListWithAnyObject:
return Node->getChild(0)->getChild(0)->getNumChildren() == 0;
case Node::Kind::ConstrainedExistential:
case Node::Kind::PackElement:
case Node::Kind::PackElementLevel:
case Node::Kind::PackExpansion:
case Node::Kind::ProtocolListWithClass:
case Node::Kind::AccessorAttachedMacroExpansion:
case Node::Kind::AccessorFunctionReference:
case Node::Kind::Allocator:
case Node::Kind::ArgumentTuple:
case Node::Kind::AssociatedConformanceDescriptor:
case Node::Kind::AssociatedTypeDescriptor:
case Node::Kind::AssociatedTypeMetadataAccessor:
case Node::Kind::AssociatedTypeWitnessTableAccessor:
case Node::Kind::AsyncRemoved:
case Node::Kind::AutoClosureType:
case Node::Kind::BaseConformanceDescriptor:
case Node::Kind::BaseWitnessTableAccessor:
case Node::Kind::BodyAttachedMacroExpansion:
case Node::Kind::ClangType:
case Node::Kind::ClassMetadataBaseOffset:
case Node::Kind::CFunctionPointer:
case Node::Kind::ConformanceAttachedMacroExpansion:
case Node::Kind::Constructor:
case Node::Kind::CoroutineContinuationPrototype:
case Node::Kind::CurryThunk:
case Node::Kind::SILThunkIdentity:
case Node::Kind::DispatchThunk:
case Node::Kind::Deallocator:
case Node::Kind::IsolatedDeallocator:
case Node::Kind::DeclContext:
case Node::Kind::DefaultArgumentInitializer:
case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
case Node::Kind::DefaultAssociatedConformanceAccessor:
case Node::Kind::DependentAssociatedTypeRef:
case Node::Kind::DependentGenericSignature:
case Node::Kind::DependentGenericParamPackMarker:
case Node::Kind::DependentGenericParamCount:
case Node::Kind::DependentGenericConformanceRequirement:
case Node::Kind::DependentGenericLayoutRequirement:
case Node::Kind::DependentGenericSameTypeRequirement:
case Node::Kind::DependentGenericSameShapeRequirement:
case Node::Kind::DependentPseudogenericSignature:
case Node::Kind::Destructor:
case Node::Kind::DidSet:
case Node::Kind::DirectMethodReferenceAttribute:
case Node::Kind::Directness:
case Node::Kind::DynamicAttribute:
case Node::Kind::EscapingAutoClosureType:
case Node::Kind::EscapingObjCBlock:
case Node::Kind::NoEscapeFunctionType:
case Node::Kind::ExplicitClosure:
case Node::Kind::Extension:
case Node::Kind::ExtensionAttachedMacroExpansion:
case Node::Kind::EnumCase:
case Node::Kind::FieldOffset:
case Node::Kind::FreestandingMacroExpansion:
case Node::Kind::FullObjCResilientClassStub:
case Node::Kind::FullTypeMetadata:
case Node::Kind::Function:
case Node::Kind::FunctionSignatureSpecialization:
case Node::Kind::FunctionSignatureSpecializationParam:
case Node::Kind::FunctionSignatureSpecializationReturn:
case Node::Kind::FunctionSignatureSpecializationParamKind:
case Node::Kind::FunctionSignatureSpecializationParamPayload:
case Node::Kind::FunctionType:
case Node::Kind::GenericProtocolWitnessTable:
case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
case Node::Kind::GenericPartialSpecialization:
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
case Node::Kind::GenericSpecialization:
case Node::Kind::GenericSpecializationNotReAbstracted:
case Node::Kind::GenericSpecializationInResilienceDomain:
case Node::Kind::GenericSpecializationParam:
case Node::Kind::GenericSpecializationPrespecialized:
case Node::Kind::InlinedGenericFunction:
case Node::Kind::GenericTypeMetadataPattern:
case Node::Kind::Getter:
case Node::Kind::Global:
case Node::Kind::GlobalGetter:
case Node::Kind::Identifier:
case Node::Kind::Index:
case Node::Kind::InitAccessor:
case Node::Kind::IVarInitializer:
case Node::Kind::IVarDestroyer:
case Node::Kind::ImplDifferentiabilityKind:
case Node::Kind::ImplEscaping:
case Node::Kind::ImplErasedIsolation:
case Node::Kind::ImplSendingResult:
case Node::Kind::ImplConvention:
case Node::Kind::ImplParameterResultDifferentiability:
case Node::Kind::ImplParameterSending:
case Node::Kind::ImplParameterIsolated:
case Node::Kind::ImplParameterImplicitLeading:
case Node::Kind::ImplFunctionAttribute:
case Node::Kind::ImplFunctionConvention:
case Node::Kind::ImplFunctionConventionName:
case Node::Kind::ImplFunctionType:
case Node::Kind::ImplCoroutineKind:
case Node::Kind::ImplInvocationSubstitutions:
case Node::Kind::ImplPatternSubstitutions:
case Node::Kind::ImplicitClosure:
case Node::Kind::ImplParameter:
case Node::Kind::ImplResult:
case Node::Kind::ImplYield:
case Node::Kind::ImplErrorResult:
case Node::Kind::InOut:
case Node::Kind::InfixOperator:
case Node::Kind::Initializer:
case Node::Kind::Isolated:
case Node::Kind::Sending:
case Node::Kind::CompileTimeLiteral:
case Node::Kind::ConstValue:
case Node::Kind::PropertyWrapperBackingInitializer:
case Node::Kind::PropertyWrapperInitFromProjectedValue:
case Node::Kind::KeyPathGetterThunkHelper:
case Node::Kind::KeyPathSetterThunkHelper:
case Node::Kind::KeyPathUnappliedMethodThunkHelper:
case Node::Kind::KeyPathAppliedMethodThunkHelper:
case Node::Kind::KeyPathEqualsThunkHelper:
case Node::Kind::KeyPathHashThunkHelper:
case Node::Kind::LazyProtocolWitnessTableAccessor:
case Node::Kind::LazyProtocolWitnessTableCacheVariable:
case Node::Kind::LocalDeclName:
case Node::Kind::Macro:
case Node::Kind::MacroExpansionLoc:
case Node::Kind::MacroExpansionUniqueName:
case Node::Kind::MaterializeForSet:
case Node::Kind::MemberAttributeAttachedMacroExpansion:
case Node::Kind::MemberAttachedMacroExpansion:
case Node::Kind::MergedFunction:
case Node::Kind::Metaclass:
case Node::Kind::MethodDescriptor:
case Node::Kind::MethodLookupFunction:
case Node::Kind::ModifyAccessor:
case Node::Kind::Modify2Accessor:
case Node::Kind::NativeOwningAddressor:
case Node::Kind::NativeOwningMutableAddressor:
case Node::Kind::NativePinningAddressor:
case Node::Kind::NativePinningMutableAddressor:
case Node::Kind::NominalTypeDescriptor:
case Node::Kind::NominalTypeDescriptorRecord:
case Node::Kind::NonObjCAttribute:
case Node::Kind::Number:
case Node::Kind::ObjCAsyncCompletionHandlerImpl:
case Node::Kind::ObjCAttribute:
case Node::Kind::ObjCBlock:
case Node::Kind::ObjCMetadataUpdateFunction:
case Node::Kind::ObjCResilientClassStub:
case Node::Kind::OpaqueTypeDescriptor:
case Node::Kind::OpaqueTypeDescriptorRecord:
case Node::Kind::OpaqueTypeDescriptorAccessor:
case Node::Kind::OpaqueTypeDescriptorAccessorImpl:
case Node::Kind::OpaqueTypeDescriptorAccessorKey:
case Node::Kind::OpaqueTypeDescriptorAccessorVar:
case Node::Kind::Owned:
case Node::Kind::OwningAddressor:
case Node::Kind::OwningMutableAddressor:
case Node::Kind::PartialApplyForwarder:
case Node::Kind::PartialApplyObjCForwarder:
case Node::Kind::PeerAttachedMacroExpansion:
case Node::Kind::PostfixOperator:
case Node::Kind::PreambleAttachedMacroExpansion:
case Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl:
case Node::Kind::PrefixOperator:
case Node::Kind::PrivateDeclName:
case Node::Kind::PropertyDescriptor:
case Node::Kind::ProtocolConformance:
case Node::Kind::ProtocolConformanceDescriptor:
case Node::Kind::ProtocolConformanceDescriptorRecord:
case Node::Kind::MetadataInstantiationCache:
case Node::Kind::ProtocolDescriptor:
case Node::Kind::ProtocolDescriptorRecord:
case Node::Kind::ProtocolRequirementsBaseDescriptor:
case Node::Kind::ProtocolSelfConformanceDescriptor:
case Node::Kind::ProtocolSelfConformanceWitness:
case Node::Kind::ProtocolSelfConformanceWitnessTable:
case Node::Kind::ProtocolWitness:
case Node::Kind::ProtocolWitnessTable:
case Node::Kind::ProtocolWitnessTableAccessor:
case Node::Kind::ProtocolWitnessTablePattern:
case Node::Kind::ReabstractionThunk:
case Node::Kind::ReabstractionThunkHelper:
case Node::Kind::ReabstractionThunkHelperWithSelf:
case Node::Kind::ReabstractionThunkHelperWithGlobalActor:
case Node::Kind::ReadAccessor:
case Node::Kind::Read2Accessor:
case Node::Kind::RelatedEntityDeclName:
case Node::Kind::RetroactiveConformance:
case Node::Kind::Setter:
case Node::Kind::Shared:
case Node::Kind::SILBoxLayout:
case Node::Kind::SILBoxMutableField:
case Node::Kind::SILBoxImmutableField:
case Node::Kind::IsSerialized:
case Node::Kind::DroppedArgument:
case Node::Kind::SpecializationPassID:
case Node::Kind::Static:
case Node::Kind::Subscript:
case Node::Kind::Suffix:
case Node::Kind::ThinFunctionType:
case Node::Kind::TupleElement:
case Node::Kind::TypeMangling:
case Node::Kind::TypeMetadata:
case Node::Kind::TypeMetadataAccessFunction:
case Node::Kind::TypeMetadataCompletionFunction:
case Node::Kind::TypeMetadataInstantiationCache:
case Node::Kind::TypeMetadataInstantiationFunction:
case Node::Kind::TypeMetadataSingletonInitializationCache:
case Node::Kind::TypeMetadataDemanglingCache:
case Node::Kind::TypeMetadataLazyCache:
case Node::Kind::UncurriedFunctionType:
#define REF_STORAGE(Name, ...) \
case Node::Kind::Name:
#include "swift/AST/ReferenceStorage.def"
case Node::Kind::UnknownIndex:
case Node::Kind::UnsafeAddressor:
case Node::Kind::UnsafeMutableAddressor:
case Node::Kind::ValueWitness:
case Node::Kind::ValueWitnessTable:
case Node::Kind::Variable:
case Node::Kind::VTableAttribute:
case Node::Kind::VTableThunk:
case Node::Kind::WillSet:
case Node::Kind::ReflectionMetadataBuiltinDescriptor:
case Node::Kind::ReflectionMetadataFieldDescriptor:
case Node::Kind::ReflectionMetadataAssocTypeDescriptor:
case Node::Kind::ReflectionMetadataSuperclassDescriptor:
case Node::Kind::ResilientProtocolWitnessTable:
case Node::Kind::GenericTypeParamDecl:
case Node::Kind::ConcurrentFunctionType:
case Node::Kind::DifferentiableFunctionType:
case Node::Kind::GlobalActorFunctionType:
case Node::Kind::IsolatedAnyFunctionType:
case Node::Kind::NonIsolatedCallerFunctionType:
case Node::Kind::SendingResultFunctionType:
case Node::Kind::AsyncAnnotation:
case Node::Kind::ThrowsAnnotation:
case Node::Kind::TypedThrowsAnnotation:
case Node::Kind::EmptyList:
case Node::Kind::FirstElementMarker:
case Node::Kind::VariadicMarker:
case Node::Kind::OutlinedBridgedMethod:
case Node::Kind::OutlinedCopy:
case Node::Kind::OutlinedConsume:
case Node::Kind::OutlinedRetain:
case Node::Kind::OutlinedRelease:
case Node::Kind::OutlinedInitializeWithTake:
case Node::Kind::OutlinedInitializeWithTakeNoValueWitness:
case Node::Kind::OutlinedInitializeWithCopy:
case Node::Kind::OutlinedAssignWithTake:
case Node::Kind::OutlinedAssignWithCopy:
case Node::Kind::OutlinedDestroy:
case Node::Kind::OutlinedInitializeWithCopyNoValueWitness:
case Node::Kind::OutlinedAssignWithTakeNoValueWitness:
case Node::Kind::OutlinedAssignWithCopyNoValueWitness:
case Node::Kind::OutlinedDestroyNoValueWitness:
case Node::Kind::OutlinedEnumTagStore:
case Node::Kind::OutlinedEnumGetTag:
case Node::Kind::OutlinedEnumProjectDataForLoad:
case Node::Kind::OutlinedVariable:
case Node::Kind::OutlinedReadOnlyObject:
case Node::Kind::AssocTypePath:
case Node::Kind::ModuleDescriptor:
case Node::Kind::AnonymousDescriptor:
case Node::Kind::AssociatedTypeGenericParamRef:
case Node::Kind::ExtensionDescriptor:
case Node::Kind::AnonymousContext:
case Node::Kind::AnyProtocolConformanceList:
case Node::Kind::ConcreteProtocolConformance:
case Node::Kind::PackProtocolConformance:
case Node::Kind::DependentAssociatedConformance:
case Node::Kind::DependentProtocolConformanceAssociated:
case Node::Kind::DependentProtocolConformanceInherited:
case Node::Kind::DependentProtocolConformanceRoot:
case Node::Kind::DependentProtocolConformanceOpaque:
case Node::Kind::ProtocolConformanceRefInTypeModule:
case Node::Kind::ProtocolConformanceRefInProtocolModule:
case Node::Kind::ProtocolConformanceRefInOtherModule:
case Node::Kind::DistributedThunk:
case Node::Kind::DistributedAccessor:
case Node::Kind::DynamicallyReplaceableFunctionKey:
case Node::Kind::DynamicallyReplaceableFunctionImpl:
case Node::Kind::DynamicallyReplaceableFunctionVar:
case Node::Kind::OpaqueType:
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
case Node::Kind::OpaqueReturnType:
case Node::Kind::OpaqueReturnTypeIndex:
case Node::Kind::OpaqueReturnTypeParent:
case Node::Kind::OpaqueReturnTypeOf:
case Node::Kind::CanonicalSpecializedGenericMetaclass:
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache:
case Node::Kind::GlobalVariableOnceDeclList:
case Node::Kind::GlobalVariableOnceFunction:
case Node::Kind::GlobalVariableOnceToken:
case Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Node::Kind::AsyncFunctionPointer:
case Node::Kind::AutoDiffFunction:
case Node::Kind::AutoDiffDerivativeVTableThunk:
case Node::Kind::AutoDiffSelfReorderingReabstractionThunk:
case Node::Kind::AutoDiffSubsetParametersThunk:
case Node::Kind::AutoDiffFunctionKind:
case Node::Kind::DifferentiabilityWitness:
case Node::Kind::NoDerivative:
case Node::Kind::IndexSubset:
case Node::Kind::AsyncAwaitResumePartialFunction:
case Node::Kind::AsyncSuspendResumePartialFunction:
case Node::Kind::AccessibleFunctionRecord:
case Node::Kind::BackDeploymentThunk:
case Node::Kind::BackDeploymentFallback:
case Node::Kind::ExtendedExistentialTypeShape:
case Node::Kind::Uniquable:
case Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference:
case Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference:
case Node::Kind::SymbolicExtendedExistentialType:
case Node::Kind::HasSymbolQuery:
case Node::Kind::ObjectiveCProtocolSymbolicReference:
case Node::Kind::DependentGenericInverseConformanceRequirement:
case Node::Kind::DependentGenericParamValueMarker:
case Node::Kind::CoroFunctionPointer:
case Node::Kind::DefaultOverride:
return false;
}
printer_unreachable("bad node kind");
}
void NodePrinter::printWithParens(NodePointer type, unsigned depth) {
bool needs_parens = !isSimpleType(type);
if (needs_parens)
Printer << "(";
print(type, depth + 1);
if (needs_parens)
Printer << ")";
}
NodePrinter::SugarType NodePrinter::findSugar(NodePointer Node) {
if (Node->getNumChildren() == 1 && Node->getKind() == Node::Kind::Type)
return findSugar(Node->getChild(0));
if (Node->getNumChildren() != 2)
return SugarType::None;
if (Node->getKind() != Node::Kind::BoundGenericEnum &&
Node->getKind() != Node::Kind::BoundGenericStructure)
return SugarType::None;
auto unboundType = Node->getChild(0)->getChild(0); // drill through Type
auto typeArgs = Node->getChild(1);
if (Node->getKind() == Node::Kind::BoundGenericEnum) {
// Swift.Optional
if (isIdentifier(unboundType->getChild(1), "Optional") &&
typeArgs->getNumChildren() == 1 &&
isSwiftModule(unboundType->getChild(0))) {
return SugarType::Optional;
}
// Swift.ImplicitlyUnwrappedOptional
if (isIdentifier(unboundType->getChild(1), "ImplicitlyUnwrappedOptional") &&
typeArgs->getNumChildren() == 1 &&
isSwiftModule(unboundType->getChild(0))) {
return SugarType::ImplicitlyUnwrappedOptional;
}
return SugarType::None;
}
assert(Node->getKind() == Node::Kind::BoundGenericStructure);
// Array
if (isIdentifier(unboundType->getChild(1), "Array") &&
typeArgs->getNumChildren() == 1 &&
isSwiftModule(unboundType->getChild(0))) {
return SugarType::Array;
}
// Dictionary
if (isIdentifier(unboundType->getChild(1), "Dictionary") &&
typeArgs->getNumChildren() == 2 &&
isSwiftModule(unboundType->getChild(0))) {
return SugarType::Dictionary;
}
return SugarType::None;
}
void NodePrinter::printBoundGeneric(NodePointer Node, unsigned depth) {
if (Node->getNumChildren() < 2)
return;
if (Node->getNumChildren() != 2) {
printBoundGenericNoSugar(Node, depth);
return;
}
if (!Options.SynthesizeSugarOnTypes ||
Node->getKind() == Node::Kind::BoundGenericClass) {
// no sugar here
printBoundGenericNoSugar(Node, depth);
return;
}
// Print the conforming type for a "bound" protocol node "as" the protocol
// type.
if (Node->getKind() == Node::Kind::BoundGenericProtocol) {
printChildren(Node->getChild(1), depth);
Printer << " as ";
print(Node->getChild(0), depth + 1);
return;
}
SugarType sugarType = findSugar(Node);
switch (sugarType) {
case SugarType::None:
printBoundGenericNoSugar(Node, depth);
break;
case SugarType::Optional:
case SugarType::ImplicitlyUnwrappedOptional: {
NodePointer type = Node->getChild(1)->getChild(0);
printWithParens(type, depth);
Printer << (sugarType == SugarType::Optional ? "?" : "!");
break;
}
case SugarType::Array: {
NodePointer type = Node->getChild(1)->getChild(0);
Printer << "[";
print(type, depth + 1);
Printer << "]";
break;
}
case SugarType::Dictionary: {
NodePointer keyType = Node->getChild(1)->getChild(0);
NodePointer valueType = Node->getChild(1)->getChild(1);
Printer << "[";
print(keyType, depth + 1);
Printer << " : ";
print(valueType, depth + 1);
Printer << "]";
break;
}
}
}
NodePointer NodePrinter::getChildIf(NodePointer Node, Node::Kind Kind) {
auto result =
std::find_if(Node->begin(), Node->end(),
[&](NodePointer child) { return child->getKind() == Kind; });
return result != Node->end() ? *result : nullptr;
}
void NodePrinter::printFunctionParameters(NodePointer LabelList,
NodePointer ParameterType,
unsigned depth, bool showTypes) {
if (ParameterType->getKind() != Node::Kind::ArgumentTuple) {
setInvalid();
return;
}
NodePointer Parameters = ParameterType->getFirstChild();
assert(Parameters->getKind() == Node::Kind::Type);
Parameters = Parameters->getFirstChild();
if (Parameters->getKind() != Node::Kind::Tuple) {
// only a single not-named parameter
if (showTypes) {
Printer << '(';
print(Parameters, depth + 1);
Printer << ')';
} else {
Printer << "(_:)";
}
return;
}
auto getLabelFor = [&](NodePointer Param, unsigned Index) -> std::string {
auto Label = LabelList->getChild(Index);
assert(Label && (Label->getKind() == Node::Kind::Identifier ||
Label->getKind() == Node::Kind::FirstElementMarker));
return Label->getKind() == Node::Kind::Identifier ? Label->getText().str()
: "_";
};
unsigned ParamIndex = 0;
bool hasLabels = LabelList && LabelList->getNumChildren() > 0;
Printer << '(';
llvm::interleave(
Parameters->begin(), Parameters->end(),
[&](NodePointer Param) {
assert(Param->getKind() == Node::Kind::TupleElement);
if (hasLabels) {
Printer << getLabelFor(Param, ParamIndex) << ':';
} else if (!showTypes) {
if (auto Label = getChildIf(Param, Node::Kind::TupleElementName))
Printer << Label->getText() << ":";
else
Printer << "_:";
}
if (hasLabels && showTypes)
Printer << ' ';
++ParamIndex;
if (showTypes)
print(Param, depth + 1);
},
[&]() { Printer << (showTypes ? ", " : ""); });
Printer << ')';
}
void NodePrinter::printFunctionType(NodePointer LabelList, NodePointer node,
unsigned depth) {
if (node->getNumChildren() < 2) {
setInvalid();
return;
}
auto printConventionWithMangledCType = [this, node,
depth](const char *convention) {
Printer << "@convention(" << convention;
if (node->getFirstChild()->getKind() == Node::Kind::ClangType) {
Printer << ", mangledCType: \"";
print(node->getFirstChild(), depth + 1);
Printer << '"';
}
Printer << ") ";
};
switch (node->getKind()) {
case Node::Kind::FunctionType:
case Node::Kind::UncurriedFunctionType:
case Node::Kind::NoEscapeFunctionType:
break;
case Node::Kind::AutoClosureType:
case Node::Kind::EscapingAutoClosureType:
Printer << "@autoclosure ";
break;
case Node::Kind::ThinFunctionType:
Printer << "@convention(thin) ";
break;
case Node::Kind::CFunctionPointer:
printConventionWithMangledCType("c");
break;
case Node::Kind::EscapingObjCBlock:
Printer << "@escaping ";
LLVM_FALLTHROUGH;
case Node::Kind::ObjCBlock:
printConventionWithMangledCType("block");
break;
default:
assert(false && "Unhandled function type in printFunctionType!");
}
unsigned argIndex = node->getNumChildren() - 2;
unsigned startIndex = 0;
bool isSendable = false, isAsync = false, hasSendingResult = false;
auto diffKind = MangledDifferentiabilityKind::NonDifferentiable;
if (node->getChild(startIndex)->getKind() == Node::Kind::ClangType) {
// handled earlier
++startIndex;
}
// Be sure to check for function signature components in the same
// order that they're added by the demangler, which is the reverse
// of the order that they appear in the mangling grammar.
if (node->getChild(startIndex)->getKind() ==
Node::Kind::SendingResultFunctionType) {
++startIndex;
hasSendingResult = true;
}
// function-isolation; note that these can't actually both appear.
if (node->getChild(startIndex)->getKind() ==
Node::Kind::IsolatedAnyFunctionType) {
print(node->getChild(startIndex), depth + 1);
++startIndex;
}
Node *nonIsolatedCallerNode = nullptr;
if (node->getChild(startIndex)->getKind() ==
Node::Kind::NonIsolatedCallerFunctionType) {
nonIsolatedCallerNode = node->getChild(startIndex);
++startIndex;
}
if (node->getChild(startIndex)->getKind() ==
Node::Kind::GlobalActorFunctionType) {
print(node->getChild(startIndex), depth + 1);
++startIndex;
}
if (node->getChild(startIndex)->getKind() ==
Node::Kind::DifferentiableFunctionType) {
diffKind =
(MangledDifferentiabilityKind)node->getChild(startIndex)->getIndex();
++startIndex;
}
Node *thrownErrorNode = nullptr;
if (node->getChild(startIndex)->getKind() == Node::Kind::ThrowsAnnotation ||
node->getChild(startIndex)->getKind() ==
Node::Kind::TypedThrowsAnnotation) {
thrownErrorNode = node->getChild(startIndex);
++startIndex;
}
if (node->getChild(startIndex)->getKind() ==
Node::Kind::ConcurrentFunctionType) {
++startIndex;
isSendable = true;
}
if (node->getChild(startIndex)->getKind() == Node::Kind::AsyncAnnotation) {
++startIndex;
isAsync = true;
}
switch (diffKind) {
case MangledDifferentiabilityKind::Forward:
Printer << "@differentiable(_forward) ";
break;
case MangledDifferentiabilityKind::Reverse:
Printer << "@differentiable(reverse) ";
break;
case MangledDifferentiabilityKind::Linear:
Printer << "@differentiable(_linear) ";
break;
case MangledDifferentiabilityKind::Normal:
Printer << "@differentiable ";
break;
case MangledDifferentiabilityKind::NonDifferentiable:
break;
}
if (nonIsolatedCallerNode)
print(nonIsolatedCallerNode, depth + 1);
if (isSendable)
Printer << "@Sendable ";
printFunctionParameters(LabelList, node->getChild(argIndex), depth,
Options.ShowFunctionArgumentTypes);
if (!Options.ShowFunctionArgumentTypes)
return;
if (isAsync)
Printer << " async";
if (thrownErrorNode) {
print(thrownErrorNode, depth + 1);
}
Printer << " -> ";
if (hasSendingResult)
Printer << "sending ";
print(node->getChild(argIndex + 1), depth + 1);
}
void NodePrinter::printImplFunctionType(NodePointer fn, unsigned depth) {
NodePointer patternSubs = nullptr;
NodePointer invocationSubs = nullptr;
NodePointer sendingResult = nullptr;
enum State { Attrs, Inputs, Results } curState = Attrs;
auto transitionTo = [&](State newState) {
assert(newState >= curState);
for (; curState != newState; curState = State(curState + 1)) {
switch (curState) {
case Attrs:
if (patternSubs) {
Printer << "@substituted ";
print(patternSubs->getChild(0), depth + 1);
Printer << ' ';
}
Printer << '(';
continue;
case Inputs:
Printer << ") -> ";
if (sendingResult) {
print(sendingResult, depth + 1);
Printer << " ";
}
Printer << "(";
continue;
case Results:
printer_unreachable("no state after Results");
}
printer_unreachable("bad state");
}
};
for (auto &child : *fn) {
if (child->getKind() == Node::Kind::ImplParameter) {
if (curState == Inputs)
Printer << ", ";
transitionTo(Inputs);
print(child, depth + 1);
} else if (child->getKind() == Node::Kind::ImplResult ||
child->getKind() == Node::Kind::ImplYield ||
child->getKind() == Node::Kind::ImplErrorResult) {
if (curState == Results)
Printer << ", ";
transitionTo(Results);
print(child, depth + 1);
} else if (child->getKind() == Node::Kind::ImplPatternSubstitutions) {
patternSubs = child;
} else if (child->getKind() == Node::Kind::ImplInvocationSubstitutions) {
invocationSubs = child;
} else if (child->getKind() == Node::Kind::ImplSendingResult) {
sendingResult = child;
} else {
assert(curState == Attrs);
print(child, depth + 1);
Printer << ' ';
}
}
transitionTo(Results);
Printer << ')';
if (patternSubs) {
Printer << " for <";
printChildren(patternSubs->getChild(1), depth);
Printer << '>';
}
if (invocationSubs) {
Printer << " for <";
printChildren(invocationSubs->getChild(0), depth);
Printer << '>';
}
}
void NodePrinter::printGenericSignature(NodePointer Node, unsigned depth) {
Printer << '<';
unsigned numChildren = Node->getNumChildren();
unsigned numGenericParams = 0;
for (; numGenericParams < numChildren; ++numGenericParams) {
if (Node->getChild(numGenericParams)->getKind() !=
Node::Kind::DependentGenericParamCount) {
break;
}
}
unsigned firstRequirement = numGenericParams;
for (; firstRequirement < numChildren; ++firstRequirement) {
auto child = Node->getChild(firstRequirement);
if (child->getKind() == Node::Kind::Type)
child = child->getChild(0);
if (child->getKind() != Node::Kind::DependentGenericParamPackMarker &&
child->getKind() != Node::Kind::DependentGenericParamValueMarker) {
break;
}
}
auto isGenericParamPack = [&](unsigned depth, unsigned index) {
for (unsigned i = numGenericParams; i < firstRequirement; ++i) {
auto child = Node->getChild(i);
if (child->getKind() != Node::Kind::DependentGenericParamPackMarker)
continue;
child = child->getChild(0);
if (child->getKind() != Node::Kind::Type)
continue;
child = child->getChild(0);
if (child->getKind() != Node::Kind::DependentGenericParamType)
continue;
if (index == child->getChild(0)->getIndex() &&
depth == child->getChild(1)->getIndex()) {
return true;
}
}
return false;
};
auto isGenericParamValue = [&](unsigned depth, unsigned index) {
for (unsigned i = numGenericParams; i < firstRequirement; ++i) {
auto child = Node->getChild(i);
if (child->getKind() != Node::Kind::DependentGenericParamValueMarker)
continue;
child = child->getChild(0);
if (child->getKind() != Node::Kind::Type)
continue;
auto param = child->getChild(0);
auto type = child->getChild(1);
if (param->getKind() != Node::Kind::DependentGenericParamType)
continue;
if (index == param->getChild(0)->getIndex() &&
depth == param->getChild(1)->getIndex()) {
return std::make_pair(true, type);
}
}
return std::make_pair(false, NodePointer());
};
unsigned gpDepth = 0;
for (; gpDepth < numGenericParams; ++gpDepth) {
if (gpDepth != 0)
Printer << "><";
unsigned count = Node->getChild(gpDepth)->getIndex();
for (unsigned index = 0; index < count; ++index) {
if (index != 0)
Printer << ", ";
// Limit the number of printed generic parameters. In practice this
// it will never be exceeded. The limit is only important for malformed
// symbols where count can be really huge.
if (index >= 128) {
Printer << "...";
break;
}
if (isGenericParamPack(gpDepth, index))
Printer << "each ";
auto value = isGenericParamValue(gpDepth, index);
if (value.first)
Printer << "let ";
// FIXME: Depth won't match when a generic signature applies to a
// method in generic type context.
Printer << Options.GenericParameterName(gpDepth, index);
if (value.second) {
Printer << ": ";
print(value.second, depth + 1);
}
}
}
if (firstRequirement != numChildren) {
if (Options.DisplayWhereClauses) {
Printer << " where ";
for (unsigned i = firstRequirement; i < numChildren; ++i) {
if (i > firstRequirement)
Printer << ", ";
print(Node->getChild(i), depth + 1);
}
}
}
Printer << '>';
}
/// Print the relevant parameters and return the new index.
void NodePrinter::printFunctionSigSpecializationParams(NodePointer Node,
unsigned depth) {
unsigned Idx = 0;
unsigned End = Node->getNumChildren();
while (Idx < End) {
NodePointer firstChild = Node->getChild(Idx);
unsigned V = firstChild->getIndex();
auto K = FunctionSigSpecializationParamKind(V);
switch (K) {
case FunctionSigSpecializationParamKind::BoxToValue:
case FunctionSigSpecializationParamKind::BoxToStack:
case FunctionSigSpecializationParamKind::InOutToOut:
print(Node->getChild(Idx++), depth + 1);
break;
case FunctionSigSpecializationParamKind::ConstantPropFunction:
case FunctionSigSpecializationParamKind::ConstantPropGlobal: {
if (Idx + 2 > End)
return;
Printer << "[";
print(Node->getChild(Idx++), depth + 1);
Printer << " : ";
const auto &text = Node->getChild(Idx++)->getText();
std::string demangledName = demangleSymbolAsString(text);
if (demangledName.empty()) {
Printer << text;
} else {
Printer << demangledName;
}
Printer << "]";
break;
}
case FunctionSigSpecializationParamKind::ConstantPropInteger:
case FunctionSigSpecializationParamKind::ConstantPropFloat:
if (Idx + 2 > End)
return;
Printer << "[";
print(Node->getChild(Idx++), depth + 1);
Printer << " : ";
print(Node->getChild(Idx++), depth + 1);
Printer << "]";
break;
case FunctionSigSpecializationParamKind::ConstantPropString:
if (Idx + 3 > End)
return;
Printer << "[";
print(Node->getChild(Idx++), depth + 1);
Printer << " : ";
print(Node->getChild(Idx++), depth + 1);
Printer << "'";
print(Node->getChild(Idx++), depth + 1);
Printer << "'";
Printer << "]";
break;
case FunctionSigSpecializationParamKind::ConstantPropKeyPath:
if (Idx + 4 > End)
return;
Printer << "[";
print(Node->getChild(Idx++), depth + 1);
Printer << " : ";
print(Node->getChild(Idx++), depth + 1);
Printer << "<";
print(Node->getChild(Idx++), depth + 1);
Printer << ",";
print(Node->getChild(Idx++), depth + 1);
Printer << ">]";
break;
case FunctionSigSpecializationParamKind::ClosureProp:
if (Idx + 2 > End)
return;
Printer << "[";
print(Node->getChild(Idx++), depth + 1);
Printer << " : ";
print(Node->getChild(Idx++), depth + 1);
Printer << ", Argument Types : [";
for (unsigned e = Node->getNumChildren(); Idx < e;) {
NodePointer child = Node->getChild(Idx);
// Until we no longer have a type node, keep demangling.
if (child->getKind() != Node::Kind::Type)
break;
print(child, depth + 1);
++Idx;
// If we are not done, print the ", ".
if (Idx < e && Node->getChild(Idx)->hasText())
Printer << ", ";
}
Printer << "]";
break;
default:
assert(
((V & unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed)) ||
(V & unsigned(FunctionSigSpecializationParamKind::GuaranteedToOwned)) ||
(V & unsigned(FunctionSigSpecializationParamKind::SROA)) ||
(V & unsigned(FunctionSigSpecializationParamKind::Dead))||
(V & unsigned(
FunctionSigSpecializationParamKind::ExistentialToGeneric))) &&
"Invalid OptionSet");
print(Node->getChild(Idx++), depth + 1);
}
}
}
void NodePrinter::printSpecializationPrefix(NodePointer node,
StringRef Description,
unsigned depth,
StringRef ParamPrefix) {
if (!Options.DisplayGenericSpecializations) {
if (!SpecializationPrefixPrinted) {
Printer << "specialized ";
SpecializationPrefixPrinted = true;
}
return;
}
Printer << Description << " <";
const char *Separator = "";
int argNum = 0;
for (NodePointer child : *node) {
switch (child->getKind()) {
case Node::Kind::SpecializationPassID:
case Node::Kind::DroppedArgument:
// We skip those nodes since it does not contain any
// information that is useful to our users.
break;
case Node::Kind::IsSerialized:
Printer << Separator;
Separator = ", ";
print(child, depth + 1);
break;
default:
// Ignore empty specializations.
if (child->hasChildren()) {
Printer << Separator << ParamPrefix;
Separator = ", ";
switch (child->getKind()) {
case Node::Kind::FunctionSignatureSpecializationParam:
Printer << "Arg[" << argNum << "] = ";
printFunctionSigSpecializationParams(child, depth);
break;
case Node::Kind::FunctionSignatureSpecializationReturn:
Printer << "Return = ";
printFunctionSigSpecializationParams(child, depth);
break;
default:
print(child, depth + 1);
}
}
++argNum;
break;
}
}
Printer << "> of ";
}
static bool isClassType(NodePointer Node) {
return Node->getKind() == Node::Kind::Class;
}
static bool needSpaceBeforeType(NodePointer Type) {
switch (Type->getKind()) {
case Node::Kind::Type:
return needSpaceBeforeType(Type->getFirstChild());
case Node::Kind::FunctionType:
case Node::Kind::NoEscapeFunctionType:
case Node::Kind::UncurriedFunctionType:
case Node::Kind::DependentGenericType:
return false;
default:
return true;
}
}
/// Determine whether to print an entity's type.
static bool shouldShowEntityType(Node::Kind EntityKind,
const DemangleOptions &Options) {
switch (EntityKind) {
case Node::Kind::ExplicitClosure:
case Node::Kind::ImplicitClosure:
/// The signature of a closure (its `Type` node) can optionally be omitted.
/// Unlike functions which can have overloads, the signature of a closure is
/// not needed to be uniquely identified. A closure is uniquely identified
/// by its index and parent. Omitting the signature improves the readability
/// when long type names are in use.
return Options.ShowClosureSignature;
default:
return true;
}
}
NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
bool asPrefixContext) {
if (depth > NodePrinter::MaxDepth) {
Printer << "<<too complex>>";
return nullptr;
}
if (!Node) {
Printer << "<null node pointer>";
return nullptr;
}
switch (auto kind = Node->getKind()) {
case Node::Kind::Static:
Printer << "static ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AsyncRemoved:
Printer << "async demotion of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::CurryThunk:
Printer << "curry thunk of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::SILThunkIdentity:
Printer << "identity thunk of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::DispatchThunk:
Printer << "dispatch thunk of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::MethodDescriptor:
Printer << "method descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::MethodLookupFunction:
Printer << "method lookup function for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ObjCMetadataUpdateFunction:
Printer << "ObjC metadata update function for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ObjCResilientClassStub:
Printer << "ObjC resilient class stub for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::FullObjCResilientClassStub:
Printer << "full ObjC resilient class stub for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedBridgedMethod:
Printer << "outlined bridged method (" << Node->getText() << ") of ";
return nullptr;
case Node::Kind::OutlinedCopy:
Printer << "outlined copy of ";
print(Node->getChild(0), depth + 1);
if (Node->getNumChildren() > 1)
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::OutlinedConsume:
Printer << "outlined consume of ";
print(Node->getChild(0), depth + 1);
if (Node->getNumChildren() > 1)
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::OutlinedRetain:
Printer << "outlined retain of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedRelease:
Printer << "outlined release of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedInitializeWithTake:
case Node::Kind::OutlinedInitializeWithTakeNoValueWitness:
Printer << "outlined init with take of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedInitializeWithCopy:
case Node::Kind::OutlinedInitializeWithCopyNoValueWitness:
Printer << "outlined init with copy of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedAssignWithTake:
case Node::Kind::OutlinedAssignWithTakeNoValueWitness:
Printer << "outlined assign with take of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedAssignWithCopy:
case Node::Kind::OutlinedAssignWithCopyNoValueWitness:
Printer << "outlined assign with copy of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedDestroy:
case Node::Kind::OutlinedDestroyNoValueWitness:
Printer << "outlined destroy of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedEnumProjectDataForLoad:
Printer << "outlined enum project data for load of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedEnumTagStore:
Printer << "outlined enum tag store of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedEnumGetTag:
Printer << "outlined enum get tag of ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OutlinedVariable:
Printer << "outlined variable #" << Node->getIndex() << " of ";
return nullptr;
case Node::Kind::OutlinedReadOnlyObject:
Printer << "outlined read-only object #" << Node->getIndex() << " of ";
return nullptr;
case Node::Kind::Directness:
Printer << toString(Directness(Node->getIndex())) << " ";
return nullptr;
case Node::Kind::AnonymousContext:
if (Options.QualifyEntities && Options.DisplayExtensionContexts) {
print(Node->getChild(1), depth + 1);
Printer << ".(unknown context at ";
print(Node->getChild(0), depth + 1);
Printer << ")";
if (Node->getNumChildren() >= 3 &&
Node->getChild(2)->getNumChildren() > 0) {
Printer << '<';
print(Node->getChild(2), depth + 1);
Printer << '>';
}
}
return nullptr;
case Node::Kind::Extension:
assert((Node->getNumChildren() == 2 || Node->getNumChildren() == 3)
&& "Extension expects 2 or 3 children.");
if (Options.QualifyEntities && Options.DisplayExtensionContexts) {
Printer << "(extension in ";
// Print the module where extension is defined.
print(Node->getChild(0), depth + 1, true);
Printer << "):";
}
print(Node->getChild(1), depth + 1);
if (Node->getNumChildren() == 3) {
// Currently the runtime does not mangle the generic signature.
// This is an open to-do in swift::_buildDemanglingForContext().
if (!Options.PrintForTypeName)
print(Node->getChild(2), depth + 1);
}
return nullptr;
case Node::Kind::Variable:
return printEntity(Node, depth, asPrefixContext, TypePrinting::WithColon,
/*hasName*/ true);
case Node::Kind::Function:
case Node::Kind::BoundGenericFunction:
return printEntity(Node, depth, asPrefixContext,
TypePrinting::FunctionStyle,
/*hasName*/ true);
case Node::Kind::Subscript:
return printEntity(
Node, depth, asPrefixContext, TypePrinting::FunctionStyle,
/*hasName*/ false, /*ExtraName*/ "", /*ExtraIndex*/ -1, "subscript");
case Node::Kind::Macro:
return printEntity(Node, depth, asPrefixContext,
Node->getNumChildren() == 3? TypePrinting::WithColon
: TypePrinting::FunctionStyle,
/*hasName*/ true);
#define FREESTANDING_MACRO_ROLE(Name, Description)
#define ATTACHED_MACRO_ROLE(Name, Description, MangledChar) \
case Node::Kind::Name##AttachedMacroExpansion: \
return printEntity(Node, depth, asPrefixContext, \
TypePrinting::NoType, /*hasName*/true, \
(Description " macro @" + \
nodeToString(Node->getChild(2)) + " expansion #"), \
(int)Node->getChild(3)->getIndex() + 1);
#include "swift/Basic/MacroRoles.def"
case Node::Kind::FreestandingMacroExpansion:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "freestanding macro expansion #",
(int)Node->getChild(2)->getIndex() + 1);
case Node::Kind::MacroExpansionLoc:
if (Node->getNumChildren() > 0) {
Printer << "module ";
print(Node->getChild(0), depth + 1);
}
if (Node->getNumChildren() > 1) {
Printer << " file ";
print(Node->getChild(1), depth + 1);
}
if (Node->getNumChildren() > 2) {
Printer << " line ";
print(Node->getChild(2), depth + 1);
}
if (Node->getNumChildren() > 3) {
Printer << " column ";
print(Node->getChild(3), depth + 1);
}
return nullptr;
case Node::Kind::MacroExpansionUniqueName:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/true, "unique name #",
(int)Node->getChild(2)->getIndex() + 1);
case Node::Kind::GenericTypeParamDecl:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ true);
case Node::Kind::ExplicitClosure:
return printEntity(
Node, depth, asPrefixContext,
Options.ShowFunctionArgumentTypes ? TypePrinting::FunctionStyle
: TypePrinting::NoType,
/*hasName*/ false, "closure #", (int)Node->getChild(1)->getIndex() + 1);
case Node::Kind::ImplicitClosure:
return printEntity(Node, depth, asPrefixContext,
Options.ShowFunctionArgumentTypes
? TypePrinting::FunctionStyle
: TypePrinting::NoType,
/*hasName*/ false, "implicit closure #",
(int)Node->getChild(1)->getIndex() + 1);
case Node::Kind::Global:
printChildren(Node, depth);
return nullptr;
case Node::Kind::Suffix:
if (Options.DisplayUnmangledSuffix) {
Printer << " with unmangled suffix "
<< QuotedString(Node->getText().str());
}
return nullptr;
case Node::Kind::Initializer:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false, "variable initialization expression");
case Node::Kind::PropertyWrapperBackingInitializer:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false,
"property wrapper backing initializer");
case Node::Kind::PropertyWrapperInitFromProjectedValue:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false,
"property wrapper init from projected value");
case Node::Kind::DefaultArgumentInitializer:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false, "default argument ",
(int)Node->getChild(1)->getIndex());
case Node::Kind::DeclContext:
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Type:
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMangling:
if (Node->getChild(0)->getKind() == Node::Kind::LabelList) {
printFunctionType(Node->getChild(0), Node->getChild(1)->getFirstChild(),
depth);
} else {
print(Node->getChild(0), depth + 1);
}
return nullptr;
case Node::Kind::Class:
case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Protocol:
case Node::Kind::TypeAlias:
case Node::Kind::OtherNominalType:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ true);
case Node::Kind::LocalDeclName:
print(Node->getChild(1), depth + 1);
if (Options.DisplayLocalNameContexts)
Printer << " #" << (Node->getChild(0)->getIndex() + 1);
return nullptr;
case Node::Kind::PrivateDeclName:
if (Node->getNumChildren() > 1) {
if (Options.ShowPrivateDiscriminators)
Printer << '(';
print(Node->getChild(1), depth + 1);
if (Options.ShowPrivateDiscriminators)
Printer << " in " << Node->getChild(0)->getText() << ')';
} else {
if (Options.ShowPrivateDiscriminators) {
Printer << "(in " << Node->getChild(0)->getText() << ')';
}
}
return nullptr;
case Node::Kind::RelatedEntityDeclName:
Printer << "related decl '" << Node->getFirstChild()->getText() << "' for ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::Module:
if (Options.DisplayModuleNames)
Printer << Node->getText();
return nullptr;
case Node::Kind::Identifier:
Printer << Node->getText();
return nullptr;
case Node::Kind::Index:
Printer << Node->getIndex();
return nullptr;
case Node::Kind::UnknownIndex:
Printer << "unknown index";
return nullptr;
case Node::Kind::FunctionType:
case Node::Kind::UncurriedFunctionType:
case Node::Kind::NoEscapeFunctionType:
case Node::Kind::AutoClosureType:
case Node::Kind::EscapingAutoClosureType:
case Node::Kind::ThinFunctionType:
case Node::Kind::CFunctionPointer:
case Node::Kind::ObjCBlock:
case Node::Kind::EscapingObjCBlock:
printFunctionType(nullptr, Node, depth);
return nullptr;
case Node::Kind::ClangType:
Printer << Node->getText();
return nullptr;
case Node::Kind::ArgumentTuple:
printFunctionParameters(nullptr, Node, depth,
Options.ShowFunctionArgumentTypes);
return nullptr;
case Node::Kind::Tuple: {
Printer << "(";
printChildren(Node, depth, ", ");
Printer << ")";
return nullptr;
}
case Node::Kind::TupleElement: {
if (auto Label = getChildIf(Node, Node::Kind::TupleElementName))
Printer << Label->getText() << ": ";
auto Type = getChildIf(Node, Node::Kind::Type);
assert(Type && "malformed Node::Kind::TupleElement");
print(Type, depth + 1);
if (getChildIf(Node, Node::Kind::VariadicMarker))
Printer << "...";
return nullptr;
}
case Node::Kind::TupleElementName:
Printer << Node->getText() << ": ";
return nullptr;
case Node::Kind::Pack: {
Printer << "Pack{";
printChildren(Node, depth, ", ");
Printer << "}";
return nullptr;
}
case Node::Kind::SILPackDirect:
case Node::Kind::SILPackIndirect: {
Printer << (kind == Node::Kind::SILPackDirect ? "@direct" : "@indirect");
Printer << " Pack{";
printChildren(Node, depth, ", ");
Printer << "}";
return nullptr;
}
case Node::Kind::PackExpansion: {
Printer << "repeat ";
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::PackElement: {
Printer << "/* level: " << Node->getChild(1)->getIndex() << " */ ";
Printer << "each ";
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::PackElementLevel:
printer_unreachable("should be handled in Node::Kind::PackElement");
case Node::Kind::ReturnType:
if (Node->getNumChildren() == 0)
Printer << Node->getText();
else {
printChildren(Node, depth);
}
return nullptr;
case Node::Kind::RetroactiveConformance:
if (Node->getNumChildren() != 2)
return nullptr;
Printer << "retroactive @ ";
print(Node->getChild(0), depth + 1);
print(Node->getChild(1), depth + 1);
return nullptr;
#define REF_STORAGE(Name, ...) \
case Node::Kind::Name: \
Printer << keywordOf(ReferenceOwnership::Name) << " "; \
print(Node->getChild(0), depth + 1); \
return nullptr;
#include "swift/AST/ReferenceStorage.def"
case Node::Kind::InOut:
Printer << "inout ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Isolated:
Printer << "isolated ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Sending:
Printer << "sending ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::CompileTimeLiteral:
Printer << "_const ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ConstValue:
Printer << "@const ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Shared:
Printer << "__shared ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Owned:
Printer << "__owned ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NoDerivative:
Printer << "@noDerivative ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NonObjCAttribute:
Printer << "@nonobjc ";
return nullptr;
case Node::Kind::ObjCAttribute:
Printer << "@objc ";
return nullptr;
case Node::Kind::DirectMethodReferenceAttribute:
Printer << "super ";
return nullptr;
case Node::Kind::DynamicAttribute:
Printer << "dynamic ";
return nullptr;
case Node::Kind::VTableAttribute:
Printer << "override ";
return nullptr;
case Node::Kind::FunctionSignatureSpecialization:
printSpecializationPrefix(Node, "function signature specialization", depth);
return nullptr;
case Node::Kind::GenericPartialSpecialization:
printSpecializationPrefix(Node, "generic partial specialization", depth,
"Signature = ");
return nullptr;
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
printSpecializationPrefix(Node,
"generic not-reabstracted partial specialization",
depth, "Signature = ");
return nullptr;
case Node::Kind::GenericSpecialization:
case Node::Kind::GenericSpecializationInResilienceDomain:
printSpecializationPrefix(Node, "generic specialization", depth);
return nullptr;
case Node::Kind::GenericSpecializationPrespecialized:
printSpecializationPrefix(Node, "generic pre-specialization", depth);
return nullptr;
case Node::Kind::GenericSpecializationNotReAbstracted:
printSpecializationPrefix(Node, "generic not re-abstracted specialization",
depth);
return nullptr;
case Node::Kind::InlinedGenericFunction:
printSpecializationPrefix(Node, "inlined generic function", depth);
return nullptr;
case Node::Kind::IsSerialized:
Printer << "serialized";
return nullptr;
case Node::Kind::DroppedArgument:
Printer << "param" << Node->getIndex() << "-removed";
return nullptr;
case Node::Kind::GenericSpecializationParam:
print(Node->getChild(0), depth + 1);
for (unsigned i = 1, e = Node->getNumChildren(); i < e; ++i) {
if (i == 1)
Printer << " with ";
else
Printer << " and ";
print(Node->getChild(i), depth + 1);
}
return nullptr;
case Node::Kind::FunctionSignatureSpecializationReturn:
case Node::Kind::FunctionSignatureSpecializationParam:
printer_unreachable("should be handled in printSpecializationPrefix");
case Node::Kind::FunctionSignatureSpecializationParamPayload: {
std::string demangledName = demangleSymbolAsString(Node->getText());
if (demangledName.empty()) {
Printer << Node->getText();
} else {
Printer << demangledName;
}
return nullptr;
}
case Node::Kind::FunctionSignatureSpecializationParamKind: {
uint64_t raw = Node->getIndex();
bool printedOptionSet = false;
if (raw &
uint64_t(FunctionSigSpecializationParamKind::ExistentialToGeneric)) {
printedOptionSet = true;
Printer << "Existential To Protocol Constrained Generic";
}
if (raw & uint64_t(FunctionSigSpecializationParamKind::Dead)) {
if (printedOptionSet)
Printer << " and ";
printedOptionSet = true;
Printer << "Dead";
}
if (raw & uint64_t(FunctionSigSpecializationParamKind::OwnedToGuaranteed)) {
if (printedOptionSet)
Printer << " and ";
printedOptionSet = true;
Printer << "Owned To Guaranteed";
}
if (raw & uint64_t(FunctionSigSpecializationParamKind::GuaranteedToOwned)) {
if (printedOptionSet)
Printer << " and ";
printedOptionSet = true;
Printer << "Guaranteed To Owned";
}
if (raw & uint64_t(FunctionSigSpecializationParamKind::SROA)) {
if (printedOptionSet)
Printer << " and ";
Printer << "Exploded";
return nullptr;
}
if (printedOptionSet)
return nullptr;
switch (FunctionSigSpecializationParamKind(raw)) {
case FunctionSigSpecializationParamKind::BoxToValue:
Printer << "Value Promoted from Box";
return nullptr;
case FunctionSigSpecializationParamKind::BoxToStack:
Printer << "Stack Promoted from Box";
return nullptr;
case FunctionSigSpecializationParamKind::InOutToOut:
Printer << "InOut Converted to Out";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropFunction:
Printer << "Constant Propagated Function";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropGlobal:
Printer << "Constant Propagated Global";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropInteger:
Printer << "Constant Propagated Integer";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropFloat:
Printer << "Constant Propagated Float";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropString:
Printer << "Constant Propagated String";
return nullptr;
case FunctionSigSpecializationParamKind::ConstantPropKeyPath:
Printer << "Constant Propagated KeyPath";
return nullptr;
case FunctionSigSpecializationParamKind::ClosureProp:
Printer << "Closure Propagated";
return nullptr;
case FunctionSigSpecializationParamKind::ExistentialToGeneric:
case FunctionSigSpecializationParamKind::Dead:
case FunctionSigSpecializationParamKind::OwnedToGuaranteed:
case FunctionSigSpecializationParamKind::GuaranteedToOwned:
case FunctionSigSpecializationParamKind::SROA:
printer_unreachable("option sets should have been handled earlier");
}
return nullptr;
}
case Node::Kind::SpecializationPassID:
Printer << Node->getIndex();
return nullptr;
case Node::Kind::BuiltinTypeName:
Printer << Node->getText();
return nullptr;
case Node::Kind::BuiltinTupleType:
Printer << "Builtin.TheTupleType";
return nullptr;
case Node::Kind::BuiltinFixedArray:
Printer << "Builtin.FixedArray<";
print(Node->getChild(0), depth + 1);
Printer << ", ";
print(Node->getChild(1), depth + 1);
Printer << ">";
return nullptr;
case Node::Kind::Number:
Printer << Node->getIndex();
return nullptr;
case Node::Kind::InfixOperator:
Printer << Node->getText() << " infix";
return nullptr;
case Node::Kind::PrefixOperator:
Printer << Node->getText() << " prefix";
return nullptr;
case Node::Kind::PostfixOperator:
Printer << Node->getText() << " postfix";
return nullptr;
case Node::Kind::LazyProtocolWitnessTableAccessor:
Printer << "lazy protocol witness table accessor for type ";
print(Node->getChild(0), depth + 1);
Printer << " and conformance ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::LazyProtocolWitnessTableCacheVariable:
Printer << "lazy protocol witness table cache variable for type ";
print(Node->getChild(0), depth + 1);
Printer << " and conformance ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::ProtocolSelfConformanceWitnessTable:
Printer << "protocol self-conformance witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::ProtocolWitnessTableAccessor:
Printer << "protocol witness table accessor for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::ProtocolWitnessTable:
Printer << "protocol witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::ProtocolWitnessTablePattern:
Printer << "protocol witness table pattern for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::GenericProtocolWitnessTable:
Printer << "generic protocol witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
Printer << "instantiation function for generic protocol witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::ResilientProtocolWitnessTable:
Printer << "resilient protocol witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::VTableThunk: {
Printer << "vtable thunk for ";
print(Node->getChild(1), depth + 1);
Printer << " dispatching to ";
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::ProtocolSelfConformanceWitness: {
Printer << "protocol self-conformance witness for ";
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::ProtocolWitness: {
Printer << "protocol witness for ";
print(Node->getChild(1), depth + 1);
Printer << " in conformance ";
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::PartialApplyForwarder:
if (Options.ShortenPartialApply)
Printer << "partial apply";
else
Printer << "partial apply forwarder";
if (Node->hasChildren()) {
Printer << " for ";
printChildren(Node, depth);
}
return nullptr;
case Node::Kind::PartialApplyObjCForwarder:
if (Options.ShortenPartialApply)
Printer << "partial apply";
else
Printer << "partial apply ObjC forwarder";
if (Node->hasChildren()) {
Printer << " for ";
printChildren(Node, depth);
}
return nullptr;
case Node::Kind::KeyPathGetterThunkHelper:
case Node::Kind::KeyPathSetterThunkHelper:
case Node::Kind::KeyPathUnappliedMethodThunkHelper:
case Node::Kind::KeyPathAppliedMethodThunkHelper:
if (Node->getKind() == Node::Kind::KeyPathGetterThunkHelper)
Printer << "key path getter for ";
else if (Node->getKind() == Node::Kind::KeyPathSetterThunkHelper)
Printer << "key path setter for ";
else if (Node->getKind() == Node::Kind::KeyPathUnappliedMethodThunkHelper)
Printer << "key path unapplied method ";
else if (Node->getKind() == Node::Kind::KeyPathAppliedMethodThunkHelper)
Printer << "key path applied method ";
print(Node->getChild(0), depth + 1);
Printer << " : ";
for (unsigned index = 1; index < Node->getNumChildren(); ++index) {
auto Child = Node->getChild(index);
if (Child->getKind() == Node::Kind::IsSerialized)
Printer << ", ";
print(Child, depth + 1);
}
return nullptr;
case Node::Kind::KeyPathEqualsThunkHelper:
case Node::Kind::KeyPathHashThunkHelper: {
Printer << "key path index "
<< (Node->getKind() == Node::Kind::KeyPathEqualsThunkHelper
? "equality" : "hash")
<< " operator for ";
unsigned lastChildIndex = Node->getNumChildren();
auto lastChild = Node->getChild(lastChildIndex - 1);
if (lastChild->getKind() == Node::Kind::IsSerialized) {
--lastChildIndex;
lastChild = Node->getChild(lastChildIndex - 1);
}
if (lastChild->getKind() == Node::Kind::DependentGenericSignature) {
print(lastChild, depth + 1);
--lastChildIndex;
}
Printer << "(";
for (unsigned i = 0; i < lastChildIndex; ++i) {
if (i != 0)
Printer << ", ";
print(Node->getChild(i), depth + 1);
}
Printer << ")";
return nullptr;
}
case Node::Kind::FieldOffset: {
print(Node->getChild(0), depth + 1); // directness
Printer << "field offset for ";
auto entity = Node->getChild(1);
print(entity, depth + 1, /*asContext*/ false);
return nullptr;
}
case Node::Kind::EnumCase: {
Printer << "enum case for ";
auto entity = Node->getChild(0);
print(entity, depth + 1, /*asContext*/ false);
return nullptr;
}
case Node::Kind::ReabstractionThunk:
case Node::Kind::ReabstractionThunkHelper: {
if (Options.ShortenThunk) {
Printer << "thunk for ";
print(Node->getChild(Node->getNumChildren() - 1), depth + 1);
return nullptr;
}
Printer << "reabstraction thunk ";
if (Node->getKind() == Node::Kind::ReabstractionThunkHelper)
Printer << "helper ";
unsigned idx = 0;
if (Node->getNumChildren() == 3) {
auto generics = Node->getChild(0);
idx = 1;
print(generics, depth + 1);
Printer << " ";
}
Printer << "from ";
print(Node->getChild(idx + 1), depth + 1);
Printer << " to ";
print(Node->getChild(idx), depth + 1);
return nullptr;
}
case Node::Kind::ReabstractionThunkHelperWithGlobalActor: {
print(Node->getChild(0), depth + 1);
Printer << " with global actor constraint ";
print(Node->getChild(1), depth + 1);
return nullptr;
}
case Node::Kind::ReabstractionThunkHelperWithSelf: {
Printer << "reabstraction thunk ";
unsigned idx = 0;
if (Node->getNumChildren() == 4) {
auto generics = Node->getChild(0);
idx = 1;
print(generics, depth + 1);
Printer << " ";
}
Printer << "from ";
print(Node->getChild(idx + 2), depth + 1);
Printer << " to ";
print(Node->getChild(idx + 1), depth + 1);
Printer << " self ";
print(Node->getChild(idx), depth + 1);
return nullptr;
}
case Node::Kind::AutoDiffFunction:
case Node::Kind::AutoDiffDerivativeVTableThunk: {
unsigned prefixEndIndex = 0;
while (prefixEndIndex != Node->getNumChildren() &&
Node->getChild(prefixEndIndex)->getKind()
!= Node::Kind::AutoDiffFunctionKind)
++prefixEndIndex;
auto funcKind = Node->getChild(prefixEndIndex);
auto paramIndices = Node->getChild(prefixEndIndex + 1);
auto resultIndices = Node->getChild(prefixEndIndex + 2);
if (kind == Node::Kind::AutoDiffDerivativeVTableThunk)
Printer << "vtable thunk for ";
print(funcKind, depth + 1);
Printer << " of ";
NodePointer optionalGenSig = nullptr;
for (unsigned i = 0; i < prefixEndIndex; ++i) {
// The last node may be a generic signature. If so, print it later.
if (i == prefixEndIndex - 1 &&
Node->getChild(i)->getKind()
== Node::Kind::DependentGenericSignature) {
optionalGenSig = Node->getChild(i);
break;
}
print(Node->getChild(i), depth + 1);
}
if (Options.ShortenThunk)
return nullptr;
Printer << " with respect to parameters ";
print(paramIndices, depth + 1);
Printer << " and results ";
print(resultIndices, depth + 1);
if (optionalGenSig && Options.DisplayWhereClauses) {
Printer << " with ";
print(optionalGenSig, depth + 1);
}
return nullptr;
}
case Node::Kind::AutoDiffSelfReorderingReabstractionThunk: {
Printer << "autodiff self-reordering reabstraction thunk ";
auto childIt = Node->begin();
auto fromType = *childIt++;
auto toType = *childIt++;
if (Options.ShortenThunk) {
Printer << "for ";
print(fromType, depth + 1);
return nullptr;
}
NodePointer optionalGenSig =
(*childIt)->getKind() == Node::Kind::DependentGenericSignature
? *childIt++ : nullptr;
Printer << "for ";
print(*childIt++, depth + 1); // kind
if (optionalGenSig) {
print(optionalGenSig, depth + 1);
Printer << ' ';
}
Printer << " from ";
print(fromType, depth + 1);
Printer << " to ";
print(toType, depth + 1);
return nullptr;
}
case Node::Kind::AutoDiffSubsetParametersThunk: {
Printer << "autodiff subset parameters thunk for ";
auto currentIndex = Node->getNumChildren() - 1;
auto toParamIndices = Node->getChild(currentIndex--);
auto resultIndices = Node->getChild(currentIndex--);
auto paramIndices = Node->getChild(currentIndex--);
auto kind = Node->getChild(currentIndex--);
print(kind, depth + 1);
Printer << " from ";
// Print the "from" thing.
if (currentIndex == 0) {
print(Node->getFirstChild(), depth + 1); // the "from" type
} else {
for (unsigned i = 0; i < currentIndex; ++i) // the "from" global
print(Node->getChild(i), depth + 1);
}
if (Options.ShortenThunk)
return nullptr;
Printer << " with respect to parameters ";
print(paramIndices, depth + 1);
Printer << " and results ";
print(resultIndices, depth + 1);
Printer << " to parameters ";
print(toParamIndices, depth + 1);
if (currentIndex > 0) {
Printer << " of type ";
print(Node->getChild(currentIndex), depth + 1); // "to" type
}
return nullptr;
}
case Node::Kind::AutoDiffFunctionKind: {
auto kind = (AutoDiffFunctionKind)Node->getIndex();
switch (kind) {
case AutoDiffFunctionKind::JVP:
Printer << "forward-mode derivative";
break;
case AutoDiffFunctionKind::VJP:
Printer << "reverse-mode derivative";
break;
case AutoDiffFunctionKind::Differential:
Printer << "differential";
break;
case AutoDiffFunctionKind::Pullback:
Printer << "pullback";
break;
}
return nullptr;
}
case Node::Kind::DifferentiabilityWitness: {
auto kindNodeIndex = Node->getNumChildren() - (
Node->getLastChild()->getKind() == Node::Kind::DependentGenericSignature
? 4 : 3);
auto kind =
(MangledDifferentiabilityKind)Node->getChild(kindNodeIndex)->getIndex();
switch (kind) {
case MangledDifferentiabilityKind::Forward:
Printer << "forward-mode";
break;
case MangledDifferentiabilityKind::Reverse:
Printer << "reverse-mode";
break;
case MangledDifferentiabilityKind::Normal:
Printer << "normal";
break;
case MangledDifferentiabilityKind::Linear:
Printer << "linear";
break;
case MangledDifferentiabilityKind::NonDifferentiable:
assert(false && "Impossible case");
}
Printer << " differentiability witness for ";
unsigned idx = 0;
for (auto numChildren = Node->getNumChildren();
idx < numChildren &&
Node->getChild(idx)->getKind() != Node::Kind::Index; ++idx)
print(Node->getChild(idx), depth + 1);
++idx; // kind (handled earlier)
Printer << " with respect to parameters ";
print(Node->getChild(idx++), depth + 1); // parameter indices
Printer << " and results ";
print(Node->getChild(idx++), depth + 1);
if (idx < Node->getNumChildren()) {
auto *genSig = Node->getChild(idx);
assert(genSig->getKind() == Node::Kind::DependentGenericSignature);
Printer << " with ";
print(genSig, depth + 1);
}
return nullptr;
}
case Node::Kind::IndexSubset: {
Printer << '{';
auto text = Node->getText();
bool printedAnyIndex = false;
for (unsigned i = 0, n = text.size(); i < n; ++i) {
if (text[i] != 'S') {
assert(text[i] == 'U');
continue;
}
if (printedAnyIndex)
Printer << ", ";
Printer << i;
printedAnyIndex = true;
}
Printer << '}';
return nullptr;
}
case Node::Kind::MergedFunction:
if (!Options.ShortenThunk) {
Printer << "merged ";
}
return nullptr;
case Node::Kind::TypeSymbolicReference:
Printer << "type symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
Printer << "opaque type symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::DistributedThunk:
if (!Options.ShortenThunk) {
Printer << "distributed thunk ";
}
return nullptr;
case Node::Kind::DistributedAccessor:
if (!Options.ShortenThunk) {
Printer << "distributed accessor for ";
}
return nullptr;
case Node::Kind::AccessibleFunctionRecord:
if (!Options.ShortenThunk) {
Printer << "accessible function runtime record for ";
}
return nullptr;
case Node::Kind::DynamicallyReplaceableFunctionKey:
if (!Options.ShortenThunk) {
Printer << "dynamically replaceable key for ";
}
return nullptr;
case Node::Kind::DynamicallyReplaceableFunctionImpl:
if (!Options.ShortenThunk) {
Printer << "dynamically replaceable thunk for ";
}
return nullptr;
case Node::Kind::DynamicallyReplaceableFunctionVar:
if (!Options.ShortenThunk) {
Printer << "dynamically replaceable variable for ";
}
return nullptr;
case Node::Kind::BackDeploymentThunk:
if (!Options.ShortenThunk) {
Printer << "back deployment thunk for ";
}
return nullptr;
case Node::Kind::BackDeploymentFallback:
Printer << "back deployment fallback for ";
return nullptr;
case Node::Kind::ProtocolSymbolicReference:
Printer << "protocol symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::GenericTypeMetadataPattern:
Printer << "generic type metadata pattern for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::Metaclass:
Printer << "metaclass for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::ProtocolSelfConformanceDescriptor:
Printer << "protocol self-conformance descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ProtocolConformanceDescriptor:
Printer << "protocol conformance descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ProtocolConformanceDescriptorRecord:
Printer << "protocol conformance descriptor runtime record for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ProtocolDescriptor:
Printer << "protocol descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ProtocolDescriptorRecord:
Printer << "protocol descriptor runtime record for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ProtocolRequirementsBaseDescriptor:
Printer << "protocol requirements base descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::FullTypeMetadata:
Printer << "full type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadata:
Printer << "type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataAccessFunction:
Printer << "type metadata accessor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataInstantiationCache:
Printer << "type metadata instantiation cache for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataInstantiationFunction:
Printer << "type metadata instantiation function for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataSingletonInitializationCache:
Printer << "type metadata singleton initialization cache for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataCompletionFunction:
Printer << "type metadata completion function for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataDemanglingCache:
Printer << "demangling cache variable for type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::TypeMetadataLazyCache:
Printer << "lazy cache variable for type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AssociatedConformanceDescriptor:
Printer << "associated conformance descriptor for ";
print(Node->getChild(0), depth + 1);
Printer << ".";
print(Node->getChild(1), depth + 1);
Printer << ": ";
print(Node->getChild(2), depth + 1);
return nullptr;
case Node::Kind::DefaultAssociatedConformanceAccessor:
Printer << "default associated conformance accessor for ";
print(Node->getChild(0), depth + 1);
Printer << ".";
print(Node->getChild(1), depth + 1);
Printer << ": ";
print(Node->getChild(2), depth + 1);
return nullptr;
case Node::Kind::AssociatedTypeDescriptor:
Printer << "associated type descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AssociatedTypeMetadataAccessor:
Printer << "associated type metadata accessor for ";
print(Node->getChild(1), depth + 1);
Printer << " in ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::BaseConformanceDescriptor:
Printer << "base conformance descriptor for ";
print(Node->getChild(0), depth + 1);
Printer << ": ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
Printer << "default associated type metadata accessor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AssociatedTypeWitnessTableAccessor:
Printer << "associated type witness table accessor for ";
print(Node->getChild(1), depth + 1);
Printer << " : ";
print(Node->getChild(2), depth + 1);
Printer << " in ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::BaseWitnessTableAccessor:
Printer << "base witness table accessor for ";
print(Node->getChild(1), depth + 1);
Printer << " in ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ClassMetadataBaseOffset:
Printer << "class metadata base offset for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::PropertyDescriptor:
Printer << "property descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NominalTypeDescriptor:
Printer << "nominal type descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NominalTypeDescriptorRecord:
Printer << "nominal type descriptor runtime record for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptor:
Printer << "opaque type descriptor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptorRecord:
Printer << "opaque type descriptor runtime record for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptorAccessor:
Printer << "opaque type descriptor accessor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptorAccessorImpl:
Printer << "opaque type descriptor accessor impl for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptorAccessorKey:
Printer << "opaque type descriptor accessor key for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::OpaqueTypeDescriptorAccessorVar:
Printer << "opaque type descriptor accessor var for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::CoroutineContinuationPrototype:
Printer << "coroutine continuation prototype for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ValueWitness:
Printer << toString(ValueWitnessKind(Node->getFirstChild()->getIndex()));
if (Options.ShortenValueWitness) Printer << " for ";
else Printer << " value witness for ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::ValueWitnessTable:
Printer << "value witness table for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericProtocol:
case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericTypeAlias:
printBoundGeneric(Node, depth);
return nullptr;
case Node::Kind::DynamicSelf:
Printer << "Self";
return nullptr;
case Node::Kind::SILBoxType: {
Printer << "@box ";
NodePointer type = Node->getChild(0);
print(type, depth + 1);
return nullptr;
}
case Node::Kind::Metatype: {
unsigned Idx = 0;
if (Node->getNumChildren() == 2) {
NodePointer repr = Node->getChild(Idx);
print(repr, depth + 1);
Printer << " ";
++Idx;
}
NodePointer type = Node->getChild(Idx)->getChild(0);
printWithParens(type, depth);
if (isExistentialType(type)) {
Printer << ".Protocol";
} else {
Printer << ".Type";
}
return nullptr;
}
case Node::Kind::ConstrainedExistential: {
Printer << "any ";
print(Node->getChild(0), depth + 1);
Printer << "<";
print(Node->getChild(1), depth + 1);
Printer << ">";
return nullptr;
}
case Node::Kind::ConstrainedExistentialRequirementList: {
printChildren(Node, depth, ", ");
return nullptr;
}
case Node::Kind::ExistentialMetatype: {
unsigned Idx = 0;
if (Node->getNumChildren() == 2) {
NodePointer repr = Node->getChild(Idx);
print(repr, depth + 1);
Printer << " ";
++Idx;
}
NodePointer type = Node->getChild(Idx);
print(type, depth + 1);
Printer << ".Type";
return nullptr;
}
case Node::Kind::ConstrainedExistentialSelf:
Printer << "Self";
return nullptr;
case Node::Kind::MetatypeRepresentation: {
Printer << Node->getText();
return nullptr;
}
case Node::Kind::AssociatedTypeRef:
print(Node->getChild(0), depth + 1);
Printer << '.' << Node->getChild(1)->getText();
return nullptr;
case Node::Kind::ProtocolList: {
NodePointer type_list = Node->getChild(0);
if (!type_list)
return nullptr;
if (type_list->getNumChildren() == 0)
Printer << "Any";
else
printChildren(type_list, depth, " & ");
return nullptr;
}
case Node::Kind::ProtocolListWithClass: {
if (Node->getNumChildren() < 2)
return nullptr;
NodePointer protocols = Node->getChild(0);
NodePointer superclass = Node->getChild(1);
print(superclass, depth + 1);
Printer << " & ";
if (protocols->getNumChildren() < 1)
return nullptr;
NodePointer type_list = protocols->getChild(0);
printChildren(type_list, depth, " & ");
return nullptr;
}
case Node::Kind::ProtocolListWithAnyObject: {
if (Node->getNumChildren() < 1)
return nullptr;
NodePointer protocols = Node->getChild(0);
if (protocols->getNumChildren() < 1)
return nullptr;
NodePointer type_list = protocols->getChild(0);
if (type_list->getNumChildren() > 0) {
printChildren(type_list, depth, " & ");
Printer << " & ";
}
if (Options.QualifyEntities && Options.DisplayStdlibModule)
Printer << swift::STDLIB_NAME << ".";
Printer << "AnyObject";
return nullptr;
}
case Node::Kind::AssociatedType:
// Don't print for now.
return nullptr;
case Node::Kind::OwningAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"owningAddressor");
case Node::Kind::OwningMutableAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"owningMutableAddressor");
case Node::Kind::NativeOwningAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"nativeOwningAddressor");
case Node::Kind::NativeOwningMutableAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"nativeOwningMutableAddressor");
case Node::Kind::NativePinningAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"nativePinningAddressor");
case Node::Kind::NativePinningMutableAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"nativePinningMutableAddressor");
case Node::Kind::UnsafeAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"unsafeAddressor");
case Node::Kind::UnsafeMutableAddressor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"unsafeMutableAddressor");
case Node::Kind::GlobalGetter:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"getter");
case Node::Kind::Getter:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"getter");
case Node::Kind::Setter:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"setter");
case Node::Kind::MaterializeForSet:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"materializeForSet");
case Node::Kind::WillSet:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"willset");
case Node::Kind::DidSet:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"didset");
case Node::Kind::ReadAccessor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"read");
case Node::Kind::Read2Accessor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"read2");
case Node::Kind::ModifyAccessor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"modify");
case Node::Kind::Modify2Accessor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"modify2");
case Node::Kind::InitAccessor:
return printAbstractStorage(Node->getFirstChild(), depth, asPrefixContext,
"init");
case Node::Kind::Allocator:
return printEntity(
Node, depth, asPrefixContext, TypePrinting::FunctionStyle,
/*hasName*/ false,
isClassType(Node->getChild(0)) ? "__allocating_init" : "init");
case Node::Kind::Constructor:
return printEntity(Node, depth, asPrefixContext,
TypePrinting::FunctionStyle,
/*hasName*/ Node->getNumChildren() > 2, "init");
case Node::Kind::Destructor:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false, "deinit");
case Node::Kind::Deallocator:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false,
isClassType(Node->getChild(0)) ? "__deallocating_deinit"
: "deinit");
case Node::Kind::IsolatedDeallocator:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false,
isClassType(Node->getChild(0))
? "__isolated_deallocating_deinit"
: "deinit");
case Node::Kind::IVarInitializer:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false, "__ivar_initializer");
case Node::Kind::IVarDestroyer:
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
/*hasName*/ false, "__ivar_destroyer");
case Node::Kind::ProtocolConformance: {
NodePointer child0 = Node->getChild(0);
NodePointer child1 = Node->getChild(1);
NodePointer child2 = Node->getChild(2);
if (Node->getNumChildren() == 4) {
// TODO: check if this is correct
Printer << "property behavior storage of ";
print(child2, depth + 1);
Printer << " in ";
print(child0, depth + 1);
Printer << " : ";
print(child1, depth + 1);
} else {
print(child0, depth + 1);
if (Options.DisplayProtocolConformances) {
Printer << " : ";
print(child1, depth + 1);
Printer << " in ";
print(child2, depth + 1);
}
}
return nullptr;
}
case Node::Kind::TypeList:
printChildren(Node, depth);
return nullptr;
case Node::Kind::LabelList:
return nullptr;
case Node::Kind::ImplDifferentiabilityKind:
Printer << "@differentiable";
switch ((MangledDifferentiabilityKind)Node->getIndex()) {
case MangledDifferentiabilityKind::Normal:
break;
case MangledDifferentiabilityKind::Linear:
Printer << "(_linear)";
break;
case MangledDifferentiabilityKind::Forward:
Printer << "(_forward)";
break;
case MangledDifferentiabilityKind::Reverse:
Printer << "(reverse)";
break;
case MangledDifferentiabilityKind::NonDifferentiable:
assert(false && "Impossible case 'NonDifferentiable'");
}
return nullptr;
case Node::Kind::ImplEscaping:
Printer << "@escaping";
return nullptr;
case Node::Kind::ImplErasedIsolation:
Printer << "@isolated(any)";
return nullptr;
case Node::Kind::ImplCoroutineKind:
// Skip if text is empty.
if (Node->getText().empty())
return nullptr;
// Otherwise, print with leading @.
Printer << '@' << Node->getText();
return nullptr;
case Node::Kind::ImplSendingResult:
Printer << "sending";
return nullptr;
case Node::Kind::ImplConvention:
Printer << Node->getText();
return nullptr;
case Node::Kind::ImplParameterResultDifferentiability:
// Skip if text is empty.
if (Node->getText().empty())
return nullptr;
// Otherwise, print with trailing space.
Printer << Node->getText() << ' ';
return nullptr;
case Node::Kind::ImplParameterSending:
case Node::Kind::ImplParameterIsolated:
case Node::Kind::ImplParameterImplicitLeading:
// Skip if text is empty.
if (Node->getText().empty())
return nullptr;
// Otherwise, print with trailing space.
Printer << Node->getText() << ' ';
return nullptr;
case Node::Kind::ImplFunctionAttribute:
Printer << Node->getText();
return nullptr;
case Node::Kind::ImplFunctionConvention:
Printer << "@convention(";
switch (Node->getNumChildren()) {
case 1:
Printer << Node->getChild(0)->getText();
break;
case 2:
Printer << Node->getChild(0)->getText() << ", mangledCType: \"";
print(Node->getChild(1), depth + 1);
Printer << '"';
break;
default:
assert(false && "Unexpected numChildren for ImplFunctionConvention");
}
Printer << ')';
return nullptr;
case Node::Kind::ImplFunctionConventionName:
assert(false && "Already handled in ImplFunctionConvention");
return nullptr;
case Node::Kind::ImplErrorResult:
Printer << "@error ";
printChildren(Node, depth, " ");
return nullptr;
case Node::Kind::ImplYield:
Printer << "@yields ";
printChildren(Node, depth, " ");
return nullptr;
case Node::Kind::ImplParameter:
case Node::Kind::ImplResult:
// Children: `convention, differentiability?, type`
// Print convention.
print(Node->getChild(0), depth + 1);
Printer << " ";
// Print differentiability, if it exists.
if (Node->getNumChildren() == 3)
print(Node->getChild(1), depth + 1);
// Print differentiability and sending if it exists.
if (Node->getNumChildren() == 4) {
print(Node->getChild(1), depth + 1);
print(Node->getChild(2), depth + 1);
}
// Print type.
print(Node->getLastChild(), depth + 1);
return nullptr;
case Node::Kind::ImplFunctionType:
printImplFunctionType(Node, depth);
return nullptr;
case Node::Kind::ImplInvocationSubstitutions:
Printer << "for <";
printChildren(Node->getChild(0), depth, ", ");
Printer << '>';
return nullptr;
case Node::Kind::ImplPatternSubstitutions:
Printer << "@substituted ";
print(Node->getChild(0), depth + 1);
Printer << " for <";
printChildren(Node->getChild(1), depth, ", ");
Printer << '>';
return nullptr;
case Node::Kind::ErrorType:
Printer << "<ERROR TYPE>";
return nullptr;
case Node::Kind::DependentPseudogenericSignature:
case Node::Kind::DependentGenericSignature: {
printGenericSignature(Node, depth);
return nullptr;
}
case Node::Kind::DependentGenericParamCount:
case Node::Kind::DependentGenericParamPackMarker:
case Node::Kind::DependentGenericParamValueMarker:
printer_unreachable("should be printed as a child of a "
"DependentGenericSignature");
case Node::Kind::DependentGenericConformanceRequirement: {
NodePointer type = Node->getChild(0);
NodePointer reqt = Node->getChild(1);
print(type, depth + 1);
Printer << ": ";
print(reqt, depth + 1);
return nullptr;
}
case Node::Kind::DependentGenericInverseConformanceRequirement: {
NodePointer type = Node->getChild(0);
print(type, depth + 1);
Printer << ": ~";
switch (Node->getChild(1)->getIndex()) {
#define INVERTIBLE_PROTOCOL(Name, Bit) \
case Bit: Printer << "Swift." << #Name; break;
#include "swift/ABI/InvertibleProtocols.def"
default:
Printer << "Swift.<bit " << Node->getChild(1)->getIndex() << ">";
break;
}
return nullptr;
}
case Node::Kind::DependentGenericLayoutRequirement: {
NodePointer type = Node->getChild(0);
NodePointer layout = Node->getChild(1);
print(type, depth + 1);
Printer << ": ";
assert(layout->getKind() == Node::Kind::Identifier);
assert(layout->getText().size() == 1);
char c = layout->getText()[0];
StringRef name;
if (c == 'U') {
name = "_UnknownLayout";
} else if (c == 'R') {
name = "_RefCountedObject";
} else if (c == 'N') {
name = "_NativeRefCountedObject";
} else if (c == 'C') {
name = "AnyObject";
} else if (c == 'D') {
name = "_NativeClass";
} else if (c == 'T') {
name = "_Trivial";
} else if (c == 'E' || c == 'e') {
name = "_Trivial";
} else if (c == 'M' || c == 'm') {
name = "_TrivialAtMost";
}
Printer << name;
if (Node->getNumChildren() > 2) {
Printer << "(";
print(Node->getChild(2), depth + 1);
if (Node->getNumChildren() > 3) {
Printer << ", ";
print(Node->getChild(3), depth + 1);
}
Printer << ")";
}
return nullptr;
}
case Node::Kind::DependentGenericSameTypeRequirement: {
NodePointer fst = Node->getChild(0);
NodePointer snd = Node->getChild(1);
print(fst, depth + 1);
Printer << " == ";
print(snd, depth + 1);
return nullptr;
}
case Node::Kind::DependentGenericSameShapeRequirement: {
NodePointer fst = Node->getChild(0);
NodePointer snd = Node->getChild(1);
print(fst, depth + 1);
Printer << ".shape == ";
print(snd, depth + 1);
Printer << ".shape";
return nullptr;
}
case Node::Kind::DependentGenericParamType: {
unsigned index = Node->getChild(1)->getIndex();
unsigned depth = Node->getChild(0)->getIndex();
Printer << Options.GenericParameterName(depth, index);
return nullptr;
}
case Node::Kind::DependentGenericType: {
NodePointer sig = Node->getChild(0);
NodePointer depTy = Node->getChild(1);
print(sig, depth + 1);
if (needSpaceBeforeType(depTy))
Printer << ' ';
print(depTy, depth + 1);
return nullptr;
}
case Node::Kind::DependentMemberType: {
NodePointer base = Node->getChild(0);
print(base, depth + 1);
Printer << '.';
NodePointer assocTy = Node->getChild(1);
print(assocTy, depth + 1);
return nullptr;
}
case Node::Kind::DependentAssociatedTypeRef: {
if (Node->getNumChildren() > 1) {
print(Node->getChild(1), depth + 1);
Printer << '.';
}
print(Node->getChild(0), depth + 1);
return nullptr;
}
case Node::Kind::ReflectionMetadataBuiltinDescriptor:
Printer << "reflection metadata builtin descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ReflectionMetadataFieldDescriptor:
Printer << "reflection metadata field descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ReflectionMetadataAssocTypeDescriptor:
Printer << "reflection metadata associated type descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ReflectionMetadataSuperclassDescriptor:
Printer << "reflection metadata superclass descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ConcurrentFunctionType:
Printer << "@Sendable ";
return nullptr;
case Node::Kind::DifferentiableFunctionType: {
Printer << "@differentiable";
auto kind = (MangledDifferentiabilityKind)Node->getIndex();
switch (kind) {
case MangledDifferentiabilityKind::Forward:
Printer << "(_forward)";
break;
case MangledDifferentiabilityKind::Reverse:
Printer << "(reverse)";
break;
case MangledDifferentiabilityKind::Linear:
Printer << "(_linear)";
break;
case MangledDifferentiabilityKind::Normal:
break;
case MangledDifferentiabilityKind::NonDifferentiable:
assert(false && "Unexpected case NonDifferentiable");
}
Printer << ' ';
return nullptr;
}
case Node::Kind::GlobalActorFunctionType: {
if (Node->getNumChildren() > 0) {
Printer << '@';
print(Node->getChild(0), depth + 1);
Printer << ' ';
}
return nullptr;
}
case Node::Kind::IsolatedAnyFunctionType:
Printer << "@isolated(any) ";
return nullptr;
case Node::Kind::NonIsolatedCallerFunctionType:
Printer << "nonisolated(nonsending) ";
return nullptr;
case Node::Kind::SendingResultFunctionType:
Printer << "sending ";
return nullptr;
case Node::Kind::AsyncAnnotation:
Printer << " async";
return nullptr;
case Node::Kind::ThrowsAnnotation:
Printer << " throws";
return nullptr;
case Node::Kind::TypedThrowsAnnotation:
Printer << " throws(";
if (Node->getNumChildren() == 1)
print(Node->getChild(0), depth + 1);
Printer << ")";
return nullptr;
case Node::Kind::EmptyList:
Printer << " empty-list ";
return nullptr;
case Node::Kind::FirstElementMarker:
Printer << " first-element-marker ";
return nullptr;
case Node::Kind::VariadicMarker:
Printer << " variadic-marker ";
return nullptr;
case Node::Kind::SILBoxTypeWithLayout: {
assert(Node->getNumChildren() == 1 || Node->getNumChildren() == 3);
NodePointer layout = Node->getChild(0);
assert(layout->getKind() == Node::Kind::SILBoxLayout);
NodePointer signature, genericArgs = nullptr;
if (Node->getNumChildren() == 3) {
signature = Node->getChild(1);
assert(signature->getKind() == Node::Kind::DependentGenericSignature);
genericArgs = Node->getChild(2);
assert(genericArgs->getKind() == Node::Kind::TypeList);
print(signature, depth + 1);
Printer << ' ';
}
print(layout, depth + 1);
if (genericArgs) {
Printer << " <";
for (unsigned i = 0, e = genericArgs->getNumChildren(); i < e; ++i) {
if (i > 0)
Printer << ", ";
print(genericArgs->getChild(i), depth + 1);
}
Printer << '>';
}
return nullptr;
}
case Node::Kind::SILBoxLayout:
Printer << '{';
for (unsigned i = 0; i < Node->getNumChildren(); ++i) {
if (i > 0)
Printer << ',';
Printer << ' ';
print(Node->getChild(i), depth + 1);
}
Printer << " }";
return nullptr;
case Node::Kind::SILBoxImmutableField:
case Node::Kind::SILBoxMutableField:
Printer << (Node->getKind() == Node::Kind::SILBoxImmutableField
? "let "
: "var ");
assert(Node->getNumChildren() == 1
&& Node->getChild(0)->getKind() == Node::Kind::Type);
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AssocTypePath:
printChildren(Node->begin(), Node->end(), depth, ".");
return nullptr;
case Node::Kind::ModuleDescriptor:
Printer << "module descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AnonymousDescriptor:
Printer << "anonymous descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ExtensionDescriptor:
Printer << "extension descriptor ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AssociatedTypeGenericParamRef:
Printer << "generic parameter reference for associated type ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::AnyProtocolConformanceList:
if (Node->getNumChildren() > 0) {
Printer << "(";
for (unsigned i = 0; i < Node->getNumChildren(); ++i) {
if (i > 0)
Printer << ", ";
print(Node->getChild(i), depth + 1);
}
Printer << ")";
}
return nullptr;
case Node::Kind::ConcreteProtocolConformance:
Printer << "concrete protocol conformance ";
if (Node->hasIndex())
Printer << "#" << Node->getIndex() << " ";
print(Node->getChild(0), depth + 1);
Printer << " to ";
print(Node->getChild(1), depth + 1);
if (Node->getNumChildren() > 2 &&
Node->getChild(2)->getNumChildren() > 0) {
Printer << " with conditional requirements: ";
print(Node->getChild(2), depth + 1);
}
return nullptr;
case Node::Kind::PackProtocolConformance:
Printer << "pack protocol conformance ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::DependentAssociatedConformance:
Printer << "dependent associated conformance ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::DependentProtocolConformanceAssociated:
Printer << "dependent associated protocol conformance ";
printOptionalIndex(Node->getChild(2));
print(Node->getChild(0), depth + 1);
Printer << " to ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::DependentProtocolConformanceInherited:
Printer << "dependent inherited protocol conformance ";
printOptionalIndex(Node->getChild(2));
print(Node->getChild(0), depth + 1);
Printer << " to ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::DependentProtocolConformanceRoot:
Printer << "dependent root protocol conformance ";
printOptionalIndex(Node->getChild(2));
print(Node->getChild(0), depth + 1);
Printer << " to ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::DependentProtocolConformanceOpaque:
Printer << "opaque result conformance ";
print(Node->getChild(0), depth + 1);
Printer << " of ";
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::ProtocolConformanceRefInTypeModule:
Printer << "protocol conformance ref (type's module) ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::ProtocolConformanceRefInProtocolModule:
Printer << "protocol conformance ref (protocol's module) ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::ProtocolConformanceRefInOtherModule:
Printer << "protocol conformance ref (retroactive) ";
printChildren(Node, depth);
return nullptr;
case Node::Kind::SugaredOptional:
printWithParens(Node->getChild(0), depth);
Printer << "?";
return nullptr;
case Node::Kind::SugaredArray:
Printer << "[";
print(Node->getChild(0), depth + 1);
Printer << "]";
return nullptr;
case Node::Kind::SugaredInlineArray: {
Printer << "[";
print(Node->getChild(0), depth + 1);
Printer << " of ";
print(Node->getChild(1), depth + 1);
Printer << "]";
return nullptr;
}
case Node::Kind::SugaredDictionary:
Printer << "[";
print(Node->getChild(0), depth + 1);
Printer << " : ";
print(Node->getChild(1), depth + 1);
Printer << "]";
return nullptr;
case Node::Kind::SugaredParen:
Printer << "(";
print(Node->getChild(0), depth + 1);
Printer << ")";
return nullptr;
case Node::Kind::OpaqueReturnType:
Printer << "some";
return nullptr;
case Node::Kind::OpaqueReturnTypeOf:
Printer << "<<opaque return type of ";
printChildren(Node, depth);
Printer << ">>";
return nullptr;
case Node::Kind::OpaqueType:
print(Node->getChild(0), depth + 1);
Printer << '.';
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::AccessorFunctionReference:
Printer << "accessor function at " << Node->getIndex();
return nullptr;
case Node::Kind::CanonicalSpecializedGenericMetaclass:
Printer << "specialized generic metaclass for ";
print(Node->getFirstChild(), depth + 1);
return nullptr;
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
Printer << "canonical specialized generic type metadata accessor for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::MetadataInstantiationCache:
Printer << "metadata instantiation cache for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadata:
Printer << "noncanonical specialized generic type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache:
Printer << "cache variable for noncanonical specialized generic type metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::GlobalVariableOnceToken:
case Node::Kind::GlobalVariableOnceFunction:
Printer << (kind == Node::Kind::GlobalVariableOnceToken
? "one-time initialization token for "
: "one-time initialization function for ");
printContext(Node->getChild(0));
print(Node->getChild(1), depth + 1);
return nullptr;
case Node::Kind::GlobalVariableOnceDeclList:
if (Node->getNumChildren() == 1) {
print(Node->getChild(0), depth + 1);
} else {
Printer << '(';
for (unsigned i = 0, e = Node->getNumChildren(); i < e; ++i) {
if (i != 0) {
Printer << ", ";
}
print(Node->getChild(i), depth + 1);
}
Printer << ')';
}
return nullptr;
case Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl:
Printer << "predefined ";
LLVM_FALLTHROUGH;
case Node::Kind::ObjCAsyncCompletionHandlerImpl:
Printer << "@objc completion handler block implementation for ";
if (Node->getNumChildren() >= 4)
print(Node->getChild(3), depth + 1);
print(Node->getChild(0), depth + 1);
Printer << " with result type ";
print(Node->getChild(1), depth + 1);
switch (Node->getChild(2)->getIndex()) {
case 0:
break;
case 1:
Printer << " nonzero on error";
break;
case 2:
Printer << " zero on error";
break;
default:
Printer << " <invalid error flag>";
break;
}
return nullptr;
case Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
Printer << "flag for loading of canonical specialized generic type "
"metadata for ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::AsyncFunctionPointer:
Printer << "async function pointer to ";
return nullptr;
case Node::Kind::AsyncAwaitResumePartialFunction:
if (Options.ShowAsyncResumePartial) {
Printer << "(";
print(Node->getChild(0), depth + 1);
Printer << ")";
Printer << " await resume partial function for ";
}
return nullptr;
case Node::Kind::AsyncSuspendResumePartialFunction:
if (Options.ShowAsyncResumePartial) {
Printer << "(";
print(Node->getChild(0), depth + 1);
Printer << ")";
Printer << " suspend resume partial function for ";
}
return nullptr;
case Node::Kind::Uniquable:
Printer << "uniquable ";
print(Node->getChild(0), depth + 1);
return nullptr;
case Node::Kind::ExtendedExistentialTypeShape: {
// Printing the requirement signature is pretty useless if we
// don't print `where` clauses.
auto savedDisplayWhereClauses = Options.DisplayWhereClauses;
Options.DisplayWhereClauses = true;
NodePointer genSig = nullptr, type = nullptr;
if (Node->getNumChildren() == 2) {
genSig = Node->getChild(1);
type = Node->getChild(2);
} else {
type = Node->getChild(1);
}
Printer << "existential shape for ";
if (genSig) {
print(genSig, depth + 1);
Printer << " ";
}
Printer << "any ";
print(type, depth + 1);
Options.DisplayWhereClauses = savedDisplayWhereClauses;
return nullptr;
}
case Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference:
Printer << "unique existential shape symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference:
Printer << "non-unique existential shape symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::ObjectiveCProtocolSymbolicReference:
Printer << "objective-c protocol symbolic reference 0x";
Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::SymbolicExtendedExistentialType: {
auto shape = Node->getChild(0);
bool isUnique =
(shape->getKind() ==
Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference);
Printer << "symbolic existential type ("
<< (isUnique ? "" : "non-")
<< "unique) 0x";
Printer.writeHex(shape->getIndex());
Printer << " <";
print(Node->getChild(1), depth + 1);
if (Node->getNumChildren() > 2) {
Printer << ", ";
print(Node->getChild(2), depth + 1);
}
Printer << ">";
return nullptr;
}
case Node::Kind::HasSymbolQuery:
Printer << "#_hasSymbol query for ";
return nullptr;
case Node::Kind::OpaqueReturnTypeIndex:
case Node::Kind::OpaqueReturnTypeParent:
return nullptr;
case Node::Kind::Integer:
Printer << Node->getIndex();
return nullptr;
case Node::Kind::NegativeInteger: {
intptr_t signedValue = Node->getIndex();
Printer << signedValue;
return nullptr;
}
case Node::Kind::CoroFunctionPointer:
Printer << "coro function pointer to ";
return nullptr;
case Node::Kind::DefaultOverride:
Printer << "default override of ";
return nullptr;
}
printer_unreachable("bad node kind!");
}
NodePointer NodePrinter::printAbstractStorage(NodePointer Node, unsigned depth,
bool asPrefixContent,
StringRef ExtraName) {
switch (Node->getKind()) {
case Node::Kind::Variable:
return printEntity(Node, depth, asPrefixContent, TypePrinting::WithColon,
/*hasName*/ true, ExtraName);
case Node::Kind::Subscript:
return printEntity(Node, depth, asPrefixContent, TypePrinting::WithColon,
/*hasName*/ false, ExtraName, /*ExtraIndex*/ -1,
"subscript");
default:
printer_unreachable("Not an abstract storage node");
}
}
NodePointer NodePrinter::printEntity(NodePointer Entity, unsigned depth,
bool asPrefixContext, TypePrinting TypePr,
bool hasName, StringRef ExtraName,
int ExtraIndex, StringRef OverwriteName) {
NodePointer genericFunctionTypeList = nullptr;
if (Entity->getKind() == Node::Kind::BoundGenericFunction) {
genericFunctionTypeList = Entity->getChild(1);
Entity = Entity->getFirstChild();
}
// Either we print the context in prefix form "<context>.<name>" or in
// suffix form "<name> in <context>".
bool MultiWordName = ExtraName.contains(' ');
// Also a local name (e.g. Mystruct #1) does not look good if its context is
// printed in prefix form.
bool LocalName =
hasName && Entity->getChild(1)->getKind() == Node::Kind::LocalDeclName;
if (LocalName && Options.DisplayLocalNameContexts)
MultiWordName = true;
if (asPrefixContext && (TypePr != TypePrinting::NoType || MultiWordName)) {
// If the context has a type to be printed, we can't use the prefix form.
return Entity;
}
NodePointer PostfixContext = nullptr;
NodePointer Context = Entity->getChild(0);
if (printContext(Context)) {
if (MultiWordName) {
// If the name contains some spaces we don't print the context now but
// later in suffix form.
PostfixContext = Context;
} else {
size_t CurrentPos = Printer.getStringRef().size();
PostfixContext = print(Context, depth + 1, /*asPrefixContext*/ true);
// Was the context printed as prefix?
if (Printer.getStringRef().size() != CurrentPos)
Printer << '.';
}
}
printFunctionName(hasName, OverwriteName, ExtraName, MultiWordName,
ExtraIndex, Entity, depth);
if (TypePr != TypePrinting::NoType) {
NodePointer type = getChildIf(Entity, Node::Kind::Type);
assert(type && "malformed entity");
if (!type) {
setInvalid();
return nullptr;
}
type = type->getChild(0);
if (TypePr == TypePrinting::FunctionStyle) {
// We expect to see a function type here, but if we don't, use the colon.
NodePointer t = type;
while (t->getKind() == Node::Kind::DependentGenericType)
t = t->getChild(1)->getChild(0);
if (t->getKind() != Node::Kind::FunctionType &&
t->getKind() != Node::Kind::NoEscapeFunctionType &&
t->getKind() != Node::Kind::UncurriedFunctionType &&
t->getKind() != Node::Kind::CFunctionPointer &&
t->getKind() != Node::Kind::ThinFunctionType) {
TypePr = TypePrinting::WithColon;
}
}
if (TypePr == TypePrinting::WithColon) {
if (Options.DisplayEntityTypes) {
Printer << " : ";
printEntityType(Entity, type, genericFunctionTypeList, depth);
}
} else if (shouldShowEntityType(Entity->getKind(), Options)) {
assert(TypePr == TypePrinting::FunctionStyle);
if (MultiWordName || needSpaceBeforeType(type))
Printer << ' ';
printEntityType(Entity, type, genericFunctionTypeList, depth);
}
}
if (!asPrefixContext && PostfixContext &&
(!LocalName || Options.DisplayLocalNameContexts)) {
// Print any left over context which couldn't be printed in prefix form.
if (Entity->getKind() == Node::Kind::DefaultArgumentInitializer ||
Entity->getKind() == Node::Kind::Initializer ||
Entity->getKind() == Node::Kind::PropertyWrapperBackingInitializer ||
Entity->getKind() == Node::Kind::PropertyWrapperInitFromProjectedValue) {
Printer << " of ";
} else {
Printer << " in ";
}
print(PostfixContext, depth + 1);
PostfixContext = nullptr;
}
return PostfixContext;
}
void NodePrinter::printFunctionName(bool hasName,
llvm::StringRef &OverwriteName,
llvm::StringRef &ExtraName,
bool MultiWordName, int &ExtraIndex,
swift::Demangle::NodePointer Entity,
unsigned int depth) {
if (hasName || !OverwriteName.empty()) {
if (!ExtraName.empty() && MultiWordName) {
Printer << ExtraName;
if (ExtraIndex >= 0)
Printer << ExtraIndex;
Printer << " of ";
ExtraName = "";
ExtraIndex = -1;
}
size_t CurrentPos = Printer.getStringRef().size();
if (!OverwriteName.empty()) {
Printer << OverwriteName;
} else {
auto Name = Entity->getChild(1);
if (Name->getKind() != Node::Kind::PrivateDeclName)
print(Name, depth + 1);
if (auto PrivateName = getChildIf(Entity, Node::Kind::PrivateDeclName))
print(PrivateName, depth + 1);
}
if (Printer.getStringRef().size() != CurrentPos && !ExtraName.empty())
Printer << '.';
}
if (!ExtraName.empty()) {
Printer << ExtraName;
if (ExtraIndex >= 0)
Printer << ExtraIndex;
}
}
void NodePrinter::printEntityType(NodePointer Entity, NodePointer type,
NodePointer genericFunctionTypeList,
unsigned depth) {
NodePointer labelList = getChildIf(Entity, Node::Kind::LabelList);
if (labelList || genericFunctionTypeList) {
if (genericFunctionTypeList) {
Printer << "<";
printChildren(genericFunctionTypeList, depth, ", ");
Printer << ">";
}
if (type->getKind() == Node::Kind::DependentGenericType) {
if (!genericFunctionTypeList)
print(type->getChild(0), depth + 1); // generic signature
auto dependentType = type->getChild(1);
if (needSpaceBeforeType(dependentType))
Printer << ' ';
type = dependentType->getFirstChild();
}
printFunctionType(labelList, type, depth);
} else {
print(type, depth + 1);
}
}
NodePointer
matchSequenceOfKinds(NodePointer start,
std::vector<std::tuple<Node::Kind, size_t>> pattern) {
if (start != nullptr) {
NodePointer current = start;
size_t idx = 0;
while (idx < pattern.size()) {
std::tuple<Node::Kind, size_t> next = pattern[idx];
idx += 1;
NodePointer nextChild = current->getChild(std::get<1>(next));
if (nextChild != nullptr && nextChild->getKind() == std::get<0>(next)) {
current = nextChild;
} else {
return nullptr;
}
}
if (idx == pattern.size()) {
return current;
} else {
return nullptr;
}
} else {
return nullptr;
}
}
std::string Demangle::keyPathSourceString(const char *MangledName,
size_t MangledNameLength) {
std::string invalid = "";
std::string unlabelledArg = "_: ";
Context ctx;
NodePointer root =
ctx.demangleSymbolAsNode(StringRef(MangledName, MangledNameLength));
if (!root)
return invalid;
if (root->getNumChildren() >= 1) {
NodePointer firstChild = root->getChild(0);
if (firstChild->getKind() == Node::Kind::KeyPathGetterThunkHelper) {
NodePointer child = firstChild->getChild(0);
switch (child->getKind()) {
case Node::Kind::Subscript: {
std::string subscriptText = "subscript(";
std::vector<std::string> argumentTypeNames;
auto getArgumentTypeName = [&argumentTypeNames](size_t i) {
if (i < argumentTypeNames.size())
return argumentTypeNames[i];
return std::string("<unknown>");
};
auto getArgumentNodeName = [](NodePointer node) {
if (node->getKind() == Node::Kind::Identifier) {
return std::string(node->getText());
}
if (node->getKind() == Node::Kind::LocalDeclName) {
auto text = node->getChild(1)->getText();
auto index = node->getChild(0)->getIndex() + 1;
return std::string(text) + " #" + std::to_string(index);
}
return std::string("<unknown>");
};
// Multiple arguments case
NodePointer argList = matchSequenceOfKinds(
child, {
std::make_pair(Node::Kind::Type, 2),
std::make_pair(Node::Kind::FunctionType, 0),
std::make_pair(Node::Kind::ArgumentTuple, 0),
std::make_pair(Node::Kind::Type, 0),
std::make_pair(Node::Kind::Tuple, 0),
});
if (argList != nullptr) {
size_t numArgumentTypes = argList->getNumChildren();
size_t idx = 0;
while (idx < numArgumentTypes) {
NodePointer argumentType = argList->getChild(idx);
idx += 1;
if (argumentType->getKind() == Node::Kind::TupleElement) {
argumentType =
argumentType->getChild(0)->getChild(0)->getChild(1);
argumentTypeNames.push_back(getArgumentNodeName(argumentType));
continue;
}
argumentTypeNames.push_back("<Unknown>");
}
} else {
// Case where there is a single argument
argList = matchSequenceOfKinds(
child, {
std::make_pair(Node::Kind::Type, 2),
std::make_pair(Node::Kind::FunctionType, 0),
std::make_pair(Node::Kind::ArgumentTuple, 0),
std::make_pair(Node::Kind::Type, 0),
});
if (argList != nullptr) {
argumentTypeNames.push_back(
getArgumentNodeName(argList->getChild(0)->getChild(1)));
}
}
child = child->getChild(1);
size_t idx = 0;
// There is an argument label:
if (child != nullptr) {
if (child->getKind() == Node::Kind::LabelList) {
size_t numChildren = child->getNumChildren();
if (numChildren == 0) {
subscriptText += unlabelledArg + getArgumentTypeName(0);
} else {
while (idx < numChildren) {
Node *argChild = child->getChild(idx);
idx += 1;
if (argChild->getKind() == Node::Kind::Identifier) {
subscriptText += std::string(argChild->getText()) + ": " +
getArgumentTypeName(idx - 1);
if (idx != numChildren) {
subscriptText += ", ";
}
} else if (argChild->getKind() ==
Node::Kind::FirstElementMarker ||
argChild->getKind() == Node::Kind::VariadicMarker) {
subscriptText += unlabelledArg + getArgumentTypeName(idx - 1);
}
}
}
}
} else {
subscriptText += unlabelledArg + getArgumentTypeName(0);
}
return subscriptText + ")";
}
case Node::Kind::Variable: {
child = child->getChild(1);
if (child == nullptr) {
return invalid;
}
if (child->getKind() == Node::Kind::PrivateDeclName) {
child = child->getChild(1);
if (child == nullptr) {
return invalid;
}
if (child->getKind() == Node::Kind::Identifier) {
return std::string(child->getText());
}
} else if (child->getKind() == Node::Kind::Identifier) {
return std::string(child->getText());
}
break;
}
default:
return invalid;
}
}
}
return invalid;
}
/// Converts a demangled node to a string.
///
/// \param root The root of the AST to demangle.
/// \param options The `DemangleOptions` which will be used to create the
/// NodePrinter.
///
/// \return The demangled node as a string.
std::string Demangle::nodeToString(NodePointer root,
const DemangleOptions &options) {
if (!root)
return "";
NodePrinter printer = NodePrinter(options);
nodeToString(root, printer);
return printer.takeString();
}
/// Converts a demangled node to a string, which is stored in the `printer`.
///
/// \param root The root of the AST to demangle.
/// \param printer The `NodePrinter` which will be used to print the AST to a
/// string.
void Demangle::nodeToString(NodePointer root, NodePrinter &printer) {
if (!root)
return;
printer.printRoot(root);
}
#endif