Skip to content

Commit c5900a6

Browse files
authored
Merge pull request #12434 from eeckstein/fix_atp
Demangler: fix demangling and remangling of associated type paths.
2 parents e0a97ed + e21b912 commit c5900a6

File tree

13 files changed

+75
-13
lines changed

13 files changed

+75
-13
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Globals
7474
global ::= protocol-conformance 'WP' // protocol witness table
7575

7676
global ::= protocol-conformance identifier 'Wt' // associated type metadata accessor
77-
global ::= protocol-conformance identifier nominal-type 'WT' // associated type witness table accessor
77+
global ::= protocol-conformance assoc_type_path nominal-type 'WT' // associated type witness table accessor
7878
global ::= type protocol-conformance 'Wl' // lazy protocol witness table accessor
7979
global ::= type 'WV' // value witness table
8080
global ::= entity 'Wv' DIRECTNESS // field offset
@@ -84,6 +84,8 @@ Globals
8484
global ::= type 'Wr' // Outlined Retain Function Type
8585
global ::= type 'Ws' // Outlined Release Function Type
8686

87+
assoc_type_path ::= identifier '_' identifier*
88+
8789
DIRECTNESS ::= 'd' // direct
8890
DIRECTNESS ::= 'i' // indirect
8991

include/swift/Basic/Mangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class Mangler {
111111
static void verify(StringRef mangledName);
112112
static void verifyOld(StringRef mangledName);
113113

114+
void dump();
115+
114116
/// Appends a mangled identifier string.
115117
void appendIdentifier(StringRef ident);
116118

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,5 +189,6 @@ NODE(OutlinedConsume)
189189
NODE(OutlinedRetain)
190190
NODE(OutlinedRelease)
191191
NODE(OutlinedVariable)
192+
NODE(AssocTypePath)
192193
#undef CONTEXT_NODE
193194
#undef NODE

lib/Basic/Mangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ void Mangler::appendIdentifier(StringRef ident) {
239239
recordOpStat("<identifier>", OldPos);
240240
}
241241

242+
void Mangler::dump() {
243+
llvm::errs() << Buffer.str() << '\n';
244+
}
245+
242246
bool Mangler::tryMangleSubstitution(const void *ptr) {
243247
auto ir = Substitutions.find(ptr);
244248
if (ir == Substitutions.end())

lib/Demangling/Demangler.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,10 +1653,20 @@ NodePointer Demangler::demangleWitness() {
16531653
}
16541654
case 'T': {
16551655
NodePointer ProtoTy = popNode(Node::Kind::Type);
1656-
NodePointer Name = popNode(isDeclName);
1656+
NodePointer AssocTypePath = createNode(Node::Kind::AssocTypePath);
1657+
bool firstElem = false;
1658+
do {
1659+
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
1660+
NodePointer AssocTyName = popNode(isDeclName);
1661+
if (!AssocTyName)
1662+
return nullptr;
1663+
AssocTypePath->addChild(AssocTyName, *this);
1664+
} while (!firstElem);
1665+
AssocTypePath->reverseChildren();
1666+
16571667
NodePointer Conf = popProtocolConformance();
16581668
return createWithChildren(Node::Kind::AssociatedTypeWitnessTableAccessor,
1659-
Conf, Name, ProtoTy);
1669+
Conf, AssocTypePath, ProtoTy);
16601670
}
16611671
case 'y': {
16621672
return createWithChild(Node::Kind::OutlinedCopy,

lib/Demangling/NodePrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ class NodePrinter {
416416
case Node::Kind::OutlinedRetain:
417417
case Node::Kind::OutlinedRelease:
418418
case Node::Kind::OutlinedVariable:
419+
case Node::Kind::AssocTypePath:
419420
return false;
420421
}
421422
printer_unreachable("bad node kind");
@@ -1779,6 +1780,9 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
17791780
&& Node->getChild(0)->getKind() == Node::Kind::Type);
17801781
print(Node->getChild(0));
17811782
return nullptr;
1783+
case Node::Kind::AssocTypePath:
1784+
printChildren(Node->begin(), Node->end(), ".");
1785+
return nullptr;
17821786
}
17831787
printer_unreachable("bad node kind!");
17841788
}

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,10 @@ void Remangler::mangleSILBoxImmutableField(Node *node) {
17971797
mangleType(node->getChild(0));
17981798
}
17991799

1800+
void Remangler::mangleAssocTypePath(Node *node) {
1801+
unreachable("unsupported");
1802+
}
1803+
18001804
/// The top-level interface to the remangler.
18011805
std::string Demangle::mangleNodeOld(const NodePointer &node) {
18021806
if (!node) return "";

lib/Demangling/Remangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,14 @@ void Remangler::mangleSILBoxImmutableField(Node *node) {
17991799
unreachable("should be part of SILBoxTypeWithLayout");
18001800
}
18011801

1802+
void Remangler::mangleAssocTypePath(Node *node) {
1803+
bool FirstElem = true;
1804+
for (NodePointer Child : *node) {
1805+
mangle(Child);
1806+
mangleListSeparator(FirstElem);
1807+
}
1808+
}
1809+
18021810
} // anonymous namespace
18031811

18041812
/// The top-level interface to the remangler.

lib/IRGen/IRGenMangler.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,18 @@ class IRGenMangler : public Mangle::ASTMangler {
113113
const ProtocolDecl *Proto) {
114114
beginMangling();
115115
appendProtocolConformance(Conformance);
116-
appendAssociatedTypePath(AssociatedType);
116+
bool isFirstAssociatedTypeIdentifier = true;
117+
appendAssociatedTypePath(AssociatedType, isFirstAssociatedTypeIdentifier);
117118
appendAnyGenericType(Proto);
118119
appendOperator("WT");
119120
return finalize();
120121
}
121122

