Skip to content

Commit 2c5ecb4

Browse files
authored
Merge pull request #20858 from DougGregor/mangled-base-protocol-witnesses
[ABI] Use mangled names for base protocol witnesses.
2 parents be8a2bf + 735a83b commit 2c5ecb4

30 files changed

+334
-193
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ Globals
146146
global ::= type protocol-conformance 'WL' // lazy protocol witness table cache variable
147147

148148
global ::= protocol-conformance identifier 'Wt' // associated type metadata accessor (HISTORICAL)
149-
global ::= protocol-conformance assoc-type-list nominal-type 'WT' // associated type witness table accessor
149+
global ::= protocol-conformance assoc-type-list protocol 'WT' // associated type witness table accessor
150+
global ::= protocol-conformance protocol 'Wb' // base protocol witness table accessor
150151
global ::= type protocol-conformance 'Wl' // lazy protocol witness table accessor
151152

152153
global ::= type 'WV' // value witness table
@@ -200,6 +201,7 @@ types where the metadata itself has unknown layout.)
200201
global ::= assoc-type-name 'TM' // default associated type witness accessor (HISTORICAL)
201202
global ::= type assoc-type-list protocol 'Tn' // associated conformance descriptor
202203
global ::= type assoc-type-list protocol 'TN' // default associated conformance witness accessor
204+
global ::= type protocol 'Tb' // base conformance descriptor
203205

204206
REABSTRACT-THUNK-TYPE ::= 'R' // reabstraction thunk helper function
205207
REABSTRACT-THUNK-TYPE ::= 'r' // reabstraction thunk

include/swift/AST/ProtocolAssociations.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@ class AssociatedType {
6868
}
6969
};
7070

71+
/// A base conformance of a protocol.
72+
class BaseConformance {
73+
ProtocolDecl *Source;
74+
ProtocolDecl *Requirement;
75+
76+
public:
77+
explicit BaseConformance(ProtocolDecl *source,
78+
ProtocolDecl *requirement)
79+
: Source(source), Requirement(requirement) {
80+
assert(source && requirement);
81+
}
82+
83+
ProtocolDecl *getSourceProtocol() const {
84+
return Source;
85+
}
86+
87+
ProtocolDecl *getBaseRequirement() const {
88+
return Requirement;
89+
}
90+
};
91+
7192
/// A conformance associated with a protocol.
7293
class AssociatedConformance {
7394
ProtocolDecl *Source;

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ NODE(AssociatedTypeRef)
3333
NODE(AssociatedTypeMetadataAccessor)
3434
NODE(DefaultAssociatedTypeMetadataAccessor)
3535
NODE(AssociatedTypeWitnessTableAccessor)
36+
NODE(BaseWitnessTableAccessor)
3637
NODE(AutoClosureType)
3738
NODE(BoundGenericClass)
3839
NODE(BoundGenericEnum)
@@ -226,6 +227,7 @@ NODE(MethodDescriptor)
226227
NODE(ProtocolRequirementsBaseDescriptor)
227228
NODE(AssociatedConformanceDescriptor)
228229
NODE(DefaultAssociatedConformanceAccessor)
230+
NODE(BaseConformanceDescriptor)
229231
NODE(AssociatedTypeDescriptor)
230232
NODE(ThrowsAnnotation)
231233
NODE(EmptyList)

include/swift/IRGen/Linking.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ class LinkEntity {
230230
/// is stored in the data.
231231
DefaultAssociatedConformanceAccessor,
232232

233+
/// An descriptor for an base conformance within a protocol, which
234+
/// will alias the TargetProtocolRequirement descripting this
235+
/// particular base conformance.
236+
/// The pointer is a ProtocolDecl*; the index of the base conformance
237+
/// is stored in the data.
238+
BaseConformanceDescriptor,
239+
233240
/// A global function pointer for dynamically replaceable functions.
234241
/// The pointer is a AbstractStorageDecl*.
235242
DynamicallyReplaceableFunctionVariableAST,
@@ -810,6 +817,18 @@ class LinkEntity {
810817
return entity;
811818
}
812819

820+
static LinkEntity
821+
forBaseConformanceDescriptor(BaseConformance conformance) {
822+
LinkEntity entity;
823+
entity.setForProtocolAndAssociatedConformance(
824+
Kind::BaseConformanceDescriptor,
825+
conformance.getSourceProtocol(),
826+
conformance.getSourceProtocol()->getSelfInterfaceType()
827+
->getCanonicalType(),
828+
conformance.getBaseRequirement());
829+
return entity;
830+
}
831+
813832
static LinkEntity
814833
forAssociatedTypeWitnessTableAccessFunction(const ProtocolConformance *C,
815834
const AssociatedConformance &association) {
@@ -963,7 +982,8 @@ class LinkEntity {
963982
}
964983

965984
assert(getKind() == Kind::AssociatedConformanceDescriptor ||
966-
getKind() == Kind::DefaultAssociatedConformanceAccessor);
985+
getKind() == Kind::DefaultAssociatedConformanceAccessor ||
986+
getKind() == Kind::BaseConformanceDescriptor);
967987
return getAssociatedConformanceByIndex(
968988
cast<ProtocolDecl>(getDecl()),
969989
LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex));

lib/Demangling/Context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ bool Context::hasSwiftCallingConvention(llvm::StringRef MangledName) {
162162
case Node::Kind::LazyProtocolWitnessTableAccessor:
163163
case Node::Kind::AssociatedTypeMetadataAccessor:
164164
case Node::Kind::AssociatedTypeWitnessTableAccessor:
165+
case Node::Kind::BaseWitnessTableAccessor:
165166
case Node::Kind::ObjCAttribute:
166167
return false;
167168
default:

lib/Demangling/Demangler.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,10 +2048,10 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
20482048

20492049
case 'n': {
20502050
NodePointer requirementTy = popProtocol();
2051-
auto assocTypePath = popAssocTypePath();
2051+
NodePointer conformingType = popAssocTypePath();
20522052
NodePointer protoTy = popNode(Node::Kind::Type);
20532053
return createWithChildren(Node::Kind::AssociatedConformanceDescriptor,
2054-
protoTy, assocTypePath, requirementTy);
2054+
protoTy, conformingType, requirementTy);
20552055
}
20562056

20572057
case 'N': {
@@ -2063,6 +2063,13 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
20632063
protoTy, assocTypePath, requirementTy);
20642064
}
20652065

