Skip to content

Commit 136c179

Browse files
authored
Merge pull request #63840 from jckarter/irgen-struct-deinit
IRGen: Use `deinit` to destroy move-only structs that have them.
2 parents 7ac96f8 + afa5837 commit 136c179

14 files changed

+449
-50
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,10 @@ namespace {
529529
}
530530

531531
void assign(IRGenFunction &IGF, Explosion &e, Address addr,
532-
bool isOutlined) const override {
532+
bool isOutlined, SILType T) const override {
533533
if (!getLoadableSingleton()) return;
534534
getLoadableSingleton()->assign(IGF, e, getSingletonAddress(IGF, addr),
535-
isOutlined);
535+
isOutlined, getSingletonType(IGF.IGM, T));
536536
}
537537

538538
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src,
@@ -623,9 +623,11 @@ namespace {
623623
}
624624

625625
void consume(IRGenFunction &IGF, Explosion &src,
626-
Atomicity atomicity) const override {
626+
Atomicity atomicity,
627+
SILType T) const override {
627628
if (getLoadableSingleton())
628-
getLoadableSingleton()->consume(IGF, src, atomicity);
629+
getLoadableSingleton()->consume(IGF, src, atomicity,
630+
getSingletonType(IGF.IGM, T));
629631
}
630632

