Skip to content

[swift-4.0] Fix SIL serialization of witness tables and protocol witness thunks #10384

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 5 commits into from
Jun 26, 2017
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
4 changes: 0 additions & 4 deletions include/swift/AST/ProtocolConformance.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,6 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
/// is either the default definition or was otherwise deduced.
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const;

/// Returns true if this conformance has a layout that is known to all
/// consumers, based on the type/protocol involved in it.
bool hasFixedLayout() const;

// Make vanilla new/delete illegal for protocol conformances.
void *operator new(size_t bytes) = delete;
void operator delete(void *data) SWIFT_DELETE_OPERATOR_DELETED;
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ class SILOptions {
/// \brief Enable large loadable types IRGen pass.
bool EnableLargeLoadableTypes = false;

/// Enables the "fully fragile" resilience strategy.
///
/// \see ResilienceStrategy::Fragile
bool SILSerializeAll = false;

/// If set, SIL witness tables will be serialized.
///
/// It is supposed to be used only for compiling overlays.
/// User code should never be compiled with this flag set.
bool SILSerializeWitnessTables = false;

SILOptions() : Sanitize(SanitizerKind::None) {}

/// Return a hash code of any components from these options that should
Expand Down
5 changes: 0 additions & 5 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,6 @@ class FrontendOptions {
/// by the Clang importer as part of semantic analysis.
bool SerializeBridgingHeader = false;

/// Enables the "fully fragile" resilience strategy.
///
/// \see ResilienceStrategy::Fragile
bool SILSerializeAll = false;

/// Indicates whether or not the frontend should print statistics upon
/// termination.
bool PrintStats = false;
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ def sil_link_all : Flag<["-"], "sil-link-all">,
def sil_serialize_all : Flag<["-"], "sil-serialize-all">,
HelpText<"Serialize all generated SIL">;

def sil_serialize_witness_tables : Flag<["-"], "sil-serialize-witness-tables">,
HelpText<"Serialize eligible SIL witness tables">;

def sil_verify_all : Flag<["-"], "sil-verify-all">,
HelpText<"Verify SIL after each transform">;

Expand Down
16 changes: 4 additions & 12 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,6 @@ class SILModule {
/// optimizations can assume that they see the whole module.
bool wholeModule;

/// True if this SILModule is being completely serialized.
bool WholeModuleSerialized;

/// The options passed into this SILModule.
SILOptions &Options;

Expand All @@ -222,7 +219,7 @@ class SILModule {
// Intentionally marked private so that we need to use 'constructSIL()'
// to construct a SILModule.
SILModule(ModuleDecl *M, SILOptions &Options, const DeclContext *associatedDC,
bool wholeModule, bool wholeModuleSerialized);
bool wholeModule);

SILModule(const SILModule&) = delete;
void operator=(const SILModule&) = delete;
Expand Down Expand Up @@ -285,23 +282,18 @@ class SILModule {
///
/// If a source file is provided, SIL will only be emitted for decls in that
/// source file, starting from the specified element number.
///
/// If \p makeModuleFragile is true, all functions and global variables of
/// the module are marked as serialized. This is used for compiling the stdlib.
static std::unique_ptr<SILModule>
constructSIL(ModuleDecl *M, SILOptions &Options, FileUnit *sf = nullptr,
Optional<unsigned> startElem = None,
bool makeModuleFragile = false,
bool isWholeModule = false);

/// \brief Create and return an empty SIL module that we can
/// later parse SIL bodies directly into, without converting from an AST.
static std::unique_ptr<SILModule>
createEmptyModule(ModuleDecl *M, SILOptions &Options,
bool WholeModule = false,
bool WholeModuleSerialized = false) {
bool WholeModule = false) {
return std::unique_ptr<SILModule>(
new SILModule(M, Options, M, WholeModule, WholeModuleSerialized));
new SILModule(M, Options, M, WholeModule));
}

/// Get the Swift module associated with this SIL module.
Expand Down Expand Up @@ -330,7 +322,7 @@ class SILModule {
}

/// Returns true if everything in this SILModule is being serialized.
bool isWholeModuleSerialized() const { return WholeModuleSerialized; }
bool isWholeModuleSerialized() const { return Options.SILSerializeAll; }

SILOptions &getOptions() const { return Options; }

Expand Down
8 changes: 1 addition & 7 deletions include/swift/Subsystems.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,25 +242,19 @@ namespace swift {
///
/// The module must contain source files.
///
/// If \p makeModuleFragile is true, all functions and global variables of
/// the module are marked as fragile. This is used for compiling the stdlib.
/// if \p wholeModuleCompilation is true, the optimizer assumes that the SIL
/// of all files in the module is present in the SILModule.
std::unique_ptr<SILModule>
performSILGeneration(ModuleDecl *M, SILOptions &options,
bool makeModuleFragile = false,
bool wholeModuleCompilation = false);

/// Turn a source file into SIL IR.
///
/// If \p StartElem is provided, the module is assumed to be only part of the
/// SourceFile, and any optimizations should take that into account.
/// If \p makeModuleFragile is true, all functions and global variables of
/// the module are marked as fragile. This is used for compiling the stdlib.
std::unique_ptr<SILModule>
performSILGeneration(FileUnit &SF, SILOptions &options,
Optional<unsigned> StartElem = None,
bool makeModuleFragile = false);
Optional<unsigned> StartElem = None);

using ModuleOrSourceFile = PointerUnion<ModuleDecl *, SourceFile *>;

Expand Down
12 changes: 0 additions & 12 deletions lib/AST/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,18 +252,6 @@ usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
CONFORMANCE_SUBCLASS_DISPATCH(usesDefaultDefinition, (requirement))
}

bool ProtocolConformance::hasFixedLayout() const {
// A conformance/witness table has fixed layout if type has a fixed layout in
// all resilience domains, and the conformance is externally visible.
if (auto nominal = getType()->getAnyNominal())
if (nominal->hasFixedLayout() &&
getProtocol()->getEffectiveAccess() >= Accessibility::Public &&
nominal->getEffectiveAccess() >= Accessibility::Public)
return true;

return false;
}

GenericEnvironment *ProtocolConformance::getGenericEnvironment() const {
switch (getKind()) {
case ProtocolConformanceKind::Inherited:
Expand Down
5 changes: 4 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,6 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Args.hasArg(OPT_serialize_debugging_options);
Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
Opts.EnableSerializationNestedTypeLookupTable &=
!Args.hasArg(OPT_disable_serialization_nested_type_lookup_table);

Expand Down Expand Up @@ -1329,6 +1328,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_sil_merge_partial_modules))
Opts.MergePartialModules = true;

Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
Opts.SILSerializeWitnessTables |=
Args.hasArg(OPT_sil_serialize_witness_tables);

// Parse the optimization level.
if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
if (A->getOption().matches(OPT_Onone)) {
Expand Down
5 changes: 2 additions & 3 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ std::string CompilerInvocation::getPCHHash() const {
void CompilerInstance::createSILModule(bool WholeModule) {
assert(MainModule && "main module not created yet");
TheSILModule = SILModule::createEmptyModule(
getMainModule(), Invocation.getSILOptions(), WholeModule,
Invocation.getFrontendOptions().SILSerializeAll);
getMainModule(), Invocation.getSILOptions(), WholeModule);
}

void CompilerInstance::setPrimarySourceFile(SourceFile *SF) {
Expand Down Expand Up @@ -250,7 +249,7 @@ ModuleDecl *CompilerInstance::getMainModule() {

if (Invocation.getFrontendOptions().EnableResilience)
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
else if (Invocation.getFrontendOptions().SILSerializeAll)
else if (Invocation.getSILOptions().SILSerializeAll)
MainModule->setResilienceStrategy(ResilienceStrategy::Fragile);
}
return MainModule;
Expand Down
7 changes: 4 additions & 3 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,13 +691,13 @@ static bool performCompile(CompilerInstance &Instance,
}
astGuaranteedToCorrespondToSIL = !fileIsSIB(PrimaryFile);
SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(),
None, opts.SILSerializeAll);
None);
} else {
auto mod = Instance.getMainModule();
astGuaranteedToCorrespondToSIL =
llvm::none_of(mod->getFiles(), fileIsSIB);
SM = performSILGeneration(mod, Invocation.getSILOptions(),
opts.SILSerializeAll, true);
true);
}
}

