@@ -199,10 +199,10 @@ static bool emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
199
199
return false ;
200
200
}
201
201
202
- static bool emitMakeDependenciesIfNeeded (DiagnosticEngine &diags,
202
+ static void emitMakeDependenciesIfNeeded (DiagnosticEngine &diags,
203
203
DependencyTracker *depTracker,
204
204
const FrontendOptions &opts) {
205
- return opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
205
+ opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
206
206
[&](const InputFile &f) -> bool {
207
207
return emitMakeDependenciesIfNeeded (diags, depTracker, opts, f);
208
208
});
@@ -480,11 +480,11 @@ static bool emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
480
480
return true ;
481
481
}
482
482
483
- static bool
483
+ static void
484
484
emitLoadedModuleTraceForAllPrimariesIfNeeded (ModuleDecl *mainModule,
485
485
DependencyTracker *depTracker,
486
486
const FrontendOptions &opts) {
487
- return opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
487
+ opts.InputsAndOutputs .forEachInputProducingSupplementaryOutput (
488
488
[&](const InputFile &input) -> bool {
489
489
return emitLoadedModuleTraceIfNeeded (
490
490
mainModule, depTracker, opts.PrebuiltModuleCachePath ,
@@ -682,8 +682,8 @@ static void countStatsOfSourceFile(UnifiedStatsReporter &Stats,
682
682
}
683
683
}
684
684
685
- static void countStatsPostSema (UnifiedStatsReporter &Stats,
686
- CompilerInstance& Instance) {
685
+ static void countASTStats (UnifiedStatsReporter &Stats,
686
+ CompilerInstance& Instance) {
687
687
auto &C = Stats.getFrontendCounters ();
688
688
auto &SM = Instance.getSourceMgr ();
689
689
C.NumSourceBuffers = SM.getLLVMSourceMgr ().getNumBuffers ();
@@ -1154,15 +1154,22 @@ static void emitIndexData(const CompilerInstance &Instance) {
1154
1154
1155
1155
// / Emits all "one-per-module" supplementary outputs that don't depend on
1156
1156
// / 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).
1161
1157
static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs (
1162
1158
CompilerInstance &Instance) {
1163
1159
const auto &Invocation = Instance.getInvocation ();
1164
1160
const FrontendOptions &opts = Invocation.getFrontendOptions ();
1165
1161
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
+
1166
1173
// Record whether we failed to emit any of these outputs, but keep going; one
1167
1174
// failure does not mean skipping the rest.
1168
1175
bool hadAnyError = false ;
@@ -1223,6 +1230,16 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
1223
1230
static void performEndOfPipelineActions (CompilerInstance &Instance) {
1224
1231
assert (Instance.hasASTContext ());
1225
1232
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);
1226
1243
1227
1244
// Make sure we didn't load a module during a parse-only invocation, unless
1228
1245
// it's -emit-imported-modules, which can load modules.
@@ -1237,9 +1254,27 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) {
1237
1254
// Verify the AST for all the modules we've loaded.
1238
1255
ctx.verifyAllLoadedModules ();
1239
1256
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
+
1240
1269
// Emit dependencies and index data.
1241
1270
emitReferenceDependenciesForAllPrimaryInputsIfNeeded (Instance);
1242
1271
emitIndexData (Instance);
1272
+ emitMakeDependenciesIfNeeded (Instance.getDiags (),
1273
+ Instance.getDependencyTracker (), opts);
1274
+
1275
+ // Emit information about the parsed primaries.
1276
+ emitSwiftRangesForAllPrimaryInputsIfNeeded (Instance);
1277
+ emitCompiledSourceForAllPrimaryInputsIfNeeded (Instance);
1243
1278
}
1244
1279
1245
1280
// / Performs the compile requested by the user.
@@ -1280,13 +1315,23 @@ static bool performCompile(CompilerInstance &Instance,
1280
1315
return true ;
1281
1316
}
1282
1317
1318
+ bool didFinishPipeline = false ;
1283
1319
SWIFT_DEFER {
1320
+ assert (didFinishPipeline && " Returned without calling finishPipeline" );
1321
+ };
1322
+
1323
+ auto finishPipeline = [&](bool hadError) -> bool {
1284
1324
// We might have freed the ASTContext already, but in that case we would
1285
1325
// have already performed these actions.
1286
- if (Instance.hasASTContext ())
1326
+ if (Instance.hasASTContext ()) {
1287
1327
performEndOfPipelineActions (Instance);
1328
+ hadError |= Instance.getASTContext ().hadError ();
1329
+ }
1330
+ didFinishPipeline = true ;
1331
+ return hadError;
1288
1332
};
1289
1333
1334
+ auto &Context = Instance.getASTContext ();
1290
1335
if (FrontendOptions::shouldActionOnlyParse (Action)) {
1291
1336
// Parsing gets triggered lazily, but let's make sure we have the right
1292
1337
// input kind.
@@ -1298,39 +1343,27 @@ static bool performCompile(CompilerInstance &Instance,
1298
1343
(void )kind;
1299
1344
} else if (Action == FrontendOptions::ActionType::ResolveImports) {
1300
1345
Instance.performParseAndResolveImportsOnly ();
1346
+ return finishPipeline (Context.hadError ());
1301
1347
} else {
1302
1348
Instance.performSema ();
1303
1349
}
1304
1350
1305
- ASTContext &Context = Instance.getASTContext ();
1306
1351
if (Action == FrontendOptions::ActionType::Parse) {
1307
1352
// A -parse invocation only cares about the side effects of parsing, so
1308
1353
// force the parsing of all the source files.
1309
1354
for (auto *file : Instance.getMainModule ()->getFiles ()) {
1310
1355
if (auto *SF = dyn_cast<SourceFile>(file))
1311
1356
(void )SF->getTopLevelDecls ();
1312
1357
}
1313
- return Context.hadError ();
1314
- }
1315
-
1316
- if (Action == FrontendOptions::ActionType::ScanDependencies) {
1317
- scanDependencies (Instance);
1358
+ return finishPipeline (Context.hadError ());
1318
1359
}
1319
1360
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));
1326
1363
1327
1364
if (observer)
1328
1365
observer->performedSemanticAnalysis (Instance);
1329
1366
1330
- if (auto *Stats = Context.Stats ) {
1331
- countStatsPostSema (*Stats, Instance);
1332
- }
1333
-
1334
1367
{
1335
1368
FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode ;
1336
1369
if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse)
@@ -1339,8 +1372,6 @@ static bool performCompile(CompilerInstance &Instance,
1339
1372
debugFailWithCrash ();
1340
1373
}
1341
1374
1342
- verifyGenericSignaturesIfNeeded (Invocation, Context);
1343
-
1344
1375
(void )migrator::updateCodeAndEmitRemapIfNeeded (&Instance);
1345
1376
1346
1377
if (Action == FrontendOptions::ActionType::REPL) {
@@ -1349,43 +1380,20 @@ static bool performCompile(CompilerInstance &Instance,
1349
1380
}
1350
1381
1351
1382
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);
1360
1384
1361
1385
if (Context.hadError ())
1362
- return true ;
1363
-
1364
- (void )emitLoadedModuleTraceForAllPrimariesIfNeeded (
1365
- Instance.getMainModule (), Instance.getDependencyTracker (), opts);
1386
+ return finishPipeline (/* hadError*/ true );
1366
1387
1367
1388
// 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 );
1384
1391
1385
1392
assert (FrontendOptions::doesActionGenerateSIL (Action) &&
1386
1393
" All actions not requiring SILGen must have been handled!" );
1387
1394
1388
- return performCompileStepsPostSema (Instance, ReturnValue, observer);
1395
+ return finishPipeline (
1396
+ performCompileStepsPostSema (Instance, ReturnValue, observer));
1389
1397
}
1390
1398
1391
1399
static bool serializeSIB (SILModule *SM, const PrimarySpecificPaths &PSPs,
@@ -1650,8 +1658,6 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
1650
1658
if (observer)
1651
1659
observer->performedSILProcessing (*SM);
1652
1660
1653
- emitAnyWholeModulePostTypeCheckSupplementaryOutputs (Instance);
1654
-
1655
1661
if (Action == FrontendOptions::ActionType::EmitSIB)
1656
1662
return serializeSIB (SM.get (), PSPs, Context, MSF);
1657
1663
0 commit comments