diff options
Diffstat (limited to 'lld/MachO/LTO.cpp')
-rw-r--r-- | lld/MachO/LTO.cpp | 70 |
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; } |