Skip to content

Commit 29bc118

Browse files
committed
[Demangling] [Runtime] More protocol conformance demangling.
Added: * Demangle node types for the various symbolic manglings. * SymbolicReferenceKind values for the symbolic manglings. * A method on the demangler to demangle a conformance. * Support for printing the new node types. * Remangler support for the new node types. * Code to the runtime to deal with the symbolic references. * A private _getAssocWitnessTableFromMangledName() function to use from Metadata.cpp. Use the demangler from swift_getAssociatedConformanceWitnessSlowImpl(), rather than the existing hack. Also rebased on current swift/main. rdar://46280860
1 parent 7f98799 commit 29bc118

File tree

12 files changed

+424
-94
lines changed

12 files changed

+424
-94
lines changed

include/swift/Demangling/DemangleNodes.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,5 +320,11 @@ NODE(IndexSubset)
320320
NODE(AsyncAwaitResumePartialFunction)
321321
NODE(AsyncSuspendResumePartialFunction)
322322

323+
// Added in Swift 5.6
324+
NODE(AssociatedConformanceProtocolRelativeAccessor)
325+
NODE(AssociatedConformanceTypeRelativeAccessor)
326+
NODE(ProtocolConformanceDescriptorRef)
327+
NODE(AssociatedConformanceDescriptorRef)
328+
323329
#undef CONTEXT_NODE
324330
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@ enum class SymbolicReferenceKind : uint8_t {
340340
/// A symbolic reference to a context descriptor, representing the
341341
/// (unapplied generic) context.
342342
Context,
343+
/// A protocol conformance descriptor.
344+
ProtocolConformanceDescriptor,
345+
/// An associated conformance descriptor.
346+
AssociatedConformanceDescriptor,
347+
/// An associated conformance access function.
348+
AssociatedConformanceProtocolRelativeAccessor,
349+
AssociatedConformanceTypeRelativeAccessor,
343350
/// A symbolic reference to an accessor function, which can be executed in
344351
/// the process to get a pointer to the referenced entity.
345352
AccessorFunctionReference,
@@ -618,6 +625,21 @@ class Demangler : public NodeFactory {
618625
NodePointer demangleType(StringRef MangledName,
619626
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
620627
= nullptr);
628+
629+
/// Demangle the given protocol conformance and return the parse tree.
630+
///
631+
/// \param MangledName The mangled conformance string, which does _not_ start
632+
/// with the mangling prefix $S.
633+
/// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in
634+
/// the string. If null, then symbolic references will cause the demangle to fail.
635+
///
636+
/// \returns A parse tree for the demangled string - or a null pointer
637+
/// on failure.
638+
/// The lifetime of the returned node tree ends with the lifetime of the
639+
/// Demangler or with a call of clear().
640+
NodePointer demangleConformance(StringRef MangledName,
641+
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
642+
= nullptr);
621643
};
622644

623645
/// A demangler which uses stack space for its initial memory.
@@ -634,6 +656,7 @@ template <size_t Size> class StackAllocatedDemangler : public Demangler {
634656

635657
NodePointer demangleOldSymbolAsNode(StringRef MangledName,
636658
NodeFactory &Factory);
659+
637660
SWIFT_END_INLINE_NAMESPACE
638661
} // end namespace Demangle
639662
} // end namespace swift

