Skip to content

Commit 4ad7f3d

Browse files
committed
SILCombine: handle properties in superclasses in the keypath optimization
We ended up with invalid ref_element_addr instructions which let the SILVerifier crash. Inserting upcasts fixes this. rdar://problem/56410011
1 parent 1914417 commit 4ad7f3d

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,23 @@ static SILValue createKeypathProjections(SILValue keyPath, SILValue root,
600600
if (addr->getType().getStructOrBoundGenericStruct()) {
601601
addr = builder.createStructElementAddr(loc, addr, storedProperty);
602602
} else if (addr->getType().getClassOrBoundGenericClass()) {
603-
LoadInst *Ref = builder.createLoad(loc, addr,
603+
SingleValueInstruction *Ref = builder.createLoad(loc, addr,
604604
LoadOwnershipQualifier::Unqualified);
605605
insertEndAccess(beginAccess, /*isModify*/ false, builder);
606+
607+
// Handle the case where the storedProperty is in a super class.
608+
while (Ref->getType().getClassOrBoundGenericClass() !=
609+
storedProperty->getDeclContext()) {
610+
SILType superCl = Ref->getType().getSuperclass();
611+
if (!superCl) {
612+
// This should never happen, because the property should be in the
613+
// decl or in a superclass of it. Just handle this to be on the safe
614+
// side.
615+
return SILValue();
616+
}
617+
Ref = builder.createUpcast(loc, Ref, superCl);
618+
}
619+
606620
addr = builder.createRefElementAddr(loc, Ref, storedProperty);
607621

608622
// Class members need access enforcement.

test/SILOptimizer/optimize_keypath.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ final class GenClass<T : P> : P {
4141
}
4242
}
4343

44+
class Base<T> {
45+
final var i: Int = 12
46+
}
47+
48+
class DerivedClass<T> : Base<T> {
49+
}
50+
51+
final class DerivedClass2 : DerivedClass<Int> {
52+
}
53+
4454
final class SimpleClass : P {
4555
var i: Int
4656
static var numObjs = 0
@@ -97,6 +107,33 @@ func testGenClassRead<T>(_ c: GenClass<T>) -> T {
97107
return c[keyPath: kp]
98108
}
99109

110+
// CHECK-LABEL: sil {{.*}}testDerivedClassRead
111+
// CHECK: [[C:%[0-9]+]] = upcast %0
112+
// CHECK: [[E:%[0-9]+]] = ref_element_addr [[C]]
113+
// CHECK: [[A:%[0-9]+]] = begin_access [read] [dynamic] [no_nested_conflict] [[E]]
114+
// CHECK: [[V:%[0-9]+]] = load [[A]]
115+
// CHECK: end_access [[A]]
116+
// CHECK: return [[V]]
117+
@inline(never)
118+
@_semantics("optimize.sil.specialize.generic.never")
119+
func testDerivedClassRead<T>(_ c: DerivedClass<T>) -> Int {
120+
let kp = \DerivedClass<T>.i
121+
return c[keyPath: kp]
122+
}
123+
124+
// CHECK-LABEL: sil {{.*}}testDerivedClass2Read
125+
// CHECK: [[C:%[0-9]+]] = upcast %0
126+
// CHECK: [[E:%[0-9]+]] = ref_element_addr [[C]]
127+
// CHECK: [[A:%[0-9]+]] = begin_access [read] [dynamic] [no_nested_conflict] [[E]]
128+
// CHECK: [[V:%[0-9]+]] = load [[A]]
129+
// CHECK: end_access [[A]]
130+
// CHECK: return [[V]]
131+
@inline(never)
132+
func testDerivedClass2Read(_ c: DerivedClass2) -> Int {
133+
let kp = \DerivedClass2.i
134+
return c[keyPath: kp]
135+
}
136+
100137
// CHECK-LABEL: sil {{.*}}testGenClassWrite
101138
// CHECK: [[S:%[0-9]+]] = alloc_stack $T
102139
// CHECK: [[E:%[0-9]+]] = ref_element_addr %0
@@ -233,6 +270,12 @@ func testit() {
233270
// CHECK-OUTPUT: GenClassRead: 29
234271
print("GenClassRead: \(testGenClassRead(GenClass(SimpleClass(29))).i)")
235272

273+
// CHECK-OUTPUT: DerivedClassRead: 12
274+
print("DerivedClassRead: \(testDerivedClassRead(DerivedClass<Int>())))")
275+
276+
// CHECK-OUTPUT: DerivedClass2Read: 12
277+
print("DerivedClass2Read: \(testDerivedClass2Read(DerivedClass2())))")
278+
236279
// CHECK-OUTPUT: GenClassWrite: 30
237280
let c = GenClass(SimpleClass(0))
238281
testGenClassWrite(c, SimpleClass(30))

0 commit comments

Comments
 (0)