zequanwu created this revision.
zequanwu added reviewers: rnk, tejohnson, mehdi_amini.
Herald added subscribers: pmatos, asb, ormris, steven_wu, hiraditya, 
arichardson, inglorion, sbc100, emaste.
Herald added a reviewer: MaskRay.
Herald added projects: lld-macho, All.
Herald added a reviewer: lld-macho.
zequanwu requested review of this revision.
Herald added subscribers: llvm-commits, lldb-commits, cfe-commits, StephenFan, 
aheejin.
Herald added projects: clang, LLDB, LLVM.

Currently the lto native object files have names like main.exe.lto.1.obj. In
PDB, those names are used as names for each compiland. Microsoft’s tool
SizeBench uses those names to present to users the size of each object files.
So, names like main.exe.lto.1.obj is not user friendly.

This patch makes the lto native object file names more readable by using
the bitcode file names as part of the file names. For example, if the input
bitcode file has path like "path/to/foo.obj", its corresponding lto native
object file path would be "path/to/main.exe.lto.foo.obj". Since the lto native
object file name only bothers PDB, this patch only changes the lld-linker's
behavior.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137217

Files:
  clang/lib/CodeGen/BackendUtil.cpp
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
  lld/COFF/LTO.cpp
  lld/COFF/LTO.h
  lld/ELF/LTO.cpp
  lld/MachO/LTO.cpp
  lld/test/COFF/lto-obj-path.ll
  lld/test/COFF/pdb-thinlto.ll
  lld/test/COFF/thinlto.ll
  lld/wasm/LTO.cpp
  lldb/source/Core/DataFileCache.cpp
  llvm/include/llvm/Support/Caching.h
  llvm/lib/Debuginfod/Debuginfod.cpp
  llvm/lib/LTO/LTO.cpp
  llvm/lib/LTO/LTOBackend.cpp
  llvm/lib/LTO/LTOCodeGenerator.cpp
  llvm/lib/Support/Caching.cpp
  llvm/tools/llvm-lto/llvm-lto.cpp
  llvm/tools/llvm-lto2/llvm-lto2.cpp

Index: llvm/tools/llvm-lto2/llvm-lto2.cpp
===================================================================
--- llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -411,7 +411,8 @@
   if (HasErrors)
     return 1;
 
-  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+  auto AddStream = [&](size_t Task,
+                       Twine File) -> std::unique_ptr<CachedFileStream> {
     std::string Path = OutputFilename + "." + utostr(Task);
 
     std::error_code EC;
@@ -420,8 +421,9 @@
     return std::make_unique<CachedFileStream>(std::move(S), Path);
   };
 
-  auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
-    *AddStream(Task)->OS << MB->getBuffer();
+  auto AddBuffer = [&](size_t Task, Twine File,
+                       std::unique_ptr<MemoryBuffer> MB) {
+    *AddStream(Task, File)->OS << MB->getBuffer();
   };
 
   FileCache Cache;
Index: llvm/tools/llvm-lto/llvm-lto.cpp
===================================================================
--- llvm/tools/llvm-lto/llvm-lto.cpp
+++ llvm/tools/llvm-lto/llvm-lto.cpp
@@ -317,11 +317,11 @@
       if (!CurrentActivity.empty())
         OS << ' ' << CurrentActivity;
       OS << ": ";
-  
+
       DiagnosticPrinterRawOStream DP(OS);
       DI.print(DP);
       OS << '\n';
-  
+
       if (DI.getSeverity() == DS_Error)
         exit(1);
       return true;
@@ -1099,7 +1099,8 @@
         error("writing merged module failed.");
     }
 
