Skip to content

[Frontend] Set up output file .swiftmodule.summary #33324

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
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
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ ERROR(error_mode_cannot_emit_module_source_info,none,
"this mode does not support emitting module source info files", ())
ERROR(error_mode_cannot_emit_interface,none,
"this mode does not support emitting module interface files", ())
ERROR(error_mode_cannot_emit_module_summary,none,
"this mode does not support emitting module summary files", ())
ERROR(cannot_emit_ir_skipping_function_bodies,none,
"-experimental-skip-non-inlinable-function-bodies does not support "
"emitting IR", ())
Expand Down
1 change: 1 addition & 0 deletions include/swift/Basic/FileTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
TYPE("swiftinterface", SwiftModuleInterfaceFile, "swiftinterface", "")
TYPE("private-swiftinterface", PrivateSwiftModuleInterfaceFile, "private.swiftinterface", "")
TYPE("swiftmodulesummary", SwiftModuleSummaryFile, "swiftmodulesummary", "")
TYPE("swiftsourceinfo", SwiftSourceInfoFile, "swiftsourceinfo", "")
TYPE("assembly", Assembly, "s", "")
TYPE("raw-sil", RawSIL, "sil", "")
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/PrimarySpecificPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class PrimarySpecificPaths {
return !SupplementaryOutputs.ModuleOutputPath.empty() ||
!SupplementaryOutputs.ModuleDocOutputPath.empty();
}
bool haveModuleSummaryOutputPath() const {
return !SupplementaryOutputs.ModuleSummaryOutputPath.empty();
}
};
} // namespace swift

Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/SupplementaryOutputPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ struct SupplementaryOutputPaths {
/// name per symbol, we should eventually remove this.
std::string LdAddCFilePath;

/// The path to which we should emit module summary file.
std::string ModuleSummaryOutputPath;

SupplementaryOutputPaths() = default;
SupplementaryOutputPaths(const SupplementaryOutputPaths &) = default;

Expand Down
5 changes: 5 additions & 0 deletions include/swift/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ class Driver {
file_types::ID fileType,
CommandOutput *output) const;

void chooseModuleSummaryPath(Compilation &C, const TypeToPathMap *OutputMap,
StringRef workingDirectory,
llvm::SmallString<128> &Buf,
CommandOutput *Output) const;

void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,
CommandOutput *Output) const;

Expand Down
1 change: 1 addition & 0 deletions include/swift/Frontend/FrontendInputsAndOutputs.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class FrontendInputsAndOutputs {
bool hasModuleSourceInfoOutputPath() const;
bool hasModuleInterfaceOutputPath() const;
bool hasPrivateModuleInterfaceOutputPath() const;
bool hasModuleSummaryOutputPath() const;
bool hasTBDPath() const;

bool hasDependencyTrackerPath() const;
Expand Down
1 change: 1 addition & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ class FrontendOptions {
static bool canActionEmitLoadedModuleTrace(ActionType);
static bool canActionEmitModule(ActionType);
static bool canActionEmitModuleDoc(ActionType);
static bool canActionEmitModuleSummary(ActionType);
static bool canActionEmitInterface(ActionType);

public:
Expand Down
11 changes: 11 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,17 @@ def emit_module_path_EQ : Joined<["-"], "emit-module-path=">,
ArgumentIsPath, SupplementaryOutput]>,
Alias<emit_module_path>;

def emit_module_summary :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would put these new entries either above emit_module_interface or below emit_private_module_interface_path to avoid splitting the module interface options from each other.

Flag<["-"], "emit-module-summary">,
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild,
SupplementaryOutput]>,
HelpText<"Output module summary file">;
def emit_module_summary_path :
Separate<["-"], "emit-module-summary-path">,
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
ArgumentIsPath, SupplementaryOutput]>,
MetaVarName<"<path>">, HelpText<"Output module summary file to <path>">;

def emit_module_interface :
Flag<["-"], "emit-module-interface">,
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild,
Expand Down
3 changes: 3 additions & 0 deletions lib/Basic/FileTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ bool file_types::isTextual(ID Id) {
case file_types::TY_SwiftModuleDocFile:
case file_types::TY_SwiftSourceInfoFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_LLVM_BC:
case file_types::TY_SerializedDiagnostics:
case file_types::TY_ClangModuleFile:
Expand Down Expand Up @@ -138,6 +139,7 @@ bool file_types::isAfterLLVM(ID Id) {
case file_types::TY_SwiftModuleDocFile:
case file_types::TY_SwiftSourceInfoFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_SwiftOverlayFile:
case file_types::TY_SerializedDiagnostics:
case file_types::TY_ClangModuleFile:
Expand Down Expand Up @@ -189,6 +191,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
case file_types::TY_SwiftSourceInfoFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftOverlayFile:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_SerializedDiagnostics:
case file_types::TY_ClangModuleFile:
case file_types::TY_SwiftDeps:
Expand Down
21 changes: 21 additions & 0 deletions lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2004,6 +2004,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftOverlayFile:
case file_types::TY_JSONDependencies:
Expand Down Expand Up @@ -2855,6 +2856,10 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
Output.get());
}

