Skip to content

Commit 4aa1aa7

Browse files
committed
IRGen: Preliminary support for nested generic types
For now, just run the existing SILGen test to completion. I'll work on more tests later, I wanted to check this stuff in before it bitrots any further.
1 parent 8ffa514 commit 4aa1aa7

File tree

5 files changed

+26
-19
lines changed

5 files changed

+26
-19
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2338,7 +2338,7 @@ IRGenModule::getAddrOfGenericTypeMetadataAccessFunction(
23382338
assert(nominal->isGenericContext());
23392339

23402340
auto type = nominal->getDeclaredType()->getCanonicalType();
2341-
assert(isa<UnboundGenericType>(type));
2341+
assert(type->hasUnboundGenericType());
23422342
LinkEntity entity = LinkEntity::forTypeMetadataAccessFunction(type);
23432343
llvm::Function *&entry = GlobalFuncs[entity];
23442344
if (entry) {

lib/IRGen/GenMeta.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,23 @@ namespace {
189189
}
190190
}
191191

192-
void collect(IRGenFunction &IGF, CanBoundGenericType type) {
193-
GenericTypeRequirements requirements(IGF.IGM, type->getDecl());
192+
void collect(IRGenFunction &IGF, CanType type) {
193+
NominalTypeDecl *decl;
194+
CanType parentType;
195+
196+
if (auto nominalType = dyn_cast<NominalType>(type)) {
197+
decl = nominalType->getDecl();
198+
parentType = nominalType.getParent();
199+
} else {
200+
auto boundType = cast<BoundGenericType>(type);
201+
decl = boundType->getDecl();
202+
parentType = boundType.getParent();
203+
}
204+
205+
GenericTypeRequirements requirements(IGF.IGM, decl);
194206

195207
if (requirements.hasParentType()) {
196-
Values.push_back(IGF.emitTypeMetadataRef(type.getParent()));
208+
Values.push_back(IGF.emitTypeMetadataRef(parentType));
197209
}
198210

199211
auto subs =
@@ -208,7 +220,7 @@ namespace {
208220
}
209221
});
210222

211-
collectTypes(IGF.IGM, type->getDecl());
223+
collectTypes(IGF.IGM, decl);
212224
assert(Types.size() == Values.size());
213225
}
214226
};
@@ -372,8 +384,8 @@ static llvm::Value *emitNominalMetadataRef(IRGenFunction &IGF,
372384
}
373385

374386
// We are applying generic parameters to a generic type.
375-
auto boundGeneric = cast<BoundGenericType>(theType);
376-
assert(boundGeneric->getDecl() == theDecl);
387+
assert(theType->isSpecialized() &&
388+
theType->getAnyNominal() == theDecl);
377389

378390
// Check to see if we've maybe got a local reference already.
379391
if (auto cache = IGF.tryGetLocalTypeData(theType,
@@ -382,7 +394,7 @@ static llvm::Value *emitNominalMetadataRef(IRGenFunction &IGF,
382394

383395
// Grab the substitutions.
384396
GenericArguments genericArgs;
385-
genericArgs.collect(IGF, boundGeneric);
397+
genericArgs.collect(IGF, theType);
386398
assert(genericArgs.Values.size() > 0 && "no generic args?!");
387399

388400
// Call the generic metadata accessor function.
@@ -451,8 +463,6 @@ bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
451463
// access if it contains a resilient type.
452464
if (isa<StructType>(type) || isa<EnumType>(type)) {
453465
auto nominalType = cast<NominalType>(type);
454-
assert(!nominalType->getDecl()->isGenericContext() &&
455-
"shouldn't be called for a generic type");
456466

457467
// Imported type metadata always requires an accessor.
458468
if (nominalType->getDecl()->hasClangNode())
@@ -529,9 +539,9 @@ irgen::getTypeMetadataAccessStrategy(IRGenModule &IGM, CanType type) {
529539
// Metadata accessors for fully-substituted generic types are
530540
// emitted with shared linkage.
531541
if (nominal->isGenericContext() && !nominal->isObjC()) {
532-
if (isa<BoundGenericType>(type))
542+
if (type->isSpecialized())
533543
return MetadataAccessStrategy::NonUniqueAccessor;
534-
assert(isa<UnboundGenericType>(type));
544+
assert(type->hasUnboundGenericType());
535545
}
536546

537547
// If the type doesn't guarantee that it has an access function,

lib/IRGen/GenType.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ TypeCacheEntry TypeConverter::convertAnyNominalType(CanType type,
15581558
llvm_unreachable("bad declaration kind");
15591559
}
15601560

1561-
assert(decl->getGenericParams());
1561+
assert(decl->isGenericContext());
15621562

15631563
// Look to see if we've already emitted this type under a different
15641564
// set of arguments. We cache under the unbound type, which should
@@ -1567,7 +1567,7 @@ TypeCacheEntry TypeConverter::convertAnyNominalType(CanType type,
15671567
// FIXME: this isn't really inherently good; we might want to use
15681568
// different type implementations for different applications.
15691569
assert(decl->getDeclaredType()->isCanonical());
1570-
assert(decl->getDeclaredType()->is<UnboundGenericType>());
1570+
assert(decl->getDeclaredType()->hasUnboundGenericType());
15711571
TypeBase *key = decl->getDeclaredType().getPointer();
15721572
auto &Cache = Types.IndependentCache;
15731573
auto entry = Cache.find(key);

lib/IRGen/GenValueWitness.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,10 +1334,7 @@ static void addValueWitnesses(IRGenModule &IGM, FixedPacking packing,
13341334
/// Currently, this is true if the size and/or alignment of the type is
13351335
/// dependent on its generic parameters.
13361336
bool irgen::hasDependentValueWitnessTable(IRGenModule &IGM, CanType ty) {
1337-
if (auto ugt = dyn_cast<UnboundGenericType>(ty))
1338-
ty = ugt->getDecl()->getDeclaredTypeInContext()->getCanonicalType();
1339-
1340-
return !IGM.getTypeInfoForUnlowered(ty).isFixedSize();
1337+
return !IGM.getTypeInfoForUnlowered(getFormalTypeInContext(ty)).isFixedSize();
13411338
}
13421339

13431340
static void addValueWitnessesForAbstractType(IRGenModule &IGM,

test/SILGen/nested_generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-experimental-nested-generic-types -parse-as-library %s | FileCheck %s
22
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-sil -enable-experimental-nested-generic-types -parse-as-library %s > /dev/null
33
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-sil -O -enable-experimental-nested-generic-types -parse-as-library %s > /dev/null
4+
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-ir -enable-experimental-nested-generic-types -parse-as-library %s > /dev/null
45

56
// TODO:
67
// - test generated SIL -- mostly we're just testing mangling here
@@ -9,7 +10,6 @@
910
// - inner generic parameters on protocol requirements
1011
// - generic parameter list on method in nested type
1112
// - types nested inside unconstrained extensions of generic types
12-
// - add IRGen support and tests, and ensure this test runs to completion with -emit-ir
1313

1414
protocol Pizza : class {
1515
associatedtype Topping

0 commit comments

Comments
 (0)