Expand Down Expand Up @@ -835,7 +835,8 @@ static bool performCompile(CompilerInstance &Instance,
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str();
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
serializationOpts.SerializeAllSIL = opts.SILSerializeAll;
serializationOpts.SerializeAllSIL =
Invocation.getSILOptions().SILSerializeAll;
if (opts.SerializeBridgingHeader)
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
Expand Down
5 changes: 2 additions & 3 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1352,9 +1352,8 @@ bool LinkEntity::isFragile(ForDefinition_t isDefinition) const {
auto isCompletelySerialized = conformanceModule->getResilienceStrategy() ==
ResilienceStrategy::Fragile;

// The conformance is fragile if it is in a -sil-serialize-all module, or
// has a fully publicly determined layout.
return isCompletelySerialized || conformance->hasFixedLayout();
// The conformance is fragile if it is in a -sil-serialize-all module.
return isCompletelySerialized;
}
return false;
}
Expand Down
6 changes: 2 additions & 4 deletions lib/SIL/SILModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,10 @@ class SILModule::SerializationCallback : public SerializedSILLoader::Callback {
};

SILModule::SILModule(ModuleDecl *SwiftModule, SILOptions &Options,
const DeclContext *associatedDC, bool wholeModule,
bool wholeModuleSerialized)
const DeclContext *associatedDC, bool wholeModule)
: TheSwiftModule(SwiftModule), AssociatedDeclContext(associatedDC),
Stage(SILStage::Raw), Callback(new SILModule::SerializationCallback()),
wholeModule(wholeModule), WholeModuleSerialized(wholeModuleSerialized),
Options(Options), Types(*this) {}
wholeModule(wholeModule), Options(Options), Types(*this) {}

