Skip to content

Commit 78c9cfa

Browse files
committed
[Runtime] Have the runtime copy instantiation arguments into private data.
Rather than having the witness table instantiation function copy the instantiation arguments that corresponding to conditional requirements into the private area, have the runtime do it. We’re going to depend on these lining up anyway (and the witness table can of course have *more* private slots that it manages some other way), so centralize the code. More of rdar://problem/46282080. (cherry picked from commit 19941d3)
1 parent 8d2fbbf commit 78c9cfa

File tree

5 files changed

+24
-94
lines changed

5 files changed

+24
-94
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
14891489

14901490
private:
14911491
void addConditionalConformances() {
1492+
assert(NextPrivateDataIndex == 0);
14921493
for (auto conditional : SILConditionalConformances) {
14931494
// We don't actually need to know anything about the specific
14941495
// conformances here, just make sure we get right private data slots.
@@ -1788,10 +1789,9 @@ void WitnessTableBuilder::collectResilientWitnesses(
17881789
}
17891790

17901791
llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
1791-
// We need an instantiation function if the base conformance
1792+
// We need an instantiation function if any base conformance
17921793
// is non-dependent.
1793-
if (SpecializedBaseConformances.empty() &&
1794-
ConditionalRequirementPrivateDataIndices.empty())
1794+
if (SpecializedBaseConformances.empty())
17951795
return nullptr;
17961796

17971797
assert(isa<NormalProtocolConformance>(Conformance) &&
@@ -1819,19 +1819,12 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
18191819
IGF.IGM.WitnessTablePtrPtrTy),
18201820
PointerAlignment);
18211821

1822-
/// Run through the conditional conformance witness tables, pulling them out
1823-
/// of the slice and putting them into the private data of the witness table.
1822+
// Register local type data for the conditional conformance witness tables.
18241823
for (auto idx : indices(ConditionalRequirementPrivateDataIndices)) {
18251824
Address conditionalTablePtr =
18261825
IGF.Builder.CreateConstArrayGEP(conditionalTables, idx, PointerSize);
1827-
Address slot = getAddressOfPrivateDataSlot(
1828-
IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
18291826
auto conditionalTable = IGF.Builder.CreateLoad(conditionalTablePtr);
1830-
auto coercedSlot =
1831-
IGF.Builder.CreateElementBitCast(slot, conditionalTable->getType());
1832-
IGF.Builder.CreateStore(conditionalTable, coercedSlot);
18331827

1834-
// Register local type data for the conditional conformance witness table.
18351828
const auto &condConformance = SILConditionalConformances[idx];
18361829
CanType reqTypeInContext =
18371830
Conformance.getDeclContext()

stdlib/public/runtime/Metadata.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4058,6 +4058,26 @@ WitnessTableCacheEntry::allocate(
40584058
table[i] = pattern[i];
40594059
}
40604060

4061+
// Copy any instantiation arguments that correspond to conditional
4062+
// requirements into the private area.
4063+
{
4064+
unsigned currentInstantiationArg = 0;
4065+
auto copyNextInstantiationArg = [&] {
4066+
assert(currentInstantiationArg < privateSizeInWords);
4067+
table[-1 - (int)currentInstantiationArg] =
4068+
const_cast<void *>(instantiationArgs[currentInstantiationArg]);
4069+
++currentInstantiationArg;
4070+
};
4071+
4072+
for (const auto &conditionalRequirement
4073+
: conformance->getConditionalRequirements()) {
4074+
if (conditionalRequirement.Flags.hasKeyArgument())
4075+
copyNextInstantiationArg();
4076+
if (conditionalRequirement.Flags.hasExtraArgument())
4077+
copyNextInstantiationArg();
4078+
}
4079+
}
4080+
40614081
// Fill in any default requirements.
40624082
initializeResilientWitnessTable(conformance, genericTable, table);
40634083
auto castTable = reinterpret_cast<WitnessTable*>(table);

test/Inputs/conditional_conformance_basic_conformances.swift

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -238,44 +238,6 @@ public func double_concrete_concrete() {
238238
// CHECK-NEXT: }
239239

240240

241-
// # Witness table instantiators
242-
243-
// witness table instantiator for Single : P1
244-
245-
// CHECK-LABEL: define internal void @"$s42conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWI"(i8**, %swift.type* %"Single<A>", i8**)
246-
// CHECK-NEXT: entry:
247-
// CHECK-NEXT: [[TABLES:%.*]] = bitcast i8** %1 to i8***
248-
249-
// CHECK-NEXT: [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
250-
// CHECK-NEXT: [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
251-
// CHECK-NEXT: [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
252-
// CHECK-NEXT: [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
253-
// CHECK-NEXT: store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
254-
255-
// CHECK-NEXT: ret void
256-
// CHECK-NEXT: }
257-
258-
// witness table instantiator for Double : P1
259-
260-
// CHECK-LABEL: define internal void @"$s42conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWI"(i8**, %swift.type* %"Double<B, C>", i8**)
261-
// CHECK-NEXT: entry:
262-
// CHECK-NEXT: [[TABLES:%.*]] = bitcast i8** %1 to i8***
263-
264-
// CHECK-NEXT: [[B_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
265-
// CHECK-NEXT: [[B_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
266-
// CHECK-NEXT: [[B_P2:%.*]] = load i8**, i8*** [[B_P2_SRC]], align 8
267-
// CHECK-NEXT: [[CAST_B_P2_DEST:%.*]] = bitcast i8** [[B_P2_DEST]] to i8***
268-
// CHECK-NEXT: store i8** [[B_P2]], i8*** [[CAST_B_P2_DEST]], align 8
269-
270-
// CHECK-NEXT: [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
271-
// CHECK-NEXT: [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
272-
// CHECK-NEXT: [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
273-
// CHECK-NEXT: [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
274-
// CHECK-NEXT: store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
275-
276-
// CHECK-NEXT: ret void
277-
// CHECK-NEXT: }
278-
279241
func dynamicCastToP1(_ value: Any) -> P1? {
280242
return value as? P1
281243
}

test/Inputs/conditional_conformance_subclass.swift

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,3 @@ public func subclassgenericconcrete() {
166166
// CHECK-NEXT: [[T0:%.*]] = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
167167
// CHECK-NEXT: ret i8** [[T0]]
168168
// CHECK-NEXT: }
169-
170-
171-
// witness tabel instantiation function for Base : P1
172-
173-
// CHECK-LABEL: define internal void @"$s32conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWI"(i8**, %swift.type* %"Base<A>", i8**)
174-
// CHECK-NEXT: entry:
175-
// CHECK-NEXT: [[TABLES:%.*]] = bitcast i8** %1 to i8***
176-
177-
// CHECK-NEXT: [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
178-
// CHECK-NEXT: [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
179-
// CHECK-NEXT: [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
180-
// CHECK-NEXT: [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
181-
// CHECK-NEXT: store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
182-
183-
// CHECK-NEXT: ret void
184-
// CHECK-NEXT: }
185-
186-

test/Inputs/conditional_conformance_with_assoc.swift

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -220,33 +220,6 @@ public func concrete_concrete() {
220220

221221

222222

223-
// witness table instantiator for Double : P1
224-
225-
// CHECK-LABEL: define internal void @"$s34conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWI"(i8**, %swift.type* %"Double<B, C>", i8**)
226-
// CHECK-NEXT: entry:
227-
// CHECK-NEXT: [[TABLES:%.*]] = bitcast i8** %1 to i8***
228-
229-
// CHECK-NEXT: [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
230-
// CHECK-NEXT: [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
231-
// CHECK-NEXT: [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
232-
// CHECK-NEXT: [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
233-
// CHECK-NEXT: store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
234-
235-
// CHECK-NEXT: [[B_AT2_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
236-
// CHECK-NEXT: [[B_AT2_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
237-
// CHECK-NEXT: [[B_AT2_P2:%.*]] = load i8**, i8*** [[B_AT2_P2_SRC]], align 8
238-
// CHECK-NEXT: [[CAST_B_AT2_P2_DEST:%.*]] = bitcast i8** [[B_AT2_P2_DEST]] to i8***
239-
// CHECK-NEXT: store i8** [[B_AT2_P2]], i8*** [[CAST_B_AT2_P2_DEST]], align 8
240-
241-
// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 2
242-
// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -3
243-
// CHECK-NEXT: [[B_AT2_AT2_AT3_P3:%.*]] = load i8**, i8*** [[B_AT2_AT2_AT3_P3_SRC]], align 8
244-
// CHECK-NEXT: [[CAST_B_AT2_AT2_AT3_P3_DEST:%.*]] = bitcast i8** [[B_AT2_AT2_AT3_P3_DEST]] to i8***
245-
// CHECK-NEXT: store i8** [[B_AT2_AT2_AT3_P3]], i8*** [[CAST_B_AT2_AT2_AT3_P3_DEST]], align 8
246-
247-
// CHECK-NEXT: ret void
248-
// CHECK-NEXT: }
249-
250223
protocol Base {
251224
}
252225

0 commit comments

Comments
 (0)