#include "llvm-c/lto.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/LTO/legacy/LTOCodeGenerator.h"
#include "llvm/LTO/legacy/LTOModule.h"
#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <string>
#include <system_error>
#include <tuple>
#include <utility>
#include <vector>
usingnamespacellvm;
static codegen::RegisterCodeGenFlags CGF;
static cl::OptionCategory LTOCategory("LTO Options");
static cl::opt<char>
OptLevel("O",
cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
"(default = '-O2')"),
cl::Prefix, cl::init('2'), cl::cat(LTOCategory));
static cl::opt<bool>
IndexStats("thinlto-index-stats",
cl::desc("Print statistic for the index in every input files"),
cl::init(false), cl::cat(LTOCategory));
static cl::opt<bool> DisableVerify(
"disable-verify", cl::init(false),
cl::desc("Do not run the verifier during the optimization pipeline"),
cl::cat(LTOCategory));
static cl::opt<bool> EnableFreestanding(
"lto-freestanding", cl::init(false),
cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
cl::cat(LTOCategory));
static cl::opt<bool> UseDiagnosticHandler(
"use-diagnostic-handler", cl::init(false),
cl::desc("Use a diagnostic handler to test the handler interface"),
cl::cat(LTOCategory));
static cl::opt<bool>
ThinLTO("thinlto", cl::init(false),
cl::desc("Only write combined global index for ThinLTO backends"),
cl::cat(LTOCategory));
enum ThinLTOModes { … };
cl::opt<ThinLTOModes> ThinLTOMode(
"thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
cl::values(
clEnumValN(
THINLINK, "thinlink",
"ThinLink: produces the index by linking only the summaries."),
clEnumValN(THINDISTRIBUTE, "distributedindexes",
"Produces individual indexes for distributed backends."),
clEnumValN(THINEMITIMPORTS, "emitimports",
"Emit imports files for distributed backends."),
clEnumValN(THINPROMOTE, "promote",
"Perform pre-import promotion (requires -thinlto-index)."),
clEnumValN(THINIMPORT, "import",
"Perform both promotion and "
"cross-module importing (requires "
"-thinlto-index)."),
clEnumValN(THININTERNALIZE, "internalize",
"Perform internalization driven by -exported-symbol "
"(requires -thinlto-index)."),
clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")),
cl::cat(LTOCategory));
static cl::opt<std::string>
ThinLTOIndex("thinlto-index",
cl::desc("Provide the index produced by a ThinLink, required "
"to perform the promotion and/or importing."),
cl::cat(LTOCategory));
static cl::opt<std::string> ThinLTOPrefixReplace(
"thinlto-prefix-replace",
cl::desc("Control where files for distributed backends are "
"created. Expects 'oldprefix;newprefix' and if path "
"prefix of output file is oldprefix it will be "
"replaced with newprefix."),
cl::cat(LTOCategory));
static cl::opt<std::string> ThinLTOModuleId(
"thinlto-module-id",
cl::desc("For the module ID for the file to process, useful to "
"match what is in the index."),
cl::cat(LTOCategory));
static cl::opt<std::string> ThinLTOCacheDir("thinlto-cache-dir",
cl::desc("Enable ThinLTO caching."),
cl::cat(LTOCategory));
static cl::opt<int> ThinLTOCachePruningInterval(
"thinlto-cache-pruning-interval", cl::init(1200),
cl::desc("Set ThinLTO cache pruning interval."), cl::cat(LTOCategory));
static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
"thinlto-cache-max-size-bytes",
cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."),
cl::cat(LTOCategory));
static cl::opt<int> ThinLTOCacheMaxSizeFiles(
"thinlto-cache-max-size-files", cl::init(1000000),
cl::desc("Set ThinLTO cache pruning directory maximum number of files."),
cl::cat(LTOCategory));
static cl::opt<unsigned> ThinLTOCacheEntryExpiration(
"thinlto-cache-entry-expiration", cl::init(604800) ,
cl::desc("Set ThinLTO cache entry expiration time."), cl::cat(LTOCategory));
static cl::opt<std::string> ThinLTOSaveTempsPrefix(
"thinlto-save-temps",
cl::desc("Save ThinLTO temp files using filenames created by adding "
"suffixes to the given file path prefix."),
cl::cat(LTOCategory));
static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
"thinlto-save-objects",
cl::desc("Save ThinLTO generated object files using filenames created in "
"the given directory."),
cl::cat(LTOCategory));
static cl::opt<bool> SaveLinkedModuleFile(
"save-linked-module", cl::init(false),
cl::desc("Write linked LTO module to file before optimize"),
cl::cat(LTOCategory));
static cl::opt<bool>
SaveModuleFile("save-merged-module", cl::init(false),
cl::desc("Write merged LTO module to file before CodeGen"),
cl::cat(LTOCategory));
static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
cl::desc("<input bitcode files>"),
cl::cat(LTOCategory));
static cl::opt<std::string> OutputFilename("o", cl::init(""),
cl::desc("Override output filename"),
cl::value_desc("filename"),
cl::cat(LTOCategory));
static cl::list<std::string> ExportedSymbols(
"exported-symbol",
cl::desc("List of symbols to export from the resulting object file"),
cl::cat(LTOCategory));
static cl::list<std::string>
DSOSymbols("dso-symbol",
cl::desc("Symbol to put in the symtab in the resulting dso"),
cl::cat(LTOCategory));
static cl::opt<bool> ListSymbolsOnly(
"list-symbols-only", cl::init(false),
cl::desc("Instead of running LTO, list the symbols in each IR file"),
cl::cat(LTOCategory));
static cl::opt<bool> ListDependentLibrariesOnly(
"list-dependent-libraries-only", cl::init(false),
cl::desc(
"Instead of running LTO, list the dependent libraries in each IR file"),
cl::cat(LTOCategory));
static cl::opt<bool> QueryHasCtorDtor(
"query-hasCtorDtor", cl::init(false),
cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
static cl::opt<bool>
SetMergedModule("set-merged-module", cl::init(false),
cl::desc("Use the first input module as the merged module"),
cl::cat(LTOCategory));
static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
cl::desc("Number of backend threads"),
cl::cat(LTOCategory));
static cl::opt<bool> RestoreGlobalsLinkage(
"restore-linkage", cl::init(false),
cl::desc("Restore original linkage of globals prior to CodeGen"),
cl::cat(LTOCategory));
static cl::opt<bool> CheckHasObjC(
"check-for-objc", cl::init(false),
cl::desc("Only check if the module has objective-C defined in it"),
cl::cat(LTOCategory));
static cl::opt<bool> PrintMachOCPUOnly(
"print-macho-cpu-only", cl::init(false),
cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"),
cl::cat(LTOCategory));
static cl::opt<bool>
DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
cl::desc("Print pass management debugging information"),
cl::cat(LTOCategory));
static cl::opt<bool>
LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
cl::desc("Save the IR before running optimizations"));
static cl::opt<bool> TryUseNewDbgInfoFormat(
"try-experimental-debuginfo-iterators",
cl::desc("Enable debuginfo iterator positions, if they're built in"),
cl::init(false), cl::Hidden);
extern cl::opt<bool> UseNewDbgInfoFormat;
extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat;
extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
namespace {
struct ModuleInfo { … };
}
static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
const char *Msg, void *) { … }
static std::string CurrentActivity;
namespace {
struct LLVMLTODiagnosticHandler : public DiagnosticHandler { … };
}
static void error(const Twine &Msg) { … }
static void error(std::error_code EC, const Twine &Prefix) { … }
template <typename T>
static void error(const ErrorOr<T> &V, const Twine &Prefix) { … }
static void maybeVerifyModule(const Module &Mod) { … }
static std::unique_ptr<LTOModule>
getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
const TargetOptions &Options) { … }
static void printIndexStats() { … }
static void testLTOModule(const TargetOptions &Options) { … }
static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) { … }
static void listDependentLibraries() { … }
static void printMachOCPUOnly() { … }
static void createCombinedModuleSummaryIndex() { … }
static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
std::string &NewPrefix) { … }
static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
StringRef NewPrefix) { … }
namespace thinlto {
std::vector<std::unique_ptr<MemoryBuffer>>
loadAllFilesForIndex(const ModuleSummaryIndex &Index) { … }
std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() { … }
static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) { … }
static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
LLVMContext &CTX) { … }
static void writeModuleToFile(Module &TheModule, StringRef Filename) { … }
class ThinLTOProcessing { … };
}
int main(int argc, char **argv) { … }