Skip to content

Commit 01c4717

Browse files
authored
Merge pull request #27014 from jckarter/opaque-type-assoc-type-mangling
Mangle associated types of opaque types like dependent member types. …
2 parents f1690b0 + 0ae86c9 commit 01c4717

File tree

13 files changed

+371
-133
lines changed

13 files changed

+371
-133
lines changed

docs/ABI/Mangling.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,11 @@ Types
551551
type ::= assoc-type-name 'Qz' // shortcut for 'Qyz'
552552
type ::= assoc-type-list 'QY' GENERIC-PARAM-INDEX // associated type at depth
553553
type ::= assoc-type-list 'QZ' // shortcut for 'QYz'
554+
555+
#if SWIFT_RUNTIME_VERSION >= 5.2
556+
type ::= type assoc-type-name 'Qx' // associated type relative to base `type`
557+
type ::= type assoc-type-list 'QX' // associated type relative to base `type`
558+
#endif
554559

555560
protocol-list ::= protocol '_' protocol*
556561
protocol-list ::= empty-list

lib/AST/ASTMangler.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,22 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
10051005

10061006
case TypeKind::NestedArchetype: {
10071007
auto nestedType = cast<NestedArchetypeType>(tybase);
1008+
1009+
// Mangle associated types of opaque archetypes like dependent member
1010+
// types, so that they can be accurately demangled at runtime.
1011+
if (auto opaque =
1012+
dyn_cast<OpaqueTypeArchetypeType>(nestedType->getRoot())) {
1013+
if (tryMangleTypeSubstitution(nestedType))
1014+
return;
1015+
1016+
appendType(opaque);
1017+
bool isAssocTypeAtDepth = false;
1018+
appendAssocType(nestedType->getInterfaceType(), isAssocTypeAtDepth);
1019+
appendOperator(isAssocTypeAtDepth ? "QX" : "Qx");
1020+
addTypeSubstitution(nestedType);
1021+
return;
1022+
}
1023+
10081024
appendType(nestedType->getParent());
10091025
appendIdentifier(nestedType->getName().str());
10101026
appendOperator("Qa");

lib/Basic/Platform.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ swift::getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple){
351351
if (Major == 10) {
352352
if (Minor <= 14) {
353353
return llvm::VersionTuple(5, 0);
354+
} else if (Minor <= 15) {
355+
return llvm::VersionTuple(5, 1);
354356
} else {
355357
return None;
356358
}
@@ -361,13 +363,17 @@ swift::getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple){
361363
Triple.getiOSVersion(Major, Minor, Micro);
362364
if (Major <= 12) {
363365
return llvm::VersionTuple(5, 0);
366+
} else if (Major <= 13) {
367+
return llvm::VersionTuple(5, 1);
364368
} else {
365369
return None;
366370
}
367371
} else if (Triple.isWatchOS()) {
368372
Triple.getWatchOSVersion(Major, Minor, Micro);
369373
if (Major <= 5) {
370374
return llvm::VersionTuple(5, 0);
375+
} else if (Major <= 6) {
376+
return llvm::VersionTuple(5, 1);
371377
} else {
372378
return None;
373379
}

lib/Demangling/Demangler.cpp

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,79 +1919,96 @@ NodePointer Demangler::demanglePrivateContextDescriptor() {
19191919

19201920
NodePointer Demangler::demangleArchetype() {
19211921
switch (nextChar()) {
1922-
case 'a': {
1923-
NodePointer Ident = popNode(Node::Kind::Identifier);
1924-
NodePointer ArcheTy = popTypeAndGetChild();
1925-
NodePointer AssocTy = createType(
1926-
createWithChildren(Node::Kind::AssociatedTypeRef, ArcheTy, Ident));
1927-
addSubstitution(AssocTy);
1928-
return AssocTy;
1929-
}
1930-
case 'O': {
1931-
auto definingContext = popContext();
1932-
return createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext);
1933-
}
1934-
case 'o': {
1935-
auto index = demangleIndex();
1936-
Vector<NodePointer> boundGenericArgs;
1937-
NodePointer retroactiveConformances;
1938-
if (!demangleBoundGenerics(boundGenericArgs, retroactiveConformances))
1939-
return nullptr;
1940-
auto Name = popNode();
1941-
auto opaque = createWithChildren(Node::Kind::OpaqueType, Name,
1942-
createNode(Node::Kind::Index, index));
1943-
auto boundGenerics = createNode(Node::Kind::TypeList);
1944-
for (unsigned i = boundGenericArgs.size(); i-- > 0;)
1945-
boundGenerics->addChild(boundGenericArgs[i], *this);
1946-
opaque->addChild(boundGenerics, *this);
1947-
if (retroactiveConformances)
1948-
opaque->addChild(retroactiveConformances, *this);
1949-
1950-
auto opaqueTy = createType(opaque);
1951-
addSubstitution(opaqueTy);
1952-
return opaqueTy;
1953-
}
1954-
case 'r': {
1955-
return createType(createNode(Node::Kind::OpaqueReturnType));
1956-
}
1957-
case 'y': {
1958-
NodePointer T = demangleAssociatedTypeSimple(demangleGenericParamIndex());
1959-
addSubstitution(T);
1960-
return T;
1961-
}
1962-
case 'z': {
1963-
NodePointer T = demangleAssociatedTypeSimple(
1964-
getDependentGenericParamType(0, 0));
1965-
addSubstitution(T);
1966-
return T;
1967-
}
1968-
case 'Y': {
1969-
NodePointer T = demangleAssociatedTypeCompound(
1970-
demangleGenericParamIndex());
1971-
addSubstitution(T);
1972-
return T;
1973-
}
1974-
case 'Z': {
1975-
NodePointer T = demangleAssociatedTypeCompound(
1976-
getDependentGenericParamType(0, 0));
1977-
addSubstitution(T);
1978-
return T;
1979-
}
1980-
default:
1922+
case 'a': {
1923+
NodePointer Ident = popNode(Node::Kind::Identifier);
1924+
NodePointer ArcheTy = popTypeAndGetChild();
1925+
NodePointer AssocTy = createType(
1926+
createWithChildren(Node::Kind::AssociatedTypeRef, ArcheTy, Ident));
1927+
addSubstitution(AssocTy);
1928+
return AssocTy;
1929+
}
1930+
case 'O': {
1931+
auto definingContext = popContext();
1932+
return createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext);
1933+
}
1934+
case 'o': {
1935+
auto index = demangleIndex();
1936+
Vector<NodePointer> boundGenericArgs;
1937+
NodePointer retroactiveConformances;
1938+
if (!demangleBoundGenerics(boundGenericArgs, retroactiveConformances))
19811939
return nullptr;
1940+
auto Name = popNode();
1941+
auto opaque = createWithChildren(Node::Kind::OpaqueType, Name,
1942+
createNode(Node::Kind::Index, index));
1943+
auto boundGenerics = createNode(Node::Kind::TypeList);
1944+
for (unsigned i = boundGenericArgs.size(); i-- > 0;)
1945+
boundGenerics->addChild(boundGenericArgs[i], *this);
1946+
opaque->addChild(boundGenerics, *this);
1947+
if (retroactiveConformances)
1948+
opaque->addChild(retroactiveConformances, *this);
1949+
1950+
auto opaqueTy = createType(opaque);
1951+
addSubstitution(opaqueTy);
1952+
return opaqueTy;
1953+
}
1954+
case 'r': {
1955+
return createType(createNode(Node::Kind::OpaqueReturnType));
1956+
}
1957+
1958+
case 'x': {
1959+
NodePointer T = demangleAssociatedTypeSimple(nullptr);
1960+
addSubstitution(T);
1961+
return T;
1962+
}
1963+
1964+
case 'X': {
1965+
NodePointer T = demangleAssociatedTypeCompound(nullptr);
1966+
addSubstitution(T);
1967+
return T;
1968+
}
1969+
1970+
case 'y': {
1971+
NodePointer T = demangleAssociatedTypeSimple(demangleGenericParamIndex());
1972+
addSubstitution(T);
1973+
return T;
1974+
}
1975+
case 'Y': {
1976+
NodePointer T = demangleAssociatedTypeCompound(
1977+
demangleGenericParamIndex());
1978+
addSubstitution(T);
1979+
return T;
1980+
}
1981+
1982+
case 'z': {
1983+
NodePointer T = demangleAssociatedTypeSimple(
1984+
getDependentGenericParamType(0, 0));
1985+
addSubstitution(T);
1986+
return T;
1987+
}
1988+
case 'Z': {
1989+
NodePointer T = demangleAssociatedTypeCompound(
1990+
getDependentGenericParamType(0, 0));
1991+
addSubstitution(T);
1992+
return T;
1993+
}
1994+
default:
1995+
return nullptr;
19821996
}
19831997
}
19841998

1985-
NodePointer Demangler::demangleAssociatedTypeSimple(
1986-
NodePointer GenericParamIdx) {
1987-
NodePointer GPI = createType(GenericParamIdx);
1999+
NodePointer Demangler::demangleAssociatedTypeSimple(NodePointer Base) {
19882000
NodePointer ATName = popAssocTypeName();
2001+
NodePointer BaseTy;
2002+
if (Base) {
2003+
BaseTy = createType(Base);
2004+
} else {
2005+
BaseTy = popNode(Node::Kind::Type);
2006+
}
19892007
return createType(createWithChildren(Node::Kind::DependentMemberType,
1990-
GPI, ATName));
2008+
BaseTy, ATName));
19912009
}
19922010

