Skip to content

Commit cf60ed5

Browse files
committed
SILGen: Force lazy conformances referenced from various places in the AST
SILGen has the ability to lazily emit ClangImporter-synthesized conformances. Sema builds a per-SourceFile list of "used" conformances, which are forced to be emitted by SILGen. All other conformances can be emitted lazily. Some of these "used" conformances are in fact not referenced by SILGen at all, but must exist for emission by IRGen so that they can be referenced from type metadata accessors, as well as available at runtime for the dynamic cast machinery. To handle these cases, add an AST walk to SILGen which emits the types of stored properties, the superclass of a class, and a few other things that might not be referenced directly from SIL. For now, this is all redundant because Sema forces the right conformances anyway, but that's going to change soon.
1 parent 9ffe12d commit cf60ed5

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

lib/SILGen/SILGen.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
431431
/// Emit all lazy conformances referenced from this function body.
432432
void emitLazyConformancesForFunction(SILFunction *F);
433433

434+
/// Emit all lazy conformances referenced from this type's signature and
435+
/// stored properties (or in the case of enums, associated values).
436+
void emitLazyConformancesForType(NominalTypeDecl *NTD);
437+
434438
/// Mark a protocol conformance as used, so we know we need to emit it if
435439
/// it's in our TU.
436440
void useConformance(ProtocolConformanceRef conformance);

lib/SILGen/SILGenLazyConformance.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,42 @@ void SILGenModule::emitLazyConformancesForFunction(SILFunction *F) {
249249
for (auto &BB : *F)
250250
for (auto &I : BB)
251251
emitter.visit(&I);
252+
}
253+
254+
void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) {
255+
auto *genericSig = NTD->getGenericSignature();
256+
257+
if (genericSig) {
258+
for (auto reqt : genericSig->getRequirements()) {
259+
if (reqt.getKind() != RequirementKind::Layout)
260+
useConformancesFromType(reqt.getSecondType()->getCanonicalType());
261+
}
262+
}
263+
264+
if (auto *ED = dyn_cast<EnumDecl>(NTD)) {
265+
for (auto *EED : ED->getAllElements()) {
266+
if (EED->hasAssociatedValues()) {
267+
useConformancesFromType(EED->getArgumentInterfaceType()
268+
->getCanonicalType(genericSig));
269+
}
270+
}
271+
}
272+
273+
if (isa<StructDecl>(NTD) || isa<ClassDecl>(NTD)) {
274+
for (auto *VD : NTD->getStoredProperties()) {
275+
useConformancesFromType(VD->getValueInterfaceType()
276+
->getCanonicalType(genericSig));
277+
}
278+
}
279+
280+
if (auto *CD = dyn_cast<ClassDecl>(NTD))
281+
if (auto superclass = CD->getSuperclass())
282+
useConformancesFromType(superclass->getCanonicalType(genericSig));
283+
284+
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
285+
for (auto reqt : PD->getRequirementSignature()) {
286+
if (reqt.getKind() != RequirementKind::Layout)
287+
useConformancesFromType(reqt.getSecondType()->getCanonicalType());
288+
}
289+
}
252290
}

lib/SILGen/SILGenType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,8 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
949949

950950
/// Emit SIL functions for all the members of the type.
951951
void emitType() {
952+
SGM.emitLazyConformancesForType(theType);
953+
952954
for (Decl *member : theType->getMembers())
953955
visit(member);
954956

0 commit comments

Comments
 (0)