LLVM  6.0.0svn
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"
16 #include "llvm/Support/Errc.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/Process.h"
21 
22 using namespace llvm;
23 using namespace llvm::lto;
24 
26  AddBufferFn AddBuffer) {
27  if (std::error_code EC = sys::fs::create_directories(CacheDirectoryPath))
28  return errorCodeToError(EC);
29 
30  return [=](unsigned Task, StringRef Key) -> AddStreamFn {
31  // This choice of file name allows the cache to be pruned (see pruneCache()
32  // in include/llvm/Support/CachePruning.h).
33  SmallString<64> EntryPath;
34  sys::path::append(EntryPath, CacheDirectoryPath, "llvmcache-" + Key);
35  // First, see if we have a cache hit.
37  MemoryBuffer::getFile(EntryPath);
38  if (MBOrErr) {
39  AddBuffer(Task, std::move(*MBOrErr), EntryPath);
40  return AddStreamFn();
41  }
42 
44  report_fatal_error(Twine("Failed to open cache file ") + EntryPath +
45  ": " + MBOrErr.getError().message() + "\n");
46 
47  // This native object stream is responsible for commiting the resulting
48  // file to the cache and calling AddBuffer to add it to the link.
49  struct CacheStream : NativeObjectStream {
50  AddBufferFn AddBuffer;
51  sys::fs::TempFile TempFile;
52  std::string EntryPath;
53  unsigned Task;
54 
55  CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddBufferFn AddBuffer,
56  sys::fs::TempFile TempFile, std::string EntryPath,
57  unsigned Task)
58  : NativeObjectStream(std::move(OS)), AddBuffer(std::move(AddBuffer)),
59  TempFile(std::move(TempFile)), EntryPath(std::move(EntryPath)),
60  Task(Task) {}
61 
62  ~CacheStream() {
63  // Make sure the stream is closed before committing it.
64  OS.reset();
65 
66  // Open the file first to avoid racing with a cache pruner.
68  MemoryBuffer::getOpenFile(TempFile.FD, TempFile.TmpName,
69  /*FileSize*/ -1,
70  /*RequiresNullTerminator*/ false);
71  if (!MBOrErr)
72  report_fatal_error(Twine("Failed to open new cache file ") +
73  TempFile.TmpName + ": " +
74  MBOrErr.getError().message() + "\n");
75 
76  // On POSIX systems, this will atomically replace the destination if
77  // it already exists. We try to emulate this on Windows, but this may
78  // fail with a permission denied error (for example, if the destination
79  // is currently opened by another process that does not give us the
80  // sharing permissions we need). Since the existing file should be
81  // semantically equivalent to the one we are trying to write, we give
82  // AddBuffer a copy of the bytes we wrote in that case. We do this
83  // instead of just using the existing file, because the pruner might
84  // delete the file before we get a chance to use it.
85  Error E = TempFile.keep(EntryPath);
86  E = handleErrors(std::move(E), [&](const ECError &E) -> Error {
87  std::error_code EC = E.convertToErrorCode();
88  if (EC != errc::permission_denied)
89  return errorCodeToError(EC);
90 
91  auto MBCopy = MemoryBuffer::getMemBufferCopy((*MBOrErr)->getBuffer(),
92  EntryPath);
93  MBOrErr = std::move(MBCopy);
94 
95  // FIXME: should we consume the discard error?
96  consumeError(TempFile.discard());
97 
98  return Error::success();
99  });
100 
101  if (E)
102  report_fatal_error(Twine("Failed to rename temporary file ") +
103  TempFile.TmpName + " to " + EntryPath + ": " +
104  toString(std::move(E)) + "\n");
105 
106  AddBuffer(Task, std::move(*MBOrErr), EntryPath);
107  }
108  };
109 
110  return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
111  // Write to a temporary to avoid race condition
112  SmallString<64> TempFilenameModel;
113  sys::path::append(TempFilenameModel, CacheDirectoryPath, "Thin-%%%%%%.tmp.o");
115  TempFilenameModel, sys::fs::owner_read | sys::fs::owner_write);
116  if (!Temp) {
117  errs() << "Error: " << toString(Temp.takeError()) << "\n";
118  report_fatal_error("ThinLTO: Can't get a temporary file");
119  }
120 
121  // This CacheStream will move the temporary file into the cache when done.
122  return llvm::make_unique<CacheStream>(
123  llvm::make_unique<raw_fd_ostream>(Temp->FD, /* ShouldClose */ false),
124  AddBuffer, std::move(*Temp), EntryPath.str(), Task);
125  };
126  };
127 }
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:945
Represents either an error or a value T.
Definition: ErrorOr.h:69
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.
Definition: Error.cpp:115
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Error takeError()
Take ownership of the stored error.
Definition: Error.h:537
static Expected< TempFile > create(const Twine &Model, unsigned Mode=all_read|all_write)
This creates a temporary file with createUniqueFile and schedules it for deletion with sys::RemoveFil...
Definition: Path.cpp:824
Error keep(const Twine &Name)
Definition: Path.cpp:789
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
Definition: Error.h:1039
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:175
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:465
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:947
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Represents a temporary file.
Definition: FileSystem.h:705
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
Key
PAL metadata keys.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:78
This class wraps an output stream for a native object.
Definition: LTO.h:163
Expected< NativeObjectCache > localCache(StringRef CacheDirectoryPath, AddBufferFn AddBuffer)
Create a local file system cache which uses the given cache directory and file callback.
Definition: Caching.cpp:25
std::error_code getError() const
Definition: ErrorOr.h:172
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:962
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it...
Provides a library for accessing information about this process and other processes on the operating ...
std::function< void(unsigned Task, std::unique_ptr< MemoryBuffer > MB, StringRef Path)> AddBufferFn
This type defines the callback to add a pre-existing native object file (e.g.
Definition: Caching.h:34
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:866
This class wraps a std::error_code in a Error.
Definition: Error.h:1034
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false)
Given an already-open file descriptor, read the file and return a MemoryBuffer.