@@ -106,6 +106,11 @@ static cl::opt<bool> DeterministicCheck(
106
106
cl::init((bool )sys::Process::GetEnv(
107
107
" LLVM_CACHE_CHECK_REPRODUCIBLE_CACHING_ISSUES" )),
108
108
cl::Hidden);
109
+ static cl::opt<bool > StrictCASErrors (
110
+ " thinlto-strict-cas-errors" ,
111
+ cl::desc (" Treat CAS errors during ThinLTO as fatal errors" ),
112
+ cl::init((bool )sys::Process::GetEnv(" LLVM_THINLTO_STRICT_CAS_ERRORS" )),
113
+ cl::Hidden);
109
114
110
115
class LoggingStream {
111
116
public:
@@ -474,6 +479,25 @@ class FileModuleCacheEntry : public ModuleCacheEntry {
474
479
SmallString<128 > EntryPath;
475
480
};
476
481
482
+ static void handleCASError (
483
+ Error E, llvm::function_ref<void (llvm::function_ref<void (raw_ostream &OS)>)>
484
+ Logger) {
485
+ if (!E)
486
+ return ;
487
+
488
+ // If strict CAS error, abort.
489
+ if (StrictCASErrors)
490
+ report_fatal_error (std::move (E));
491
+
492
+ // Otherwise, log the error message and return error_code.
493
+ if (Logger)
494
+ Logger ([&](raw_ostream &OS) {
495
+ OS << " LTO CAS Error: '" << toString (std::move (E)) << " '\n " ;
496
+ });
497
+ else
498
+ consumeError (std::move (E));
499
+ }
500
+
477
501
class CASModuleCacheEntry : public ModuleCacheEntry {
478
502
public:
479
503
// Create a cache entry. This compute a unique hash for the Module considering
@@ -501,8 +525,11 @@ class CASModuleCacheEntry : public ModuleCacheEntry {
501
525
// TODO: We can have an alternative hashing function that doesn't
502
526
// need to store the key into CAS to get the CacheKey.
503
527
auto CASKey = CAS.createProxy (std::nullopt, *Key);
504
- if (!CASKey)
505
- report_fatal_error (CASKey.takeError ());
528
+ if (!CASKey) {
529
+ handleCASError (CASKey.takeError (), this ->Logger );
530
+ // return as if the key doesn't exist, which will be treated as miss.
531
+ return ;
532
+ }
506
533
507
534
ID = CASKey->getID ();
508
535
}
@@ -530,8 +557,11 @@ class CASModuleCacheEntry : public ModuleCacheEntry {
530
557
}
531
558
});
532
559
533
- if (Error E = Cache.get (*ID, /* Globally=*/ true ).moveInto (MaybeKeyID))
534
- return errorToErrorCode (std::move (E));
560
+ if (Error E = Cache.get (*ID, /* Globally=*/ true ).moveInto (MaybeKeyID)) {
561
+ handleCASError (std::move (E), Logger);
562
+ // If handleCASError didn't abort, treat as miss.
563
+ return std::error_code ();
564
+ }
535
565
}
536
566
537
567
if (!MaybeKeyID)
@@ -547,8 +577,11 @@ class CASModuleCacheEntry : public ModuleCacheEntry {
547
577
});
548
578
549
579
auto MaybeObject = CAS.getProxy (*MaybeKeyID);
550
- if (!MaybeObject)
551
- return errorToErrorCode (MaybeObject.takeError ());
580
+ if (!MaybeObject) {
581
+ handleCASError (MaybeObject.takeError (), Logger);
582
+ // If handleCASError didn't abort, treat as miss.
583
+ return std::error_code ();
584
+ }
552
585
553
586
return MaybeObject->getMemoryBuffer (" " , /* NullTerminated=*/ true );
554
587
}
@@ -571,7 +604,7 @@ class CASModuleCacheEntry : public ModuleCacheEntry {
571
604
572
605
if (Error E = CAS.createProxy (std::nullopt, OutputBuffer.getBuffer ())
573
606
.moveInto (Proxy))
574
- report_fatal_error (std::move (E));
607
+ return handleCASError (std::move (E), Logger );
575
608
}
576
609
577
610
ScopedDurationTimer ScopedTime ([&](double Seconds) {
@@ -584,7 +617,7 @@ class CASModuleCacheEntry : public ModuleCacheEntry {
584
617
});
585
618
586
619
if (auto Err = Cache.put (*ID, Proxy->getID (), /* Globally=*/ true ))
587
- report_fatal_error (std::move (Err));
620
+ handleCASError (std::move (Err), Logger );
588
621
}
589
622
590
623
private:
@@ -639,8 +672,11 @@ class RemoteModuleCacheEntry : public ModuleCacheEntry {
639
672
}
640
673
});
641
674
642
- if (Error E = Service.KVDB ->getValueSync (ID).moveInto (GetResponse))
643
- return errorToErrorCode (std::move (E));
675
+ if (Error E = Service.KVDB ->getValueSync (ID).moveInto (GetResponse)) {
676
+ handleCASError (std::move (E), Logger);
677
+ // If handleCASError didn't abort, treat as miss.
678
+ return std::error_code ();
679
+ }
644
680
}
645
681
646
682
// Cache Miss.
@@ -666,8 +702,11 @@ class RemoteModuleCacheEntry : public ModuleCacheEntry {
666
702
667
703
// Request the output buffer.
668
704
auto LoadResponse = Service.CASDB ->loadSync (Result->getValue (), OutputPath);
669
- if (!LoadResponse)
670
- return errorToErrorCode (LoadResponse.takeError ());
705
+ if (!LoadResponse) {
706
+ handleCASError (LoadResponse.takeError (), Logger);
707
+ // If handleCASError didn't abort, treat as miss.
708
+ return std::error_code ();
709
+ }
671
710
672
711
// Object not found. Treat it as a miss.
673
712
if (LoadResponse->KeyNotFound )
@@ -699,7 +738,7 @@ class RemoteModuleCacheEntry : public ModuleCacheEntry {
699
738
700
739
if (Error E =
701
740
Service.CASDB ->saveFileSync (OutputPath).moveInto (SaveResponse))
702
- report_fatal_error (std::move (E));
741
+ return handleCASError (std::move (E), Logger );
703
742
}
704
743
705
744
// Only check determinism when the cache lookup succeeded before.
@@ -722,7 +761,7 @@ class RemoteModuleCacheEntry : public ModuleCacheEntry {
722
761
cas::remote::KeyValueDBClient::ValueTy CompResult;
723
762
CompResult[" Output" ] = *SaveResponse;
724
763
if (auto Err = Service.KVDB ->putValueSync (ID, CompResult))
725
- report_fatal_error (std::move (Err));
764
+ handleCASError (std::move (Err), Logger );
726
765
}
727
766
728
767
Error writeObject (const MemoryBuffer &OutputBuffer,
0 commit comments