Skip to content

Commit a3ceda6

Browse files
author
Gwen Mittertreiner
committed
Teach TypeLayout the Different Types of References
Summary: As part of SR-14273, the type layout infrastructure needs to be able to be able to differentiate between types of scalars so it knows how to release/retain appropriately. Right now, for example, to destroy a scalar, it blindly calls into typeInfo's irgen functions which means it's not able to generate any of the needed information for itself. This patch adds a field to ScalarTypeLayout to allow them to know what kind of reference they are and strings through the machinery to provide the information to set it. This also moves ScalarTypeLayout::destroy to use the new information. Test Plan: ninja check-swift Reviewers: mren, #pika_compiler Reviewed By: mren Subscribers: apl, phabricatorlinter Differential Revision: https://phabricator.intern.facebook.com/D30983093 Tasks: T100580959 Tags: swift-adoption Signature: 30983093:1632340205:3bdd3218ae86ad6b3d199cc1b504a625e3650ec0
1 parent ce334af commit a3ceda6

18 files changed

+647
-108
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: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "GenExistential.h"
1818

19+
#include "TypeLayout.h"
1920
#include "swift/AST/ASTContext.h"
2021
#include "swift/AST/Decl.h"
2122
#include "swift/AST/ExistentialLayout.h"
@@ -28,6 +29,7 @@
2829
#include "llvm/IR/DerivedTypes.h"
2930
#include "llvm/IR/Function.h"
3031
#include "llvm/IR/Module.h"
32+
#include "llvm/Support/ErrorHandling.h"
3133
#include "llvm/Support/raw_ostream.h"
3234

3335
#include "BitPatternBuilder.h"
@@ -683,7 +685,16 @@ namespace {
683685
IsOptional(isOptional) {} \
684686
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
685687
SILType T) const override { \
686-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
688+
ScalarKind kind; \
689+
switch (Refcounting) { \
690+
case ReferenceCounting::Native: kind = ScalarKind::NativeStrongReference; break; \
691+
case ReferenceCounting::ObjC: kind = ScalarKind::ObjCReference; break; \
692+
case ReferenceCounting::Block: kind = ScalarKind::BlockReference; break; \
693+
case ReferenceCounting::Unknown: kind = ScalarKind::UnknownReference; break; \
694+
case ReferenceCounting::Bridge: kind = ScalarKind::BridgeReference; break; \
695+
case ReferenceCounting::Error: kind = ScalarKind::ErrorReference; break; \
696+
} \
697+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); \
687698
} \
688699
void emitValueAssignWithCopy(IRGenFunction &IGF, \
689700
Address dest, Address src) const { \
@@ -731,7 +742,16 @@ namespace {
731742
} \
732743
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
733744
SILType T) const override { \
734-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
745+
ScalarKind kind; \
746+
switch (Refcounting) { \
747+
case ReferenceCounting::Native: kind = ScalarKind::NativeStrongReference; break; \
748+
case ReferenceCounting::ObjC: kind = ScalarKind::ObjCReference; break; \
749+
case ReferenceCounting::Block: kind = ScalarKind::BlockReference; break; \
750+
case ReferenceCounting::Unknown: kind = ScalarKind::UnknownReference; break; \
751+
case ReferenceCounting::Bridge: kind = ScalarKind::BridgeReference; break; \
752+
case ReferenceCounting::Error: kind = ScalarKind::ErrorReference; break; \
753+
} \
754+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); \
735755
} \
736756
llvm::Type *getValueType() const { \
737757
return ValueType; \
@@ -778,7 +798,7 @@ namespace {
778798
spareBits, align, IsPOD, IsFixedSize) {} \
779799
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
780800
SILType T) const override { \
781-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
801+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, ScalarKind::POD); \
782802
} \
783803
const LoadableTypeInfo & \
784804
getValueTypeInfoForExtraInhabitants(IRGenModule &IGM) const { \
@@ -847,7 +867,8 @@ class OpaqueExistentialTypeInfo final :
847867

848868
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
849869
SILType T) const override {
850-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
870+
return IGM.typeLayoutCache.getOrCreateScalarEntry(
871+
*this, T, ScalarKind::ExistentialReference);
851872
}
852873

853874
Address projectWitnessTable(IRGenFunction &IGF, Address obj,
@@ -995,7 +1016,21 @@ class ClassExistentialTypeInfo final
9951016

9961017
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
9971018
SILType T) const override {
998-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1019+
ScalarKind kind;
1020+
switch (Refcounting) {
1021+
case ReferenceCounting::Native:
1022+
kind = ScalarKind::NativeStrongReference;
1023+
break;
1024+
case ReferenceCounting::ObjC:
1025+
kind = ScalarKind::ObjCReference;
1026+
break;
1027+
case ReferenceCounting::Unknown:
1028+
kind = ScalarKind::UnknownReference;
1029+
break;
1030+
default:
1031+
llvm_unreachable("Unsupported refcounting style");
1032+
}
1033+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind);
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);

lib/IRGen/GenFunc.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ namespace {
156156

157157
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
158158
SILType T) const override {
159-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
159+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T,
160+
ScalarKind::POD);
160161
}
161162

162163
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
@@ -223,7 +224,13 @@ namespace {
223224

224225
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
225226
SILType T) const override {
226-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
227+
if (isPOD(ResilienceExpansion::Maximal)) {
228+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T,
229+
ScalarKind::POD);
230+
} else {
231+
return IGM.typeLayoutCache.getOrCreateScalarEntry(
232+
*this, T, ScalarKind::ThickFunc);
233+
}
227234
}
228235

229236
static Size getFirstElementSize(IRGenModule &IGM) {
@@ -385,20 +392,19 @@ namespace {
385392
public FuncSignatureInfo
386393
{
387394
public:
388-
BlockTypeInfo(CanSILFunctionType ty,
389-
llvm::PointerType *storageType,
395+
BlockTypeInfo(CanSILFunctionType ty, llvm::PointerType *storageType,
390396
Size size, SpareBitVector spareBits, Alignment align)
391-
: HeapTypeInfo(storageType, size, spareBits, align),
392-
FuncSignatureInfo(ty)
393-
{
394-
}
397+
: HeapTypeInfo(ReferenceCounting::Block, storageType, size, spareBits,
398+
align),
399+
FuncSignatureInfo(ty) {}
395400

396401
ReferenceCounting getReferenceCounting() const {
397402
return ReferenceCounting::Block;
398403
}
399404
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
400405
SILType T) const override {
401-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
406+
return IGM.typeLayoutCache.getOrCreateScalarEntry(
407+
*this, T, ScalarKind::BlockReference);
402408
}
403409
};
404410

@@ -420,7 +426,8 @@ namespace {
420426

421427
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
422428
SILType T) const override {
423-
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
429+
return IGM.typeLayoutCache.getOrCreateScalarEntry(
430+
*this, T, ScalarKind::BlockStorage);
424431
}
425432
// The lowered type should be an LLVM struct comprising the block header
426433
// (IGM.ObjCBlockStructTy) as its first element and the capture as its

0 commit comments

Comments
 (0)