2066+
case 'b': {
2067+
NodePointer requirementTy = popProtocol();
2068+
NodePointer protoTy = popNode(Node::Kind::Type);
2069+
return createWithChildren(Node::Kind::BaseConformanceDescriptor,
2070+
protoTy, requirementTy);
2071+
}
2072+
20662073
case 'H':
20672074
case 'h': {
20682075
auto nodeKind = c == 'H' ? Node::Kind::KeyPathEqualsThunkHelper
@@ -2437,11 +2444,16 @@ NodePointer Demangler::demangleWitness() {
24372444
}
24382445
case 'T': {
24392446
NodePointer ProtoTy = popNode(Node::Kind::Type);
2440-
auto AssocTypePath = popAssocTypePath();
2441-
2447+
NodePointer ConformingType = popAssocTypePath();
24422448
NodePointer Conf = popProtocolConformance();
24432449
return createWithChildren(Node::Kind::AssociatedTypeWitnessTableAccessor,
2444-
Conf, AssocTypePath, ProtoTy);
2450+
Conf, ConformingType, ProtoTy);
2451+
}
2452+
case 'b': {
2453+
NodePointer ProtoTy = popNode(Node::Kind::Type);
2454+
NodePointer Conf = popProtocolConformance();
2455+
return createWithChildren(Node::Kind::BaseWitnessTableAccessor,
2456+
Conf, ProtoTy);
24452457
}
24462458
case 'O': {
24472459
switch (nextChar()) {

lib/Demangling/NodePrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ class NodePrinter {
319319
case Node::Kind::AssociatedTypeMetadataAccessor:
320320
case Node::Kind::AssociatedTypeWitnessTableAccessor:
321321
case Node::Kind::AutoClosureType:
322+
case Node::Kind::BaseConformanceDescriptor:
323+
case Node::Kind::BaseWitnessTableAccessor:
322324
case Node::Kind::ClassMetadataBaseOffset:
323325
case Node::Kind::CFunctionPointer:
324326
case Node::Kind::Constructor:
@@ -1638,6 +1640,12 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
16381640
Printer << " in ";
16391641
print(Node->getChild(0));
16401642
return nullptr;
1643+
case Node::Kind::BaseConformanceDescriptor:
1644+
Printer << "base conformance descriptor for ";
1645+
print(Node->getChild(0));
1646+
Printer << ": ";
1647+
print(Node->getChild(1));
1648+
return nullptr;
16411649
case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
16421650
Printer << "default associated type metadata accessor for ";
16431651
print(Node->getChild(0));
@@ -1650,6 +1658,12 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
16501658
Printer << " in ";
16511659
print(Node->getChild(0));
16521660
return nullptr;
1661+
case Node::Kind::BaseWitnessTableAccessor:
1662+
Printer << "base witness table accessor for ";
1663+
print(Node->getChild(1));
1664+
Printer << " in ";
1665+
print(Node->getChild(0));
1666+
return nullptr;
16531667
case Node::Kind::ClassMetadataBaseOffset:
16541668
Printer << "class metadata base offset for ";
16551669
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,10 @@ void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) {
942942
Out << "<default-associated-conformance-descriptor>";
943943
}
944944

945+
void Remangler::mangleBaseConformanceDescriptor(Node *node) {
946+
Out << "<base-conformance-descriptor>";
947+
}
948+
945949
void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
946950
Out << "Wt";
947951
mangleChildNodes(node); // protocol conformance, identifier
@@ -955,10 +959,14 @@ void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
955959
Out << "WT";
956960
assert(node->getNumChildren() == 3);
957961
mangleChildNode(node, 0); // protocol conformance
958-
mangleChildNode(node, 1); // identifier
962+
mangleChildNode(node, 1); // type
959963
mangleProtocolWithoutPrefix(node->begin()[2]); // type
960964
}
961965

966+
void Remangler::mangleBaseWitnessTableAccessor(Node *node) {
967+
Out << "<base-witness-table-accessor>";
968+
}
969+
962970
void Remangler::mangleReabstractionThunkHelper(Node *node) {
963971
Out << "TR";
964972
if (node->getNumChildren() == 3) Out << 'G';

lib/Demangling/Remangler.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,11 @@ void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) {
587587
Buffer << "TN";
588588
}
589589

590+
void Remangler::mangleBaseConformanceDescriptor(Node *node) {
591+
mangleChildNodes(node);
592+
Buffer << "Tb";
593+
}
594+
590595
void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
591596
mangleChildNodes(node); // protocol conformance, identifier
592597
Buffer << "Wt";
@@ -598,10 +603,15 @@ void Remangler::mangleDefaultAssociatedTypeMetadataAccessor(Node *node) {
598603
}
599604

600605
void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
601-
mangleChildNodes(node); // protocol conformance, identifier, type
606+
mangleChildNodes(node); // protocol conformance, type, protocol
602607
Buffer << "WT";
603608
}
604609

