blob: b7542049dbf66863577e1d81a272e65ab86577a1 [file] [log] [blame]
Mehdi Aminiadc0e262016-08-23 21:30:12 +00001//===-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"
Mehdi Aminiadc0e262016-08-23 21:30:12 +000015#include "llvm/ADT/StringExtras.h"
16#include "llvm/Support/FileSystem.h"
Peter Collingbourne80186a52016-09-23 21:33:43 +000017#include "llvm/Support/MemoryBuffer.h"
Mehdi Aminiadc0e262016-08-23 21:30:12 +000018#include "llvm/Support/Path.h"
19#include "llvm/Support/raw_ostream.h"
20
21using namespace llvm;
22using namespace llvm::lto;
23
Peter Collingbourneab76a192017-03-02 02:02:38 +000024Expected<NativeObjectCache> lto::localCache(StringRef CacheDirectoryPath,
25 AddFileFn AddFile) {
26 if (std::error_code EC = sys::fs::create_directories(CacheDirectoryPath))
27 return errorCodeToError(EC);
28
Peter Collingbourne80186a52016-09-23 21:33:43 +000029 return [=](unsigned Task, StringRef Key) -> AddStreamFn {
30 // First, see if we have a cache hit.
31 SmallString<64> EntryPath;
32 sys::path::append(EntryPath, CacheDirectoryPath, Key);
33 if (sys::fs::exists(EntryPath)) {
34 AddFile(Task, EntryPath);
35 return AddStreamFn();
36 }
Mehdi Aminiadc0e262016-08-23 21:30:12 +000037
Peter Collingbourne80186a52016-09-23 21:33:43 +000038 // This native object stream is responsible for commiting the resulting
39 // file to the cache and calling AddFile to add it to the link.
40 struct CacheStream : NativeObjectStream {
41 AddFileFn AddFile;
42 std::string TempFilename;
43 std::string EntryPath;
44 unsigned Task;
Mehdi Aminiadc0e262016-08-23 21:30:12 +000045
Peter Collingbourne80186a52016-09-23 21:33:43 +000046 CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddFileFn AddFile,
47 std::string TempFilename, std::string EntryPath,
48 unsigned Task)
Benjamin Kramer061f4a52017-01-13 14:39:03 +000049 : NativeObjectStream(std::move(OS)), AddFile(std::move(AddFile)),
50 TempFilename(std::move(TempFilename)),
51 EntryPath(std::move(EntryPath)), Task(Task) {}
Peter Collingbourne80186a52016-09-23 21:33:43 +000052
53 ~CacheStream() {
54 // Make sure the file is closed before committing it.
55 OS.reset();
Peter Collingbournecb46a6b2017-03-16 18:20:06 +000056 // This is atomic on POSIX systems.
57 if (auto EC = sys::fs::rename(TempFilename, EntryPath))
58 report_fatal_error(Twine("Failed to rename temporary file ") +
59 TempFilename + ": " + EC.message() + "\n");
Peter Collingbourne80186a52016-09-23 21:33:43 +000060 AddFile(Task, EntryPath);
61 }
62 };
63
64 return [=](size_t Task) -> std::unique_ptr<NativeObjectStream> {
65 // Write to a temporary to avoid race condition
66 int TempFD;
Peter Collingbournecb46a6b2017-03-16 18:20:06 +000067 SmallString<64> TempFilenameModel, TempFilename;
68 sys::path::append(TempFilenameModel, CacheDirectoryPath, "Thin-%%%%%%.tmp.o");
Peter Collingbourne80186a52016-09-23 21:33:43 +000069 std::error_code EC =
Peter Collingbournecb46a6b2017-03-16 18:20:06 +000070 sys::fs::createUniqueFile(TempFilenameModel, TempFD, TempFilename,
71 sys::fs::owner_read | sys::fs::owner_write);
Peter Collingbourne80186a52016-09-23 21:33:43 +000072 if (EC) {
73 errs() << "Error: " << EC.message() << "\n";
74 report_fatal_error("ThinLTO: Can't get a temporary file");
75 }
76
77 // This CacheStream will move the temporary file into the cache when done.
Peter Collingbournea638fe02016-09-23 23:23:23 +000078 return llvm::make_unique<CacheStream>(
Peter Collingbourne80186a52016-09-23 21:33:43 +000079 llvm::make_unique<raw_fd_ostream>(TempFD, /* ShouldClose */ true),
80 AddFile, TempFilename.str(), EntryPath.str(), Task);
81 };
82 };
Mehdi Aminiadc0e262016-08-23 21:30:12 +000083}