IRGen: Deserialize SIL witness tables and shared-linkage definitions by need.

Code may end up indirectly using a witness table for a Clang-imported type by inlining code that used the conformance from another module, in which case we need to ensure we have a local definition at hand in the inlining module so we can have something to link against independently. This needs to be fixed from both sides:

- During serialization, serialize not only witness tables from the current module, but from Clang-imported modules too, so that their definitions can be used by other modules that inline code from the current module
- During IRGen, when we emit a reference to a SILWitnessTable or SILFunction declaration with shared linkage, attempt to deserialize the definition on demand

Fixes rdar://problem/38687726.
This commit is contained in:
Joe Groff
2018-03-28 15:32:01 -07:00
parent 5db268292f
commit ae2d2973d1
9 changed files with 117 additions and 10 deletions

View File

@@ -24,6 +24,7 @@
#include "swift/IRGen/Linking.h"
#include "swift/Runtime/RuntimeFnWrappersGen.h"
#include "swift/Runtime/Config.h"
#include "swift/SIL/FormalLinkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetInfo.h"
@@ -658,6 +659,9 @@ llvm::Module *IRGenModule::releaseModule() {
}
bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) {
if (LazilyEmittedWitnessTables.count(wt))
return true;
if (Opts.UseJIT)
return false;
@@ -685,6 +689,21 @@ void IRGenerator::addLazyWitnessTable(const ProtocolConformance *Conf) {
LazilyEmittedWitnessTables.insert(wt).second) {
LazyWitnessTables.push_back(wt);
}
// Shared-linkage protocol conformances may not have been deserialized yet
// if they were used by inlined code. See if we can deserialize it now.
} else {
auto linkage =
getLinkageForProtocolConformance(Conf->getRootNormalConformance(),
ForDefinition);
if (hasSharedVisibility(linkage)) {
SIL.createWitnessTableDeclaration(const_cast<ProtocolConformance*>(Conf),
linkage);
SILWitnessTable *wt = SIL.lookUpWitnessTable(Conf);
if (wt && wt->isDefinition()
&& LazilyEmittedWitnessTables.insert(wt).second) {
LazyWitnessTables.push_back(wt);
}
}
}
}