-    auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+    auto AddStream = [&](size_t Task,
+                         Twine File) -> std::unique_ptr<CachedFileStream> {
       std::string PartFilename = OutputFilename;
       if (Parallelism != 1)
         PartFilename += "." + utostr(Task);
Index: llvm/lib/Support/Caching.cpp
===================================================================
--- llvm/lib/Support/Caching.cpp
+++ llvm/lib/Support/Caching.cpp
@@ -37,7 +37,8 @@
   TempFilePrefixRef.toVector(TempFilePrefix);
   CacheDirectoryPathRef.toVector(CacheDirectoryPath);
 
-  return [=](unsigned Task, StringRef Key) -> Expected<AddStreamFn> {
+  return [=](unsigned Task, StringRef Key,
+             Twine File) -> Expected<AddStreamFn> {
     // This choice of file name allows the cache to be pruned (see pruneCache()
     // in include/llvm/Support/CachePruning.h).
     SmallString<64> EntryPath;
@@ -54,7 +55,7 @@
                                     /*RequiresNullTerminator=*/false);
       sys::fs::closeFile(*FDOrErr);
       if (MBOrErr) {
-        AddBuffer(Task, std::move(*MBOrErr));
+        AddBuffer(Task, File, std::move(*MBOrErr));
         return AddStreamFn();
       }
       EC = MBOrErr.getError();
@@ -77,14 +78,15 @@
     struct CacheStream : CachedFileStream {
       AddBufferFn AddBuffer;
       sys::fs::TempFile TempFile;
+      std::string ModuleName;
       unsigned Task;
 
       CacheStream(std::unique_ptr<raw_pwrite_stream> OS, AddBufferFn AddBuffer,
                   sys::fs::TempFile TempFile, std::string EntryPath,
-                  unsigned Task)
+                  std::string ModuleName, unsigned Task)
           : CachedFileStream(std::move(OS), std::move(EntryPath)),
             AddBuffer(std::move(AddBuffer)), TempFile(std::move(TempFile)),
-            Task(Task) {}
+            ModuleName(ModuleName), Task(Task) {}
 
       ~CacheStream() {
         // TODO: Manually commit rather than using non-trivial destructor,
@@ -133,11 +135,12 @@
                              TempFile.TmpName + " to " + ObjectPathName + ": " +
                              toString(std::move(E)) + "\n");
 
-        AddBuffer(Task, std::move(*MBOrErr));
+        AddBuffer(Task, ModuleName, std::move(*MBOrErr));
       }
     };
 
-    return [=](size_t Task) -> Expected<std::unique_ptr<CachedFileStream>> {
+    return [=](size_t Task,
+               Twine File) -> Expected<std::unique_ptr<CachedFileStream>> {
       // Create the cache directory if not already done. Doing this lazily
       // ensures the filesystem isn't mutated until the cache is.
       if (std::error_code EC = sys::fs::create_directories(
@@ -158,7 +161,8 @@
       // This CacheStream will move the temporary file into the cache when done.
       return std::make_unique<CacheStream>(
           std::make_unique<raw_fd_ostream>(Temp->FD, /* ShouldClose */ false),
-          AddBuffer, std::move(*Temp), std::string(EntryPath.str()), Task);
+          AddBuffer, std::move(*Temp), std::string(EntryPath.str()), File.str(),
+          Task);
     };
   };
 }
Index: llvm/lib/LTO/LTOCodeGenerator.cpp
===================================================================
--- llvm/lib/LTO/LTOCodeGenerator.cpp
+++ llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -301,7 +301,8 @@
   // make unique temp output file to put generated code
   SmallString<128> Filename;
 
-  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+  auto AddStream = [&](size_t Task,
+                       Twine File) -> std::unique_ptr<CachedFileStream> {
     StringRef Extension(Config.CGFileType == CGFT_AssemblyFile ? "s" : "o");
 
     int FD;
Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ llvm/lib/LTO/LTOBackend.cpp
@@ -391,7 +391,8 @@
                          EC.message());
   }
 
-  Expected<std::unique_ptr<CachedFileStream>> StreamOrErr = AddStream(Task);
+  Expected<std::unique_ptr<CachedFileStream>> StreamOrErr =
+      AddStream(Task, Mod.getModuleIdentifier());
   if (Error Err = StreamOrErr.takeError())
     report_fatal_error(std::move(Err));
   std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
Index: llvm/lib/LTO/LTO.cpp
===================================================================
--- llvm/lib/LTO/LTO.cpp
+++ llvm/lib/LTO/LTO.cpp
@@ -1296,7 +1296,7 @@
     computeLTOCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList,
                        ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs,
                        CfiFunctionDecls);
-    Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, Key);
+    Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, Key, ModuleID);
     if (Error Err = CacheAddStreamOrErr.takeError())
       return Err;
     AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
Index: llvm/lib/Debuginfod/Debuginfod.cpp
===================================================================
--- llvm/lib/Debuginfod/Debuginfod.cpp
+++ llvm/lib/Debuginfod/Debuginfod.cpp
@@ -184,7 +184,7 @@
   FileCache Cache = *CacheOrErr;
   // We choose an arbitrary Task parameter as we do not make use of it.
   unsigned Task = 0;
-  Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, UniqueKey);
+  Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task, UniqueKey, "");
   if (!CacheAddStreamOrErr)
     return CacheAddStreamOrErr.takeError();
   AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