122-
void appendAssociatedTypePath(CanType associatedType) {
123+
void appendAssociatedTypePath(CanType associatedType, bool &isFirst) {
123124
if (auto memberType = dyn_cast<DependentMemberType>(associatedType)) {
124-
appendAssociatedTypePath(memberType.getBase());
125+
appendAssociatedTypePath(memberType.getBase(), isFirst);
125126
appendIdentifier(memberType->getName().str());
127+
appendListSeparator(isFirst);
126128
} else {
127129
assert(isa<GenericTypeParamType>(associatedType));
128130
}

test/Demangle/Inputs/manglings.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,4 @@ _T0So11UITextFieldC4textSSSgvgToTepb_ ---> outlined bridged method (pb) of @objc
271271
_T0So11UITextFieldC4textSSSgvgToTeab_ ---> outlined bridged method (ab) of @objc __ObjC.UITextField.text.getter : Swift.String?
272272
_T0So5GizmoC11doSomethingSQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
273273
_T0So5GizmoC12modifyStringSQySSGAD_Si10withNumberSQyypG0D6FoobartFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
274+
_T04test1SVyxGAA1RA2A1ZRzAA1Y2ZZRpzl1A_AhaGPWT ---> {C} associated type witness table accessor for A.ZZ : test.Y in <A where A: test.Z, A.ZZ: test.Y> test.S<A> : test.R in test

test/IRGen/associated_type_witness.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ struct GenericWithUniversal<T> : Assocked {
4141
// Witness table for Fulfilled : Assocked.
4242
// GLOBAL-LABEL: @_T023associated_type_witness9FulfilledVyxGAA8AssockedAAWP = hidden constant [3 x i8*] [
4343
// GLOBAL-SAME: i8* bitcast (%swift.type* (%swift.type*, i8**)* @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocWt to i8*)
44-
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAA1PPWT to i8*)
45-
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAA1QPWT to i8*)
44+
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5Assoc_AA1PPWT to i8*)
45+
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5Assoc_AA1QPWT to i8*)
4646
// GLOBAL-SAME: ]
4747
struct Fulfilled<T : P & Q> : Assocked {
4848
typealias Assoc = T
@@ -56,14 +56,14 @@ struct Fulfilled<T : P & Q> : Assocked {
5656
// CHECK-NEXT: ret %swift.type* [[T2]]
5757

5858
// Associated type witness table access function for Fulfilled.Assoc : P.
59-
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAA1PPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
59+
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5Assoc_AA1PPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
6060
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
6161
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 3
6262
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
6363
// CHECK-NEXT: ret i8** [[T2]]
6464

6565
// Associated type witness table access function for Fulfilled.Assoc : Q.
66-
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAA1QPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
66+
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedAA5Assoc_AA1QPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
6767
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
6868
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 4
6969
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
@@ -74,8 +74,8 @@ struct Pair<T, U> : P, Q {}
7474
// Generic witness table pattern for Computed : Assocked.
7575
// GLOBAL-LABEL: @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAAWP = hidden constant [3 x i8*] [
7676
// GLOBAL-SAME: i8* bitcast (%swift.type* (%swift.type*, i8**)* @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAA5AssocWt to i8*)
77-
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAA5AssocAA1PPWT to i8*)
78-
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAA5AssocAA1QPWT to i8*)
77+
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAA5Assoc_AA1PPWT to i8*)
78+
// GLOBAL-SAME: i8* bitcast (i8** (%swift.type*, %swift.type*, i8**)* @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAA5Assoc_AA1QPWT to i8*)
7979
// GLOBAL-SAME: ]
8080
// Generic witness table cache for Computed : Assocked.
8181
// GLOBAL-LABEL: @_T023associated_type_witness8ComputedVyxq_GAA8AssockedAAWG = internal constant %swift.generic_witness_table_cache {

test/IRGen/assoctypepath.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s
2+
3+
// Check that we can mangle+demangle the associated type witness table accessor
4+
// and do not crash
5+
6+
protocol V {}
7+
protocol W: V {}
8+
protocol X: W {}
9+
protocol Y: X {}
10+
protocol Z: W {
11+
associatedtype ZZ: X
12+
}
13+
14+
protocol P {
15+
associatedtype A: W
16+
}
17+
protocol Q: P where A: Z {}
18+
protocol R: Q where A.ZZ: Y {}
19+
20+
// CHECK: define {{.*}} @_T013assoctypepath1SVyxGAA1RAA1A_2ZZAA1YPWT
21+
22+
struct S<T>: R where T: Z, T.ZZ: Y {
23+
typealias A = T
24+
}

test/IRGen/same_type_constraints.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,5 @@ where Self : CodingType,
6060
print(Self.ValueType.self)
6161
}
6262

63-
// OSIZE: define internal i8** @_T021same_type_constraints12GenericKlazzCyxq_GAA1EAA4DataAA0F4TypePWT(%swift.type* %"GenericKlazz<T, R>.Data", %swift.type* nocapture readonly %"GenericKlazz<T, R>", i8** nocapture readnone %"GenericKlazz<T, R>.E") [[ATTRS:#[0-9]+]] {
63+
// OSIZE: define internal i8** @_T021same_type_constraints12GenericKlazzCyxq_GAA1EAA4Data_AA0F4TypePWT(%swift.type* %"GenericKlazz<T, R>.Data", %swift.type* nocapture readonly %"GenericKlazz<T, R>", i8** nocapture readnone %"GenericKlazz<T, R>.E") [[ATTRS:#[0-9]+]] {
6464
// OSIZE: [[ATTRS]] = {{{.*}}noinline

0 commit comments

Comments
 (0)