Index: ELF/CMakeLists.txt =================================================================== --- ELF/CMakeLists.txt +++ ELF/CMakeLists.txt @@ -11,7 +11,6 @@ ICF.cpp InputFiles.cpp InputSection.cpp - LTO.cpp LinkerScript.cpp MarkLive.cpp Mips.cpp Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -16,6 +16,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/raw_ostream.h" Index: ELF/Error.h =================================================================== --- ELF/Error.h +++ ELF/Error.h @@ -12,6 +12,8 @@ #include "lld/Core/LLVM.h" +#include "llvm/Support/Error.h" + namespace lld { namespace elf { @@ -31,6 +33,13 @@ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg, const Twine &Prefix); +inline void check(Error E, std::string Msg = "") { + handleAllErrors(std::move(E), [&](llvm::ErrorInfoBase &EIB) { + error(EIB.message().c_str()); + return Error::success(); + }); +} + template T check(ErrorOr E) { if (auto EC = E.getError()) fatal(EC.message()); Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -239,6 +239,7 @@ ArrayRef getSymbols() { return Symbols; } static bool shouldSkip(uint32_t Flags); std::unique_ptr Obj; + MemoryBufferRef getBuffer() { return MB; } private: std::vector Symbols; Index: ELF/LTO.h =================================================================== --- ELF/LTO.h +++ /dev/null @@ -1,54 +0,0 @@ -//===- LTO.h ----------------------------------------------------*- C++ -*-===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a way to combine bitcode files into one ELF -// file by compiling them using LLVM. -// -// If LTO is in use, your input files are not in regular ELF files -// but instead LLVM bitcode files. In that case, the linker has to -// convert bitcode files into the native format so that we can create -// an ELF file that contains native code. This file provides that -// functionality. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_ELF_LTO_H -#define LLD_ELF_LTO_H - -#include "lld/Core/LLVM.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/IR/Module.h" -#include "llvm/Linker/IRMover.h" - -namespace lld { -namespace elf { - -class BitcodeFile; -class InputFile; - -class BitcodeCompiler { -public: - BitcodeCompiler(); - void add(BitcodeFile &F); - std::vector> compile(); - -private: - std::vector> runSplitCodegen( - const std::function()> &TMFactory); - - std::unique_ptr Combined; - std::vector> OwningData; - llvm::StringSet<> InternalizedSyms; - llvm::StringSet<> AsmUndefinedRefs; -}; -} -} - -#endif Index: ELF/LTO.cpp =================================================================== --- ELF/LTO.cpp +++ /dev/null @@ -1,333 +0,0 @@ -//===- LTO.cpp ------------------------------------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LTO.h" -#include "Config.h" -#include "Driver.h" -#include "Error.h" -#include "InputFiles.h" -#include "Symbols.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/CGSCCPassManager.h" -#include "llvm/Analysis/LoopPassManager.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/CodeGen/CommandFlags.h" -#include "llvm/CodeGen/ParallelCG.h" -#include "llvm/IR/AutoUpgrade.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/LTO/legacy/UpdateCompilerUsed.h" -#include "llvm/Linker/IRMover.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/Support/StringSaver.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" - -using namespace llvm; -using namespace llvm::object; -using namespace llvm::ELF; - -using namespace lld; -using namespace lld::elf; - -// This is for use when debugging LTO. -static void saveBuffer(StringRef Buffer, const Twine &Path) { - std::error_code EC; - raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); - if (EC) - error(EC, "cannot create " + Path); - OS << Buffer; -} - -// This is for use when debugging LTO. -static void saveBCFile(Module &M, const Twine &Path) { - std::error_code EC; - raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); - if (EC) - error(EC, "cannot create " + Path); - WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ true); -} - -static void runNewCustomLtoPasses(Module &M, TargetMachine &TM) { - PassBuilder PB(&TM); - - AAManager AA; - - // Parse a custom AA pipeline if asked to. - if (!PB.parseAAPipeline(AA, Config->LtoAAPipeline)) { - error("Unable to parse AA pipeline description: " + Config->LtoAAPipeline); - return; - } - - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - - // Register the AA manager first so that our version is the one used. - FAM.registerPass([&] { return std::move(AA); }); - - // Register all the basic analyses with the managers. - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - - ModulePassManager MPM; - if (!Config->DisableVerify) - MPM.addPass(VerifierPass()); - - // Now, add all the passes we've been requested to. - if (!PB.parsePassPipeline(MPM, Config->LtoNewPmPasses)) { - error("unable to parse pass pipeline description: " + - Config->LtoNewPmPasses); - return; - } - - if (!Config->DisableVerify) - MPM.addPass(VerifierPass()); - MPM.run(M, MAM); -} - -static void runOldLtoPasses(Module &M, TargetMachine &TM) { - // Note that the gold plugin has a similar piece of code, so - // it is probably better to move this code to a common place. - legacy::PassManager LtoPasses; - LtoPasses.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis())); - PassManagerBuilder PMB; - PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM.getTargetTriple())); - PMB.Inliner = createFunctionInliningPass(); - PMB.VerifyInput = PMB.VerifyOutput = !Config->DisableVerify; - PMB.LoopVectorize = true; - PMB.SLPVectorize = true; - PMB.OptLevel = Config->LtoO; - PMB.populateLTOPassManager(LtoPasses); - LtoPasses.run(M); -} - -static void runLTOPasses(Module &M, TargetMachine &TM) { - if (!Config->LtoNewPmPasses.empty()) { - // The user explicitly asked for a set of passes to be run. - // This needs the new PM to work as there's no clean way to - // pass a set of passes to run in the legacy PM. - runNewCustomLtoPasses(M, TM); - if (HasError) - return; - } else { - // Run the 'default' set of LTO passes. This code still uses - // the legacy PM as the new one is not the default. - runOldLtoPasses(M, TM); - } - - if (Config->SaveTemps) - saveBCFile(M, Config->OutputFile + ".lto.opt.bc"); -} - -static bool shouldInternalize(const SmallPtrSet &Used, - Symbol *S, GlobalValue *GV) { - if (S->IsUsedInRegularObj || Used.count(GV)) - return false; - return !S->includeInDynsym(); -} - -BitcodeCompiler::BitcodeCompiler() - : Combined(new Module("ld-temp.o", Driver->Context)) {} - -static void undefine(Symbol *S) { - replaceBody(S, S->body()->getName(), STV_DEFAULT, S->body()->Type, - nullptr); -} - -static void handleUndefinedAsmRefs(const BasicSymbolRef &Sym, GlobalValue *GV, - StringSet<> &AsmUndefinedRefs) { - // GV associated => not an assembly symbol, bail out. - if (GV) - return; - - // This is an undefined reference to a symbol in asm. We put that in - // compiler.used, so that we can preserve it from being dropped from - // the output, without necessarily preventing its internalization. - SmallString<64> Name; - raw_svector_ostream OS(Name); - Sym.printName(OS); - AsmUndefinedRefs.insert(Name.str()); -} - -void BitcodeCompiler::add(BitcodeFile &F) { - std::unique_ptr Obj = std::move(F.Obj); - std::vector Keep; - unsigned BodyIndex = 0; - ArrayRef Syms = F.getSymbols(); - - Module &M = Obj->getModule(); - if (M.getDataLayoutStr().empty()) - fatal("invalid bitcode file: " + F.getName() + " has no datalayout"); - - // Discard non-compatible debug infos if necessary. - M.materializeMetadata(); - UpgradeDebugInfo(M); - - // If a symbol appears in @llvm.used, the linker is required - // to treat the symbol as there is a reference to the symbol - // that it cannot see. Therefore, we can't internalize. - SmallPtrSet Used; - collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false); - - for (const BasicSymbolRef &Sym : Obj->symbols()) { - uint32_t Flags = Sym.getFlags(); - GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); - if (GV && GV->hasAppendingLinkage()) - Keep.push_back(GV); - if (BitcodeFile::shouldSkip(Flags)) - continue; - Symbol *S = Syms[BodyIndex++]; - if (GV) - GV->setUnnamedAddr(S->HasUnnamedAddr ? GlobalValue::UnnamedAddr::Global - : GlobalValue::UnnamedAddr::None); - if (Flags & BasicSymbolRef::SF_Undefined) { - handleUndefinedAsmRefs(Sym, GV, AsmUndefinedRefs); - continue; - } - SymbolBody *B = S->body(); - if (B->File != &F) - continue; - - // We collect the set of symbols we want to internalize here - // and change the linkage after the IRMover executed, i.e. after - // we imported the symbols and satisfied undefined references - // to it. We can't just change linkage here because otherwise - // the IRMover will just rename the symbol. - if (GV && shouldInternalize(Used, S, GV)) - InternalizedSyms.insert(GV->getName()); - - // At this point we know that either the combined LTO object will provide a - // definition of a symbol, or we will internalize it. In either case, we - // need to undefine the symbol. In the former case, the real definition - // needs to be able to replace the original definition without conflicting. - // In the latter case, we need to allow the combined LTO object to provide a - // definition with the same name, for example when doing parallel codegen. - if (auto *C = dyn_cast(B)) { - if (auto *GO = dyn_cast(GV)) - GO->setAlignment(C->Alignment); - } else { - undefine(S); - } - - if (!GV) - // Module asm symbol. - continue; - - switch (GV->getLinkage()) { - default: - break; - case GlobalValue::LinkOnceAnyLinkage: - GV->setLinkage(GlobalValue::WeakAnyLinkage); - break; - case GlobalValue::LinkOnceODRLinkage: - GV->setLinkage(GlobalValue::WeakODRLinkage); - break; - } - - Keep.push_back(GV); - } - - IRMover Mover(*Combined); - if (Error E = Mover.move(Obj->takeModule(), Keep, - [](GlobalValue &, IRMover::ValueAdder) {})) { - handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) { - fatal("failed to link module " + F.getName() + ": " + EIB.message()); - }); - } -} - -static void internalize(GlobalValue &GV) { - assert(!GV.hasLocalLinkage() && - "Trying to internalize a symbol with local linkage!"); - GV.setLinkage(GlobalValue::InternalLinkage); -} - -std::vector> BitcodeCompiler::runSplitCodegen( - const std::function()> &TMFactory) { - unsigned NumThreads = Config->LtoJobs; - OwningData.resize(NumThreads); - - std::list OSs; - std::vector OSPtrs; - for (SmallString<0> &Obj : OwningData) { - OSs.emplace_back(Obj); - OSPtrs.push_back(&OSs.back()); - } - - splitCodeGen(std::move(Combined), OSPtrs, {}, TMFactory); - - std::vector> ObjFiles; - for (SmallString<0> &Obj : OwningData) - ObjFiles.push_back(createObjectFile( - MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object"))); - - // If -save-temps is given, we need to save temporary objects to files. - // This is for debugging. - if (Config->SaveTemps) { - if (NumThreads == 1) { - saveBuffer(OwningData[0], Config->OutputFile + ".lto.o"); - } else { - for (unsigned I = 0; I < NumThreads; ++I) - saveBuffer(OwningData[I], Config->OutputFile + Twine(I) + ".lto.o"); - } - } - - return ObjFiles; -} - -// Merge all the bitcode files we have seen, codegen the result -// and return the resulting ObjectFile. -std::vector> BitcodeCompiler::compile() { - for (const auto &Name : InternalizedSyms) { - GlobalValue *GV = Combined->getNamedValue(Name.first()); - assert(GV); - internalize(*GV); - } - - std::string TheTriple = Combined->getTargetTriple(); - std::string Msg; - const Target *T = TargetRegistry::lookupTarget(TheTriple, Msg); - if (!T) - fatal("target not found: " + Msg); - - // LLD supports the new relocations. - TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - Options.RelaxELFRelocations = true; - - auto CreateTargetMachine = [&]() { - return std::unique_ptr(T->createTargetMachine( - TheTriple, "", "", Options, Config->Pic ? Reloc::PIC_ : Reloc::Static)); - }; - - std::unique_ptr TM = CreateTargetMachine(); - - // Update llvm.compiler.used so that optimizations won't strip - // off AsmUndefinedReferences. - updateCompilerUsed(*Combined, *TM, AsmUndefinedRefs); - - if (Config->SaveTemps) - saveBCFile(*Combined, Config->OutputFile + ".lto.bc"); - - runLTOPasses(*Combined, *TM); - if (HasError) - return {}; - - return runSplitCodegen(CreateTargetMachine); -} Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -11,7 +11,6 @@ #define LLD_ELF_SYMBOL_TABLE_H #include "InputFiles.h" -#include "LTO.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Regex.h" @@ -136,7 +135,8 @@ // Set of .so files to not link the same shared object file more than once. llvm::DenseSet SoNames; - std::unique_ptr Lto; + // Set of compiler LTO bitcode files. + std::vector> CompiledBitcodeFiles; }; template struct Symtab { static SymbolTable *X; }; Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -16,11 +16,16 @@ #include "SymbolTable.h" #include "Config.h" +#include "Driver.h" #include "Error.h" #include "LinkerScript.h" #include "SymbolListFile.h" #include "Symbols.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/CommandFlags.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/LTO/LTO.h" +#include "llvm/LTO/LTOBackend.h" #include "llvm/Support/StringSaver.h" using namespace llvm; @@ -102,6 +107,92 @@ F->parse(ComdatGroups); } +static void diagnosticHandler(const DiagnosticInfo &DI) { + if (const auto *BDI = dyn_cast(&DI)) { + std::error_code EC = BDI->getError(); + if (EC == BitcodeError::InvalidBitcodeSignature) + return; + } + + std::string ErrStorage; + { + raw_string_ostream OS(ErrStorage); + DiagnosticPrinterRawOStream DP(OS); + DI.print(DP); + } + warning(ErrStorage.c_str()); +} + +static std::unique_ptr createLTO() { + lto::Config Conf; + lto::ThinBackend Backend; + unsigned ParallelCodeGenParallelismLevel = Config->LtoJobs; + + // LLD supports the new relocations. + Conf.Options = InitTargetOptionsFromCodeGenFlags(); + Conf.Options.RelaxELFRelocations = true; + + Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static; + Conf.DisableVerify = Config->DisableVerify; + Conf.DiagHandler = diagnosticHandler; + Conf.OptLevel = Config->LtoO; + + // Set up a custom pipeline if we've been asked to. + if (!Config->LtoNewPmPasses.empty()) + Conf.OptPipeline = Config->LtoNewPmPasses; + + if (Config->SaveTemps) + check(Conf.addSaveTemps(std::string(Config->OutputFile) + ".", + /*UseInputModulePath*/ true)); + + return (HasError) + ? nullptr + : llvm::make_unique(std::move(Conf), Backend, + ParallelCodeGenParallelismLevel); +} + +namespace { +// Define the LTOOutput handling +class LTOOutput : public lto::NativeObjectOutput { + StringRef Path; + +public: + LTOOutput(StringRef Path) : Path(Path) {} + // Open the filename \p Path and allocate a stream. + std::unique_ptr getStream() override { + int FD; + std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_None); + if (EC) + llvm_unreachable("can't open the file"); + return llvm::make_unique(FD, true); + } +}; +} + +/// Return the desired output filename given a base input name, a flag +/// indicating whether a temp file should be generated, and an optional task id. +/// The new filename generated is returned in \p NewFilename. +static void getOutputFileName(SmallString<128> InFilename, + SmallString<128> &NewFilename, int TaskID = -1) { + NewFilename = InFilename; + if (TaskID >= 0) + NewFilename += utostr(TaskID); +} + +static void undefine(Symbol *S) { + replaceBody(S, S->body()->getName(), STV_DEFAULT, S->body()->Type, + nullptr); +} + +// This is for use when debugging LTO. +static void saveBuffer(StringRef Buffer, const Twine &Path) { + std::error_code EC; + raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); + if (EC) + error(EC, "cannot create " + Path); + OS << Buffer; +} + // This function is where all the optimizations of link-time // optimization happens. When LTO is in use, some input files are // not in native object file format but in the LLVM bitcode format. @@ -113,19 +204,83 @@ if (BitcodeFiles.empty()) return; - // Compile bitcode files. - Lto.reset(new BitcodeCompiler); - for (const std::unique_ptr &F : BitcodeFiles) - Lto->add(*F); - std::vector> IFs = Lto->compile(); + std::unique_ptr LtoObj = createLTO(); + if (HasError) + return; + + for (const std::unique_ptr &F : BitcodeFiles) { + Expected> ObjOrErr = + lto::InputFile::create(F->getBuffer()); + if (!ObjOrErr) + error(toString(ObjOrErr.takeError()).c_str()); + if (HasError) + return; + lto::InputFile &Obj = **ObjOrErr; + if (Obj.getDataLayoutStr().empty()) + fatal("invalid bitcode file: " + F->getName() + " has no datalayout"); + + unsigned SymNum = 0; + std::vector Syms = F->getSymbols(); + std::vector Resols(Syms.size()); + for (LLVM_ATTRIBUTE_UNUSED auto &ObjSym : Obj.symbols()) { + Symbol *Sym = Syms[SymNum]; + lto::SymbolResolution &R = Resols[SymNum]; + ++SymNum; + SymbolBody *B = Sym->body(); + if (B->File != F.get()) + continue; + if (Sym->body()->isUndefined()) + continue; + R.Prevailing = Sym->body()->isDefined(); + R.VisibleToRegularObj = Sym->IsUsedInRegularObj || Sym->includeInDynsym(); + if (Sym->body()->isDefined()) + undefine(Sym); + } + check(LtoObj->add(std::move(*ObjOrErr), Resols)); + if (HasError) + return; + } + + SmallString<128> Filename; + Filename = Config->OutputFile; + unsigned MaxTasks = LtoObj->getMaxTasks(); + std::vector> Filenames(MaxTasks); + + auto AddOutput = + [&](size_t Task) -> std::unique_ptr { + auto &OutputName = Filenames[Task]; + getOutputFileName(Filename, OutputName, MaxTasks > 1 ? Task : -1); + return llvm::make_unique(OutputName); + }; - // Replace bitcode symbols. - for (auto &IF : IFs) { - ObjectFile *Obj = cast>(IF.release()); + check(LtoObj->run(AddOutput)); + if (HasError) + return; - DenseSet DummyGroups; - Obj->parse(DummyGroups); - ObjectFiles.emplace_back(Obj); + for (unsigned I = 0; I != MaxTasks; ++I) { + if (!Filenames[I].empty()) { + auto MBOrErr = MemoryBuffer::getFile(Filenames[I]); + if (auto EC = MBOrErr.getError()) { + error(EC, "cannot open " + Filenames[I]); + return; + } + MemoryBufferRef MB = (*MBOrErr)->getMemBufferRef(); + + // Do we want to move this to the LTO API? + if (Config->SaveTemps) { + if (MaxTasks == 1) + saveBuffer(MB.getBuffer(), Config->OutputFile + ".lto.o"); + else + saveBuffer(MB.getBuffer(), Config->OutputFile + Twine(I) + ".lto.o"); + } + + CompiledBitcodeFiles.push_back(std::move(*MBOrErr)); + ObjectFile *Obj = + cast>(createObjectFile(MB).release()); + DenseSet DummyGroups; + Obj->parse(DummyGroups); + ObjectFiles.emplace_back(Obj); + } } } Index: test/ELF/lto/archive-3.ll =================================================================== --- test/ELF/lto/archive-3.ll +++ test/ELF/lto/archive-3.ll @@ -3,12 +3,12 @@ ; RUN: llvm-as %s -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t3 -save-temps -; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t3.0.2.internalize.bc -o - | FileCheck %s ; RUN: rm -f %t.a ; RUN: llvm-ar rcs %t.a %t1.o ; RUN: ld.lld -m elf_x86_64 %t.a %t1.o %t2.o -o %t3 -save-temps -; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t3.0.2.internalize.bc -o - | FileCheck %s ; CHECK: define internal void @foo() { Index: test/ELF/lto/available-externally.ll =================================================================== --- test/ELF/lto/available-externally.ll +++ test/ELF/lto/available-externally.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o ; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps -; RUN: llvm-dis < %t.so.lto.bc | FileCheck %s +; RUN: llvm-dis < %t.so.0.2.internalize.bc | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/common2.ll =================================================================== --- test/ELF/lto/common2.ll +++ test/ELF/lto/common2.ll @@ -1,6 +1,6 @@ ; RUN: llvm-as %s -o %t1.o ; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps -; RUN: llvm-dis < %t.lto.bc | FileCheck %s +; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s ; RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SHARED target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/common3.ll =================================================================== --- test/ELF/lto/common3.ll +++ test/ELF/lto/common3.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %S/Inputs/common3.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t -shared -save-temps -; RUN: llvm-dis < %t.lto.bc | FileCheck %s +; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/discard-value-names.ll =================================================================== --- test/ELF/lto/discard-value-names.ll +++ test/ELF/lto/discard-value-names.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 -shared -save-temps %t.o -o %t2.o -; RUN: llvm-dis < %t2.o.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.o.0.0.preopt.bc | FileCheck %s ; CHECK: @GlobalValueName ; CHECK: @foo(i32 %in) Index: test/ELF/lto/drop-debug-info.ll =================================================================== --- test/ELF/lto/drop-debug-info.ll +++ test/ELF/lto/drop-debug-info.ll @@ -5,5 +5,5 @@ ; ; RUN: ld.lld -m elf_x86_64 -shared %p/Inputs/drop-debug-info.bc \ ; RUN: -disable-verify 2>&1 | FileCheck %s -; CHECK: warning: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc +; CHECK: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc Index: test/ELF/lto/drop-linkage.ll =================================================================== --- test/ELF/lto/drop-linkage.ll +++ test/ELF/lto/drop-linkage.ll @@ -5,7 +5,7 @@ ; RUN: llc %s -o %t.o -filetype=obj ; RUN: llvm-as %p/Inputs/drop-linkage.ll -o %t2.o ; RUN: ld.lld %t.o %t2.o -o %t.so -save-temps -shared -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s define void @foo() { ret void Index: test/ELF/lto/internalize-basic.ll =================================================================== --- test/ELF/lto/internalize-basic.ll +++ test/ELF/lto/internalize-basic.ll @@ -1,7 +1,7 @@ ; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps -; RUN: llvm-dis < %t2.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.0.2.internalize.bc | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/internalize-exportdyn.ll =================================================================== --- test/ELF/lto/internalize-exportdyn.ll +++ test/ELF/lto/internalize-exportdyn.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps -; RUN: llvm-dis < %t2.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.0.2.internalize.bc | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/internalize-llvmused.ll =================================================================== --- test/ELF/lto/internalize-llvmused.ll +++ test/ELF/lto/internalize-llvmused.ll @@ -1,7 +1,7 @@ ; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps -; RUN: llvm-dis < %t2.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.0.2.internalize.bc | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/internalize-undef.ll =================================================================== --- test/ELF/lto/internalize-undef.ll +++ test/ELF/lto/internalize-undef.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: llvm-as %p/Inputs/internalize-undef.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -save-temps -; RUN: llvm-dis < %t.lto.bc | FileCheck %s +; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/internalize-version-script.ll =================================================================== --- test/ELF/lto/internalize-version-script.ll +++ test/ELF/lto/internalize-version-script.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: echo "{ global: foo; local: *; };" > %t.script ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps -; RUN: llvm-dis < %t2.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.0.2.internalize.bc | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/irmover-error.ll =================================================================== --- test/ELF/lto/irmover-error.ll +++ test/ELF/lto/irmover-error.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as -o %t2.bc %S/Inputs/irmover-error.ll ; RUN: not ld.lld -m elf_x86_64 %t1.bc %t2.bc -o %t 2>&1 | FileCheck %s -; CHECK: failed to link module {{.*}}2.bc: linking module flags 'foo': IDs have conflicting values +; CHECK: linking module flags 'foo': IDs have conflicting values target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/linkonce-odr.ll =================================================================== --- test/ELF/lto/linkonce-odr.ll +++ test/ELF/lto/linkonce-odr.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %p/Inputs/linkonce-odr.ll -o %t1.o ; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj ; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/linkonce.ll =================================================================== --- test/ELF/lto/linkonce.ll +++ test/ELF/lto/linkonce.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %p/Inputs/linkonce.ll -o %t1.o ; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj ; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/ltopasses-basic.ll =================================================================== --- test/ELF/lto/ltopasses-basic.ll +++ test/ELF/lto/ltopasses-basic.ll @@ -1,8 +1,7 @@ ; REQUIRES: x86 -; RUN: rm -f %t.so.lto.bc %t.so.lto.opt.bc %t.so.lto.o ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -mllvm -debug-pass=Arguments -shared 2>&1 | FileCheck %s --check-prefix=MLLVM -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/ltopasses-custom.ll =================================================================== --- test/ELF/lto/ltopasses-custom.ll +++ test/ELF/lto/ltopasses-custom.ll @@ -3,8 +3,8 @@ ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps --lto-aa-pipeline=basic-aa \ ; RUN: --lto-newpm-passes=ipsccp -shared ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2.so -save-temps --lto-newpm-passes=loweratomic -shared -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s -; RUN: llvm-dis %t2.so.lto.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t2.so.0.4.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/save-temps.ll =================================================================== --- test/ELF/lto/save-temps.ll +++ test/ELF/lto/save-temps.ll @@ -5,9 +5,9 @@ ; RUN: llvm-as %p/Inputs/save-temps.ll -o %t2.o ; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o -save-temps ; RUN: llvm-nm a.out | FileCheck %s -; RUN: llvm-nm a.out.lto.bc | FileCheck %s +; RUN: llvm-nm a.out.0.0.preopt.bc | FileCheck %s ; RUN: llvm-nm a.out.lto.o | FileCheck %s -; RUN: llvm-dis a.out.lto.bc +; RUN: llvm-dis a.out.0.0.preopt.bc target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/type-merge.ll =================================================================== --- test/ELF/lto/type-merge.ll +++ test/ELF/lto/type-merge.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: llvm-as %p/Inputs/type-merge.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -shared -save-temps -; RUN: llvm-dis < %t.lto.bc | FileCheck %s +; RUN: llvm-dis < %t.0.0.preopt.bc | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/type-merge2.ll =================================================================== --- test/ELF/lto/type-merge2.ll +++ test/ELF/lto/type-merge2.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: llvm-as %p/Inputs/type-merge2.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared -save-temps -; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.0.preopt.bc -o - | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/unnamed-addr-comdat.ll =================================================================== --- test/ELF/lto/unnamed-addr-comdat.ll +++ test/ELF/lto/unnamed-addr-comdat.ll @@ -1,6 +1,6 @@ ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -save-temps -shared -; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/unnamed-addr-drop.ll =================================================================== --- test/ELF/lto/unnamed-addr-drop.ll +++ test/ELF/lto/unnamed-addr-drop.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %S/Inputs/unnamed-addr-drop.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -save-temps -shared -; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/unnamed-addr-lib.ll =================================================================== --- test/ELF/lto/unnamed-addr-lib.ll +++ test/ELF/lto/unnamed-addr-lib.ll @@ -3,7 +3,7 @@ ; RUN: llvm-mc %p/Inputs/unnamed-addr-lib.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux ; RUN: ld.lld %t2.o -shared -o %t2.so ; RUN: ld.lld -m elf_x86_64 %t.o %t2.so -o %t.so -save-temps -shared -; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s ; This documents a small limitation of lld's internalization logic. We decide ; that bar should be in the symbol table because if it is it will preempt the @@ -11,8 +11,8 @@ ; We could add one extra bit for ODR so that we know that preemption is not ; necessary, but that is probably not worth it. -; CHECK: @foo = internal constant i8 42 -; CHECK: @bar = weak_odr constant i8 42 +; CHECK: @foo = internal unnamed_addr constant i8 42 +; CHECK: @bar = weak_odr unnamed_addr constant i8 42 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/ELF/lto/unnamed-addr.ll =================================================================== --- test/ELF/lto/unnamed-addr.ll +++ test/ELF/lto/unnamed-addr.ll @@ -1,6 +1,6 @@ ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -shared -; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s +; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/lto/version-script.ll =================================================================== --- test/ELF/lto/version-script.ll +++ test/ELF/lto/version-script.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps -; RUN: llvm-dis < %t2.lto.bc | FileCheck %s +; RUN: llvm-dis < %t2.0.0.preopt.bc | FileCheck %s ; RUN: llvm-readobj -V -dyn-symbols %t2 | FileCheck --check-prefix=DSO %s target triple = "x86_64-unknown-linux-gnu"