Skip to content

Commit 93af58d

Browse files
committed
IRGen: Correctly calculate base offset variable for generic classes
If a generic class has non-resilient ancestry, we cannot use the template size so far as the constant value of the base offset variable, because the template will not contain entries for all metadata members; instead, use metadata layout as with everything else.
1 parent ac19b1c commit 93af58d

File tree

4 files changed

+39
-14
lines changed

4 files changed

+39
-14
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,11 +2937,6 @@ namespace {
29372937
return B.getNextOffsetFromGlobal() - TemplateHeaderSize;
29382938
}
29392939

2940-
/// Ignore the destructor and value witness table.
2941-
Size getNextOffsetFromAddressPoint() const {
2942-
return getNextOffsetFromTemplateHeader() - AddressPoint;
2943-
}
2944-
29452940
template <class... T>
29462941
void addGenericArgument(CanType type, T &&...args) {
29472942
FillOps.push_back({type, None});
@@ -3194,7 +3189,6 @@ namespace {
31943189

31953190
public:
31963191
void noteResilientSuperclass() {
3197-
// FIXME: Perform sliding
31983192
HasResilientSuperclass = true;
31993193
}
32003194

@@ -3224,8 +3218,10 @@ namespace {
32243218

32253219
// Otherwise, we know the offset at compile time, even if our
32263220
// clients do not, so just emit a constant.
3227-
auto value = asImpl().getNextOffsetFromAddressPoint().getValue();
3228-
auto *init = llvm::ConstantInt::get(IGM.SizeTy, value);
3221+
auto &layout = IGM.getMetadataLayout(theClass);
3222+
3223+
auto value = layout.getStartOfImmediateMembers();
3224+
auto *init = llvm::ConstantInt::get(IGM.SizeTy, value.getValue());
32293225

32303226
offsetVar->setInitializer(init);
32313227
offsetVar->setConstant(true);
@@ -3503,13 +3499,15 @@ namespace {
35033499
Address sizeSlot = IGF.Builder.CreateConstByteArrayGEP(
35043500
metadataAsBytes,
35053501
layout.getMetadataSizeOffset());
3506-
sizeSlot = IGF.Builder.CreateBitCast(sizeSlot, IGM.Int32Ty->getPointerTo());
3502+
sizeSlot = IGF.Builder.CreateBitCast(sizeSlot,
3503+
IGM.Int32Ty->getPointerTo());
35073504
llvm::Value *size = IGF.Builder.CreateLoad(sizeSlot);
35083505

35093506
Address addressPointSlot = IGF.Builder.CreateConstByteArrayGEP(
35103507
metadataAsBytes,
35113508
layout.getMetadataAddressPointOffset());
3512-
addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot, IGM.Int32Ty->getPointerTo());
3509+
addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot,
3510+
IGM.Int32Ty->getPointerTo());
35133511
llvm::Value *addressPoint = IGF.Builder.CreateLoad(addressPointSlot);
35143512

35153513
size = IGF.Builder.CreateSub(size, addressPoint);
@@ -3653,10 +3651,6 @@ namespace {
36533651
AddressPoint = B.getNextOffsetFromGlobal();
36543652
}
36553653

3656-
Size getNextOffsetFromAddressPoint() const {
3657-
return B.getNextOffsetFromGlobal() - AddressPoint;
3658-
}
3659-
36603654
void addSuperClass() {
36613655
// If this is a root class, use SwiftObject as our formal parent.
36623656
if (!Target->hasSuperclass()) {

lib/IRGen/MetadataLayout.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
250250
// If our superclass is resilient to us, or the class itself is resilient
251251
// to us, we will access metadata members relative to a base offset.
252252
if (forClass == Target) {
253+
Layout.StartOfImmediateMembers = getNextOffset();
254+
253255
if (Layout.HasResilientSuperclass ||
254256
IGM.isResilient(forClass, ResilienceExpansion::Maximal)) {
255257
assert(!DynamicOffsetBase);

lib/IRGen/MetadataLayout.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ class ClassMetadataLayout : public NominalMetadataLayout {
169169
private:
170170
bool HasResilientSuperclass = false;
171171

172+
StoredOffset StartOfImmediateMembers;
173+
172174
StoredOffset MetadataSize;
173175
StoredOffset MetadataAddressPoint;
174176

@@ -262,6 +264,12 @@ class ClassMetadataLayout : public NominalMetadataLayout {
262264

263265
Offset getFieldOffsetVectorOffset(IRGenFunction &IGF) const;
264266

267+
/// If the start of the immediate members is statically known, this
268+
/// method will return it. Otherwise, it will assert.
269+
Size getStartOfImmediateMembers() const {
270+
return StartOfImmediateMembers.getStaticOffset();
271+
}
272+
265273
/// The number of members to add after superclass metadata. The size of
266274
/// this metadata is the superclass size plus the number of immediate
267275
/// 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

0 commit comments

Comments
 (0)