if (isa<CompileJobAction>(JA)) {
chooseModuleSummaryPath(C, OutputMap, workingDirectory, Buf, Output.get());
}

if (isa<MergeModuleJobAction>(JA) ||
(isa<CompileJobAction>(JA) &&
OI.CompilerMode == OutputInfo::Mode::SingleCompile)) {
Expand Down Expand Up @@ -3208,6 +3213,22 @@ void Driver::chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
output->setAdditionalOutputForType(fileType, outputPath);
}

void Driver::chooseModuleSummaryPath(Compilation &C,
const TypeToPathMap *OutputMap,
StringRef workingDirectory,
llvm::SmallString<128> &Buf,
CommandOutput *Output) const {
StringRef pathFromArgs;
if (const Arg *A =
C.getArgs().getLastArg(options::OPT_emit_module_summary_path)) {
pathFromArgs = A->getValue();
}

addAuxiliaryOutput(C, *Output, file_types::TY_SwiftModuleSummaryFile,
OutputMap, workingDirectory, pathFromArgs,
/*requireArg=*/options::OPT_emit_module_summary);
}

void Driver::chooseSerializedDiagnosticsPath(Compilation &C,
const JobAction *JA,
const TypeToPathMap *OutputMap,
Expand Down
5 changes: 5 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_SwiftSourceInfoFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftOverlayFile:
Expand Down Expand Up @@ -765,6 +766,9 @@ void ToolChain::JobContext::addFrontendSupplementaryOutputArguments(
"-emit-loaded-module-trace-path");
addOutputsOfType(arguments, Output, Args, file_types::TY_TBD,
"-emit-tbd-path");
addOutputsOfType(arguments, Output, Args,
file_types::TY_SwiftModuleSummaryFile,
"-emit-module-summary-path");
}

ToolChain::InvocationInfo
Expand Down Expand Up @@ -877,6 +881,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
case file_types::TY_BitstreamOptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_PrivateSwiftModuleInterfaceFile:
case file_types::TY_SwiftModuleSummaryFile:
case file_types::TY_SwiftSourceInfoFile:
case file_types::TY_SwiftCrossImportDir:
case file_types::TY_SwiftOverlayFile:
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_interface);
return true;
}
if (!FrontendOptions::canActionEmitModuleSummary(Opts.RequestedAction) &&
Opts.InputsAndOutputs.hasModuleSummaryOutputPath()) {
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_summary);
return true;
}
return false;
}

Expand Down
11 changes: 10 additions & 1 deletion lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,13 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
options::OPT_emit_module_source_info_path);
auto ldAddCFileOutput = getSupplementaryFilenamesFromArguments(
options::OPT_emit_ldadd_cfile_path);
auto moduleSummaryOutput = getSupplementaryFilenamesFromArguments(
options::OPT_emit_module_summary_path);
if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
!dependenciesFile || !referenceDependenciesFile ||
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD ||
!moduleInterfaceOutput || !privateModuleInterfaceOutput ||
!moduleSourceInfoOutput || !ldAddCFileOutput) {
!moduleSourceInfoOutput || !ldAddCFileOutput || !moduleSummaryOutput) {
return None;
}
std::vector<SupplementaryOutputPaths> result;
Expand All @@ -334,6 +336,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[i];
sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i];
sop.LdAddCFilePath = (*ldAddCFileOutput)[i];
sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i];
result.push_back(sop);
}
return result;
Expand Down Expand Up @@ -422,6 +425,10 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
OPT_emit_module_source_info, pathsFromArguments.ModuleSourceInfoOutputPath,
file_types::TY_SwiftSourceInfoFile, "",
defaultSupplementaryOutputPathExcludingExtension);
auto moduleSummaryOutputPath = determineSupplementaryOutputFilename(
OPT_emit_module_summary, pathsFromArguments.ModuleSummaryOutputPath,
file_types::TY_SwiftModuleSummaryFile, "",
defaultSupplementaryOutputPathExcludingExtension);

// There is no non-path form of -emit-interface-path
auto ModuleInterfaceOutputPath =
Expand Down Expand Up @@ -456,6 +463,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
sop.PrivateModuleInterfaceOutputPath = PrivateModuleInterfaceOutputPath;
sop.ModuleSourceInfoOutputPath = moduleSourceInfoOutputPath;
sop.LdAddCFilePath = pathsFromArguments.LdAddCFilePath;
sop.ModuleSummaryOutputPath = moduleSummaryOutputPath;
return sop;
}

