Skip to content

Commit 9a8c814

Browse files
committed
[Outlining] Pass polymorphic args of type.
If any deinit must be called, just pass the full generic environment of the type being destroyed.
1 parent b83085b commit 9a8c814

File tree

4 files changed

+349
-29
lines changed

4 files changed

+349
-29
lines changed

lib/IRGen/Outlining.cpp

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Explosion.h"
2020
#include "GenOpaque.h"
2121
#include "GenProto.h"
22+
#include "GenericRequirement.h"
2223
#include "IRGenFunction.h"
2324
#include "IRGenMangler.h"
2425
#include "IRGenModule.h"
@@ -27,6 +28,7 @@
2728
#include "MetadataRequest.h"
2829
#include "swift/AST/GenericEnvironment.h"
2930
#include "swift/AST/IRGenOptions.h"
31+
#include "swift/IRGen/GenericRequirement.h"
3032
#include "swift/SIL/SILModule.h"
3133

3234
using namespace swift;
@@ -65,18 +67,8 @@ void OutliningMetadataCollector::collectTypeMetadata(SILType ty) {
6567
// Substitute opaque types if allowed.
6668
ty = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(ty, CanGenericSignature());
6769

68-
auto astType = ty.getASTType();
69-
auto &ti = IGF.IGM.getTypeInfoForLowered(astType);
70-
71-
if (needsDeinit) {
72-
auto *nominal = ty.getASTType()->getAnyNominal();
73-
if (nominal && nominal->getValueTypeDestructor()) {
74-
assert(ty.isMoveOnly());
75-
collectFormalTypeMetadata(ty.getASTType());
76-
}
77-
}
78-
7970
collectTypeMetadataForLayout(ty);
71+
collectTypeMetadataForDeinit(ty);
8072
}
8173

8274
void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType ty) {
@@ -103,6 +95,33 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType ty) {
10395
collectRepresentationTypeMetadata(ty);
10496
}
10597

