[llvm-branch-commits] [llvm] 3ba66b6 - upgrade IR symtab in parallel ahead of time.
Yuanfang Chen via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 2 15:25:53 PST 2019
Author: Yuanfang Chen
Date: 2019-11-05T00:01:43-08:00
New Revision: 3ba66b6229f5400a2637cd3b4529b1dd7987feee
URL: https://github.com/llvm/llvm-project/commit/3ba66b6229f5400a2637cd3b4529b1dd7987feee
DIFF: https://github.com/llvm/llvm-project/commit/3ba66b6229f5400a2637cd3b4529b1dd7987feee.diff
LOG: upgrade IR symtab in parallel ahead of time.
Added:
Modified:
lld/ELF/Driver.cpp
lld/ELF/Driver.h
lld/ELF/InputFiles.cpp
llvm/include/llvm/Bitcode/BitcodeReader.h
llvm/include/llvm/LTO/LTO.h
llvm/include/llvm/Object/IRObjectFile.h
llvm/include/llvm/Object/IRSymtab.h
llvm/include/llvm/Support/MemoryBuffer.h
llvm/lib/LTO/LTO.cpp
llvm/lib/Object/IRObjectFile.cpp
llvm/lib/Object/IRSymtab.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 1b1a50bf6d1c..0f5f63093633 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -49,6 +49,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/LTO/LTO.h"
+#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/GlobPattern.h"
@@ -67,6 +68,8 @@ using namespace llvm::sys;
using namespace llvm::support;
namespace lld {
+llvm::lto::IRSymtabFileCache *irSymTabCache;
+
namespace elf {
Configuration *config;
@@ -189,10 +192,18 @@ std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
void LinkerDriver::addFile(StringRef path, bool withLOption) {
using namespace sys::fs;
- Optional<MemoryBufferRef> buffer = readFile(path);
- if (!buffer.hasValue())
- return;
- MemoryBufferRef mbref = *buffer;
+ MemoryBufferRef mbref;
+ MemoryBufferRef *MB = nullptr;
+ if (irSymTabCache)
+ MB = irSymTabCache->getMemBufferForPath(path);
+ if (MB) {
+ mbref = *MB;
+ } else {
+ Optional<MemoryBufferRef> buffer = readFile(path);
+ if (!buffer.hasValue())
+ return;
+ mbref = *buffer;
+ }
if (config->formatBinary) {
files.push_back(make<BinaryFile>(mbref));
@@ -486,6 +497,8 @@ void LinkerDriver::main(ArrayRef<const char *> argsArr) {
if (args.hasArg(OPT_version))
return;
+ irSymTabCache = new lto::IRSymtabFileCache();
+
initLLVM();
createFiles(args);
if (errorCount())
@@ -1161,10 +1174,54 @@ static bool isFormatBinary(StringRef s) {
return false;
}
+void addFileToIrSymTabCache(StringRef path,
+ llvm::StringMap<MemoryBufferRef> &LoadedFiles,
+ std::vector<MemoryBufferRef> &ToCache) {
+ using namespace sys::fs;
+
+ Optional<MemoryBufferRef> buffer = readFile(path);
+ if (!buffer.hasValue())
+ return;
+ MemoryBufferRef mbref = *buffer;
+ LoadedFiles.try_emplace(path, mbref);
+
+ switch (identify_magic(mbref.getBuffer())) {
+ case file_magic::archive: {
+ for (const std::pair<MemoryBufferRef, uint64_t> &p :
+ getArchiveMembers(mbref))
+ if (identify_magic(p.first.getBuffer()) == file_magic::bitcode)
+ ToCache.push_back(p.first);
+ break;
+ }
+
+ case file_magic::bitcode:
+ ToCache.push_back(mbref);
+ break;
+ default:
+ break;
+ }
+}
+
void LinkerDriver::createFiles(opt::InputArgList &args) {
// For --{push,pop}-state.
std::vector<std::tuple<bool, bool, bool>> stack;
+ if (irSymTabCache) {
+ std::vector<std::string> Files;
+ for (auto *arg : args) {
+ switch (arg->getOption().getID()) {
+ case OPT_library:
+ if (Optional<std::string> path = searchLibrary(arg->getValue()))
+ Files.push_back(*path);
+ break;
+ case OPT_INPUT:
+ Files.push_back(arg->getValue());
+ break;
+ }
+ }
+ irSymTabCache->upgrade(Files, addFileToIrSymTabCache);
+ }
+
// Iterate over argv to process input files and positional arguments.
for (auto *arg : args) {
switch (arg->getOption().getID()) {
@@ -1755,6 +1812,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
for (size_t i = 0; i < files.size(); ++i)
parseFile(files[i]);
+ if (irSymTabCache) {
+ delete irSymTabCache;
+ irSymTabCache = nullptr;
+ }
+
// Now that we have every file, we can decide if we will need a
// dynamic symbol table.
// We need one if we were asked to export dynamic symbols or if we are
diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h
index 3115e28d1669..a7ebf1e49eba 100644
--- a/lld/ELF/Driver.h
+++ b/lld/ELF/Driver.h
@@ -14,13 +14,25 @@
#include "lld/Common/LLVM.h"
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/raw_ostream.h"
+namespace llvm {
+namespace lto {
+ class IRSymtabFileCache;
+}
+}
+
namespace lld {
+extern llvm::lto::IRSymtabFileCache *irSymTabCache;
+
namespace elf {
+void addFileToIrSymTabCache(StringRef path,
+ llvm::StringMap<MemoryBufferRef> &LoadedFiles,
+ std::vector<MemoryBufferRef> &ToCache);
extern class LinkerDriver *driver;
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 09b20463af2f..cbc1d9fa98cc 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -475,6 +475,16 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
this->sections.resize(sections.size());
}
+static Optional<std::pair<std::string, bool>> getPath(StringRef specifier) {
+ if (fs::exists(specifier))
+ return std::make_pair(specifier.str(), false);
+ else if (Optional<std::string> s = findFromSearchPaths(specifier))
+ return std::make_pair(*s, true);
+ else if (Optional<std::string> s = searchLibraryBaseName(specifier))
+ return std::make_pair(*s, true);
+ return None;
+}
+
// An ELF object file may contain a `.deplibs` section. If it exists, the
// section contains a list of library specifiers such as `m` for libm. This
// function resolves a given name by finding the first matching library checking
@@ -484,12 +494,8 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
static void addDependentLibrary(StringRef specifier, const InputFile *f) {
if (!config->dependentLibraries)
return;
- if (fs::exists(specifier))
- driver->addFile(specifier, /*withLOption=*/false);
- else if (Optional<std::string> s = findFromSearchPaths(specifier))
- driver->addFile(*s, /*withLOption=*/true);
- else if (Optional<std::string> s = searchLibraryBaseName(specifier))
- driver->addFile(*s, /*withLOption=*/true);
+ if (Optional<std::pair<std::string, bool>> path = getPath(specifier))
+ driver->addFile(path->first, /*withLOption=*/path->second);
else
error(toString(f) +
": unable to find library from dependent library specifier: " +
@@ -1365,6 +1371,11 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
if (config->thinLTOIndexOnly)
path = replaceThinLTOSuffix(mb.getBufferIdentifier());
+ if (irSymTabCache)
+ obj = CHECK(lto::InputFile::create(mb, *irSymTabCache), this);
+ else
+ obj = CHECK(lto::InputFile::create(mb), this);
+
// ThinLTO assumes that all MemoryBufferRefs given to it have a unique
// name. If two archives define two members with the same name, this
// causes a collision which result in only one of the objects being taken
@@ -1375,9 +1386,7 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
? saver.save(path)
: saver.save(archiveName + "(" + path + " at " +
utostr(offsetInArchive) + ")");
- MemoryBufferRef mbref(mb.getBuffer(), name);
-
- obj = CHECK(lto::InputFile::create(mbref), this);
+ obj->getSingleBitcodeModule().setModuleIdentifier(name);
Triple t(obj->getTargetTriple());
ekind = getBitcodeELFKind(t);
@@ -1436,6 +1445,14 @@ template <class ELFT> void BitcodeFile::parse() {
for (const lto::InputFile::Symbol &objSym : obj->symbols())
symbols.push_back(createBitcodeSymbol<ELFT>(keptComdats, objSym, *this));
+ if (config->dependentLibraries && irSymTabCache) {
+ std::vector<std::string> filesToUpgrade;
+ for (auto l : obj->getDependentLibraries())
+ if (Optional<std::pair<std::string, bool>> path = getPath(l))
+ filesToUpgrade.push_back(path->first);
+ irSymTabCache->upgrade(filesToUpgrade, addFileToIrSymTabCache);
+ }
+
for (auto l : obj->getDependentLibraries())
addDependentLibrary(l, this);
}
diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h
index ba61da733bea..404f061bbb2a 100644
--- a/llvm/include/llvm/Bitcode/BitcodeReader.h
+++ b/llvm/include/llvm/Bitcode/BitcodeReader.h
@@ -90,6 +90,7 @@ class Module;
StringRef getStrtab() const { return Strtab; }
StringRef getModuleIdentifier() const { return ModuleIdentifier; }
+ void setModuleIdentifier(StringRef ModId) { ModuleIdentifier = ModId; }
/// Read the bitcode module and prepare for lazy deserialization of function
/// bodies. If ShouldLazyLoadMetadata is true, lazily load metadata as well.
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 0a1e3e1d0e42..ea86ecb90452 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -18,14 +18,17 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/LTO/Config.h"
#include "llvm/Linker/IRMover.h"
+#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/IRSymtab.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/thread.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/IPO/FunctionImport.h"
@@ -99,6 +102,28 @@ class LTO;
struct SymbolResolution;
class ThinBackendProc;
+// For parallelizing IR symtab upgrading.
+class IRSymtabFileCache {
+ unsigned ThinLTOParallelismLevel;
+ ThreadPool BackendThreadPool;
+ using CacheType =
+ DenseMap<MemoryBufferRef, std::unique_ptr<object::IRSymtabFile>>;
+ CacheType Cache;
+ StringMap<MemoryBufferRef> LoadedFiles;
+
+ using AddFileFn = std::function<void(StringRef path,
+ StringMap<MemoryBufferRef> &LoadedFiles,
+ std::vector<MemoryBufferRef> &ToLoad)>;
+
+public:
+ IRSymtabFileCache()
+ : ThinLTOParallelismLevel(std::thread::hardware_concurrency()),
+ BackendThreadPool(ThinLTOParallelismLevel) {}
+ void upgrade(const std::vector<std::string> &Files, AddFileFn AFF);
+ object::IRSymtabFile *get(const MemoryBufferRef &M);
+ MemoryBufferRef *getMemBufferForPath(StringRef Path);
+};
+
/// An input file. This is a symbol table wrapper that only exposes the
/// information that an LTO client should need in order to do symbol resolution.
class InputFile {
@@ -109,6 +134,7 @@ class InputFile {
// FIXME: Remove LTO class friendship once we have bitcode symbol tables.
friend LTO;
InputFile() = default;
+ InputFile(object::IRSymtabFile &SF);
std::vector<BitcodeModule> Mods;
SmallVector<char, 0> Strtab;
@@ -126,6 +152,8 @@ class InputFile {
/// Create an InputFile.
static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object);
+ static Expected<std::unique_ptr<InputFile>>
+ create(MemoryBufferRef Object, IRSymtabFileCache &IRSymTabCache);
/// The purpose of this class is to only expose the symbol information that an
/// LTO client should need in order to do symbol resolution.
diff --git a/llvm/include/llvm/Object/IRObjectFile.h b/llvm/include/llvm/Object/IRObjectFile.h
index 08b92f1bae50..a0fc57343d57 100644
--- a/llvm/include/llvm/Object/IRObjectFile.h
+++ b/llvm/include/llvm/Object/IRObjectFile.h
@@ -83,6 +83,7 @@ struct IRSymtabFile {
/// Reads a bitcode file, creating its irsymtab if necessary.
Expected<IRSymtabFile> readIRSymtab(MemoryBufferRef MBRef);
+bool needToUpgradeIRSymtab(MemoryBufferRef MBRef);
}
diff --git a/llvm/include/llvm/Object/IRSymtab.h b/llvm/include/llvm/Object/IRSymtab.h
index 0bbfc932493c..025b3fa2fb67 100644
--- a/llvm/include/llvm/Object/IRSymtab.h
+++ b/llvm/include/llvm/Object/IRSymtab.h
@@ -366,6 +366,7 @@ struct FileContents {
/// Reads the contents of a bitcode file, creating its irsymtab if necessary.
Expected<FileContents> readBitcode(const BitcodeFileContents &BFC);
+bool needUpgrade(const BitcodeFileContents &BFC);
} // end namespace irsymtab
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/MemoryBuffer.h b/llvm/include/llvm/Support/MemoryBuffer.h
index b5196cd84cb4..acfba5761bab 100644
--- a/llvm/include/llvm/Support/MemoryBuffer.h
+++ b/llvm/include/llvm/Support/MemoryBuffer.h
@@ -15,6 +15,7 @@
#include "llvm-c/Types.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CBindingWrapping.h"
@@ -281,6 +282,28 @@ class MemoryBufferRef {
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
+// Support MemoryBufferRef as DenseMap keys.
+template <> struct DenseMapInfo<MemoryBufferRef> {
+ static inline MemoryBufferRef getEmptyKey() {
+ static MemoryBufferRef EmptyKey(DenseMapInfo<StringRef>::getEmptyKey(),
+ DenseMapInfo<StringRef>::getEmptyKey());
+ return EmptyKey;
+ }
+ static inline MemoryBufferRef getTombstoneKey() {
+ static MemoryBufferRef TombstoneKey(
+ DenseMapInfo<StringRef>::getTombstoneKey(),
+ DenseMapInfo<StringRef>::getTombstoneKey());
+ return TombstoneKey;
+ }
+ static unsigned getHashValue(const MemoryBufferRef &mbref) {
+ return hash_combine(mbref.getBuffer().data(), mbref.getBuffer().size());
+ }
+ static bool isEqual(const MemoryBufferRef &LHS, const MemoryBufferRef &RHS) {
+ return LHS.getBuffer().data() == RHS.getBuffer().data() &&
+ LHS.getBuffer().size() == RHS.getBuffer().size();
+ }
+};
+
} // end namespace llvm
#endif // LLVM_SUPPORT_MEMORYBUFFER_H
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 1e345e7dd89e..e2cc99fb94e0 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -28,15 +28,14 @@
#include "llvm/LTO/LTOBackend.h"
#include "llvm/LTO/SummaryBasedOptimizations.h"
#include "llvm/Linker/IRMover.h"
-#include "llvm/Object/IRObjectFile.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VCSRevision.h"
#include "llvm/Support/raw_ostream.h"
@@ -426,33 +425,41 @@ void llvm::thinLTOInternalizeAndPromoteInIndex(
// 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);
+InputFile::InputFile(IRSymtabFile &SF) {
+ TargetTriple = SF.TheReader.getTargetTriple();
+ SourceFileName = SF.TheReader.getSourceFileName();
+ COFFLinkerOpts = SF.TheReader.getCOFFLinkerOpts();
+ DependentLibraries = SF.TheReader.getDependentLibraries();
+ ComdatTable = SF.TheReader.getComdatTable();
- Expected<IRSymtabFile> FOrErr = readIRSymtab(Object);
- if (!FOrErr)
- return FOrErr.takeError();
-
- File->TargetTriple = FOrErr->TheReader.getTargetTriple();
- File->SourceFileName = FOrErr->TheReader.getSourceFileName();
- File->COFFLinkerOpts = FOrErr->TheReader.getCOFFLinkerOpts();
- File->DependentLibraries = FOrErr->TheReader.getDependentLibraries();
- File->ComdatTable = FOrErr->TheReader.getComdatTable();
-
- for (unsigned I = 0; I != FOrErr->Mods.size(); ++I) {
- size_t Begin = File->Symbols.size();
+ for (unsigned I = 0; I != SF.Mods.size(); ++I) {
+ size_t Begin = Symbols.size();
for (const irsymtab::Reader::SymbolRef &Sym :
- FOrErr->TheReader.module_symbols(I))
+ SF.TheReader.module_symbols(I))
// Skip symbols that are irrelevant to LTO. Note that this condition needs
// to match the one in Skip() in LTO::addRegularLTO().
if (Sym.isGlobal() && !Sym.isFormatSpecific())
- File->Symbols.push_back(Sym);
- File->ModuleSymIndices.push_back({Begin, File->Symbols.size()});
+ Symbols.push_back(Sym);
+ ModuleSymIndices.push_back({Begin, Symbols.size()});
}
- File->Mods = FOrErr->Mods;
- File->Strtab = std::move(FOrErr->Strtab);
- return std::move(File);
+ Mods = SF.Mods;
+ Strtab = std::move(SF.Strtab);
+}
+
+Expected<std::unique_ptr<InputFile>>
+InputFile::create(MemoryBufferRef Object) {
+ Expected<IRSymtabFile> FOrErr = readIRSymtab(Object);
+ if (!FOrErr)
+ return FOrErr.takeError();
+ return std::unique_ptr<InputFile>(new InputFile(*FOrErr));
+}
+
+Expected<std::unique_ptr<InputFile>>
+InputFile::create(MemoryBufferRef Object, IRSymtabFileCache &IRSymTabCache) {
+ if (IRSymtabFile *FOrErr = IRSymTabCache.get(Object))
+ return std::unique_ptr<InputFile>(new InputFile(*FOrErr));
+ return InputFile::create(Object);
}
StringRef InputFile::getName() const {
@@ -1375,6 +1382,76 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
return BackendProc->wait();
}
+IRSymtabFile *IRSymtabFileCache::get(const MemoryBufferRef &M) {
+ auto Iter = Cache.find(M);
+ if (Iter != Cache.end())
+ return Iter->second.get();
+ return nullptr;
+}
+
+void IRSymtabFileCache::upgrade(const std::vector<std::string> &Files,
+ AddFileFn AFF) {
+ std::vector<MemoryBufferRef> MBrefs;
+ for (auto &F : Files)
+ AFF(F, LoadedFiles, MBrefs);
+
+ // Cache IR SymTab only if it needs upgrade. Also try to balance the amount
+ // work each thread will do based on aggregate MemoryBufferRef size.
+ std::vector<MemoryBufferRef> ToCache;
+ unsigned TotalBufSize = 0;
+ for (auto &M : MBrefs)
+ if (Cache.count(M) == 0 && needToUpgradeIRSymtab(M)) {
+ ToCache.push_back(M);
+ TotalBufSize += M.getBufferSize();
+ Cache.try_emplace(M, nullptr);
+ }
+
+ if (!ToCache.size())
+ return;
+
+ // If too few symtabs to cache, assign one to each thread.
+ const unsigned ThreadLocal = ToCache.size() >= ThinLTOParallelismLevel
+ ? TotalBufSize / ThinLTOParallelismLevel
+ : 0;
+
+ auto PreLoad = [&](std::vector<MemoryBufferRef>::iterator II,
+ std::vector<MemoryBufferRef>::iterator IE) {
+ for (; II != IE; ++II) {
+ Expected<IRSymtabFile> FOrErr = readIRSymtab(*II);
+ if (FOrErr)
+ Cache.find(*II)->second.reset(new IRSymtabFile(std::move(*FOrErr)));
+ else
+ consumeError(FOrErr.takeError());
+ }
+ };
+
+ auto CI = ToCache.begin();
+ unsigned CurTotal = 0;
+ unsigned NumThread = 0;
+ for (auto I = ToCache.begin(), E = ToCache.end(); I != E; ++I) {
+ CurTotal += I->getBufferSize();
+ if (CurTotal < ThreadLocal)
+ continue;
+
+ CurTotal = 0;
+ auto TI = I;
+ BackendThreadPool.async(PreLoad, CI, ++TI);
+ CI = TI;
+ if (++NumThread == (ThinLTOParallelismLevel - 1)) {
+ BackendThreadPool.async(PreLoad, CI, ToCache.end());
+ break;
+ }
+ }
+ BackendThreadPool.wait();
+}
+
+MemoryBufferRef *IRSymtabFileCache::getMemBufferForPath(StringRef Path) {
+ auto I = LoadedFiles.find(Path);
+ if (I != LoadedFiles.end())
+ return &I->second;
+ return nullptr;
+}
+
Expected<std::unique_ptr<ToolOutputFile>>
lto::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp
index 636f1521262f..bb0da6bb5e42 100644
--- a/llvm/lib/Object/IRObjectFile.cpp
+++ b/llvm/lib/Object/IRObjectFile.cpp
@@ -132,6 +132,18 @@ IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
new IRObjectFile(*BCOrErr, std::move(Mods)));
}
+bool object::needToUpgradeIRSymtab(MemoryBufferRef MBRef) {
+ Expected<MemoryBufferRef> BCOrErr =
+ IRObjectFile::findBitcodeInMemBuffer(MBRef);
+ if (!BCOrErr)
+ return false;
+
+ Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
+ if (!BFCOrErr)
+ return false;
+ return irsymtab::needUpgrade(*BFCOrErr);
+}
+
Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
IRSymtabFile F;
Expected<MemoryBufferRef> BCOrErr =
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index e4282b9d6bd3..a5a4d5bce582 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -374,14 +374,13 @@ static Expected<FileContents> upgrade(ArrayRef<BitcodeModule> BMs) {
return std::move(FC);
}
-Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
+bool irsymtab::needUpgrade(const BitcodeFileContents &BFC) {
if (BFC.Mods.empty())
- return make_error<StringError>("Bitcode file does not contain any modules",
- inconvertibleErrorCode());
+ return false;
if (BFC.StrtabForSymtab.empty() ||
BFC.Symtab.size() < sizeof(storage::Header))
- return upgrade(BFC.Mods);
+ return true;
// We cannot use the regular reader to read the version and producer, because
// it will expect the header to be in the current format. The only thing we
@@ -392,7 +391,7 @@ Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
StringRef Producer = Hdr->Producer.get(BFC.StrtabForSymtab);
if (Version != storage::Header::kCurrentVersion ||
Producer != kExpectedProducerName)
- return upgrade(BFC.Mods);
+ return true;
FileContents FC;
FC.TheReader = {{BFC.Symtab.data(), BFC.Symtab.size()},
@@ -403,7 +402,20 @@ Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
// the bitcode file was created by binary concatenation, so we need to create
// a new symbol table from scratch.
if (FC.TheReader.getNumModules() != BFC.Mods.size())
- return upgrade(std::move(BFC.Mods));
+ return true;
+
+ return false;
+}
+
+Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
+ if (BFC.Mods.empty())
+ return make_error<StringError>("Bitcode file does not contain any modules",
+ inconvertibleErrorCode());
+ if (needUpgrade(BFC))
+ return upgrade(BFC.Mods);
+ FileContents FC;
+ FC.TheReader = {{BFC.Symtab.data(), BFC.Symtab.size()},
+ {BFC.StrtabForSymtab.data(), BFC.StrtabForSymtab.size()}};
return std::move(FC);
}
More information about the llvm-branch-commits
mailing list