Skip to content

Commit 0075682

Browse files
committed
[IRGen] Single payload enums consumes call deinits
The include the necessary metadata.
1 parent 04d0680 commit 0075682

File tree

5 files changed

+322
-15
lines changed

5 files changed

+322
-15
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,10 +1639,11 @@ namespace {
16391639
return {payload, extraTag};
16401640
}
16411641
std::pair<EnumPayload, llvm::Value *>
1642-
getPayloadAndExtraTagFromExplosionOutlined(IRGenFunction &IGF,
1643-
Explosion &src) const {
1642+
getPayloadAndExtraTagFromExplosionOutlined(
1643+
IRGenFunction &IGF, Explosion &src,
1644+
OutliningMetadataCollector *collector) const {
16441645
EnumPayload payload;
1645-
unsigned claimSZ = src.size();
1646+
unsigned claimSZ = src.size() - (collector ? collector->size() : 0);
16461647
if (ExtraTagBitCount > 0) {
16471648
--claimSZ;
16481649
}
@@ -1833,7 +1834,7 @@ namespace {
18331834
EnumPayload payload;
18341835
llvm::Value *extraTag;
18351836
std::tie(payload, extraTag) =
1836-
getPayloadAndExtraTagFromExplosionOutlined(IGF, src);
1837+
getPayloadAndExtraTagFromExplosionOutlined(IGF, src, nullptr);
18371838
llvm::BasicBlock *endBB =
18381839
testFixedEnumContainsPayload(IGF, payload, extraTag);
18391840

@@ -1856,25 +1857,33 @@ namespace {
18561857

18571858
void emitCallToConsumeEnumFunction(IRGenFunction &IGF, Explosion &src,
18581859
SILType theEnumType) const {
1860+
OutliningMetadataCollector collector(theEnumType, IGF, LayoutIsNotNeeded,
1861+
DeinitIsNeeded);
1862+
IGF.getTypeInfo(theEnumType)
1863+
.collectMetadataForOutlining(collector, theEnumType);
18591864
if (!consumeEnumFunction)
1860-
consumeEnumFunction = emitConsumeEnumFunction(IGF.IGM, loweredType);
1865+
consumeEnumFunction =
1866+
emitConsumeEnumFunction(IGF.IGM, theEnumType, collector);
18611867
Explosion tmp;
1862-
fillExplosionForOutlinedCall(IGF, src, tmp);
1868+
fillExplosionForOutlinedCall(IGF, src, tmp, &collector);
18631869
llvm::CallInst *call = IGF.Builder.CreateCallWithoutDbgLoc(
18641870
consumeEnumFunction->getFunctionType(), consumeEnumFunction,
18651871
tmp.claimAll());
18661872
call->setCallingConv(IGM.DefaultCC);
18671873
}
18681874

1869-
llvm::Function *emitConsumeEnumFunction(IRGenModule &IGM,
1870-
SILType theEnumType) const {
1875+
llvm::Function *
1876+
emitConsumeEnumFunction(IRGenModule &IGM, SILType theEnumType,
1877+
OutliningMetadataCollector &collector) const {
18711878
IRGenMangler Mangler;
18721879
auto manglingBits =
18731880
getTypeAndGenericSignatureForManglingOutlineFunction(theEnumType);
18741881
std::string name =
18751882
Mangler.mangleOutlinedConsumeFunction(manglingBits.first,
18761883
manglingBits.second);
1877-
auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType);
1884+
SmallVector<llvm::Type *, 2> params(PayloadTypesAndTagType);
1885+
collector.addPolymorphicParameterTypes(params);
1886+
auto func = createOutlineLLVMFunction(IGM, name, params);
18781887

18791888
IRGenFunction IGF(IGM, func);
18801889
Explosion src = IGF.collectParameters();
@@ -1884,7 +1893,8 @@ namespace {
18841893
EnumPayload payload;
18851894
llvm::Value *extraTag;
18861895
std::tie(payload, extraTag) =
1887-
getPayloadAndExtraTagFromExplosionOutlined(IGF, src);
1896+
getPayloadAndExtraTagFromExplosionOutlined(IGF, src, &collector);
1897+
collector.bindPolymorphicParameters(IGF, src);
18881898
llvm::BasicBlock *endBB =
18891899
testFixedEnumContainsPayload(IGF, payload, extraTag);
18901900

@@ -2678,8 +2688,10 @@ namespace {
26782688
}
26792689
}
26802690

2681-
void fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src,
2682-
Explosion &out) const {
2691+
void
2692+
fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src,
2693+
Explosion &out,
2694+
OutliningMetadataCollector *collector) const {
26832695
assert(out.empty() && "Out explosion must be empty!");
26842696
EnumPayload payload;
26852697
llvm::Value *extraTag;
@@ -2688,8 +2700,16 @@ namespace {
26882700
payload.explode(IGM, out);
26892701
if (extraTag)
26902702
out.add(extraTag);
2703+
2704+
if (!collector)
2705+
return;
2706+
llvm::SmallVector<llvm::Value *, 4> args;
2707+
collector->addPolymorphicArguments(args);
2708+
for (auto *arg : args) {
2709+
out.add(arg);
2710+
}
26912711
}
2692-
2712+
26932713
void unpackIntoPayloadExplosion(IRGenFunction &IGF,
26942714
Explosion &asEnumIn,
26952715
Explosion &asPayloadOut) const {
@@ -2749,7 +2769,7 @@ namespace {
27492769
if (!copyEnumFunction)
27502770
copyEnumFunction = emitCopyEnumFunction(IGM, loweredType);
27512771
Explosion tmp;
2752-
fillExplosionForOutlinedCall(IGF, src, tmp);
2772+
fillExplosionForOutlinedCall(IGF, src, tmp, nullptr);
27532773
llvm::CallInst *call = IGF.Builder.CreateCallWithoutDbgLoc(
27542774
copyEnumFunction->getFunctionType(), copyEnumFunction,
27552775
tmp.getAll());
@@ -2818,7 +2838,7 @@ namespace {
28182838
IGF.Builder.emitBlock(endBB);
28192839
return;
28202840
}
2821-
emitCallToConsumeEnumFunction(IGF, src, loweredType);
2841+
emitCallToConsumeEnumFunction(IGF, src, T);
28222842
return;
28232843
}
28242844

lib/IRGen/Outlining.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class OutliningMetadataCollector {
8080
LayoutIsNeeded_t needsLayout,
8181
DeinitIsNeeded_t needsDeinitTypes);
8282

83+
unsigned size() const {
84+
return Subs.has_value() ? Requirements.size() : Values.size();
85+
}
86+
8387
// If any local type data is needed for \p type, add it.
8488
//
8589
// NOTE: To be called from TypeData instances.

test/IRGen/moveonly_value_functions.swift

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ public struct InnerDeinitingDestructableNC<T> : ~Copyable {
4949
}
5050
}
5151

52+
public struct InnerDeinitingWithLayoutNC<T> : ~Copyable {
53+
public let t: T
54+
deinit {}
55+
}
56+
57+
public struct InnerDeinitingWithoutLayoutNC<T>: ~Copyable {
58+
public let ptr: Int
59+
deinit {}
60+
}
61+
5262
public struct OuterDeinitingNC_1<T> : ~Copyable {
5363
public let i1: Int
5464
public let c1: C<T>
@@ -95,6 +105,21 @@ extension GenericContext_1 : P where T : P {
95105
}
96106
}
97107

108+
public enum OuterSinglePayloadNC_1<T>: ~Copyable {
109+
case none
110+
case some(InnerDeinitingWithoutLayoutNC<T>)
111+
}
112+
113+
public enum OuterSinglePayloadNC_2<T>: ~Copyable {
114+
case none
115+
case some(InnerDeinitingReleasableNC<T>)
116+
}
117+
118+
public enum OuterSinglePayloadNC_3<T>: ~Copyable {
119+
case none
120+
case some(InnerDeinitingDestructableNC<T>)
121+
}
122+
98123
// Destroyed value:
99124
// - has deinit
100125
// On lifetime end:
@@ -218,3 +243,71 @@ public func takeOuterNC_2<T>(_ o: consuming OuterNC_2<T>) {
218243
// CHECK-SAME: ptr noalias swiftself %0)
219244
// CHECK: }
220245
public func takeGenericContext_1OuterNC_1<T : P>(_ e: consuming GenericContext_1<T>.OuterNC_1) {}
246+
247+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions26takeOuterSinglePayloadNC_1yyAA0efgH2_1OyxGnlF"(
248+
// : i64 %0,
249+
// : i8 %1,
250+
// CHECK-SAME: ptr %T)
251+
// CHECK-SAME: {
252+
// CHECK: call{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_1OyxGlWOe"(
253+
// : i64 %0,
254+
// : i1 %2,
255+
// CHECK-SAME: ptr %T)
256+
// CHECK: }
257+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_1OyxGlWOe"(
258+
// : i64 %0,
259+
// : i1 %1,
260+
// CHECK-SAME: ptr %T)
261+
// CHECK-SAME: {
262+
// CHECK: call{{.*}} @"$s24moveonly_value_functions29InnerDeinitingWithoutLayoutNCVfD"(
263+
// : i64 %0,
264+
// CHECK-SAME: ptr %T)
265+
// CHECK: }
266+
public func takeOuterSinglePayloadNC_1<T>(_ e: consuming OuterSinglePayloadNC_1<T>) {}
267+
268+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions26takeOuterSinglePayloadNC_2yyAA0efgH2_2OyxGnlF"(
269+
// CHECK-SAME: ptr noalias nocapture dereferenceable(64) %0,
270+
// CHECK-SAME: ptr %T)
271+
// CHECK-SAME: {
272+
// CHECK: call{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_2OyxGlWOs"(
273+
// CHECK-SAME: ptr %0,
274+
// CHECK-SAME: ptr %T)
275+
// CHECK: }
276+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_2OyxGlWOs"(
277+
// CHECK-SAME: ptr %0,
278+
// CHECK-SAME: ptr %T)
279+
// CHECK-SAME: {
280+
// CHECK: call{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_2OyxGlWOe"(
281+
// : i64 %2,
282+
// : i64 %4,
283+
// : i64 %6,
284+
// : i64 %8,
285+
// : i64 %10,
286+
// : i64 %12,
287+
// : i64 %14,
288+
// : i64 %16,
289+
// : ptr %T)
290+
// CHECK: }
291+
public func takeOuterSinglePayloadNC_2<T>(_ e: consuming OuterSinglePayloadNC_2<T>) {}
292+
293+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions26takeOuterSinglePayloadNC_3yyAA0efgH2_3OyxGnlF"(
294+
// CHECK-SAME: ptr noalias %0,
295+
// CHECK-SAME: ptr %T)
296+
// CHECK-SAME: {
297+
// CHECK: call{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_3OyxGlWOh"(
298+
// CHECK-SAME: ptr %0,
299+
// CHECK-SAME: ptr %T)
300+
// CHECK: }
301+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions22OuterSinglePayloadNC_3OyxGlWOh"(
302+
// CHECK-SAME: ptr %0,
303+
// CHECK-SAME: ptr %T)
304+
// CHECK-SAME: {
305+
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVMa"(
306+
// : i64 0,
307+
// CHECK-SAME: ptr %T)
308+
// CHECK: [[METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE:%[^,]+]], 0
309+
// CHECK: call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVfD"(
310+
// CHECK-SAME: ptr [[METADATA:%[^,]+]],
311+
// : ptr noalias swiftself %0)
312+
// CHECK: }
313+
public func takeOuterSinglePayloadNC_3<T>(_ e: consuming OuterSinglePayloadNC_3<T>) {}

test/IRGen/moveonly_value_functions_onone.swift

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ extension GenericContext_1 : P where T : P {
9999
}
100100
}
101101

102+
public enum OuterSinglePayloadNC_1<T>: ~Copyable {
103+
case none
104+
case some(InnerDeinitingWithoutLayoutNC<T>)
105+
}
106+
107+
public enum OuterSinglePayloadNC_2<T>: ~Copyable {
108+
case none
109+
case some(InnerDeinitingReleasableNC<T>)
110+
}
111+
112+
public enum OuterSinglePayloadNC_3<T>: ~Copyable {
113+
case none
114+
case some(InnerDeinitingDestructableNC<T>)
115+
}
116+
102117
// Destroyed value:
103118
// - has deinit
104119
// On lifetime end:
@@ -222,3 +237,68 @@ public func takeOuterNC_2<T>(_ o: consuming OuterNC_2<T>) {
222237
// CHECK-SAME: ptr noalias swiftself %0)
223238
// CHECK: }
224239
public func takeGenericContext_1OuterNC_1<T : P>(_ e: consuming GenericContext_1<T>.OuterNC_1) {}
240+
241+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone26takeOuterSinglePayloadNC_1yyAA0fghI2_1OyxGnlF"(
242+
// : i64 %0,
243+
// : i8 %1,
244+
// CHECK-SAME: ptr %T)
245+
// CHECK-SAME: {
246+
// CHECK: call{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_1OyxGlWOh"(
247+
// : i64 %0,
248+
// : i1 %2,
249+
// CHECK-SAME: ptr %T)
250+
// CHECK: }
251+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_1OyxGlWOh"(
252+
// : i64 %0,
253+
// : i1 %1,
254+
// CHECK-SAME: ptr %T)
255+
// CHECK-SAME: {
256+
// CHECK: call{{.*}} @"$s30moveonly_value_functions_onone29InnerDeinitingWithoutLayoutNCVfD"(
257+
// : i64 %0,
258+
// CHECK-SAME: ptr %T)
259+
// CHECK: }
260+
public func takeOuterSinglePayloadNC_1<T>(_ e: consuming OuterSinglePayloadNC_1<T>) {}
261+
262+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone26takeOuterSinglePayloadNC_2yyAA0fghI2_2OyxGnlF"(
263+
// CHECK-SAME: ptr noalias nocapture dereferenceable(64) %0,
264+
// CHECK-SAME: ptr %T)
265+
// CHECK-SAME: {
266+
// CHECK: call{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_2OyxGlWOh"(
267+
// : ptr %0,
268+
// CHECK-SAME: ptr %T)
269+
// CHECK: }
270+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_2OyxGlWOh"(
271+
// CHECK-SAME: ptr %0,
272+
// CHECK-SAME: ptr %T)
273+
// CHECK-SAME: {
274+
// CHECK: [[RESPONSE:%[^,]+]] = call swiftcc %swift.metadata_response @"$s30moveonly_value_functions_onone26InnerDeinitingReleasableNCVMa"(
275+
// CHECK-SAME: i64 0,
276+
// CHECK-SAME: ptr %T)
277+
// CHECK: [[METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
278+
// CHECK: call swiftcc void @"$s30moveonly_value_functions_onone26InnerDeinitingReleasableNCVfD"(
279+
// CHECK-SAME: ptr [[METADATA]],
280+
// CHECK-SAME: ptr noalias nocapture swiftself dereferenceable(64) %0)
281+
// CHECK: }
282+
public func takeOuterSinglePayloadNC_2<T>(_ e: consuming OuterSinglePayloadNC_2<T>) {}
283+
284+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone26takeOuterSinglePayloadNC_3yyAA0fghI2_3OyxGnlF"(
285+
// CHECK-SAME: ptr noalias %0,
286+
// CHECK-SAME: ptr %T)
287+
// CHECK-SAME: {
288+
// CHECK: call{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_3OyxGlWOh"(
289+
// : ptr %0,
290+
// CHECK-SAME: ptr %T)
291+
// CHECK: }
292+
// CHECK-LABEL: define{{.*}} @"$s30moveonly_value_functions_onone22OuterSinglePayloadNC_3OyxGlWOh"(
293+
// CHECK-SAME: ptr %0,
294+
// CHECK-SAME: ptr %T)
295+
// CHECK-SAME: {
296+
// CHECK: [[RESPONSE:%[^,]+]] = call{{.*}} @"$s30moveonly_value_functions_onone28InnerDeinitingDestructableNCVMa"(
297+
// : i64 0,
298+
// CHECK-SAME: ptr %T)
299+
// CHECK: [[METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE:%[^,]+]], 0
300+
// CHECK: call{{.*}} @"$s30moveonly_value_functions_onone28InnerDeinitingDestructableNCVfD"(
301+
// CHECK-SAME: ptr [[METADATA:%[^,]+]],
302+
// : ptr noalias swiftself %0)
303+
// CHECK: }
304+
public func takeOuterSinglePayloadNC_3<T>(_ e: consuming OuterSinglePayloadNC_3<T>) {}

0 commit comments

Comments
 (0)