@@ -199,10 +199,10 @@ static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
199199 return false ;
200200}
201201
202- static bool emitMakeDependenciesIfNeeded (DiagnosticEngine &diags,
202+ static void emitMakeDependenciesIfNeeded (DiagnosticEngine &diags,
203203 DependencyTracker *depTracker,
204204 const FrontendOptions &opts) {
205- return opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
205+ opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
206206 [&](const InputFile &f) -> bool {
207207 return emitMakeDependenciesIfNeeded (diags, depTracker, opts, f);
208208 });
@@ -480,11 +480,11 @@ static bool emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
480480 return true ;
481481}
482482
483- static bool
483+ static void
484484emitLoadedModuleTraceForAllPrimariesIfNeeded (ModuleDecl *mainModule,
485485 DependencyTracker *depTracker,
486486 const FrontendOptions &opts) {
487- return opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
487+ opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
488488 [&](const InputFile &input) -> bool {
489489 return emitLoadedModuleTraceIfNeeded (
490490 mainModule, depTracker, opts.PrebuiltModuleCachePath ,
@@ -682,8 +682,8 @@ static void countStatsOfSourceFile(UnifiedStatsReporter &Stats,
682682 }
683683}
684684
685- static void countStatsPostSema (UnifiedStatsReporter &Stats,
686- CompilerInstance& Instance) {
685+ static void countASTStats (UnifiedStatsReporter &Stats,
686+ CompilerInstance& Instance) {
687687 auto &C = Stats.getFrontendCounters ();
688688 auto &SM = Instance.getSourceMgr ();
689689 C.NumSourceBuffers = SM.getLLVMSourceMgr ().getNumBuffers ();
@@ -1154,15 +1154,22 @@ static void emitIndexData(const CompilerInstance &Instance) {
11541154
11551155// / Emits all "one-per-module" supplementary outputs that don't depend on
11561156// / anything past type-checking.
1157- // /
1158- // / These are extracted out so that they can be invoked early when using
1159- // / `-typecheck`, but skipped for any mode that runs SIL diagnostics if there's
1160- // / an error found there (to get those diagnostics back to the user faster).
11611157static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs (
11621158 CompilerInstance &Instance) {
11631159 const auto &Invocation = Instance.getInvocation ();
11641160 const FrontendOptions &opts = Invocation.getFrontendOptions ();
11651161
1162+ // FIXME: Whole-module outputs with a non-whole-module action ought to
1163+ // be disallowed, but the driver implements -index-file mode by generating a
1164+ // regular whole-module frontend command line and modifying it to index just
1165+ // one file (by making it a primary) instead of all of them. If that
1166+ // invocation also has flags to emit whole-module supplementary outputs, the
1167+ // compiler can crash trying to access information for non-type-checked
1168+ // declarations in the non-primary files. For now, prevent those crashes by
1169+ // guarding the emission of whole-module supplementary outputs.
1170+ if (!opts.InputsAndOutputs .isWholeModule ())
1171+ return false ;
1172+
11661173 // Record whether we failed to emit any of these outputs, but keep going; one
11671174 // failure does not mean skipping the rest.
11681175 bool hadAnyError = false ;
@@ -1223,6 +1230,16 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
12231230static void performEndOfPipelineActions (CompilerInstance &Instance) {
12241231 assert (Instance.hasASTContext ());
12251232 auto &ctx = Instance.getASTContext ();
1233+ const auto &Invocation = Instance.getInvocation ();
1234+ const auto &opts = Invocation.getFrontendOptions ();
1235+
1236+ // If we were asked to print Clang stats, do so.
1237+ if (opts.PrintClangStats && ctx.getClangModuleLoader ())
1238+ ctx.getClangModuleLoader ()->printStatistics ();
1239+
1240+ // Report AST stats if needed.
1241+ if (auto *stats = ctx.Stats )
1242+ countASTStats (*stats, Instance);
12261243
12271244 // Make sure we didn't load a module during a parse-only invocation, unless
12281245 // it's -emit-imported-modules, which can load modules.
@@ -1237,9 +1254,27 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) {
12371254 // Verify the AST for all the modules we've loaded.
12381255 ctx.verifyAllLoadedModules ();
12391256
1257+ // Verify generic signatures if we've been asked to.
1258+ verifyGenericSignaturesIfNeeded (Invocation, ctx);
1259+
1260+ // Emit any additional outputs that we only need for a successful compilation.
1261+ // We don't want to unnecessarily delay getting any errors back to the user.
1262+ if (!ctx.hadError ()) {
1263+ emitLoadedModuleTraceForAllPrimariesIfNeeded (
1264+ Instance.getMainModule (), Instance.getDependencyTracker (), opts);
1265+
1266+ emitAnyWholeModulePostTypeCheckSupplementaryOutputs (Instance);
1267+ }
1268+
12401269 // Emit dependencies and index data.
12411270 emitReferenceDependenciesForAllPrimaryInputsIfNeeded (Instance);
12421271 emitIndexData (Instance);
1272+ emitMakeDependenciesIfNeeded (Instance.getDiags (),
1273+ Instance.getDependencyTracker (), opts);
1274+
1275+ // Emit information about the parsed primaries.
1276+ emitSwiftRangesForAllPrimaryInputsIfNeeded (Instance);
1277+ emitCompiledSourceForAllPrimaryInputsIfNeeded (Instance);
12431278}
12441279
12451280// / Performs the compile requested by the user.
@@ -1280,13 +1315,23 @@ static bool performCompile(CompilerInstance &Instance,
12801315 return true ;
12811316 }
12821317
1318+ bool didFinishPipeline = false ;
12831319 SWIFT_DEFER {
1320+ assert (didFinishPipeline && " Returned without calling finishPipeline" );
1321+ };
1322+
1323+ auto finishPipeline = [&](bool hadError) -> bool {
12841324 // We might have freed the ASTContext already, but in that case we would
12851325 // have already performed these actions.
1286- if (Instance.hasASTContext ())
1326+ if (Instance.hasASTContext ()) {
12871327 performEndOfPipelineActions (Instance);
1328+ hadError |= Instance.getASTContext ().hadError ();
1329+ }
1330+ didFinishPipeline = true ;
1331+ return hadError;
12881332 };
12891333
1334+ auto &Context = Instance.getASTContext ();
12901335 if (FrontendOptions::shouldActionOnlyParse (Action)) {
12911336 // Parsing gets triggered lazily, but let's make sure we have the right
12921337 // input kind.
@@ -1298,39 +1343,27 @@ static bool performCompile(CompilerInstance &Instance,
12981343 (void )kind;
12991344 } else if (Action == FrontendOptions::ActionType::ResolveImports) {
13001345 Instance.performParseAndResolveImportsOnly ();
1346+ return finishPipeline (Context.hadError ());
13011347 } else {
13021348 Instance.performSema ();
13031349 }
13041350
1305- ASTContext &Context = Instance.getASTContext ();
13061351 if (Action == FrontendOptions::ActionType::Parse) {
13071352 // A -parse invocation only cares about the side effects of parsing, so
13081353 // force the parsing of all the source files.
13091354 for (auto *file : Instance.getMainModule ()->getFiles ()) {
13101355 if (auto *SF = dyn_cast<SourceFile>(file))
13111356 (void )SF->getTopLevelDecls ();
13121357 }
1313- return Context.hadError ();
1314- }
1315-
1316- if (Action == FrontendOptions::ActionType::ScanDependencies) {
1317- scanDependencies (Instance);
1358+ return finishPipeline (Context.hadError ());
13181359 }
13191360
1320- (void )emitMakeDependenciesIfNeeded (Instance.getDiags (),
1321- Instance.getDependencyTracker (), opts);
1322-
1323- if (Action == FrontendOptions::ActionType::ResolveImports ||
1324- Action == FrontendOptions::ActionType::ScanDependencies)
1325- return Context.hadError ();
1361+ if (Action == FrontendOptions::ActionType::ScanDependencies)
1362+ return finishPipeline (scanDependencies (Instance));
13261363
13271364 if (observer)
13281365 observer->performedSemanticAnalysis (Instance);
13291366
1330- if (auto *Stats = Context.Stats ) {
1331- countStatsPostSema (*Stats, Instance);
1332- }
1333-
13341367 {
13351368 FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode ;
13361369 if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse)
@@ -1339,8 +1372,6 @@ static bool performCompile(CompilerInstance &Instance,
13391372 debugFailWithCrash ();
13401373 }
13411374
1342- verifyGenericSignaturesIfNeeded (Invocation, Context);
1343-
13441375 (void )migrator::updateCodeAndEmitRemapIfNeeded (&Instance);
13451376
13461377 if (Action == FrontendOptions::ActionType::REPL) {
@@ -1349,43 +1380,20 @@ static bool performCompile(CompilerInstance &Instance,
13491380 }
13501381
13511382 if (auto r = dumpASTIfNeeded (Instance))
1352- return *r;
1353-
1354- // If we were asked to print Clang stats, do so.
1355- if (opts.PrintClangStats && Context.getClangModuleLoader ())
1356- Context.getClangModuleLoader ()->printStatistics ();
1357-
1358- emitSwiftRangesForAllPrimaryInputsIfNeeded (Instance);
1359- emitCompiledSourceForAllPrimaryInputsIfNeeded (Instance);
1383+ return finishPipeline (*r);
13601384
13611385 if (Context.hadError ())
1362- return true ;
1363-
1364- (void )emitLoadedModuleTraceForAllPrimariesIfNeeded (
1365- Instance.getMainModule (), Instance.getDependencyTracker (), opts);
1386+ return finishPipeline (/* hadError*/ true );
13661387
13671388 // We've just been told to perform a typecheck, so we can return now.
1368- if (Action == FrontendOptions::ActionType::Typecheck) {
1369- // FIXME: Whole-module outputs with a non-whole-module -typecheck ought to
1370- // be disallowed, but the driver implements -index-file mode by generating a
1371- // regular whole-module frontend command line and modifying it to index just
1372- // one file (by making it a primary) instead of all of them. If that
1373- // invocation also has flags to emit whole-module supplementary outputs, the
1374- // compiler can crash trying to access information for non-type-checked
1375- // declarations in the non-primary files. For now, prevent those crashes by
1376- // guarding the emission of whole-module supplementary outputs.
1377- if (opts.InputsAndOutputs .isWholeModule ()) {
1378- if (emitAnyWholeModulePostTypeCheckSupplementaryOutputs (Instance)) {
1379- return true ;
1380- }
1381- }
1382- return false ;
1383- }
1389+ if (Action == FrontendOptions::ActionType::Typecheck)
1390+ return finishPipeline (/* hadError*/ false );
13841391
13851392 assert (FrontendOptions::doesActionGenerateSIL (Action) &&
13861393 " All actions not requiring SILGen must have been handled!" );
13871394
1388- return performCompileStepsPostSema (Instance, ReturnValue, observer);
1395+ return finishPipeline (
1396+ performCompileStepsPostSema (Instance, ReturnValue, observer));
13891397}
13901398
13911399static bool serializeSIB (SILModule *SM, const PrimarySpecificPaths &PSPs,
@@ -1650,8 +1658,6 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
16501658 if (observer)
16511659 observer->performedSILProcessing (*SM);
16521660
1653- emitAnyWholeModulePostTypeCheckSupplementaryOutputs (Instance);
1654-
16551661 if (Action == FrontendOptions::ActionType::EmitSIB)
16561662 return serializeSIB (SM.get (), PSPs, Context, MSF);
16571663
0 commit comments