include/swift/Demangling/TypeDecoder.h

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "TypeLookupError.h"
2222
#include "swift/Basic/LLVM.h"
23+
#include "swift/ABI/Metadata.h"
2324
#include "swift/ABI/MetadataValues.h"
2425
#include "swift/AST/LayoutConstraintKind.h"
2526
#include "swift/AST/RequirementBase.h"
@@ -470,29 +471,53 @@ class TypeDecoder {
470471
public:
471472
explicit TypeDecoder(BuilderType &Builder) : Builder(Builder) {}
472473

474+
/// Given a demangle tree, attempt to turn it into a type.
475+
TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node) {
476+
return decodeMangledType(Node, 0);
477+
}
478+
473479
/// Given a demangle tree, attempt to turn it into a protocol conformance.
474480
BuiltProtocolConformance decodeMangledProtocolConformance(NodePointer Node) {
475-
if (!Node) return BuiltProtocolConformance();
481+
return decodeMangledProtocolConformance(Node, 0);
482+
}
483+
484+
/// Given a demangle tree, attempt to turn it into a conformance decl.
485+
BuiltProtocolConformanceDecl
486+
decodeMangledProtocolConformanceDecl(BuiltType ConformingType,
487+
NodePointer Node) {
488+
return decodeMangledProtocolConformanceDecl(ConformingType, Node, 0);
489+
}
490+
491+
protected:
492+
static const unsigned MaxDepth = 1024;
493+
494+
BuiltProtocolConformance decodeMangledProtocolConformance(NodePointer Node,
495+
unsigned depth) {
496+
if (!Node || depth > TypeDecoder::MaxDepth)
497+
return BuiltProtocolConformance();
476498

477499
using NodeKind = Demangle::Node::Kind;
478500
switch (Node->getKind()) {
479501
case NodeKind::Global:
480502
if (Node->getNumChildren() < 1)
481503
return BuiltProtocolConformance();
482504

483-
return decodeMangledProtocolConformance(Node->getChild(0));
505+
return decodeMangledProtocolConformance(Node->getChild(0), depth + 1);
484506

485507
case NodeKind::ConcreteProtocolConformance: {
486508
if (Node->getNumChildren() < 3)
487509
return BuiltProtocolConformance();
488510

489-
auto conformingType = decodeMangledType(Node->getChild(0));
490-
if (!conformingType)
511+
auto conformingTypeOrError = decodeMangledType(Node->getChild(0),
512+
depth + 1);
513+
if (conformingTypeOrError.isError())
491514
return BuiltProtocolConformance();
492515

516+
auto conformingType = conformingTypeOrError.getValue();
493517
auto conformanceDecl
494518
= decodeMangledProtocolConformanceDecl(conformingType,
495-
Node->getChild(1));
519+
Node->getChild(1),
520+
depth + 1);
496521

497522
if (!conformanceDecl)
498523
return BuiltProtocolConformance();
@@ -503,7 +528,7 @@ class TypeDecoder {
503528
return BuiltProtocolConformance();
504529

505530
for (auto mangledArg : *Node->getChild(2)) {
506-
auto arg = decodeMangledProtocolConformance(mangledArg);
531+
auto arg = decodeMangledProtocolConformance(mangledArg, depth + 1);
507532
if (!arg)
508533
return BuiltProtocolConformance();
509534
conformanceArgs.push_back(arg);
@@ -518,11 +543,14 @@ class TypeDecoder {
518543
if (Node->getNumChildren() < 3)
519544
return BuiltProtocolConformance();
520545

521-
auto conformingType = decodeMangledType(Node->getChild(0));
522-
if (!conformingType)
546+
auto conformingTypeOrError = decodeMangledType(Node->getChild(0),
547+
depth + 1);
548+
if (conformingTypeOrError.isError())
523549
return BuiltProtocolConformance();
524550

525-
auto conformingRequirement = decodeMangledProtocolType(Node->getChild(1));
551+
auto conformingType = conformingTypeOrError.getValue();
552+
auto conformingRequirement = decodeMangledProtocolType(Node->getChild(1),
553+
depth + 1);
526554
if (!conformingRequirement)
527555
return BuiltProtocolConformance();
528556

@@ -540,7 +568,7 @@ class TypeDecoder {
540568
if (Node->getNumChildren() < 3)
541569
return BuiltProtocolConformance();
542570

543-
auto base = decodeMangledProtocolConformance(Node->getChild(0));
571+
auto base = decodeMangledProtocolConformance(Node->getChild(0), depth + 1);
544572
if (!base)
545573
return BuiltProtocolConformance();
546574

@@ -549,10 +577,13 @@ class TypeDecoder {
549577
if (Node->getChild(1)->getNumChildren() < 2)
550578
return BuiltProtocolConformance();
551579

552-
auto conformingType = decodeMangledType(Node->getChild(1)->getChild(0));
553-
if (!conformingType)
580+
auto conformingTypeOrError
581+
= decodeMangledType(Node->getChild(1)->getChild(0), depth + 1);
582+
if (conformingTypeOrError.isError())
554583
return BuiltProtocolConformance();
555-
auto conformingRequirement = decodeMangledProtocolType(Node->getChild(1)->getChild(1));
584+
auto conformingType = conformingTypeOrError.getValue();
585+
auto conformingRequirement
586+
= decodeMangledProtocolType(Node->getChild(1)->getChild(1), depth + 1);
556587
if (!conformingRequirement)
557588
return BuiltProtocolConformance();
558589

@@ -571,11 +602,12 @@ class TypeDecoder {
571602
if (Node->getNumChildren() < 3)
572603
return BuiltProtocolConformance();
573604

574-
auto base = decodeMangledProtocolConformance(Node->getChild(0));
605+
auto base = decodeMangledProtocolConformance(Node->getChild(0), depth + 1);
575606
if (!base)
576607
return BuiltProtocolConformance();
577608

578-
auto superRequirement = decodeMangledProtocolType(Node->getChild(1));
609+
auto superRequirement = decodeMangledProtocolType(Node->getChild(1),
610+
depth + 1);
579611
if (!superRequirement)
580612
return BuiltProtocolConformance();
581613

@@ -589,22 +621,32 @@ class TypeDecoder {
589621
index);
590622
}
591623

624+
case NodeKind::AssociatedConformanceProtocolRelativeAccessor:
625+
case NodeKind::AssociatedConformanceTypeRelativeAccessor: {
626+
auto witnessFn = reinterpret_cast<AssociatedWitnessTableAccessFunction *>(
627+
Node->getIndex());
628+
return Builder.createProtocolConformanceFromAccessor(witnessFn);
629+
}
592630
default:
593631
return BuiltProtocolConformance();
594632
}
595633
}
596634

597-
BuiltProtocolConformanceDecl decodeMangledProtocolConformanceDecl(BuiltType ConformingType,
598-
NodePointer Node) {
599-
if (!Node) return BuiltProtocolConformanceDecl();
635+
BuiltProtocolConformanceDecl
636+
decodeMangledProtocolConformanceDecl(BuiltType ConformingType,
637+
NodePointer Node,
638+
unsigned depth) {
639+
if (!Node || depth > TypeDecoder::MaxDepth)
640+
return BuiltProtocolConformanceDecl();
600641

601642
using NodeKind = Demangle::Node::Kind;
602643
switch (Node->getKind()) {
603644
case NodeKind::ProtocolConformanceRefInTypeModule: {
604645
if (Node->getNumChildren() < 1)
605646
return BuiltProtocolConformanceDecl();
606647

607-
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0));
648+
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0),
649+
depth + 1);
608650
if (!protocolRequirement)
609651
return BuiltProtocolConformanceDecl();
610652

@@ -616,7 +658,8 @@ class TypeDecoder {
616658
if (Node->getNumChildren() < 1)
617659
return BuiltProtocolConformanceDecl();
618660

619-
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0));
661+
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0),
662+
depth + 1);
620663
if (!protocolRequirement)
621664
return BuiltProtocolConformanceDecl();
622665

@@ -628,7 +671,8 @@ class TypeDecoder {
628671
if (Node->getNumChildren() < 2)
629672
return BuiltProtocolConformanceDecl();
630673

631-
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0));
674+
auto protocolRequirement = decodeMangledProtocolType(Node->getChild(0),
675+
depth + 1);
632676
if (!protocolRequirement)
633677
return BuiltProtocolConformanceDecl();
634678

@@ -639,25 +683,18 @@ class TypeDecoder {
639683
moduleName);
640684
}
641685

