diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp index 2cbee6179e0e1..f465c41aec6c7 100644 --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -52,6 +52,18 @@ static lto::Config createConfig() { return c; } +// If `originalPath` exists, hardlinks `path` to `originalPath`. If that fails, +// or `originalPath` is not set, saves `buffer` to `path`. +static void saveOrHardlinkBuffer(StringRef buffer, const Twine &path, + Optional originalPath) { + if (originalPath) { + auto err = fs::create_hard_link(*originalPath, path); + if (!err) + return; + } + saveBuffer(buffer, path); +} + BitcodeCompiler::BitcodeCompiler() { lto::ThinBackend backend = lto::createInProcessThinBackend( heavyweight_hardware_concurrency(config->thinLTOJobs)); @@ -154,10 +166,13 @@ std::vector BitcodeCompiler::compile() { // not use the cached MemoryBuffer directly to ensure dsymutil does not // race with the cache pruner. StringRef objBuf; - if (files[i]) + Optional cachePath = llvm::None; + if (files[i]) { objBuf = files[i]->getBuffer(); - else + cachePath = files[i]->getBufferIdentifier(); + } else { objBuf = buf[i]; + } if (objBuf.empty()) continue; @@ -174,7 +189,7 @@ std::vector BitcodeCompiler::compile() { path::append(filePath, Twine(i) + "." + getArchitectureName(config->arch()) + ".lto.o"); - saveBuffer(objBuf, filePath); + saveOrHardlinkBuffer(objBuf, filePath, cachePath); modTime = getModTime(filePath); } ret.push_back(make( diff --git a/lld/test/MachO/lto-object-path.ll b/lld/test/MachO/lto-object-path.ll index 44e71860a0639..39bf4c006a09e 100644 --- a/lld/test/MachO/lto-object-path.ll +++ b/lld/test/MachO/lto-object-path.ll @@ -16,6 +16,16 @@ ;; And that dsymutil can read the result ; RUN: dsymutil -f -o - %t/test | llvm-dwarfdump - | FileCheck %s --check-prefix=DSYM +;; Test that the object path hardlinks to the cache when possible +;; NB: +;; 1) Need to delete current object path contents or hardlink will fail. +;; 2) Note the cache policy is different from the test above (which is crafted +;; to ensure that the cache is pruned immediately; we want the opposite here). +; RUN: rm -rf %t/lto-temps +; RUN: %lld %t/test.o -o %t/test -object_path_lto %t/lto-temps -prune_interval_lto 20 -cache_path_lto %t/cache --thinlto-cache-policy=cache_size_files=10:cache_size_bytes=10000 +;; Get the link count. +; RUN: ls -l %t/lto-temps/1.x86_64.lto.o | tr -s ' ' | cut -f 2 -d ' ' | FileCheck %s --check-prefix=HARDLINK + ;; check that the object path can be an existing file ; RUN: touch %t/lto-tmp.o ; RUN: %lld %t/test.o -o %t/test -object_path_lto %t/lto-tmp.o @@ -32,6 +42,7 @@ ; CHECK-NEXT: 0000000000000000 - 01 0000 SO ; CHECK-NEXT: {{[0-9a-f]+}} T _main ; DSYM: DW_AT_name ("test.cpp") +; HARDLINK: 2 target triple = "x86_64-apple-macosx10.15.0" target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"