Skip to content

Commit 9748a5a

Browse files
authored
Merge pull request swiftlang#27101 from slavapestov/outlined-existential-operations-fix
IRGen: Clean up types of outlined existential buffer operations
2 parents f5ad014 + bc1aa97 commit 9748a5a

File tree

7 files changed

+216
-82
lines changed

7 files changed

+216
-82
lines changed

lib/IRGen/GenExistential.cpp

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -789,12 +789,10 @@ namespace {
789789

790790

791791
static llvm::Constant *getAssignBoxedOpaqueExistentialBufferFunction(
792-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
793-
llvm::Type *existContainerPointerTy);
792+
IRGenModule &IGM, OpaqueExistentialLayout existLayout);
794793

795794
static llvm::Constant *getDestroyBoxedOpaqueExistentialBufferFunction(
796-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
797-
llvm::Type *existContainerPointerTy);
795+
IRGenModule &IGM, OpaqueExistentialLayout existLayout);
798796

799797
static llvm::Constant *
800798
getProjectBoxedOpaqueExistentialFunction(IRGenFunction &IGF,
@@ -843,13 +841,14 @@ class OpaqueExistentialTypeInfo final :
843841
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T,
844842
bool isOutlined) const override {
845843

846-
auto objPtrTy = dest.getAddress()->getType();
847-
848844
// Use copy-on-write existentials?
849845
auto fn = getAssignBoxedOpaqueExistentialBufferFunction(
850-
IGF.IGM, getLayout(), objPtrTy);
846+
IGF.IGM, getLayout());
847+
auto *type = IGF.IGM.getExistentialPtrTy(getLayout().getNumTables());
848+
auto *destAddr = IGF.Builder.CreateBitCast(dest.getAddress(), type);
849+
auto *srcAddr = IGF.Builder.CreateBitCast(src.getAddress(), type);
851850
auto call =
852-
IGF.Builder.CreateCall(fn, {dest.getAddress(), src.getAddress()});
851+
IGF.Builder.CreateCall(fn, {destAddr, srcAddr});
853852
call->setCallingConv(IGF.IGM.DefaultCC);
854853
call->setDoesNotThrow();
855854
return;
@@ -904,12 +903,15 @@ class OpaqueExistentialTypeInfo final :
904903
}
905904
}
906905

907-
void destroy(IRGenFunction &IGF, Address addr, SILType T,
906+
void destroy(IRGenFunction &IGF, Address buffer, SILType T,
908907
bool isOutlined) const override {
909908
// Use copy-on-write existentials?
910909
auto fn = getDestroyBoxedOpaqueExistentialBufferFunction(
911-
IGF.IGM, getLayout(), addr.getAddress()->getType());
912-
auto call = IGF.Builder.CreateCall(fn, {addr.getAddress()});
910+
IGF.IGM, getLayout());
911+
auto *addr = IGF.Builder.CreateBitCast(
912+
buffer.getAddress(),
913+
IGF.IGM.getExistentialPtrTy(getLayout().getNumTables()));
914+
auto call = IGF.Builder.CreateCall(fn, {addr});
913915
call->setCallingConv(IGF.IGM.DefaultCC);
914916
call->setDoesNotThrow();
915917
return;
@@ -1355,6 +1357,36 @@ createErrorExistentialTypeInfo(IRGenModule &IGM,
13551357
refcounting);
13561358
}
13571359

1360+
llvm::Type *TypeConverter::getExistentialType(unsigned numWitnessTables) {
1361+
llvm::StructType *&type = OpaqueExistentialTypes[numWitnessTables];
1362+
if (type)
1363+
return type;
1364+
1365+
SmallVector<llvm::Type*, 5> fields;
1366+
1367+
fields.push_back(IGM.getFixedBufferTy());
1368+
fields.push_back(IGM.TypeMetadataPtrTy);
1369+
1370+
for (auto i : range(numWitnessTables)) {
1371+
fields.push_back(IGM.WitnessTablePtrTy);
1372+
(void) i;
1373+
}
1374+
1375+
llvm::SmallString<40> typeName;
1376+
llvm::raw_svector_ostream(typeName)
1377+
<< "__opaque_existential_type_"
1378+
<< numWitnessTables;
1379+
1380+
type = llvm::StructType::create(IGM.getLLVMContext(), StringRef(typeName));
1381+
type->setBody(fields);
1382+
1383+
return type;
1384+
}
1385+
1386+
llvm::PointerType *IRGenModule::getExistentialPtrTy(unsigned numTables) {
1387+
return Types.getExistentialType(numTables)->getPointerTo();
1388+
}
1389+
13581390
static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM, CanType T) {
13591391
auto layout = T.getExistentialLayout();
13601392

@@ -1767,24 +1799,26 @@ void irgen::emitExistentialMetatypeContainer(IRGenFunction &IGF,
17671799
});
17681800
}
17691801

