Path: blob/main/contrib/llvm-project/lld/COFF/LTO.cpp
34870 views
//===- LTO.cpp ------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "LTO.h"9#include "COFFLinkerContext.h"10#include "Config.h"11#include "InputFiles.h"12#include "Symbols.h"13#include "lld/Common/Args.h"14#include "lld/Common/CommonLinkerContext.h"15#include "lld/Common/Filesystem.h"16#include "lld/Common/Strings.h"17#include "lld/Common/TargetOptionsCommandFlags.h"18#include "llvm/ADT/STLExtras.h"19#include "llvm/ADT/SmallString.h"20#include "llvm/ADT/StringRef.h"21#include "llvm/ADT/Twine.h"22#include "llvm/Bitcode/BitcodeWriter.h"23#include "llvm/IR/DiagnosticPrinter.h"24#include "llvm/LTO/Config.h"25#include "llvm/LTO/LTO.h"26#include "llvm/Object/SymbolicFile.h"27#include "llvm/Support/Caching.h"28#include "llvm/Support/CodeGen.h"29#include "llvm/Support/Error.h"30#include "llvm/Support/FileSystem.h"31#include "llvm/Support/MemoryBuffer.h"32#include "llvm/Support/raw_ostream.h"33#include <algorithm>34#include <cstddef>35#include <memory>36#include <string>37#include <system_error>38#include <vector>3940using namespace llvm;41using namespace llvm::object;42using namespace lld;43using namespace lld::coff;4445std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) {46return lto::getThinLTOOutputFile(path, ctx.config.thinLTOPrefixReplaceOld,47ctx.config.thinLTOPrefixReplaceNew);48}4950lto::Config BitcodeCompiler::createConfig() {51lto::Config c;52c.Options = initTargetOptionsFromCodeGenFlags();53c.Options.EmitAddrsig = true;54for (StringRef C : ctx.config.mllvmOpts)55c.MllvmArgs.emplace_back(C.str());5657// Always emit a section per function/datum with LTO. LLVM LTO should get most58// of the benefit of linker GC, but there are still opportunities for ICF.59c.Options.FunctionSections = true;60c.Options.DataSections = true;6162// Use static reloc model on 32-bit x86 because it usually results in more63// compact code, and because there are also known code generation bugs when64// using the PIC model (see PR34306).65if (ctx.config.machine == COFF::IMAGE_FILE_MACHINE_I386)66c.RelocModel = Reloc::Static;67else68c.RelocModel = Reloc::PIC_;69#ifndef NDEBUG70c.DisableVerify = false;71#else72c.DisableVerify = true;73#endif74c.DiagHandler = diagnosticHandler;75c.DwoDir = ctx.config.dwoDir.str();76c.OptLevel = ctx.config.ltoo;77c.CPU = getCPUStr();78c.MAttrs = getMAttrs();79std::optional<CodeGenOptLevel> optLevelOrNone = CodeGenOpt::getLevel(80ctx.config.ltoCgo.value_or(args::getCGOptLevel(ctx.config.ltoo)));81assert(optLevelOrNone && "Invalid optimization level!");82c.CGOptLevel = *optLevelOrNone;83c.AlwaysEmitRegularLTOObj = !ctx.config.ltoObjPath.empty();84c.DebugPassManager = ctx.config.ltoDebugPassManager;85c.CSIRProfile = std::string(ctx.config.ltoCSProfileFile);86c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate;87c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch;88c.SampleProfile = ctx.config.ltoSampleProfileName;89c.TimeTraceEnabled = ctx.config.timeTraceEnabled;90c.TimeTraceGranularity = ctx.config.timeTraceGranularity;9192if (ctx.config.emit == EmitKind::LLVM) {93c.PreCodeGenModuleHook = [this](size_t task, const Module &m) {94if (std::unique_ptr<raw_fd_ostream> os =95openLTOOutputFile(ctx.config.outputFile))96WriteBitcodeToFile(m, *os, false);97return false;98};99} else if (ctx.config.emit == EmitKind::ASM) {100c.CGFileType = CodeGenFileType::AssemblyFile;101c.Options.MCOptions.AsmVerbose = true;102}103104if (ctx.config.saveTemps)105checkError(c.addSaveTemps(std::string(ctx.config.outputFile) + ".",106/*UseInputModulePath*/ true));107return c;108}109110BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {111// Initialize indexFile.112if (!ctx.config.thinLTOIndexOnlyArg.empty())113indexFile = openFile(ctx.config.thinLTOIndexOnlyArg);114115// Initialize ltoObj.116lto::ThinBackend backend;117if (ctx.config.thinLTOIndexOnly) {118auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };119backend = lto::createWriteIndexesThinBackend(120std::string(ctx.config.thinLTOPrefixReplaceOld),121std::string(ctx.config.thinLTOPrefixReplaceNew),122std::string(ctx.config.thinLTOPrefixReplaceNativeObject),123ctx.config.thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);124} else {125backend = lto::createInProcessThinBackend(126llvm::heavyweight_hardware_concurrency(ctx.config.thinLTOJobs));127}128129ltoObj = std::make_unique<lto::LTO>(createConfig(), backend,130ctx.config.ltoPartitions);131}132133BitcodeCompiler::~BitcodeCompiler() = default;134135static void undefine(Symbol *s) { replaceSymbol<Undefined>(s, s->getName()); }136137void BitcodeCompiler::add(BitcodeFile &f) {138lto::InputFile &obj = *f.obj;139unsigned symNum = 0;140std::vector<Symbol *> symBodies = f.getSymbols();141std::vector<lto::SymbolResolution> resols(symBodies.size());142143if (ctx.config.thinLTOIndexOnly)144thinIndices.insert(obj.getName());145146// Provide a resolution to the LTO API for each symbol.147for (const lto::InputFile::Symbol &objSym : obj.symbols()) {148Symbol *sym = symBodies[symNum];149lto::SymbolResolution &r = resols[symNum];150++symNum;151152// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile153// reports two symbols for module ASM defined. Without this check, lld154// flags an undefined in IR with a definition in ASM as prevailing.155// Once IRObjectFile is fixed to report only one symbol this hack can156// be removed.157r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;158r.VisibleToRegularObj = sym->isUsedInRegularObj;159if (r.Prevailing)160undefine(sym);161162// We tell LTO to not apply interprocedural optimization for wrapped163// (with -wrap) symbols because otherwise LTO would inline them while164// their values are still not final.165r.LinkerRedefined = !sym->canInline;166}167checkError(ltoObj->add(std::move(f.obj), resols));168}169170// Merge all the bitcode files we have seen, codegen the result171// and return the resulting objects.172std::vector<InputFile *> BitcodeCompiler::compile() {173unsigned maxTasks = ltoObj->getMaxTasks();174buf.resize(maxTasks);175files.resize(maxTasks);176file_names.resize(maxTasks);177178// The /lldltocache option specifies the path to a directory in which to cache179// native object files for ThinLTO incremental builds. If a path was180// specified, configure LTO to use it as the cache directory.181FileCache cache;182if (!ctx.config.ltoCache.empty())183cache = check(localCache("ThinLTO", "Thin", ctx.config.ltoCache,184[&](size_t task, const Twine &moduleName,185std::unique_ptr<MemoryBuffer> mb) {186files[task] = std::move(mb);187file_names[task] = moduleName.str();188}));189190checkError(ltoObj->run(191[&](size_t task, const Twine &moduleName) {192buf[task].first = moduleName.str();193return std::make_unique<CachedFileStream>(194std::make_unique<raw_svector_ostream>(buf[task].second));195},196cache));197198// Emit empty index files for non-indexed files199for (StringRef s : thinIndices) {200std::string path = getThinLTOOutputFile(s);201openFile(path + ".thinlto.bc");202if (ctx.config.thinLTOEmitImportsFiles)203openFile(path + ".imports");204}205206// ThinLTO with index only option is required to generate only the index207// files. After that, we exit from linker and ThinLTO backend runs in a208// distributed environment.209if (ctx.config.thinLTOIndexOnly) {210if (!ctx.config.ltoObjPath.empty())211saveBuffer(buf[0].second, ctx.config.ltoObjPath);212if (indexFile)213indexFile->close();214return {};215}216217if (!ctx.config.ltoCache.empty())218pruneCache(ctx.config.ltoCache, ctx.config.ltoCachePolicy, files);219220std::vector<InputFile *> ret;221bool emitASM = ctx.config.emit == EmitKind::ASM;222const char *Ext = emitASM ? ".s" : ".obj";223for (unsigned i = 0; i != maxTasks; ++i) {224StringRef bitcodeFilePath;225// Get the native object contents either from the cache or from memory. Do226// not use the cached MemoryBuffer directly, or the PDB will not be227// deterministic.228StringRef objBuf;229if (files[i]) {230objBuf = files[i]->getBuffer();231bitcodeFilePath = file_names[i];232} else {233objBuf = buf[i].second;234bitcodeFilePath = buf[i].first;235}236if (objBuf.empty())237continue;238239// If the input bitcode file is path/to/a.obj, then the corresponding lto240// object file name will look something like: path/to/main.exe.lto.a.obj.241StringRef ltoObjName;242if (bitcodeFilePath == "ld-temp.o") {243ltoObjName =244saver().save(Twine(ctx.config.outputFile) + ".lto" +245(i == 0 ? Twine("") : Twine('.') + Twine(i)) + Ext);246} else {247StringRef directory = sys::path::parent_path(bitcodeFilePath);248StringRef baseName = sys::path::stem(bitcodeFilePath);249StringRef outputFileBaseName = sys::path::filename(ctx.config.outputFile);250SmallString<64> path;251sys::path::append(path, directory,252outputFileBaseName + ".lto." + baseName + Ext);253sys::path::remove_dots(path, true);254ltoObjName = saver().save(path.str());255}256if (ctx.config.saveTemps || emitASM)257saveBuffer(buf[i].second, ltoObjName);258if (!emitASM)259ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));260}261262return ret;263}264265266