forked from OSchip/llvm-project
Added support for ThinLTO plugin options : thinlto-index-only and thinlto-prefix-replace
Differential Revision: https://reviews.llvm.org/D46034 llvm-svn: 331405
This commit is contained in:
parent
e3b437935f
commit
d366e36bbf
|
@ -94,6 +94,8 @@ struct Configuration {
|
||||||
llvm::StringRef SoName;
|
llvm::StringRef SoName;
|
||||||
llvm::StringRef Sysroot;
|
llvm::StringRef Sysroot;
|
||||||
llvm::StringRef ThinLTOCacheDir;
|
llvm::StringRef ThinLTOCacheDir;
|
||||||
|
llvm::StringRef ThinLTOIndexOnlyObjectsFile;
|
||||||
|
llvm::StringRef ThinLTOPrefixReplace;
|
||||||
std::string Rpath;
|
std::string Rpath;
|
||||||
std::vector<VersionDefinition> VersionDefinitions;
|
std::vector<VersionDefinition> VersionDefinitions;
|
||||||
std::vector<llvm::StringRef> AuxiliaryList;
|
std::vector<llvm::StringRef> AuxiliaryList;
|
||||||
|
@ -156,6 +158,7 @@ struct Configuration {
|
||||||
bool SysvHash = false;
|
bool SysvHash = false;
|
||||||
bool Target1Rel;
|
bool Target1Rel;
|
||||||
bool Trace;
|
bool Trace;
|
||||||
|
bool ThinLTOIndexOnly;
|
||||||
bool UndefinedVersion;
|
bool UndefinedVersion;
|
||||||
bool WarnBackrefs;
|
bool WarnBackrefs;
|
||||||
bool WarnCommon;
|
bool WarnCommon;
|
||||||
|
|
|
@ -777,28 +777,38 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||||
// Parse LTO plugin-related options for compatibility with gold.
|
// Parse LTO plugin-related options for compatibility with gold.
|
||||||
for (auto *Arg : Args.filtered(OPT_plugin_opt)) {
|
for (auto *Arg : Args.filtered(OPT_plugin_opt)) {
|
||||||
StringRef S = Arg->getValue();
|
StringRef S = Arg->getValue();
|
||||||
if (S == "disable-verify")
|
if (S == "disable-verify") {
|
||||||
Config->DisableVerify = true;
|
Config->DisableVerify = true;
|
||||||
else if (S == "save-temps")
|
} else if (S == "save-temps") {
|
||||||
Config->SaveTemps = true;
|
Config->SaveTemps = true;
|
||||||
else if (S.startswith("O"))
|
} else if (S.startswith("O")) {
|
||||||
Config->LTOO = parseInt(S.substr(1), Arg);
|
Config->LTOO = parseInt(S.substr(1), Arg);
|
||||||
else if (S.startswith("lto-partitions="))
|
} else if (S.startswith("lto-partitions=")) {
|
||||||
Config->LTOPartitions = parseInt(S.substr(15), Arg);
|
Config->LTOPartitions = parseInt(S.substr(15), Arg);
|
||||||
else if (S.startswith("jobs="))
|
} else if (S.startswith("jobs=")) {
|
||||||
Config->ThinLTOJobs = parseInt(S.substr(5), Arg);
|
Config->ThinLTOJobs = parseInt(S.substr(5), Arg);
|
||||||
else if (S.startswith("mcpu="))
|
} else if (S.startswith("mcpu=")) {
|
||||||
parseClangOption(Saver.save("-" + S), Arg->getSpelling());
|
parseClangOption(Saver.save("-" + S), Arg->getSpelling());
|
||||||
else if (S == "new-pass-manager")
|
} else if (S == "new-pass-manager") {
|
||||||
Config->LTONewPassManager = true;
|
Config->LTONewPassManager = true;
|
||||||
else if (S == "debug-pass-manager")
|
} else if (S == "debug-pass-manager") {
|
||||||
Config->LTODebugPassManager = true;
|
Config->LTODebugPassManager = true;
|
||||||
else if (S.startswith("sample-profile="))
|
} else if (S.startswith("sample-profile=")) {
|
||||||
Config->LTOSampleProfile = S.substr(strlen("sample-profile="));
|
Config->LTOSampleProfile = S.substr(15);
|
||||||
else if (!S.startswith("/") && !S.startswith("-fresolution=") &&
|
} else if (S == "thinlto-index-only") {
|
||||||
!S.startswith("-pass-through=") && !S.startswith("thinlto"))
|
Config->ThinLTOIndexOnly = true;
|
||||||
|
} else if (S.startswith("thinlto-index-only=")) {
|
||||||
|
Config->ThinLTOIndexOnly = true;
|
||||||
|
Config->ThinLTOIndexOnlyObjectsFile = S.substr(19);
|
||||||
|
} else if (S.startswith("thinlto-prefix-replace=")) {
|
||||||
|
Config->ThinLTOPrefixReplace = S.substr(23);
|
||||||
|
if (!Config->ThinLTOPrefixReplace.contains(';'))
|
||||||
|
error("thinlto-prefix-replace expects 'old;new' format");
|
||||||
|
} else if (!S.startswith("/") && !S.startswith("-fresolution=") &&
|
||||||
|
!S.startswith("-pass-through=") && !S.startswith("thinlto")) {
|
||||||
parseClangOption(S, Arg->getSpelling());
|
parseClangOption(S, Arg->getSpelling());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse -mllvm options.
|
// Parse -mllvm options.
|
||||||
for (auto *Arg : Args.filtered(OPT_mllvm))
|
for (auto *Arg : Args.filtered(OPT_mllvm))
|
||||||
|
|
|
@ -42,6 +42,7 @@ bool InputFile::IsInGroup;
|
||||||
uint32_t InputFile::NextGroupId;
|
uint32_t InputFile::NextGroupId;
|
||||||
std::vector<BinaryFile *> elf::BinaryFiles;
|
std::vector<BinaryFile *> elf::BinaryFiles;
|
||||||
std::vector<BitcodeFile *> elf::BitcodeFiles;
|
std::vector<BitcodeFile *> elf::BitcodeFiles;
|
||||||
|
std::vector<LazyObjFile *> elf::LazyObjFiles;
|
||||||
std::vector<InputFile *> elf::ObjectFiles;
|
std::vector<InputFile *> elf::ObjectFiles;
|
||||||
std::vector<InputFile *> elf::SharedFiles;
|
std::vector<InputFile *> elf::SharedFiles;
|
||||||
|
|
||||||
|
@ -1024,9 +1025,10 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,
|
||||||
// this causes a collision which result in only one of the objects being
|
// this causes a collision which result in only one of the objects being
|
||||||
// taken into consideration at LTO time (which very likely causes undefined
|
// taken into consideration at LTO time (which very likely causes undefined
|
||||||
// symbols later in the link stage).
|
// symbols later in the link stage).
|
||||||
MemoryBufferRef MBRef(MB.getBuffer(),
|
MemoryBufferRef MBRef(
|
||||||
|
MB.getBuffer(),
|
||||||
Saver.save(ArchiveName + MB.getBufferIdentifier() +
|
Saver.save(ArchiveName + MB.getBufferIdentifier() +
|
||||||
utostr(OffsetInArchive)));
|
(ArchiveName.empty() ? "" : utostr(OffsetInArchive))));
|
||||||
Obj = CHECK(lto::InputFile::create(MBRef), this);
|
Obj = CHECK(lto::InputFile::create(MBRef), this);
|
||||||
|
|
||||||
Triple T(Obj->getTargetTriple());
|
Triple T(Obj->getTargetTriple());
|
||||||
|
@ -1128,11 +1130,6 @@ void BinaryFile::parse() {
|
||||||
Data.size(), 0, STB_GLOBAL, nullptr, nullptr);
|
Data.size(), 0, STB_GLOBAL, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isBitcode(MemoryBufferRef MB) {
|
|
||||||
using namespace sys::fs;
|
|
||||||
return identify_magic(MB.getBuffer()) == file_magic::bitcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,
|
InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,
|
||||||
uint64_t OffsetInArchive) {
|
uint64_t OffsetInArchive) {
|
||||||
if (isBitcode(MB))
|
if (isBitcode(MB))
|
||||||
|
@ -1168,9 +1165,9 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBufferRef LazyObjFile::getBuffer() {
|
MemoryBufferRef LazyObjFile::getBuffer() {
|
||||||
if (Seen)
|
if (AddedToLink)
|
||||||
return MemoryBufferRef();
|
return MemoryBufferRef();
|
||||||
Seen = true;
|
AddedToLink = true;
|
||||||
return MB;
|
return MB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -259,11 +259,11 @@ public:
|
||||||
template <class ELFT> void parse();
|
template <class ELFT> void parse();
|
||||||
MemoryBufferRef getBuffer();
|
MemoryBufferRef getBuffer();
|
||||||
InputFile *fetch();
|
InputFile *fetch();
|
||||||
|
bool AddedToLink = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class ELFT> void addElfSymbols();
|
template <class ELFT> void addElfSymbols();
|
||||||
|
|
||||||
bool Seen = false;
|
|
||||||
uint64_t OffsetInArchive;
|
uint64_t OffsetInArchive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,8 +351,13 @@ InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",
|
||||||
uint64_t OffsetInArchive = 0);
|
uint64_t OffsetInArchive = 0);
|
||||||
InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName);
|
InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName);
|
||||||
|
|
||||||
|
inline bool isBitcode(MemoryBufferRef MB) {
|
||||||
|
return identify_magic(MB.getBuffer()) == llvm::file_magic::bitcode;
|
||||||
|
}
|
||||||
|
|
||||||
extern std::vector<BinaryFile *> BinaryFiles;
|
extern std::vector<BinaryFile *> BinaryFiles;
|
||||||
extern std::vector<BitcodeFile *> BitcodeFiles;
|
extern std::vector<BitcodeFile *> BitcodeFiles;
|
||||||
|
extern std::vector<LazyObjFile *> LazyObjFiles;
|
||||||
extern std::vector<InputFile *> ObjectFiles;
|
extern std::vector<InputFile *> ObjectFiles;
|
||||||
extern std::vector<InputFile *> SharedFiles;
|
extern std::vector<InputFile *> SharedFiles;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/BinaryFormat/ELF.h"
|
#include "llvm/BinaryFormat/ELF.h"
|
||||||
|
#include "llvm/Bitcode/BitcodeReader.h"
|
||||||
|
#include "llvm/Bitcode/BitcodeWriter.h"
|
||||||
#include "llvm/IR/DiagnosticPrinter.h"
|
#include "llvm/IR/DiagnosticPrinter.h"
|
||||||
#include "llvm/LTO/Caching.h"
|
#include "llvm/LTO/Caching.h"
|
||||||
#include "llvm/LTO/Config.h"
|
#include "llvm/LTO/Config.h"
|
||||||
|
@ -29,7 +31,6 @@
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -66,7 +67,57 @@ static void checkError(Error E) {
|
||||||
[&](ErrorInfoBase &EIB) { error(EIB.message()); });
|
[&](ErrorInfoBase &EIB) { error(EIB.message()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<lto::LTO> createLTO() {
|
// With the ThinLTOIndexOnly option, only the thin link is performed, and will
|
||||||
|
// generate index files for the ThinLTO backends in a distributed build system.
|
||||||
|
// The distributed build system may expect that index files are created for all
|
||||||
|
// input bitcode objects provided to the linker for the thin link. However,
|
||||||
|
// index files will not normally be created for input bitcode objects that
|
||||||
|
// either aren't selected by the linker (i.e. in a static library and not
|
||||||
|
// needed), or because they don't have a summary. Therefore we need to create
|
||||||
|
// empty dummy index file outputs in those cases.
|
||||||
|
// If SkipModule is true then .thinlto.bc should contain just
|
||||||
|
// SkipModuleByDistributedBackend flag which requests distributed backend
|
||||||
|
// to skip the compilation of the corresponding module and produce an empty
|
||||||
|
// object file.
|
||||||
|
static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
|
||||||
|
const std::string &OldPrefix,
|
||||||
|
const std::string &NewPrefix,
|
||||||
|
bool SkipModule) {
|
||||||
|
std::string NewModulePath =
|
||||||
|
lto::getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
|
||||||
|
std::error_code EC;
|
||||||
|
|
||||||
|
raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
|
||||||
|
sys::fs::OpenFlags::F_None);
|
||||||
|
if (EC)
|
||||||
|
error("failed to write " + NewModulePath + ".thinlto.bc" + ": " +
|
||||||
|
EC.message());
|
||||||
|
|
||||||
|
if (SkipModule) {
|
||||||
|
ModuleSummaryIndex Index(false);
|
||||||
|
Index.setSkipModuleByDistributedBackend();
|
||||||
|
WriteIndexToFile(Index, OS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates and returns output stream with a list of object files for final
|
||||||
|
// linking of distributed ThinLTO.
|
||||||
|
static std::unique_ptr<raw_fd_ostream> createLinkedObjectsFile() {
|
||||||
|
if (Config->ThinLTOIndexOnlyObjectsFile.empty())
|
||||||
|
return nullptr;
|
||||||
|
std::error_code EC;
|
||||||
|
auto LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>(
|
||||||
|
Config->ThinLTOIndexOnlyObjectsFile, EC, sys::fs::OpenFlags::F_None);
|
||||||
|
if (EC)
|
||||||
|
error("cannot create " + Config->ThinLTOIndexOnlyObjectsFile + ": " +
|
||||||
|
EC.message());
|
||||||
|
return LinkedObjectsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates instance of LTO.
|
||||||
|
// LinkedObjectsFile is an output stream to write the list of object files for
|
||||||
|
// the final ThinLTO linking. Can be nullptr.
|
||||||
|
static std::unique_ptr<lto::LTO> createLTO(raw_fd_ostream *LinkedObjectsFile) {
|
||||||
lto::Config Conf;
|
lto::Config Conf;
|
||||||
|
|
||||||
// LLD supports the new relocations.
|
// LLD supports the new relocations.
|
||||||
|
@ -105,6 +156,13 @@ static std::unique_ptr<lto::LTO> createLTO() {
|
||||||
if (Config->ThinLTOJobs != -1u)
|
if (Config->ThinLTOJobs != -1u)
|
||||||
Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
|
Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
|
||||||
|
|
||||||
|
if (Config->ThinLTOIndexOnly) {
|
||||||
|
std::string OldPrefix, NewPrefix;
|
||||||
|
std::tie(OldPrefix, NewPrefix) = Config->ThinLTOPrefixReplace.split(';');
|
||||||
|
Backend = lto::createWriteIndexesThinBackend(OldPrefix, NewPrefix, true,
|
||||||
|
LinkedObjectsFile, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
Conf.SampleProfile = Config->LTOSampleProfile;
|
Conf.SampleProfile = Config->LTOSampleProfile;
|
||||||
Conf.UseNewPM = Config->LTONewPassManager;
|
Conf.UseNewPM = Config->LTONewPassManager;
|
||||||
Conf.DebugPassManager = Config->LTODebugPassManager;
|
Conf.DebugPassManager = Config->LTODebugPassManager;
|
||||||
|
@ -113,7 +171,9 @@ static std::unique_ptr<lto::LTO> createLTO() {
|
||||||
Config->LTOPartitions);
|
Config->LTOPartitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {
|
BitcodeCompiler::BitcodeCompiler() {
|
||||||
|
LinkedObjects = createLinkedObjectsFile();
|
||||||
|
LTOObj = createLTO(LinkedObjects.get());
|
||||||
for (Symbol *Sym : Symtab->getSymbols()) {
|
for (Symbol *Sym : Symtab->getSymbols()) {
|
||||||
StringRef Name = Sym->getName();
|
StringRef Name = Sym->getName();
|
||||||
for (StringRef Prefix : {"__start_", "__stop_"})
|
for (StringRef Prefix : {"__start_", "__stop_"})
|
||||||
|
@ -131,6 +191,13 @@ static void undefine(Symbol *S) {
|
||||||
|
|
||||||
void BitcodeCompiler::add(BitcodeFile &F) {
|
void BitcodeCompiler::add(BitcodeFile &F) {
|
||||||
lto::InputFile &Obj = *F.Obj;
|
lto::InputFile &Obj = *F.Obj;
|
||||||
|
|
||||||
|
std::string OldPrefix, NewPrefix;
|
||||||
|
std::tie(OldPrefix, NewPrefix) = Config->ThinLTOPrefixReplace.split(';');
|
||||||
|
|
||||||
|
// Create the empty files which, if indexed, will be overwritten later.
|
||||||
|
writeEmptyDistributedBuildOutputs(Obj.getName(), OldPrefix, NewPrefix, false);
|
||||||
|
|
||||||
unsigned SymNum = 0;
|
unsigned SymNum = 0;
|
||||||
std::vector<Symbol *> Syms = F.getSymbols();
|
std::vector<Symbol *> Syms = F.getSymbols();
|
||||||
std::vector<lto::SymbolResolution> Resols(Syms.size());
|
std::vector<lto::SymbolResolution> Resols(Syms.size());
|
||||||
|
@ -188,6 +255,12 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
|
||||||
Buff.resize(MaxTasks);
|
Buff.resize(MaxTasks);
|
||||||
Files.resize(MaxTasks);
|
Files.resize(MaxTasks);
|
||||||
|
|
||||||
|
// If LazyObjFile has not been added to link, emit empty index files
|
||||||
|
if (Config->ThinLTOIndexOnly)
|
||||||
|
for (LazyObjFile *F : LazyObjFiles)
|
||||||
|
if (!F->AddedToLink && isBitcode(F->MB))
|
||||||
|
addLazyObjFile(F);
|
||||||
|
|
||||||
// The --thinlto-cache-dir option specifies the path to a directory in which
|
// 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
|
// to cache native object files for ThinLTO incremental builds. If a path was
|
||||||
// specified, configure LTO to use it as the cache directory.
|
// specified, configure LTO to use it as the cache directory.
|
||||||
|
@ -222,9 +295,24 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
|
||||||
Ret.push_back(Obj);
|
Ret.push_back(Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// distributed environment.
|
||||||
|
if (Config->ThinLTOIndexOnly)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
for (std::unique_ptr<MemoryBuffer> &File : Files)
|
for (std::unique_ptr<MemoryBuffer> &File : Files)
|
||||||
if (File)
|
if (File)
|
||||||
Ret.push_back(createObjectFile(*File));
|
Ret.push_back(createObjectFile(*File));
|
||||||
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For lazy object files not added to link, adds empty index files
|
||||||
|
void BitcodeCompiler::addLazyObjFile(LazyObjFile *File) {
|
||||||
|
StringRef Identifier = File->getBuffer().getBufferIdentifier();
|
||||||
|
std::string OldPrefix, NewPrefix;
|
||||||
|
std::tie(OldPrefix, NewPrefix) = Config->ThinLTOPrefixReplace.split(';');
|
||||||
|
writeEmptyDistributedBuildOutputs(Identifier, OldPrefix, NewPrefix,
|
||||||
|
/* SkipModule */ true);
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "lld/Common/LLVM.h"
|
#include "lld/Common/LLVM.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ namespace elf {
|
||||||
|
|
||||||
class BitcodeFile;
|
class BitcodeFile;
|
||||||
class InputFile;
|
class InputFile;
|
||||||
|
class LazyObjFile;
|
||||||
|
|
||||||
class BitcodeCompiler {
|
class BitcodeCompiler {
|
||||||
public:
|
public:
|
||||||
|
@ -46,12 +48,14 @@ public:
|
||||||
|
|
||||||
void add(BitcodeFile &F);
|
void add(BitcodeFile &F);
|
||||||
std::vector<InputFile *> compile();
|
std::vector<InputFile *> compile();
|
||||||
|
void addLazyObjFile(LazyObjFile *File);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<llvm::lto::LTO> LTOObj;
|
std::unique_ptr<llvm::lto::LTO> LTOObj;
|
||||||
std::vector<SmallString<0>> Buff;
|
std::vector<SmallString<0>> Buff;
|
||||||
std::vector<std::unique_ptr<MemoryBuffer>> Files;
|
std::vector<std::unique_ptr<MemoryBuffer>> Files;
|
||||||
llvm::DenseSet<StringRef> UsedStartStop;
|
llvm::DenseSet<StringRef> UsedStartStop;
|
||||||
|
std::unique_ptr<llvm::raw_fd_ostream> LinkedObjects;
|
||||||
};
|
};
|
||||||
} // namespace elf
|
} // namespace elf
|
||||||
} // namespace lld
|
} // namespace lld
|
||||||
|
|
|
@ -82,6 +82,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
|
||||||
|
|
||||||
// Lazy object file
|
// Lazy object file
|
||||||
if (auto *F = dyn_cast<LazyObjFile>(File)) {
|
if (auto *F = dyn_cast<LazyObjFile>(File)) {
|
||||||
|
LazyObjFiles.push_back(F);
|
||||||
F->parse<ELFT>();
|
F->parse<ELFT>();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
|
@ -1,7 +1,37 @@
|
||||||
; REQUIRES: x86
|
; REQUIRES: x86
|
||||||
|
|
||||||
|
; First ensure that the ThinLTO handling in lld handles
|
||||||
|
; bitcode without summary sections gracefully and generates index file.
|
||||||
|
; RUN: llvm-as %s -o %t.o
|
||||||
|
; RUN: llvm-as %p/Inputs/thinlto.ll -o %t2.o
|
||||||
|
; RUN: ld.lld -m elf_x86_64 --plugin-opt=thinlto-index-only -shared %t.o %t2.o -o %t3
|
||||||
|
; RUN: ls %t2.o.thinlto.bc
|
||||||
|
; RUN: not test -e %t3
|
||||||
|
; RUN: ld.lld -m elf_x86_64 -shared %t.o %t2.o -o %t4
|
||||||
|
; RUN: llvm-nm %t4 | FileCheck %s --check-prefix=NM
|
||||||
|
|
||||||
; Basic ThinLTO tests.
|
; Basic ThinLTO tests.
|
||||||
; RUN: opt -module-summary %s -o %t.o
|
; RUN: opt -module-summary %s -o %t.o
|
||||||
; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.o
|
; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.o
|
||||||
|
; RUN: opt -module-summary %p/Inputs/thinlto_empty.ll -o %t4.o
|
||||||
|
|
||||||
|
; Ensure lld generates an index and not a binary if requested.
|
||||||
|
; RUN: ld.lld -m elf_x86_64 --plugin-opt=thinlto-index-only -shared %t.o %t2.o -o %t3
|
||||||
|
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=BACKEND1
|
||||||
|
; RUN: llvm-bcanalyzer -dump %t2.o.thinlto.bc | FileCheck %s --check-prefix=BACKEND2
|
||||||
|
; RUN: not test -e %t3
|
||||||
|
|
||||||
|
; Ensure lld generates an index even if the file is wrapped in --start-lib/--end-lib
|
||||||
|
; RUN: rm -f %t2.o.thinlto.bc
|
||||||
|
; RUN: ld.lld -m elf_x86_64 --plugin-opt=thinlto-index-only -shared %t.o %t4.o --start-lib %t2.o --end-lib -o %t5
|
||||||
|
; RUN: ls %t2.o.thinlto.bc
|
||||||
|
|
||||||
|
; Ensure lld generates error if unable to write to index file
|
||||||
|
; RUN: rm -f %t4.o.thinlto.bc
|
||||||
|
; RUN: touch %t4.o.thinlto.bc
|
||||||
|
; RUN: chmod 400 %t4.o.thinlto.bc
|
||||||
|
; RUN: ld.lld -m elf_x86_64 --plugin-opt=thinlto-index-only -shared %t.o %t4.o -o %t5 2>&1 | FileCheck %s --check-prefix=ERR
|
||||||
|
; ERR: failed to write {{.*}}4.o.thinlto.bc: Permission denied
|
||||||
|
|
||||||
; First force single-threaded mode
|
; First force single-threaded mode
|
||||||
; RUN: rm -f %t.lto.o %t1.lto.o
|
; RUN: rm -f %t.lto.o %t1.lto.o
|
||||||
|
@ -15,16 +45,43 @@
|
||||||
; RUN: llvm-nm %t21.lto.o | FileCheck %s --check-prefix=NM1
|
; RUN: llvm-nm %t21.lto.o | FileCheck %s --check-prefix=NM1
|
||||||
; RUN: llvm-nm %t22.lto.o | FileCheck %s --check-prefix=NM2
|
; RUN: llvm-nm %t22.lto.o | FileCheck %s --check-prefix=NM2
|
||||||
|
|
||||||
; NM1: T f
|
|
||||||
; NM1-NOT: U g
|
|
||||||
|
|
||||||
; NM2: T g
|
|
||||||
|
|
||||||
; Then check without --thinlto-jobs (which currently default to hardware_concurrency)
|
; Then check without --thinlto-jobs (which currently default to hardware_concurrency)
|
||||||
; We just check that we don't crash or fail (as it's not sure which tests are
|
; We just check that we don't crash or fail (as it's not sure which tests are
|
||||||
; stable on the final output file itself.
|
; stable on the final output file itself.
|
||||||
; RUN: ld.lld -shared %t.o %t2.o -o %t2
|
; RUN: ld.lld -shared %t.o %t2.o -o %t2
|
||||||
|
|
||||||
|
; NM: T f
|
||||||
|
; NM1: T f
|
||||||
|
; NM1-NOT: U g
|
||||||
|
; NM2: T g
|
||||||
|
|
||||||
|
; The backend index for this module contains summaries from itself and
|
||||||
|
; Inputs/thinlto.ll, as it imports from the latter.
|
||||||
|
; BACKEND1: <MODULE_STRTAB_BLOCK
|
||||||
|
; BACKEND1-NEXT: <ENTRY {{.*}} record string = '{{.*}}/thinlto.ll.tmp{{.*}}.o'
|
||||||
|
; BACKEND1-NEXT: <ENTRY {{.*}} record string = '{{.*}}/thinlto.ll.tmp{{.*}}.o'
|
||||||
|
; BACKEND1-NEXT: </MODULE_STRTAB_BLOCK
|
||||||
|
; BACKEND1: <GLOBALVAL_SUMMARY_BLOCK
|
||||||
|
; BACKEND1: <VERSION
|
||||||
|
; BACKEND1: <FLAGS
|
||||||
|
; BACKEND1: <VALUE_GUID op0={{1|2}} op1={{-3706093650706652785|-5300342847281564238}}
|
||||||
|
; BACKEND1: <VALUE_GUID op0={{1|2}} op1={{-3706093650706652785|-5300342847281564238}}
|
||||||
|
; BACKEND1: <COMBINED
|
||||||
|
; BACKEND1: <COMBINED
|
||||||
|
; BACKEND1: </GLOBALVAL_SUMMARY_BLOCK
|
||||||
|
|
||||||
|
; The backend index for Input/thinlto.ll contains summaries from itself only,
|
||||||
|
; as it does not import anything.
|
||||||
|
; BACKEND2: <MODULE_STRTAB_BLOCK
|
||||||
|
; BACKEND2-NEXT: <ENTRY {{.*}} record string = '{{.*}}/thinlto.ll.tmp2.o'
|
||||||
|
; BACKEND2-NEXT: </MODULE_STRTAB_BLOCK
|
||||||
|
; BACKEND2-NEXT: <GLOBALVAL_SUMMARY_BLOCK
|
||||||
|
; BACKEND2-NEXT: <VERSION
|
||||||
|
; BACKEND2-NEXT: <FLAGS
|
||||||
|
; BACKEND2-NEXT: <VALUE_GUID op0=1 op1=-5300342847281564238
|
||||||
|
; BACKEND2-NEXT: <COMBINED
|
||||||
|
; BACKEND2-NEXT: </GLOBALVAL_SUMMARY_BLOCK
|
||||||
|
|
||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
target triple = "x86_64-unknown-linux-gnu"
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
; REQUIRES: x86
|
||||||
|
; Check that changing the output path via thinlto-prefix-replace works
|
||||||
|
; RUN: mkdir -p %t/oldpath
|
||||||
|
; RUN: opt -module-summary %s -o %t/oldpath/thinlto_prefix_replace.o
|
||||||
|
|
||||||
|
; Ensure that there is no existing file at the new path, so we properly
|
||||||
|
; test the creation of the new file there.
|
||||||
|
; RUN: rm -f %t/newpath/thinlto_prefix_replace.o.thinlto.bc
|
||||||
|
; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-prefix-replace="%t/oldpath/;%t/newpath/" -shared %t/oldpath/thinlto_prefix_replace.o -o %t/thinlto_prefix_replace
|
||||||
|
; RUN: ls %t/newpath/thinlto_prefix_replace.o.thinlto.bc
|
||||||
|
|
||||||
|
; Ensure that lld generates error if prefix replace option does not have 'old;new' format
|
||||||
|
; RUN: rm -f %t/newpath/thinlto_prefix_replace.o.thinlto.bc
|
||||||
|
; RUN: not ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-prefix-replace="%t/oldpath/:%t/newpath/" -shared %t/oldpath/thinlto_prefix_replace.o -o %t/thinlto_prefix_replace 2>&1 | FileCheck %s --check-prefix=ERR
|
||||||
|
; ERR: thinlto-prefix-replace expects 'old;new' format
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define void @f() {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
Reference in New Issue