Skip to content

Commit 3269b9a

Browse files
authored
Merge pull request #13718 from slavapestov/class-resilience-part-12
Class resilience part 12
2 parents ceba366 + 82d0af2 commit 3269b9a

10 files changed

+318
-14
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,11 +2952,6 @@ namespace {
29522952
return B.getNextOffsetFromGlobal() - TemplateHeaderSize;
29532953
}
29542954

2955-
/// Ignore the destructor and value witness table.
2956-
Size getNextOffsetFromAddressPoint() const {
2957-
return getNextOffsetFromTemplateHeader() - AddressPoint;
2958-
}
2959-
29602955
template <class... T>
29612956
void addGenericArgument(CanType type, T &&...args) {
29622957
FillOps.push_back({type, None});
@@ -3209,7 +3204,6 @@ namespace {
32093204

32103205
public:
32113206
void noteResilientSuperclass() {
3212-
// FIXME: Perform sliding
32133207
HasResilientSuperclass = true;
32143208
}
32153209

@@ -3239,8 +3233,10 @@ namespace {
32393233

32403234
// Otherwise, we know the offset at compile time, even if our
32413235
// clients do not, so just emit a constant.
3242-
auto value = asImpl().getNextOffsetFromAddressPoint().getValue();
3243-
auto *init = llvm::ConstantInt::get(IGM.SizeTy, value);
3236+
auto &layout = IGM.getMetadataLayout(theClass);
3237+
3238+
auto value = layout.getStartOfImmediateMembers();
3239+
auto *init = llvm::ConstantInt::get(IGM.SizeTy, value.getValue());
32443240

32453241
offsetVar->setInitializer(init);
32463242
offsetVar->setConstant(true);
@@ -3518,13 +3514,15 @@ namespace {
35183514
Address sizeSlot = IGF.Builder.CreateConstByteArrayGEP(
35193515
metadataAsBytes,
35203516
layout.getMetadataSizeOffset());
3521-
sizeSlot = IGF.Builder.CreateBitCast(sizeSlot, IGM.Int32Ty->getPointerTo());
3517+
sizeSlot = IGF.Builder.CreateBitCast(sizeSlot,
3518+
IGM.Int32Ty->getPointerTo());
35223519
llvm::Value *size = IGF.Builder.CreateLoad(sizeSlot);
35233520

35243521
Address addressPointSlot = IGF.Builder.CreateConstByteArrayGEP(
35253522
metadataAsBytes,
35263523
layout.getMetadataAddressPointOffset());
3527-
addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot, IGM.Int32Ty->getPointerTo());
3524+
addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot,
3525+
IGM.Int32Ty->getPointerTo());
35283526
llvm::Value *addressPoint = IGF.Builder.CreateLoad(addressPointSlot);
35293527

35303528
size = IGF.Builder.CreateSub(size, addressPoint);
@@ -3668,10 +3666,6 @@ namespace {
36683666
AddressPoint = B.getNextOffsetFromGlobal();
36693667
}
36703668

3671-
Size getNextOffsetFromAddressPoint() const {
3672-
return B.getNextOffsetFromGlobal() - AddressPoint;
3673-
}
3674-
36753669
void addSuperClass() {
36763670
// If this is a root class, use SwiftObject as our formal parent.
36773671
if (!Target->hasSuperclass()) {

lib/IRGen/MetadataLayout.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
271271
// If our superclass is resilient to us, or the class itself is resilient
272272
// to us, we will access metadata members relative to a base offset.
273273
if (forClass == Target) {
274+
Layout.StartOfImmediateMembers = getNextOffset();
275+
274276
if (Layout.HasResilientSuperclass ||
275277
IGM.isResilient(forClass, ResilienceExpansion::Maximal)) {
276278
assert(!DynamicOffsetBase);

lib/IRGen/MetadataLayout.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ class ClassMetadataLayout : public NominalMetadataLayout {
177177
private:
178178
bool HasResilientSuperclass = false;
179179

180+
StoredOffset StartOfImmediateMembers;
181+
180182
StoredOffset MetadataSize;
181183
StoredOffset MetadataAddressPoint;
182184

@@ -270,6 +272,12 @@ class ClassMetadataLayout : public NominalMetadataLayout {
270272

271273
Offset getFieldOffsetVectorOffset(IRGenFunction &IGF) const;
272274

275+
/// If the start of the immediate members is statically known, this
276+
/// method will return it. Otherwise, it will assert.
277+
Size getStartOfImmediateMembers() const {
278+
return StartOfImmediateMembers.getStaticOffset();
279+
}
280+
273281
/// The number of members to add after superclass metadata. The size of
274282
/// this metadata is the superclass size plus the number of immediate
275283
/// members in the class itself.

test/IRGen/class_resilience.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959

6060
// CHECK: @_T016class_resilience16MyResilientChildCMo = {{(protected )?}}constant [[INT]] {{60|96}}
6161

62+
// CHECK: @_T016class_resilience24MyResilientGenericParentCMo = {{(protected )?}}constant [[INT]] {{52|80}}
63+
64+
// CHECK: @_T016class_resilience24MyResilientConcreteChildCMo = {{(protected )?}}constant [[INT]] {{64|104}}
65+
6266
import resilient_class
6367
import resilient_struct
6468
import resilient_enum
@@ -164,6 +168,23 @@ public class MyResilientChild : MyResilientParent {
164168
}
165169

166170

171+
public class MyResilientGenericParent<T> {
172+
public let t: T
173+
174+
public init(t: T) {
175+
self.t = t
176+
}
177+
}
178+
179+
public class MyResilientConcreteChild : MyResilientGenericParent<Int> {
180+
public let x: Int
181+
182+
public init(x: Int) {
183+
self.x = x
184+
super.init(t: x)
185+
}
186+
}
187+
167188
extension ResilientGenericOutsideParent {
168189
public func genericExtensionMethod() -> A.Type {
169190
return A.self
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
#if BEFORE
3+
4+
open class AddStoredProperty {
5+
public let x: Int
6+
7+
public init(x: Int) {
8+
self.x = x
9+
}
10+
11+
public func get() -> (Int, Int) {
12+
return (x, -x)
13+
}
14+
}
15+
16+
#else
17+
18+
open class AddStoredProperty {
19+
public let x: Int
20+
public let y: Int
21+
22+
public init(x: Int) {
23+
self.x = x
24+
self.y = -x
25+
}
26+
27+
public func get() -> (Int, Int) {
28+
return (x, y)
29+
}
30+
}
31+
32+
#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
#if BEFORE
3+
4+
open class AddVirtualMethod {
5+
public init() {}
6+
7+
open func f1() -> Int {
8+
return 1
9+
}
10+
}
11+
12+
#else
13+
14+
open class AddVirtualMethod {
15+
public init() {}
16+
17+
open func f1() -> Int {
18+
return f2() + 1
19+
}
20+
21+
open func f2() -> Int {
22+
return 0
23+
}
24+
}
25+
26+
#endif
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
2+
#if BEFORE
3+
4+
open class FirstMiddle {
5+
let x: String
6+
7+
public init(x: String) {
8+
self.x = x
9+
}
10+
11+
public func get() -> String {
12+
return x
13+
}
14+
}
15+
16+
open class SecondMiddle {
17+
let x: String
18+
19+
public init(x: String) {
20+
self.x = x
21+
}
22+
23+
public func get() -> String {
24+
return x
25+
}
26+
}
27+
28+
open class GenericMiddle<T> {
29+
let x: T
30+
31+
public init(x: T) {
32+
self.x = x
33+
}
34+
35+
public func get() -> T {
36+
return x
37+
}
38+
}
39+
40+
#else
41+
42+
// Insert concrete superclass
43+
open class Base {
44+
let x: String
45+
46+
public init(t: String) {
47+
self.x = t
48+
}
49+
}
50+
51+
open class FirstMiddle : Base {
52+
public init(x: String) {
53+
super.init(t: x)
54+
}
55+
56+
public func get() -> String {
57+
return x
58+
}
59+
}
60+
61+
// Insert generic superclass
62+
open class GenericBase<T> {
63+
let x: T
64+
65+
public init(t: T) {
66+
self.x = t
67+
}
68+
}
69+
70+
open class SecondMiddle : GenericBase<String> {
71+
public init(x: String) {
72+
super.init(t: x)
73+
}
74+
75+
public func get() -> String {
76+
return x
77+
}
78+
}
79+
80+
// Insert concrete superclass - class itself is generic
81+
open class GenericMiddle<T> : GenericBase<T> {
82+
public init(x: T) {
83+
super.init(t: x)
84+
}
85+
86+
public func get() -> T {
87+
return x
88+
}
89+
}
90+
91+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-resilience-test
2+
// REQUIRES: executable_test
3+
4+
import StdlibUnittest
5+
import class_add_property_subclass
6+
7+
8+
var ClassAddPropertySubclassTest = TestSuite("ClassAddPropertySubclass")
9+
10+
class AddStoredPropertySubclass : AddStoredProperty {
11+
var z: Int
12+
13+
init(x: Int, z: Int) {
14+
self.z = z
15+
super.init(x: x)
16+
}
17+
}
18+
19+
ClassAddPropertySubclassTest.test("AddStoredProperty") {
20+
let t = AddStoredPropertySubclass(x: 1, z: 2)
21+
22+
expectEqual(1, t.get().0)
23+
expectEqual(-1, t.get().1)
24+
expectEqual(2, t.z)
25+
}
26+
27+
class AddStoredPropertyGenericSubclass<T> : AddStoredProperty {
28+
var z: T
29+
30+
init(x: Int, z: T) {
31+
self.z = z
32+
super.init(x: x)
33+
}
34+
}
35+
36+
ClassAddPropertySubclassTest.test("AddStoredPropertyGeneric") {
37+
let t = AddStoredPropertyGenericSubclass(x: 1, z: "hello world")
38+
39+
expectEqual(1, t.get().0)
40+
expectEqual(-1, t.get().1)
41+
expectEqual("hello world", t.z)
42+
}
43+
44+
runAllTests()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-resilience-test
2+
// REQUIRES: executable_test
3+
4+
import StdlibUnittest
5+
import class_add_virtual_method_subclass
6+
7+
8+
var ClassAddVirtualMethodSubclassTest = TestSuite("ClassAddVirtualMethodSubclass")
9+
10+
class AddVirtualMethodSubclass : AddVirtualMethod {
11+
func f3() -> Int {
12+
return f1() + 1
13+
}
14+
}
15+
16+
ClassAddVirtualMethodSubclassTest.test("AddVirtualMethod") {
17+
let t = AddVirtualMethodSubclass()
18+
19+
expectEqual(1, t.f1())
20+
expectEqual(2, t.f3())
21+
}
22+
23+
class AddVirtualMethodGenericSubclass<T : Strideable> : AddVirtualMethod
24+
where T.Stride == Int {
25+
func f3(_ t: T) -> T {
26+
return t + f1()
27+
}
28+
}
29+
30+
ClassAddVirtualMethodSubclassTest.test("AddVirtualMethodGeneric") {
31+
let t = AddVirtualMethodGenericSubclass<Int32>()
32+
33+
expectEqual(1, t.f1())
34+
expectEqual(2, t.f3(1))
35+
}
36+
37+
runAllTests()

0 commit comments

Comments
 (0)