610+
void Remangler::mangleBaseWitnessTableAccessor(Node *node) {
611+
mangleChildNodes(node); // protocol conformance, protocol
612+
Buffer << "Wb";
613+
}
614+
605615
void Remangler::mangleAutoClosureType(Node *node) {
606616
mangleChildNodesReversed(node); // argument tuple, result type
607617
Buffer << "XK";

lib/IRGen/GenDecl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3536,6 +3536,19 @@ llvm::GlobalValue *IRGenModule::defineAssociatedConformanceDescriptor(
35363536
return defineAlias(entity, definition);
35373537
}
35383538

3539+
llvm::Constant *IRGenModule::getAddrOfBaseConformanceDescriptor(
3540+
BaseConformance conformance) {
3541+
auto entity = LinkEntity::forBaseConformanceDescriptor(conformance);
3542+
return getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
3543+
}
3544+
3545+
llvm::GlobalValue *IRGenModule::defineBaseConformanceDescriptor(
3546+
BaseConformance conformance,
3547+
llvm::Constant *definition) {
3548+
auto entity = LinkEntity::forBaseConformanceDescriptor(conformance);
3549+
return defineAlias(entity, definition);
3550+
}
3551+
35393552
llvm::Constant *IRGenModule::getAddrOfProtocolConformanceDescriptor(
35403553
const RootProtocolConformance *conformance,
35413554
ConstantInit definition) {

lib/IRGen/GenMeta.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,15 @@ namespace {
729729
B.getAddrOfCurrentPosition(IGM.ProtocolRequirementStructTy));
730730
}
731731

732+
if (entry.isBase()) {
733+
// Define a base conformance descriptor, which is just an associated
734+
// conformance descriptor for a base protocol.
735+
BaseConformance conformance(Proto, entry.getBase());
736+
IGM.defineBaseConformanceDescriptor(
737+
conformance,
738+
B.getAddrOfCurrentPosition(IGM.ProtocolRequirementStructTy));
739+
}
740+
732741
auto reqt = B.beginStruct(IGM.ProtocolRequirementStructTy);
733742

734743
auto info = getRequirementInfo(entry);

0 commit comments

Comments
 (0)