Skip to content

Commit e6c31d1

Browse files
authored
Merge pull request #24872 from slavapestov/lazy-nserror-bridging-conformances
Remove useBridgedNSErrorConformances()
2 parents 1e032ad + 73f1b10 commit e6c31d1

15 files changed

+94
-270
lines changed

lib/SIL/TypeLowering.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/DiagnosticsSIL.h"
2020
#include "swift/AST/Expr.h"
2121
#include "swift/AST/GenericEnvironment.h"
22+
#include "swift/AST/LazyResolver.h"
2223
#include "swift/AST/Module.h"
2324
#include "swift/AST/NameLookup.h"
2425
#include "swift/AST/Pattern.h"
@@ -1900,6 +1901,10 @@ TypeConverter::getFunctionInterfaceTypeWithCaptures(CanAnyFunctionType funcType,
19001901
CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
19011902
auto *vd = c.loc.dyn_cast<ValueDecl *>();
19021903

1904+
if (vd && !vd->hasInterfaceType()) {
1905+
Context.getLazyResolver()->resolveDeclSignature(vd);
1906+
}
1907+
19031908
switch (c.kind) {
19041909
case SILDeclRef::Kind::Func: {
19051910
if (auto *ACE = c.loc.dyn_cast<AbstractClosureExpr *>()) {

lib/SILGen/SILGen.cpp

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,6 @@ static SILFunction *getFunctionToInsertAfter(SILGenModule &SGM,
568568
return nullptr;
569569
}
570570

571-
static bool hasSILBody(FuncDecl *fd) {
572-
return fd->getBody(/*canSynthesize=*/false);
573-
}
574-
575571
static bool haveProfiledAssociatedFunction(SILDeclRef constant) {
576572
return constant.isDefaultArgGenerator() || constant.isForeign ||
577573
constant.isCurried;
@@ -610,7 +606,7 @@ static void setUpForProfiling(SILDeclRef constant, SILFunction *F,
610606
if (!haveProfiledAssociatedFunction(constant)) {
611607
if (constant.hasDecl()) {
612608
if (auto *fd = constant.getFuncDecl()) {
613-
if (hasSILBody(fd)) {
609+
if (fd->hasBody()) {
614610
F->createProfiler(fd, forDefinition);
615611
profiledNode = fd->getBody(/*canSynthesize=*/false);
616612
}
@@ -625,6 +621,32 @@ static void setUpForProfiling(SILDeclRef constant, SILFunction *F,
625621
}
626622
}
627623

624+
static bool isEmittedOnDemand(SILModule &M, SILDeclRef constant) {
625+
if (!constant.hasDecl())
626+
return false;
627+
628+
if (constant.isCurried ||
629+
constant.isForeign ||
630+
constant.isDirectReference)
631+
return false;
632+
633+
auto *d = constant.getDecl();
634+
auto *dc = d->getDeclContext()->getModuleScopeContext();
635+
636+
if (isa<ClangModuleUnit>(dc))
637+
return true;
638+
639+
if (auto *sf = dyn_cast<SourceFile>(dc))
640+
if (M.isWholeModule() || M.getAssociatedContext() == dc)
641+
return false;
642+
643+
if (auto *func = dyn_cast<FuncDecl>(d))
644+
if (func->hasForcedStaticDispatch())
645+
return true;
646+
647+
return false;
648+
}
649+
628650
SILFunction *SILGenModule::getFunction(SILDeclRef constant,
629651
ForDefinition_t forDefinition) {
630652
// If we already emitted the function, return it (potentially preparing it
@@ -645,6 +667,21 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
645667

646668
emittedFunctions[constant] = F;
647669

670+
if (isEmittedOnDemand(M, constant) &&
671+
!delayedFunctions.count(constant)) {
672+
auto *d = constant.getDecl();
673+
if (auto *func = dyn_cast<FuncDecl>(d)) {
674+
if (constant.kind == SILDeclRef::Kind::Func)
675+
emitFunction(func);
676+
} else if (auto *ctor = dyn_cast<ConstructorDecl>(d)) {
677+
// For factories, we don't need to emit a special thunk; the normal
678+
// foreign-to-native thunk is sufficient.
679+
if (!ctor->isFactoryInit() &&
680+
constant.kind == SILDeclRef::Kind::Allocator)
681+
emitConstructor(ctor);
682+
}
683+
}
684+
648685
// If we delayed emitting this function previously, we need it now.
649686
auto foundDelayed = delayedFunctions.find(constant);
650687
if (foundDelayed != delayedFunctions.end()) {
@@ -816,7 +853,7 @@ void SILGenModule::emitFunction(FuncDecl *fd) {
816853

817854
emitAbstractFuncDecl(fd);
818855

819-
if (hasSILBody(fd)) {
856+
if (fd->hasBody()) {
820857
FrontendStatsTracer Tracer(getASTContext().Stats, "SILGen-funcdecl", fd);
821858
PrettyStackTraceDecl stackTrace("emitting SIL for", fd);
822859

@@ -1736,27 +1773,19 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF) {
17361773
M->getSILLoader()->getAllForModule(mod->getName(), nullptr);
17371774
}
17381775

1739-
// Emit external definitions used by this module.
1740-
for (size_t i = 0, e = mod->getASTContext().LastCheckedExternalDefinition;
1741-
i != e; ++i) {
1742-
auto def = mod->getASTContext().ExternalDefinitions[i];
1743-
SGM.emitExternalDefinition(def);
1744-
}
1745-
17461776
// Emit any delayed definitions that were forced.
17471777
// Emitting these may in turn force more definitions, so we have to take care
17481778
// to keep pumping the queues.
17491779
while (!SGM.forcedFunctions.empty()
1750-
|| !SGM.forcedConformances.empty()) {
1780+
|| !SGM.pendingConformances.empty()) {
17511781
while (!SGM.forcedFunctions.empty()) {
17521782
auto &front = SGM.forcedFunctions.front();
17531783
front.second.emitter(SGM.getFunction(front.first, ForDefinition));
17541784
SGM.forcedFunctions.pop_front();
17551785
}
1756-
while (!SGM.forcedConformances.empty()) {
1757-
auto &front = SGM.forcedConformances.front();
1758-
SGM.getWitnessTable(front.first);
1759-
SGM.forcedConformances.pop_front();
1786+
while (!SGM.pendingConformances.empty()) {
1787+
SGM.getWitnessTable(SGM.pendingConformances.front());
1788+
SGM.pendingConformances.pop_front();
17601789
}
17611790
}
17621791

lib/SILGen/SILGen.h

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,28 +77,16 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
7777
/// The most recent declaration we considered for emission.
7878
SILDeclRef lastEmittedFunction;
7979

80-
/// Set of used conformances for which witness tables need to be emitted.
81-
llvm::DenseSet<RootProtocolConformance *> usedConformances;
82-
8380
/// Bookkeeping to ensure that useConformancesFrom{ObjectiveC,}Type() is
8481
/// only called once for each unique type, as an optimization.
8582
llvm::DenseSet<TypeBase *> usedConformancesFromTypes;
8683
llvm::DenseSet<TypeBase *> usedConformancesFromObjectiveCTypes;
8784

88-
struct DelayedWitnessTable {
89-
NormalProtocolConformance *insertAfter;
90-
};
91-
92-
/// Set of conformances we delayed emitting witness tables for.
93-
llvm::DenseMap<NormalProtocolConformance *, DelayedWitnessTable>
94-
delayedConformances;
85+
/// Queue of delayed conformances that need to be emitted.
86+
std::deque<NormalProtocolConformance *> pendingConformances;
9587

96-
/// Queue of delayed conformances that need to be forced.
97-
std::deque<std::pair<NormalProtocolConformance *, DelayedWitnessTable>>
98-
forcedConformances;
99-
100-
/// The most recent conformance...
101-
NormalProtocolConformance *lastEmittedConformance = nullptr;
88+
/// Set of delayed conformances that have already been forced.
89+
llvm::DenseSet<NormalProtocolConformance *> forcedConformances;
10290

10391
/// Profiler instances for constructors, grouped by associated decl.
10492
/// Each profiler is shared by all member initializers for a nominal type.
@@ -275,12 +263,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
275263

276264
/// Add a global variable to the SILModule.
277265
void addGlobalVariable(VarDecl *global);
278-
279-
/// Emit SIL related to a Clang-imported declaration.
280-
void emitExternalDefinition(Decl *d);
281-
282-
/// Emit SIL related to a Clang-imported declaration.
283-
void emitExternalWitnessTable(NormalProtocolConformance *d);
284266

285267
/// Emit the ObjC-compatible entry point for a method.
286268
void emitObjCMethodThunk(FuncDecl *method);

lib/SILGen/SILGenDecl.cpp

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,95 +1391,6 @@ CleanupHandle SILGenFunction::enterDeinitExistentialCleanup(
13911391
return Cleanups.getTopCleanup();
13921392
}
13931393

1394-
void SILGenModule::emitExternalWitnessTable(NormalProtocolConformance *c) {
1395-
// Emit the witness table right now if we used it.
1396-
if (usedConformances.count(c)) {
1397-
getWitnessTable(c);
1398-
return;
1399-
}
1400-
// Otherwise, remember it for later.
1401-
delayedConformances.insert({c, {lastEmittedConformance}});
1402-
lastEmittedConformance = c;
1403-
}
1404-
1405-
static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
1406-
auto *dc = d->getDeclContext();
1407-
if (auto *sf = dyn_cast<SourceFile>(dc->getModuleScopeContext()))
1408-
if (M.isWholeModule() || M.getAssociatedContext() == sf)
1409-
return true;
1410-
1411-
return false;
1412-
}
1413-
1414-
void SILGenModule::emitExternalDefinition(Decl *d) {
1415-
if (isDeclaredInPrimaryFile(M, d))
1416-
return;
1417-
1418-
switch (d->getKind()) {
1419-
case DeclKind::Func:
1420-
case DeclKind::Accessor: {
1421-
emitFunction(cast<FuncDecl>(d));
1422-
break;
1423-
}
1424-
case DeclKind::Constructor: {
1425-
auto C = cast<ConstructorDecl>(d);
1426-
// For factories, we don't need to emit a special thunk; the normal
1427-
// foreign-to-native thunk is sufficient.
1428-
if (C->isFactoryInit())
1429-
break;
1430-
1431-
emitConstructor(C);
1432-
break;
1433-
}
1434-
case DeclKind::Enum:
1435-
case DeclKind::Struct:
1436-
case DeclKind::Class: {
1437-
// Emit witness tables.
1438-
auto nom = cast<NominalTypeDecl>(d);
1439-
for (auto c : nom->getLocalConformances(ConformanceLookupKind::NonInherited,
1440-
nullptr)) {
1441-
auto *proto = c->getProtocol();
1442-
if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
1443-
isa<NormalProtocolConformance>(c)) {
1444-
emitExternalWitnessTable(cast<NormalProtocolConformance>(c));
1445-
}
1446-
}
1447-
break;
1448-
}
1449-
1450-
case DeclKind::Protocol:
1451-
// Nothing to do in SILGen for other external types.
1452-
break;
1453-
1454-
case DeclKind::Var:
1455-
// Imported static vars are handled solely in IRGen.
1456-
break;
1457-
1458-
case DeclKind::IfConfig:
1459-
case DeclKind::PoundDiagnostic:
1460-
case DeclKind::Extension:
1461-
case DeclKind::PatternBinding:
1462-
case DeclKind::EnumCase:
1463-
case DeclKind::EnumElement:
1464-
case DeclKind::TopLevelCode:
1465-
case DeclKind::TypeAlias:
1466-
case DeclKind::AssociatedType:
1467-
case DeclKind::GenericTypeParam:
1468-
case DeclKind::Param:
1469-
case DeclKind::Import:
1470-
case DeclKind::Subscript:
1471-
case DeclKind::Destructor:
1472-
case DeclKind::InfixOperator:
1473-
case DeclKind::PrefixOperator:
1474-
case DeclKind::PostfixOperator:
1475-
case DeclKind::PrecedenceGroup:
1476-
case DeclKind::Module:
1477-
case DeclKind::MissingMember:
1478-
case DeclKind::OpaqueType:
1479-
llvm_unreachable("Not a valid external definition for SILGen");
1480-
}
1481-
}
1482-
14831394
/// Create a LocalVariableInitialization for the uninitialized var.
14841395
InitializationPtr SILGenFunction::emitLocalVariableWithCleanup(
14851396
VarDecl *vd, Optional<MarkUninitializedInst::Kind> kind, unsigned ArgNo) {

lib/SILGen/SILGenLazyConformance.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,11 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
5353
if (emittedWitnessTables.count(normal))
5454
return;
5555

56-
// If we delayed emitting this witness table, force it.
57-
auto foundDelayed = delayedConformances.find(normal);
58-
if (foundDelayed != delayedConformances.end()) {
59-
forcedConformances.push_back(*foundDelayed);
60-
delayedConformances.erase(foundDelayed);
56+
// Check if we already forced this witness table but haven't emitted it yet.
57+
if (!forcedConformances.insert(normal).second)
6158
return;
62-
}
6359

64-
// Otherwise, just remember the fact we used this conformance.
65-
usedConformances.insert(normal);
60+
pendingConformances.push_back(normal);
6661
}
6762

6863
void SILGenModule::useConformancesFromSubstitutions(

lib/SILGen/SILGenType.cpp

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -545,27 +545,6 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
545545

546546
} // end anonymous namespace
547547

548-
static SILWitnessTable *
549-
getWitnessTableToInsertAfter(SILGenModule &SGM,
550-
NormalProtocolConformance *insertAfter) {
551-
while (insertAfter) {
552-
// If the table was emitted, emit after it.
553-
auto found = SGM.emittedWitnessTables.find(insertAfter);
554-
if (found != SGM.emittedWitnessTables.end())
555-
return found->second;
556-
557-
// Otherwise, try inserting after the table we would transitively be
558-
// inserted after.
559-
auto foundDelayed = SGM.delayedConformances.find(insertAfter);
560-
if (foundDelayed != SGM.delayedConformances.end())
561-
insertAfter = foundDelayed->second.insertAfter;
562-
else
563-
break;
564-
}
565-
566-
return nullptr;
567-
}
568-
569548
SILWitnessTable *
570549
SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
571550
// If we've already emitted this witness table, return it.
@@ -576,23 +555,6 @@ SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
576555
SILWitnessTable *table = SILGenConformance(*this, conformance).emit();
577556
emittedWitnessTables.insert({conformance, table});
578557

579-
// If we delayed emission of this witness table, move it to its rightful
580-
// place within the module.
581-
auto foundDelayed = delayedConformances.find(conformance);
582-
if (foundDelayed != delayedConformances.end()) {
583-
M.witnessTables.remove(table);
584-
auto insertAfter = getWitnessTableToInsertAfter(*this,
585-
foundDelayed->second.insertAfter);
586-
if (!insertAfter) {
587-
M.witnessTables.push_front(table);
588-
} else {
589-
M.witnessTables.insertAfter(insertAfter->getIterator(), table);
590-
}
591-
} else {
592-
// We would have marked a delayed conformance as "last emitted" when it
593-
// was delayed.
594-
lastEmittedConformance = conformance;
595-
}
596558
return table;
597559
}
598560

0 commit comments

Comments
 (0)