mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
LTO: Add support for multi-module bitcode files.
Differential Revision: https://reviews.llvm.org/D27313 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289621 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d5f6cc37da
commit
08850161ec
@ -70,6 +70,8 @@ namespace llvm {
|
||||
return StringRef((const char *)Buffer.begin(), Buffer.size());
|
||||
}
|
||||
|
||||
StringRef getModuleIdentifier() const { return ModuleIdentifier; }
|
||||
|
||||
/// Read the bitcode module and prepare for lazy deserialization of function
|
||||
/// bodies. If ShouldLazyLoadMetadata is true, lazily load metadata as well.
|
||||
Expected<std::unique_ptr<Module>>
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BitcodeModule;
|
||||
class Error;
|
||||
class LLVMContext;
|
||||
class MemoryBufferRef;
|
||||
@ -80,14 +81,16 @@ class InputFile {
|
||||
|
||||
// FIXME: Remove the LLVMContext once we have bitcode symbol tables.
|
||||
LLVMContext Ctx;
|
||||
struct InputModule;
|
||||
std::vector<InputModule> Mods;
|
||||
ModuleSymbolTable SymTab;
|
||||
std::unique_ptr<Module> Mod;
|
||||
MemoryBufferRef MBRef;
|
||||
|
||||
std::vector<StringRef> Comdats;
|
||||
DenseMap<const Comdat *, unsigned> ComdatMap;
|
||||
|
||||
public:
|
||||
~InputFile();
|
||||
|
||||
/// Create an InputFile.
|
||||
static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object);
|
||||
|
||||
@ -217,11 +220,17 @@ public:
|
||||
symbol_iterator(SymTab.symbols().end(), SymTab, this));
|
||||
}
|
||||
|
||||
StringRef getSourceFileName() const { return Mod->getSourceFileName(); }
|
||||
MemoryBufferRef getMemoryBufferRef() const { return MBRef; }
|
||||
/// Returns the path to the InputFile.
|
||||
StringRef getName() const;
|
||||
|
||||
/// Returns the source file path specified at compile time.
|
||||
StringRef getSourceFileName() const;
|
||||
|
||||
// Returns a table with all the comdats used by this file.
|
||||
ArrayRef<StringRef> getComdatTable() const { return Comdats; }
|
||||
|
||||
private:
|
||||
iterator_range<symbol_iterator> module_symbols(InputModule &IM);
|
||||
};
|
||||
|
||||
/// This class wraps an output stream for a native object. Most clients should
|
||||
@ -311,6 +320,7 @@ public:
|
||||
/// Until that is fixed, a Config argument is required.
|
||||
LTO(Config Conf, ThinBackend Backend = nullptr,
|
||||
unsigned ParallelCodeGenParallelismLevel = 1);
|
||||
~LTO();
|
||||
|
||||
/// Add an input file to the LTO link, using the provided symbol resolutions.
|
||||
/// The symbol resolutions must appear in the enumeration order given by
|
||||
@ -357,7 +367,7 @@ private:
|
||||
|
||||
ThinBackend Backend;
|
||||
ModuleSummaryIndex CombinedIndex;
|
||||
MapVector<StringRef, MemoryBufferRef> ModuleMap;
|
||||
MapVector<StringRef, BitcodeModule> ModuleMap;
|
||||
DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID;
|
||||
} ThinLTO;
|
||||
|
||||
@ -405,10 +415,17 @@ private:
|
||||
const InputFile::Symbol &Sym, SymbolResolution Res,
|
||||
unsigned Partition);
|
||||
|
||||
Error addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
ArrayRef<SymbolResolution> Res);
|
||||
Error addThinLTO(std::unique_ptr<InputFile> Input,
|
||||
ArrayRef<SymbolResolution> Res);
|
||||
// These functions take a range of symbol resolutions [ResI, ResE) and consume
|
||||
// the resolutions used by a single input module by incrementing ResI. After
|
||||
// these functions return, [ResI, ResE) will refer to the resolution range for
|
||||
// the remaining modules in the InputFile.
|
||||
Error addModule(InputFile &Input, InputFile::InputModule &IM,
|
||||
const SymbolResolution *&ResI, const SymbolResolution *ResE);
|
||||
Error addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
|
||||
const SymbolResolution *ResE);
|
||||
Error addThinLTO(BitcodeModule BM, Module &M,
|
||||
iterator_range<InputFile::symbol_iterator> Syms,
|
||||
const SymbolResolution *&ResI, const SymbolResolution *ResE);
|
||||
|
||||
Error runRegularLTO(AddStreamFn AddStream);
|
||||
Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BitcodeModule;
|
||||
class Error;
|
||||
class Module;
|
||||
class Target;
|
||||
@ -43,7 +44,7 @@ Error thinBackend(Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
|
||||
ModuleSummaryIndex &CombinedIndex,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap);
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
170
lib/LTO/LTO.cpp
170
lib/LTO/LTO.cpp
@ -214,6 +214,17 @@ void llvm::thinLTOInternalizeAndPromoteInIndex(
|
||||
thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
|
||||
}
|
||||
|
||||
struct InputFile::InputModule {
|
||||
BitcodeModule BM;
|
||||
std::unique_ptr<Module> Mod;
|
||||
|
||||
// The range of ModuleSymbolTable entries for this input module.
|
||||
size_t SymBegin, SymEnd;
|
||||
};
|
||||
|
||||
// Requires a destructor for std::vector<InputModule>.
|
||||
InputFile::~InputFile() = default;
|
||||
|
||||
Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
|
||||
std::unique_ptr<InputFile> File(new InputFile);
|
||||
|
||||
@ -221,23 +232,37 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
|
||||
IRObjectFile::findBitcodeInMemBuffer(Object);
|
||||
if (!BCOrErr)
|
||||
return errorCodeToError(BCOrErr.getError());
|
||||
File->MBRef = *BCOrErr;
|
||||
|
||||
Expected<std::unique_ptr<Module>> MOrErr =
|
||||
getLazyBitcodeModule(*BCOrErr, File->Ctx,
|
||||
/*ShouldLazyLoadMetadata*/ true);
|
||||
if (!MOrErr)
|
||||
return MOrErr.takeError();
|
||||
Expected<std::vector<BitcodeModule>> BMsOrErr =
|
||||
getBitcodeModuleList(*BCOrErr);
|
||||
if (!BMsOrErr)
|
||||
return BMsOrErr.takeError();
|
||||
|
||||
File->Mod = std::move(*MOrErr);
|
||||
File->SymTab.addModule(File->Mod.get());
|
||||
if (BMsOrErr->empty())
|
||||
return make_error<StringError>("Bitcode file does not contain any modules",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
for (const auto &C : File->Mod->getComdatSymbolTable()) {
|
||||
auto P =
|
||||
File->ComdatMap.insert(std::make_pair(&C.second, File->Comdats.size()));
|
||||
assert(P.second);
|
||||
(void)P;
|
||||
File->Comdats.push_back(C.first());
|
||||
// Create an InputModule for each module in the InputFile, and add it to the
|
||||
// ModuleSymbolTable.
|
||||
for (auto BM : *BMsOrErr) {
|
||||
Expected<std::unique_ptr<Module>> MOrErr =
|
||||
BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true);
|
||||
if (!MOrErr)
|
||||
return MOrErr.takeError();
|
||||
|
||||
size_t SymBegin = File->SymTab.symbols().size();
|
||||
File->SymTab.addModule(MOrErr->get());
|
||||
size_t SymEnd = File->SymTab.symbols().size();
|
||||
|
||||
for (const auto &C : (*MOrErr)->getComdatSymbolTable()) {
|
||||
auto P = File->ComdatMap.insert(
|
||||
std::make_pair(&C.second, File->Comdats.size()));
|
||||
assert(P.second);
|
||||
(void)P;
|
||||
File->Comdats.push_back(C.first());
|
||||
}
|
||||
|
||||
File->Mods.push_back({BM, std::move(*MOrErr), SymBegin, SymEnd});
|
||||
}
|
||||
|
||||
return std::move(File);
|
||||
@ -258,6 +283,21 @@ Expected<int> InputFile::Symbol::getComdatIndex() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
StringRef InputFile::getName() const {
|
||||
return Mods[0].BM.getModuleIdentifier();
|
||||
}
|
||||
|
||||
StringRef InputFile::getSourceFileName() const {
|
||||
return Mods[0].Mod->getSourceFileName();
|
||||
}
|
||||
|
||||
iterator_range<InputFile::symbol_iterator>
|
||||
InputFile::module_symbols(InputModule &IM) {
|
||||
return llvm::make_range(
|
||||
symbol_iterator(SymTab.symbols().data() + IM.SymBegin, SymTab, this),
|
||||
symbol_iterator(SymTab.symbols().data() + IM.SymEnd, SymTab, this));
|
||||
}
|
||||
|
||||
LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
|
||||
Config &Conf)
|
||||
: ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
|
||||
@ -275,6 +315,9 @@ LTO::LTO(Config Conf, ThinBackend Backend,
|
||||
RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
|
||||
ThinLTO(std::move(Backend)) {}
|
||||
|
||||
// Requires a destructor for MapVector<BitcodeModule>.
|
||||
LTO::~LTO() = default;
|
||||
|
||||
// Add the given symbol to the GlobalResolutions map, and resolve its partition.
|
||||
void LTO::addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
|
||||
const InputFile::Symbol &Sym,
|
||||
@ -297,7 +340,7 @@ void LTO::addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
|
||||
|
||||
static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
StringRef Path = Input->getMemoryBufferRef().getBufferIdentifier();
|
||||
StringRef Path = Input->getName();
|
||||
OS << Path << '\n';
|
||||
auto ResI = Res.begin();
|
||||
for (const InputFile::Symbol &Sym : Input->symbols()) {
|
||||
@ -323,34 +366,45 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
|
||||
if (Conf.ResolutionFile)
|
||||
writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);
|
||||
|
||||
const SymbolResolution *ResI = Res.begin();
|
||||
for (InputFile::InputModule &IM : Input->Mods)
|
||||
if (Error Err = addModule(*Input, IM, ResI, Res.end()))
|
||||
return Err;
|
||||
|
||||
assert(ResI == Res.end());
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error LTO::addModule(InputFile &Input, InputFile::InputModule &IM,
|
||||
const SymbolResolution *&ResI,
|
||||
const SymbolResolution *ResE) {
|
||||
// FIXME: move to backend
|
||||
Module &M = *Input->Mod;
|
||||
Module &M = *IM.Mod;
|
||||
if (!Conf.OverrideTriple.empty())
|
||||
M.setTargetTriple(Conf.OverrideTriple);
|
||||
else if (M.getTargetTriple().empty())
|
||||
M.setTargetTriple(Conf.DefaultTriple);
|
||||
|
||||
Expected<bool> HasThinLTOSummary = hasGlobalValueSummary(Input->MBRef);
|
||||
Expected<bool> HasThinLTOSummary = IM.BM.hasSummary();
|
||||
if (!HasThinLTOSummary)
|
||||
return HasThinLTOSummary.takeError();
|
||||
|
||||
if (*HasThinLTOSummary)
|
||||
return addThinLTO(std::move(Input), Res);
|
||||
return addThinLTO(IM.BM, M, Input.module_symbols(IM), ResI, ResE);
|
||||
else
|
||||
return addRegularLTO(std::move(Input), Res);
|
||||
return addRegularLTO(IM.BM, ResI, ResE);
|
||||
}
|
||||
|
||||
// Add a regular LTO object to the link.
|
||||
Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
|
||||
const SymbolResolution *ResE) {
|
||||
if (!RegularLTO.CombinedModule) {
|
||||
RegularLTO.CombinedModule =
|
||||
llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
|
||||
RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
|
||||
}
|
||||
Expected<std::unique_ptr<Module>> MOrErr =
|
||||
getLazyBitcodeModule(Input->MBRef, RegularLTO.Ctx,
|
||||
/*ShouldLazyLoadMetadata*/ true);
|
||||
BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true);
|
||||
if (!MOrErr)
|
||||
return MOrErr.takeError();
|
||||
|
||||
@ -371,13 +425,12 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
if (GV.hasAppendingLinkage())
|
||||
Keep.push_back(&GV);
|
||||
|
||||
auto ResI = Res.begin();
|
||||
for (const InputFile::Symbol &Sym :
|
||||
make_range(InputFile::symbol_iterator(SymTab.symbols().begin(), SymTab,
|
||||
nullptr),
|
||||
InputFile::symbol_iterator(SymTab.symbols().end(), SymTab,
|
||||
nullptr))) {
|
||||
assert(ResI != Res.end());
|
||||
assert(ResI != ResE);
|
||||
SymbolResolution Res = *ResI++;
|
||||
addSymbolToGlobalRes(Used, Sym, Res, 0);
|
||||
|
||||
@ -411,7 +464,6 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
|
||||
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
|
||||
}
|
||||
assert(ResI == Res.end());
|
||||
|
||||
return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
|
||||
[](GlobalValue &, IRMover::ValueAdder) {},
|
||||
@ -420,33 +472,36 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
}
|
||||
|
||||
// Add a ThinLTO object to the link.
|
||||
Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
|
||||
ArrayRef<SymbolResolution> Res) {
|
||||
Module &M = *Input->Mod;
|
||||
// FIXME: This function should not need to take as many parameters once we have
|
||||
// a bitcode symbol table.
|
||||
Error LTO::addThinLTO(BitcodeModule BM, Module &M,
|
||||
iterator_range<InputFile::symbol_iterator> Syms,
|
||||
const SymbolResolution *&ResI,
|
||||
const SymbolResolution *ResE) {
|
||||
SmallPtrSet<GlobalValue *, 8> Used;
|
||||
collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
|
||||
|
||||
MemoryBufferRef MBRef = Input->MBRef;
|
||||
Expected<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
|
||||
SummaryObjOrErr = object::ModuleSummaryIndexObjectFile::create(MBRef);
|
||||
if (!SummaryObjOrErr)
|
||||
return SummaryObjOrErr.takeError();
|
||||
ThinLTO.CombinedIndex.mergeFrom((*SummaryObjOrErr)->takeIndex(),
|
||||
Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr = BM.getSummary();
|
||||
if (!SummaryOrErr)
|
||||
return SummaryOrErr.takeError();
|
||||
ThinLTO.CombinedIndex.mergeFrom(std::move(*SummaryOrErr),
|
||||
ThinLTO.ModuleMap.size());
|
||||
|
||||
auto ResI = Res.begin();
|
||||
for (const InputFile::Symbol &Sym : Input->symbols()) {
|
||||
assert(ResI != Res.end());
|
||||
for (const InputFile::Symbol &Sym : Syms) {
|
||||
assert(ResI != ResE);
|
||||
SymbolResolution Res = *ResI++;
|
||||
addSymbolToGlobalRes(Used, Sym, Res, ThinLTO.ModuleMap.size() + 1);
|
||||
|
||||
if (Res.Prevailing && Sym.isGV())
|
||||
ThinLTO.PrevailingModuleForGUID[Sym.getGV()->getGUID()] =
|
||||
MBRef.getBufferIdentifier();
|
||||
BM.getModuleIdentifier();
|
||||
}
|
||||
assert(ResI == Res.end());
|
||||
|
||||
ThinLTO.ModuleMap[MBRef.getBufferIdentifier()] = MBRef;
|
||||
if (!ThinLTO.ModuleMap.insert({BM.getModuleIdentifier(), BM}).second)
|
||||
return make_error<StringError>(
|
||||
"Expected at most one ThinLTO module per bitcode file",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
@ -543,11 +598,11 @@ public:
|
||||
|
||||
virtual ~ThinBackendProc() {}
|
||||
virtual Error start(
|
||||
unsigned Task, MemoryBufferRef MBRef,
|
||||
unsigned Task, BitcodeModule BM,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) = 0;
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) = 0;
|
||||
virtual Error wait() = 0;
|
||||
};
|
||||
|
||||
@ -572,16 +627,15 @@ public:
|
||||
|
||||
Error runThinLTOBackendThread(
|
||||
AddStreamFn AddStream, NativeObjectCache Cache, unsigned Task,
|
||||
MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
|
||||
BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
auto RunThinBackend = [&](AddStreamFn AddStream) {
|
||||
LTOLLVMContext BackendContext(Conf);
|
||||
Expected<std::unique_ptr<Module>> MOrErr =
|
||||
parseBitcodeFile(MBRef, BackendContext);
|
||||
Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(BackendContext);
|
||||
if (!MOrErr)
|
||||
return MOrErr.takeError();
|
||||
|
||||
@ -589,7 +643,7 @@ public:
|
||||
ImportList, DefinedGlobals, ModuleMap);
|
||||
};
|
||||
|
||||
auto ModuleID = MBRef.getBufferIdentifier();
|
||||
auto ModuleID = BM.getModuleIdentifier();
|
||||
|
||||
if (!Cache || !CombinedIndex.modulePaths().count(ModuleID) ||
|
||||
all_of(CombinedIndex.getModuleHash(ModuleID),
|
||||
@ -609,25 +663,25 @@ public:
|
||||
}
|
||||
|
||||
Error start(
|
||||
unsigned Task, MemoryBufferRef MBRef,
|
||||
unsigned Task, BitcodeModule BM,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
|
||||
StringRef ModulePath = MBRef.getBufferIdentifier();
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
|
||||
StringRef ModulePath = BM.getModuleIdentifier();
|
||||
assert(ModuleToDefinedGVSummaries.count(ModulePath));
|
||||
const GVSummaryMapTy &DefinedGlobals =
|
||||
ModuleToDefinedGVSummaries.find(ModulePath)->second;
|
||||
BackendThreadPool.async(
|
||||
[=](MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
|
||||
[=](BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
|
||||
&ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
Error E = runThinLTOBackendThread(
|
||||
AddStream, Cache, Task, MBRef, CombinedIndex, ImportList,
|
||||
AddStream, Cache, Task, BM, CombinedIndex, ImportList,
|
||||
ExportList, ResolvedODR, DefinedGlobals, ModuleMap);
|
||||
if (E) {
|
||||
std::unique_lock<std::mutex> L(ErrMu);
|
||||
@ -637,7 +691,7 @@ public:
|
||||
Err = std::move(E);
|
||||
}
|
||||
},
|
||||
MBRef, std::ref(CombinedIndex), std::ref(ImportList),
|
||||
BM, std::ref(CombinedIndex), std::ref(ImportList),
|
||||
std::ref(ExportList), std::ref(ResolvedODR), std::ref(DefinedGlobals),
|
||||
std::ref(ModuleMap));
|
||||
return Error::success();
|
||||
@ -703,12 +757,12 @@ public:
|
||||
LinkedObjectsFileName(LinkedObjectsFileName) {}
|
||||
|
||||
Error start(
|
||||
unsigned Task, MemoryBufferRef MBRef,
|
||||
unsigned Task, BitcodeModule BM,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
|
||||
StringRef ModulePath = MBRef.getBufferIdentifier();
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
|
||||
StringRef ModulePath = BM.getModuleIdentifier();
|
||||
std::string NewModulePath =
|
||||
getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
|
||||
|
||||
|
@ -318,7 +318,7 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||
Module &Mod, ModuleSummaryIndex &CombinedIndex,
|
||||
const FunctionImporter::ImportMapTy &ImportList,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
|
||||
if (!TOrErr)
|
||||
return TOrErr.takeError();
|
||||
@ -353,8 +353,10 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
|
||||
auto ModuleLoader = [&](StringRef Identifier) {
|
||||
assert(Mod.getContext().isODRUniquingDebugTypes() &&
|
||||
"ODR Type uniquing should be enabled on the context");
|
||||
return getLazyBitcodeModule(ModuleMap[Identifier], Mod.getContext(),
|
||||
/*ShouldLazyLoadMetadata=*/true);
|
||||
auto I = ModuleMap.find(Identifier);
|
||||
assert(I != ModuleMap.end());
|
||||
return I->second.getLazyModule(Mod.getContext(),
|
||||
/*ShouldLazyLoadMetadata=*/true);
|
||||
};
|
||||
|
||||
FunctionImporter Importer(CombinedIndex, ModuleLoader);
|
||||
|
3
test/LTO/Resolution/X86/empty-bitcode.test
Normal file
3
test/LTO/Resolution/X86/empty-bitcode.test
Normal file
@ -0,0 +1,3 @@
|
||||
RUN: llvm-cat -o %t.o
|
||||
RUN: not llvm-lto2 -o %t2 %t.o 2>&1 | FileCheck %s
|
||||
CHECK: Bitcode file does not contain any modules
|
@ -13,6 +13,12 @@
|
||||
; NM1-DAG: T main
|
||||
; NM1-DAG: U g
|
||||
|
||||
; Do the same test again, but with the regular and thin LTO modules in the same file.
|
||||
; RUN: llvm-cat -b -o %t4.o %t2.o %t1.o
|
||||
; RUN: llvm-lto2 -o %t5.o %t4.o -r %t4.o,main,px -r %t4.o,g, -r %t4.o,g,px
|
||||
; RUN: llvm-nm %t5.o.0 | FileCheck %s --check-prefix=NM0
|
||||
; RUN: llvm-nm %t5.o.1 | FileCheck %s --check-prefix=NM1
|
||||
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
define i32 @g() {
|
||||
ret i32 0
|
||||
|
6
test/LTO/Resolution/X86/multi-thinlto.ll
Normal file
6
test/LTO/Resolution/X86/multi-thinlto.ll
Normal file
@ -0,0 +1,6 @@
|
||||
; RUN: opt -module-summary %s -o %t.o
|
||||
; RUN: llvm-cat -b -o %t2.o %t.o %t.o
|
||||
; RUN: not llvm-lto2 -o %t3.o %t2.o 2>&1 | FileCheck %s
|
||||
; CHECK: Expected at most one ThinLTO module per bitcode file
|
||||
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
Loading…
Reference in New Issue
Block a user