Expand Down Expand Up @@ -537,6 +545,7 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
{file_types::TY_TBD, paths.TBDPath},
{file_types::TY_SwiftModuleInterfaceFile,
paths.ModuleInterfaceOutputPath},
{file_types::TY_SwiftModuleSummaryFile, paths.ModuleSummaryOutputPath},
{file_types::TY_PrivateSwiftModuleInterfaceFile,
paths.PrivateModuleInterfaceOutputPath}};
for (const std::pair<file_types::ID, std::string &> &typeAndString :
Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/FrontendInputsAndOutputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,12 @@ bool FrontendInputsAndOutputs::hasPrivateModuleInterfaceOutputPath() const {
return outs.PrivateModuleInterfaceOutputPath;
});
}
bool FrontendInputsAndOutputs::hasModuleSummaryOutputPath() const {
return hasSupplementaryOutputPath(
[](const SupplementaryOutputPaths &outs) -> const std::string & {
return outs.ModuleSummaryOutputPath;
});
}
bool FrontendInputsAndOutputs::hasTBDPath() const {
return hasSupplementaryOutputPath(
[](const SupplementaryOutputPaths &outs) -> const std::string & {
Expand Down
41 changes: 41 additions & 0 deletions lib/Frontend/FrontendOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,47 @@ bool FrontendOptions::canActionEmitCompiledSource(ActionType action) {
return canActionEmitReferenceDependencies(action);
}

bool FrontendOptions::canActionEmitModuleSummary(ActionType action) {
switch (action) {
case ActionType::NoneAction:
case ActionType::Parse:
case ActionType::ResolveImports:
case ActionType::DumpParse:
case ActionType::DumpInterfaceHash:
case ActionType::DumpAST:
case ActionType::EmitSyntax:
case ActionType::PrintAST:
case ActionType::EmitImportedModules:
case ActionType::EmitPCH:
case ActionType::DumpScopeMaps:
case ActionType::DumpTypeRefinementContexts:
case ActionType::DumpTypeInfo:
case ActionType::EmitSILGen:
case ActionType::EmitSIBGen:
case ActionType::CompileModuleFromInterface:
case ActionType::TypecheckModuleFromInterface:
case ActionType::Immediate:
case ActionType::REPL:
case ActionType::EmitPCM:
case ActionType::DumpPCM:
case ActionType::ScanDependencies:
case ActionType::ScanClangDependencies:
case ActionType::Typecheck:
case ActionType::MergeModules:
case ActionType::EmitModuleOnly:
case ActionType::PrintVersion:
return false;
case ActionType::EmitSIL:
case ActionType::EmitSIB:
case ActionType::EmitIR:
case ActionType::EmitBC:
case ActionType::EmitAssembly:
case ActionType::EmitObject:
return true;
}
llvm_unreachable("unhandled action");
}

bool FrontendOptions::canActionEmitObjCHeader(ActionType action) {
switch (action) {
case ActionType::NoneAction:
Expand Down
17 changes: 17 additions & 0 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,17 @@ static bool serializeSIB(SILModule *SM, const PrimarySpecificPaths &PSPs,
return Context.hadError();
}

static bool serializeModuleSummary(SILModule *SM,
const PrimarySpecificPaths &PSPs,
const ASTContext &Context) {
auto summaryOutputPath = PSPs.SupplementaryOutputs.ModuleSummaryOutputPath;
return withOutputFile(Context.Diags, summaryOutputPath,
[&](llvm::raw_ostream &out) {
out << "Some stuff";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just quickly checking: if the tools that are meant to consume these files read Some stuff, will they break in an obvious way? (I don't know what you eventually intend for these files to look like.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, swiftmodulesummary will be serialized into LLVM bitcode stream, so if deserializer reads this text, it will fail due to signature checking.

return false;
});
}

static GeneratedModule
generateIR(const IRGenOptions &IRGenOpts, const TBDGenOptions &TBDOpts,
std::unique_ptr<SILModule> SM,
Expand Down Expand Up @@ -2123,6 +2134,12 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
if (observer)
observer->performedSILProcessing(*SM);

if (PSPs.haveModuleSummaryOutputPath()) {
if (serializeModuleSummary(SM.get(), PSPs, Context)) {
return true;
}
}

if (Action == FrontendOptions::ActionType::EmitSIB)
return serializeSIB(SM.get(), PSPs, Context, MSF);

Expand Down
6 changes: 6 additions & 0 deletions test/Driver/emit-module-summary.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: echo 'print("Hello, World!")' >%t/main.swift
// RUN: cd %t

// RUN: %target-swiftc_driver -emit-sib -emit-module-summary -emit-module-summary-path %t/main.swiftmodulesummary %t/main.swift
// RUN: test -f %t/main.swiftmodulesummary
10 changes: 10 additions & 0 deletions test/Frontend/emit-module-summary.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %empty-directory(%t)
// RUN: echo 'print("Hello, World!")' >%t/main.swift
// RUN: cd %t

// RUN: %target-swift-frontend -emit-sib -emit-module-summary-path %t/main.swiftmodulesummary %t/main.swift
// RUN: test -f %t/main.swiftmodulesummary

// RUN: echo '"%/t/main.swift": { swiftmodulesummary: "%/t/foo.swiftmodulesummary" }' > %/t/filemap.yaml
// RUN: %target-swift-frontend -emit-sib -supplementary-output-file-map %/t/filemap.yaml %/t/main.swift
// RUN: test -f %t/foo.swiftmodulesummary