|
@@ -18,6 +18,7 @@
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/ADT/Twine.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"
|
|
@@ -41,7 +42,19 @@ using namespace llvm::object;
|
|
using namespace lld;
|
|
using namespace lld;
|
|
using namespace lld::coff;
|
|
using namespace lld::coff;
|
|
|
|
|
|
-static std::unique_ptr<lto::LTO> createLTO() {
|
|
|
|
|
|
+// Creates an empty file to and returns a raw_fd_ostream to write to it.
|
|
|
|
+static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
|
|
|
|
+ std::error_code ec;
|
|
|
|
+ auto ret =
|
|
|
|
+ llvm::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::F_None);
|
|
|
|
+ if (ec) {
|
|
|
|
+ error("cannot open " + file + ": " + ec.message());
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static lto::Config createConfig() {
|
|
lto::Config c;
|
|
lto::Config c;
|
|
c.Options = initTargetOptionsFromCodeGenFlags();
|
|
c.Options = initTargetOptionsFromCodeGenFlags();
|
|
|
|
|
|
@@ -67,14 +80,27 @@ static std::unique_ptr<lto::LTO> createLTO() {
|
|
if (config->saveTemps)
|
|
if (config->saveTemps)
|
|
checkError(c.addSaveTemps(std::string(config->outputFile) + ".",
|
|
checkError(c.addSaveTemps(std::string(config->outputFile) + ".",
|
|
/*UseInputModulePath*/ true));
|
|
/*UseInputModulePath*/ true));
|
|
|
|
+ return c;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+BitcodeCompiler::BitcodeCompiler() {
|
|
|
|
+ // Initialize indexFile.
|
|
|
|
+ if (!config->thinLTOIndexOnlyArg.empty())
|
|
|
|
+ indexFile = openFile(config->thinLTOIndexOnlyArg);
|
|
|
|
+
|
|
|
|
+ // Initialize ltoObj.
|
|
lto::ThinBackend backend;
|
|
lto::ThinBackend backend;
|
|
- if (config->thinLTOJobs != 0)
|
|
|
|
|
|
+ if (config->thinLTOIndexOnly) {
|
|
|
|
+ auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
|
|
|
|
+ backend = lto::createWriteIndexesThinBackend(
|
|
|
|
+ "", "", config->thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);
|
|
|
|
+ } else if (config->thinLTOJobs != 0) {
|
|
backend = lto::createInProcessThinBackend(config->thinLTOJobs);
|
|
backend = lto::createInProcessThinBackend(config->thinLTOJobs);
|
|
- return llvm::make_unique<lto::LTO>(std::move(c), backend,
|
|
|
|
- config->ltoPartitions);
|
|
|
|
-}
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-BitcodeCompiler::BitcodeCompiler() : ltoObj(createLTO()) {}
|
|
|
|
|
|
+ ltoObj = llvm::make_unique<lto::LTO>(createConfig(), backend,
|
|
|
|
+ config->ltoPartitions);
|
|
|
|
+}
|
|
|
|
|
|
BitcodeCompiler::~BitcodeCompiler() = default;
|
|
BitcodeCompiler::~BitcodeCompiler() = default;
|
|
|
|
|
|
@@ -86,6 +112,9 @@ void BitcodeCompiler::add(BitcodeFile &f) {
|
|
std::vector<Symbol *> symBodies = f.getSymbols();
|
|
std::vector<Symbol *> symBodies = f.getSymbols();
|
|
std::vector<lto::SymbolResolution> resols(symBodies.size());
|
|
std::vector<lto::SymbolResolution> resols(symBodies.size());
|
|
|
|
|
|
|
|
+ if (config->thinLTOIndexOnly)
|
|
|
|
+ thinIndices.insert(obj.getName());
|
|
|
|
+
|
|
// Provide a resolution to the LTO API for each symbol.
|
|
// Provide a resolution to the LTO API for each symbol.
|
|
for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
|
|
for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
|
|
Symbol *sym = symBodies[symNum];
|
|
Symbol *sym = symBodies[symNum];
|
|
@@ -129,6 +158,23 @@ std::vector<StringRef> BitcodeCompiler::compile() {
|
|
},
|
|
},
|
|
cache));
|
|
cache));
|
|
|
|
|
|
|
|
+ // Emit empty index files for non-indexed files
|
|
|
|
+ for (StringRef S : thinIndices) {
|
|
|
|
+ std::string Path(S);
|
|
|
|
+ openFile(Path + ".thinlto.bc");
|
|
|
|
+ if (config->thinLTOEmitImportsFiles)
|
|
|
|
+ openFile(Path + ".imports");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 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) {
|
|
|
|
+ if (indexFile)
|
|
|
|
+ indexFile->close();
|
|
|
|
+ return {};
|
|
|
|
+ }
|
|
|
|
+
|
|
if (!config->ltoCache.empty())
|
|
if (!config->ltoCache.empty())
|
|
pruneCache(config->ltoCache, config->ltoCachePolicy);
|
|
pruneCache(config->ltoCache, config->ltoCachePolicy);
|
|
|
|
|