From 54435aca4f50455b7648e2a049f19d6cfbc36c1e Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 18 Aug 2023 15:49:53 -0700 Subject: [PATCH 1/2] Frontend: Introduce -experimental-lazy-typecheck action. This action is currently just an alias of the `-resolve-imports` action. However, it's named to more clearly reflect the purpose which is to do the minimal typechecking needed in order to emit the requested outputs. This mode is intended to improve performance when emitting `.swiftinterface` and `.tbd` files. --- include/swift/Frontend/FrontendOptions.h | 1 + include/swift/Option/Options.td | 3 +++ lib/Driver/Driver.cpp | 1 + .../ArgsToFrontendOptionsConverter.cpp | 2 ++ lib/Frontend/FrontendOptions.cpp | 19 +++++++++++++++++++ lib/FrontendTool/FrontendTool.cpp | 3 +++ 6 files changed, 29 insertions(+) diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 99255c978aa6c..0e4db93ddcfb8 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -155,6 +155,7 @@ class FrontendOptions { NoneAction, ///< No specific action Parse, ///< Parse only ResolveImports, ///< Parse and resolve imports only + LazyTypecheck, ///< Parse and then do minimal type-checking for outputs Typecheck, ///< Parse and type-check only DumpParse, ///< Parse only and dump AST DumpInterfaceHash, ///< Parse and dump the interface token hash. diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 137058650ca1f..a6faf8336f371 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1160,6 +1160,9 @@ def resolve_imports : Flag<["-"], "resolve-imports">, def typecheck : Flag<["-"], "typecheck">, HelpText<"Parse and type-check input file(s)">, ModeOpt, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; +def experimental_lazy_typecheck : Flag<["-"], "experimental-lazy-typecheck">, + HelpText<"Parse input file(s), then type-check lazily as needed to produce requested outputs">, ModeOpt, + Flags<[FrontendOption, NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>; def dump_parse : Flag<["-"], "dump-parse">, HelpText<"Parse input file(s) and dump AST(s)">, ModeOpt, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index a2b5b5d35a7a8..c3dc3aa283897 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1607,6 +1607,7 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, case options::OPT_parse: case options::OPT_resolve_imports: + case options::OPT_experimental_lazy_typecheck: case options::OPT_typecheck: case options::OPT_dump_parse: case options::OPT_print_ast: diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index ac0275ebbf73d..b7e2d64e721e0 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -552,6 +552,8 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) { return FrontendOptions::ActionType::Parse; if (Opt.matches(OPT_resolve_imports)) return FrontendOptions::ActionType::ResolveImports; + if (Opt.matches(OPT_experimental_lazy_typecheck)) + return FrontendOptions::ActionType::LazyTypecheck; if (Opt.matches(OPT_typecheck)) return FrontendOptions::ActionType::Typecheck; if (Opt.matches(OPT_dump_parse)) diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index ad6fc9630ed88..a893d2762c2cd 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -33,6 +33,7 @@ bool FrontendOptions::needsProperModuleName(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpParse: case ActionType::DumpAST: @@ -104,6 +105,7 @@ bool FrontendOptions::doesActionRequireSwiftStandardLibrary(ActionType action) { case ActionType::PrintFeature: return false; case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpAST: case ActionType::PrintAST: @@ -149,6 +151,7 @@ bool FrontendOptions::doesActionRequireInputs(ActionType action) { case ActionType::CompileModuleFromInterface: case ActionType::TypecheckModuleFromInterface: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpAST: case ActionType::PrintAST: @@ -191,6 +194,7 @@ bool FrontendOptions::doesActionPerformEndOfPipelineActions(ActionType action) { case ActionType::CompileModuleFromInterface: case ActionType::TypecheckModuleFromInterface: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpAST: case ActionType::PrintAST: @@ -230,6 +234,7 @@ bool FrontendOptions::supportCompilationCaching(ActionType action) { case ActionType::EmitImportedModules: case ActionType::ScanDependencies: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpAST: case ActionType::PrintAST: @@ -290,6 +295,7 @@ FrontendOptions::formatForPrincipalOutputFileForAction(ActionType action) { case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::TypecheckModuleFromInterface: case ActionType::DumpParse: @@ -377,6 +383,7 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) { case ActionType::PrintFeature: return false; case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::MergeModules: case ActionType::EmitModuleOnly: @@ -403,6 +410,7 @@ bool FrontendOptions::canActionEmitReferenceDependencies(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -445,6 +453,7 @@ bool FrontendOptions::canActionEmitModuleSummary(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -506,6 +515,7 @@ bool FrontendOptions::canActionEmitClangHeader(ActionType action) { case ActionType::PrintVersion: case ActionType::PrintFeature: return false; + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::MergeModules: case ActionType::EmitModuleOnly: @@ -547,6 +557,7 @@ bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) { case ActionType::PrintFeature: return false; case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::MergeModules: case ActionType::EmitModuleOnly: @@ -576,6 +587,7 @@ bool FrontendOptions::canActionEmitModuleSemanticInfo(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -619,6 +631,7 @@ bool FrontendOptions::canActionEmitConstValues(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -660,6 +673,7 @@ bool FrontendOptions::canActionEmitModule(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: @@ -727,6 +741,7 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) { case ActionType::PrintFeature: return false; case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::MergeModules: case ActionType::EmitModuleOnly: @@ -747,6 +762,7 @@ bool FrontendOptions::doesActionProduceOutput(ActionType action) { switch (action) { case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpParse: case ActionType::DumpAST: @@ -805,6 +821,7 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) { case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: @@ -834,6 +851,7 @@ bool FrontendOptions::doesActionGenerateSIL(ActionType action) { case ActionType::NoneAction: case ActionType::Parse: case ActionType::ResolveImports: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: @@ -885,6 +903,7 @@ bool FrontendOptions::doesActionGenerateIR(ActionType action) { case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: case ActionType::TypecheckModuleFromInterface: + case ActionType::LazyTypecheck: case ActionType::Typecheck: case ActionType::ResolveImports: case ActionType::MergeModules: diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 1e358e91b6288..b846a16457a90 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1359,6 +1359,9 @@ static bool performAction(CompilerInstance &Instance, return performParseOnly(*Instance.getMainModule()); case FrontendOptions::ActionType::ResolveImports: return Instance.performParseAndResolveImportsOnly(); + case FrontendOptions::ActionType::LazyTypecheck: + // For now, this action is just an alias of ResolveImports. + return Instance.performParseAndResolveImportsOnly(); case FrontendOptions::ActionType::Typecheck: return withSemanticAnalysis(Instance, observer, [](CompilerInstance &Instance) { From c05b3e4d66b3aa79320a504f17be2360a48b3a58 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 18 Aug 2023 16:13:43 -0700 Subject: [PATCH 2/2] Tests: Adopt -experimental-lazy-typecheck in tests. Also, restructure the `CHECK:` lines for the `-emit-tbd` test. The number of columns in the `.tbd` file appears to be variable, so we can't assume a layout for the symbols in the YAML. --- test/Driver/emit-interface.swift | 6 ++++++ ...lve-imports.swift => lazy-typecheck.swift} | 3 ++- ...lve_imports.swift => lazy_typecheck.swift} | 21 ++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) rename test/ModuleInterface/{resolve-imports.swift => lazy-typecheck.swift} (78%) rename test/TBD/{resolve_imports.swift => lazy_typecheck.swift} (50%) diff --git a/test/Driver/emit-interface.swift b/test/Driver/emit-interface.swift index 2b71d6cc523d7..f49714a98015d 100644 --- a/test/Driver/emit-interface.swift +++ b/test/Driver/emit-interface.swift @@ -26,3 +26,9 @@ // CHECK-FILELIST: swift{{(-frontend|c)?(\.exe)?"?}} -frontend // CHECK-FILELIST-SAME: -supplementary-output-file-map // CHECK-FILELIST-NOT: emit-interface.swift{{ }} + +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -experimental-lazy-typecheck %s -emit-module-interface -o %t/foo 2>&1 | %FileCheck -check-prefix=CHECK-LAZY-TYPECHECK %s + +// CHECK-LAZY-TYPECHECK: swift{{(-frontend|c)?(\.exe)?"?}} -frontend +// CHECK-LAZY-TYPECHECK-SAME: -experimental-lazy-typecheck +// CHECK-LAZY-TYPECHECK-SAME: emit-interface.swift diff --git a/test/ModuleInterface/resolve-imports.swift b/test/ModuleInterface/lazy-typecheck.swift similarity index 78% rename from test/ModuleInterface/resolve-imports.swift rename to test/ModuleInterface/lazy-typecheck.swift index d263e6144da97..0192b79862f45 100644 --- a/test/ModuleInterface/resolve-imports.swift +++ b/test/ModuleInterface/lazy-typecheck.swift @@ -1,6 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -resolve-imports %s -emit-module-interface-path %t/main.swiftinterface -enable-library-evolution +// RUN: %target-swift-frontend -experimental-lazy-typecheck %s -emit-module-interface-path %t/main.swiftinterface -enable-library-evolution // RUN: %FileCheck %s < %t/main.swiftinterface // CHECK: import Swift @@ -22,4 +23,4 @@ public class C {} // CHECK: } // Globals -public var year = 2023 \ No newline at end of file +public var year = 2023 diff --git a/test/TBD/resolve_imports.swift b/test/TBD/lazy_typecheck.swift similarity index 50% rename from test/TBD/resolve_imports.swift rename to test/TBD/lazy_typecheck.swift index 5c095b825cc81..b5c1b021e43e2 100644 --- a/test/TBD/resolve_imports.swift +++ b/test/TBD/lazy_typecheck.swift @@ -1,6 +1,8 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -resolve-imports -emit-tbd -emit-tbd-path %t/resolve_imports.tbd %s -disable-availability-checking +// RUN: %target-swift-frontend -experimental-lazy-typecheck -emit-tbd -emit-tbd-path %t/lazy_typecheck.tbd %s -disable-availability-checking // RUN: %FileCheck %s < %t/resolve_imports.tbd +// RUN: %FileCheck %s < %t/lazy_typecheck.tbd // REQUIRES: OS=macosx @@ -27,8 +29,17 @@ extension PrivateProto { public struct S: PrivateProto {} -// CHECK: symbols: [ '_$s15resolve_imports1CCMa', '_$s15resolve_imports1CCMm', -// CHECK-NEXT: '_$s15resolve_imports1CCMn', '_$s15resolve_imports1CCN', '_$s15resolve_imports1CCfD', -// CHECK-NEXT: '_$s15resolve_imports1CCfd', '_$s15resolve_imports1SVMa', -// CHECK-NEXT: '_$s15resolve_imports1SVMn', '_$s15resolve_imports1SVN', '_$s15resolve_imports1SVSQAAMc', -// CHECK-NEXT: '_$s15resolve_imports1SVSQAASQ2eeoiySbx_xtFZTW', _main ] +// CHECK: symbols: [ +// CHECK: '_$s14lazy_typecheck1CCMa', +// CHECK: '_$s14lazy_typecheck1CCMm', +// CHECK: '_$s14lazy_typecheck1CCMn', +// CHECK: '_$s14lazy_typecheck1CCN', +// CHECK: '_$s14lazy_typecheck1CCfD', +// CHECK: '_$s14lazy_typecheck1CCfd', +// CHECK: '_$s14lazy_typecheck1SVMa', +// CHECK: '_$s14lazy_typecheck1SVMn', +// CHECK: '_$s14lazy_typecheck1SVN', +// CHECK: '_$s14lazy_typecheck1SVSQAAMc', +// CHECK: '_$s14lazy_typecheck1SVSQAASQ2eeoiySbx_xtFZTW', +// CHECK: _main +// CHECK: ]