Skip to content

Remove useBridgedNSErrorConformances() #24872

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Pattern.h"
Expand Down Expand Up @@ -1900,6 +1901,10 @@ TypeConverter::getFunctionInterfaceTypeWithCaptures(CanAnyFunctionType funcType,
CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
auto *vd = c.loc.dyn_cast<ValueDecl *>();

if (vd && !vd->hasInterfaceType()) {
Context.getLazyResolver()->resolveDeclSignature(vd);
}

switch (c.kind) {
case SILDeclRef::Kind::Func: {
if (auto *ACE = c.loc.dyn_cast<AbstractClosureExpr *>()) {
Expand Down
65 changes: 47 additions & 18 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,6 @@ static SILFunction *getFunctionToInsertAfter(SILGenModule &SGM,
return nullptr;
}

static bool hasSILBody(FuncDecl *fd) {
return fd->getBody(/*canSynthesize=*/false);
}

static bool haveProfiledAssociatedFunction(SILDeclRef constant) {
return constant.isDefaultArgGenerator() || constant.isForeign ||
constant.isCurried;
Expand Down Expand Up @@ -610,7 +606,7 @@ static void setUpForProfiling(SILDeclRef constant, SILFunction *F,
if (!haveProfiledAssociatedFunction(constant)) {
if (constant.hasDecl()) {
if (auto *fd = constant.getFuncDecl()) {
if (hasSILBody(fd)) {
if (fd->hasBody()) {
F->createProfiler(fd, forDefinition);
profiledNode = fd->getBody(/*canSynthesize=*/false);
}
Expand All @@ -625,6 +621,32 @@ static void setUpForProfiling(SILDeclRef constant, SILFunction *F,
}
}

static bool isEmittedOnDemand(SILModule &M, SILDeclRef constant) {
if (!constant.hasDecl())
return false;

if (constant.isCurried ||
constant.isForeign ||
constant.isDirectReference)
return false;

auto *d = constant.getDecl();
auto *dc = d->getDeclContext()->getModuleScopeContext();

if (isa<ClangModuleUnit>(dc))
return true;

if (auto *sf = dyn_cast<SourceFile>(dc))
if (M.isWholeModule() || M.getAssociatedContext() == dc)
return false;

if (auto *func = dyn_cast<FuncDecl>(d))
if (func->hasForcedStaticDispatch())
return true;

return false;
}

SILFunction *SILGenModule::getFunction(SILDeclRef constant,
ForDefinition_t forDefinition) {
// If we already emitted the function, return it (potentially preparing it
Expand All @@ -645,6 +667,21 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,

emittedFunctions[constant] = F;

if (isEmittedOnDemand(M, constant) &&
!delayedFunctions.count(constant)) {
auto *d = constant.getDecl();
if (auto *func = dyn_cast<FuncDecl>(d)) {
if (constant.kind == SILDeclRef::Kind::Func)
emitFunction(func);
} else if (auto *ctor = dyn_cast<ConstructorDecl>(d)) {
// For factories, we don't need to emit a special thunk; the normal
// foreign-to-native thunk is sufficient.
if (!ctor->isFactoryInit() &&
constant.kind == SILDeclRef::Kind::Allocator)
emitConstructor(ctor);
}
}

// If we delayed emitting this function previously, we need it now.
auto foundDelayed = delayedFunctions.find(constant);
if (foundDelayed != delayedFunctions.end()) {
Expand Down Expand Up @@ -816,7 +853,7 @@ void SILGenModule::emitFunction(FuncDecl *fd) {

emitAbstractFuncDecl(fd);

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

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

// Emit external definitions used by this module.
for (size_t i = 0, e = mod->getASTContext().LastCheckedExternalDefinition;
i != e; ++i) {
auto def = mod->getASTContext().ExternalDefinitions[i];
SGM.emitExternalDefinition(def);
}

// Emit any delayed definitions that were forced.
// Emitting these may in turn force more definitions, so we have to take care
// to keep pumping the queues.
while (!SGM.forcedFunctions.empty()
|| !SGM.forcedConformances.empty()) {
|| !SGM.pendingConformances.empty()) {
while (!SGM.forcedFunctions.empty()) {
auto &front = SGM.forcedFunctions.front();
front.second.emitter(SGM.getFunction(front.first, ForDefinition));
SGM.forcedFunctions.pop_front();
}
while (!SGM.forcedConformances.empty()) {
auto &front = SGM.forcedConformances.front();
SGM.getWitnessTable(front.first);
SGM.forcedConformances.pop_front();
while (!SGM.pendingConformances.empty()) {
SGM.getWitnessTable(SGM.pendingConformances.front());
SGM.pendingConformances.pop_front();
}
}

Expand Down
26 changes: 4 additions & 22 deletions lib/SILGen/SILGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,28 +77,16 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
/// The most recent declaration we considered for emission.
SILDeclRef lastEmittedFunction;

/// Set of used conformances for which witness tables need to be emitted.
llvm::DenseSet<RootProtocolConformance *> usedConformances;

/// Bookkeeping to ensure that useConformancesFrom{ObjectiveC,}Type() is
/// only called once for each unique type, as an optimization.
llvm::DenseSet<TypeBase *> usedConformancesFromTypes;
llvm::DenseSet<TypeBase *> usedConformancesFromObjectiveCTypes;

struct DelayedWitnessTable {
NormalProtocolConformance *insertAfter;
};

/// Set of conformances we delayed emitting witness tables for.
llvm::DenseMap<NormalProtocolConformance *, DelayedWitnessTable>
delayedConformances;
/// Queue of delayed conformances that need to be emitted.
std::deque<NormalProtocolConformance *> pendingConformances;

/// Queue of delayed conformances that need to be forced.
std::deque<std::pair<NormalProtocolConformance *, DelayedWitnessTable>>
forcedConformances;

/// The most recent conformance...
NormalProtocolConformance *lastEmittedConformance = nullptr;
/// Set of delayed conformances that have already been forced.
llvm::DenseSet<NormalProtocolConformance *> forcedConformances;

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

/// Add a global variable to the SILModule.
void addGlobalVariable(VarDecl *global);

/// Emit SIL related to a Clang-imported declaration.
void emitExternalDefinition(Decl *d);

/// Emit SIL related to a Clang-imported declaration.
void emitExternalWitnessTable(NormalProtocolConformance *d);

/// Emit the ObjC-compatible entry point for a method.
void emitObjCMethodThunk(FuncDecl *method);
Expand Down
89 changes: 0 additions & 89 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1391,95 +1391,6 @@ CleanupHandle SILGenFunction::enterDeinitExistentialCleanup(
return Cleanups.getTopCleanup();
}

void SILGenModule::emitExternalWitnessTable(NormalProtocolConformance *c) {
// Emit the witness table right now if we used it.
if (usedConformances.count(c)) {
getWitnessTable(c);
return;
}
// Otherwise, remember it for later.
delayedConformances.insert({c, {lastEmittedConformance}});
lastEmittedConformance = c;
}

static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
auto *dc = d->getDeclContext();
if (auto *sf = dyn_cast<SourceFile>(dc->getModuleScopeContext()))
if (M.isWholeModule() || M.getAssociatedContext() == sf)
return true;

return false;
}

void SILGenModule::emitExternalDefinition(Decl *d) {
if (isDeclaredInPrimaryFile(M, d))
return;

switch (d->getKind()) {
case DeclKind::Func:
case DeclKind::Accessor: {
emitFunction(cast<FuncDecl>(d));
break;
}
case DeclKind::Constructor: {
auto C = cast<ConstructorDecl>(d);
// For factories, we don't need to emit a special thunk; the normal
// foreign-to-native thunk is sufficient.
if (C->isFactoryInit())
break;

emitConstructor(C);
break;
}
case DeclKind::Enum:
case DeclKind::Struct:
case DeclKind::Class: {
// Emit witness tables.
auto nom = cast<NominalTypeDecl>(d);
for (auto c : nom->getLocalConformances(ConformanceLookupKind::NonInherited,
nullptr)) {
auto *proto = c->getProtocol();
if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
isa<NormalProtocolConformance>(c)) {
emitExternalWitnessTable(cast<NormalProtocolConformance>(c));
}
}
break;
}

case DeclKind::Protocol:
// Nothing to do in SILGen for other external types.
break;

case DeclKind::Var:
// Imported static vars are handled solely in IRGen.
break;

case DeclKind::IfConfig:
case DeclKind::PoundDiagnostic:
case DeclKind::Extension:
case DeclKind::PatternBinding:
case DeclKind::EnumCase:
case DeclKind::EnumElement:
case DeclKind::TopLevelCode:
case DeclKind::TypeAlias:
case DeclKind::AssociatedType:
case DeclKind::GenericTypeParam:
case DeclKind::Param:
case DeclKind::Import:
case DeclKind::Subscript:
case DeclKind::Destructor:
case DeclKind::InfixOperator:
case DeclKind::PrefixOperator:
case DeclKind::PostfixOperator:
case DeclKind::PrecedenceGroup:
case DeclKind::Module:
case DeclKind::MissingMember:
case DeclKind::OpaqueType:
llvm_unreachable("Not a valid external definition for SILGen");
}
}

/// Create a LocalVariableInitialization for the uninitialized var.
InitializationPtr SILGenFunction::emitLocalVariableWithCleanup(
VarDecl *vd, Optional<MarkUninitializedInst::Kind> kind, unsigned ArgNo) {
Expand Down
11 changes: 3 additions & 8 deletions lib/SILGen/SILGenLazyConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,11 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
if (emittedWitnessTables.count(normal))
return;

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

// Otherwise, just remember the fact we used this conformance.
usedConformances.insert(normal);
pendingConformances.push_back(normal);
}

void SILGenModule::useConformancesFromSubstitutions(
Expand Down
38 changes: 0 additions & 38 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,27 +545,6 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {

} // end anonymous namespace

static SILWitnessTable *
getWitnessTableToInsertAfter(SILGenModule &SGM,
NormalProtocolConformance *insertAfter) {
while (insertAfter) {
// If the table was emitted, emit after it.
auto found = SGM.emittedWitnessTables.find(insertAfter);
if (found != SGM.emittedWitnessTables.end())
return found->second;

// Otherwise, try inserting after the table we would transitively be
// inserted after.
auto foundDelayed = SGM.delayedConformances.find(insertAfter);
if (foundDelayed != SGM.delayedConformances.end())
insertAfter = foundDelayed->second.insertAfter;
else
break;
}

return nullptr;
}

SILWitnessTable *
SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
// If we've already emitted this witness table, return it.
Expand All @@ -576,23 +555,6 @@ SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
SILWitnessTable *table = SILGenConformance(*this, conformance).emit();
emittedWitnessTables.insert({conformance, table});

// If we delayed emission of this witness table, move it to its rightful
// place within the module.
auto foundDelayed = delayedConformances.find(conformance);
if (foundDelayed != delayedConformances.end()) {
M.witnessTables.remove(table);
auto insertAfter = getWitnessTableToInsertAfter(*this,
foundDelayed->second.insertAfter);
if (!insertAfter) {
M.witnessTables.push_front(table);
} else {
M.witnessTables.insertAfter(insertAfter->getIterator(), table);
}
} else {
// We would have marked a delayed conformance as "last emitted" when it
// was delayed.
lastEmittedConformance = conformance;
}
return table;
}

Expand Down
Loading