Skip to content

Commit 59ed33d

Browse files
authored
Merge pull request #10384 from swiftix/swift-4.0-branch-fixes1
[swift-4.0] Fix SIL serialization of witness tables and protocol witness thunks
2 parents 058a720 + 253069d commit 59ed33d

33 files changed

+99
-105
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,6 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
234234
/// is either the default definition or was otherwise deduced.
235235
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const;
236236

237-
/// Returns true if this conformance has a layout that is known to all
238-
/// consumers, based on the type/protocol involved in it.
239-
bool hasFixedLayout() const;
240-
241237
// Make vanilla new/delete illegal for protocol conformances.
242238
void *operator new(size_t bytes) = delete;
243239
void operator delete(void *data) SWIFT_DELETE_OPERATOR_DELETED;

include/swift/AST/SILOptions.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ class SILOptions {
152152
/// \brief Enable large loadable types IRGen pass.
153153
bool EnableLargeLoadableTypes = false;
154154

155+
/// Enables the "fully fragile" resilience strategy.
156+
///
157+
/// \see ResilienceStrategy::Fragile
158+
bool SILSerializeAll = false;
159+
160+
/// If set, SIL witness tables will be serialized.
161+
///
162+
/// It is supposed to be used only for compiling overlays.
163+
/// User code should never be compiled with this flag set.
164+
bool SILSerializeWitnessTables = false;
165+
155166
SILOptions() : Sanitize(SanitizerKind::None) {}
156167

157168
/// Return a hash code of any components from these options that should

include/swift/Frontend/FrontendOptions.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,6 @@ class FrontendOptions {
245245
/// by the Clang importer as part of semantic analysis.
246246
bool SerializeBridgingHeader = false;
247247

248-
/// Enables the "fully fragile" resilience strategy.
249-
///
250-
/// \see ResilienceStrategy::Fragile
251-
bool SILSerializeAll = false;
252-
253248
/// Indicates whether or not the frontend should print statistics upon
254249
/// termination.
255250
bool PrintStats = false;

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ def sil_link_all : Flag<["-"], "sil-link-all">,
368368
def sil_serialize_all : Flag<["-"], "sil-serialize-all">,
369369
HelpText<"Serialize all generated SIL">;
370370

371+
def sil_serialize_witness_tables : Flag<["-"], "sil-serialize-witness-tables">,
372+
HelpText<"Serialize eligible SIL witness tables">;
373+
371374
def sil_verify_all : Flag<["-"], "sil-verify-all">,
372375
HelpText<"Verify SIL after each transform">;
373376

include/swift/SIL/SILModule.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,6 @@ class SILModule {
209209
/// optimizations can assume that they see the whole module.
210210
bool wholeModule;
211211

212-
/// True if this SILModule is being completely serialized.
213-
bool WholeModuleSerialized;
214-
215212
/// The options passed into this SILModule.
216213
SILOptions &Options;
217214

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

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

297290
/// \brief Create and return an empty SIL module that we can
298291
/// later parse SIL bodies directly into, without converting from an AST.
299292
static std::unique_ptr<SILModule>
300293
createEmptyModule(ModuleDecl *M, SILOptions &Options,
301-
bool WholeModule = false,
302-
bool WholeModuleSerialized = false) {
294+
bool WholeModule = false) {
303295
return std::unique_ptr<SILModule>(
304-
new SILModule(M, Options, M, WholeModule, WholeModuleSerialized));
296+
new SILModule(M, Options, M, WholeModule));
305297
}
306298

307299
/// Get the Swift module associated with this SIL module.
@@ -330,7 +322,7 @@ class SILModule {
330322
}
331323

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

335327
SILOptions &getOptions() const { return Options; }
336328

include/swift/Subsystems.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,19 @@ namespace swift {
243243
///
244244
/// The module must contain source files.
245245
///
246-
/// If \p makeModuleFragile is true, all functions and global variables of
247-
/// the module are marked as fragile. This is used for compiling the stdlib.
248246
/// if \p wholeModuleCompilation is true, the optimizer assumes that the SIL
249247
/// of all files in the module is present in the SILModule.
250248
std::unique_ptr<SILModule>
251249
performSILGeneration(ModuleDecl *M, SILOptions &options,
252-
bool makeModuleFragile = false,
253250
bool wholeModuleCompilation = false);
254251

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

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

lib/AST/ProtocolConformance.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -252,18 +252,6 @@ usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
252252
CONFORMANCE_SUBCLASS_DISPATCH(usesDefaultDefinition, (requirement))
253253
}
254254

255-
bool ProtocolConformance::hasFixedLayout() const {
256-
// A conformance/witness table has fixed layout if type has a fixed layout in
257-
// all resilience domains, and the conformance is externally visible.
258-
if (auto nominal = getType()->getAnyNominal())
259-
if (nominal->hasFixedLayout() &&
260-
getProtocol()->getEffectiveAccess() >= Accessibility::Public &&
261-
nominal->getEffectiveAccess() >= Accessibility::Public)
262-
return true;
263-
264-
return false;
265-
}
266-
267255
GenericEnvironment *ProtocolConformance::getGenericEnvironment() const {
268256
switch (getKind()) {
269257
case ProtocolConformanceKind::Inherited:

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,6 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
869869
Args.hasArg(OPT_serialize_debugging_options);
870870
Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
871871
Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
872-
Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
873872
Opts.EnableSerializationNestedTypeLookupTable &=
874873
!Args.hasArg(OPT_disable_serialization_nested_type_lookup_table);
875874

@@ -1339,6 +1338,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
13391338
if (Args.hasArg(OPT_sil_merge_partial_modules))
13401339
Opts.MergePartialModules = true;
13411340

1341+
Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
1342+
Opts.SILSerializeWitnessTables |=
1343+
Args.hasArg(OPT_sil_serialize_witness_tables);
1344+
13421345
// Parse the optimization level.
13431346
if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
13441347
if (A->getOption().matches(OPT_Onone)) {

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ std::string CompilerInvocation::getPCHHash() const {
5555
void CompilerInstance::createSILModule(bool WholeModule) {
5656
assert(MainModule && "main module not created yet");
5757
TheSILModule = SILModule::createEmptyModule(
58-
getMainModule(), Invocation.getSILOptions(), WholeModule,
59-
Invocation.getFrontendOptions().SILSerializeAll);
58+
getMainModule(), Invocation.getSILOptions(), WholeModule);
6059
}
6160

6261
void CompilerInstance::setPrimarySourceFile(SourceFile *SF) {
@@ -250,7 +249,7 @@ ModuleDecl *CompilerInstance::getMainModule() {
250249

251250
if (Invocation.getFrontendOptions().EnableResilience)
252251
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
253-
else if (Invocation.getFrontendOptions().SILSerializeAll)
252+
else if (Invocation.getSILOptions().SILSerializeAll)
254253
MainModule->setResilienceStrategy(ResilienceStrategy::Fragile);
255254
}
256255
return MainModule;

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -691,13 +691,13 @@ static bool performCompile(CompilerInstance &Instance,
691691
}
692692
astGuaranteedToCorrespondToSIL = !fileIsSIB(PrimaryFile);
693693
SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(),
694-
None, opts.SILSerializeAll);
694+
None);
695695
} else {
696696
auto mod = Instance.getMainModule();
697697
astGuaranteedToCorrespondToSIL =
698698
llvm::none_of(mod->getFiles(), fileIsSIB);
699699
SM = performSILGeneration(mod, Invocation.getSILOptions(),
700-
opts.SILSerializeAll, true);
700+
true);
701701
}
702702
}
703703

@@ -835,7 +835,8 @@ static bool performCompile(CompilerInstance &Instance,
835835
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
836836
serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str();
837837
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
838-
serializationOpts.SerializeAllSIL = opts.SILSerializeAll;
838+
serializationOpts.SerializeAllSIL =
839+
Invocation.getSILOptions().SILSerializeAll;
839840
if (opts.SerializeBridgingHeader)
840841
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
841842
serializationOpts.ModuleLinkName = opts.ModuleLinkName;

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,9 +1352,8 @@ bool LinkEntity::isFragile(ForDefinition_t isDefinition) const {
13521352
auto isCompletelySerialized = conformanceModule->getResilienceStrategy() ==
13531353
ResilienceStrategy::Fragile;
13541354

1355-
// The conformance is fragile if it is in a -sil-serialize-all module, or
1356-
// has a fully publicly determined layout.
1357-
return isCompletelySerialized || conformance->hasFixedLayout();
1355+
// The conformance is fragile if it is in a -sil-serialize-all module.
1356+
return isCompletelySerialized;
13581357
}
13591358
return false;
13601359
}

lib/SIL/SILModule.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,10 @@ class SILModule::SerializationCallback : public SerializedSILLoader::Callback {
8383
};
8484

8585
SILModule::SILModule(ModuleDecl *SwiftModule, SILOptions &Options,
86-
const DeclContext *associatedDC, bool wholeModule,
87-
bool wholeModuleSerialized)
86+
const DeclContext *associatedDC, bool wholeModule)
8887
: TheSwiftModule(SwiftModule), AssociatedDeclContext(associatedDC),
8988
Stage(SILStage::Raw), Callback(new SILModule::SerializationCallback()),
90-
wholeModule(wholeModule), WholeModuleSerialized(wholeModuleSerialized),
91-
Options(Options), Types(*this) {}
89+
wholeModule(wholeModule), Options(Options), Types(*this) {}
9290

