Index: lld/COFF/Config.h =================================================================== --- lld/COFF/Config.h +++ lld/COFF/Config.h @@ -220,14 +220,21 @@ // Used for /thinlto-prefix-replace: // Replace the prefix in paths generated for ThinLTO, replacing - // thinLTOPrefixReplaceOld with thinLTOPrefixReplaceNew. If + // thinLTOPrefixReplaceFullBitcode with thinLTOPrefixReplaceOutput. 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; + // thinLTOPrefixReplaceNativeObject, instead of thinLTOPrefixReplaceOutput. + // If thinLTOPrefixReplaceMinimizedBitcode, replace the prefix of the + // minimized thin link input bitcode files, + // thinLTOPrefixReplaceMinimizedBitcode, with thinLTOPrefixReplaceFullBitcode, + // when the bitcode path is written to output index and imports files, + // allowing minimized thin link input bitcode files to be in a different + // directory as the full bitcode files + llvm::StringRef thinLTOPrefixReplaceFullBitcode; + llvm::StringRef thinLTOPrefixReplaceOutput; llvm::StringRef thinLTOPrefixReplaceNativeObject; + llvm::StringRef thinLTOPrefixReplaceMinimizedBitcode; // Used for /thinlto-object-suffix-replace: std::pair thinLTOObjectSuffixReplace; Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -91,12 +91,13 @@ return ret; } -// Parse options of the form "old;new[;extra]". -static std::tuple +// Parse options of the form "old;new[;extra][;extra2]". +static std::tuple getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { auto [oldDir, second] = getOldNewOptions(args, id); - auto [newDir, extraDir] = second.split(';'); - return {oldDir, newDir, extraDir}; + auto [newDir, third] = second.split(';'); + auto [extraDir, extraDir2] = third.split(';'); + return {oldDir, newDir, extraDir, extraDir2}; } // Drop directory components and replace extension with @@ -1893,8 +1894,10 @@ args.hasArg(OPT_thinlto_index_only_arg); config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_arg); - std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, - config->thinLTOPrefixReplaceNativeObject) = + std::tie(config->thinLTOPrefixReplaceFullBitcode, + config->thinLTOPrefixReplaceOutput, + config->thinLTOPrefixReplaceNativeObject, + config->thinLTOPrefixReplaceMinimizedBitcode) = getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace); Index: lld/COFF/InputFiles.cpp =================================================================== --- lld/COFF/InputFiles.cpp +++ lld/COFF/InputFiles.cpp @@ -996,10 +996,16 @@ bool lazy) : InputFile(ctx, BitcodeKind, mb, lazy) { std::string path = mb.getBufferIdentifier().str(); - if (ctx.config.thinLTOIndexOnly) + if (ctx.config.thinLTOIndexOnly) { path = replaceThinLTOSuffix(mb.getBufferIdentifier(), ctx.config.thinLTOObjectSuffixReplace.first, ctx.config.thinLTOObjectSuffixReplace.second); + if (!ctx.config.thinLTOPrefixReplaceMinimizedBitcode.empty()) { + path = lto::getThinLTOReplacePathPrefix( + path, ctx.config.thinLTOPrefixReplaceMinimizedBitcode.str(), + ctx.config.thinLTOPrefixReplaceFullBitcode.str()); + } + } // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this Index: lld/COFF/LTO.h =================================================================== --- lld/COFF/LTO.h +++ lld/COFF/LTO.h @@ -54,7 +54,7 @@ std::unique_ptr indexFile; llvm::DenseSet thinIndices; - std::string getThinLTOOutputFile(StringRef path); + std::string getThinLTOReplacePathPrefix(StringRef path); llvm::lto::Config createConfig(); COFFLinkerContext &ctx; Index: lld/COFF/LTO.cpp =================================================================== --- lld/COFF/LTO.cpp +++ lld/COFF/LTO.cpp @@ -54,10 +54,11 @@ return ret; } -std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) { - return lto::getThinLTOOutputFile( - std::string(path), std::string(ctx.config.thinLTOPrefixReplaceOld), - std::string(ctx.config.thinLTOPrefixReplaceNew)); +std::string BitcodeCompiler::getThinLTOReplacePathPrefix(StringRef path) { + return lto::getThinLTOReplacePathPrefix( + std::string(path), + std::string(ctx.config.thinLTOPrefixReplaceFullBitcode), + std::string(ctx.config.thinLTOPrefixReplaceOutput)); } lto::Config BitcodeCompiler::createConfig() { @@ -114,8 +115,8 @@ if (ctx.config.thinLTOIndexOnly) { auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); }; backend = lto::createWriteIndexesThinBackend( - std::string(ctx.config.thinLTOPrefixReplaceOld), - std::string(ctx.config.thinLTOPrefixReplaceNew), + std::string(ctx.config.thinLTOPrefixReplaceFullBitcode), + std::string(ctx.config.thinLTOPrefixReplaceOutput), std::string(ctx.config.thinLTOPrefixReplaceNativeObject), ctx.config.thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite); } else { @@ -194,7 +195,7 @@ // Emit empty index files for non-indexed files for (StringRef s : thinIndices) { - std::string path = getThinLTOOutputFile(s); + std::string path = getThinLTOReplacePathPrefix(s); openFile(path + ".thinlto.bc"); if (ctx.config.thinLTOEmitImportsFiles) openFile(path + ".imports"); Index: lld/ELF/Config.h =================================================================== --- lld/ELF/Config.h +++ lld/ELF/Config.h @@ -177,9 +177,25 @@ StringRef zCetReport = "none"; llvm::StringRef ltoBasicBlockSections; std::pair thinLTOObjectSuffixReplace; - llvm::StringRef thinLTOPrefixReplaceOld; - llvm::StringRef thinLTOPrefixReplaceNew; + + // Used for /thinlto-prefix-replace: + // Replace the prefix in paths generated for ThinLTO, replacing + // thinLTOPrefixReplaceFullBitcode with thinLTOPrefixReplaceOutput. 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 thinLTOPrefixReplaceOutput. + // If thinLTOPrefixReplaceMinimizedBitcode, replace the prefix of the + // minimized thin link input bitcode files, + // thinLTOPrefixReplaceMinimizedBitcode, with thinLTOPrefixReplaceFullBitcode, + // when the bitcode path is written to output index and imports files, + // allowing minimized thin link input bitcode files to be in a different + // directory as the full bitcode files + llvm::StringRef thinLTOPrefixReplaceFullBitcode; + llvm::StringRef thinLTOPrefixReplaceOutput; llvm::StringRef thinLTOPrefixReplaceNativeObject; + llvm::StringRef thinLTOPrefixReplaceMinimizedBitcode; + std::string rpath; llvm::SmallVector versionDefinitions; llvm::SmallVector auxiliaryList; Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -1024,12 +1024,13 @@ return ret; } -// Parse options of the form "old;new[;extra]". -static std::tuple +// Parse options of the form "old;new[;extra][;extra2]". +static std::tuple getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { auto [oldDir, second] = getOldNewOptions(args, id); - auto [newDir, extraDir] = second.split(';'); - return {oldDir, newDir, extraDir}; + auto [newDir, third] = second.split(';'); + auto [extraDir, extraDir2] = third.split(';'); + return {oldDir, newDir, extraDir, extraDir2}; } // Parse the symbol ordering file and warn for any duplicate entries. @@ -1258,8 +1259,10 @@ config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); - std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, - config->thinLTOPrefixReplaceNativeObject) = + std::tie(config->thinLTOPrefixReplaceFullBitcode, + config->thinLTOPrefixReplaceOutput, + config->thinLTOPrefixReplaceNativeObject, + config->thinLTOPrefixReplaceMinimizedBitcode) = getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq); if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) { if (args.hasArg(OPT_thinlto_object_suffix_replace_eq)) Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -1581,8 +1581,14 @@ this->lazy = lazy; std::string path = mb.getBufferIdentifier().str(); - if (config->thinLTOIndexOnly) + if (config->thinLTOIndexOnly) { path = replaceThinLTOSuffix(mb.getBufferIdentifier()); + if (!config->thinLTOPrefixReplaceMinimizedBitcode.empty()) { + path = lto::getThinLTOReplacePathPrefix( + path, config->thinLTOPrefixReplaceMinimizedBitcode.str(), + config->thinLTOPrefixReplaceFullBitcode.str()); + } + } // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this Index: lld/ELF/LTO.cpp =================================================================== --- lld/ELF/LTO.cpp +++ lld/ELF/LTO.cpp @@ -66,10 +66,11 @@ return openFile(file); } -static std::string getThinLTOOutputFile(StringRef modulePath) { - return lto::getThinLTOOutputFile( - std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld), - std::string(config->thinLTOPrefixReplaceNew)); +static std::string getThinLTOReplacePathPrefix(StringRef modulePath) { + return lto::getThinLTOReplacePathPrefix( + std::string(modulePath), + std::string(config->thinLTOPrefixReplaceFullBitcode), + std::string(config->thinLTOPrefixReplaceOutput)); } static lto::Config createConfig() { @@ -196,8 +197,8 @@ auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); }; if (config->thinLTOIndexOnly) { backend = lto::createWriteIndexesThinBackend( - std::string(config->thinLTOPrefixReplaceOld), - std::string(config->thinLTOPrefixReplaceNew), + std::string(config->thinLTOPrefixReplaceFullBitcode), + std::string(config->thinLTOPrefixReplaceOutput), std::string(config->thinLTOPrefixReplaceNativeObject), config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite); } else { @@ -302,7 +303,7 @@ if (linkedBitCodeFiles.contains(f->getName())) continue; std::string path = - replaceThinLTOSuffix(getThinLTOOutputFile(f->obj->getName())); + replaceThinLTOSuffix(getThinLTOReplacePathPrefix(f->obj->getName())); std::unique_ptr os = openFile(path + ".thinlto.bc"); if (!os) continue; @@ -344,7 +345,7 @@ // Emit empty index files for non-indexed files but not in single-module mode. if (config->thinLTOModulesToCompile.empty()) { for (StringRef s : thinIndices) { - std::string path = getThinLTOOutputFile(s); + std::string path = getThinLTOReplacePathPrefix(s); openFile(path + ".thinlto.bc"); if (config->thinLTOEmitImportsFiles) openFile(path + ".imports"); Index: lld/MachO/Config.h =================================================================== --- lld/MachO/Config.h +++ lld/MachO/Config.h @@ -173,9 +173,25 @@ llvm::StringRef thinLTOCacheDir; llvm::StringRef thinLTOIndexOnlyArg; std::pair thinLTOObjectSuffixReplace; - llvm::StringRef thinLTOPrefixReplaceOld; - llvm::StringRef thinLTOPrefixReplaceNew; + + // Used for /thinlto-prefix-replace: + // Replace the prefix in paths generated for ThinLTO, replacing + // thinLTOPrefixReplaceFullBitcode with thinLTOPrefixReplaceOutput. 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 thinLTOPrefixReplaceOutput. + // If thinLTOPrefixReplaceMinimizedBitcode, replace the prefix of the + // minimized thin link input bitcode files, + // thinLTOPrefixReplaceMinimizedBitcode, with thinLTOPrefixReplaceFullBitcode, + // when the bitcode path is written to output index and imports files, + // allowing minimized thin link input bitcode files to be in a different + // directory as the full bitcode files + llvm::StringRef thinLTOPrefixReplaceFullBitcode; + llvm::StringRef thinLTOPrefixReplaceOutput; llvm::StringRef thinLTOPrefixReplaceNativeObject; + llvm::StringRef thinLTOPrefixReplaceMinimizedBitcode; + bool deadStripDylibs = false; bool demangle = false; bool deadStrip = false; Index: lld/MachO/Driver.cpp =================================================================== --- lld/MachO/Driver.cpp +++ lld/MachO/Driver.cpp @@ -868,12 +868,13 @@ return ret; } -// Parse options of the form "old;new[;extra]". -static std::tuple +// Parse options of the form "old;new[;extra][;extra2]". +static std::tuple getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) { auto [oldDir, second] = getOldNewOptions(args, id); - auto [newDir, extraDir] = second.split(';'); - return {oldDir, newDir, extraDir}; + auto [newDir, third] = second.split(';'); + auto [extraDir, extraDir2] = third.split(';'); + return {oldDir, newDir, extraDir, extraDir2}; } static void parseClangOption(StringRef opt, const Twine &msg) { @@ -1586,8 +1587,10 @@ config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); config->thinLTOObjectSuffixReplace = getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); - std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew, - config->thinLTOPrefixReplaceNativeObject) = + std::tie(config->thinLTOPrefixReplaceFullBitcode, + config->thinLTOPrefixReplaceOutput, + config->thinLTOPrefixReplaceNativeObject, + config->thinLTOPrefixReplaceMinimizedBitcode) = getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq); if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) { if (args.hasArg(OPT_thinlto_object_suffix_replace_eq)) Index: lld/MachO/InputFiles.cpp =================================================================== --- lld/MachO/InputFiles.cpp +++ lld/MachO/InputFiles.cpp @@ -2194,8 +2194,14 @@ : InputFile(BitcodeKind, mb, lazy), forceHidden(forceHidden) { this->archiveName = std::string(archiveName); std::string path = mb.getBufferIdentifier().str(); - if (config->thinLTOIndexOnly) + if (config->thinLTOIndexOnly) { path = replaceThinLTOSuffix(mb.getBufferIdentifier()); + if (!config->thinLTOPrefixReplaceMinimizedBitcode.empty()) { + path = lto::getThinLTOReplacePathPrefix( + path, config->thinLTOPrefixReplaceMinimizedBitcode.str(), + config->thinLTOPrefixReplaceFullBitcode.str()); + } + } // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two members with the same name are provided, this causes a Index: lld/MachO/LTO.cpp =================================================================== --- lld/MachO/LTO.cpp +++ lld/MachO/LTO.cpp @@ -45,10 +45,11 @@ return ret; } -static std::string getThinLTOOutputFile(StringRef modulePath) { - return lto::getThinLTOOutputFile( - std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld), - std::string(config->thinLTOPrefixReplaceNew)); +static std::string getThinLTOReplacePathPrefix(StringRef modulePath) { + return lto::getThinLTOReplacePathPrefix( + std::string(modulePath), + std::string(config->thinLTOPrefixReplaceFullBitcode), + std::string(config->thinLTOPrefixReplaceOutput)); } static lto::Config createConfig() { @@ -99,8 +100,8 @@ auto onIndexWrite = [&](StringRef S) { thinIndices.erase(S); }; if (config->thinLTOIndexOnly) { backend = lto::createWriteIndexesThinBackend( - std::string(config->thinLTOPrefixReplaceOld), - std::string(config->thinLTOPrefixReplaceNew), + std::string(config->thinLTOPrefixReplaceFullBitcode), + std::string(config->thinLTOPrefixReplaceOutput), std::string(config->thinLTOPrefixReplaceNativeObject), config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite); } else { @@ -181,7 +182,7 @@ if (linkedBitCodeFiles.contains(f->getName())) continue; std::string path = - replaceThinLTOSuffix(getThinLTOOutputFile(f->obj->getName())); + replaceThinLTOSuffix(getThinLTOReplacePathPrefix(f->obj->getName())); std::unique_ptr os = openFile(path + ".thinlto.bc"); if (!os) continue; @@ -223,7 +224,7 @@ // Emit empty index files for non-indexed files for (StringRef s : thinIndices) { - std::string path = getThinLTOOutputFile(s); + std::string path = getThinLTOReplacePathPrefix(s); openFile(path + ".thinlto.bc"); if (config->thinLTOEmitImportsFiles) openFile(path + ".imports"); Index: lld/test/COFF/thinlto-minimized-bitcode-prefix-replace.ll =================================================================== --- /dev/null +++ lld/test/COFF/thinlto-minimized-bitcode-prefix-replace.ll @@ -0,0 +1,38 @@ +; REQUIRES: x86 +;; Test to make sure the thinlto-prefix-replace option can replace the +;; prefix of minimized bitcode files +; RUN: rm -rf %t && mkdir -p %t/minimized %t/full %t/indexing + +;; Generate bitcode file with summary, as well as a minimized bitcode without +; the debug metadata for the thin link. +; RUN: opt -thinlto-bc %s -thin-link-bitcode-file=%t/minimized/1.obj -o %t/full/1.obj + +;; First perform the thin link on the normal bitcode file, and save the +;; resulting index. +; RUN: lld-link -entry:main -thinlto-index-only -thinlto-prefix-replace:"%t/full;%t/indexing" %t/full/1.obj -out:%t/t.exe +; RUN: cp %t/indexing/1.obj.thinlto.bc %t/indexing/1.obj.thinlto.bc.orig + +;; Next perform the thin link on the minimized bitcode file, and compare dump +;; of the resulting index to the above dump to ensure they are identical. +;; Make sure it isn't inadvertently using the regular bitcode file. +; RUN: rm -f %t/full/1.obj +; RUN: lld-link -entry:main -thinlto-index-only -thinlto-prefix-replace:"%t/full;%t/indexing;;%t/minimized" \ +; RUN: %t/minimized/1.obj -out:%t/t.exe +; RUN: cmp %t/indexing/1.obj.thinlto.bc.orig %t/indexing/1.obj.thinlto.bc +;; Make sure the third string to thinlto-prefix-replace does not affect the test +; RUN: lld-link -entry:main -thinlto-index-only:"%t/unused" -thinlto-prefix-replace:"%t/full;%t/indexing;%t/unused;%t/minimized" \ +; RUN: %t/minimized/1.obj -out:%t/t.exe +; RUN: cmp %t/indexing/1.obj.thinlto.bc.orig %t/indexing/1.obj.thinlto.bc + +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" + +define void @main() { +entry: + ret void +} + +!llvm.dbg.cu = !{} + +!1 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.module.flags = !{!1} \ No newline at end of file Index: lld/test/ELF/lto/thinlto-minimized-bitcode-prefix-replace.ll =================================================================== --- /dev/null +++ lld/test/ELF/lto/thinlto-minimized-bitcode-prefix-replace.ll @@ -0,0 +1,51 @@ +; REQUIRES: x86 +;; Test to make sure the thinlto-object-suffix-replace option is handled +;; correctly. +; RUN: rm -rf %t && mkdir -p %t/minimized %t/full %t/indexing && cd %t + +;; Generate bitcode file with summary, as well as a minimized bitcode without +; the debug metadata for the thin link. +; RUN: opt --thinlto-bc %s -thin-link-bitcode-file=1.thinlink.bc -o 1.o + +;; First perform the thin link on the normal bitcode file, and save the +;; resulting index. +; RUN: ld.lld --plugin-opt=thinlto-index-only -shared 1.o -o 3 +; RUN: cp 1.o.thinlto.bc 1.o.thinlto.bc.orig + +;; Next perform the thin link on the minimized bitcode file, and compare dump +;; of the resulting index to the above dump to ensure they are identical. +; RUN: rm -f 1.o.thinlto.bc +;; Make sure it isn't inadvertently using the regular bitcode file. +; RUN: rm -f 1.o +; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-object-suffix-replace=".thinlink.bc;.o" \ +; RUN: -shared 1.thinlink.bc -o 3 +; RUN: cmp 1.o.thinlto.bc.orig 1.o.thinlto.bc +;; Also check that this works without the --plugin-opt= prefix. +; RUN: ld.lld --thinlto-index-only --thinlto-object-suffix-replace=".thinlink.bc;.o" \ +; RUN: -shared 1.thinlink.bc -o 3 +; RUN: cmp 1.o.thinlto.bc.orig 1.o.thinlto.bc + +;; Ensure lld generates error if object suffix replace option does not have 'old;new' format +; RUN: rm -f 1.o.thinlto.bc +; RUN: not ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-object-suffix-replace="abc:def" -shared 1.thinlink.bc \ +; RUN: -o 3 2>&1 | FileCheck %s --check-prefix=ERR1 +; ERR1: --plugin-opt=thinlto-object-suffix-replace= expects 'old;new' format, but got abc:def + +;; If filename does not end with old suffix, no suffix change should occur, +;; so ".thinlto.bc" will simply be appended to the input file name. +; RUN: rm -f 1.thinlink.bc.thinlto.bc +; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-object-suffix-replace=".abc;.o" -shared 1.thinlink.bc -o /dev/null +; RUN: ls 1.thinlink.bc.thinlto.bc + +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" + +define void @f() { +entry: + ret void +} + +!llvm.dbg.cu = !{} + +!1 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.module.flags = !{!1} Index: lld/test/MachO/thinlto-minimized-bitcode-prefix-replace.ll =================================================================== --- /dev/null +++ lld/test/MachO/thinlto-minimized-bitcode-prefix-replace.ll @@ -0,0 +1,38 @@ +; REQUIRES: x86 +;; Test to make sure the thinlto-prefix-replace option can replace the +;; prefix of minimized bitcode files +; RUN: rm -rf %t && mkdir -p %t/minimized %t/full %t/indexing + +;; Generate bitcode file with summary, as well as a minimized bitcode without +; the debug metadata for the thin link. +; RUN: opt --thinlto-bc %s -thin-link-bitcode-file=%t/minimized/1.o -o %t/full/1.o + +;; First perform the thin link on the normal bitcode file, and save the +;; resulting index. +; RUN: %lld --thinlto-index-only --thinlto-prefix-replace="%t/full;%t/indexing" -dylib %t/full/1.o -o 3 +; RUN: cp %t/indexing/1.o.thinlto.bc %t/indexing/1.o.thinlto.bc.orig + +;; Next perform the thin link on the minimized bitcode file, and compare dump +;; of the resulting index to the above dump to ensure they are identical. +;; Make sure it isn't inadvertently using the regular bitcode file. +; RUN: rm -f %t/full/1.o +; RUN: %lld --thinlto-index-only --thinlto-prefix-replace="%t/full;%t/indexing;;%t/minimized" \ +; RUN: -dylib %t/minimized/1.o -o 3 +; RUN: cmp %t/indexing/1.o.thinlto.bc.orig %t/indexing/1.o.thinlto.bc +;; Make sure the third string to thinlto-prefix-replace does not affect the test +; RUN: %lld --thinlto-index-only="%t/unused" --thinlto-prefix-replace="%t/full;%t/indexing;%t/unused;%t/minimized" \ +; RUN: -dylib %t/minimized/1.o -o 3 +; RUN: cmp %t/indexing/1.o.thinlto.bc.orig %t/indexing/1.o.thinlto.bc + +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 @f() { +entry: + ret void +} + +!llvm.dbg.cu = !{} + +!1 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.module.flags = !{!1} \ No newline at end of file Index: llvm/include/llvm/LTO/LTO.h =================================================================== --- llvm/include/llvm/LTO/LTO.h +++ llvm/include/llvm/LTO/LTO.h @@ -78,9 +78,9 @@ /// Given the original \p Path to an output file, replace any path /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the /// resulting directory if it does not yet exist. -std::string getThinLTOOutputFile(const std::string &Path, - const std::string &OldPrefix, - const std::string &NewPrefix); +std::string getThinLTOReplacePathPrefix(const std::string &Path, + const std::string &OldPrefix, + const std::string &NewPrefix); /// Setup optimization remarks. Expected> setupLLVMOptimizationRemarks( Index: llvm/lib/LTO/LTO.cpp =================================================================== --- llvm/lib/LTO/LTO.cpp +++ llvm/lib/LTO/LTO.cpp @@ -1403,9 +1403,9 @@ // Given the original \p Path to an output file, replace any path // prefix matching \p OldPrefix with \p NewPrefix. Also, create the // resulting directory if it does not yet exist. -std::string lto::getThinLTOOutputFile(const std::string &Path, - const std::string &OldPrefix, - const std::string &NewPrefix) { +std::string lto::getThinLTOReplacePathPrefix(const std::string &Path, + const std::string &OldPrefix, + const std::string &NewPrefix) { if (OldPrefix.empty() && NewPrefix.empty()) return Path; SmallString<128> NewPath(Path); @@ -1445,13 +1445,13 @@ const std::map &ResolvedODR, MapVector &ModuleMap) override { StringRef ModulePath = BM.getModuleIdentifier(); - std::string NewModulePath = - getThinLTOOutputFile(std::string(ModulePath), OldPrefix, NewPrefix); + std::string NewModulePath = getThinLTOReplacePathPrefix( + std::string(ModulePath), OldPrefix, NewPrefix); if (LinkedObjectsFile) { std::string ObjectPrefix = NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix; - std::string LinkedObjectsFilePath = getThinLTOOutputFile( + std::string LinkedObjectsFilePath = getThinLTOReplacePathPrefix( std::string(ModulePath), OldPrefix, ObjectPrefix); *LinkedObjectsFile << LinkedObjectsFilePath << '\n'; } Index: llvm/tools/gold/gold-plugin.cpp =================================================================== --- llvm/tools/gold/gold-plugin.cpp +++ llvm/tools/gold/gold-plugin.cpp @@ -1053,6 +1053,8 @@ // will locate the full bitcode files for compiling/importing. std::string Identifier = getThinLTOObjectFileName(F.name, OldSuffix, NewSuffix); + // TODO: Add support for optional minimized bitcode file path in + // thinlto_prefix_replace option to match lld. auto ObjFilename = ObjectToIndexFileState.insert({Identifier, false}); assert(ObjFilename.second); if (const void *View = getSymbolsAndView(F))