Skip to content

Commit f638918

Browse files
committed
[IRGen] Multi payload enum consumes call deinits.
They include the necessary metadata.
1 parent 0075682 commit f638918

File tree

3 files changed

+299
-15
lines changed

3 files changed

+299
-15
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3740,7 +3740,7 @@ namespace {
37403740
Explosion src = IGF.collectParameters();
37413741
if (IGM.DebugInfo)
37423742
IGM.DebugInfo->emitArtificialFunction(IGF, IGF.CurFn);
3743-
auto parts = destructureAndTagLoadableEnumFromOutlined(IGF, src);
3743+
auto parts = destructureAndTagLoadableEnumFromOutlined(IGF, src, nullptr);
37443744

37453745
forNontrivialPayloads(IGF, parts.tag, [&](unsigned tagIndex,
37463746
EnumImplStrategy::Element elt) {
@@ -3757,21 +3757,26 @@ namespace {
37573757
return func;
37583758
}
37593759

3760-
llvm::Function *emitConsumeEnumFunction(IRGenModule &IGM,
3761-
SILType type) const {
3760+
llvm::Function *
3761+
emitConsumeEnumFunction(IRGenModule &IGM, SILType type,
3762+
OutliningMetadataCollector &collector) const {
37623763
IRGenMangler Mangler;
37633764
auto manglingBits =
37643765
getTypeAndGenericSignatureForManglingOutlineFunction(type);
37653766
std::string name =
37663767
Mangler.mangleOutlinedConsumeFunction(manglingBits.first,
37673768
manglingBits.second);
3768-
auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType);
3769+
SmallVector<llvm::Type *, 2> params(PayloadTypesAndTagType);
3770+
collector.addPolymorphicParameterTypes(params);
3771+
auto func = createOutlineLLVMFunction(IGM, name, params);
37693772

37703773
IRGenFunction IGF(IGM, func);
37713774
if (IGM.DebugInfo)
37723775
IGM.DebugInfo->emitArtificialFunction(IGF, IGF.CurFn);
37733776
Explosion src = IGF.collectParameters();
3774-
auto parts = destructureAndTagLoadableEnumFromOutlined(IGF, src);
3777+
auto parts =
3778+
destructureAndTagLoadableEnumFromOutlined(IGF, src, &collector);
3779+
collector.bindPolymorphicParameters(IGF, src);
37753780

37763781
forNontrivialPayloads(IGF, parts.tag, [&](unsigned tagIndex,
37773782
EnumImplStrategy::Element elt) {
@@ -3826,12 +3831,15 @@ namespace {
38263831
bool allTriviallyDestroyable = true;
38273832
bool allBitwiseTakable = true;
38283833
bool allSingleRefcount = true;
3834+
bool allCopyable = true;
38293835
bool haveRefcounting = false;
38303836
for (auto &elt : ElementsWithPayload) {
38313837
if (!elt.ti->isTriviallyDestroyable(ResilienceExpansion::Maximal))
38323838
allTriviallyDestroyable = false;
38333839
if (!elt.ti->isBitwiseTakable(ResilienceExpansion::Maximal))
38343840
allBitwiseTakable = false;
3841+
if (!elt.ti->isCopyable(ResilienceExpansion::Maximal))
3842+
allCopyable = false;
38353843

38363844
// refcounting is only set in the else branches
38373845
ReferenceCounting refcounting;
@@ -3861,7 +3869,7 @@ namespace {
38613869
} else if (allSingleRefcount
38623870
&& ElementsWithNoPayload.size() <= 1) {
38633871
CopyDestroyKind = TaggedRefcounted;
3864-
} else if (allBitwiseTakable) {
3872+
} else if (allBitwiseTakable && allCopyable) {
38653873
CopyDestroyKind = BitwiseTakable;
38663874
}
38673875
}
@@ -4048,11 +4056,11 @@ namespace {
40484056

40494057
return {destructured.payload, destructured.extraTagBits, tag};
40504058
}
4051-
DestructuredAndTaggedLoadableEnum
4052-
destructureAndTagLoadableEnumFromOutlined(IRGenFunction &IGF,
4053-
Explosion &src) const {
4059+
DestructuredAndTaggedLoadableEnum destructureAndTagLoadableEnumFromOutlined(
4060+
IRGenFunction &IGF, Explosion &src,
4061+
OutliningMetadataCollector *collector) const {
40544062
EnumPayload payload;
4055-
unsigned claimSZ = src.size();
4063+
unsigned claimSZ = src.size() - (collector ? collector->size() : 0);
40564064
if (ExtraTagBitCount > 0) {
40574065
--claimSZ;
40584066
}
@@ -4722,13 +4730,23 @@ namespace {
47224730
payload.emitApplyAndMask(IGF, mask);
47234731
}
47244732

4725-
void fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src,
4726-
Explosion &out) const {
4733+
void
4734+
fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src,
4735+
Explosion &out,
4736+
OutliningMetadataCollector *collector) const {
47274737
assert(out.empty() && "Out explosion must be empty!");
47284738
auto parts = destructureAndTagLoadableEnum(IGF, src);
47294739
parts.payload.explode(IGM, out);
47304740
if (parts.extraTagBits)
47314741
out.add(parts.extraTagBits);
4742+
4743+
if (!collector)
4744+
return;
4745+
llvm::SmallVector<llvm::Value *, 4> args;
4746+
collector->addPolymorphicArguments(args);
4747+
for (auto *arg : args) {
4748+
out.add(arg);
4749+
}
47324750
}
47334751

47344752
public:
@@ -4786,7 +4804,7 @@ namespace {
47864804
if (!copyEnumFunction)
47874805
copyEnumFunction = emitCopyEnumFunction(IGM, loweredType);
47884806
Explosion tmp;
4789-
fillExplosionForOutlinedCall(IGF, src, tmp);
4807+
fillExplosionForOutlinedCall(IGF, src, tmp, nullptr);
47904808
llvm::CallInst *call = IGF.Builder.CreateCallWithoutDbgLoc(
47914809
copyEnumFunction->getFunctionType(), copyEnumFunction,
47924810
tmp.getAll());
@@ -4849,10 +4867,13 @@ namespace {
48494867
});
48504868
return;
48514869
}
4870+
OutliningMetadataCollector collector(T, IGF, LayoutIsNotNeeded,
4871+
DeinitIsNeeded);
4872+
IGF.getTypeInfo(T).collectMetadataForOutlining(collector, T);
48524873
if (!consumeEnumFunction)
4853-
consumeEnumFunction = emitConsumeEnumFunction(IGM, loweredType);
4874+
consumeEnumFunction = emitConsumeEnumFunction(IGM, T, collector);
48544875
Explosion tmp;
4855-
fillExplosionForOutlinedCall(IGF, src, tmp);
4876+
fillExplosionForOutlinedCall(IGF, src, tmp, &collector);
48564877
llvm::CallInst *call = IGF.Builder.CreateCallWithoutDbgLoc(
48574878
consumeEnumFunction->getFunctionType(), consumeEnumFunction,
48584879
tmp.claimAll());

test/IRGen/moveonly_value_functions.swift

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,31 @@ public enum OuterSinglePayloadNC_3<T>: ~Copyable {
120120
case some(InnerDeinitingDestructableNC<T>)
121121
}
122122

123+
public enum OuterMultiPayloadNC_1<T>: ~Copyable {
124+
case none
125+
case some(InnerDeinitingWithLayoutNC<T>)
126+
case some2(InnerDeinitingWithLayoutNC<T>)
127+
}
128+
129+
public enum OuterMultiPayloadNC_2<T>: ~Copyable {
130+
case none
131+
case some(InnerDeinitingWithoutLayoutNC<T>)
132+
case some2(InnerDeinitingWithoutLayoutNC<T>)
133+
}
134+
135+
// FIXME: Uncomment.
136+
public enum OuterMultiPayloadNC_3<T>: ~Copyable {
137+
case none
138+
case some(InnerDeinitingReleasableNC<T>)
139+
case some2(InnerDeinitingReleasableNC<T>)
140+
}
141+
142+
public enum OuterMultiPayloadNC_4<T>: ~Copyable {
143+
case none
144+
case some(InnerDeinitingDestructableNC<T>)
145+
case some2(InnerDeinitingDestructableNC<T>)
146+
}
147+
123148
// Destroyed value:
124149
// - has deinit
125150
// On lifetime end:
@@ -311,3 +336,107 @@ public func takeOuterSinglePayloadNC_2<T>(_ e: consuming OuterSinglePayloadNC_2<
311336
// : ptr noalias swiftself %0)
312337
// CHECK: }
313338
public func takeOuterSinglePayloadNC_3<T>(_ e: consuming OuterSinglePayloadNC_3<T>) {}
339+
340+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions25takeOuterMultiPayloadNC_1yyAA0efgH2_1OyxGnlF"(
341+
// CHECK-SAME: ptr noalias %0,
342+
// CHECK-SAME: ptr %T)
343+
// CHECK-SAME: {
344+
// CHECK: call{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_1OyxGlWOh"(
345+
// CHECK-SAME: ptr %0,
346+
// CHECK-SAME: ptr %T)
347+
// CHECK: }
348+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_1OyxGlWOh"(
349+
// CHECK-SAME: ptr %0,
350+
// CHECK-SAME: ptr %T)
351+
// CHECK-SAME: {
352+
// CHECK: [[RESPONSE1:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingWithLayoutNCVMa"(
353+
// : i64 0,
354+
// CHECK-SAME: ptr %T)
355+
// CHECK: [[METADATA1:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE1]], 0
356+
// CHECK: call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingWithLayoutNCVfD"(
357+
// CHECK-SAME: ptr [[METADATA1]],
358+
// CHECK-SAME: ptr noalias swiftself %0)
359+
// CHECK: [[RESPONSE2:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingWithLayoutNCVMa"(
360+
// : i64 0,
361+
// CHECK-SAME: ptr %T)
362+
// CHECK: [[METADATA2:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE2]], 0
363+
// CHECK: call{{.*}} @"$s24moveonly_value_functions26InnerDeinitingWithLayoutNCVfD"(
364+
// CHECK-SAME: ptr [[METADATA2]],
365+
// CHECK-SAME: ptr noalias swiftself %0)
366+
// CHECK: }
367+
public func takeOuterMultiPayloadNC_1<T>(_ e: consuming OuterMultiPayloadNC_1<T>) {}
368+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions25takeOuterMultiPayloadNC_2yyAA0efgH2_2OyxGnlF"(
369+
// : i64 %0,
370+
// : i8 %1,
371+
// CHECK-SAME: ptr %T)
372+
// CHECK-SAME: {
373+
// CHECK: call{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_2OyxGlWOe"(
374+
// : i64 %0,
375+
// : i8 %1,
376+
// CHECK-SAME: ptr %T)
377+
// CHECK: }
378+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_2OyxGlWOe"(
379+
// : i64 %0,
380+
// : i8 %1,
381+
// CHECK-SAME: ptr %T)
382+
// CHECK-SAME: {
383+
// CHECK: call{{.*}} @"$s24moveonly_value_functions29InnerDeinitingWithoutLayoutNCVfD"(
384+
// : i64 %0,
385+
// CHECK-SAME: ptr %T)
386+
// CHECK: call{{.*}} @"$s24moveonly_value_functions29InnerDeinitingWithoutLayoutNCVfD"(
387+
// : i64 %0,
388+
// CHECK-SAME: ptr %T)
389+
// CHECK: }
390+
public func takeOuterMultiPayloadNC_2<T>(_ e: consuming OuterMultiPayloadNC_2<T>) {}
391+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions25takeOuterMultiPayloadNC_3yyAA0efgH2_3OyxGnlF"(
392+
// CHECK-SAME: ptr noalias nocapture dereferenceable(64) %0,
393+
// CHECK-SAME: ptr %T)
394+
// CHECK-SAME: {
395+
// CHECK: call{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_3OyxGlWOs"(
396+
// CHECK-SAME: ptr %0,
397+
// CHECK-SAME: ptr %T)
398+
// CHECK: }
399+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_3OyxGlWOs"(
400+
// CHECK-SAME: ptr %0,
401+
// CHECK-SAME: ptr %T)
402+
// CHECK-SAME: {
403+
// CHECK: call{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_3OyxGlWOe"(
404+
// : i64 %2,
405+
// : i64 %4,
406+
// : i64 %6,
407+
// : i64 %8,
408+
// : i64 %10,
409+
// : i64 %12,
410+
// : i64 %14,
411+
// : i64 %16,
412+
// CHECK-SAME: ptr %T)
413+
// CHECK: }
414+
public func takeOuterMultiPayloadNC_3<T>(_ e: consuming OuterMultiPayloadNC_3<T>) {}
415+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions25takeOuterMultiPayloadNC_4yyAA0efgH2_4OyxGnlF"(
416+
// CHECK-SAME: ptr noalias %0,
417+
// CHECK-SAME: ptr %T)
418+
// CHECK-SAME: {
419+
// CHECK: call{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_4OyxGlWOh"(
420+
// CHECK-SAME: ptr %0,
421+
// CHECK-SAME: ptr %T)
422+
// CHECK: }
423+
// CHECK-LABEL: define{{.*}} @"$s24moveonly_value_functions21OuterMultiPayloadNC_4OyxGlWOh"(
424+
// CHECK-SAME: ptr %0,
425+
// CHECK-SAME: ptr %T)
426+
// CHECK-SAME: {
427+
// CHECK: [[RESPONSE1:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVMa"(
428+
// : i64 0,
429+
// CHECK-SAME: ptr %T)
430+
// CHECK: [[METADATA1:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE1]], 0
431+
// CHECK: call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVfD"(
432+
// CHECK-SAME: ptr [[METADATA1]],
433+
// CHECK-SAME: ptr noalias swiftself %0)
434+
// CHECK: [[RESPONSE2:%[^,]+]] = call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVMa"(
435+
// : i64 0,
436+
// CHECK-SAME: ptr %T)
437+
// CHECK: [[METADATA2:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE2]], 0
438+
// CHECK: call{{.*}} @"$s24moveonly_value_functions28InnerDeinitingDestructableNCVfD"(
439+
// CHECK-SAME: ptr [[METADATA2]],
440+
// CHECK-SAME: ptr noalias swiftself %0)
441+
// CHECK: }
442+
public func takeOuterMultiPayloadNC_4<T>(_ e: consuming OuterMultiPayloadNC_4<T>) {}

0 commit comments

Comments
 (0)