98+
void OutliningMetadataCollector::collectTypeMetadataForDeinit(SILType ty) {
99+
if (!needsDeinit)
100+
return;
101+
102+
auto *nominal = ty.getASTType()->getAnyNominal();
103+
if (!nominal)
104+
return;
105+
if (!nominal->getValueTypeDestructor())
106+
return;
107+
assert(ty.isMoveOnly());
108+
109+
if (Requirements.size())
110+
return;
111+
112+
auto pair = getTypeAndGenericSignatureForManglingOutlineFunction(T);
113+
auto sig = pair.second;
114+
auto subs =
115+
digOutGenericEnvironment(T.getASTType())->getForwardingSubstitutionMap();
116+
Subs = subs;
117+
GenericTypeRequirements requirements(IGF.IGM, sig);
118+
for (auto requirement : requirements.getRequirements()) {
119+
auto *value = emitGenericRequirementFromSubstitutions(
120+
IGF, requirement, MetadataState::Complete, subs);
121+
Requirements.insert({requirement, value});
122+
}
123+
}
124+
106125
void OutliningMetadataCollector::collectFormalTypeMetadata(CanType ty) {
107126
// If the type has no archetypes, we can emit it from scratch in the callee.
108127
assert(ty->hasArchetype());
@@ -126,6 +145,13 @@ void OutliningMetadataCollector::collectRepresentationTypeMetadata(SILType ty) {
126145

127146
void OutliningMetadataCollector::addPolymorphicArguments(
128147
SmallVectorImpl<llvm::Value *> &args) const {
148+
if (Subs) {
149+
for (auto &pair : Requirements) {
150+
auto *value = pair.second;
151+
args.push_back(value);
152+
}
153+
return;
154+
}
129155
for (auto &pair : Values) {
130156
auto metadata = pair.second;
131157
assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
@@ -135,6 +161,13 @@ void OutliningMetadataCollector::addPolymorphicArguments(
135161

136162
void OutliningMetadataCollector::addPolymorphicParameterTypes(
137163
SmallVectorImpl<llvm::Type *> &paramTys) const {
164+
if (Subs) {
165+
for (auto &pair : Requirements) {
166+
auto *value = pair.second;
167+
paramTys.push_back(value->getType());
168+
}
169+
return;
170+
}
138171
for (auto &pair : Values) {
139172
auto *metadata = pair.second;
140173
paramTys.push_back(metadata->getType());
@@ -143,6 +176,13 @@ void OutliningMetadataCollector::addPolymorphicParameterTypes(
143176

144177
void OutliningMetadataCollector::bindPolymorphicParameters(
145178
IRGenFunction &IGF, Explosion &params) const {
179+
if (Subs) {
180+
for (auto &pair : Requirements) {
181+
bindGenericRequirement(IGF, pair.first, params.claimNext(),
182+
MetadataState::Complete, *Subs);
183+
}
184+
return;
185+
}
146186
// Note that our parameter IGF intentionally shadows the IGF that this
147187
// collector was built with.
148188
for (auto &pair : Values) {

lib/IRGen/Outlining.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
#include "IRGen.h"
2121
#include "LocalTypeDataKind.h"
22+
#include "swift/AST/SubstitutionMap.h"
2223
#include "swift/Basic/LLVM.h"
24+
#include "swift/IRGen/GenericRequirement.h"
2325
#include "swift/SIL/SILType.h"
2426
#include "llvm/ADT/MapVector.h"
2527

@@ -69,6 +71,8 @@ class OutliningMetadataCollector {
6971

7072
private:
7173
llvm::MapVector<LocalTypeDataKey, llvm::Value *> Values;
74+
llvm::MapVector<GenericRequirement, llvm::Value *> Requirements;
75+
std::optional<SubstitutionMap> Subs;
7276
friend class IRGenModule;
7377

7478
public:
@@ -94,6 +98,7 @@ class OutliningMetadataCollector {
9498

9599
private:
96100
void collectTypeMetadataForLayout(SILType type);
101+
void collectTypeMetadataForDeinit(SILType type);
97102
void collectFormalTypeMetadata(CanType type);
98103
void collectRepresentationTypeMetadata(SILType ty);
99104
};

test/IRGen/moveonly_value_functions.swift

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
@_silgen_name("external_symbol")
99
func external_symbol()
1010

11+
public protocol P {
12+
static func foo()
13+
}
14+
1115
public class C<T> {
1216
deinit {
1317
external_symbol()
@@ -66,6 +70,31 @@ public struct OuterNC_2<T> : ~Copyable {
6670
public let i: InnerDeinitingDestructableNC<T>
6771
}
6872

73+
public struct GenericContext_1<T> {
74+
}
75+
76+
extension GenericContext_1 : P where T : P {
77+
public static func foo() {
78+
T.foo()
79+
}
80+
public struct OuterNC_1: ~Copyable {
81+
let i: Inner_NC1
82+
83+
func doit() {
84+
i.beinit()
85+
}
86+
}
87+
88+
public struct Inner_NC1: ~Copyable {
89+
let t: T
90+
let ptr: Int
91+
deinit {
92+
T.foo()
93+
}
94+
func beinit() {}
95+
}
96+
}
97+
6998
// Destroyed value:
7099
// - has deinit
71100
// On lifetime end:
@@ -98,13 +127,9 @@ public func takeOuterDeinitingNC_1<T>(_ t: consuming OuterDeinitingNC_1<T>) {
98127
// CHECK-SAME: ptr{{.*}} %0,
99128
// CHECK-SAME: ptr %T)
100129
// CHECK-SAME: {
101-
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingReleasableNCVMa"(
102-
// : i64 0,
103-
// CHECK-SAME: ptr %T)
104-
// CHECK: [[INNER_DEINITING_RELEASABLE_NC_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]]
105130
// CHECK: call{{.*}} @"$s24moveonly_value_functions9OuterNC_1VyxGlWOs"(
106131
// CHECK-SAME: ptr %0,
107-
// CHECK-SAME: ptr [[INNER_DEINITING_RELEASABLE_NC_METADATA]])
132+
// CHECK-SAME: ptr %T)
108133
// CHECK: }
109134

110135
// Verify that the outlined release function takes the metadata for the
@@ -113,12 +138,16 @@ public func takeOuterDeinitingNC_1<T>(_ t: consuming OuterDeinitingNC_1<T>) {
113138
// $s24moveonly_value_functions9OuterNC_1VyxGlWOs ---> outlined release of moveonly_value_functions.OuterNC_2<A>
114139
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions9OuterNC_1VyxGlWOs"(
115140
// CHECK-SAME: ptr %0,
116-
// CHECK-SAME: ptr %"InnerDeinitingReleasableNC<T>")
141+
// CHECK-SAME: ptr %T)
117142
// CHECK-SAME: {
118143
// ...
119144
// ...
145+
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingReleasableNCVMa"(
146+
// : i64 0,
147+
// CHECK-SAME: ptr %T)
148+
// CHECK: [[INNER_DEINITING_RELEASABLE_NC_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]]
120149
// CHECK: call swiftcc void @"$s24moveonly_value_functions26InnerDeinitingReleasableNCVfD"(
121-
// CHECK-SAME: ptr %"InnerDeinitingReleasableNC<T>",
150+
// CHECK-SAME: ptr [[INNER_DEINITING_RELEASABLE_NC_METADATA]],
122151
// : ptr noalias nocapture swiftself dereferenceable(64) %deinit.arg)
123152
// CHECK: }
124153
public func takeOuterNC_1<T>(_ o: consuming OuterNC_1<T>) {
@@ -137,15 +166,9 @@ public func takeOuterNC_1<T>(_ o: consuming OuterNC_1<T>) {
137166
// CHECK-SAME: ptr{{.*}} %0,
138167
// CHECK-SAME: ptr %T)
139168
// CHECK-SAME: {
140-
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVMa"(
141-
// CHECK-SAME: [[INT]] 0,
142-
// CHECK-SAME: ptr %T)
143-
// CHECK: [[INNER_DEINITING_DESTRUCTABLE_NC_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]]
144169
// CHECK: call{{.*}} @"$s24moveonly_value_functions9OuterNC_2VyxGlWOh"(
145170
// CHECK-SAME: ptr %0,
146-
// CHECK-SAME: ptr %T,
147-
// CHECK-SAME: ptr [[INNER_DEINITING_DESTRUCTABLE_NC_METADATA]],
148-
// : ptr %4)
171+
// CHECK-SAME: ptr %T)
149172
// CHECK: }
150173

151174
// Verify that the outlined destroy function takes the metadata for the
@@ -154,16 +177,44 @@ public func takeOuterNC_1<T>(_ o: consuming OuterNC_1<T>) {
154177
// $s24moveonly_value_functions9OuterNC_2VyxGlWOh ---> outlined destroy of moveonly_value_functions.OuterNC_2<A>
155178
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions9OuterNC_2VyxGlWOh"(
156179
// CHECK-SAME: ptr %0,
157-
// CHECK-SAME: ptr %T,
158-
// CHECK-SAME: ptr %"InnerDeinitingDestructableNC<T>",
159-
// CHECK-SAME: ptr %"OuterNC_2<T>")
180+
// CHECK-SAME: ptr %T)
160181
// CHECK-SAME: {
161182
// ...
162183
// ...
184+
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVMa"(
185+
// : [[INT]] 0,
186+
// CHECK-SAME: ptr %T)
187+
// CHECK: [[INNER_DEINITING_DESTRUCTABLE_NC_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]]
163188
// CHECK: call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVfD"(
164-
// CHECK-SAME: ptr %"InnerDeinitingDestructableNC<T>",
189+
// CHECK-SAME: ptr [[INNER_DEINITING_DESTRUCTABLE_NC_METADATA]],
165190
// : ptr noalias swiftself %3)
166191
// CHECK: }
167192
public func takeOuterNC_2<T>(_ o: consuming OuterNC_2<T>) {
168193
external_symbol()
169194
}
195+
196+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions29takeGenericContext_1OuterNC_1yyAA0eF2_1VA2A1PRzlE0gH2_1Vyx_GnAaERzlF"(
197+
// CHECK-SAME: ptr noalias %0,
198+
// CHECK-SAME: ptr %T,
199+
// CHECK-SAME: ptr %T.P)
200+
// CHECK-SAME: {
201+
// CHECK: call ptr @"$s24moveonly_value_functions16GenericContext_1VA2A1PRzlE9OuterNC_1Vyx_GAaDRzlWOh"(
202+
// CHECK-SAME: ptr %0,
203+
// CHECK-SAME: ptr %T,
204+
// CHECK-SAME: ptr %T.P)
205+
// CHECK: }
206+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions16GenericContext_1VA2A1PRzlE9OuterNC_1Vyx_GAaDRzlWOh"(
207+
// CHECK-SAME: ptr %0,
208+
// CHECK-SAME: ptr %T,
209+
// CHECK-SAME: ptr %T.P)
210+
// CHECK-SAME: {
211+
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions16GenericContext_1VA2A1PRzlE9Inner_NC1VMa"(
212+
// : i64 0,
213+
// CHECK-SAME: ptr %T,
214+
// CHECK-SAME: ptr %T.P)
215+
// CHECK: [[GENERIC_CONTEXT_1_INNER_NC_1_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
216+
// CHECK: call swiftcc void @"$s24moveonly_value_functions16GenericContext_1VA2A1PRzlE9Inner_NC1VfD"(
217+
// CHECK-SAME: ptr [[GENERIC_CONTEXT_1_INNER_NC_1_METADATA]],
218+
// CHECK-SAME: ptr noalias swiftself %0)
219+
// CHECK: }
220+
public func takeGenericContext_1OuterNC_1<T : P>(_ e: consuming GenericContext_1<T>.OuterNC_1) {}

0 commit comments

Comments
 (0)