Skip to content

Commit ff09603

Browse files
committed
IRGen: @_fixed_layout classes still have resilient metadata
1 parent 16a459d commit ff09603

15 files changed

+334
-179
lines changed

lib/IRGen/ClassMetadataVisitor.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ template <class Impl> class ClassMetadataVisitor
9595
if (superclassDecl->hasClangNode()) {
9696
// Nothing to do; Objective-C classes do not add new members to
9797
// Swift class metadata.
98-
} else if (IGM.isResilient(superclassDecl, ResilienceExpansion::Maximal)) {
98+
} else if (IGM.hasResilientMetadata(superclassDecl, ResilienceExpansion::Maximal)) {
9999
// Runtime metadata instantiation will initialize our field offset
100100
// vector and vtable entries.
101101
//
@@ -143,6 +143,11 @@ template <class Impl> class ClassMetadataVisitor
143143
}
144144
asImpl().noteEndOfFieldOffsets(theClass);
145145

146+
// If the class has resilient metadata, we cannot make any assumptions
147+
// about its metadata layout, so skip the rest of this method.
148+
if (IGM.hasResilientMetadata(theClass, ResilienceExpansion::Maximal))
149+
return;
150+
146151
// Add vtable entries.
147152
asImpl().addVTableEntries(theClass);
148153
}

lib/IRGen/GenClass.cpp

