@@ -98,7 +98,8 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
98
98
// differ between identical modules discovered from different translation
99
99
// units.
100
100
CI.getFrontendOpts ().Inputs .clear ();
101
- CI.getFrontendOpts ().OutputFile .clear ();
101
+ // CAS: OutputFile cannot be empty when computing a cache key.
102
+ CI.getFrontendOpts ().OutputFile = " -" ;
102
103
// FIXME: a build system may want to provide a new path.
103
104
CI.getFrontendOpts ().IndexUnitOutputPath .clear ();
104
105
@@ -118,7 +119,9 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
118
119
CI.getDiagnosticOpts ().DiagnosticSerializationFile = " -" ;
119
120
if (!CI.getDependencyOutputOpts ().OutputFile .empty ())
120
121
CI.getDependencyOutputOpts ().OutputFile = " -" ;
121
- CI.getDependencyOutputOpts ().Targets .clear ();
122
+ // CAS: -MT must be preserved for cache key.
123
+ if (!CI.getDependencyOutputOpts ().Targets .empty ())
124
+ CI.getDependencyOutputOpts ().Targets = {" -" };
122
125
123
126
CI.getFrontendOpts ().ProgramAction = frontend::GenerateModule;
124
127
CI.getFrontendOpts ().ARCMTAction = FrontendOptions::ARCMT_None;
@@ -289,6 +292,22 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
289
292
HashBuilder;
290
293
SmallString<32 > Scratch;
291
294
295
+ auto FormatHash = [&](llvm::BLAKE3Result<16 > Hash) {
296
+ std::array<uint64_t , 2 > Words;
297
+ static_assert (sizeof (Hash) == sizeof (Words), " Hash must match Words" );
298
+ std::memcpy (Words.data (), Hash.data (), sizeof (Hash));
299
+ return toString (llvm::APInt (sizeof (Words) * 8 , Words), 36 ,
300
+ /* Signed=*/ false );
301
+ };
302
+
303
+ if (MD.ModuleCacheKey ) {
304
+ // Cache keys have better canonicalization, so use them as the context hash.
305
+ // This reduces the number of modules needed when compatible configurations
306
+ // are used (e.g. change in -fmessage-length).
307
+ HashBuilder.add (*MD.ModuleCacheKey );
308
+ return FormatHash (HashBuilder.final ());
309
+ }
310
+
292
311
// Hash the compiler version and serialization version to ensure the module
293
312
// will be readable.
294
313
HashBuilder.add (getClangFullRepositoryVersion ());
@@ -324,13 +343,30 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
324
343
}
325
344
326
345
HashBuilder.add (EagerLoadModules);
346
+ return FormatHash (HashBuilder.final ());
347
+ }
327
348
328
- llvm::BLAKE3Result<16 > Hash = HashBuilder.final ();
329
- std::array<uint64_t , 2 > Words;
330
- static_assert (sizeof (Hash) == sizeof (Words), " Hash must match Words" );
331
- std::memcpy (Words.data (), Hash.data (), sizeof (Hash));
332
- return toString (llvm::APInt (sizeof (Words) * 8 , Words), 36 , /* Signed=*/ false );
349
+ #ifndef NDEBUG
350
+ static void checkCompileCacheKeyMatch (cas::ObjectStore &CAS,
351
+ StringRef OldKeyStr, cas::CASID NewKey) {
352
+ if (NewKey.toString () == OldKeyStr)
353
+ return ;
354
+
355
+ // Mismatched keys, report error.
356
+ auto OldKey = CAS.parseID (OldKeyStr);
357
+ if (!OldKey)
358
+ llvm::report_fatal_error (OldKey.takeError ());
359
+ SmallString<256 > Err;
360
+ llvm::raw_svector_ostream OS (Err);
361
+ OS << " Compile cache key for module changed; previously:" ;
362
+ if (auto E = printCompileJobCacheKey (CAS, *OldKey, OS))
363
+ OS << std::move (E);
364
+ OS << " \n key is now:" ;
365
+ if (auto E = printCompileJobCacheKey (CAS, NewKey, OS))
366
+ OS << std::move (E);
367
+ llvm::report_fatal_error (OS.str ());
333
368
}
369
+ #endif
334
370
335
371
void ModuleDepCollector::associateWithContextHash (const CompilerInvocation &CI,
336
372
ModuleDeps &Deps) {
@@ -552,17 +588,27 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
552
588
if (auto E = MDC.Controller .finalizeModuleInvocation (CI, MD))
553
589
Diags.Report (diag::err_cas_depscan_failed) << std::move (E);
554
590
591
+ // Compute the cache key, if needed. Requires dependencies.
592
+ if (MDC.ScanInstance .getFrontendOpts ().CacheCompileJob ) {
593
+ auto &CAS = MDC.ScanInstance .getOrCreateObjectStore ();
594
+ if (auto Key = createCompileJobCacheKey (CAS, Diags, CI))
595
+ MD.ModuleCacheKey = Key->toString ();
596
+ }
597
+
555
598
MDC.associateWithContextHash (CI, MD);
556
599
557
600
// Finish the compiler invocation. Requires dependencies and the context hash.
558
601
MDC.addOutputPaths (CI, MD);
559
602
560
- // Compute the cache key, if needed. Requires dependencies and outputs.
561
- if (MDC.ScanInstance .getFrontendOpts ().CacheCompileJob ) {
603
+ #ifndef NDEBUG
604
+ // Verify the key has not changed with final arguments.
605
+ if (MD.ModuleCacheKey ) {
562
606
auto &CAS = MDC.ScanInstance .getOrCreateObjectStore ();
563
- if (auto Key = createCompileJobCacheKey (CAS, Diags, CI))
564
- MD.ModuleCacheKey = Key->toString ();
607
+ auto Key = createCompileJobCacheKey (CAS, Diags, CI);
608
+ assert (Key);
609
+ checkCompileCacheKeyMatch (CAS, *MD.ModuleCacheKey , *Key);
565
610
}
611
+ #endif
566
612
567
613
MD.BuildArguments = CI.getCC1CommandLine ();
568
614
0 commit comments