LLVM  4.0.0
Caching.cpp
Go to the documentation of this file.
1 //===-Caching.cpp - LLVM Link Time Optimizer Cache Handling ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Caching for ThinLTO.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/LTO/Caching.h"
15 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/Path.h"
20 
21 using namespace llvm;
22 using namespace llvm::lto;
23 
24 static void commitEntry(StringRef TempFilename, StringRef EntryPath) {
25  // Rename to final destination (hopefully race condition won't matter here)
26  auto EC = sys::fs::rename(TempFilename, EntryPath);
27  if (EC) {
28  // Renaming failed, probably not the same filesystem, copy and delete.
29  // FIXME: Avoid needing to do this by creating the temporary file in the
30  // cache directory.
31  {
32  auto ReloadedBufferOrErr = MemoryBuffer::getFile(TempFilename);
33  if (auto EC = ReloadedBufferOrErr.getError())
34  report_fatal_error(Twine("Failed to open temp file '") + TempFilename +
35  "': " + EC.message() + "\n");
36 
37  raw_fd_ostream OS(EntryPath, EC, sys::fs::F_None);
38  if (EC)
39  report_fatal_error(Twine("Failed to open ") + EntryPath +
40  " to save cached entry\n");
41  // I'm not sure what are the guarantee if two processes are doing this
42  // at the same time.
43  OS << (*ReloadedBufferOrErr)->getBuffer();
44  }
45  sys::fs::remove(TempFilename);
46  }
47 }
48 
49 NativeObjectCache lto::localCache(std::string CacheDirectoryPath,
50  AddFileFn AddFile) {
51  return [=](unsigned Task, StringRef Key) -> AddStreamFn {
52  // First, see if we have a cache hit.
53  SmallString<64> EntryPath;
54  sys::path::append(EntryPath, CacheDirectoryPath, Key);
55  if (sys::fs::exists(EntryPath)) {
56  AddFile(Task, EntryPath);
57  return AddStreamFn();
58  }
59 
60  // This native object stream is responsible for commiting the resulting
61  // file to the cache and calling AddFile to add it to the link.
62  struct CacheStream : NativeObjectStream {
63  AddFileFn AddFile;
64  std::string TempFilename;
65  std::string EntryPath;
66  unsigned Task;
67 
68  CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddFileFn AddFile,
69  std::string TempFilename, std::string EntryPath,
70  unsigned Task)
71  : NativeObjectStream(std::move(OS)), AddFile(AddFile),
72  TempFilename(TempFilename), EntryPath(EntryPath), Task(Task) {}
73 
74  ~CacheStream() {
75  // Make sure the file is closed before committing it.
76  OS.reset();
77  commitEntry(TempFilename, EntryPath);
78  AddFile(Task, EntryPath);
79  }
80  };
81 
82  return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
83  // Write to a temporary to avoid race condition
84  int TempFD;
85  SmallString<64> TempFilename;
86  std::error_code EC =
87  sys::fs::createTemporaryFile("Thin", "tmp.o", TempFD, TempFilename);
88  if (EC) {
89  errs() << "Error: " << EC.message() << "\n";
90  report_fatal_error("ThinLTO: Can't get a temporary file");
91  }
92 
93  // This CacheStream will move the temporary file into the cache when done.
94  return llvm::make_unique<CacheStream>(
95  llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true),
96  AddFile, TempFilename.str(), EntryPath.str(), Task);
97  };
98  };
99 }
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
std::function< std::unique_ptr< NativeObjectStream >unsigned Task)> AddStreamFn
This type defines the callback to add a native object that is generated on the fly.
Definition: LTO.h:253
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:448
static void commitEntry(StringRef TempFilename, StringRef EntryPath)
Definition: Caching.cpp:24
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::function< void(unsigned Task, StringRef Path)> AddFileFn
This type defines the callback to add a pre-existing native object file (e.g.
Definition: Caching.h:28
std::function< AddStreamFn(unsigned Task, StringRef Key)> NativeObjectCache
This is the type of a native object cache.
Definition: LTO.h:268
This class wraps an output stream for a native object.
Definition: LTO.h:241
std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:357
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
Definition: Path.cpp:794
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
bool exists(file_status status)
Does file exist?
Definition: Path.cpp:940
NativeObjectCache localCache(std::string CacheDirectoryPath, AddFileFn AddFile)
Create a local file system cache which uses the given cache directory and file callback.
Definition: Caching.cpp:49