aboutsummaryrefslogtreecommitdiff
path: root/lld/MachO/LTO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/MachO/LTO.cpp')
-rw-r--r--lld/MachO/LTO.cpp70
1 files changed, 58 insertions, 12 deletions
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index f48bc24df3d7..366193a27eba 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -10,10 +10,15 @@
#include "Config.h"
#include "Driver.h"
#include "InputFiles.h"
+#include "Symbols.h"
+#include "Target.h"
+#include "lld/Common/Args.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
+#include "llvm/LTO/Caching.h"
+#include "llvm/LTO/Config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -23,6 +28,7 @@
using namespace lld;
using namespace lld::macho;
using namespace llvm;
+using namespace llvm::MachO;
using namespace llvm::sys;
static lto::Config createConfig() {
@@ -35,12 +41,19 @@ static lto::Config createConfig() {
c.PreCodeGenPassesHook = [](legacy::PassManager &pm) {
pm.add(createObjCARCContractPass());
};
+ c.TimeTraceEnabled = config->timeTraceEnabled;
+ c.TimeTraceGranularity = config->timeTraceGranularity;
+ c.OptLevel = config->ltoo;
+ c.CGOptLevel = args::getCGOptLevel(config->ltoo);
+ if (config->saveTemps)
+ checkError(c.addSaveTemps(config->outputFile.str() + ".",
+ /*UseInputModulePath=*/true));
return c;
}
BitcodeCompiler::BitcodeCompiler() {
- auto backend =
- lto::createInProcessThinBackend(heavyweight_hardware_concurrency());
+ lto::ThinBackend backend = lto::createInProcessThinBackend(
+ heavyweight_hardware_concurrency(config->thinLTOJobs));
ltoObj = std::make_unique<lto::LTO>(createConfig(), backend);
}
@@ -50,19 +63,33 @@ void BitcodeCompiler::add(BitcodeFile &f) {
resols.reserve(objSyms.size());
// Provide a resolution to the LTO API for each symbol.
+ auto symIt = f.symbols.begin();
for (const lto::InputFile::Symbol &objSym : objSyms) {
resols.emplace_back();
lto::SymbolResolution &r = resols.back();
+ Symbol *sym = *symIt++;
// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
// reports two symbols for module ASM defined. Without this check, lld
// flags an undefined in IR with a definition in ASM as prevailing.
// Once IRObjectFile is fixed to report only one symbol this hack can
// be removed.
- r.Prevailing = !objSym.isUndefined();
+ r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;
+
+ // FIXME: What about other output types? And we can probably be less
+ // restrictive with -flat_namespace, but it's an infrequent use case.
+ // FIXME: Honor config->exportDynamic.
+ r.VisibleToRegularObj = config->outputType != MH_EXECUTE ||
+ config->namespaceKind == NamespaceKind::flat ||
+ sym->isUsedInRegularObj;
+
+ // Un-define the symbol so that we don't get duplicate symbol errors when we
+ // load the ObjFile emitted by LTO compilation.
+ if (r.Prevailing)
+ replaceSymbol<Undefined>(sym, sym->getName(), sym->getFile(),
+ RefState::Strong);
// TODO: set the other resolution configs properly
- r.VisibleToRegularObj = true;
}
checkError(ltoObj->add(std::move(f.obj), resols));
}
@@ -72,11 +99,28 @@ void BitcodeCompiler::add(BitcodeFile &f) {
std::vector<ObjFile *> BitcodeCompiler::compile() {
unsigned maxTasks = ltoObj->getMaxTasks();
buf.resize(maxTasks);
+ files.resize(maxTasks);
+
+ // The -cache_path_lto option specifies the path to a directory in which
+ // to cache native object files for ThinLTO incremental builds. If a path was
+ // specified, configure LTO to use it as the cache directory.
+ lto::NativeObjectCache cache;
+ if (!config->thinLTOCacheDir.empty())
+ cache = check(
+ lto::localCache(config->thinLTOCacheDir,
+ [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
+ files[task] = std::move(mb);
+ }));
- checkError(ltoObj->run([&](size_t task) {
- return std::make_unique<lto::NativeObjectStream>(
- std::make_unique<raw_svector_ostream>(buf[task]));
- }));
+ checkError(ltoObj->run(
+ [&](size_t task) {
+ return std::make_unique<lto::NativeObjectStream>(
+ std::make_unique<raw_svector_ostream>(buf[task]));
+ },
+ cache));
+
+ if (!config->thinLTOCacheDir.empty())
+ pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy);
if (config->saveTemps) {
if (!buf[0].empty())
@@ -90,21 +134,23 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
std::vector<ObjFile *> ret;
for (unsigned i = 0; i != maxTasks; ++i) {
- if (buf[i].empty()) {
+ if (buf[i].empty())
continue;
- }
SmallString<261> filePath("/tmp/lto.tmp");
uint32_t modTime = 0;
if (!config->ltoObjPath.empty()) {
filePath = config->ltoObjPath;
path::append(filePath, Twine(i) + "." +
- getArchitectureName(config->arch) + ".lto.o");
+ getArchitectureName(config->arch()) +
+ ".lto.o");
saveBuffer(buf[i], filePath);
modTime = getModTime(filePath);
}
ret.push_back(make<ObjFile>(
MemoryBufferRef(buf[i], saver.save(filePath.str())), modTime, ""));
}
-
+ for (std::unique_ptr<MemoryBuffer> &file : files)
+ if (file)
+ ret.push_back(make<ObjFile>(*file, 0, ""));
return ret;
}