SILModule::~SILModule() {
// Decrement ref count for each SILGlobalVariable with static initializers.
Expand Down
24 changes: 11 additions & 13 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ using namespace Lowering;
// SILGenModule Class implementation
//===----------------------------------------------------------------------===//

SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM, bool makeModuleFragile)
SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM)
: M(M), Types(M.Types), SwiftModule(SM), TopLevelSGF(nullptr),
Profiler(nullptr), makeModuleFragile(makeModuleFragile) {
Profiler(nullptr) {
}

SILGenModule::~SILGenModule() {
Expand Down Expand Up @@ -451,7 +451,7 @@ SILFunction *SILGenModule::getEmittedFunction(SILDeclRef constant,
if (isAvailableExternally(F->getLinkage())) {
F->setLinkage(constant.getLinkage(ForDefinition));
}
if (makeModuleFragile) {
if (isMakeModuleFragile()) {
F->setSerialized(IsSerialized);
}
}
Expand Down Expand Up @@ -498,7 +498,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,

assert(F && "SILFunction should have been defined");

if (makeModuleFragile) {
if (isMakeModuleFragile()) {
SILLinkage linkage = constant.getLinkage(forDefinition);
if (linkage != SILLinkage::PublicExternal) {
F->setSerialized(IsSerialized);
Expand Down Expand Up @@ -959,7 +959,7 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
M.createFunction(SILLinkage::Private,
funcName, initSILType, nullptr,
SILLocation(binding), IsNotBare, IsNotTransparent,
makeModuleFragile
isMakeModuleFragile()
? IsSerialized
: IsNotSerialized);
f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
Expand Down Expand Up @@ -1375,7 +1375,7 @@ void SILGenModule::emitSourceFile(SourceFile *sf, unsigned startElem) {

std::unique_ptr<SILModule>
SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
Optional<unsigned> startElem, bool makeModuleFragile,
Optional<unsigned> startElem,
bool isWholeModule) {
SharedTimer timer("SILGen");
const DeclContext *DC;
Expand All @@ -1391,8 +1391,8 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
}

std::unique_ptr<SILModule> M(
new SILModule(mod, options, DC, isWholeModule, makeModuleFragile));
SILGenModule SGM(*M, mod, makeModuleFragile);
new SILModule(mod, options, DC, isWholeModule));
SILGenModule SGM(*M, mod);

if (SF) {
if (auto *file = dyn_cast<SourceFile>(SF)) {
Expand Down Expand Up @@ -1450,16 +1450,14 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
std::unique_ptr<SILModule>
swift::performSILGeneration(ModuleDecl *mod,
SILOptions &options,
bool makeModuleFragile,
bool wholeModuleCompilation) {
return SILModule::constructSIL(mod, options, nullptr, None, makeModuleFragile,
return SILModule::constructSIL(mod, options, nullptr, None,
wholeModuleCompilation);
}

std::unique_ptr<SILModule>
swift::performSILGeneration(FileUnit &sf, SILOptions &options,
Optional<unsigned> startElem,
bool makeModuleFragile) {
Optional<unsigned> startElem) {
return SILModule::constructSIL(sf.getParentModule(), options, &sf, startElem,
makeModuleFragile, false);
false);
}
4 changes: 2 additions & 2 deletions lib/SILGen/SILGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {

/// If true, all functions and globals are made fragile. Currently only used
/// for compiling the stdlib.
bool makeModuleFragile;
bool isMakeModuleFragile() const { return M.getOptions().SILSerializeAll; }

Optional<SILDeclRef> StringToNSStringFn;
Optional<SILDeclRef> NSStringToStringFn;
Expand Down Expand Up @@ -136,7 +136,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
Optional<ProtocolConformance *> NSErrorConformanceToError;

public:
SILGenModule(SILModule &M, ModuleDecl *SM, bool makeModuleFragile);
SILGenModule(SILModule &M, ModuleDecl *SM);

~SILGenModule();

Expand Down
4 changes: 2 additions & 2 deletions lib/SILGen/SILGenGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl,
SILType silTy = M.Types.getLoweredTypeOfGlobal(gDecl);

auto *silGlobal = SILGlobalVariable::create(M, link,
makeModuleFragile
isMakeModuleFragile()
? IsSerialized
: IsNotSerialized,
mangledName, silTy,
Expand Down Expand Up @@ -223,7 +223,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
// TODO: include the module in the onceToken's name mangling.
// Then we can make it fragile.
auto onceToken = SILGlobalVariable::create(M, SILLinkage::Private,
makeModuleFragile
isMakeModuleFragile()
? IsSerialized
: IsNotSerialized,
onceTokenBuffer, onceSILTy);
Expand Down
18 changes: 15 additions & 3 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,20 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
Serialized = IsNotSerialized;

// Serialize the witness table if we're serializing everything with
// -sil-serialize-all, or if the conformance itself thinks it should be.
if (SGM.makeModuleFragile || Conformance->hasFixedLayout())
// -sil-serialize-all.
if (SGM.isMakeModuleFragile())
Serialized = IsSerialized;

auto *nominal = Conformance->getType()->getAnyNominal();
// Serialize the witness table if the conformance itself thinks it should be
// and resilience is explicitly enabled for this compilaiton or if we serialize
// all eligible witness tables.
if ((SGM.M.getSwiftModule()->getResilienceStrategy() ==
ResilienceStrategy::Resilient ||
SGM.M.getOptions().SILSerializeWitnessTables) &&
nominal->hasFixedLayout() &&
proto->getEffectiveAccess() >= Accessibility::Public &&
nominal->getEffectiveAccess() >= Accessibility::Public)
Serialized = IsSerialized;

// Not all protocols use witness tables; in this case we just skip
Expand Down Expand Up @@ -425,7 +437,7 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
// then SILGen gives the member private linkage, ignoring the more
// visible accessibility it was given in the AST.
witnessLinkage = SILLinkage::Public;
witnessSerialized = (SGM.makeModuleFragile
witnessSerialized = (SGM.isMakeModuleFragile()
? IsSerialized
: IsNotSerialized);
} else {
Expand Down
Loading