diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -218,8 +218,16 @@ // Used for /thinlto-index-only: llvm::StringRef thinLTOIndexOnlyArg; - // Used for /thinlto-object-prefix-replace: - std::pair thinLTOPrefixReplace; + // Used for /thinlto-prefix-replace: + // Replace the prefix in paths generated for ThinLTO, replacing + // thinLTOPrefixReplaceOld with thinLTOPrefixReplaceNew. If + // thinLTOPrefixReplaceNativeObject is defined, replace the prefix of object + // file paths written to the response file given in the + // --thinlto-index-only=${response} option with + // thinLTOPrefixReplaceNativeObject, instead of thinLTOPrefixReplaceNew. + llvm::StringRef thinLTOPrefixReplaceOld; + llvm::StringRef thinLTOPrefixReplaceNew; + llvm::StringRef thinLTOPrefixReplaceNativeObject; // Used for /thinlto-object-suffix-replace: std::pair thinLTOObjectSuffixReplace; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -53,6 +53,7 @@ #include #include #include +#include using namespace llvm; using namespace llvm::object; @@ -90,6 +91,14 @@ return ret; } +// Parse options of the form "old;new[;extra]". +static std::tuple +getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { + auto [oldDir, second] = getOldNewOptions(args, id); + auto [newDir, extraDir] = second.split(';'); + return {oldDir, newDir, extraDir}; +} + // Drop directory components and replace extension with // ".exe", ".dll" or ".sys". static std::string getOutputPath(StringRef path, bool isDll, bool isDriver) { @@ -1884,8 +1893,9 @@ args.hasArg(OPT_thinlto_index_only_arg); config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_arg); - config->thinLTOPrefixReplace = - getOldNewOptions(args, OPT_thinlto_prefix_replace); + std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, + config->thinLTOPrefixReplaceNativeObject) = + getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace); config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path); diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -56,8 +56,8 @@ std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) { return lto::getThinLTOOutputFile( - std::string(path), std::string(ctx.config.thinLTOPrefixReplace.first), - std::string(ctx.config.thinLTOPrefixReplace.second)); + std::string(path), std::string(ctx.config.thinLTOPrefixReplaceOld), + std::string(ctx.config.thinLTOPrefixReplaceNew)); } lto::Config BitcodeCompiler::createConfig() { @@ -114,8 +114,9 @@ if (ctx.config.thinLTOIndexOnly) { auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); }; backend = lto::createWriteIndexesThinBackend( - std::string(ctx.config.thinLTOPrefixReplace.first), - std::string(ctx.config.thinLTOPrefixReplace.second), + std::string(ctx.config.thinLTOPrefixReplaceOld), + std::string(ctx.config.thinLTOPrefixReplaceNew), + std::string(ctx.config.thinLTOPrefixReplaceNativeObject), ctx.config.thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite); } else { backend = lto::createInProcessThinBackend( diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -177,7 +177,9 @@ StringRef zCetReport = "none"; llvm::StringRef ltoBasicBlockSections; std::pair thinLTOObjectSuffixReplace; - std::pair thinLTOPrefixReplace; + llvm::StringRef thinLTOPrefixReplaceOld; + llvm::StringRef thinLTOPrefixReplaceNew; + llvm::StringRef thinLTOPrefixReplaceNativeObject; std::string rpath; llvm::SmallVector versionDefinitions; llvm::SmallVector auxiliaryList; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -65,6 +65,7 @@ #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include +#include #include using namespace llvm; @@ -1023,6 +1024,14 @@ return ret; } +// Parse options of the form "old;new[;extra]". +static std::tuple +getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { + auto [oldDir, second] = getOldNewOptions(args, id); + auto [newDir, extraDir] = second.split(';'); + return {oldDir, newDir, extraDir}; +} + // Parse the symbol ordering file and warn for any duplicate entries. static SmallVector getSymbolOrderingFile(MemoryBufferRef mb) { SetVector> names; @@ -1249,8 +1258,9 @@ config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); - config->thinLTOPrefixReplace = - getOldNewOptions(args, OPT_thinlto_prefix_replace_eq); + std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, + config->thinLTOPrefixReplaceNativeObject) = + getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq); if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) { if (args.hasArg(OPT_thinlto_object_suffix_replace_eq)) error("--thinlto-object-suffix-replace is not supported with " @@ -1259,6 +1269,11 @@ error("--thinlto-prefix-replace is not supported with " "--thinlto-emit-index-files"); } + if (!config->thinLTOPrefixReplaceNativeObject.empty() && + config->thinLTOIndexOnlyArg.empty()) { + error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with " + "--thinlto-index-only="); + } config->thinLTOModulesToCompile = args::getStrings(args, OPT_thinlto_single_module_eq); config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq); diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -68,8 +68,8 @@ static std::string getThinLTOOutputFile(StringRef modulePath) { return lto::getThinLTOOutputFile( - std::string(modulePath), std::string(config->thinLTOPrefixReplace.first), - std::string(config->thinLTOPrefixReplace.second)); + std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld), + std::string(config->thinLTOPrefixReplaceNew)); } static lto::Config createConfig() { @@ -196,8 +196,9 @@ auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); }; if (config->thinLTOIndexOnly) { backend = lto::createWriteIndexesThinBackend( - std::string(config->thinLTOPrefixReplace.first), - std::string(config->thinLTOPrefixReplace.second), + std::string(config->thinLTOPrefixReplaceOld), + std::string(config->thinLTOPrefixReplaceNew), + std::string(config->thinLTOPrefixReplaceNativeObject), config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite); } else { backend = lto::createInProcessThinBackend( diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -173,7 +173,9 @@ llvm::StringRef thinLTOCacheDir; llvm::StringRef thinLTOIndexOnlyArg; std::pair thinLTOObjectSuffixReplace; - std::pair thinLTOPrefixReplace; + llvm::StringRef thinLTOPrefixReplaceOld; + llvm::StringRef thinLTOPrefixReplaceNew; + llvm::StringRef thinLTOPrefixReplaceNativeObject; bool deadStripDylibs = false; bool demangle = false; bool deadStrip = false; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -868,6 +868,14 @@ return ret; } +// Parse options of the form "old;new[;extra]". +static std::tuple +getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { + auto [oldDir, second] = getOldNewOptions(args, id); + auto [newDir, extraDir] = second.split(';'); + return {oldDir, newDir, extraDir}; +} + static void parseClangOption(StringRef opt, const Twine &msg) { std::string err; raw_string_ostream os(err); @@ -1578,8 +1586,9 @@ config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); - config->thinLTOPrefixReplace = - getOldNewOptions(args, OPT_thinlto_prefix_replace_eq); + std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, + config->thinLTOPrefixReplaceNativeObject) = + getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq); if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) { if (args.hasArg(OPT_thinlto_object_suffix_replace_eq)) error("--thinlto-object-suffix-replace is not supported with " @@ -1588,6 +1597,11 @@ error("--thinlto-prefix-replace is not supported with " "--thinlto-emit-index-files"); } + if (!config->thinLTOPrefixReplaceNativeObject.empty() && + config->thinLTOIndexOnlyArg.empty()) { + error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with " + "--thinlto-index-only="); + } config->runtimePaths = args::getStrings(args, OPT_rpath); config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false); config->archMultiple = args.hasArg(OPT_arch_multiple); diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -47,8 +47,8 @@ static std::string getThinLTOOutputFile(StringRef modulePath) { return lto::getThinLTOOutputFile( - std::string(modulePath), std::string(config->thinLTOPrefixReplace.first), - std::string(config->thinLTOPrefixReplace.second)); + std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld), + std::string(config->thinLTOPrefixReplaceNew)); } static lto::Config createConfig() { @@ -99,8 +99,9 @@ auto onIndexWrite = [&](StringRef S) { thinIndices.erase(S); }; if (config->thinLTOIndexOnly) { backend = lto::createWriteIndexesThinBackend( - std::string(config->thinLTOPrefixReplace.first), - std::string(config->thinLTOPrefixReplace.second), + std::string(config->thinLTOPrefixReplaceOld), + std::string(config->thinLTOPrefixReplaceNew), + std::string(config->thinLTOPrefixReplaceNativeObject), config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite); } else { backend = lto::createInProcessThinBackend( diff --git a/lld/test/COFF/thinlto-index-file-object-prefix-replace.ll b/lld/test/COFF/thinlto-index-file-object-prefix-replace.ll new file mode 100644 --- /dev/null +++ b/lld/test/COFF/thinlto-index-file-object-prefix-replace.ll @@ -0,0 +1,46 @@ +; REQUIRES: x86 +; RUN: rm -rf %t && mkdir %t +; RUN: mkdir -p %t/old/subdir +; RUN: opt -module-summary %s -o %t/old/subdir/1.obj +; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t/old/subdir/2.obj +; RUN: opt -module-summary %p/Inputs/thinlto-empty.ll -o %t/old/3.obj + +;; Ensure lld writes linked files to linked objects file. +; RUN: lld-link -entry:main -thinlto-index-only:%t/1.txt %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe +; RUN: ls %t/old/subdir/1.obj.thinlto.bc +; RUN: ls %t/old/subdir/2.obj.thinlto.bc +; RUN: ls %t/old/3.obj.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-NO-REPLACE %s < %t/1.txt +; CHECK-NO-REPLACE: old/subdir/1.obj +; CHECK-NO-REPLACE-NEXT: old/subdir/2.obj +; CHECK-NO-REPLACE-NEXT: old/3.obj + +;; Check that this also works with thinlto-prefix-replace. +; RUN: lld-link -entry:main -thinlto-index-only:%t/2.txt -thinlto-prefix-replace:"%t/old/;%t/new/" %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe +; RUN: ls %t/new/subdir/1.obj.thinlto.bc +; RUN: ls %t/new/subdir/2.obj.thinlto.bc +; RUN: ls %t/new/3.obj.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-REPLACE-PREFIX %s < %t/2.txt +; CHECK-REPLACE-PREFIX: new/subdir/1.obj +; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.obj +; CHECK-REPLACE-PREFIX-NEXT: new/3.obj + +;; Check that this also works with replacing the prefix of linked objects. +; RUN: lld-link -entry:main -thinlto-index-only:%t/3.txt -thinlto-prefix-replace:"%t/old/;%t/new/;%t/obj/" %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe +; RUN: ls %t/new/subdir/1.obj.thinlto.bc +; RUN: ls %t/new/subdir/2.obj.thinlto.bc +; RUN: ls %t/new/3.obj.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < %t/3.txt +; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.obj +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.obj +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.obj + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.24215" + +declare void @g(...) + +define void @main() { + call void (...) @g() + ret void +} diff --git a/lld/test/ELF/lto/thinlto-index-file-object-prefix-replace.ll b/lld/test/ELF/lto/thinlto-index-file-object-prefix-replace.ll new file mode 100644 --- /dev/null +++ b/lld/test/ELF/lto/thinlto-index-file-object-prefix-replace.ll @@ -0,0 +1,51 @@ +; REQUIRES: x86 +; RUN: rm -rf %t && mkdir %t && cd %t +; RUN: mkdir -p old/subdir +; RUN: opt -module-summary %s -o old/subdir/1.o +; RUN: opt -module-summary %p/Inputs/thinlto.ll -o old/subdir/2.o +; RUN: opt -module-summary %p/Inputs/thinlto_empty.ll -o old/3.o + +;; Ensure lld writes linked files to linked objects file. +; RUN: ld.lld --thinlto-index-only=1.txt -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null +; RUN: ls old/subdir/1.o.thinlto.bc +; RUN: ls old/subdir/2.o.thinlto.bc +; RUN: ls old/3.o.thinlto.bc +; RUN: FileCheck --match-full-lines --check-prefix=CHECK-NO-REPLACE %s < 1.txt +; CHECK-NO-REPLACE: old/subdir/1.o +; CHECK-NO-REPLACE-NEXT: old/subdir/2.o +; CHECK-NO-REPLACE-NEXT: old/3.o + +;; Check that this also works with thinlto-prefix-replace. +; RUN: ld.lld --thinlto-index-only=2.txt --thinlto-prefix-replace="old/;new/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null +; RUN: ls new/subdir/1.o.thinlto.bc +; RUN: ls new/subdir/2.o.thinlto.bc +; RUN: ls new/3.o.thinlto.bc +; RUN: FileCheck --match-full-lines --check-prefix=CHECK-REPLACE-PREFIX %s < 2.txt +; CHECK-REPLACE-PREFIX: new/subdir/1.o +; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.o +; CHECK-REPLACE-PREFIX-NEXT: new/3.o + +;; Check that this also works with replacing the prefix of linked objects. +; RUN: ld.lld --thinlto-index-only=3.txt --thinlto-prefix-replace="old/;new/;obj/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null +; RUN: ls new/subdir/1.o.thinlto.bc +; RUN: ls new/subdir/2.o.thinlto.bc +; RUN: ls new/3.o.thinlto.bc +; RUN: FileCheck --match-full-lines --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < 3.txt +; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.o +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.o +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.o + +; Create an error if prefix replace option have 'old;new;obj' format but index file is not set. Ensure that the error is about thinlto-prefix-replace. +; RUN: not ld.lld --thinlto-prefix-replace="old/;new/;obj/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERROR +; ERROR: error: --thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with --thinlto-index-only= + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @g(...) + +define void @f() { +entry: + call void (...) @g() + ret void +} diff --git a/lld/test/MachO/thinlto-index-file-object-prefix-replace.ll b/lld/test/MachO/thinlto-index-file-object-prefix-replace.ll new file mode 100644 --- /dev/null +++ b/lld/test/MachO/thinlto-index-file-object-prefix-replace.ll @@ -0,0 +1,67 @@ +; REQUIRES: x86 +; RUN: rm -rf %t && split-file %s %t +; RUN: mkdir -p %t/old/subdir + +; RUN: opt -module-summary %t/f.ll -o %t/old/subdir/1.o +; RUN: opt -module-summary %t/g.ll -o %t/old/subdir/2.o +; RUN: opt -module-summary %t/empty.ll -o %t/old/3.o + +;; Ensure lld writes linked files to linked objects file. +; RUN: %lld --thinlto-index-only=%t/1.txt -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null +; RUN: ls %t/old/subdir/1.o.thinlto.bc +; RUN: ls %t/old/subdir/2.o.thinlto.bc +; RUN: ls %t/old/3.o.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-NO-REPLACE %s < %t/1.txt +; CHECK-NO-REPLACE: old/subdir/1.o +; CHECK-NO-REPLACE-NEXT: old/subdir/2.o +; CHECK-NO-REPLACE-NEXT: old/3.o + +;; Check that this also works with thinlto-prefix-replace. +; RUN: %lld --thinlto-index-only=%t/2.txt --thinlto-prefix-replace="%t/old/;%t/new/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null +; RUN: ls %t/new/subdir/1.o.thinlto.bc +; RUN: ls %t/new/subdir/2.o.thinlto.bc +; RUN: ls %t/new/3.o.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-REPLACE-PREFIX %s < %t/2.txt +; CHECK-REPLACE-PREFIX: new/subdir/1.o +; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.o +; CHECK-REPLACE-PREFIX-NEXT: new/3.o + + +;; Check that this also works with replacing the prefix of linked objects. +; RUN: %lld --thinlto-index-only=%t/3.txt --thinlto-prefix-replace="%t/old/;%t/new/;%t/obj/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null +; RUN: ls %t/new/subdir/1.o.thinlto.bc +; RUN: ls %t/new/subdir/2.o.thinlto.bc +; RUN: ls %t/new/3.o.thinlto.bc +; RUN: FileCheck --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < %t/3.txt +; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.o +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.o +; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.o + +; Create an error if prefix replace option have 'old;new;obj' format but index file is not set. Ensure that the error is about thinlto-prefix-replace. +; RUN: not %lld --thinlto-prefix-replace="%t/old/;%t/new/;%t/obj/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERROR +; ERROR: error: --thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with --thinlto-index-only= + +;--- f.ll +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +declare void @g(...) + +define void @f() { +entry: + call void (...) @g() + ret void +} + +;--- g.ll +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" + +define void @g() { +entry: + ret void +} + +;--- empty.ll +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -219,11 +219,14 @@ /// ShouldEmitImportsFiles is true it also writes a list of imported files to a /// similar path with ".imports" appended instead. /// LinkedObjectsFile is an output stream to write the list of object files for -/// the final ThinLTO linking. Can be nullptr. -/// OnWrite is callback which receives module identifier and notifies LTO user -/// that index file for the module (and optionally imports file) was created. +/// the final ThinLTO linking. Can be nullptr. If LinkedObjectsFile is not +/// nullptr and NativeObjectPrefix is not empty then it replaces the prefix of +/// the objects with NativeObjectPrefix instead of NewPrefix. OnWrite is +/// callback which receives module identifier and notifies LTO user that index +/// file for the module (and optionally imports file) was created. ThinBackend createWriteIndexesThinBackend(std::string OldPrefix, std::string NewPrefix, + std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite); diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -1422,18 +1422,20 @@ namespace { class WriteIndexesThinBackend : public ThinBackendProc { - std::string OldPrefix, NewPrefix; + std::string OldPrefix, NewPrefix, NativeObjectPrefix; raw_fd_ostream *LinkedObjectsFile; public: WriteIndexesThinBackend( const Config &Conf, ModuleSummaryIndex &CombinedIndex, const StringMap &ModuleToDefinedGVSummaries, - std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles, + std::string OldPrefix, std::string NewPrefix, + std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite) : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries, OnWrite, ShouldEmitImportsFiles), OldPrefix(OldPrefix), NewPrefix(NewPrefix), + NativeObjectPrefix(NativeObjectPrefix), LinkedObjectsFile(LinkedObjectsFile) {} Error start( @@ -1446,8 +1448,13 @@ std::string NewModulePath = getThinLTOOutputFile(std::string(ModulePath), OldPrefix, NewPrefix); - if (LinkedObjectsFile) - *LinkedObjectsFile << NewModulePath << '\n'; + if (LinkedObjectsFile) { + std::string ObjectPrefix = + NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix; + std::string LinkedObjectsFilePath = getThinLTOOutputFile( + std::string(ModulePath), OldPrefix, ObjectPrefix); + *LinkedObjectsFile << LinkedObjectsFilePath << '\n'; + } if (auto E = emitFiles(ImportList, ModulePath, NewModulePath)) return E; @@ -1466,14 +1473,15 @@ } // end anonymous namespace ThinBackend lto::createWriteIndexesThinBackend( - std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles, + std::string OldPrefix, std::string NewPrefix, + std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite) { return [=](const Config &Conf, ModuleSummaryIndex &CombinedIndex, const StringMap &ModuleToDefinedGVSummaries, AddStreamFn AddStream, FileCache Cache) { return std::make_unique( Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix, NewPrefix, - ShouldEmitImportsFiles, LinkedObjectsFile, OnWrite); + NativeObjectPrefix, ShouldEmitImportsFiles, LinkedObjectsFile, OnWrite); }; } diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -891,9 +891,12 @@ if (options::thinlto_index_only) { std::string OldPrefix, NewPrefix; getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); - Backend = createWriteIndexesThinBackend(OldPrefix, NewPrefix, - options::thinlto_emit_imports_files, - LinkedObjectsFile, OnIndexWrite); + Backend = createWriteIndexesThinBackend( + OldPrefix, NewPrefix, + // TODO: Add support for optional native object path in + // thinlto_prefix_replace option to match lld. + /*NativeObjectPrefix=*/"", options::thinlto_emit_imports_files, + LinkedObjectsFile, OnIndexWrite); } else { Backend = createInProcessThinBackend( llvm::heavyweight_hardware_concurrency(options::Parallelism)); diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -320,11 +320,12 @@ ThinBackend Backend; if (ThinLTODistributedIndexes) - Backend = - createWriteIndexesThinBackend(/* OldPrefix */ "", - /* NewPrefix */ "", ThinLTOEmitImports, - /* LinkedObjectsFile */ nullptr, - /* OnWrite */ {}); + Backend = createWriteIndexesThinBackend(/*OldPrefix=*/"", + /*NewPrefix=*/"", + /*NativeObjectPrefix=*/"", + ThinLTOEmitImports, + /*LinkedObjectsFile=*/nullptr, + /*OnWrite=*/{}); else Backend = createInProcessThinBackend( llvm::heavyweight_hardware_concurrency(Threads),