@@ -211,8 +211,8 @@
 
     // Perform the HTTP request and if successful, write the response body to
     // the cache.
-    StreamedHTTPResponseHandler Handler([&]() { return CacheAddStream(Task); },
-                                        Client);
+    StreamedHTTPResponseHandler Handler(
+        [&]() { return CacheAddStream(Task, ""); }, Client);
     HTTPRequest Request(ArtifactUrl);
     Error Err = Client.perform(Request, Handler);
     if (Err)
Index: llvm/include/llvm/Support/Caching.h
===================================================================
--- llvm/include/llvm/Support/Caching.h
+++ llvm/include/llvm/Support/Caching.h
@@ -38,8 +38,8 @@
 /// This type defines the callback to add a file that is generated on the fly.
 ///
 /// Stream callbacks must be thread safe.
-using AddStreamFn =
-    std::function<Expected<std::unique_ptr<CachedFileStream>>(unsigned Task)>;
+using AddStreamFn = std::function<Expected<std::unique_ptr<CachedFileStream>>(
+    unsigned Task, Twine File)>;
 
 /// This is the type of a file cache. To request an item from the cache, pass a
 /// unique string as the Key. For hits, the cached file will be added to the
@@ -52,14 +52,14 @@
 ///
 /// if (AddStreamFn AddStream = Cache(Task, Key))
 ///   ProduceContent(AddStream);
-using FileCache =
-    std::function<Expected<AddStreamFn>(unsigned Task, StringRef Key)>;
+using FileCache = std::function<Expected<AddStreamFn>(
+    unsigned Task, StringRef Key, Twine File)>;
 
 /// This type defines the callback to add a pre-existing file (e.g. in a cache).
 ///
 /// Buffer callbacks must be thread safe.
-using AddBufferFn =
-    std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)>;
+using AddBufferFn = std::function<void(unsigned Task, Twine File,
+                                       std::unique_ptr<MemoryBuffer> MB)>;
 
 /// Create a local file system cache which uses the given cache name, temporary
 /// file prefix, cache directory and file callback.  This function does not
@@ -69,8 +69,8 @@
 /// temporary file naming scheme used when writing files atomically.
 Expected<FileCache> localCache(
     Twine CacheNameRef, Twine TempFilePrefixRef, Twine CacheDirectoryPathRef,
-    AddBufferFn AddBuffer = [](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
-    });
+    AddBufferFn AddBuffer = [](size_t Task, Twine File,
+                               std::unique_ptr<MemoryBuffer> MB) {});
 } // namespace llvm
 
 #endif
Index: lldb/source/Core/DataFileCache.cpp
===================================================================
--- lldb/source/Core/DataFileCache.cpp
+++ lldb/source/Core/DataFileCache.cpp
@@ -54,7 +54,8 @@
   // m_take_ownership member variable to indicate if we need to take
   // ownership.
 