+12-9
Original file line numberDiff line numberDiff line change
@@ -329,20 +329,21 @@ namespace {
329329
auto superclassDecl = superclassType.getClassOrBoundGenericClass();
330330
assert(superclassType && superclassDecl);
331331

332-
if (IGM.isResilient(superclassDecl, ResilienceExpansion::Maximal)) {
333-
// If the class is resilient, don't walk over its fields; we have to
334-
// calculate the layout at runtime.
332+
if (IGM.hasResilientMetadata(superclassDecl, ResilienceExpansion::Maximal))
335333
ClassHasResilientAncestry = true;
334+
335+
// If the superclass has resilient storage, don't walk its fields.
336+
if (IGM.isResilient(superclassDecl, ResilienceExpansion::Maximal)) {
336337
ClassHasResilientMembers = true;
337338

338-
// Furthermore, if the superclass is generic, we have to assume
339-
// that its layout depends on its generic parameters. But this only
340-
// propagates down to subclasses whose superclass type depends on the
341-
// subclass's generic context.
339+
// If the superclass is generic, we have to assume that its layout
340+
// depends on its generic parameters. But this only propagates down to
341+
// subclasses whose superclass type depends on the subclass's generic
342+
// context.
342343
if (superclassType.hasArchetype())
343344
ClassHasGenericLayout = true;
344345
} else {
345-
// Otherwise, we have total knowledge of the class and its
346+
// Otherwise, we are allowed to have total knowledge of the superclass
346347
// fields, so walk them to compute the layout.
347348
addFieldsForClass(superclassDecl, superclassType, /*superclass=*/true);
348349
}
@@ -354,8 +355,10 @@ namespace {
354355
if (classHasIncompleteLayout(IGM, theClass))
355356
ClassHasMissingMembers = true;
356357

357-
if (IGM.isResilient(theClass, ResilienceExpansion::Maximal)) {
358+
if (IGM.hasResilientMetadata(theClass, ResilienceExpansion::Maximal))
358359
ClassHasResilientAncestry = true;
360+
361+
if (IGM.isResilient(theClass, ResilienceExpansion::Maximal)) {
359362
ClassHasResilientMembers = true;
360363
return;
361364
}

lib/IRGen/GenMeta.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ namespace {
13811381
RequireMetadata_t requireMetadata)
13821382
: super(IGM, Type, requireMetadata),
13831383
VTable(IGM.getSILModule().lookUpVTable(getType())),
1384-
Resilient(IGM.isResilient(Type, ResilienceExpansion::Minimal)) {
1384+
Resilient(IGM.hasResilientMetadata(Type, ResilienceExpansion::Minimal)) {
13851385

13861386
if (getType()->isForeign()) return;
13871387

@@ -1485,7 +1485,7 @@ namespace {
14851485

14861486
// Only emit a method lookup function if the class is resilient
14871487
// and has a non-empty vtable.
1488-
if (IGM.isResilient(getType(), ResilienceExpansion::Minimal))
1488+
if (IGM.hasResilientMetadata(getType(), ResilienceExpansion::Minimal))
14891489
IGM.emitMethodLookupFunction(getType());
14901490

14911491
auto offset = MetadataLayout->hasResilientSuperclass()
@@ -2250,7 +2250,7 @@ static void emitClassMetadataBaseOffset(IRGenModule &IGM,
22502250
// Only classes defined in resilient modules, or those that have
22512251
// a resilient superclass need this.
22522252
if (!layout.hasResilientSuperclass() &&
2253-
!IGM.isResilient(classDecl, ResilienceExpansion::Minimal)) {
2253+
!IGM.hasResilientMetadata(classDecl, ResilienceExpansion::Minimal)) {
22542254
return;
22552255
}
22562256

lib/IRGen/IRGenSIL.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -5460,12 +5460,12 @@ void IRGenSILFunction::visitSuperMethodInst(swift::SuperMethodInst *i) {
54605460
// its offset since methods can be re-ordered resiliently. Instead, we call
54615461
// the class method lookup function, passing in a reference to the
54625462
// method descriptor.
5463-
if (IGM.isResilient(classDecl, ResilienceExpansion::Maximal)) {
5463+
if (IGM.hasResilientMetadata(classDecl, ResilienceExpansion::Maximal)) {
54645464
// Load the superclass of the static type of the 'self' value.
54655465
llvm::Value *superMetadata;
54665466
auto instanceTy = CanType(baseType.getASTType()->getMetatypeInstanceType());
5467-
if (!IGM.isResilient(instanceTy.getClassOrBoundGenericClass(),
5468-
ResilienceExpansion::Maximal)) {
5467+
if (!IGM.hasResilientMetadata(instanceTy.getClassOrBoundGenericClass(),
5468+
ResilienceExpansion::Maximal)) {
54695469
// It's still possible that the static type of 'self' is not resilient, in
54705470
// which case we can assume its superclass.
54715471
//
@@ -5544,8 +5544,8 @@ void IRGenSILFunction::visitClassMethodInst(swift::ClassMethodInst *i) {
55445544
auto methodType = i->getType().castTo<SILFunctionType>();
55455545

55465546
auto *classDecl = cast<ClassDecl>(method.getDecl()->getDeclContext());
5547-
if (IGM.isResilient(classDecl,
5548-
ResilienceExpansion::Maximal)) {
5547+
if (IGM.hasResilientMetadata(classDecl,
5548+
ResilienceExpansion::Maximal)) {
55495549
auto *fnPtr = IGM.getAddrOfDispatchThunk(method, NotForDefinition);
55505550
auto sig = IGM.getSignature(methodType);
55515551
FunctionPointer fn(fnPtr, sig);

lib/IRGen/MetadataLayout.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
280280
Layout.StartOfImmediateMembers = getNextOffset();
281281

282282
if (Layout.HasResilientSuperclass ||
283-
IGM.isResilient(forClass, ResilienceExpansion::Maximal)) {
283+
IGM.hasResilientMetadata(forClass, ResilienceExpansion::Maximal)) {
284284
assert(!DynamicOffsetBase);
285285
DynamicOffsetBase = NextOffset;
286286
}

lib/SIL/SILDeclRef.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,9 @@ SubclassScope SILDeclRef::getSubclassScope() const {
928928
assert(FD->getEffectiveAccess() <= classType->getEffectiveAccess() &&
929929
"class must be as visible as its members");
930930

931+
// FIXME: This is too narrow. Any class with resilient metadata should
932+
// probably have this, at least for method overrides that don't add new
933+
// vtable entries.
931934
if (classType->isResilient())
932935
return SubclassScope::Resilient;
933936

lib/TBDGen/TBDGen.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,11 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
313313
visitNominalTypeDecl(CD);
314314

315315
auto hasResilientAncestor =
316-
CD->isResilient(SwiftModule, ResilienceExpansion::Minimal);
316+
CD->hasResilientMetadata(SwiftModule, ResilienceExpansion::Minimal);
317317
auto ancestor = CD->getSuperclassDecl();
318318
while (ancestor && !hasResilientAncestor) {
319319
hasResilientAncestor |=
320-
ancestor->isResilient(SwiftModule, ResilienceExpansion::Maximal);
320+
ancestor->hasResilientMetadata(SwiftModule, ResilienceExpansion::Maximal);
321321
ancestor = ancestor->getSuperclassDecl();
322322
}
323323

@@ -338,7 +338,7 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
338338
void addMethod(SILDeclRef method) {
339339
assert(method.getDecl()->getDeclContext() == CD);
340340

341-
if (CD->isResilient()) {
341+
if (CD->hasResilientMetadata()) {
342342
if (FirstTime) {
343343
FirstTime = false;
344344

test/IRGen/class_resilience.swift

-23
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@
9797
// CHECK-objc-SAME: @"$s16class_resilience14ResilientChildCMm"
9898
// CHECK-native-SAME: i32 0
9999

100-
// CHECK: @"$s16class_resilience16FixedLayoutChildCMo" = {{(protected )?}}{{(dllexport )?}}global [[BOUNDS]] zeroinitializer
101-
102100
// CHECK: @"$s16class_resilience17MyResilientParentCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]]
103101
// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
104102
// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
@@ -119,10 +117,6 @@
119117
// CHECK: @"$s16class_resilience14ResilientChildC5fields5Int32VvsTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
120118
// CHECK: @"$s16class_resilience14ResilientChildC5fields5Int32VvMTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
121119

122-
// CHECK: @"$s16class_resilience16FixedLayoutChildC5fields5Int32VvgTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
123-
// CHECK: @"$s16class_resilience16FixedLayoutChildC5fields5Int32VvsTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
124-
// CHECK: @"$s16class_resilience16FixedLayoutChildC5fields5Int32VvMTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
125-
126120
// CHECK: @"$s16class_resilience21ResilientGenericChildC5fields5Int32VvgTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
127121
// CHECK: @"$s16class_resilience21ResilientGenericChildC5fields5Int32VvsTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
128122
// CHECK: @"$s16class_resilience21ResilientGenericChildC5fields5Int32VvMTq" = {{(protected )?}}{{(dllexport )?}}alias %swift.method_descriptor, getelementptr inbounds
@@ -206,15 +200,6 @@ public class ResilientChild : ResilientOutsideParent {
206200
}
207201
}
208202

209-
// Superclass is resilient, but the class is fixed-layout.
210-
// This simulates a user app subclassing a class in a resilient
211-
// framework. In this case, we still want to emit a base offset
212-
// global.
213-
214-
@_fixed_layout public class FixedLayoutChild : ResilientOutsideParent {
215-
public var field: Int32 = 0
216-
}
217-
218203
// Superclass is resilient, so the number of fields and their
219204
// offsets is not known at compile time
220205

@@ -525,14 +510,6 @@ extension ResilientGenericOutsideParent {
525510
// CHECK-NEXT: ret void
526511

527512

528-
// FixedLayoutChild metadata initialization function
529-
530-
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$s16class_resilience16FixedLayoutChildCMr"(%swift.type*, i8*, i8**)
531-
532-
// Initialize the superclass field...
533-
// CHECK: call void @swift_initClassMetadata(%swift.type* %0, [[INT]] 0, [[INT]] 1, i8*** {{%.*}}, [[INT]]* {{%.*}})
534-
535-
536513
// ResilientGenericChild metadata initialization function
537514

538515
// CHECK-LABEL: define internal %swift.type* @"$s16class_resilience21ResilientGenericChildCMi"(%swift.type_descriptor*, i8**, i8*)

test/IRGen/fixed_layout_class.swift

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/chex.py < %s > %t/class_resilience.swift
3+
// RUN: %target-swift-frontend -emit-module -enable-resilience -enable-class-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
4+
// RUN: %target-swift-frontend -emit-module -enable-resilience -enable-class-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
5+
// RUN: %target-swift-frontend -emit-module -enable-resilience -enable-class-resilience -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/../Inputs/resilient_class.swift
6+
// RUN: %target-swift-frontend -emit-module -enable-resilience -enable-class-resilience -emit-module-path=%t/fixed_layout_class.swiftmodule -module-name=fixed_layout_class -I %t %S/../Inputs/fixed_layout_class.swift
7+
// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -enable-class-resilience %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -DINT=i%target-ptrsize
8+
// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -enable-class-resilience -O %t/class_resilience.swift
9+
10+
// This tests @_fixed_layout classes in resilient modules.
11+
import fixed_layout_class
12+
13+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience20useRootClassPropertyyy013fixed_layout_A0026OutsideParentWithResilientF0CF"(%T18fixed_layout_class34OutsideParentWithResilientPropertyC*)
14+
public func useRootClassProperty(_ o: OutsideParentWithResilientProperty) {
15+
// CHECK: getelementptr inbounds %T18fixed_layout_class34OutsideParentWithResilientPropertyC, %T18fixed_layout_class34OutsideParentWithResilientPropertyC* %0, i32 0, i32 1
16+
_ = o.p
17+
// CHECK: load [[INT]], [[INT]]* @"$s18fixed_layout_class34OutsideParentWithResilientPropertyC1s16resilient_struct4SizeVvpWvd"
18+
_ = o.s
19+
// CHECK: load [[INT]], [[INT]]* @"$s18fixed_layout_class34OutsideParentWithResilientPropertyC5colors5Int32VvpWvd"
20+
_ = o.color
21+
// CHECK: ret void
22+
}
23+
24+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience19useSubclassPropertyyy013fixed_layout_A012OutsideChildCF"(%T18fixed_layout_class12OutsideChildC*)
25+
public func useSubclassProperty(_ o: OutsideChild) {
26+
// CHECK: getelementptr inbounds %T18fixed_layout_class13OutsideParentC, %T18fixed_layout_class13OutsideParentC* %4, i32 0, i32 1
27+
_ = o.property
28+
// CHECK: getelementptr inbounds %T18fixed_layout_class12OutsideChildC, %T18fixed_layout_class12OutsideChildC* %0, i32 0, i32 2
29+
_ = o.childProperty
30+
// CHECK: ret void
31+
}
32+
33+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience27useGenericRootClassPropertyyy013fixed_layout_A00D13OutsideParentCyxGlF"(%T18fixed_layout_class20GenericOutsideParentC*)
34+
public func useGenericRootClassProperty<A>(_ o: GenericOutsideParent<A>) {
35+
// -- we load the base offset twice, first to get the generic parameter out and
36+
// then for the property itself.
37+
38+
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ({ [[INT]], i32, i32 }, { [[INT]], i32, i32 }* @"$s18fixed_layout_class20GenericOutsideParentCMo", i32 0, i32 0)
39+
40+
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T18fixed_layout_class20GenericOutsideParentC, %T18fixed_layout_class20GenericOutsideParentC* %0, i32 0, i32 0, i32 0
41+
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
42+
43+
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ({ [[INT]], i32, i32 }, { [[INT]], i32, i32 }* @"$s18fixed_layout_class20GenericOutsideParentCMo", i32 0, i32 0)
44+
// CHECK: [[FIELD_OFFSET_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
45+
46+
// CHECK: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
47+
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ADDR]], [[INT]] [[FIELD_OFFSET_OFFSET]]
48+
// CHECK: [[FIELD_OFFSET_PTR:%.*]] = bitcast i8* [[FIELD_OFFSET_ADDR]] to [[INT]]*
49+
// CHECK: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
50+
_ = o.property
51+
52+
// CHECK: ret void
53+
}
54+
55+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience27useGenericRootClassPropertyyy013fixed_layout_A00D13OutsideParentCySiGF"(%T18fixed_layout_class20GenericOutsideParentCySiG*)
56+
public func useGenericRootClassProperty(_ o: GenericOutsideParent<Int>) {
57+
// CHECK: getelementptr inbounds %T18fixed_layout_class20GenericOutsideParentCySiG, %T18fixed_layout_class20GenericOutsideParentCySiG* %0, i32 0, i32 1
58+
_ = o.property
59+
60+
// CHECK: ret void
61+
}
62+
63+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience26useGenericSubclassPropertyyy013fixed_layout_A00D12OutsideChildCyxGlF"(%T18fixed_layout_class19GenericOutsideChildC*)
64+
public func useGenericSubclassProperty<A>(_ o: GenericOutsideChild<A>) {
65+
// -- we load the base offset twice, first to get the generic parameter out and
66+
// then for the property itself.
67+
68+
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ({ [[INT]], i32, i32 }, { [[INT]], i32, i32 }* @"$s18fixed_layout_class19GenericOutsideChildCMo", i32 0, i32 0)
69+
70+
// CHECK: [[UPCAST:%.*]] = bitcast %T18fixed_layout_class19GenericOutsideChildC* %0 to %T18fixed_layout_class20GenericOutsideParentC*
71+
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T18fixed_layout_class20GenericOutsideParentC, %T18fixed_layout_class20GenericOutsideParentC* [[UPCAST]], i32 0, i32 0, i32 0
72+
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
73+
74+
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ({ [[INT]], i32, i32 }, { [[INT]], i32, i32 }* @"$s18fixed_layout_class20GenericOutsideParentCMo", i32 0, i32 0)
75+
// CHECK: [[FIELD_OFFSET_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
76+
77+
// CHECK: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
78+
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ADDR]], [[INT]] [[FIELD_OFFSET_OFFSET]]
79+
// CHECK: [[FIELD_OFFSET_PTR:%.*]] = bitcast i8* [[FIELD_OFFSET_ADDR]] to [[INT]]*
80+
// CHECK: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
81+
_ = o.property
82+
83+
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T18fixed_layout_class19GenericOutsideChildC, %T18fixed_layout_class19GenericOutsideChildC* %0, i32 0, i32 0, i32 0
84+
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
85+
86+
// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ({ [[INT]], i32, i32 }, { [[INT]], i32, i32 }* @"$s18fixed_layout_class19GenericOutsideChildCMo", i32 0, i32 0)
87+
// CHECK: [[FIELD_OFFSET_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
88+
89+
// CHECK: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
90+
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ADDR]], [[INT]] [[FIELD_OFFSET_OFFSET]]
91+
// CHECK: [[FIELD_OFFSET_PTR:%.*]] = bitcast i8* [[FIELD_OFFSET_ADDR]] to [[INT]]*
92+
// CHECK: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
93+
_ = o.childProperty
94+
95+
// CHECK: ret void
96+
}
97+
98+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience26useGenericSubclassPropertyyy013fixed_layout_A00D12OutsideChildCySiGF"(%T18fixed_layout_class19GenericOutsideChildCySiG*)
99+
public func useGenericSubclassProperty(_ o: GenericOutsideChild<Int>) {
100+
// CHECK: [[UPCAST:%.*]] = bitcast %T18fixed_layout_class19GenericOutsideChildCySiG* %0 to %T18fixed_layout_class20GenericOutsideParentCySiG*
101+
// CHECK: getelementptr inbounds %T18fixed_layout_class20GenericOutsideParentCySiG, %T18fixed_layout_class20GenericOutsideParentCySiG* [[UPCAST]], i32 0, i32 1
102+
_ = o.property
103+
104+
// CHECK: getelementptr inbounds %T18fixed_layout_class19GenericOutsideChildCySiG, %T18fixed_layout_class19GenericOutsideChildCySiG* %0, i32 0, i32 2
105+
_ = o.childProperty
106+
107+
// CHECK: ret void
108+
}
109+
110+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience17callVirtualMethodyy013fixed_layout_A013OutsideParentCF"(%T18fixed_layout_class13OutsideParentC*)
111+
public func callVirtualMethod(_ o: OutsideParent) {
112+
// Note: virtual method calls still use dispatch thunks
113+
114+
// CHECK: call swiftcc void @"$s18fixed_layout_class13OutsideParentC6methodyyFTj"
115+
_ = o.method()
116+
117+
// CHECK: ret void
118+
}
119+
120+
@_fixed_layout open class MyChildOfOutsideParent : OutsideParent {
121+
public func newMethod() {}
122+
}
123+
124+
// Make sure we emit the dispatch thunk:
125+
126+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s16class_resilience22MyChildOfOutsideParentC9newMethodyyFTj"(%T16class_resilience22MyChildOfOutsideParentC* swiftself)

0 commit comments

Comments
 (0)