1770-
void irgen::emitMetatypeOfOpaqueExistential(IRGenFunction &IGF, Address addr,
1802+
void irgen::emitMetatypeOfOpaqueExistential(IRGenFunction &IGF, Address buffer,
17711803
SILType type, Explosion &out) {
17721804
assert(type.isExistentialType());
17731805
assert(!type.isClassExistentialType());
17741806
auto &baseTI = IGF.getTypeInfo(type).as<OpaqueExistentialTypeInfo>();
17751807

17761808
// Get the static metadata.
17771809
auto existLayout = baseTI.getLayout();
1778-
llvm::Value *metadata = existLayout.loadMetadataRef(IGF, addr);
1810+
llvm::Value *metadata = existLayout.loadMetadataRef(IGF, buffer);
17791811

17801812
// Project the buffer and apply the 'typeof' value witness.
1781-
Address buffer = existLayout.projectExistentialBuffer(IGF, addr);
17821813
llvm::Value *object;
17831814

1815+
auto *addr = IGF.Builder.CreateBitCast(
1816+
buffer.getAddress(),
1817+
IGF.IGM.getExistentialPtrTy(existLayout.getNumTables()));
17841818
auto *projectFunc = getProjectBoxedOpaqueExistentialFunction(
17851819
IGF, OpenedExistentialAccess::Immutable, existLayout);
17861820
auto *addrOfValue =
1787-
IGF.Builder.CreateCall(projectFunc, {buffer.getAddress(), metadata});
1821+
IGF.Builder.CreateCall(projectFunc, {addr, metadata});
17881822
addrOfValue->setCallingConv(IGF.IGM.DefaultCC);
17891823
addrOfValue->setDoesNotThrow();
17901824
object = addrOfValue;
@@ -1796,7 +1830,7 @@ void irgen::emitMetatypeOfOpaqueExistential(IRGenFunction &IGF, Address addr,
17961830
out.add(dynamicType);
17971831

17981832
// Get the witness tables.
1799-
baseTI.emitLoadOfTables(IGF, addr, out);
1833+
baseTI.emitLoadOfTables(IGF, buffer, out);
18001834
}
18011835

18021836
void irgen::emitMetatypeOfBoxedExistential(IRGenFunction &IGF, Explosion &value,
@@ -1967,10 +2001,9 @@ static Address castToOpaquePtr(IRGenFunction &IGF, Address addr) {
19672001
}
19682002

19692003
static llvm::Constant *getAllocateBoxedOpaqueExistentialBufferFunction(
1970-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
1971-
llvm::Type *existContainerPointerTy) {
2004+
IRGenModule &IGM, OpaqueExistentialLayout existLayout) {
19722005

1973-
llvm::Type *argTys[] = {existContainerPointerTy};
2006+
llvm::Type *argTys[] = {IGM.getExistentialPtrTy(existLayout.getNumTables())};
19742007

19752008
// __swift_allocate_boxed_opaque_existential__N is the well-known function for
19762009
// allocating buffers in existential containers of types with N witness
@@ -2051,20 +2084,22 @@ Address irgen::emitAllocateBoxedOpaqueExistentialBuffer(
20512084
}
20522085
/// Call a function to handle the non-fixed case.
20532086
auto *allocateFun = getAllocateBoxedOpaqueExistentialBufferFunction(
2054-
IGF.IGM, existLayout, existentialContainer.getAddress()->getType());
2087+
IGF.IGM, existLayout);
2088+
auto *existentialAddr = IGF.Builder.CreateBitCast(
2089+
existentialContainer.getAddress(),
2090+
IGF.IGM.getExistentialPtrTy(existLayout.getNumTables()));
20552091
auto *call =
2056-
IGF.Builder.CreateCall(allocateFun, {existentialContainer.getAddress()});
2092+
IGF.Builder.CreateCall(allocateFun, {existentialAddr});
20572093
call->setCallingConv(IGF.IGM.DefaultCC);
20582094
call->setDoesNotThrow();
20592095
auto addressOfValue = IGF.Builder.CreateBitCast(call, valuePointerType);
20602096
return valueTI.getAddressForPointer(addressOfValue);
20612097
}
20622098

20632099
static llvm::Constant *getDeallocateBoxedOpaqueExistentialBufferFunction(
2064-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
2065-
llvm::Type *existContainerPointerTy) {
2100+
IRGenModule &IGM, OpaqueExistentialLayout existLayout) {
20662101

2067-
llvm::Type *argTys[] = {existContainerPointerTy};
2102+
llvm::Type *argTys[] = {IGM.getExistentialPtrTy(existLayout.getNumTables())};
20682103

20692104
// __swift_deallocate_boxed_opaque_existential_N is the well-known function
20702105
// for deallocating buffers in existential containers of types with N witness
@@ -2141,9 +2176,11 @@ void irgen::emitDeallocateBoxedOpaqueExistentialBuffer(
21412176
OpaqueExistentialLayout existLayout = existentialTI.getLayout();
21422177

21432178
auto *deallocateFun = getDeallocateBoxedOpaqueExistentialBufferFunction(
2144-
IGF.IGM, existLayout, existentialContainer.getAddress()->getType());
2145-
auto *call = IGF.Builder.CreateCall(deallocateFun,
2146-
{existentialContainer.getAddress()});
2179+
IGF.IGM, existLayout);
2180+
auto *bufferAddr = IGF.Builder.CreateBitCast(
2181+
existentialContainer.getAddress(),
2182+
IGF.IGM.getExistentialPtrTy(existLayout.getNumTables()));
2183+
auto *call = IGF.Builder.CreateCall(deallocateFun, {bufferAddr});
21472184
call->setCallingConv(IGF.IGM.DefaultCC);
21482185
call->setDoesNotThrow();
21492186
return;
@@ -2155,7 +2192,7 @@ getProjectBoxedOpaqueExistentialFunction(IRGenFunction &IGF,
21552192
OpaqueExistentialLayout existLayout) {
21562193

21572194
auto &IGM = IGF.IGM;
2158-
auto *existentialBufferTy = IGM.getFixedBufferTy()->getPointerTo();
2195+
auto *existentialBufferTy = IGM.getExistentialPtrTy(existLayout.getNumTables());
21592196
llvm::Type *argTys[] = {existentialBufferTy, IGM.TypeMetadataPtrTy};
21602197

21612198
// __swift_project_boxed_opaque_existential_N is the well-known function for
@@ -2278,11 +2315,13 @@ Address irgen::emitOpaqueBoxedExistentialProjection(
22782315
wtables);
22792316
}
22802317

2281-
Address buffer = layout.projectExistentialBuffer(IGF, base);
22822318
auto *projectFunc =
22832319
getProjectBoxedOpaqueExistentialFunction(IGF, accessKind, layout);
2320+
auto *bufferAddr = IGF.Builder.CreateBitCast(
2321+
base.getAddress(),
2322+
IGF.IGM.getExistentialPtrTy(layout.getNumTables()));
22842323
auto *addrOfValue =
2285-
IGF.Builder.CreateCall(projectFunc, {buffer.getAddress(), metadata});
2324+
IGF.Builder.CreateCall(projectFunc, {bufferAddr, metadata});
22862325
addrOfValue->setCallingConv(IGF.IGM.DefaultCC);
22872326
addrOfValue->setDoesNotThrow();
22882327

@@ -2309,10 +2348,10 @@ static void initBufferWithCopyOfReference(IRGenFunction &IGF,
23092348
}
23102349

23112350
static llvm::Constant *getAssignBoxedOpaqueExistentialBufferFunction(
2312-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
2313-
llvm::Type *existContainerPointerTy) {
2351+
IRGenModule &IGM, OpaqueExistentialLayout existLayout) {
23142352

2315-
llvm::Type *argTys[] = {existContainerPointerTy, existContainerPointerTy};
2353+
llvm::Type *argTys[] = {IGM.getExistentialPtrTy(existLayout.getNumTables()),
2354+
IGM.getExistentialPtrTy(existLayout.getNumTables())};
23162355

23172356
// __swift_assign_box_in_existentials_N is the well-known function for
23182357
// assigning buffers in existential containers of types with N witness
@@ -2528,10 +2567,9 @@ static llvm::Constant *getAssignBoxedOpaqueExistentialBufferFunction(
25282567
}
25292568

25302569
static llvm::Constant *getDestroyBoxedOpaqueExistentialBufferFunction(
2531-
IRGenModule &IGM, OpaqueExistentialLayout existLayout,
2532-
llvm::Type *existContainerPointerTy) {
2570+
IRGenModule &IGM, OpaqueExistentialLayout existLayout) {
25332571

2534-
llvm::Type *argTys[] = {existContainerPointerTy};
2572+
llvm::Type *argTys[] = {IGM.getExistentialPtrTy(existLayout.getNumTables())};
25352573

25362574
llvm::SmallString<40> fnName;
25372575
llvm::raw_svector_ostream(fnName)

lib/IRGen/GenType.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ class TypeConverter {
117117
llvm::StringMap<YAMLTypeInfoNode> LegacyTypeInfos;
118118
llvm::DenseMap<NominalTypeDecl *, std::string> DeclMangledNames;
119119

120+
/// The key is the number of witness tables.
121+
llvm::DenseMap<unsigned, llvm::StructType *> OpaqueExistentialTypes;
122+
120123
const LoadableTypeInfo *createPrimitive(llvm::Type *T,
121124
Size size, Alignment align);
122125
const LoadableTypeInfo *createPrimitiveForAlignedPointer(llvm::PointerType *T,
@@ -182,6 +185,8 @@ class TypeConverter {
182185
bool isOptional);
183186
#include "swift/AST/ReferenceStorage.def"
184187

188+
llvm::Type *getExistentialType(unsigned numWitnessTables);
189+
185190
/// Enter a generic context for lowering the parameters of a generic function
186191
/// type.
187192
void pushGenericContext(CanGenericSignature signature);

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ class IRGenModule {
725725
ReferenceCounting style) const;
726726

727727
llvm::Type *getFixedBufferTy();
728+
llvm::PointerType *getExistentialPtrTy(unsigned numTables);
728729
llvm::Type *getValueWitnessTy(ValueWitness index);
729730
Signature getValueWitnessSignature(ValueWitness index);
730731

0 commit comments

Comments
 (0)