-  auto add_buffer = [this](unsigned task, std::unique_ptr<llvm::MemoryBuffer> m) {
+  auto add_buffer = [this](unsigned task, llvm::Twine file,
+                           std::unique_ptr<llvm::MemoryBuffer> m) {
     if (m_take_ownership)
       m_mem_buff_up = std::move(m);
   };
@@ -80,7 +81,7 @@
   // turn take ownership of the member buffer that is passed to the callback and
   // put it into a member variable.
   llvm::Expected<llvm::AddStreamFn> add_stream_or_err =
-      m_cache_callback(task, key);
+      m_cache_callback(task, key, "");
   m_take_ownership = false;
   // At this point we either already called the "add_buffer" lambda with
   // the data or we haven't. We can tell if we got the cached data by checking
@@ -112,7 +113,7 @@
   // add_buffer lambda function from the constructor which will ignore the
   // data.
   llvm::Expected<llvm::AddStreamFn> add_stream_or_err =
-      m_cache_callback(task, key);
+      m_cache_callback(task, key, "");
   // If we reach this code then we either already called the callback with
   // the data or we haven't. We can tell if we had the cached data by checking
   // the CacheAddStream function pointer value below.
@@ -127,7 +128,7 @@
     // want to write the data.
     if (add_stream) {
       llvm::Expected<std::unique_ptr<llvm::CachedFileStream>> file_or_err =
-          add_stream(task);
+          add_stream(task, "");
       if (file_or_err) {
         llvm::CachedFileStream *cfs = file_or_err->get();
         cfs->OS->write((const char *)data.data(), data.size());
Index: lld/wasm/LTO.cpp
===================================================================
--- lld/wasm/LTO.cpp
+++ lld/wasm/LTO.cpp
@@ -128,14 +128,14 @@
   // specified, configure LTO to use it as the cache directory.
   FileCache cache;
   if (!config->thinLTOCacheDir.empty())
-    cache =
-        check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
-                         [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
-                           files[task] = std::move(mb);
-                         }));
+    cache = check(localCache(
+        "ThinLTO", "Thin", config->thinLTOCacheDir,
+        [&](size_t task, Twine originFile, std::unique_ptr<MemoryBuffer> mb) {
+          files[task] = std::move(mb);
+        }));
 
   checkError(ltoObj->run(
-      [&](size_t task) {
+      [&](size_t task, Twine file) {
         return std::make_unique<CachedFileStream>(
             std::make_unique<raw_svector_ostream>(buf[task]));
       },
Index: lld/test/COFF/thinlto.ll
===================================================================
--- lld/test/COFF/thinlto.ll
+++ lld/test/COFF/thinlto.ll
@@ -4,15 +4,15 @@
 ; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s
 ; RUN: opt -thinlto-bc -o %T/thinlto/foo.obj %S/Inputs/lto-dep.ll
 ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj
-; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s
+; RUN: llvm-nm %T/thinlto/main.exe.lto.foo.obj | FileCheck %s
 
 ; Test various possible options for /opt:lldltojobs
 ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=1
-; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s
+; RUN: llvm-nm %T/thinlto/main.exe.lto.foo.obj | FileCheck %s
 ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=all
-; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s
+; RUN: llvm-nm %T/thinlto/main.exe.lto.foo.obj | FileCheck %s
 ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=100
-; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s
+; RUN: llvm-nm %T/thinlto/main.exe.lto.foo.obj | FileCheck %s
 ; RUN: not lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=foo 2>&1 | FileCheck %s --check-prefix=BAD-JOBS
 ; BAD-JOBS: error: /opt:lldltojobs: invalid job count: foo
 
Index: lld/test/COFF/pdb-thinlto.ll
===================================================================
--- lld/test/COFF/pdb-thinlto.ll
+++ lld/test/COFF/pdb-thinlto.ll
@@ -29,8 +29,8 @@
 
 ; CHECK:                           Modules
 ; CHECK: ============================================================
-; CHECK: Mod 0000 | `{{.*}}main.exe.lto.1.obj`:
-; CHECK: Obj: `{{.*}}main.exe.lto.1.obj`:
-; CHECK: Mod 0001 | `{{.*}}main.exe.lto.2.obj`:
-; CHECK: Obj: `{{.*}}main.exe.lto.2.obj`:
+; CHECK: Mod 0000 | `{{.*}}main.exe.lto.main.bc`:
+; CHECK: Obj: `{{.*}}main.exe.lto.main.bc`:
+; CHECK: Mod 0001 | `{{.*}}main.exe.lto.foo.bc`:
+; CHECK: Obj: `{{.*}}main.exe.lto.foo.bc`:
 ; CHECK: Mod 0002 | `* Linker *`:
Index: lld/test/COFF/lto-obj-path.ll
===================================================================
--- lld/test/COFF/lto-obj-path.ll
+++ lld/test/COFF/lto-obj-path.ll
@@ -2,26 +2,31 @@
 
 ; Test to ensure that thinlto-index-only with lto-obj-path creates
 ; the native object file.
-; RUN: opt -module-summary %s -o %t1.obj
-; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.obj
-; RUN: rm -f %t4.obj
-; RUN: lld-link -thinlto-index-only -lto-obj-path:%t4.obj -out:t3.exe \
-; RUN:     -entry:main %t1.obj %t2.obj
-; RUN: llvm-readobj -h %t4.obj | FileCheck %s
-; RUN: llvm-nm %t4.obj 2>&1 | FileCheck %s -check-prefix=SYMBOLS
-; RUN: llvm-nm %t4.obj 2>&1 | count 1
+; RUN: rm -rf %t.dir/objpath && mkdir -p %t.dir/objpath
+; RUN: opt -module-summary %s -o %t.dir/objpath/t1.obj
+; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t.dir/objpath/t2.obj
+; RUN: rm -f %t.dir/objpath/t4.obj
+; RUN: lld-link -thinlto-index-only -lto-obj-path:%t.dir/objpath/t4.obj \
+; RUN:     -out:%t.dir/objpath/t3.exe -entry:main %t.dir/objpath/t1.obj \
+; RUN:     %t.dir/objpath/t2.obj
+; RUN: llvm-readobj -h %t.dir/objpath/t4.obj | FileCheck %s
+; RUN: llvm-nm %t.dir/objpath/t4.obj 2>&1 | FileCheck %s -check-prefix=SYMBOLS
+; RUN: llvm-nm %t.dir/objpath/t4.obj 2>&1 | count 1
 
 ;; Ensure lld emits empty combined module if specific obj-path.
-; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
-; RUN: lld-link /out:%t.dir/objpath/a.exe -lto-obj-path:%t4.obj \
-; RUN:     -entry:main %t1.obj %t2.obj -lldsavetemps
-; RUN: ls %t.dir/objpath/a.exe.lto.* | count 3
+; RUN: lld-link /out:%t.dir/objpath/a.exe -lto-obj-path:%t.dir/objpath/t4.obj \
+; RUN:     -entry:main %t.dir/objpath/t1.obj %t.dir/objpath/t2.obj -lldsavetemps
+; RUN: ls %t.dir/objpath/a.exe.lto.obj
+; RUN: ls %t.dir/objpath/a.exe.lto.t1.obj
+; RUN: ls %t.dir/objpath/a.exe.lto.t2.obj
 
 ;; Ensure lld does not emit empty combined module in default.
-; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
+; RUN: rm %t.dir/objpath/a.exe.lto.*
 ; RUN: lld-link /out:%t.dir/objpath/a.exe \
-; RUN:     -entry:main %t1.obj %t2.obj -lldsavetemps
-; RUN: ls %t.dir/objpath/a.exe.lto.* | count 2
+; RUN:     -entry:main %t.dir/objpath/t1.obj %t.dir/objpath/t2.obj -lldsavetemps
+; RUN: ls %t.dir/objpath/a.exe.lto.t1.obj
+; RUN: ls %t.dir/objpath/a.exe.lto.t2.obj
+; RUN: not ls %t.dir/objpath/a.exe.lto.obj
 
 ; CHECK: Format: COFF-x86-64
 ; SYMBOLS: @feat.00
Index: lld/MachO/LTO.cpp
===================================================================
--- lld/MachO/LTO.cpp
+++ lld/MachO/LTO.cpp
@@ -127,14 +127,14 @@
   // specified, configure LTO to use it as the cache directory.
   FileCache cache;
   if (!config->thinLTOCacheDir.empty())
-    cache =
-        check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
-                         [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
-                           files[task] = std::move(mb);
-                         }));
+    cache = check(localCache(
+        "ThinLTO", "Thin", config->thinLTOCacheDir,
+        [&](size_t task, Twine originFile, std::unique_ptr<MemoryBuffer> mb) {
+          files[task] = std::move(mb);
+        }));
 
   checkError(ltoObj->run(
-      [&](size_t task) {
+      [&](size_t task, Twine file) {
         return std::make_unique<CachedFileStream>(
             std::make_unique<raw_svector_ostream>(buf[task]));
       },
Index: lld/ELF/LTO.cpp
===================================================================
--- lld/ELF/LTO.cpp
+++ lld/ELF/LTO.cpp
@@ -327,15 +327,15 @@
   // specified, configure LTO to use it as the cache directory.
   FileCache cache;
   if (!config->thinLTOCacheDir.empty())
-    cache =
-        check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
-                         [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
-                           files[task] = std::move(mb);
-                         }));
+    cache = check(localCache(
+        "ThinLTO", "Thin", config->thinLTOCacheDir,
+        [&](size_t task, Twine file, std::unique_ptr<MemoryBuffer> mb) {
+          files[task] = std::move(mb);
+        }));
 
   if (!ctx.bitcodeFiles.empty())
     checkError(ltoObj->run(
-        [&](size_t task) {
+        [&](size_t task, Twine file) {
           return std::make_unique<CachedFileStream>(
               std::make_unique<raw_svector_ostream>(buf[task]));
         },
Index: lld/COFF/LTO.h
===================================================================
--- lld/COFF/LTO.h
+++ lld/COFF/LTO.h
@@ -47,8 +47,8 @@
 
 private:
   std::unique_ptr<llvm::lto::LTO> ltoObj;
-  std::vector<SmallString<0>> buf;
-  std::vector<std::unique_ptr<MemoryBuffer>> files;
+  std::vector<std::pair<std::string, SmallString<0>>> buf;
+  std::vector<std::pair<std::string, std::unique_ptr<MemoryBuffer>>> files;
   std::unique_ptr<llvm::raw_fd_ostream> indexFile;
   llvm::DenseSet<StringRef> thinIndices;
 };
Index: lld/COFF/LTO.cpp
===================================================================
--- lld/COFF/LTO.cpp
+++ lld/COFF/LTO.cpp
@@ -169,16 +169,18 @@
   // specified, configure LTO to use it as the cache directory.
   FileCache cache;
   if (!config->ltoCache.empty())
-    cache =
-        check(localCache("ThinLTO", "Thin", config->ltoCache,
-                         [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
-                           files[task] = std::move(mb);
-                         }));
+    cache = check(localCache(
+        "ThinLTO", "Thin", config->ltoCache,
+        [&](size_t task, Twine file, std::unique_ptr<MemoryBuffer> mb) {
+          files[task].first = file.str();
+          files[task].second = std::move(mb);
+        }));
 
   checkError(ltoObj->run(
-      [&](size_t task) {
+      [&](size_t task, Twine file) {
+        buf[task].first = file.str();
         return std::make_unique<CachedFileStream>(
-            std::make_unique<raw_svector_ostream>(buf[task]));
+            std::make_unique<raw_svector_ostream>(buf[task].second));
       },
       cache));
 
@@ -195,7 +197,7 @@
   // distributed environment.
   if (config->thinLTOIndexOnly) {
     if (!config->ltoObjPath.empty())
-      saveBuffer(buf[0], config->ltoObjPath);
+      saveBuffer(buf[0].second, config->ltoObjPath);
     if (indexFile)
       indexFile->close();
     return {};
@@ -206,28 +208,40 @@
 
   std::vector<InputFile *> ret;
   for (unsigned i = 0; i != maxTasks; ++i) {
-    // Assign unique names to LTO objects. This ensures they have unique names
-    // in the PDB if one is produced. The names should look like:
-    // - foo.exe.lto.obj
-    // - foo.exe.lto.1.obj
-    // - ...
-    StringRef ltoObjName =
-        saver().save(Twine(config->outputFile) + ".lto" +
-                     (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj");
-
+    StringRef bitcodeFilePath;
     // Get the native object contents either from the cache or from memory.  Do
     // not use the cached MemoryBuffer directly, or the PDB will not be
     // deterministic.
     StringRef objBuf;
-    if (files[i])
-      objBuf = files[i]->getBuffer();
-    else
-      objBuf = buf[i];
+    if (files[i].second) {
+      objBuf = files[i].second->getBuffer();
+      bitcodeFilePath = files[i].first;
+    } else {
+      objBuf = buf[i].second;
+      bitcodeFilePath = buf[i].first;
+    }
     if (objBuf.empty())
       continue;
 
+    // If the input bitcode file is path/to/a.obj, then the corresponding lto
+    // object file name will soemthing like: path/to/main.exe.lto.a.obj.
+    StringRef ltoObjName;
+    if (bitcodeFilePath == "ld-temp.o") {
+      ltoObjName =
+          saver().save(Twine(config->outputFile) + ".lto" +
+                       (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj");
+    } else {
+      StringRef directory = sys::path::parent_path(bitcodeFilePath);
+      StringRef baseName = sys::path::filename(bitcodeFilePath);
+      StringRef outputFileBaseName = sys::path::filename(config->outputFile);
+      SmallString<64> path;
+      sys::path::append(path, directory,
+                        outputFileBaseName + ".lto." + baseName);
+      sys::path::remove_dots(path, true);
+      ltoObjName = saver().save(path.str());
+    }
     if (config->saveTemps)
-      saveBuffer(buf[i], ltoObjName);
+      saveBuffer(buf[i].second, ltoObjName);
     ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));
   }
 
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -842,7 +842,8 @@
   // Run the LTO job to compile the bitcode.
   size_t MaxTasks = LTOBackend->getMaxTasks();
   SmallVector<StringRef> Files(MaxTasks);
-  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+  auto AddStream = [&](size_t Task,
+                       Twine File) -> std::unique_ptr<CachedFileStream> {
     int FD = -1;
     auto &TempFile = Files[Task];
     StringRef Extension = (Triple.isNVPTX()) ? "s" : "o";
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -1101,7 +1101,7 @@
   if (!lto::initImportList(*M, *CombinedIndex, ImportList))
     return;
 
-  auto AddStream = [&](size_t Task) {
+  auto AddStream = [&](size_t Task, Twine File) {
     return std::make_unique<CachedFileStream>(std::move(OS),
                                               CGOpts.ObjectFilenameForDebug);
   };
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to