Skip to content

Commit 2d377a4

Browse files
committed
SIL: Serialization for external key path components
1 parent b00ea61 commit 2d377a4

File tree

4 files changed

+80
-7
lines changed

4 files changed

+80
-7
lines changed

lib/Serialization/DeserializeSIL.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2247,7 +2247,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
22472247
}
22482248

22492249
indices = MF->getContext().AllocateCopy(indicesBuf);
2250-
if (!indices.empty()) {
2250+
if (!indices.empty() &&
2251+
kind != KeyPathComponentKindEncoding::External) {
22512252
auto indicesEqualsName = MF->getIdentifier(ListOfValues[nextValue++]);
22522253
auto indicesHashName = MF->getIdentifier(ListOfValues[nextValue++]);
22532254
indicesEquals = getFuncForReference(indicesEqualsName.str());
@@ -2296,6 +2297,21 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
22962297
components.push_back(KeyPathPatternComponent::forOptional(
22972298
KeyPathPatternComponent::Kind::OptionalWrap, type));
22982299
break;
2300+
case KeyPathComponentKindEncoding::External: {
2301+
auto declID = ListOfValues[nextValue++];
2302+
auto decl = cast<AbstractStorageDecl>(MF->getDecl(declID));
2303+
auto numComponentSubstitutions = ListOfValues[nextValue++];
2304+
SmallVector<Substitution, 4> subs;
2305+
while (numComponentSubstitutions-- > 0) {
2306+
auto sub = MF->maybeReadSubstitution(SILCursor);
2307+
subs.push_back(*sub);
2308+
}
2309+
handleComputedIndices();
2310+
components.push_back(
2311+
KeyPathPatternComponent::forExternal(decl,
2312+
MF->getContext().AllocateCopy(subs), indices, type));
2313+
break;
2314+
}
22992315
}
23002316
}
23012317

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum class KeyPathComponentKindEncoding : uint8_t {
8484
OptionalChain,
8585
OptionalForce,
8686
OptionalWrap,
87+
External,
8788
};
8889
enum class KeyPathComputedComponentIdKindEncoding : uint8_t {
8990
Property,

lib/Serialization/SerializeSIL.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,7 +1915,25 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
19151915
ListOfValues.push_back(0);
19161916
}
19171917

1918-
SmallVector<ProtocolConformanceRef, 4> hashableConformances;
1918+
// Some components need to serialize additional Substitutions or
1919+
// ProtocolConformances after the main record is emitted.
1920+
struct ConformanceOrSubstitution {
1921+
enum { ProtocolConformance, SubstitutionList } Kind;
1922+
union {
1923+
swift::ProtocolConformanceRef Conformance;
1924+
swift::SubstitutionList Substitutions;
1925+
};
1926+
1927+
ConformanceOrSubstitution(ProtocolConformanceRef c)
1928+
: Kind(ProtocolConformance), Conformance(c)
1929+
{}
1930+
1931+
ConformanceOrSubstitution(swift::SubstitutionList s)
1932+
: Kind(SubstitutionList), Substitutions(s)
1933+
{}
1934+
};
1935+
SmallVector<ConformanceOrSubstitution, 4> serializeAfter;
1936+
SmallVector<SubstitutionList, 4> externalSubstitutions;
19191937

