mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
3794 lines
131 KiB
C++
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
|