Skip to content

Commit ad6f6de

Browse files
committed
IRGen: We cannot call destroy through metadata of private types of non-copyable fields
So call the destroy on the closing type instead. Amends the concepts areFieldsABIAccessible/isABIAccessible to take metadata accessibility of non-copyable types into account. rdar://133990500
1 parent ebe1769 commit ad6f6de

19 files changed

+268
-85
lines changed

lib/IRGen/FixedTypeInfo.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ class FixedTypeInfo : public TypeInfo {
4646
IsBitwiseTakable_t bt,
4747
IsCopyable_t copy,
4848
IsFixedSize_t alwaysFixedSize,
49+
IsABIAccessible_t isABIAccessible,
4950
SpecialTypeInfoKind stik = SpecialTypeInfoKind::Fixed)
50-
: TypeInfo(type, align, pod, bt, copy, alwaysFixedSize, IsABIAccessible, stik),
51+
: TypeInfo(type, align, pod, bt, copy, alwaysFixedSize, isABIAccessible, stik),
5152
SpareBits(spareBits) {
5253
assert(SpareBits.size() == size.getValueInBits());
5354
assert(isFixedSize());
@@ -61,8 +62,9 @@ class FixedTypeInfo : public TypeInfo {
6162
IsBitwiseTakable_t bt,
6263
IsCopyable_t copy,
6364
IsFixedSize_t alwaysFixedSize,
65+
IsABIAccessible_t isABIAccessible,
6466
SpecialTypeInfoKind stik = SpecialTypeInfoKind::Fixed)
65-
: TypeInfo(type, align, pod, bt, copy, alwaysFixedSize, IsABIAccessible, stik),
67+
: TypeInfo(type, align, pod, bt, copy, alwaysFixedSize, isABIAccessible, stik),
6668
SpareBits(std::move(spareBits)) {
6769
assert(SpareBits.size() == size.getValueInBits());
6870
assert(isFixedSize());
@@ -73,7 +75,6 @@ class FixedTypeInfo : public TypeInfo {
7375
public:
7476
// This is useful for metaprogramming.
7577
static bool isFixed() { return true; }
76-
static IsABIAccessible_t isABIAccessible() { return IsABIAccessible; }
7778

7879
/// Whether this type is known to be empty.
7980
bool isKnownEmpty(ResilienceExpansion expansion) const {

lib/IRGen/GenConcurrency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ExecutorTypeInfo :
4646
Size size, Alignment align, SpareBitVector &&spareBits)
4747
: TrivialScalarPairTypeInfo(storageType, size, std::move(spareBits),
4848
align, IsTriviallyDestroyable,
49-
IsCopyable, IsFixedSize) {}
49+
IsCopyable, IsFixedSize, IsABIAccessible) {}
5050

5151
static Size getFirstElementSize(IRGenModule &IGM) {
5252
return IGM.getPointerSize();

lib/IRGen/GenDiffFunc.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ class DifferentiableFuncTypeInfo final
9696
unsigned explosionSize, llvm::Type *ty, Size size,
9797
SpareBitVector &&spareBits, Alignment align,
9898
IsTriviallyDestroyable_t isTriviallyDestroyable, IsFixedSize_t alwaysFixedSize)
99-
: super(fields, explosionSize, ty, size, std::move(spareBits), align,
100-
isTriviallyDestroyable, IsCopyable, alwaysFixedSize) {}
99+
: super(fields, explosionSize, FieldsAreABIAccessible, ty, size, std::move(spareBits), align,
100+
isTriviallyDestroyable, IsCopyable, alwaysFixedSize, IsABIAccessible) {}
101101

102102
Address projectFieldAddress(IRGenFunction &IGF, Address addr, SILType T,
103103
const DifferentiableFuncFieldInfo &field) const {
@@ -174,12 +174,14 @@ class DifferentiableFuncTypeBuilder
174174
}
175175

176176
TypeInfo *createFixed(ArrayRef<DifferentiableFuncFieldInfo> fields,
177+
FieldsAreABIAccessible_t unused,
177178
StructLayout &&layout) {
178179
llvm_unreachable("@differentiable functions are always loadable");
179180
}
180181

181182
DifferentiableFuncTypeInfo *
182183
createLoadable(ArrayRef<DifferentiableFuncFieldInfo> fields,
184+
FieldsAreABIAccessible_t unused,
183185
StructLayout &&layout, unsigned explosionSize) {
184186
return DifferentiableFuncTypeInfo::create(
185187
fields, explosionSize, layout.getType(), layout.getSize(),
@@ -273,8 +275,8 @@ class LinearFuncTypeInfo final
273275
unsigned explosionSize, llvm::Type *ty, Size size,
274276
SpareBitVector &&spareBits, Alignment align, IsTriviallyDestroyable_t isTriviallyDestroyable,
275277
IsFixedSize_t alwaysFixedSize)
276-
: super(fields, explosionSize, ty, size, std::move(spareBits), align,
277-
isTriviallyDestroyable, IsCopyable, alwaysFixedSize) {}
278+
: super(fields, explosionSize, FieldsAreABIAccessible, ty, size, std::move(spareBits), align,
279+
isTriviallyDestroyable, IsCopyable, alwaysFixedSize, IsABIAccessible) {}
278280

279281
Address projectFieldAddress(IRGenFunction &IGF, Address addr, SILType T,
280282
const LinearFuncFieldInfo &field) const {
@@ -345,11 +347,13 @@ class LinearFuncTypeBuilder
345347
}
346348

347349
TypeInfo *createFixed(ArrayRef<LinearFuncFieldInfo> fields,
350+
FieldsAreABIAccessible_t areFieldsABIAccessible,
348351
StructLayout &&layout) {
349352
llvm_unreachable("@differentiable functions are always loadable");
350353
}
351354

352355
LinearFuncTypeInfo *createLoadable(ArrayRef<LinearFuncFieldInfo> fields,
356+
FieldsAreABIAccessible_t unused,
353357
StructLayout &&layout,
354358
unsigned explosionSize) {
355359
return LinearFuncTypeInfo::create(

lib/IRGen/GenEnum.cpp

Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,15 @@ namespace {
659659
void consume(IRGenFunction &IGF, Explosion &src,
660660
Atomicity atomicity,
661661
SILType T) const override {
662-
if (tryEmitConsumeUsingDeinit(IGF, src, T)) {
662+
if (ElementsAreABIAccessible &&
663+
tryEmitConsumeUsingDeinit(IGF, src, T)) {
664+
return;
665+
}
666+
667+
if (!ElementsAreABIAccessible) {
668+
auto temporary = TI->allocateStack(IGF, T, "deinit.arg").getAddress();
669+
cast<LoadableTypeInfo>(TI)->initialize(IGF, src, temporary, /*outlined*/false);
670+
emitDestroyCall(IGF, T, temporary);
663671
return;
664672
}
665673

@@ -674,10 +682,11 @@ namespace {
674682

675683
void destroy(IRGenFunction &IGF, Address addr, SILType T,
676684
bool isOutlined) const override {
677-
if (tryEmitDestroyUsingDeinit(IGF, addr, T)) {
685+
if (ElementsAreABIAccessible &&
686+
tryEmitDestroyUsingDeinit(IGF, addr, T)) {
678687
return;
679688
}
680-
689+
681690
if (getSingleton() &&
682691
!getSingleton()->isTriviallyDestroyable(ResilienceExpansion::Maximal)) {
683692
if (!ElementsAreABIAccessible) {
@@ -1986,6 +1995,7 @@ namespace {
19861995

19871996
// If the payload is TriviallyDestroyable, then we can use TriviallyDestroyable value semantics.
19881997
auto &payloadTI = *ElementsWithPayload[0].ti;
1998+
19891999
if (!payloadTI.isABIAccessible()) {
19902000
CopyDestroyKind = ABIInaccessible;
19912001
} else if (payloadTI.isTriviallyDestroyable(ResilienceExpansion::Maximal)) {
@@ -2848,9 +2858,18 @@ namespace {
28482858

28492859
void consume(IRGenFunction &IGF, Explosion &src,
28502860
Atomicity atomicity, SILType T) const override {
2851-
if (tryEmitConsumeUsingDeinit(IGF, src, T)) {
2861+
if (ElementsAreABIAccessible &&
2862+
tryEmitConsumeUsingDeinit(IGF, src, T)) {
28522863
return;
28532864
}
2865+
2866+
if (!ElementsAreABIAccessible) {
2867+
auto temporary = TI->allocateStack(IGF, T, "deinit.arg").getAddress();
2868+
cast<LoadableTypeInfo>(TI)->initialize(IGF, src, temporary, /*outlined*/false);
2869+
emitDestroyCall(IGF, T, temporary);
2870+
return;
2871+
}
2872+
28542873
assert(TIK >= Loadable);
28552874

28562875
switch (CopyDestroyKind) {
@@ -2968,7 +2987,8 @@ namespace {
29682987

29692988
void destroy(IRGenFunction &IGF, Address addr, SILType T,
29702989
bool isOutlined) const override {
2971-
if (tryEmitDestroyUsingDeinit(IGF, addr, T)) {
2990+
if (ElementsAreABIAccessible &&
2991+
tryEmitDestroyUsingDeinit(IGF, addr, T)) {
29722992
return;
29732993
}
29742994

@@ -4879,9 +4899,18 @@ namespace {
48794899

48804900
void consume(IRGenFunction &IGF, Explosion &src,
48814901
Atomicity atomicity, SILType T) const override {
4882-
if (tryEmitConsumeUsingDeinit(IGF, src, T)) {
4902+
if (ElementsAreABIAccessible &&
4903+
tryEmitConsumeUsingDeinit(IGF, src, T)) {
48834904
return;
48844905
}
4906+
4907+
if (!ElementsAreABIAccessible) {
4908+
auto temporary = TI->allocateStack(IGF, T, "deinit.arg").getAddress();
4909+
cast<LoadableTypeInfo>(TI)->initialize(IGF, src, temporary, /*outlined*/false);
4910+
emitDestroyCall(IGF, T, temporary);
4911+
return;
4912+
}
4913+
48854914
assert(TIK >= Loadable);
48864915
switch (CopyDestroyKind) {
48874916
case TriviallyDestroyable:
@@ -5230,7 +5259,8 @@ namespace {
52305259

52315260
void destroy(IRGenFunction &IGF, Address addr, SILType T,
52325261
bool isOutlined) const override {
5233-
if (tryEmitDestroyUsingDeinit(IGF, addr, T)) {
5262+
if (ElementsAreABIAccessible &&
5263+
tryEmitDestroyUsingDeinit(IGF, addr, T)) {
52345264
return;
52355265
}
52365266

@@ -6407,7 +6437,6 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
64076437
// fixed-size from this resilience scope.
64086438
ResilienceExpansion layoutScope =
64096439
TC.IGM.getResilienceExpansionForLayout(theEnum);
6410-
64116440
for (auto elt : theEnum->getAllElements()) {
64126441
++numElements;
64136442

@@ -6652,8 +6681,6 @@ namespace {
66526681
public:
66536682
using EnumTypeInfoBase<Base>::Strategy;
66546683

6655-
/// \group Methods delegated to the EnumImplStrategy
6656-
66576684
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
66586685
return Strategy.getFixedExtraInhabitantCount(IGM);
66596686
}
@@ -6693,10 +6720,11 @@ namespace {
66936720
IsTriviallyDestroyable_t isTriviallyDestroyable,
66946721
IsBitwiseTakable_t isBT,
66956722
IsCopyable_t copyable,
6696-
IsFixedSize_t alwaysFixedSize)
6723+
IsFixedSize_t alwaysFixedSize,
6724+
IsABIAccessible_t isABIAccessible)
66976725
: FixedEnumTypeInfoBase(strategy, T, S, std::move(SB), A,
66986726
isTriviallyDestroyable, isBT, copyable,
6699-
alwaysFixedSize) {}
6727+
alwaysFixedSize, isABIAccessible) {}
67006728
};
67016729

67026730
/// TypeInfo for loadable enum types.
@@ -6708,10 +6736,11 @@ namespace {
67086736
Alignment A,
67096737
IsTriviallyDestroyable_t isTriviallyDestroyable,
67106738
IsCopyable_t copyable,
6711-
IsFixedSize_t alwaysFixedSize)
6739+
IsFixedSize_t alwaysFixedSize,
6740+
IsABIAccessible_t isABIAccessible)
67126741
: FixedEnumTypeInfoBase(strategy, T, S, std::move(SB), A,
67136742
isTriviallyDestroyable, copyable,
6714-
alwaysFixedSize) {}
6743+
alwaysFixedSize, isABIAccessible) {}
67156744

67166745
void addToAggLowering(IRGenModule &IGM, SwiftAggLowering &lowering,
67176746
Size offset) const override {
@@ -6821,7 +6850,8 @@ EnumImplStrategy::getFixedEnumTypeInfo(llvm::StructType *T, Size S,
68216850
Alignment A,
68226851
IsTriviallyDestroyable_t isTriviallyDestroyable,
68236852
IsBitwiseTakable_t isBT,
6824-
IsCopyable_t isCopyable) {
6853+
IsCopyable_t isCopyable,
6854+
IsABIAccessible_t abiAccessible) {
68256855
TypeInfo *mutableTI;
68266856
switch (TIK) {
68276857
case Opaque:
@@ -6831,14 +6861,16 @@ EnumImplStrategy::getFixedEnumTypeInfo(llvm::StructType *T, Size S,
68316861
isTriviallyDestroyable,
68326862
isBT,
68336863
isCopyable,
6834-
AlwaysFixedSize);
6864+
AlwaysFixedSize,
6865+
abiAccessible);
68356866
break;
68366867
case Loadable:
68376868
assert(isBT && "loadable enum not bitwise takable?!");
68386869
mutableTI = new LoadableEnumTypeInfo(*this, T, S, std::move(SB), A,
68396870
isTriviallyDestroyable,
68406871
isCopyable,
6841-
AlwaysFixedSize);
6872+
AlwaysFixedSize,
6873+
abiAccessible);
68426874
break;
68436875
}
68446876
TI = mutableTI;
@@ -6859,7 +6891,8 @@ SingletonEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
68596891
alignment,
68606892
TriviallyDestroyable,
68616893
Copyable,
6862-
AlwaysFixedSize));
6894+
AlwaysFixedSize,
6895+
IsABIAccessible));
68636896
} else {
68646897
const TypeInfo &eltTI = *getSingleton();
68656898

@@ -6886,13 +6919,19 @@ SingletonEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
68866919
auto alignment = fixedEltTI.getFixedAlignment();
68876920
applyLayoutAttributes(TC.IGM, theEnum, /*fixed*/true, alignment);
68886921

6922+
IsABIAccessible_t isABIAccessible = IsABIAccessible;
6923+
if (Type.getASTType()->isNoncopyable() &&
6924+
!IGM.getSILModule().isTypeMetadataAccessible(Type.getASTType()))
6925+
isABIAccessible = IsNotABIAccessible;
6926+
68896927
return getFixedEnumTypeInfo(enumTy,
68906928
fixedEltTI.getFixedSize(),
68916929
fixedEltTI.getSpareBits(),
68926930
alignment,
68936931
TriviallyDestroyable,
68946932
BitwiseTakable,
6895-
Copyable);
6933+
Copyable,
6934+
isABIAccessible);
68966935
}
68976936
}
68986937
}
@@ -6927,7 +6966,8 @@ NoPayloadEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
69276966
alignment,
69286967
TriviallyDestroyable,
69296968
Copyable,
6930-
AlwaysFixedSize));
6969+
AlwaysFixedSize,
6970+
IsABIAccessible));
69316971
}
69326972

69336973
TypeInfo *
@@ -6976,7 +7016,8 @@ CCompatibleEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
69767016
alignment,
69777017
IsTriviallyDestroyable,
69787018
IsCopyable,
6979-
IsFixedSize));
7019+
IsFixedSize,
7020+
IsABIAccessible));
69807021
}
69817022

69827023
TypeInfo *SinglePayloadEnumImplStrategy::completeFixedLayout(
@@ -7044,11 +7085,18 @@ TypeInfo *SinglePayloadEnumImplStrategy::completeFixedLayout(
70447085
? IsNotTriviallyDestroyable : IsTriviallyDestroyable;
70457086
auto copyable = !theEnum->canBeCopyable()
70467087
? IsNotCopyable : IsCopyable;
7088+
7089+
IsABIAccessible_t isABIAccessible = IsABIAccessible;
7090+
if (Type.getASTType()->isNoncopyable() &&
7091+
!IGM.getSILModule().isTypeMetadataAccessible(Type.getASTType()))
7092+
isABIAccessible = IsNotABIAccessible;
7093+
70477094
getFixedEnumTypeInfo(
70487095
enumTy, Size(sizeWithTag), spareBits.build(), alignment,
70497096
deinit & payloadTI.isTriviallyDestroyable(ResilienceExpansion::Maximal),
70507097
payloadTI.isBitwiseTakable(ResilienceExpansion::Maximal),
7051-
copyable);
7098+
copyable, isABIAccessible);
7099+
70527100
if (TIK >= Loadable && CopyDestroyKind == Normal) {
70537101
computePayloadTypesAndTagType(TC.IGM, *TI, PayloadTypesAndTagType);
70547102
loweredType = Type;
@@ -7255,9 +7303,15 @@ MultiPayloadEnumImplStrategy::completeFixedLayout(TypeConverter &TC,
72557303

72567304
applyLayoutAttributes(TC.IGM, theEnum, /*fixed*/ true, worstAlignment);
72577305

7306+
IsABIAccessible_t isABIAccessible = IsABIAccessible;
7307+
if (Type.getASTType()->isNoncopyable() &&
7308+
!IGM.getSILModule().isTypeMetadataAccessible(Type.getASTType()))
7309+
isABIAccessible = IsNotABIAccessible;
7310+
72587311
getFixedEnumTypeInfo(enumTy, Size(sizeWithTag), std::move(spareBits),
72597312
worstAlignment, isTriviallyDestroyable, isBT,
7260-
isCopyable);
7313+
isCopyable, isABIAccessible);
7314+
72617315
if (TIK >= Loadable &&
72627316
(CopyDestroyKind == Normal || CopyDestroyKind == BitwiseTakable)) {
72637317
computePayloadTypesAndTagType(TC.IGM, *TI, PayloadTypesAndTagType);

lib/IRGen/GenEnum.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ class EnumImplStrategy {
180180
Alignment A,
181181
IsTriviallyDestroyable_t isTriviallyDestroyable,
182182
IsBitwiseTakable_t isBT,
183-
IsCopyable_t isCopyable);
183+
IsCopyable_t isCopyable,
184+
IsABIAccessible_t abiAccessible);
184185

185186
public:
186187
virtual ~EnumImplStrategy() { }

0 commit comments

Comments
 (0)