Skip to content

Commit 8d2fbbf

Browse files
committed
[IRGen] Emit base protocol witnesses as mangled names.
Rather than setting the witness tables for base protocols in a witness table’s instantiation function, use mangled names as we do for associated conformances. The runtime will eagerly realize them so clients of witness tables are not affected. For now, only do this for unconditional conformances: conditional conformances won’t work yet because the instantiation function currently copies the instantiation arguments (which satisfy the conditional requirements) in to the private area. The runtime will need to take over this responsibility for conditional conformances to work. Part of rdar://problem/46282080. (cherry picked from commit 3fce389)
1 parent e85375d commit 8d2fbbf

File tree

4 files changed

+36
-27
lines changed

4 files changed

+36
-27
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -995,14 +995,9 @@ static bool hasDependentTypeWitness(
995995
return false;
996996
}
997997

998-
static bool hasDependentTypeWitness(const RootProtocolConformance *root) {
999-
if (auto normal = dyn_cast<NormalProtocolConformance>(root))
1000-
return hasDependentTypeWitness(normal);
1001-
return false; // no associated types
1002-
}
1003-
1004998
static bool isDependentConformance(
1005999
const RootProtocolConformance *rootConformance,
1000+
bool considerResilience,
10061001
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> &visited){
10071002
// Self-conformances are never dependent.
10081003
auto conformance = dyn_cast<NormalProtocolConformance>(rootConformance);
@@ -1015,7 +1010,7 @@ static bool isDependentConformance(
10151010
return false;
10161011

10171012
// If the conformance is resilient, this is always true.
1018-
if (isResilientConformance(conformance))
1013+
if (considerResilience && isResilientConformance(conformance))
10191014
return true;
10201015

10211016
// Check whether any of the conformances are dependent.
@@ -1033,6 +1028,7 @@ static bool isDependentConformance(
10331028
if (assocConformance.isAbstract() ||
10341029
isDependentConformance(assocConformance.getConcrete()
10351030
->getRootConformance(),
1031+
considerResilience,
10361032
visited))
10371033
return true;
10381034
}
@@ -1048,9 +1044,10 @@ static bool isDependentConformance(
10481044

10491045
/// Is there anything about the given conformance that requires witness
10501046
/// tables to be dependently-generated?
1051-
static bool isDependentConformance(const RootProtocolConformance *conformance) {
1047+
static bool isDependentConformance(const RootProtocolConformance *conformance,
1048+
bool considerResilience) {
10521049
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
1053-
return ::isDependentConformance(conformance, visited);
1050+
return ::isDependentConformance(conformance, considerResilience, visited);
10541051
}
10551052

10561053
static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
@@ -1349,6 +1346,25 @@ class AccessorConformanceInfo : public ConformanceInfo {
13491346
return;
13501347
}
13511348

1349+
// If this isn't a conditional conformance, we can emit a mangled name.
1350+
// FIXME: Conditional conformances won't currently work because the
1351+
// witness tables for conditional requirements won't have been written
1352+
// into the private area yet.
1353+
if (SILConditionalConformances.empty()) {
1354+
if (isDependentConformance(astConf->getRootConformance(),
1355+
/*considerResilience=*/false))
1356+
RequiresSpecialization = true;
1357+
1358+
auto proto = Conformance.getProtocol();
1359+
CanType selfType = proto->getProtocolSelfType()->getCanonicalType();
1360+
AssociatedConformance requirement(proto, selfType, baseProto);
1361+
llvm::Constant *witnessEntry =
1362+
getAssociatedConformanceWitness(requirement, ConcreteType,
1363+
ProtocolConformanceRef(astConf));
1364+
Table.addBitCast(witnessEntry, IGM.Int8PtrTy);
1365+
return;
1366+
}
1367+
13521368
// Otherwise, we'll need to derive it at instantiation time.
13531369
RequiresSpecialization = true;
13541370
SpecializedBaseConformances.push_back({Table.size(), &conf});
@@ -2152,7 +2168,7 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
21522168
// so in theory we could allocate them on a BumpPtrAllocator. But there's not
21532169
// a good one for us to use. (The ASTContext's outlives the IRGenModule in
21542170
// batch mode.)
2155-
if (isDependentConformance(rootConformance) ||
2171+
if (isDependentConformance(rootConformance, /*considerResilience=*/true) ||
21562172
// Foreign types need to go through the accessor to unique the witness
21572173
// table.
21582174
isSynthesizedNonUnique(rootConformance)) {
@@ -2220,7 +2236,7 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
22202236
// Produce the initializer value.
22212237
auto initializer = wtableContents.finishAndCreateFuture();
22222238

2223-
bool isDependent = isDependentConformance(conf);
2239+
bool isDependent = isDependentConformance(conf, /*considerResilience=*/true);
22242240
auto global = cast<llvm::GlobalVariable>(
22252241
isDependent
22262242
? getAddrOfWitnessTablePattern(cast<NormalProtocolConformance>(conf),
@@ -2235,7 +2251,9 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
22352251
wtableBuilder.getTableSize(),
22362252
wtableBuilder.getTablePrivateSize(),
22372253
wtableBuilder.requiresSpecialization(),
2238-
hasDependentTypeWitness(conf));
2254+
isDependentConformance(
2255+
conf,
2256+
/*considerResilience=*/false));
22392257

22402258
// Build the instantiation function, we if need one.
22412259
description.instantiationFn = wtableBuilder.buildInstantiationFunction();

test/IRGen/associated_type_witness.swift

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,6 @@ struct Computed<T, U> : Assocked {
9797
typealias Assoc = Pair<T, U>
9898
}
9999

100-
// Instantiation function for GenericComputed : DerivedFromSimpleAssoc.
101-
// CHECK-LABEL: define internal void @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI"(i8**, %swift.type* %"GenericComputed<T>", i8**)
102-
// CHECK: [[T0:%.*]] = call i8** @swift_getWitnessTable({{.*}}@"$s23associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAMc"
103-
// CHECK-NEXT: [[T1:%.*]] = bitcast i8** [[T0]] to i8*
104-
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8*, i8** %0, i32 1
105-
// CHECK-NEXT: store i8* [[T1]], i8** [[T2]], align 8
106-
// CHECK-NEXT: ret void
107-
108-
109100
struct PBox<T: P> {}
110101
protocol HasSimpleAssoc {
111102
associatedtype Assoc
@@ -115,7 +106,7 @@ protocol DerivedFromSimpleAssoc : HasSimpleAssoc {}
115106
// Generic witness table pattern for GenericComputed : DerivedFromSimpleAssoc.
116107
// GLOBAL-LABEL: @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWp" = internal constant [2 x i8*]
117108
// GLOBAL-SAME: @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAMc"
118-
// GLOBAL-SAME: i8* null
109+
// GLOBAL-SAME: @"associated conformance 23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocA2A03HashI0"
119110

120111
// Relative reference to private data
121112
struct GenericComputed<T: P> : DerivedFromSimpleAssoc {
@@ -146,7 +137,7 @@ struct UsesVoid : HasSimpleAssoc {
146137
// Protocol conformance descriptor for GenericComputed : DerivedFromSimpleAssoc.
147138
// GLOBAL-LABEL: @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAMc" = hidden constant
148139
// GLOBAL-SAME: i16 2,
149-
// GLOBAL-SAME: i16 0,
140+
// GLOBAL-SAME: i16 1,
150141

151-
// Relative reference to instantiator function
152-
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint (void (i8**, %swift.type*, i8**)* @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI" to i64),
142+
// No instantiator function needed
143+
// GLOBAL-SAME: i32 0

test/IRGen/deserialize-clang-importer-witness-tables.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public func foo(line: String) {
99
// from the default argument expression passed to `RegEx(pattern:options:)`
1010
// below. Ensure that a local copy of the definition was deserialized
1111
// and lowered to IR.
12-
// CHECK-LABEL: define {{.*}} void @"$sSo26NSRegularExpressionOptionsVs10SetAlgebraSCsACPxycfCTW"
1312
// CHECK-LABEL: define {{.*}} i8** @"$sSo26NSRegularExpressionOptionsVABSQSCWl"()
13+
// CHECK-LABEL: define {{.*}} void @"$sSo26NSRegularExpressionOptionsVs10SetAlgebraSCsACPxycfCTW"
1414
let versionRegex = try! RegEx(pattern: "Apple")
1515
_ = versionRegex.firstMatch(in: line)
1616
}

test/IRGen/generic_wt_linkage.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ sil_default_witness_table hidden DerivedFromSimpleAssoc {
4444
no_default
4545
}
4646

47-
// CHECK: define internal void @"$s4test15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI"
47+
// CHECK: define internal swiftcc i8** @"$s4test15GenericComputedVyxGAA22DerivedFromSimpleAssocAAxAA03HasfG0PWT"
4848

4949

0 commit comments

Comments
 (0)