631633
void fixLifetime(IRGenFunction &IGF, Explosion &src) const override {
@@ -1495,14 +1497,14 @@ namespace {
14951497
}
14961498

14971499
void assign(IRGenFunction &IGF, Explosion &e, Address addr,
1498-
bool isOutlined) const override {
1500+
bool isOutlined, SILType T) const override {
14991501
assert(TIK >= Loadable);
15001502
Explosion old;
15011503
if (!isPOD(ResilienceExpansion::Maximal))
15021504
loadAsTake(IGF, addr, old);
15031505
initialize(IGF, e, addr, isOutlined);
15041506
if (!isPOD(ResilienceExpansion::Maximal))
1505-
consume(IGF, old, IGF.getDefaultAtomicity());
1507+
consume(IGF, old, IGF.getDefaultAtomicity(), T);
15061508
}
15071509

15081510
void initialize(IRGenFunction &IGF, Explosion &e, Address addr,
@@ -1780,7 +1782,8 @@ namespace {
17801782
Explosion payloadValue;
17811783
auto &loadableTI = getLoadablePayloadTypeInfo();
17821784
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
1783-
loadableTI.consume(IGF, payloadValue, IGF.getDefaultAtomicity());
1785+
loadableTI.consume(IGF, payloadValue, IGF.getDefaultAtomicity(),
1786+
getPayloadType(IGF.IGM, theEnumType));
17841787
}
17851788

17861789
IGF.Builder.CreateBr(endBB);
@@ -2640,7 +2643,7 @@ namespace {
26402643
}
26412644

26422645
void consume(IRGenFunction &IGF, Explosion &src,
2643-
Atomicity atomicity) const override {
2646+
Atomicity atomicity, SILType T) const override {
26442647
assert(TIK >= Loadable);
26452648

26462649
switch (CopyDestroyKind) {
@@ -2666,7 +2669,8 @@ namespace {
26662669
Explosion payloadValue;
26672670
auto &loadableTI = getLoadablePayloadTypeInfo();
26682671
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
2669-
loadableTI.consume(IGF, payloadValue, IGF.getDefaultAtomicity());
2672+
loadableTI.consume(IGF, payloadValue, IGF.getDefaultAtomicity(),
2673+
getPayloadType(IGF.IGM, T));
26702674
}
26712675

26722676
IGF.Builder.CreateBr(endBB);
@@ -2699,7 +2703,8 @@ namespace {
26992703
// operation.
27002704
Explosion srcAsPayload;
27012705
unpackIntoPayloadExplosion(IGF, src, srcAsPayload);
2702-
payloadTI.consume(IGF, srcAsPayload, atomicity);
2706+
payloadTI.consume(IGF, srcAsPayload, atomicity,
2707+
getPayloadType(IGF.IGM, T));
27032708
return;
27042709
}
27052710
}
@@ -3607,7 +3612,10 @@ namespace {
36073612
Explosion value;
36083613
projectPayloadValue(IGF, parts.payload, tagIndex, lti, value);
36093614

3610-
lti.consume(IGF, value, IGF.getDefaultAtomicity());
3615+
lti.consume(IGF, value, IGF.getDefaultAtomicity(),
3616+
type.getEnumElementType(elt.decl,
3617+
IGM.getSILTypes(),
3618+
IGM.getMaximalTypeExpansionContext()));
36113619
});
36123620

36133621
IGF.Builder.CreateRetVoid();
@@ -4636,7 +4644,7 @@ namespace {
46364644
}
46374645

46384646
void consume(IRGenFunction &IGF, Explosion &src,
4639-
Atomicity atomicity) const override {
4647+
Atomicity atomicity, SILType T) const override {
46404648
assert(TIK >= Loadable);
46414649
switch (CopyDestroyKind) {
46424650
case POD:
@@ -4658,7 +4666,10 @@ namespace {
46584666
Explosion value;
46594667
projectPayloadValue(IGF, parts.payload, tagIndex, lti, value);
46604668

4661-
lti.consume(IGF, value, IGF.getDefaultAtomicity());
4669+
lti.consume(IGF, value, IGF.getDefaultAtomicity(),
4670+
T.getEnumElementType(elt.decl,
4671+
IGF.IGM.getSILTypes(),
4672+
IGF.IGM.getMaximalTypeExpansionContext()));
46624673
});
46634674
return;
46644675
}
@@ -4753,7 +4764,7 @@ namespace {
47534764

47544765
loadAsTake(IGF, dest, tmpOld);
47554766
initialize(IGF, tmpSrc, dest, isOutlined);
4756-
consume(IGF, tmpOld, IGF.getDefaultAtomicity());
4767+
consume(IGF, tmpOld, IGF.getDefaultAtomicity(), T);
47574768
return;
47584769
}
47594770

@@ -4998,7 +5009,7 @@ namespace {
49985009
if (TI->isLoadable()) {
49995010
Explosion tmp;
50005011
loadAsTake(IGF, addr, tmp);
5001-
consume(IGF, tmp, IGF.getDefaultAtomicity());
5012+
consume(IGF, tmp, IGF.getDefaultAtomicity(), T);
50025013
return;
50035014
}
50045015

@@ -5892,7 +5903,7 @@ namespace {
58925903
}
58935904

58945905
void assign(IRGenFunction &IGF, Explosion &e, Address addr,
5895-
bool isOutlined) const override {
5906+
bool isOutlined, SILType T) const override {
58965907
llvm_unreachable("resilient enums are always indirect");
58975908
}
58985909

@@ -5912,7 +5923,7 @@ namespace {
59125923
}
59135924

59145925
void consume(IRGenFunction &IGF, Explosion &src,
5915-
Atomicity atomicity) const override {
5926+
Atomicity atomicity, SILType T) const override {
59165927
llvm_unreachable("resilient enums are always indirect");
59175928
}
59185929

@@ -6337,8 +6348,8 @@ namespace {
63376348
return Strategy.loadAsTake(IGF, addr, e);
63386349
}
63396350
void assign(IRGenFunction &IGF, Explosion &e, Address addr,
6340-
bool isOutlined) const override {
6341-
return Strategy.assign(IGF, e, addr, isOutlined);
6351+
bool isOutlined, SILType T) const override {
6352+
return Strategy.assign(IGF, e, addr, isOutlined, T);
63426353
}
63436354
void initialize(IRGenFunction &IGF, Explosion &e, Address addr,
63446355
bool isOutlined) const override {
@@ -6353,8 +6364,8 @@ namespace {
63536364
return Strategy.copy(IGF, src, dest, atomicity);
63546365
}
63556366
void consume(IRGenFunction &IGF, Explosion &src,
6356-
Atomicity atomicity) const override {
6357-
return Strategy.consume(IGF, src, atomicity);
6367+
Atomicity atomicity, SILType T) const override {
6368+
return Strategy.consume(IGF, src, atomicity, T);
63586369
}
63596370
void fixLifetime(IRGenFunction &IGF, Explosion &src) const override {
63606371
return Strategy.fixLifetime(IGF, src);

lib/IRGen/GenEnum.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,15 @@ class EnumImplStrategy {
419419
virtual void loadAsTake(IRGenFunction &IGF, Address addr,
420420
Explosion &e) const = 0;
421421
virtual void assign(IRGenFunction &IGF, Explosion &e, Address addr,
422-
bool isOutlined) const = 0;
422+
bool isOutlined, SILType T) const = 0;
423423
virtual void initialize(IRGenFunction &IGF, Explosion &e, Address addr,
424424
bool isOutlined) const = 0;
425425
virtual void reexplode(IRGenFunction &IGF, Explosion &src,
426426
Explosion &dest) const = 0;
427427
virtual void copy(IRGenFunction &IGF, Explosion &src,
428428
Explosion &dest, Atomicity atomicity) const = 0;
429429
virtual void consume(IRGenFunction &IGF, Explosion &src,
430-
Atomicity atomicity) const = 0;
430+
Atomicity atomicity, SILType T) const = 0;
431431
virtual void fixLifetime(IRGenFunction &IGF, Explosion &src) const = 0;
432432
virtual void packIntoEnumPayload(IRGenFunction &IGF,
433433
EnumPayload &payload,

lib/IRGen/GenExistential.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ namespace {
450450
}
451451

452452
void assign(IRGenFunction &IGF, Explosion &e, Address address,
453-
bool isOutlined) const override {
453+
bool isOutlined, SILType T) const override {
454454
// Assign the value.
455455
Address instanceAddr = asDerived().projectValue(IGF, address);
456456
llvm::Value *old = IGF.Builder.CreateLoad(instanceAddr);
@@ -483,7 +483,8 @@ namespace {
483483
src.transferInto(dest, getNumStoredProtocols());
484484
}
485485

486-
void consume(IRGenFunction &IGF, Explosion &src, Atomicity atomicity)
486+
void consume(IRGenFunction &IGF, Explosion &src, Atomicity atomicity,
487+
SILType T)
487488
const override {
488489
// Copy the instance pointer.
489490
llvm::Value *value = src.claimNext();

lib/IRGen/GenRecord.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,22 @@ class RecordTypeInfo<Impl, Base, FieldImpl,
741741
}
742742
}
743743

744+
template <void (LoadableTypeInfo::*Op)(IRGenFunction &IGF, Explosion &in,
745+
Address addr, bool isOutlined,
746+
SILType T) const>
747+
void forAllFields(IRGenFunction &IGF, Explosion &in, Address addr,
748+
bool isOutlined, SILType T) const {
749+
auto offsets = asImpl().getNonFixedOffsets(IGF);
750+
for (auto &field : getFields()) {
751+
if (field.isEmpty()) continue;
752+
753+
Address fieldAddr = field.projectAddress(IGF, addr, offsets);
754+
(cast<LoadableTypeInfo>(field.getTypeInfo()).*Op)(IGF, in, fieldAddr,
755+
isOutlined,
756+
field.getType(IGF.IGM, T));
757+
}
758+
}
759+
744760
public:
745761
using super::getFields;
746762

@@ -755,8 +771,8 @@ class RecordTypeInfo<Impl, Base, FieldImpl,
755771
}
756772

757773
void assign(IRGenFunction &IGF, Explosion &e, Address addr,
758-
bool isOutlined) const override {
759-
forAllFields<&LoadableTypeInfo::assign>(IGF, e, addr, isOutlined);
774+
bool isOutlined, SILType T) const override {
775+
forAllFields<&LoadableTypeInfo::assign>(IGF, e, addr, isOutlined, T);
760776
}
761777

762778
void initialize(IRGenFunction &IGF, Explosion &e, Address addr,
@@ -782,10 +798,11 @@ class RecordTypeInfo<Impl, Base, FieldImpl,
782798
}
783799

784800
void consume(IRGenFunction &IGF, Explosion &src,
785-
Atomicity atomicity) const override {
786-
for (auto &field : getFields())
801+
Atomicity atomicity, SILType T) const override {
802+
for (auto &field : getFields()) {
787803
cast<LoadableTypeInfo>(field.getTypeInfo())
788-
.consume(IGF, src, atomicity);
804+
.consume(IGF, src, atomicity, field.getType(IGF.IGM, T));
805+
}
789806
}
790807

791808
void fixLifetime(IRGenFunction &IGF, Explosion &src) const override {

lib/IRGen/GenStruct.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,18 @@ namespace {
250250
return fields[0].getTypeInfo().isSingleRetainablePointer(expansion, rc);
251251
}
252252

253+
void destroy(IRGenFunction &IGF, Address address, SILType T,
254+
bool isOutlined) const override {
255+
// If the struct has a deinit declared, then call it to destroy the
256+
// value.
257+
if (tryEmitDestroyUsingDeinit(IGF, address, T)) {
258+
return;
259+
}
260+
261+
// Otherwise, perform elementwise destruction of the value.
262+
return super::destroy(IGF, address, T, isOutlined);
263+
}
264+
253265
void verify(IRGenTypeVerifierFunction &IGF,
254266
llvm::Value *metadata,
255267
SILType structType) const override {
@@ -748,6 +760,7 @@ namespace {
748760
/// A type implementation for loadable struct types.
749761
class LoadableStructTypeInfo final
750762
: public StructTypeInfoBase<LoadableStructTypeInfo, LoadableTypeInfo> {
763+
using super = StructTypeInfoBase<LoadableStructTypeInfo, LoadableTypeInfo>;
751764
public:
752765
LoadableStructTypeInfo(ArrayRef<StructFieldInfo> fields,
753766
unsigned explosionSize,
@@ -814,6 +827,18 @@ namespace {
814827
const StructFieldInfo &field) const {
815828
llvm_unreachable("non-fixed field in loadable type?");
816829
}
830+
831+
void consume(IRGenFunction &IGF, Explosion &explosion,
832+
Atomicity atomicity, SILType T) const override {
833+
// If the struct has a deinit declared, then call it to consume the
834+
// value.
835+
if (tryEmitConsumeUsingDeinit(IGF, explosion, T)) {
836+
return;
837+
}
838+
839+
// Otherwise, do elementwise destruction of the value.
840+
return super::consume(IGF, explosion, atomicity, T);
841+
}
817842
};
818843

819844
/// A type implementation for non-loadable but fixed-size struct types.

0 commit comments

Comments
 (0)