Skip to content

Commit d27e6e1

Browse files
authored
Merge pull request #40356 from gmittert/TypeLayoutFixes
Reapply "Teach TypeLayout the Different Types of References" with fixes
2 parents f2e85a2 + 335f426 commit d27e6e1

19 files changed

+796
-152
lines changed

lib/IRGen/ClassTypeInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "ClassLayout.h"
2121
#include "HeapTypeInfo.h"
22+
#include "TypeLayout.h"
2223

2324
namespace swift {
2425
namespace irgen {
@@ -46,7 +47,7 @@ class ClassTypeInfo : public HeapTypeInfo<ClassTypeInfo> {
4647
ClassTypeInfo(llvm::PointerType *irType, Size size, SpareBitVector spareBits,
4748
Alignment align, ClassDecl *theClass,
4849
ReferenceCounting refcount)
49-
: HeapTypeInfo(irType, size, std::move(spareBits), align),
50+
: HeapTypeInfo(refcount, irType, size, std::move(spareBits), align),
5051
TheClass(theClass), Refcount(refcount) {}
5152

5253
ReferenceCounting getReferenceCounting() const { return Refcount; }

lib/IRGen/GenArchetype.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "GenArchetype.h"
1818

19+
#include "TypeLayout.h"
1920
#include "swift/AST/ASTContext.h"
2021
#include "swift/AST/Decl.h"
2122
#include "swift/AST/GenericEnvironment.h"
@@ -126,13 +127,11 @@ class ClassArchetypeTypeInfo
126127
{
127128
ReferenceCounting RefCount;
128129

129-
ClassArchetypeTypeInfo(llvm::PointerType *storageType,
130-
Size size, const SpareBitVector &spareBits,
131-
Alignment align,
130+
ClassArchetypeTypeInfo(llvm::PointerType *storageType, Size size,
131+
const SpareBitVector &spareBits, Alignment align,
132132
ReferenceCounting refCount)
133-
: HeapTypeInfo(storageType, size, spareBits, align),
134-
RefCount(refCount)
135-
{}
133+
: HeapTypeInfo(refCount, storageType, size, spareBits, align),
134+
RefCount(refCount) {}
136135

137136
public:
138137
static const ClassArchetypeTypeInfo *create(llvm::PointerType *storageType,

lib/IRGen/GenConcurrency.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class ExecutorTypeInfo :
5353

5454
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
5555
SILType T) const override {
56-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
56+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T,
57+
ScalarKind::POD);
5758
}
5859

5960
static Size getSecondElementOffset(IRGenModule &IGM) {

lib/IRGen/GenDiffFunc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class DifferentiableFuncTypeInfo final
120120
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
121121
SILType T) const override {
122122
if (!IGM.getOptions().ForceStructTypeLayouts || !areFieldsABIAccessible()) {
123-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
123+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
124124
}
125125

126126
if (getFields().empty()) {
@@ -292,7 +292,7 @@ class LinearFuncTypeInfo final
292292
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
293293
SILType T) const override {
294294
if (!IGM.getOptions().ForceStructTypeLayouts || !areFieldsABIAccessible()) {
295-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
295+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
296296
}
297297

298298
if (getFields().empty()) {

lib/IRGen/GenEnum.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
//
9999
//===----------------------------------------------------------------------===//
100100

101+
#include "TypeLayout.h"
101102
#define DEBUG_TYPE "enum-layout"
102103
#include "llvm/Support/Debug.h"
103104

@@ -385,9 +386,10 @@ namespace {
385386
return IGM.typeLayoutCache.getEmptyEntry();
386387
if (!ElementsAreABIAccessible)
387388
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
388-
if (TIK >= Loadable) {
389-
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
390-
}
389+
390+
if (TIK >= Loadable && !IGM.getOptions().ForceStructTypeLayouts)
391+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(getTypeInfo(),
392+
T);
391393

392394
return getSingleton()->buildTypeLayoutEntry(IGM,
393395
getSingletonType(IGM, T));
@@ -1079,7 +1081,8 @@ namespace {
10791081

10801082
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
10811083
SILType T) const override {
1082-
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
1084+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T,
1085+
ScalarKind::POD);
10831086
}
10841087

10851088

@@ -1231,7 +1234,8 @@ namespace {
12311234

12321235
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
12331236
SILType T) const override {
1234-
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
1237+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T,
1238+
ScalarKind::POD);
12351239
}
12361240

12371241
/// \group Extra inhabitants for C-compatible enums.
@@ -3507,9 +3511,10 @@ namespace {
35073511
if (!ElementsAreABIAccessible)
35083512
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
35093513

3510-
if (AllowFixedLayoutOptimizations && TIK >= Loadable) {
3514+
if (!IGM.getOptions().ForceStructTypeLayouts && (AllowFixedLayoutOptimizations && TIK >= Loadable)) {
35113515
// The type layout entry code does not handle spare bits atm.
3512-
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
3516+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(getTypeInfo(),
3517+
T);
35133518
}
35143519

35153520
unsigned emptyCases = ElementsWithNoPayload.size();

lib/IRGen/GenExistential.cpp

Lines changed: 121 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -661,51 +661,52 @@ namespace {
661661
return Super::getFixedExtraInhabitantMask(IGM); \
662662
} \
663663
}
664-
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
665-
class AddressOnly##Name##ClassExistentialTypeInfo final : \
666-
public AddressOnlyClassExistentialTypeInfoBase< \
667-
AddressOnly##Name##ClassExistentialTypeInfo, \
668-
FixedTypeInfo> { \
669-
bool IsOptional; \
670-
public: \
671-
AddressOnly##Name##ClassExistentialTypeInfo( \
672-
ArrayRef<const ProtocolDecl *> protocols, \
673-
llvm::Type *ty, \
674-
SpareBitVector &&spareBits, \
675-
Size size, Alignment align, \
676-
ReferenceCounting refcounting, \
677-
bool isOptional) \
678-
: AddressOnlyClassExistentialTypeInfoBase(protocols, refcounting, \
679-
ty, size, std::move(spareBits), \
680-
align, IsNotPOD, \
681-
IsNotBitwiseTakable, \
682-
IsFixedSize), \
683-
IsOptional(isOptional) {} \
684-
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
685-
SILType T) const override { \
686-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
687-
} \
688-
void emitValueAssignWithCopy(IRGenFunction &IGF, \
689-
Address dest, Address src) const { \
690-
IGF.emit##Name##CopyAssign(dest, src, Refcounting); \
691-
} \
692-
void emitValueInitializeWithCopy(IRGenFunction &IGF, \
693-
Address dest, Address src) const { \
694-
IGF.emit##Name##CopyInit(dest, src, Refcounting); \
695-
} \
696-
void emitValueAssignWithTake(IRGenFunction &IGF, \
697-
Address dest, Address src) const { \
698-
IGF.emit##Name##TakeAssign(dest, src, Refcounting); \
699-
} \
700-
void emitValueInitializeWithTake(IRGenFunction &IGF, \
701-
Address dest, Address src) const { \
702-
IGF.emit##Name##TakeInit(dest, src, Refcounting); \
703-
} \
704-
void emitValueDestroy(IRGenFunction &IGF, Address addr) const { \
705-
IGF.emit##Name##Destroy(addr, Refcounting); \
706-
} \
707-
StringRef getStructNameSuffix() const { return "." #name "ref"; } \
708-
REF_STORAGE_HELPER(Name, FixedTypeInfo) \
664+
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
665+
class AddressOnly##Name##ClassExistentialTypeInfo final \
666+
: public AddressOnlyClassExistentialTypeInfoBase< \
667+
AddressOnly##Name##ClassExistentialTypeInfo, FixedTypeInfo> { \
668+
bool IsOptional; \
669+
\
670+
public: \
671+
AddressOnly##Name##ClassExistentialTypeInfo( \
672+
ArrayRef<const ProtocolDecl *> protocols, llvm::Type *ty, \
673+
SpareBitVector &&spareBits, Size size, Alignment align, \
674+
ReferenceCounting refcounting, bool isOptional) \
675+
: AddressOnlyClassExistentialTypeInfoBase( \
676+
protocols, refcounting, ty, size, std::move(spareBits), align, \
677+
IsNotPOD, IsNotBitwiseTakable, IsFixedSize), \
678+
IsOptional(isOptional) {} \
679+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
680+
SILType T) const override { \
681+
if (Refcounting == ReferenceCounting::Native) { \
682+
return IGM.typeLayoutCache.getOrCreateScalarEntry( \
683+
*this, T, ScalarKind::Native##Name##Reference); \
684+
} else { \
685+
return IGM.typeLayoutCache.getOrCreateScalarEntry( \
686+
*this, T, ScalarKind::Unknown##Name##Reference); \
687+
} \
688+
} \
689+
void emitValueAssignWithCopy(IRGenFunction &IGF, Address dest, \
690+
Address src) const { \
691+
IGF.emit##Name##CopyAssign(dest, src, Refcounting); \
692+
} \
693+
void emitValueInitializeWithCopy(IRGenFunction &IGF, Address dest, \
694+
Address src) const { \
695+
IGF.emit##Name##CopyInit(dest, src, Refcounting); \
696+
} \
697+
void emitValueAssignWithTake(IRGenFunction &IGF, Address dest, \
698+
Address src) const { \
699+
IGF.emit##Name##TakeAssign(dest, src, Refcounting); \
700+
} \
701+
void emitValueInitializeWithTake(IRGenFunction &IGF, Address dest, \
702+
Address src) const { \
703+
IGF.emit##Name##TakeInit(dest, src, Refcounting); \
704+
} \
705+
void emitValueDestroy(IRGenFunction &IGF, Address addr) const { \
706+
IGF.emit##Name##Destroy(addr, Refcounting); \
707+
} \
708+
StringRef getStructNameSuffix() const { return "." #name "ref"; } \
709+
REF_STORAGE_HELPER(Name, FixedTypeInfo) \
709710
};
710711
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
711712
class Loadable##Name##ClassExistentialTypeInfo final \
@@ -731,7 +732,16 @@ namespace {
731732
} \
732733
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
733734
SILType T) const override { \
734-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
735+
ScalarKind kind; \
736+
switch (Refcounting) { \
737+
case ReferenceCounting::Native: kind = ScalarKind::NativeStrongReference; break; \
738+
case ReferenceCounting::ObjC: kind = ScalarKind::ObjCReference; break; \
739+
case ReferenceCounting::Block: kind = ScalarKind::BlockReference; break; \
740+
case ReferenceCounting::Unknown: kind = ScalarKind::UnknownReference; break; \
741+
case ReferenceCounting::Bridge: kind = ScalarKind::BridgeReference; break; \
742+
case ReferenceCounting::Error: kind = ScalarKind::ErrorReference; break; \
743+
} \
744+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); \
735745
} \
736746
llvm::Type *getValueType() const { \
737747
return ValueType; \
@@ -778,7 +788,7 @@ namespace {
778788
spareBits, align, IsPOD, IsFixedSize) {} \
779789
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
780790
SILType T) const override { \
781-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
791+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, ScalarKind::POD); \
782792
} \
783793
const LoadableTypeInfo & \
784794
getValueTypeInfoForExtraInhabitants(IRGenModule &IGM) const { \
@@ -847,7 +857,8 @@ class OpaqueExistentialTypeInfo final :
847857

848858
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
849859
SILType T) const override {
850-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
860+
return IGM.typeLayoutCache.getOrCreateScalarEntry(
861+
*this, T, ScalarKind::ExistentialReference);
851862
}
852863

853864
Address projectWitnessTable(IRGenFunction &IGF, Address obj,
@@ -995,7 +1006,31 @@ class ClassExistentialTypeInfo final
9951006

9961007
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
9971008
SILType T) const override {
998-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1009+
// We can't create an objc typeinfo by itself, so don't destructure if we
1010+
// have one
1011+
if (Refcounting == ReferenceCounting::ObjC) {
1012+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
1013+
}
1014+
1015+
/// The storage type of a class existential is a struct containing
1016+
/// a refcounted pointer to the class instance value followed by
1017+
/// witness table pointers for each conformed-to protocol.
1018+
std::vector<TypeLayoutEntry *> alignedGroup;
1019+
const TypeInfo &typeinfo = Refcounting == ReferenceCounting::Native
1020+
? IGM.getNativeObjectTypeInfo()
1021+
: IGM.getUnknownObjectTypeInfo();
1022+
1023+
alignedGroup.push_back(IGM.typeLayoutCache.getOrCreateScalarEntry(
1024+
typeinfo, T, refcountingToScalarKind(Refcounting)));
1025+
for (unsigned i = 0; i < getNumStoredProtocols(); i++) {
1026+
alignedGroup.push_back(IGM.typeLayoutCache.getOrCreateScalarEntry(
1027+
IGM.getWitnessTablePtrTypeInfo(),
1028+
SILType::getBuiltinIntegerType(IGM.getPointerSize().getValue(),
1029+
IGM.Context),
1030+
ScalarKind::POD));
1031+
}
1032+
1033+
return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(alignedGroup, 0);
9991034
}
10001035

10011036
/// Given an explosion with multiple pointer elements in them, pack them
@@ -1327,7 +1362,8 @@ class ExistentialMetatypeTypeInfo final
13271362

13281363
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
13291364
SILType T) const override {
1330-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1365+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T,
1366+
ScalarKind::POD);
13311367
}
13321368

13331369
void emitValueRetain(IRGenFunction &IGF, llvm::Value *value,
@@ -1353,17 +1389,27 @@ class ErrorExistentialTypeInfo : public HeapTypeInfo<ErrorExistentialTypeInfo>
13531389
ReferenceCounting Refcounting;
13541390

13551391
public:
1356-
ErrorExistentialTypeInfo(llvm::PointerType *storage,
1357-
Size size, SpareBitVector spareBits,
1358-
Alignment align,
1392+
ErrorExistentialTypeInfo(llvm::PointerType *storage, Size size,
1393+
SpareBitVector spareBits, Alignment align,
13591394
const ProtocolDecl *errorProto,
13601395
ReferenceCounting refcounting)
1361-
: HeapTypeInfo(storage, size, spareBits, align), ErrorProto(errorProto),
1362-
Refcounting(refcounting) {}
1396+
: HeapTypeInfo(refcounting, storage, size, spareBits, align),
1397+
ErrorProto(errorProto), Refcounting(refcounting) {}
13631398

13641399
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
13651400
SILType T) const override {
1366-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1401+
ScalarKind kind;
1402+
switch (Refcounting) {
1403+
case ReferenceCounting::Native:
1404+
kind = ScalarKind::NativeStrongReference;
1405+
break;
1406+
case ReferenceCounting::Error:
1407+
kind = ScalarKind::ErrorReference;
1408+
break;
1409+
default:
1410+
llvm_unreachable("unsupported refcounting type");
1411+
}
1412+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind);
13671413
}
13681414

13691415
ReferenceCounting getReferenceCounting() const {
@@ -2246,6 +2292,25 @@ void irgen::emitDeallocateBoxedOpaqueExistentialBuffer(
22462292
return;
22472293
}
22482294

2295+
void irgen::emitDestroyBoxedOpaqueExistentialBuffer(
2296+
IRGenFunction &IGF, SILType existentialType, Address existentialContainer) {
2297+
2298+
// Project to the existential buffer in the existential container.
2299+
auto &existentialTI =
2300+
IGF.getTypeInfo(existentialType).as<OpaqueExistentialTypeInfo>();
2301+
OpaqueExistentialLayout existLayout = existentialTI.getLayout();
2302+
2303+
auto *deallocateFun =
2304+
getDestroyBoxedOpaqueExistentialBufferFunction(IGF.IGM, existLayout);
2305+
auto *bufferAddr = IGF.Builder.CreateBitCast(
2306+
existentialContainer.getAddress(),
2307+
IGF.IGM.getExistentialPtrTy(existLayout.getNumTables()));
2308+
auto *call = IGF.Builder.CreateCall(deallocateFun, {bufferAddr});
2309+
call->setCallingConv(IGF.IGM.DefaultCC);
2310+
call->setDoesNotThrow();
2311+
return;
2312+
}
2313+
22492314
static llvm::Constant *
22502315
getProjectBoxedOpaqueExistentialFunction(IRGenFunction &IGF,
22512316
OpenedExistentialAccess accessKind,

lib/IRGen/GenExistential.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ namespace irgen {
9595
void emitDeallocateBoxedOpaqueExistentialBuffer(IRGenFunction &IGF,
9696
SILType existentialType,
9797
Address existentialContainer);
98+
99+
/// Free the storage for an opaque existential in the existential
100+
/// container.
101+
/// If the value is not stored inline, this will free the box for the
102+
/// value.
103+
void emitDestroyBoxedOpaqueExistentialBuffer(IRGenFunction &IGF,
104+
SILType existentialType,
105+
Address existentialContainer);
98106
Address emitOpaqueBoxedExistentialProjection(
99107
IRGenFunction &IGF, OpenedExistentialAccess accessKind, Address base,
100108
SILType existentialType, CanArchetypeType openedArchetype);

0 commit comments

Comments
 (0)