summaryrefslogtreecommitdiffstats
path: root/llvm/lib/LTO/Caching.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2016-09-23 21:33:43 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2016-09-23 21:33:43 +0000
commit80186a57d66c4374aea9118045d8489dcdb6071b (patch)
tree757a092ded2644d8663928ae9e30c04f29bb8723 /llvm/lib/LTO/Caching.cpp
parent6951707943c771422c4e22ee8b7cd653642272ce (diff)
downloadbcm5719-llvm-80186a57d66c4374aea9118045d8489dcdb6071b.tar.gz
bcm5719-llvm-80186a57d66c4374aea9118045d8489dcdb6071b.zip
LTO: Simplify caching interface.
The NativeObjectOutput class has a design problem: it mixes up the caching policy with the interface for output streams, which makes the client-side code hard to follow and would for example make it harder to replace the cache implementation in an arbitrary client. This change separates the two aspects by moving the caching policy to a separate field in Config, replacing NativeObjectOutput with a NativeObjectStream class which only deals with streams and does not need to be overridden by most clients and introducing an AddFile callback for adding files (e.g. from the cache) to the link. Differential Revision: https://reviews.llvm.org/D24622 llvm-svn: 282299
Diffstat (limited to 'llvm/lib/LTO/Caching.cpp')
-rw-r--r--llvm/lib/LTO/Caching.cpp101
1 files changed, 51 insertions, 50 deletions
diff --git a/llvm/lib/LTO/Caching.cpp b/llvm/lib/LTO/Caching.cpp
index 728e5164dfa..065239cbb1b 100644
--- a/llvm/lib/LTO/Caching.cpp
+++ b/llvm/lib/LTO/Caching.cpp
@@ -12,13 +12,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/LTO/Caching.h"
-
-#ifdef HAVE_LLVM_REVISION
-#include "LLVMLTORevision.h"
-#endif
-
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -30,6 +26,8 @@ static void commitEntry(StringRef TempFilename, StringRef EntryPath) {
auto EC = sys::fs::rename(TempFilename, EntryPath);
if (EC) {
// Renaming failed, probably not the same filesystem, copy and delete.
+ // FIXME: Avoid needing to do this by creating the temporary file in the
+ // cache directory.
{
auto ReloadedBufferOrErr = MemoryBuffer::getFile(TempFilename);
if (auto EC = ReloadedBufferOrErr.getError())
@@ -48,51 +46,54 @@ static void commitEntry(StringRef TempFilename, StringRef EntryPath) {
}
}
-CacheObjectOutput::~CacheObjectOutput() {
- if (EntryPath.empty())
- // The entry was never used by the client (tryLoadFromCache() wasn't called)
- return;
- // TempFilename is only set if getStream() was called, i.e. on cache miss when
- // tryLoadFromCache() returned false. And EntryPath is valid if a Key was
- // submitted, otherwise it has been set to CacheDirectoryPath in
- // tryLoadFromCache.
- if (!TempFilename.empty()) {
- if (EntryPath == CacheDirectoryPath)
- // The Key supplied to tryLoadFromCache was empty, do not commit the temp.
- EntryPath = TempFilename;
- else
- // We commit the tempfile into the cache now, by moving it to EntryPath.
- commitEntry(TempFilename, EntryPath);
- }
- // Supply the cache path to the user.
- AddBuffer(EntryPath.str());
-}
+NativeObjectCache lto::localCache(std::string CacheDirectoryPath,
+ AddFileFn AddFile) {
+ return [=](unsigned Task, StringRef Key) -> AddStreamFn {
+ // First, see if we have a cache hit.
+ SmallString<64> EntryPath;
+ sys::path::append(EntryPath, CacheDirectoryPath, Key);
+ if (sys::fs::exists(EntryPath)) {
+ AddFile(Task, EntryPath);
+ return AddStreamFn();
+ }
-// Return an allocated stream for the output, or null in case of failure.
-std::unique_ptr<raw_pwrite_stream> CacheObjectOutput::getStream() {
- assert(!EntryPath.empty() && "API Violation: client didn't call "
- "tryLoadFromCache() before getStream()");
- // Write to a temporary to avoid race condition
- int TempFD;
- std::error_code EC =
- sys::fs::createTemporaryFile("Thin", "tmp.o", TempFD, TempFilename);
- if (EC) {
- errs() << "Error: " << EC.message() << "\n";
- report_fatal_error("ThinLTO: Can't get a temporary file");
- }
- return llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true);
-}
+ // This native object stream is responsible for commiting the resulting
+ // file to the cache and calling AddFile to add it to the link.
+ struct CacheStream : NativeObjectStream {
+ AddFileFn AddFile;
+ std::string TempFilename;
+ std::string EntryPath;
+ unsigned Task;
-// Try loading from a possible cache first, return true on cache hit.
-bool CacheObjectOutput::tryLoadFromCache(StringRef Key) {
- assert(!CacheDirectoryPath.empty() &&
- "CacheObjectOutput was initialized without a cache path");
- if (Key.empty()) {
- // Client didn't compute a valid key. EntryPath has been set to
- // CacheDirectoryPath.
- EntryPath = CacheDirectoryPath;
- return false;
- }
- sys::path::append(EntryPath, CacheDirectoryPath, Key);
- return sys::fs::exists(EntryPath);
+ CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddFileFn AddFile,
+ std::string TempFilename, std::string EntryPath,
+ unsigned Task)
+ : NativeObjectStream(std::move(OS)), AddFile(AddFile),
+ TempFilename(TempFilename), EntryPath(EntryPath), Task(Task) {}
+
+ ~CacheStream() {
+ // Make sure the file is closed before committing it.
+ OS.reset();
+ commitEntry(TempFilename, EntryPath);
+ AddFile(Task, EntryPath);
+ }
+ };
+
+ return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
+ // Write to a temporary to avoid race condition
+ int TempFD;
+ SmallString<64> TempFilename;
+ std::error_code EC =
+ sys::fs::createTemporaryFile("Thin", "tmp.o", TempFD, TempFilename);
+ if (EC) {
+ errs() << "Error: " << EC.message() << "\n";
+ report_fatal_error("ThinLTO: Can't get a temporary file");
+ }
+
+ // This CacheStream will move the temporary file into the cache when done.
+ return make_unique<CacheStream>(
+ llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true),
+ AddFile, TempFilename.str(), EntryPath.str(), Task);
+ };
+ };
}
OpenPOWER on IntegriCloud