1993-
NodePointer Demangler::demangleAssociatedTypeCompound(
1994-
NodePointer GenericParamIdx) {
2011+
NodePointer Demangler::demangleAssociatedTypeCompound(NodePointer Base) {
19952012
Vector<NodePointer> AssocTyNames(*this, 4);
19962013
bool firstElem = false;
19972014
do {
@@ -2001,15 +2018,19 @@ NodePointer Demangler::demangleAssociatedTypeCompound(
20012018
return nullptr;
20022019
AssocTyNames.push_back(AssocTyName, *this);
20032020
} while (!firstElem);
2004-
2005-
NodePointer Base = GenericParamIdx;
2021+
2022+
NodePointer BaseTy;
2023+
if (Base)
2024+
BaseTy = createType(Base);
2025+
else
2026+
BaseTy = popNode(Node::Kind::Type);
20062027

20072028
while (NodePointer AssocTy = AssocTyNames.pop_back_val()) {
20082029
NodePointer depTy = createNode(Node::Kind::DependentMemberType);
2009-
depTy = addChild(depTy, createType(Base));
2010-
Base = addChild(depTy, AssocTy);
2030+
depTy = addChild(depTy, BaseTy);
2031+
BaseTy = createType(addChild(depTy, AssocTy));
20112032
}
2012-
return createType(Base);
2033+
return BaseTy;
20132034
}
20142035

20152036
NodePointer Demangler::popAssocTypeName() {

lib/Demangling/Remangler.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,11 @@ std::pair<int, Node *> Remangler::mangleConstrainedType(Node *node) {
424424
Chain.push_back(node->getChild(1), Factory);
425425
node = getChildOfType(node->getFirstChild());
426426
}
427-
assert(node->getKind() == Node::Kind::DependentGenericParamType);
427+
428+
if (node->getKind() != Node::Kind::DependentGenericParamType) {
429+
mangle(node);
430+
node = nullptr;
431+
}
428432

429433
const char *ListSeparator = (Chain.size() > 1 ? "_" : "");
430434
for (unsigned i = 1, n = Chain.size(); i <= n; ++i) {
@@ -811,6 +815,7 @@ void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
811815
if (ProtoOrClass->getFirstChild()->getKind() == Node::Kind::Protocol) {
812816
manglePureProtocol(ProtoOrClass);
813817
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
818+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
814819
switch (NumMembersAndParamIdx.first) {
815820
case -1: Buffer << "RQ"; return; // substitution
816821
case 0: Buffer << "R"; break;
@@ -822,6 +827,7 @@ void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
822827
}
823828
mangle(ProtoOrClass);
824829
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
830+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
825831
switch (NumMembersAndParamIdx.first) {
826832
case -1: Buffer << "RB"; return; // substitution
827833
case 0: Buffer << "Rb"; break;
@@ -849,6 +855,7 @@ void Remangler::mangleDependentGenericParamType(Node *node) {
849855
void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
850856
mangleChildNode(node, 1);
851857
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
858+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
852859
switch (NumMembersAndParamIdx.first) {
853860
case -1: Buffer << "RS"; return; // substitution
854861
case 0: Buffer << "Rs"; break;
@@ -860,6 +867,7 @@ void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
860867

861868
void Remangler::mangleDependentGenericLayoutRequirement(Node *node) {
862869
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
870+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
863871
switch (NumMembersAndParamIdx.first) {
864872
case -1: Buffer << "RL"; break; // substitution
865873
case 0: Buffer << "Rl"; break;
@@ -922,11 +930,19 @@ void Remangler::mangleDependentMemberType(Node *node) {
922930
unreachable("wrong dependent member type");
923931
case 1:
924932
Buffer << 'Q';
925-
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second, "y", 'z');
933+
if (auto dependentBase = NumMembersAndParamIdx.second) {
934+
mangleDependentGenericParamIndex(dependentBase, "y", 'z');
935+
} else {
936+
Buffer << 'x';
937+
}
926938
break;
927939
default:
928940
Buffer << 'Q';
929-
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second, "Y", 'Z');
941+
if (auto dependentBase = NumMembersAndParamIdx.second) {
942+
mangleDependentGenericParamIndex(dependentBase, "Y", 'Z');
943+
} else {
944+
Buffer << 'X';
945+
}
930946
break;
931947
}
932948
}

lib/IRGen/GenKeyPath.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,10 @@ getInitializerForComputedComponent(IRGenModule &IGM,
649649
}
650650

651651
static llvm::Constant *
652-
emitMetadataTypeRefForKeyPath(IRGenModule &IGM, CanType type) {
652+
emitMetadataTypeRefForKeyPath(IRGenModule &IGM, CanType type,
653+
CanGenericSignature sig) {
653654
// Produce a mangled name for the type.
654-
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata).first;
655+
auto constant = IGM.getTypeRef(type, sig, MangledTypeRefRole::Metadata).first;
655656

656657
// Mask the bottom bit to tell the key path runtime this is a mangled name
657658
// rather than a direct reference.
@@ -837,6 +838,10 @@ emitKeyPathComponent(IRGenModule &IGM,
837838
SmallVector<llvm::Constant *, 4> externalSubArgs;
838839
auto componentSig = externalDecl->getInnermostDeclContext()
839840
->getGenericSignatureOfContext();
841+
842+
auto componentCanSig = componentSig
843+
? componentSig->getCanonicalSignature()
844+
: CanGenericSignature();
840845
auto subs = component.getExternalSubstitutions();
841846
if (!subs.empty()) {
842847
enumerateGenericSignatureRequirements(
@@ -847,7 +852,7 @@ emitKeyPathComponent(IRGenModule &IGM,
847852
if (!reqt.Protocol) {
848853
// Type requirement.
849854
externalSubArgs.push_back(
850-
emitMetadataTypeRefForKeyPath(IGM, substType));
855+
emitMetadataTypeRefForKeyPath(IGM, substType, componentCanSig));
851856
} else {
852857
// Protocol requirement.
853858
auto conformance = subs.lookupConformance(
@@ -1182,9 +1187,11 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
11821187
getAddrOfGenericEnvironment(pattern->getGenericSignature()));
11831188
// Store type references for the root and leaf.
11841189
fields.addRelativeAddress(
1185-
emitMetadataTypeRefForKeyPath(*this, rootTy));
1190+
emitMetadataTypeRefForKeyPath(*this, rootTy,
1191+
pattern->getGenericSignature()));
11861192
fields.addRelativeAddress(
1187-
emitMetadataTypeRefForKeyPath(*this, valueTy));
1193+
emitMetadataTypeRefForKeyPath(*this, valueTy,
1194+
pattern->getGenericSignature()));
11881195

11891196
// Add a pointer to the ObjC KVC compatibility string, if there is one, or
11901197
// null otherwise.
@@ -1238,7 +1245,9 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
12381245
// For all but the last component, we pack in the type of the component.
12391246
if (i + 1 != pattern->getComponents().size()) {
12401247
fields.addRelativeAddress(
1241-
emitMetadataTypeRefForKeyPath(*this, component.getComponentType()));
1248+
emitMetadataTypeRefForKeyPath(*this,
1249+
component.getComponentType(),
1250+
pattern->getGenericSignature()));
12421251
}
12431252
baseTy = component.getComponentType();
12441253
}

lib/IRGen/GenMeta.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,11 +1683,14 @@ namespace {
16831683
}
16841684

16851685
void addUnderlyingTypeAndConformances() {
1686+
auto sig = O->getOpaqueInterfaceGenericSignature()
1687+
? O->getOpaqueInterfaceGenericSignature()->getCanonicalSignature()
1688+
: CanGenericSignature();
16861689
auto underlyingType = Type(O->getUnderlyingInterfaceType())
16871690
.subst(*O->getUnderlyingTypeSubstitutions())
1688-
->getCanonicalType(O->getOpaqueInterfaceGenericSignature());
1691+
->getCanonicalType(sig);
16891692

1690-
B.addRelativeAddress(IGM.getTypeRef(underlyingType,
1693+
B.addRelativeAddress(IGM.getTypeRef(underlyingType, sig,
16911694
MangledTypeRefRole::Metadata).first);
16921695

16931696
auto opaqueType = O->getDeclaredInterfaceType()

0 commit comments

Comments
 (0)