19201938
for (auto &component : pattern->getComponents()) {
19211939
auto handleComponentCommon = [&](KeyPathComponentKindEncoding kind) {
@@ -1951,9 +1969,10 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
19511969
ListOfValues.push_back(
19521970
S.addTypeRef(index.LoweredType.getSwiftRValueType()));
19531971
ListOfValues.push_back((unsigned)index.LoweredType.getCategory());
1954-
hashableConformances.push_back(index.Hashable);
1972+
serializeAfter.push_back(index.Hashable);
19551973
}
1956-
if (!indices.empty()) {
1974+
if (!indices.empty() &&
1975+
component.getKind() != KeyPathPatternComponent::Kind::External) {
19571976
ListOfValues.push_back(
19581977
addSILFunctionRef(component.getSubscriptIndexEquals()));
19591978
ListOfValues.push_back(
@@ -1992,7 +2011,12 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
19922011
handleComponentCommon(KeyPathComponentKindEncoding::OptionalWrap);
19932012
break;
19942013
case KeyPathPatternComponent::Kind::External:
1995-
llvm_unreachable("todo");
2014+
handleComponentCommon(KeyPathComponentKindEncoding::External);
2015+
ListOfValues.push_back(S.addDeclRef(component.getExternalDecl()));
2016+
ListOfValues.push_back(component.getExternalSubstitutions().size());
2017+
serializeAfter.push_back(component.getExternalSubstitutions());
2018+
handleComputedIndices(component);
2019+
break;
19962020
}
19972021
}
19982022

@@ -2008,8 +2032,15 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
20082032
S.addTypeRef(KPI->getType().getSwiftRValueType()),
20092033
(unsigned)KPI->getType().getCategory(),
20102034
ListOfValues);
2011-
for (auto conformance : hashableConformances) {
2012-
S.writeConformance(conformance, SILAbbrCodes);
2035+
for (auto &confOrSub : serializeAfter) {
2036+
switch (confOrSub.Kind) {
2037+
case ConformanceOrSubstitution::ProtocolConformance:
2038+
S.writeConformance(confOrSub.Conformance, SILAbbrCodes);
2039+
break;
2040+
case ConformanceOrSubstitution::SubstitutionList:
2041+
S.writeSubstitutions(confOrSub.Substitutions, SILAbbrCodes);
2042+
break;
2043+
}
20132044
}
20142045
S.writeGenericRequirements(reqts, SILAbbrCodes);
20152046
S.writeSubstitutions(KPI->getSubstitutions(), SILAbbrCodes);

test/SIL/Serialization/keypath.sil

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ struct Gen<A: P, B: Q, C: R> {
4141
var z: C
4242
}
4343

44+
public struct External<T> {
45+
var ro: T { get }
46+
47+
subscript<U: Hashable>(ro _: U) -> T { get }
48+
}
49+
4450
// CHECK-LABEL: sil shared [serialized] @stored_properties
4551
sil shared [serialized] @stored_properties : $@convention(thin) () -> () {
4652
entry:
@@ -140,6 +146,24 @@ entry(%s : $S, %c : $C):
140146
return undef : $()
141147
}
142148

149+
// CHECK-LABEL: sil shared [serialized] @external
150+
sil shared [serialized] @external : $@convention(thin) <A, B: Hashable> (@in B) -> () {
151+
entry(%z : $*B):
152+
// CHECK: %1 = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
153+
%a = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
154+
155+
// CHECK: %2 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1, τ_0_2> (root $External<τ_0_2>; external #External.ro<τ_0_2> : $τ_0_2) <A, A, A>
156+
%b = keypath $KeyPath<External<A>, A>, <C, D, E> (root $External<E>; external #External.ro <E> : $E) <A, A, A>
157+
158+
// CHECK: %3 = keypath $KeyPath<External<Int>, Int>, <τ_0_0> (root $External<τ_0_0>; external #External.ro<τ_0_0> : $τ_0_0) <Int>
159+
%c = keypath $KeyPath<External<Int>, Int>, <F> (root $External<F>; external #External.ro <F> : $F) <Int>
160+
161+
// CHECK: %4 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.subscript<τ_0_1, τ_0_0>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1) <B, A> (%0)
162+
%d = keypath $KeyPath<External<A>, A>, <G: Hashable, H> (root $External<H>; external #External.subscript <H, G> [%$0 : $G : $*G] : $H) <B, A> (%z)
163+
164+
return undef : $()
165+
}
166+
143167
sil [serialized] @serialize_all : $@convention(thin) () -> () {
144168
entry:
145169
%0 = function_ref @stored_properties : $@convention(thin) () -> ()
@@ -148,6 +172,7 @@ entry:
148172
%3 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
149173
%4 = function_ref @optional : $@convention(thin) () -> ()
150174
%5 = function_ref @indexes : $@convention(thin) (S, C) -> ()
175+
%6 = function_ref @external : $@convention(thin) <A, B: Hashable> (@in B) -> ()
151176

152177
unreachable
153178
}

0 commit comments

Comments
 (0)