Skip to content

Commit 882d72b

Browse files
committed
Extend SILModule with an API to serialize its content
The `serialize` method can be called multiple times, but it will perform the actual serialization only the first time. By means of this API we get the flexibility to serialize the SILModule not only after all the optimizations, but e.g. at any time during optimizations.
1 parent a7ee05d commit 882d72b

File tree

4 files changed

+84
-27
lines changed

4 files changed

+84
-27
lines changed

include/swift/SIL/SILModule.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class SILModule {
100100
using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
101101
using CoverageMapListType = llvm::ilist<SILCoverageMap>;
102102
using LinkingMode = SILOptions::LinkingMode;
103+
using ActionCallback = std::function<void()>;
103104

104105
private:
105106
friend KeyPathPattern;
@@ -213,6 +214,13 @@ class SILModule {
213214
/// The options passed into this SILModule.
214215
SILOptions &Options;
215216

217+
/// Set if the SILModule was serialized already. It is used
218+
/// to ensure that the module is serialized only once.
219+
bool serialized;
220+
221+
/// Action to be executed for serializing the SILModule.
222+
ActionCallback SerializeSILAction;
223+
216224
/// A list of clients that need to be notified when an instruction
217225
/// invalidation message is sent.
218226
llvm::SetVector<DeleteNotificationHandler*> NotificationHandlers;
@@ -251,6 +259,17 @@ class SILModule {
251259
/// registered handlers. The order of handlers is deterministic but arbitrary.
252260
void notifyDeleteHandlers(SILNode *node);
253261

262+
/// Set a serialization action.
263+
void setSerializeSILAction(ActionCallback SerializeSILAction);
264+
ActionCallback getSerializeSILAction() const;
265+
266+
/// Set a flag indicating that this module is serialized already.
267+
void setSerialized() { serialized = true; }
268+
bool isSerialized() const { return serialized; }
269+
270+
/// Serialize a SIL module using the configured SerializeSILAction.
271+
void serialize();
272+
254273
/// \brief This converts Swift types to SILTypes.
255274
mutable Lowering::TypeConverter Types;
256275

lib/FrontendTool/FrontendTool.cpp

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,46 @@ static bool performCompile(CompilerInstance &Instance,
854854
SM->verify();
855855
}
856856

857+
// This is the action to be used to serialize SILModule.
858+
// It may be invoked multiple times, but it will perform
859+
// serialization only once. The serialization may either happen
860+
// after high-level optimizations or after all optimizations are
861+
// done, depending on the compiler setting.
862+
863+
auto SerializeSILModuleAction = [&]() {
864+
if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) {
865+
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile)
866+
: Instance.getMainModule();
867+
if (!opts.ModuleOutputPath.empty()) {
868+
SerializationOptions serializationOpts;
869+
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
870+
serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str();
871+
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
872+
if (opts.SerializeBridgingHeader)
873+
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
874+
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
875+
serializationOpts.ExtraClangOptions =
876+
Invocation.getClangImporterOptions().ExtraArgs;
877+
serializationOpts.EnableNestedTypeLookupTable =
878+
opts.EnableSerializationNestedTypeLookupTable;
879+
if (!IRGenOpts.ForceLoadSymbolName.empty())
880+
serializationOpts.AutolinkForceLoad = true;
881+
882+
// Options contain information about the developer's computer,
883+
// so only serialize them if the module isn't going to be shipped to
884+
// the public.
885+
serializationOpts.SerializeOptionsForDebugging =
886+
!moduleIsPublic || opts.AlwaysSerializeDebuggingOptions;
887+
888+
serialize(DC, serializationOpts, SM.get());
889+
}
890+
}
891+
};
892+
893+
// Set the serialization action, so that the SIL module
894+
// can be serialized at any moment, e.g. during the optimization pipeline.
895+
SM->setSerializeSILAction(SerializeSILModuleAction);
896+
857897
// Perform SIL optimization passes if optimizations haven't been disabled.
858898
// These may change across compiler versions.
859899
{
@@ -921,32 +961,9 @@ static bool performCompile(CompilerInstance &Instance,
921961
}
922962

923963
if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) {
924-
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
925-
Instance.getMainModule();
926-
if (!opts.ModuleOutputPath.empty()) {
927-
SerializationOptions serializationOpts;
928-
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
929-
serializationOpts.DocOutputPath = opts.ModuleDocOutputPath.c_str();
930-
serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str();
931-
if (opts.SerializeBridgingHeader)
932-
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
933-
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
934-
serializationOpts.ExtraClangOptions =
935-
Invocation.getClangImporterOptions().ExtraArgs;
936-
serializationOpts.EnableNestedTypeLookupTable =
937-
opts.EnableSerializationNestedTypeLookupTable;
938-
if (!IRGenOpts.ForceLoadSymbolName.empty())
939-
serializationOpts.AutolinkForceLoad = true;
940-
941-
// Options contain information about the developer's computer,
942-
// so only serialize them if the module isn't going to be shipped to
943-
// the public.
944-
serializationOpts.SerializeOptionsForDebugging =
945-
!moduleIsPublic || opts.AlwaysSerializeDebuggingOptions;
946-
947-
serialize(DC, serializationOpts, SM.get());
948-
}
949-
964+
// Serialize the SILModule if it was not serialized yet.
965+
if (!SM.get()->isSerialized())
966+
SM.get()->serialize();
950967
if (Action == FrontendOptions::MergeModules ||
951968
Action == FrontendOptions::EmitModuleOnly) {
952969
if (shouldIndex) {

lib/SIL/SILModule.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ SILModule::SILModule(ModuleDecl *SwiftModule, SILOptions &Options,
8787
const DeclContext *associatedDC, bool wholeModule)
8888
: TheSwiftModule(SwiftModule), AssociatedDeclContext(associatedDC),
8989
Stage(SILStage::Raw), Callback(new SILModule::SerializationCallback()),
90-
wholeModule(wholeModule), Options(Options), Types(*this) {}
90+
wholeModule(wholeModule), Options(Options), serialized(false),
91+
SerializeSILAction(), Types(*this) {}
9192

9293
SILModule::~SILModule() {
9394
// Decrement ref count for each SILGlobalVariable with static initializers.
@@ -762,3 +763,20 @@ bool SILModule::isOptimizedOnoneSupportModule() const {
762763
return getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
763764
isOnoneSupportModule();
764765
}
766+
767+
void SILModule::setSerializeSILAction(SILModule::ActionCallback Action) {
768+
assert(!SerializeSILAction && "Serialization action can be set only once");
769+
SerializeSILAction = Action;
770+
}
771+
772+
SILModule::ActionCallback SILModule::getSerializeSILAction() const {
773+
return SerializeSILAction;
774+
}
775+
776+
void SILModule::serialize() {
777+
assert(SerializeSILAction && "Serialization action should be set");
778+
assert(!isSerialized() && "The module was serialized already");
779+
SerializeSILAction();
780+
setSerialized();
781+
}
782+

tools/sil-opt/SILOpt.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ int main(int argc, char **argv) {
383383
if (VerifyMode)
384384
enableDiagnosticVerifier(CI.getSourceMgr());
385385

386+
if (CI.getSILModule())
387+
CI.getSILModule()->setSerializeSILAction([]{});
388+
386389
if (OptimizationGroup == OptGroup::Diagnostics) {
387390
runSILDiagnosticPasses(*CI.getSILModule());
388391
} else if (OptimizationGroup == OptGroup::Performance) {

0 commit comments

Comments
 (0)