9391
SILModule::~SILModule() {
9492
// Decrement ref count for each SILGlobalVariable with static initializers.

lib/SILGen/SILGen.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ using namespace Lowering;
3838
// SILGenModule Class implementation
3939
//===----------------------------------------------------------------------===//
4040

41-
SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM, bool makeModuleFragile)
41+
SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM)
4242
: M(M), Types(M.Types), SwiftModule(SM), TopLevelSGF(nullptr),
43-
Profiler(nullptr), makeModuleFragile(makeModuleFragile) {
43+
Profiler(nullptr) {
4444
}
4545

4646
SILGenModule::~SILGenModule() {
@@ -451,7 +451,7 @@ SILFunction *SILGenModule::getEmittedFunction(SILDeclRef constant,
451451
if (isAvailableExternally(F->getLinkage())) {
452452
F->setLinkage(constant.getLinkage(ForDefinition));
453453
}
454-
if (makeModuleFragile) {
454+
if (isMakeModuleFragile()) {
455455
F->setSerialized(IsSerialized);
456456
}
457457
}
@@ -498,7 +498,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
498498

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

501-
if (makeModuleFragile) {
501+
if (isMakeModuleFragile()) {
502502
SILLinkage linkage = constant.getLinkage(forDefinition);
503503
if (linkage != SILLinkage::PublicExternal) {
504504
F->setSerialized(IsSerialized);
@@ -981,7 +981,7 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
981981
M.createFunction(SILLinkage::Private,
982982
funcName, initSILType, nullptr,
983983
SILLocation(binding), IsNotBare, IsNotTransparent,
984-
makeModuleFragile
984+
isMakeModuleFragile()
985985
? IsSerialized
986986
: IsNotSerialized);
987987
f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
@@ -1397,7 +1397,7 @@ void SILGenModule::emitSourceFile(SourceFile *sf, unsigned startElem) {
13971397

13981398
std::unique_ptr<SILModule>
13991399
SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
1400-
Optional<unsigned> startElem, bool makeModuleFragile,
1400+
Optional<unsigned> startElem,
14011401
bool isWholeModule) {
14021402
SharedTimer timer("SILGen");
14031403
const DeclContext *DC;
@@ -1413,8 +1413,8 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
14131413
}
14141414

14151415
std::unique_ptr<SILModule> M(
1416-
new SILModule(mod, options, DC, isWholeModule, makeModuleFragile));
1417-
SILGenModule SGM(*M, mod, makeModuleFragile);
1416+
new SILModule(mod, options, DC, isWholeModule));
1417+
SILGenModule SGM(*M, mod);
14181418

14191419
if (SF) {
14201420
if (auto *file = dyn_cast<SourceFile>(SF)) {
@@ -1472,16 +1472,14 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF,
14721472
std::unique_ptr<SILModule>
14731473
swift::performSILGeneration(ModuleDecl *mod,
14741474
SILOptions &options,
1475-
bool makeModuleFragile,
14761475
bool wholeModuleCompilation) {
1477-
return SILModule::constructSIL(mod, options, nullptr, None, makeModuleFragile,
1476+
return SILModule::constructSIL(mod, options, nullptr, None,
14781477
wholeModuleCompilation);
14791478
}
14801479

14811480
std::unique_ptr<SILModule>
14821481
swift::performSILGeneration(FileUnit &sf, SILOptions &options,
1483-
Optional<unsigned> startElem,
1484-
bool makeModuleFragile) {
1482+
Optional<unsigned> startElem) {
14851483
return SILModule::constructSIL(sf.getParentModule(), options, &sf, startElem,
1486-
makeModuleFragile, false);
1484+
false);
14871485
}

lib/SILGen/SILGen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
106106

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

111111
Optional<SILDeclRef> StringToNSStringFn;
112112
Optional<SILDeclRef> NSStringToStringFn;
@@ -136,7 +136,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
136136
Optional<ProtocolConformance *> NSErrorConformanceToError;
137137

138138
public:
139-
SILGenModule(SILModule &M, ModuleDecl *SM, bool makeModuleFragile);
139+
SILGenModule(SILModule &M, ModuleDecl *SM);
140140

141141
~SILGenModule();
142142

lib/SILGen/SILGenGlobalVariable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl,
4747
SILType silTy = M.Types.getLoweredTypeOfGlobal(gDecl);
4848

4949
auto *silGlobal = SILGlobalVariable::create(M, link,
50-
makeModuleFragile
50+
isMakeModuleFragile()
5151
? IsSerialized
5252
: IsNotSerialized,
5353
mangledName, silTy,
@@ -223,7 +223,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
223223
// TODO: include the module in the onceToken's name mangling.
224224
// Then we can make it fragile.
225225
auto onceToken = SILGlobalVariable::create(M, SILLinkage::Private,
226-
makeModuleFragile
226+
isMakeModuleFragile()
227227
? IsSerialized
228228
: IsNotSerialized,
229229
onceTokenBuffer, onceSILTy);

lib/SILGen/SILGenType.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,20 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
314314
Serialized = IsNotSerialized;
315315

316316
// Serialize the witness table if we're serializing everything with
317-
// -sil-serialize-all, or if the conformance itself thinks it should be.
318-
if (SGM.makeModuleFragile || Conformance->hasFixedLayout())
317+
// -sil-serialize-all.
318+
if (SGM.isMakeModuleFragile())
319+
Serialized = IsSerialized;
320+
321+
auto *nominal = Conformance->getType()->getAnyNominal();
322+
// Serialize the witness table if the conformance itself thinks it should be
323+
// and resilience is explicitly enabled for this compilaiton or if we serialize
324+
// all eligible witness tables.
325+
if ((SGM.M.getSwiftModule()->getResilienceStrategy() ==
326+
ResilienceStrategy::Resilient ||
327+
SGM.M.getOptions().SILSerializeWitnessTables) &&
328+
nominal->hasFixedLayout() &&
329+
proto->getEffectiveAccess() >= Accessibility::Public &&
330+
nominal->getEffectiveAccess() >= Accessibility::Public)
319331
Serialized = IsSerialized;
320332

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

0 commit comments

Comments
 (0)