diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index 728e15a6976ab..c39c6e6ea74ba 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -12,6 +12,7 @@ #include "SymbolTable.h" #include "Symbols.h" #include "lld/Common/Args.h" +#include "lld/Common/CommonLinkerContext.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Filesystem.h" #include "lld/Common/Strings.h" @@ -28,6 +29,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include #include #include @@ -305,6 +307,7 @@ std::vector BitcodeCompiler::compile() { unsigned maxTasks = ltoObj->getMaxTasks(); buf.resize(maxTasks); files.resize(maxTasks); + filenames.resize(maxTasks); // The --thinlto-cache-dir option specifies the path to a directory in which // to cache native object files for ThinLTO incremental builds. If a path was @@ -315,13 +318,15 @@ std::vector BitcodeCompiler::compile() { [&](size_t task, const Twine &moduleName, std::unique_ptr mb) { files[task] = std::move(mb); + filenames[task] = moduleName.str(); })); if (!ctx.bitcodeFiles.empty()) checkError(ltoObj->run( [&](size_t task, const Twine &moduleName) { + buf[task].first = moduleName.str(); return std::make_unique( - std::make_unique(buf[task])); + std::make_unique(buf[task].second)); }, cache)); @@ -340,7 +345,7 @@ std::vector BitcodeCompiler::compile() { if (config->thinLTOIndexOnly) { if (!config->ltoObjPath.empty()) - saveBuffer(buf[0], config->ltoObjPath); + saveBuffer(buf[0].second, config->ltoObjPath); // ThinLTO with index only option is required to generate only the index // files. After that, we exit from linker and ThinLTO backend runs in a @@ -354,32 +359,57 @@ std::vector BitcodeCompiler::compile() { pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy, files); if (!config->ltoObjPath.empty()) { - saveBuffer(buf[0], config->ltoObjPath); + saveBuffer(buf[0].second, config->ltoObjPath); for (unsigned i = 1; i != maxTasks; ++i) - saveBuffer(buf[i], config->ltoObjPath + Twine(i)); - } - - if (config->saveTempsArgs.contains("prelink")) { - if (!buf[0].empty()) - saveBuffer(buf[0], config->outputFile + ".lto.o"); - for (unsigned i = 1; i != maxTasks; ++i) - saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); - } - - if (config->ltoEmitAsm) { - saveBuffer(buf[0], config->outputFile); - for (unsigned i = 1; i != maxTasks; ++i) - saveBuffer(buf[i], config->outputFile + Twine(i)); - return {}; + saveBuffer(buf[i].second, config->ltoObjPath + Twine(i)); } + bool savePrelink = config->saveTempsArgs.contains("prelink"); std::vector ret; - for (unsigned i = 0; i != maxTasks; ++i) - if (!buf[i].empty()) - ret.push_back(createObjFile(MemoryBufferRef(buf[i], "lto.tmp"))); + const char *ext = config->ltoEmitAsm ? ".s" : ".o"; + for (unsigned i = 0; i != maxTasks; ++i) { + StringRef bitcodeFilePath; + StringRef objBuf; + if (files[i]) { + // When files[i] is not null, we get the native relocatable file from the + // cache. filenames[i] contains the original BitcodeFile's identifier. + objBuf = files[i]->getBuffer(); + bitcodeFilePath = filenames[i]; + } else { + // Get the native relocatable file after in-process LTO compilation. + objBuf = buf[i].second; + bitcodeFilePath = buf[i].first; + } + if (objBuf.empty()) + continue; - for (std::unique_ptr &file : files) - if (file) - ret.push_back(createObjFile(*file)); + // If the input bitcode file is path/to/x.o and -o specifies a.out, the + // corresponding native relocatable file path will look like: + // path/to/a.out.lto.x.o. + StringRef ltoObjName; + if (bitcodeFilePath == "ld-temp.o") { + ltoObjName = + saver().save(Twine(config->outputFile) + ".lto" + + (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ext); + } else { + StringRef directory = sys::path::parent_path(bitcodeFilePath); + // For an archive member, which has an identifier like "d/a.a(coll.o at + // 8)" (see BitcodeFile::BitcodeFile), use the filename; otherwise, use + // the stem (d/a.o => a). + StringRef baseName = bitcodeFilePath.ends_with(")") + ? sys::path::filename(bitcodeFilePath) + : sys::path::stem(bitcodeFilePath); + StringRef outputFileBaseName = sys::path::filename(config->outputFile); + SmallString<256> path; + sys::path::append(path, directory, + outputFileBaseName + ".lto." + baseName + ext); + sys::path::remove_dots(path, true); + ltoObjName = saver().save(path.str()); + } + if (savePrelink || config->ltoEmitAsm) + saveBuffer(buf[i].second, ltoObjName); + if (!config->ltoEmitAsm) + ret.push_back(createObjFile(MemoryBufferRef(objBuf, ltoObjName))); + } return ret; } diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h index 7ab654101f248..405e7f4a649e8 100644 --- a/lld/ELF/LTO.h +++ b/lld/ELF/LTO.h @@ -46,8 +46,10 @@ class BitcodeCompiler { private: std::unique_ptr ltoObj; - std::vector> buf; + // An array of (module name, native relocatable file content) pairs. + SmallVector>, 0> buf; std::vector> files; + SmallVector filenames; llvm::DenseSet usedStartStop; std::unique_ptr indexFile; llvm::DenseSet thinIndices; diff --git a/lld/test/ELF/common-archive-lookup.s b/lld/test/ELF/common-archive-lookup.s index 297d3d9b6f36e..a30d0f18d01ad 100644 --- a/lld/test/ELF/common-archive-lookup.s +++ b/lld/test/ELF/common-archive-lookup.s @@ -61,10 +61,12 @@ # RUN: ld.lld --no-fortran-common -o 11 main.o --start-lib 1.o strong_data_only.o --end-lib # RUN: llvm-readobj --syms 11 | FileCheck --check-prefix=NFC %s -# RUN: ld.lld -o - main.o 4.a --fortran-common --lto-emit-asm | FileCheck --check-prefix=ASM %s +# RUN: ld.lld -o out main.o 4.a --fortran-common --lto-emit-asm +# RUN: FileCheck --check-prefix=ASM %s < out.lto.s -# RUN: ld.lld -o - main.o --start-lib 1.bc 2.bc --end-lib --fortran-common --lto-emit-asm | \ -# RUN: FileCheck --check-prefix=ASM %s +# RUN: rm out.lto.s +# RUN: ld.lld -o out main.o --start-lib 1.bc 2.bc --end-lib --fortran-common --lto-emit-asm +# RUN: FileCheck --check-prefix=ASM %s < out.lto.s ## COMMON overrides weak. Don't extract 3.bc which provides a weak definition. # RUN: ld.lld -o /dev/null main.o --start-lib 1.bc 3.bc --end-lib -y block | FileCheck --check-prefix=LTO_WEAK %s diff --git a/lld/test/ELF/lto/cache.ll b/lld/test/ELF/lto/cache.ll index 95c68ab2315e6..aa1729853d091 100644 --- a/lld/test/ELF/lto/cache.ll +++ b/lld/test/ELF/lto/cache.ll @@ -53,10 +53,10 @@ ; RUN: rm -fr cache && mkdir cache ; RUN: ld.lld --thinlto-cache-dir=cache --save-temps -o out b.bc a.bc -M | FileCheck %s --check-prefix=MAP -; RUN: ls out1.lto.o a.bc.0.preopt.bc b.bc.0.preopt.bc +; RUN: ls out.lto.a.o a.bc.0.preopt.bc b.bc.0.preopt.bc -; MAP: llvmcache-{{.*}}:(.text) -; MAP: llvmcache-{{.*}}:(.text) +; MAP: out.lto.b.o:(.text) +; MAP: out.lto.a.o:(.text) ;; Check that mllvm options participate in the cache key ; RUN: rm -rf cache && mkdir cache diff --git a/lld/test/ELF/lto/comdat-mixed-archive.test b/lld/test/ELF/lto/comdat-mixed-archive.test index d7ea4eb18c72e..88e294ed98722 100644 --- a/lld/test/ELF/lto/comdat-mixed-archive.test +++ b/lld/test/ELF/lto/comdat-mixed-archive.test @@ -35,8 +35,8 @@ TRACE-NEXT: lib.a(obj.o): definition of bar TRACE-NEXT: lib.a(obj.o): reference to foo TRACE-NEXT: : reference to foo ;; The definition of "foo" is visible outside the LTO result. -TRACE-NEXT: lto.tmp: definition of foo -TRACE-NEXT: lto.tmp: reference to bar +TRACE-NEXT: {{.*}}.lto.o: definition of foo +TRACE-NEXT: {{.*}}.lto.o: reference to bar ;--- start.s .global _start, baz diff --git a/lld/test/ELF/lto/emit-asm.ll b/lld/test/ELF/lto/emit-asm.ll index 03cf32d904520..463b4fc3c5f62 100644 --- a/lld/test/ELF/lto/emit-asm.ll +++ b/lld/test/ELF/lto/emit-asm.ll @@ -1,13 +1,14 @@ ; REQUIRES: x86 ; RUN: rm -rf %t && mkdir %t && cd %t ; RUN: llvm-as %s -o a.bc -; RUN: ld.lld --lto-emit-asm -shared a.bc -o - | FileCheck %s -; RUN: ld.lld --plugin-opt=emit-asm --plugin-opt=lto-partitions=2 -shared a.bc -o out.s -; RUN: cat out.s out.s1 | FileCheck %s +; RUN: ld.lld --lto-emit-asm -shared a.bc -o out 2>&1 | count 0 +; RUN: FileCheck %s < out.lto.s +; RUN: ld.lld --plugin-opt=emit-asm --plugin-opt=lto-partitions=2 -shared a.bc -o out +; RUN: cat out.lto.s out.lto.1.s | FileCheck %s -; RUN: ld.lld --lto-emit-asm --save-temps -shared a.bc -o out.s -; RUN: FileCheck --input-file out.s %s -; RUN: llvm-dis out.s.0.4.opt.bc -o - | FileCheck --check-prefix=OPT %s +; RUN: ld.lld --lto-emit-asm --save-temps -shared a.bc -o out +; RUN: FileCheck --input-file out.lto.s %s +; RUN: llvm-dis out.0.4.opt.bc -o - | FileCheck --check-prefix=OPT %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lld/test/ELF/lto/exclude-libs-libcall.ll b/lld/test/ELF/lto/exclude-libs-libcall.ll index 3fdffb4276d9e..8e1d54853cc37 100644 --- a/lld/test/ELF/lto/exclude-libs-libcall.ll +++ b/lld/test/ELF/lto/exclude-libs-libcall.ll @@ -7,7 +7,7 @@ ; RUN: llvm-readelf --dyn-syms %t.so | FileCheck %s ; TRACE: {{.*}}/b.a(b.o): lazy definition of __divti3 -; TRACE-NEXT: lto.tmp: reference to __divti3 +; TRACE-NEXT: {{.*}}.lto.o: reference to __divti3 ; TRACE-NEXT: {{.*}}/b.a(b.o): definition of __divti3 ; CHECK: Symbol table '.dynsym' contains 2 entries: diff --git a/lld/test/ELF/lto/obj-path.ll b/lld/test/ELF/lto/obj-path.ll index 23b593bd36fa8..c0bb4addf2466 100644 --- a/lld/test/ELF/lto/obj-path.ll +++ b/lld/test/ELF/lto/obj-path.ll @@ -67,12 +67,12 @@ ;; Ensure lld emits empty combined module if specific obj-path. ; RUN: mkdir obj ; RUN: ld.lld --plugin-opt=obj-path=objpath.o -shared 1.bc d/2.bc -o obj/out --save-temps -; RUN: ls obj/out.lto.o obj/out1.lto.o obj/out2.lto.o +; RUN: ls obj/out.lto.o out.lto.1.o d/out.lto.2.o ;; Ensure lld does not emit empty combined module by default. ; RUN: rm -fr obj && mkdir obj ; RUN: ld.lld -shared 1.bc d/2.bc -o obj/out --save-temps -; RUN: ls obj/out*.lto.* | count 2 +; RUN: not test -e obj/out.lto.o ; EMPTY: file format elf64-x86-64 ; EMPTY-NOT: {{.}} diff --git a/lld/test/ELF/lto/parallel-internalize.ll b/lld/test/ELF/lto/parallel-internalize.ll index 9cd080360d396..a1511d6f6867d 100644 --- a/lld/test/ELF/lto/parallel-internalize.ll +++ b/lld/test/ELF/lto/parallel-internalize.ll @@ -4,7 +4,7 @@ ; RUN: ld.lld --lto-partitions=2 -save-temps -o out a.bc -e foo --lto-O0 ; RUN: llvm-readobj --symbols --dyn-syms out | FileCheck %s ; RUN: llvm-nm out.lto.o | FileCheck --check-prefix=CHECK0 %s -; RUN: llvm-nm out1.lto.o | FileCheck --check-prefix=CHECK1 %s +; RUN: llvm-nm out.lto.1.o | FileCheck --check-prefix=CHECK1 %s ; CHECK: Symbols [ ; CHECK-NEXT: Symbol { diff --git a/lld/test/ELF/lto/parallel.ll b/lld/test/ELF/lto/parallel.ll index c6c9a185677b8..6b2c352b0a965 100644 --- a/lld/test/ELF/lto/parallel.ll +++ b/lld/test/ELF/lto/parallel.ll @@ -3,7 +3,7 @@ ; RUN: llvm-as -o a.bc %s ; RUN: ld.lld --lto-partitions=2 -save-temps -o out a.bc -shared ; RUN: llvm-nm out.lto.o | FileCheck --check-prefix=CHECK0 %s -; RUN: llvm-nm out1.lto.o | FileCheck --check-prefix=CHECK1 %s +; RUN: llvm-nm out.lto.1.o | FileCheck --check-prefix=CHECK1 %s ; RUN: not ld.lld --lto-partitions=0 a.bc -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID %s ; INVALID: --lto-partitions: number of threads must be > 0 diff --git a/lld/test/ELF/lto/pseudo-probe-lto.ll b/lld/test/ELF/lto/pseudo-probe-lto.ll index 3840c7c2281c0..cabd69da33fe2 100644 --- a/lld/test/ELF/lto/pseudo-probe-lto.ll +++ b/lld/test/ELF/lto/pseudo-probe-lto.ll @@ -1,6 +1,7 @@ ; REQUIRES: x86 ; RUN: opt < %s -passes=pseudo-probe -function-sections -o %t.o -; RUN: ld.lld %t.o -shared --lto-emit-asm -o - | FileCheck %s +; RUN: ld.lld %t.o -shared --lto-emit-asm -o %t +; RUN: FileCheck %s < %t.lto.s 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-scei-ps4" diff --git a/lld/test/ELF/lto/save-temps-eq.ll b/lld/test/ELF/lto/save-temps-eq.ll index ed9c3970347f3..9befc99af9253 100644 --- a/lld/test/ELF/lto/save-temps-eq.ll +++ b/lld/test/ELF/lto/save-temps-eq.ll @@ -14,14 +14,14 @@ ;; Create the .all dir with save-temps saving everything, this will be used to compare ;; with the output from individualized save-temps later ; RUN: ld.lld main.o thin1.o --save-temps -o %t/all/a.out -; RUN: mv *.o.* %t/all +; RUN: mv a.out.lto.* *.o.*.bc %t/all ;; Sanity check that everything got moved ; RUN: ls | count 2 ;; Check precedence if both --save-temps and --save-temps= are present ; RUN: ld.lld main.o thin1.o --save-temps=preopt --save-temps --save-temps=\opt -o %t/all2/a.out ; RUN: cmp %t/all2/a.out %t/all/a.out -; RUN: mv *.o.* %t/all2 +; RUN: mv a.out.lto.* *.o.* %t/all2 ; RUN: ls | count 2 ; RUN: diff -r %t/all %t/all2 @@ -83,8 +83,8 @@ ;; Check prelink ; RUN: ld.lld main.o thin1.o --save-temps=prelink ; RUN: cmp %t/all/a.out a.out && rm -f a.out -; RUN: cp *.lto.o %t/subset2 -; RUN: mv *.lto.o %t/all3 +; RUN: cp a.out.lto.*.o %t/subset2 +; RUN: mv a.out.lto.*.o %t/all3 ; RUN: ls | count 2 ;; Check resolution @@ -104,7 +104,7 @@ ; RUN: cmp %t/all/a.out a.out && rm -f a.out ; RUN: mv *.0.preopt.* %t/subset ; RUN: mv *.4.opt* %t/subset -; RUN: mv *.lto.o %t/subset +; RUN: mv a.out.lto.*.o %t/subset ; RUN: ls | count 2 ; RUN: diff -r %t/subset2 %t/subset diff --git a/lld/test/ELF/lto/thin-archivecollision.ll b/lld/test/ELF/lto/thin-archivecollision.ll index da3d08801e96f..4fbb20d9c1280 100644 --- a/lld/test/ELF/lto/thin-archivecollision.ll +++ b/lld/test/ELF/lto/thin-archivecollision.ll @@ -9,21 +9,21 @@ ; RUN: llvm-ar rcS d/a.a d/coll.o e/coll.o ; RUN: ld.lld b.bc d/a.a -o out --save-temps ; RUN: llvm-nm out | FileCheck %s -; RUN: llvm-nm out2.lto.o | FileCheck %s --check-prefix=MOD2 -; RUN: llvm-nm out3.lto.o | FileCheck %s --check-prefix=MOD3 +;; d/out.lto.a.a(coll.o at 8).o out.lto.a.a(coll.o at 1916).o +; RUN: llvm-nm d/out.lto.a.a*at*.o | FileCheck %s --check-prefix=MOD2 ; Check we handle this case correctly even in presence of --whole-archive. -; RUN: rm out1.lto.o out2.lto.o out3.lto.o +; RUN: rm d/out.lto.a.a*at*.o ; RUN: ld.lld b.bc --whole-archive d/a.a -o out --save-temps ; RUN: llvm-nm out | FileCheck %s -; RUN: ls out1.lto.o out2.lto.o out3.lto.o +; RUN: llvm-nm d/out.lto.a.a*at*.o | FileCheck %s --check-prefix=MOD2 ; CHECK: T _start ; CHECK: T blah ; CHECK: T foo -; MOD2: T foo -; MOD3: T blah +; MOD2-DAG: T foo +; MOD2-DAG: T blah 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-scei-ps4" diff --git a/lld/test/ELF/lto/thinlto.ll b/lld/test/ELF/lto/thinlto.ll index f42a0323ff044..e0e2ca8e2e8ea 100644 --- a/lld/test/ELF/lto/thinlto.ll +++ b/lld/test/ELF/lto/thinlto.ll @@ -7,56 +7,56 @@ ; RUN: opt -module-summary %p/Inputs/thinlto.ll -o d/b.o ; First force single-threaded mode -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --thinlto-jobs=1 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ; Next force multi-threaded mode -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --thinlto-jobs=2 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ;; --plugin-opt=jobs= is an alias. -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --plugin-opt=jobs=2 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ;; --thinlto-jobs= defaults to --threads=. -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --threads=2 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ;; --thinlto-jobs= overrides --threads=. -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --threads=1 --plugin-opt=jobs=2 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ; Test with all threads, on all cores, on all CPU sockets -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --thinlto-jobs=all -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ; Test with many more threads than the system has -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: ld.lld -save-temps --thinlto-jobs=100 -shared a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ; Test with a bad value -; RUN: rm -f e/out1.lto.o e/out2.lto.o +; RUN: rm -f out.lto.a.o d/out.lto.b.o ; RUN: not ld.lld -save-temps --thinlto-jobs=foo -shared a.o d/b.o -o e/out 2>&1 | FileCheck %s --check-prefix=BAD-JOBS ; BAD-JOBS: error: --thinlto-jobs: invalid job count: foo ; Then check without --thinlto-jobs (which currently defaults to heavyweight_hardware_concurrency, meanning one thread per hardware core -- not SMT) ; RUN: ld.lld -shared -save-temps a.o d/b.o -o e/out -; RUN: llvm-nm e/out1.lto.o | FileCheck %s --check-prefix=NM1 -; RUN: llvm-nm e/out2.lto.o | FileCheck %s --check-prefix=NM2 +; RUN: llvm-nm out.lto.a.o | FileCheck %s --check-prefix=NM1 +; RUN: llvm-nm d/out.lto.b.o | FileCheck %s --check-prefix=NM2 ; Check that -save-temps is usable with thin archives ; RUN: mkdir dir