642-
/*
643-
case NodeKind::ProtocolConformanceSymbolicReference:
644-
return Builder.createSymbolicProtocolConformanceDecl(ConformingType,
645-
Node);
646-
*/
686+
case NodeKind::ProtocolConformanceDescriptorRef:
687+
case NodeKind::AssociatedConformanceDescriptorRef: {
688+
auto desc = reinterpret_cast<ProtocolConformanceDescriptor *>(
689+
Node->getIndex());
690+
return Builder.createProtocolConformanceDeclFromDescriptor(desc);
691+
}
647692

648693
default:
649-
return BuiltProtocolConformance();
694+
return BuiltProtocolConformanceDecl();
650695
}
651696
}
652697

653-
/// Given a demangle tree, attempt to turn it into a type.
654-
TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node) {
655-
return decodeMangledType(Node, 0);
656-
}
657-
658-
protected:
659-
static const unsigned MaxDepth = 1024;
660-
661698
TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node,
662699
unsigned depth) {
663700
if (depth > TypeDecoder::MaxDepth)

include/swift/Demangling/TypeLookupError.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ template <typename T> class TypeLookupErrorOr {
179179
TypeLookupErrorOr(const TypeLookupError &te) : Value(te) {}
180180

181181
T getType() {
182+
return getValue();
183+
}
184+
185+
T getValue() {
182186
if (auto *ptr = Value.template dyn_cast<T>())
183187
return *ptr;
184188
return T();

include/swift/Remote/MetadataReader.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,25 @@ class MetadataReader {
442442

443443
return buildContextMangling(context, dem);
444444
}
445+
case Demangle::SymbolicReferenceKind::AssociatedConformanceProtocolRelativeAccessor:
446+
case Demangle::SymbolicReferenceKind::AssociatedConformanceTypeRelativeAccessor:
445447
case Demangle::SymbolicReferenceKind::AccessorFunctionReference: {
446448
// The symbolic reference points at a resolver function, but we can't
447449
// execute code in the target process to resolve it from here.
448450
return nullptr;
449451
}
452+
case Demangle::SymbolicReferenceKind::ProtocolConformanceDescriptor: {
453+
return dem.createNode(
454+
Node::Kind::ProtocolConformanceDescriptor,
455+
remoteAddress
456+
);
457+
}
458+
case Demangle::SymbolicReferenceKind::AssociatedConformanceDescriptor: {
459+
return dem.createNode(
460+
Node::Kind::AssociatedConformanceDescriptor,
461+
remoteAddress
462+
);
463+
}
450464
}
451465

452466
return nullptr;

lib/Demangling/Demangler.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,30 @@ NodePointer Demangler::demangleType(StringRef MangledName,
597597
return createNode(Node::Kind::Suffix, Text);
598598
}
599599

600+
NodePointer Demangler::demangleConformance(StringRef MangledName,
601+
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver) {
602+
DemangleInitRAII state(*this, MangledName,
603+
std::move(SymbolicReferenceResolver));
604+
605+
parseAndPushNodes();
606+
607+
if (NodePointer Result = popNode()) {
608+
if (Result->getKind() == Node::Kind::Global) {
609+
if (Result->getNumChildren() < 1)
610+
return nullptr;
611+
Result = Result->getChild(0);
612+
}
613+
614+
if (Result->getKind() != Node::Kind::ConcreteProtocolConformance
615+
&& Result->getKind() != Node::Kind::DependentProtocolConformanceRoot)
616+
return nullptr;
617+
618+
return Result;
619+
}
620+
621+
return nullptr;
622+
}
623+
600624
bool Demangler::parseAndPushNodes() {
601625
const auto textSize = Text.size();
602626
while (Pos < textSize) {
@@ -714,14 +738,38 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind) {
714738
kind = SymbolicReferenceKind::Context;
715739
direct = Directness::Indirect;
716740
break;
741+
case 3:
742+
kind = SymbolicReferenceKind::ProtocolConformanceDescriptor;
743+
direct = Directness::Direct;
744+
break;
745+
case 4:
746+
kind = SymbolicReferenceKind::ProtocolConformanceDescriptor;
747+
direct = Directness::Indirect;
748+
break;
749+
case 5:
750+
kind = SymbolicReferenceKind::AssociatedConformanceDescriptor;
751+
direct = Directness::Direct;
752+
break;
753+
case 6:
754+
kind = SymbolicReferenceKind::AssociatedConformanceDescriptor;
755+
direct = Directness::Indirect;
756+
break;
757+
case 7:
758+
kind = SymbolicReferenceKind::AssociatedConformanceProtocolRelativeAccessor;
759+
direct = Directness::Direct;
760+
break;
761+
case 8:
762+
kind = SymbolicReferenceKind::AssociatedConformanceTypeRelativeAccessor;
763+
direct = Directness::Direct;
764+
break;
717765
case 9:
718766
kind = SymbolicReferenceKind::AccessorFunctionReference;
719767
direct = Directness::Direct;
720768
break;
721769
default:
722770
return nullptr;
723771
}
724-
772+
725773
// Use the resolver, if any, to produce the demangling tree the symbolic
726774
// reference represents.
727775
NodePointer resolved = nullptr;

0 commit comments

Comments
 (0)