From d7a427af6e828422e79f127967e2cad52115554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Wed, 28 Jul 2021 14:46:08 -0700 Subject: [PATCH 1/5] [Frontend] Emit incr compilation info from emit-module jobs Enable emitting the module-level incremental fine-grained compilation information from the emit-module job for incremental compilation to work with emit-module-separately. --- lib/FrontendTool/FrontendTool.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index b01c4c85a5cff..76821a621e9c8 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1549,9 +1549,19 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance, SerializationOptions serializationOpts = Invocation.computeSerializationOptions(outs, Instance.getMainModule()); + // Infer if this is an emit-module job part of an incremental build, + // vs a partial emit-module job (with primary files) or other kinds. + // We may want to rely on a flag instead to differentiate them. + const bool isEmitModuleSeparately = + Action == FrontendOptions::ActionType::EmitModuleOnly && + MSF.is() && + Instance.getInvocation() + .getTypeCheckerOptions() + .SkipFunctionBodies == FunctionBodySkipping::NonInlinableWithoutTypes; const bool canEmitIncrementalInfoIntoModule = !serializationOpts.DisableCrossModuleIncrementalInfo && - (Action == FrontendOptions::ActionType::MergeModules); + (Action == FrontendOptions::ActionType::MergeModules || + isEmitModuleSeparately); if (canEmitIncrementalInfoIntoModule) { const auto alsoEmitDotFile = Instance.getInvocation() From fc5fa85456aa73f5226afb5b5d81defbb24011ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Fri, 6 Aug 2021 09:56:32 -0700 Subject: [PATCH 2/5] [AST] Accept SynthesizedFileUnit in populateMemberCache The differentiation and actor logics insert SynthesizedFileUnit in SourceFile modules. Accepting these file units in populateMemberCache allow to cache all the top-level decls of source file modules. --- lib/AST/Module.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index e40f20e6c1e3d..11c81ff6d2f2b 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -276,8 +276,11 @@ void SourceLookupCache::populateMemberCache(const ModuleDecl &Mod) { "populate-module-class-member-cache"); for (const FileUnit *file : Mod.getFiles()) { - auto &SF = *cast(file); - addToMemberCache(SF.getTopLevelDecls()); + assert(isa(file) || + isa(file)); + SmallVector decls; + file->getTopLevelDecls(decls); + addToMemberCache(decls); } MemberCachePopulated = true; From 1f1aa3e3985d11c27a98e99f2e10e8339d9d889e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Wed, 18 Aug 2021 13:57:11 -0700 Subject: [PATCH 3/5] [Frontend] Generate an interface has for emit-module-separately jobs --- lib/Frontend/Frontend.cpp | 9 +++++---- test/InterfaceHash/added_function.swift | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 1d11600db1aa8..7bd1604417561 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -1144,10 +1144,10 @@ CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const { opts |= SourceFile::ParsingFlags::DisableDelayedBodies; } + auto typeOpts = getASTContext().TypeCheckerOpts; if (forPrimary || isWholeModuleCompilation()) { // Disable delayed body parsing for primaries and in WMO, unless // forcefully skipping function bodies - auto typeOpts = getASTContext().TypeCheckerOpts; if (typeOpts.SkipFunctionBodies == FunctionBodySkipping::None) opts |= SourceFile::ParsingFlags::DisableDelayedBodies; } else { @@ -1156,9 +1156,10 @@ CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const { opts |= SourceFile::ParsingFlags::SuppressWarnings; } - // Enable interface hash computation for primaries, but not in WMO, as it's - // only currently needed for incremental mode. - if (forPrimary) { + // Enable interface hash computation for primaries or emit-module-separately, + // but not in WMO, as it's only currently needed for incremental mode. + if (forPrimary || + typeOpts.SkipFunctionBodies == FunctionBodySkipping::NonInlinableWithoutTypes) { opts |= SourceFile::ParsingFlags::EnableInterfaceHash; } return opts; diff --git a/test/InterfaceHash/added_function.swift b/test/InterfaceHash/added_function.swift index d50c48547fcc3..4f137877f048d 100644 --- a/test/InterfaceHash/added_function.swift +++ b/test/InterfaceHash/added_function.swift @@ -4,6 +4,11 @@ // RUN: %target-swift-frontend -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash // RUN: not cmp %t/a.hash %t/b.hash +/// We should generate an interface hash for emit-module-separately jobs even +/// with no primaries. +// RUN: %target-swift-frontend -dump-interface-hash %t/b.swift -experimental-skip-non-inlinable-function-bodies-without-types 2> %t/b-emit-module.hash +// RUN: cmp %t/b.hash %t/b-emit-module.hash + // BEGIN a.swift func f() {} From f2cfe83f2e2fec17abc99bac85b38d46838be8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Wed, 8 Sep 2021 10:15:09 -0700 Subject: [PATCH 4/5] [Driver] Align definition of the emit-module-separately flag with the driver's --- include/swift/Option/Options.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 32aee49a34d12..0cac00783d1a2 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -581,8 +581,8 @@ def experimental_cxx_stdlib : def experimental_emit_module_separately: Flag<["-"], "experimental-emit-module-separately">, - Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>, - HelpText<"Schedule a swift module emission job instead of a merge-modules job (new Driver only)">; + Flags<[NoInteractiveOption, HelpHidden]>, + HelpText<"Emit module files as a distinct job (new Driver only)">; // Diagnostic control options def suppress_warnings : Flag<["-"], "suppress-warnings">, From 40dc40659dbc938f53df6cfc634f8e77dee704ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Wed, 8 Sep 2021 10:17:06 -0700 Subject: [PATCH 5/5] [Driver] Force the use of merge-module in merge-module specific test As support, accept but ignore the -no-emit-module-separately flag in the C++ driver. --- include/swift/Option/Options.td | 5 +++++ test/Driver/Dependencies/one-way-merge-module-fine.swift | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 0cac00783d1a2..629824e1ecb65 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -584,6 +584,11 @@ def experimental_emit_module_separately: Flags<[NoInteractiveOption, HelpHidden]>, HelpText<"Emit module files as a distinct job (new Driver only)">; +def no_emit_module_separately: + Flag<["-"], "no-emit-module-separately">, + Flags<[NoInteractiveOption, HelpHidden]>, + HelpText<"Force using merge-module as the incremental build mode (new Driver only)">; + // Diagnostic control options def suppress_warnings : Flag<["-"], "suppress-warnings">, Flags<[FrontendOption]>, diff --git a/test/Driver/Dependencies/one-way-merge-module-fine.swift b/test/Driver/Dependencies/one-way-merge-module-fine.swift index 50386583937f0..0a1831f367aed 100644 --- a/test/Driver/Dependencies/one-way-merge-module-fine.swift +++ b/test/Driver/Dependencies/one-way-merge-module-fine.swift @@ -4,7 +4,7 @@ // RUN: cp -r %S/Inputs/one-way-fine/* %t // RUN: touch -t 201401240005 %t/* -// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s +// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s // CHECK-FIRST-NOT: warning // CHECK-FIRST: Handled main.swift @@ -14,7 +14,7 @@ // swift-driver checks existence of all outputs // RUN: touch -t 201401240006 %t/{main,other,master}.swift{module,doc,sourceinfo} -// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s +// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s // CHECK-SECOND-NOT: warning // CHECK-SECOND-NOT: Handled