diff options
Diffstat (limited to 'tools/llvm-lto/llvm-lto.cpp')
-rw-r--r-- | tools/llvm-lto/llvm-lto.cpp | 627 |
1 files changed, 547 insertions, 80 deletions
diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 232051130cb2..b3b617b941d3 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -17,14 +17,19 @@ #include "llvm/CodeGen/CommandFlags.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/LTO/LTOCodeGenerator.h" -#include "llvm/LTO/LTOModule.h" -#include "llvm/Object/FunctionIndexObjectFile.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/Object/ModuleSummaryIndexObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" @@ -33,59 +38,108 @@ using namespace llvm; static cl::opt<char> -OptLevel("O", - cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " - "(default = '-O2')"), - cl::Prefix, - cl::ZeroOrMore, - cl::init('2')); + OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, cl::ZeroOrMore, cl::init('2')); static cl::opt<bool> DisableVerify( "disable-verify", cl::init(false), cl::desc("Do not run the verifier during the optimization pipeline")); -static cl::opt<bool> -DisableInline("disable-inlining", cl::init(false), - cl::desc("Do not run the inliner pass")); +static cl::opt<bool> DisableInline("disable-inlining", cl::init(false), + cl::desc("Do not run the inliner pass")); static cl::opt<bool> -DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), - cl::desc("Do not run the GVN load PRE pass")); + DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), + cl::desc("Do not run the GVN load PRE pass")); -static cl::opt<bool> -DisableLTOVectorization("disable-lto-vectorization", cl::init(false), - cl::desc("Do not run loop or slp vectorization during LTO")); +static cl::opt<bool> DisableLTOVectorization( + "disable-lto-vectorization", cl::init(false), + cl::desc("Do not run loop or slp vectorization during LTO")); -static cl::opt<bool> -UseDiagnosticHandler("use-diagnostic-handler", cl::init(false), - cl::desc("Use a diagnostic handler to test the handler interface")); +static cl::opt<bool> UseDiagnosticHandler( + "use-diagnostic-handler", cl::init(false), + cl::desc("Use a diagnostic handler to test the handler interface")); static cl::opt<bool> ThinLTO("thinlto", cl::init(false), cl::desc("Only write combined global index for ThinLTO backends")); -static cl::opt<bool> -SaveModuleFile("save-merged-module", cl::init(false), - cl::desc("Write merged LTO module to file before CodeGen")); +enum ThinLTOModes { + THINLINK, + THINDISTRIBUTE, + THINEMITIMPORTS, + THINPROMOTE, + THINIMPORT, + THININTERNALIZE, + THINOPT, + THINCODEGEN, + THINALL +}; -static cl::list<std::string> -InputFilenames(cl::Positional, cl::OneOrMore, - cl::desc("<input bitcode files>")); +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"), + clEnumValEnd)); static cl::opt<std::string> -OutputFilename("o", cl::init(""), - cl::desc("Override output filename"), - cl::value_desc("filename")); + ThinLTOIndex("thinlto-index", + cl::desc("Provide the index produced by a ThinLink, required " + "to perform the promotion and/or importing.")); + +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.")); + +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.")); -static cl::list<std::string> -ExportedSymbols("exported-symbol", - cl::desc("Symbol to export from the resulting object file"), - cl::ZeroOrMore); +static cl::opt<std::string> + ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching.")); + +static cl::opt<bool> + SaveModuleFile("save-merged-module", cl::init(false), + cl::desc("Write merged LTO module to file before CodeGen")); + +static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("<input bitcode files>")); + +static cl::opt<std::string> OutputFilename("o", cl::init(""), + cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::list<std::string> ExportedSymbols( + "exported-symbol", + cl::desc("List of symbols to export from the resulting object file"), + cl::ZeroOrMore); static cl::list<std::string> -DSOSymbols("dso-symbol", - cl::desc("Symbol to put in the symtab in the resulting dso"), - cl::ZeroOrMore); + DSOSymbols("dso-symbol", + cl::desc("Symbol to put in the symtab in the resulting dso"), + cl::ZeroOrMore); static cl::opt<bool> ListSymbolsOnly( "list-symbols-only", cl::init(false), @@ -98,6 +152,14 @@ static cl::opt<bool> SetMergedModule( static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1), cl::desc("Number of backend threads")); +static cl::opt<bool> RestoreGlobalsLinkage( + "restore-linkage", cl::init(false), + cl::desc("Restore original linkage of globals prior to CodeGen")); + +static cl::opt<bool> CheckHasObjC( + "check-for-objc", cl::init(false), + cl::desc("Only check if the module has objective-C defined in it")); + namespace { struct ModuleInfo { std::vector<bool> CanBeHidden; @@ -154,8 +216,8 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { exit(1); } -static void diagnosticHandlerWithContenxt(const DiagnosticInfo &DI, - void *Context) { +static void diagnosticHandlerWithContext(const DiagnosticInfo &DI, + void *Context) { diagnosticHandler(DI); } @@ -174,6 +236,11 @@ static void error(const ErrorOr<T> &V, const Twine &Prefix) { error(V.getError(), Prefix); } +static void maybeVerifyModule(const Module &Mod) { + if (!DisableVerify && verifyModule(Mod)) + error("Broken Module"); +} + static std::unique_ptr<LTOModule> getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer, const TargetOptions &Options) { @@ -182,9 +249,13 @@ getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer, error(BufferOrErr, "error loading file '" + Path + "'"); Buffer = std::move(BufferOrErr.get()); CurrentActivity = ("loading file '" + Path + "'").str(); + std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>(); + Context->setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true); ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext( - Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path); + std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(), + Options, Path); CurrentActivity = ""; + maybeVerifyModule((*Ret)->getModule()); return std::move(*Ret); } @@ -211,16 +282,17 @@ static void listSymbols(const TargetOptions &Options) { /// /// This is meant to enable testing of ThinLTO combined index generation, /// currently available via the gold plugin via -thinlto. -static void createCombinedFunctionIndex() { - FunctionInfoIndex CombinedIndex; +static void createCombinedModuleSummaryIndex() { + ModuleSummaryIndex CombinedIndex; uint64_t NextModuleId = 0; for (auto &Filename : InputFilenames) { CurrentActivity = "loading file '" + Filename + "'"; - ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr = - llvm::getFunctionIndexForFile(Filename, diagnosticHandler); - std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get()); + ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr = + llvm::getModuleSummaryIndexForFile(Filename, diagnosticHandler); + error(IndexOrErr, "error " + CurrentActivity); + std::unique_ptr<ModuleSummaryIndex> Index = std::move(IndexOrErr.get()); CurrentActivity = ""; - // Skip files without a function summary. + // Skip files without a module summary. if (!Index) continue; CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); @@ -230,13 +302,400 @@ static void createCombinedFunctionIndex() { raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'"); - WriteFunctionSummaryToFile(CombinedIndex, OS); + WriteIndexToFile(CombinedIndex, OS); OS.close(); } +/// Parse the thinlto_prefix_replace option into the \p OldPrefix and +/// \p NewPrefix strings, if it was specified. +static void getThinLTOOldAndNewPrefix(std::string &OldPrefix, + std::string &NewPrefix) { + assert(ThinLTOPrefixReplace.empty() || + ThinLTOPrefixReplace.find(";") != StringRef::npos); + StringRef PrefixReplace = ThinLTOPrefixReplace; + std::pair<StringRef, StringRef> Split = PrefixReplace.split(";"); + OldPrefix = Split.first.str(); + NewPrefix = Split.second.str(); +} + +/// Given the original \p Path to an output file, replace any path +/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the +/// resulting directory if it does not yet exist. +static std::string getThinLTOOutputFile(const std::string &Path, + const std::string &OldPrefix, + const std::string &NewPrefix) { + if (OldPrefix.empty() && NewPrefix.empty()) + return Path; + SmallString<128> NewPath(Path); + llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix); + StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str()); + if (!ParentPath.empty()) { + // Make sure the new directory exists, creating it if necessary. + if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath)) + error(EC, "error creating the directory '" + ParentPath + "'"); + } + return NewPath.str(); +} + +namespace thinlto { + +std::vector<std::unique_ptr<MemoryBuffer>> +loadAllFilesForIndex(const ModuleSummaryIndex &Index) { + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; + + for (auto &ModPath : Index.modulePaths()) { + const auto &Filename = ModPath.first(); + auto CurrentActivity = "loading file '" + Filename + "'"; + auto InputOrErr = MemoryBuffer::getFile(Filename); + error(InputOrErr, "error " + CurrentActivity); + InputBuffers.push_back(std::move(*InputOrErr)); + } + return InputBuffers; +} + +std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() { + if (ThinLTOIndex.empty()) + report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage"); + auto CurrentActivity = "loading file '" + ThinLTOIndex + "'"; + ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr = + llvm::getModuleSummaryIndexForFile(ThinLTOIndex, diagnosticHandler); + error(IndexOrErr, "error " + CurrentActivity); + return std::move(IndexOrErr.get()); +} + +static std::unique_ptr<Module> loadModule(StringRef Filename, + LLVMContext &Ctx) { + SMDiagnostic Err; + std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx)); + if (!M) { + Err.print("llvm-lto", errs()); + report_fatal_error("Can't load module for file " + Filename); + } + maybeVerifyModule(*M); + + if (ThinLTOModuleId.getNumOccurrences()) { + if (InputFilenames.size() != 1) + report_fatal_error("Can't override the module id for multiple files"); + M->setModuleIdentifier(ThinLTOModuleId); + } + return M; +} + +static void writeModuleToFile(Module &TheModule, StringRef Filename) { + std::error_code EC; + raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None); + error(EC, "error opening the file '" + Filename + "'"); + maybeVerifyModule(TheModule); + WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true); +} + +class ThinLTOProcessing { +public: + ThinLTOCodeGenerator ThinGenerator; + + ThinLTOProcessing(const TargetOptions &Options) { + ThinGenerator.setCodePICModel(getRelocModel()); + ThinGenerator.setTargetOptions(Options); + ThinGenerator.setCacheDir(ThinLTOCacheDir); + + // Add all the exported symbols to the table of symbols to preserve. + for (unsigned i = 0; i < ExportedSymbols.size(); ++i) + ThinGenerator.preserveSymbol(ExportedSymbols[i]); + } + + void run() { + switch (ThinLTOMode) { + case THINLINK: + return thinLink(); + case THINDISTRIBUTE: + return distributedIndexes(); + case THINEMITIMPORTS: + return emitImports(); + case THINPROMOTE: + return promote(); + case THINIMPORT: + return import(); + case THININTERNALIZE: + return internalize(); + case THINOPT: + return optimize(); + case THINCODEGEN: + return codegen(); + case THINALL: + return runAll(); + } + } + +private: + /// Load the input files, create the combined index, and write it out. + void thinLink() { + // Perform "ThinLink": just produce the index + if (OutputFilename.empty()) + report_fatal_error( + "OutputFilename is necessary to store the combined index.\n"); + + LLVMContext Ctx; + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; + for (unsigned i = 0; i < InputFilenames.size(); ++i) { + auto &Filename = InputFilenames[i]; + StringRef CurrentActivity = "loading file '" + Filename + "'"; + auto InputOrErr = MemoryBuffer::getFile(Filename); + error(InputOrErr, "error " + CurrentActivity); + InputBuffers.push_back(std::move(*InputOrErr)); + ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer()); + } + + auto CombinedIndex = ThinGenerator.linkCombinedIndex(); + std::error_code EC; + raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None); + error(EC, "error opening the file '" + OutputFilename + "'"); + WriteIndexToFile(*CombinedIndex, OS); + return; + } + + /// Load the combined index from disk, then compute and generate + /// individual index files suitable for ThinLTO distributed backend builds + /// on the files mentioned on the command line (these must match the index + /// content). + void distributedIndexes() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + + std::string OldPrefix, NewPrefix; + getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); + + auto Index = loadCombinedIndex(); + for (auto &Filename : InputFilenames) { + // Build a map of module to the GUIDs and summary objects that should + // be written to its index. + std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex; + ThinLTOCodeGenerator::gatherImportedSummariesForModule( + Filename, *Index, ModuleToSummariesForIndex); + + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.bc"; + } + OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix); + std::error_code EC; + raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None); + error(EC, "error opening the file '" + OutputName + "'"); + WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex); + } + } + + /// Load the combined index from disk, compute the imports, and emit + /// the import file lists for each module to disk. + void emitImports() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + + std::string OldPrefix, NewPrefix; + getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); + + auto Index = loadCombinedIndex(); + for (auto &Filename : InputFilenames) { + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".imports"; + } + OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix); + ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index); + } + } + + /// Load the combined index from disk, then load every file referenced by + /// the index and add them to the generator, finally perform the promotion + /// on the files mentioned on the command line (these must match the index + /// content). + void promote() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + + auto Index = loadCombinedIndex(); + for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + + ThinGenerator.promote(*TheModule, *Index); + + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.promoted.bc"; + } + writeModuleToFile(*TheModule, OutputName); + } + } + + /// Load the combined index from disk, then load every file referenced by + /// the index and add them to the generator, then performs the promotion and + /// cross module importing on the files mentioned on the command line + /// (these must match the index content). + void import() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + + auto Index = loadCombinedIndex(); + auto InputBuffers = loadAllFilesForIndex(*Index); + for (auto &MemBuffer : InputBuffers) + ThinGenerator.addModule(MemBuffer->getBufferIdentifier(), + MemBuffer->getBuffer()); + + for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + + ThinGenerator.crossModuleImport(*TheModule, *Index); + + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.imported.bc"; + } + writeModuleToFile(*TheModule, OutputName); + } + } + + void internalize() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + + if (ExportedSymbols.empty()) + errs() << "Warning: -internalize will not perform without " + "-exported-symbol\n"; + + auto Index = loadCombinedIndex(); + auto InputBuffers = loadAllFilesForIndex(*Index); + for (auto &MemBuffer : InputBuffers) + ThinGenerator.addModule(MemBuffer->getBufferIdentifier(), + MemBuffer->getBuffer()); + + for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + + ThinGenerator.internalize(*TheModule, *Index); + + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.internalized.bc"; + } + writeModuleToFile(*TheModule, OutputName); + } + } + + void optimize() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + if (!ThinLTOIndex.empty()) + errs() << "Warning: -thinlto-index ignored for optimize stage"; + + for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + + ThinGenerator.optimize(*TheModule); + + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.imported.bc"; + } + writeModuleToFile(*TheModule, OutputName); + } + } + + void codegen() { + if (InputFilenames.size() != 1 && !OutputFilename.empty()) + report_fatal_error("Can't handle a single output filename and multiple " + "input files, do not provide an output filename and " + "the output files will be suffixed from the input " + "ones."); + if (!ThinLTOIndex.empty()) + errs() << "Warning: -thinlto-index ignored for codegen stage"; + + for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + + auto Buffer = ThinGenerator.codegen(*TheModule); + std::string OutputName = OutputFilename; + if (OutputName.empty()) { + OutputName = Filename + ".thinlto.o"; + } + if (OutputName == "-") { + outs() << Buffer->getBuffer(); + return; + } + + std::error_code EC; + raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None); + error(EC, "error opening the file '" + OutputName + "'"); + OS << Buffer->getBuffer(); + } + } + + /// Full ThinLTO process + void runAll() { + if (!OutputFilename.empty()) + report_fatal_error("Do not provide an output filename for ThinLTO " + " processing, the output files will be suffixed from " + "the input ones."); + + if (!ThinLTOIndex.empty()) + errs() << "Warning: -thinlto-index ignored for full ThinLTO process"; + + LLVMContext Ctx; + std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; + for (unsigned i = 0; i < InputFilenames.size(); ++i) { + auto &Filename = InputFilenames[i]; + StringRef CurrentActivity = "loading file '" + Filename + "'"; + auto InputOrErr = MemoryBuffer::getFile(Filename); + error(InputOrErr, "error " + CurrentActivity); + InputBuffers.push_back(std::move(*InputOrErr)); + ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer()); + } + + ThinGenerator.run(); + + auto &Binaries = ThinGenerator.getProducedBinaries(); + if (Binaries.size() != InputFilenames.size()) + report_fatal_error("Number of output objects does not match the number " + "of inputs"); + + for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) { + auto OutputName = InputFilenames[BufID] + ".thinlto.o"; + std::error_code EC; + raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None); + error(EC, "error opening the file '" + OutputName + "'"); + OS << Binaries[BufID]->getBuffer(); + } + } + + /// Load the combined index from disk, then load every file referenced by +}; + +} // namespace thinlto + int main(int argc, char **argv) { // Print a stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(); + sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. @@ -259,25 +718,49 @@ int main(int argc, char **argv) { return 0; } + if (CheckHasObjC) { + for (auto &Filename : InputFilenames) { + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getFile(Filename); + error(BufferOrErr, "error loading file '" + Filename + "'"); + auto Buffer = std::move(BufferOrErr.get()); + LLVMContext Ctx; + if (llvm::isBitcodeContainingObjCCategory(*Buffer, Ctx)) + outs() << "Bitcode " << Filename << " contains ObjC\n"; + else + outs() << "Bitcode " << Filename << " does not contain ObjC\n"; + } + return 0; + } + + if (ThinLTOMode.getNumOccurrences()) { + if (ThinLTOMode.getNumOccurrences() > 1) + report_fatal_error("You can't specify more than one -thinlto-action"); + thinlto::ThinLTOProcessing ThinLTOProcessor(Options); + ThinLTOProcessor.run(); + return 0; + } + if (ThinLTO) { - createCombinedFunctionIndex(); + createCombinedModuleSummaryIndex(); return 0; } unsigned BaseArg = 0; LLVMContext Context; - Context.setDiagnosticHandler(diagnosticHandlerWithContenxt, nullptr, true); + Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true); LTOCodeGenerator CodeGen(Context); if (UseDiagnosticHandler) CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr); - CodeGen.setCodePICModel(RelocModel); + CodeGen.setCodePICModel(getRelocModel()); CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); + CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage); llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; for (unsigned i = 0; i < DSOSymbols.size(); ++i) @@ -289,7 +772,6 @@ int main(int argc, char **argv) { CurrentActivity = "loading file '" + InputFilenames[i] + "'"; ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr = LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options); - error(ModuleOrErr, "error " + CurrentActivity); std::unique_ptr<LTOModule> &Module = *ModuleOrErr; CurrentActivity = ""; @@ -311,8 +793,7 @@ int main(int argc, char **argv) { CodeGen.setModule(std::move(Module)); } else if (!CodeGen.addModule(Module.get())) { // Print a message here so that we know addModule() did not abort. - errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n"; - return 1; + error("error adding file '" + InputFilenames[i] + "'"); } } @@ -346,8 +827,7 @@ int main(int argc, char **argv) { if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, DisableLTOVectorization)) { // Diagnostic messages should have been printed by the handler. - errs() << argv[0] << ": error optimizing the code\n"; - return 1; + error("error optimizing the code"); } if (SaveModuleFile) { @@ -355,10 +835,8 @@ int main(int argc, char **argv) { ModuleFilename += ".merged.bc"; std::string ErrMsg; - if (!CodeGen.writeMergedModules(ModuleFilename.c_str())) { - errs() << argv[0] << ": writing merged module failed.\n"; - return 1; - } + if (!CodeGen.writeMergedModules(ModuleFilename.c_str())) + error("writing merged module failed."); } std::list<tool_output_file> OSs; @@ -369,40 +847,29 @@ int main(int argc, char **argv) { PartFilename += "." + utostr(I); std::error_code EC; OSs.emplace_back(PartFilename, EC, sys::fs::F_None); - if (EC) { - errs() << argv[0] << ": error opening the file '" << PartFilename - << "': " << EC.message() << "\n"; - return 1; - } + if (EC) + error("error opening the file '" + PartFilename + "': " + EC.message()); OSPtrs.push_back(&OSs.back().os()); } - if (!CodeGen.compileOptimized(OSPtrs)) { + if (!CodeGen.compileOptimized(OSPtrs)) // Diagnostic messages should have been printed by the handler. - errs() << argv[0] << ": error compiling the code\n"; - return 1; - } + error("error compiling the code"); for (tool_output_file &OS : OSs) OS.keep(); } else { - if (Parallelism != 1) { - errs() << argv[0] << ": -j must be specified together with -o\n"; - return 1; - } + if (Parallelism != 1) + error("-j must be specified together with -o"); - if (SaveModuleFile) { - errs() << argv[0] << ": -save-merged-module must be specified with -o\n"; - return 1; - } + if (SaveModuleFile) + error(": -save-merged-module must be specified with -o"); const char *OutputName = nullptr; if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline, - DisableGVNLoadPRE, DisableLTOVectorization)) { + DisableGVNLoadPRE, DisableLTOVectorization)) + error("error compiling the code"); // Diagnostic messages should have been printed by the handler. - errs() << argv[0] << ": error compiling the code\n"; - return 1; - } outs() << "Wrote native object file '" << OutputName << "'\n"; } |