Skip to content

Commit 8dc2a73

Browse files
authored
Merge pull request #64199 from slavapestov/nfc-variadic-generic-types-work
IRGen: Preliminary refactoring to support dynamic layout of variadic generic types
2 parents fdc9817 + 71e4031 commit 8dc2a73

File tree

13 files changed

+87
-169
lines changed

13 files changed

+87
-169
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6355,8 +6355,6 @@ class PackArchetypeType final
63556355
return T->getKind() == TypeKind::PackArchetype;
63566356
}
63576357

6358-
CanTypeWrapper<PackType> getSingletonPackType();
6359-
63606358
private:
63616359
PackArchetypeType(const ASTContext &Ctx, GenericEnvironment *GenericEnv,
63626360
Type InterfaceType, ArrayRef<ProtocolDecl *> ConformsTo,
@@ -6831,6 +6829,9 @@ BEGIN_CAN_TYPE_WRAPPER(PackType, Type)
68316829
static CanPackType get(const ASTContext &ctx, ArrayRef<CanType> elements);
68326830
static CanPackType get(const ASTContext &ctx, CanTupleEltTypeArrayRef elts);
68336831

6832+
static CanTypeWrapper<PackType>
6833+
getSingletonPackExpansion(CanType packParameter);
6834+
68346835
CanType getElementType(unsigned elementNo) const {
68356836
return CanType(getPointer()->getElementType(elementNo));
68366837
}

lib/AST/ASTContext.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3293,11 +3293,6 @@ PackType *PackType::getEmpty(const ASTContext &C) {
32933293
return cast<PackType>(CanType(C.TheEmptyPackType));
32943294
}
32953295

3296-
PackType *PackType::getSingletonPackExpansion(Type param) {
3297-
assert(param->isParameterPack() || param->is<PackArchetypeType>());
3298-
return get(param->getASTContext(), {PackExpansionType::get(param, param)});
3299-
}
3300-
33013296
CanPackType CanPackType::get(const ASTContext &C, ArrayRef<CanType> elements) {
33023297
SmallVector<Type, 8> ncElements(elements.begin(), elements.end());
33033298
return CanPackType(PackType::get(C, ncElements));

lib/AST/ParameterPack.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,10 +460,13 @@ PackType *PackType::get(const ASTContext &C,
460460
return get(C, wrappedArgs)->flattenPackTypes();
461461
}
462462

463-
CanPackType PackArchetypeType::getSingletonPackType() {
464-
SmallVector<Type, 1> types;
465-
types.push_back(PackExpansionType::get(this, getReducedShape()));
466-
return CanPackType(PackType::get(getASTContext(), types));
463+
PackType *PackType::getSingletonPackExpansion(Type param) {
464+
assert(param->isParameterPack() || param->is<PackArchetypeType>());
465+
return get(param->getASTContext(), {PackExpansionType::get(param, param)});
466+
}
467+
468+
CanPackType CanPackType::getSingletonPackExpansion(CanType param) {
469+
return CanPackType(PackType::getSingletonPackExpansion(param));
467470
}
468471

469472
bool SILPackType::containsPackExpansionType() const {

lib/AST/RequirementMachine/RuleBuilder.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,8 @@ void RuleBuilder::addReferencedProtocol(const ProtocolDecl *proto) {
444444
}
445445

446446
/// Compute the transitive closure of the set of all protocols referenced from
447-
/// the right hand sides of conformance requirements, and convert their
448-
/// requirements to rewrite rules.
447+
/// the right hand sides of conformance requirements, and import the rewrite
448+
/// rules from the requirement machine for each protocol component.
449449
void RuleBuilder::collectRulesFromReferencedProtocols() {
450450
// Compute the transitive closure.
451451
unsigned i = 0;
@@ -462,12 +462,9 @@ void RuleBuilder::collectRulesFromReferencedProtocols() {
462462
// if this is a rewrite system for a connected component of the protocol
463463
// dependency graph, add rewrite rules for each referenced protocol not part
464464
// of this connected component.
465-
466-
// First, collect all unique requirement machines, one for each connected
467-
// component of each referenced protocol.
468465
llvm::DenseSet<RequirementMachine *> machines;
469466

470-
// Now visit each subordinate requirement machine pull in its rules.
467+
// Now visit each protocol component requirement machine and pull in its rules.
471468
for (auto *proto : ProtocolsToImport) {
472469
// This will trigger requirement signature computation for this protocol,
473470
// if necessary, which will cause us to re-enter into a new RuleBuilder
@@ -478,13 +475,13 @@ void RuleBuilder::collectRulesFromReferencedProtocols() {
478475

479476
auto *machine = Context.getRequirementMachine(proto);
480477
if (!machines.insert(machine).second) {
481-
// We've already seen this connected component.
478+
// We've already seen this protocol component.
482479
continue;
483480
}
484481

485482
// We grab the machine's local rules, not *all* of its rules, to avoid
486483
// duplicates in case multiple machines share a dependency on a downstream
487-
// protocol connected component.
484+
// protocol component.
488485
auto localRules = machine->getLocalRules();
489486
ImportedRules.insert(ImportedRules.end(),
490487
localRules.begin(),

lib/IRGen/Fulfillment.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ struct Fulfillment {
3737
: SourceIndex(sourceIndex), State(unsigned(state)), Path(std::move(path)) {}
3838

3939
/// The source index.
40-
unsigned SourceIndex : 30;
40+
uint64_t SourceIndex : 56;
4141

4242
/// The state of the metadata at the fulfillment.
43-
unsigned State : 2;
43+
uint64_t State : 8;
4444

4545
/// The path from the source metadata.
4646
MetadataPath Path;

lib/IRGen/GenPack.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "IRGenFunction.h"
3131
#include "IRGenModule.h"
3232
#include "MetadataRequest.h"
33+
#include "ResilientTypeInfo.h"
3334

3435
using namespace swift;
3536
using namespace irgen;
@@ -176,7 +177,7 @@ irgen::emitPackArchetypeMetadataRef(IRGenFunction &IGF,
176177
if (auto result = IGF.tryGetLocalTypeMetadata(type, request))
177178
return result;
178179

179-
auto packType = type->getSingletonPackType();
180+
auto packType = CanPackType::getSingletonPackExpansion(type);
180181
auto response = emitTypeMetadataPackRef(IGF, packType, request);
181182

182183
IGF.setScopedLocalTypeMetadata(type, response);
@@ -216,8 +217,13 @@ static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF,
216217
if (auto response = IGF.tryGetLocalTypeMetadata(elementArchetype, request))
217218
return response.getMetadata();
218219

220+
// If the pack is on the heap, the LSB is set, so mask it off.
219221
patternPack =
220-
IGF.Builder.CreatePointerCast(patternPack, IGF.IGM.TypeMetadataPtrPtrTy);
222+
IGF.Builder.CreatePtrToInt(patternPack, IGF.IGM.SizeTy);
223+
patternPack =
224+
IGF.Builder.CreateAnd(patternPack, llvm::ConstantInt::get(IGF.IGM.SizeTy, -2));
225+
patternPack =
226+
IGF.Builder.CreateIntToPtr(patternPack, IGF.IGM.TypeMetadataPtrPtrTy);
221227

222228
Address patternPackAddress(patternPack, IGF.IGM.TypeMetadataPtrTy,
223229
IGF.IGM.getPointerAlignment());
@@ -244,8 +250,14 @@ static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
244250
auto key = LocalTypeDataKind::forProtocolWitnessTable(conf);
245251
if (auto *wtable = IGF.tryGetLocalTypeData(elementArchetype, key))
246252
return wtable;
253+
254+
// If the pack is on the heap, the LSB is set, so mask it off.
255+
wtablePack =
256+
IGF.Builder.CreatePtrToInt(wtablePack, IGF.IGM.SizeTy);
257+
wtablePack =
258+
IGF.Builder.CreateAnd(wtablePack, llvm::ConstantInt::get(IGF.IGM.SizeTy, -2));
247259
wtablePack =
248-
IGF.Builder.CreatePointerCast(wtablePack, IGF.IGM.WitnessTablePtrPtrTy);
260+
IGF.Builder.CreateIntToPtr(wtablePack, IGF.IGM.WitnessTablePtrPtrTy);
249261

250262
Address patternPackAddress(wtablePack, IGF.IGM.WitnessTablePtrTy,
251263
IGF.IGM.getPointerAlignment());

lib/IRGen/GenRecord.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,6 @@ class RecordTypeInfo<Impl, Base, FieldImpl,
542542
}
543543

544544
private:
545-
/// Scan the given field info
546545
static unsigned findUniqueNonEmptyField(ArrayRef<FieldImpl> fields) {
547546
unsigned result = 0;
548547
for (auto &field : fields) {

lib/IRGen/GenTuple.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "Explosion.h"
3737
#include "IndirectTypeInfo.h"
3838
#include "NonFixedTypeInfo.h"
39+
#include "ResilientTypeInfo.h"
3940

4041
#include "GenTuple.h"
4142

@@ -44,6 +45,33 @@
4445
using namespace swift;
4546
using namespace irgen;
4647

48+
namespace {
49+
/// A type implementation for tuple types with a dynamic number of
50+
/// elements, that is, that contain pack expansion types. For now,
51+
/// these are completely abstract.
52+
class DynamicTupleTypeInfo
53+
: public ResilientTypeInfo<DynamicTupleTypeInfo>
54+
{
55+
public:
56+
DynamicTupleTypeInfo(llvm::Type *T,
57+
IsCopyable_t copyable)
58+
: ResilientTypeInfo(T, copyable, IsABIAccessible) {}
59+
60+
TypeLayoutEntry
61+
*buildTypeLayoutEntry(IRGenModule &IGM,
62+
SILType T,
63+
bool useStructLayouts) const override {
64+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
65+
}
66+
};
67+
} // end anonymous namespace
68+
69+
const TypeInfo *
70+
TypeConverter::convertDynamicTupleType(IsCopyable_t copyable) {
71+
llvm::Type *storageType = IGM.OpaqueTy;
72+
return new DynamicTupleTypeInfo(storageType, copyable);
73+
}
74+
4775
namespace {
4876
class TupleFieldInfo : public RecordField<TupleFieldInfo> {
4977
public:
@@ -488,6 +516,11 @@ namespace {
488516
} // end anonymous namespace
489517

490518
const TypeInfo *TypeConverter::convertTupleType(TupleType *tuple) {
519+
if (tuple->containsPackExpansionType()) {
520+
// FIXME: Figure out if its copyable at least
521+
return &getDynamicTupleTypeInfo(IsCopyable);
522+
}
523+
491524
TupleTypeBuilder builder(IGM, SILType::getPrimitiveAddressType(CanType(tuple)));
492525
return builder.layout(tuple->getElements());
493526
}

lib/IRGen/GenType.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,16 @@ const LoadableTypeInfo &TypeConverter::getEmptyTypeInfo() {
18241824
return *EmptyTI;
18251825
}
18261826

1827+
const TypeInfo &
1828+
TypeConverter::getDynamicTupleTypeInfo(IsCopyable_t isCopyable) {
1829+
auto &cache = DynamicTupleTI[(unsigned)isCopyable];
1830+
if (cache) return *cache;
1831+
cache = convertDynamicTupleType(isCopyable);
1832+
cache->NextConverted = FirstType;
1833+
FirstType = cache;
1834+
return *cache;
1835+
}
1836+
18271837
const TypeInfo &
18281838
TypeConverter::getResilientStructTypeInfo(IsCopyable_t isCopyable,
18291839
IsABIAccessible_t isAccessible) {

lib/IRGen/GenType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class TypeConverter {
123123
{nullptr, nullptr},
124124
{nullptr, nullptr},
125125
};
126+
127+
const TypeInfo *DynamicTupleTI[2] = {nullptr, nullptr};
126128

127129
llvm::DenseMap<std::pair<unsigned, unsigned>, const LoadableTypeInfo *>
128130
OpaqueStorageTypes;
@@ -177,6 +179,7 @@ class TypeConverter {
177179
const LoadableTypeInfo *convertBuiltinBridgeObject();
178180
const TypeInfo *convertResilientStruct(IsCopyable_t copyable,
179181
IsABIAccessible_t abiAccessible);
182+
const TypeInfo *convertDynamicTupleType(IsCopyable_t copyable);
180183
#define REF_STORAGE(Name, ...) \
181184
const TypeInfo *convert##Name##StorageType(Name##StorageType *T);
182185
#include "swift/AST/ReferenceStorage.def"
@@ -210,6 +213,7 @@ class TypeConverter {
210213
const LoadableTypeInfo &getIntegerLiteralTypeInfo();
211214
const TypeInfo &getResilientStructTypeInfo(IsCopyable_t copyable,
212215
IsABIAccessible_t abiAccessible);
216+
const TypeInfo &getDynamicTupleTypeInfo(IsCopyable_t isCopyable);
213217
const ProtocolInfo &getProtocolInfo(ProtocolDecl *P, ProtocolInfoKind kind);
214218
const LoadableTypeInfo &getOpaqueStorageTypeInfo(Size storageSize,
215219
Alignment storageAlign);

0 commit comments

Comments
 (0)