1 //===- llvm-lto: a simple command-line program to link modules with LTO ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This program takes in a list of bitcode files, links them, performs link-time
11 // optimization, and outputs an object file.
13 //===----------------------------------------------------------------------===//
15 #include "llvm-c/lto.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Bitcode/BitcodeReader.h"
24 #include "llvm/Bitcode/BitcodeWriter.h"
25 #include "llvm/CodeGen/CommandFlags.def"
26 #include "llvm/IR/DiagnosticInfo.h"
27 #include "llvm/IR/DiagnosticPrinter.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/ModuleSummaryIndex.h"
31 #include "llvm/IR/Verifier.h"
32 #include "llvm/IRReader/IRReader.h"
33 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
34 #include "llvm/LTO/legacy/LTOModule.h"
35 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
36 #include "llvm/Support/Allocator.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Error.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/ErrorOr.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/ManagedStatic.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/Path.h"
46 #include "llvm/Support/PrettyStackTrace.h"
47 #include "llvm/Support/Signals.h"
48 #include "llvm/Support/SourceMgr.h"
49 #include "llvm/Support/TargetSelect.h"
50 #include "llvm/Support/ToolOutputFile.h"
51 #include "llvm/Support/raw_ostream.h"
52 #include "llvm/Target/TargetOptions.h"
61 #include <system_error>
69 OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
71 cl::Prefix, cl::ZeroOrMore, cl::init('2'));
74 IndexStats("thinlto-index-stats",
75 cl::desc("Print statistic for the index in every input files"),
78 static cl::opt<bool> DisableVerify(
79 "disable-verify", cl::init(false),
80 cl::desc("Do not run the verifier during the optimization pipeline"));
82 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
83 cl::desc("Do not run the inliner pass"));
86 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
87 cl::desc("Do not run the GVN load PRE pass"));
89 static cl::opt<bool> DisableLTOVectorization(
90 "disable-lto-vectorization", cl::init(false),
91 cl::desc("Do not run loop or slp vectorization during LTO"));
93 static cl::opt<bool> EnableFreestanding(
94 "lto-freestanding", cl::init(false),
95 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
97 static cl::opt<bool> UseDiagnosticHandler(
98 "use-diagnostic-handler", cl::init(false),
99 cl::desc("Use a diagnostic handler to test the handler interface"));
102 ThinLTO("thinlto", cl::init(false),
103 cl::desc("Only write combined global index for ThinLTO backends"));
117 cl::opt<ThinLTOModes> ThinLTOMode(
118 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
121 THINLINK, "thinlink",
122 "ThinLink: produces the index by linking only the summaries."),
123 clEnumValN(THINDISTRIBUTE, "distributedindexes",
124 "Produces individual indexes for distributed backends."),
125 clEnumValN(THINEMITIMPORTS, "emitimports",
126 "Emit imports files for distributed backends."),
127 clEnumValN(THINPROMOTE, "promote",
128 "Perform pre-import promotion (requires -thinlto-index)."),
129 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
130 "cross-module importing (requires "
132 clEnumValN(THININTERNALIZE, "internalize",
133 "Perform internalization driven by -exported-symbol "
134 "(requires -thinlto-index)."),
135 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
136 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
137 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
139 static cl::opt<std::string>
140 ThinLTOIndex("thinlto-index",
141 cl::desc("Provide the index produced by a ThinLink, required "
142 "to perform the promotion and/or importing."));
144 static cl::opt<std::string> ThinLTOPrefixReplace(
145 "thinlto-prefix-replace",
146 cl::desc("Control where files for distributed backends are "
147 "created. Expects 'oldprefix;newprefix' and if path "
148 "prefix of output file is oldprefix it will be "
149 "replaced with newprefix."));
151 static cl::opt<std::string> ThinLTOModuleId(
153 cl::desc("For the module ID for the file to process, useful to "
154 "match what is in the index."));
156 static cl::opt<std::string>
157 ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
160 ThinLTOCachePruningInterval("thinlto-cache-pruning-interval", cl::desc("Set ThinLTO cache pruning interval."));
162 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
163 "thinlto-save-temps",
164 cl::desc("Save ThinLTO temp files using filenames created by adding "
165 "suffixes to the given file path prefix."));
167 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
168 "thinlto-save-objects",
169 cl::desc("Save ThinLTO generated object files using filenames created in "
170 "the given directory."));
173 SaveModuleFile("save-merged-module", cl::init(false),
174 cl::desc("Write merged LTO module to file before CodeGen"));
176 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
177 cl::desc("<input bitcode files>"));
179 static cl::opt<std::string> OutputFilename("o", cl::init(""),
180 cl::desc("Override output filename"),
181 cl::value_desc("filename"));
183 static cl::list<std::string> ExportedSymbols(
185 cl::desc("List of symbols to export from the resulting object file"),
188 static cl::list<std::string>
189 DSOSymbols("dso-symbol",
190 cl::desc("Symbol to put in the symtab in the resulting dso"),
193 static cl::opt<bool> ListSymbolsOnly(
194 "list-symbols-only", cl::init(false),
195 cl::desc("Instead of running LTO, list the symbols in each IR file"));
197 static cl::opt<bool> SetMergedModule(
198 "set-merged-module", cl::init(false),
199 cl::desc("Use the first input module as the merged module"));
201 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
202 cl::desc("Number of backend threads"));
204 static cl::opt<bool> RestoreGlobalsLinkage(
205 "restore-linkage", cl::init(false),
206 cl::desc("Restore original linkage of globals prior to CodeGen"));
208 static cl::opt<bool> CheckHasObjC(
209 "check-for-objc", cl::init(false),
210 cl::desc("Only check if the module has objective-C defined in it"));
215 std::vector<bool> CanBeHidden;
218 } // end anonymous namespace
220 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
221 const char *Msg, void *) {
222 errs() << "llvm-lto: ";
228 errs() << "remark: ";
234 errs() << "warning: ";
237 errs() << Msg << "\n";
240 static std::string CurrentActivity;
243 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
244 bool handleDiagnostics(const DiagnosticInfo &DI) override {
245 raw_ostream &OS = errs();
247 switch (DI.getSeverity()) {
261 if (!CurrentActivity.empty())
262 OS << ' ' << CurrentActivity;
265 DiagnosticPrinterRawOStream DP(OS);
269 if (DI.getSeverity() == DS_Error)
276 static void error(const Twine &Msg) {
277 errs() << "llvm-lto: " << Msg << '\n';
281 static void error(std::error_code EC, const Twine &Prefix) {
283 error(Prefix + ": " + EC.message());
286 template <typename T>
287 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
288 error(V.getError(), Prefix);
291 static void maybeVerifyModule(const Module &Mod) {
292 if (!DisableVerify && verifyModule(Mod, &errs()))
293 error("Broken Module");
296 static std::unique_ptr<LTOModule>
297 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
298 const TargetOptions &Options) {
299 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
300 MemoryBuffer::getFile(Path);
301 error(BufferOrErr, "error loading file '" + Path + "'");
302 Buffer = std::move(BufferOrErr.get());
303 CurrentActivity = ("loading file '" + Path + "'").str();
304 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
305 Context->setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
307 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
308 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
310 CurrentActivity = "";
311 maybeVerifyModule((*Ret)->getModule());
312 return std::move(*Ret);
315 /// Print some statistics on the index for each input files.
316 void printIndexStats() {
317 for (auto &Filename : InputFilenames) {
318 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
319 std::unique_ptr<ModuleSummaryIndex> Index =
320 ExitOnErr(getModuleSummaryIndexForFile(Filename));
321 // Skip files without a module summary.
323 report_fatal_error(Filename + " does not contain an index");
325 unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
326 for (auto &Summaries : *Index) {
327 for (auto &Summary : Summaries.second.SummaryList) {
328 Refs += Summary->refs().size();
329 if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
331 Calls += FuncSummary->calls().size();
332 } else if (isa<AliasSummary>(Summary.get()))
338 outs() << "Index " << Filename << " contains "
339 << (Alias + Globals + Functions) << " nodes (" << Functions
340 << " functions, " << Alias << " alias, " << Globals
341 << " globals) and " << (Calls + Refs) << " edges (" << Refs
342 << " refs and " << Calls << " calls)\n";
346 /// \brief List symbols in each IR file.
348 /// The main point here is to provide lit-testable coverage for the LTOModule
349 /// functionality that's exposed by the C API to list symbols. Moreover, this
350 /// provides testing coverage for modules that have been created in their own
352 static void listSymbols(const TargetOptions &Options) {
353 for (auto &Filename : InputFilenames) {
354 std::unique_ptr<MemoryBuffer> Buffer;
355 std::unique_ptr<LTOModule> Module =
356 getLocalLTOModule(Filename, Buffer, Options);
359 outs() << Filename << ":\n";
360 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
361 outs() << Module->getSymbolName(I) << "\n";
365 /// Create a combined index file from the input IR files and write it.
367 /// This is meant to enable testing of ThinLTO combined index generation,
368 /// currently available via the gold plugin via -thinlto.
369 static void createCombinedModuleSummaryIndex() {
370 ModuleSummaryIndex CombinedIndex;
371 uint64_t NextModuleId = 0;
372 for (auto &Filename : InputFilenames) {
373 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
374 std::unique_ptr<MemoryBuffer> MB =
375 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
376 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, ++NextModuleId));
379 assert(!OutputFilename.empty());
380 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
381 sys::fs::OpenFlags::F_None);
382 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
383 WriteIndexToFile(CombinedIndex, OS);
387 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
388 /// \p NewPrefix strings, if it was specified.
389 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
390 std::string &NewPrefix) {
391 assert(ThinLTOPrefixReplace.empty() ||
392 ThinLTOPrefixReplace.find(";") != StringRef::npos);
393 StringRef PrefixReplace = ThinLTOPrefixReplace;
394 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
395 OldPrefix = Split.first.str();
396 NewPrefix = Split.second.str();
399 /// Given the original \p Path to an output file, replace any path
400 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
401 /// resulting directory if it does not yet exist.
402 static std::string getThinLTOOutputFile(const std::string &Path,
403 const std::string &OldPrefix,
404 const std::string &NewPrefix) {
405 if (OldPrefix.empty() && NewPrefix.empty())
407 SmallString<128> NewPath(Path);
408 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
409 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
410 if (!ParentPath.empty()) {
411 // Make sure the new directory exists, creating it if necessary.
412 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
413 error(EC, "error creating the directory '" + ParentPath + "'");
415 return NewPath.str();
420 std::vector<std::unique_ptr<MemoryBuffer>>
421 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
422 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
424 for (auto &ModPath : Index.modulePaths()) {
425 const auto &Filename = ModPath.first();
426 std::string CurrentActivity = ("loading file '" + Filename + "'").str();
427 auto InputOrErr = MemoryBuffer::getFile(Filename);
428 error(InputOrErr, "error " + CurrentActivity);
429 InputBuffers.push_back(std::move(*InputOrErr));
434 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
435 if (ThinLTOIndex.empty())
436 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
437 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
439 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
442 static std::unique_ptr<Module> loadModule(StringRef Filename,
445 std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
447 Err.print("llvm-lto", errs());
448 report_fatal_error("Can't load module for file " + Filename);
450 maybeVerifyModule(*M);
452 if (ThinLTOModuleId.getNumOccurrences()) {
453 if (InputFilenames.size() != 1)
454 report_fatal_error("Can't override the module id for multiple files");
455 M->setModuleIdentifier(ThinLTOModuleId);
460 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
462 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
463 error(EC, "error opening the file '" + Filename + "'");
464 maybeVerifyModule(TheModule);
465 WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
468 class ThinLTOProcessing {
470 ThinLTOCodeGenerator ThinGenerator;
472 ThinLTOProcessing(const TargetOptions &Options) {
473 ThinGenerator.setCodePICModel(getRelocModel());
474 ThinGenerator.setTargetOptions(Options);
475 ThinGenerator.setCacheDir(ThinLTOCacheDir);
476 ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
477 ThinGenerator.setFreestanding(EnableFreestanding);
479 // Add all the exported symbols to the table of symbols to preserve.
480 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
481 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
485 switch (ThinLTOMode) {
489 return distributedIndexes();
490 case THINEMITIMPORTS:
491 return emitImports();
496 case THININTERNALIZE:
497 return internalize();
508 /// Load the input files, create the combined index, and write it out.
510 // Perform "ThinLink": just produce the index
511 if (OutputFilename.empty())
513 "OutputFilename is necessary to store the combined index.\n");
516 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
517 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
518 auto &Filename = InputFilenames[i];
519 std::string CurrentActivity = "loading file '" + Filename + "'";
520 auto InputOrErr = MemoryBuffer::getFile(Filename);
521 error(InputOrErr, "error " + CurrentActivity);
522 InputBuffers.push_back(std::move(*InputOrErr));
523 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
526 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
528 report_fatal_error("ThinLink didn't create an index");
530 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
531 error(EC, "error opening the file '" + OutputFilename + "'");
532 WriteIndexToFile(*CombinedIndex, OS);
535 /// Load the combined index from disk, then compute and generate
536 /// individual index files suitable for ThinLTO distributed backend builds
537 /// on the files mentioned on the command line (these must match the index
539 void distributedIndexes() {
540 if (InputFilenames.size() != 1 && !OutputFilename.empty())
541 report_fatal_error("Can't handle a single output filename and multiple "
542 "input files, do not provide an output filename and "
543 "the output files will be suffixed from the input "
546 std::string OldPrefix, NewPrefix;
547 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
549 auto Index = loadCombinedIndex();
550 for (auto &Filename : InputFilenames) {
551 // Build a map of module to the GUIDs and summary objects that should
552 // be written to its index.
553 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
554 ThinLTOCodeGenerator::gatherImportedSummariesForModule(
555 Filename, *Index, ModuleToSummariesForIndex);
557 std::string OutputName = OutputFilename;
558 if (OutputName.empty()) {
559 OutputName = Filename + ".thinlto.bc";
561 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
563 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
564 error(EC, "error opening the file '" + OutputName + "'");
565 WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
569 /// Load the combined index from disk, compute the imports, and emit
570 /// the import file lists for each module to disk.
572 if (InputFilenames.size() != 1 && !OutputFilename.empty())
573 report_fatal_error("Can't handle a single output filename and multiple "
574 "input files, do not provide an output filename and "
575 "the output files will be suffixed from the input "
578 std::string OldPrefix, NewPrefix;
579 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
581 auto Index = loadCombinedIndex();
582 for (auto &Filename : InputFilenames) {
583 std::string OutputName = OutputFilename;
584 if (OutputName.empty()) {
585 OutputName = Filename + ".imports";
587 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
588 ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
592 /// Load the combined index from disk, then load every file referenced by
593 /// the index and add them to the generator, finally perform the promotion
594 /// on the files mentioned on the command line (these must match the index
597 if (InputFilenames.size() != 1 && !OutputFilename.empty())
598 report_fatal_error("Can't handle a single output filename and multiple "
599 "input files, do not provide an output filename and "
600 "the output files will be suffixed from the input "
603 auto Index = loadCombinedIndex();
604 for (auto &Filename : InputFilenames) {
606 auto TheModule = loadModule(Filename, Ctx);
608 ThinGenerator.promote(*TheModule, *Index);
610 std::string OutputName = OutputFilename;
611 if (OutputName.empty()) {
612 OutputName = Filename + ".thinlto.promoted.bc";
614 writeModuleToFile(*TheModule, OutputName);
618 /// Load the combined index from disk, then load every file referenced by
619 /// the index and add them to the generator, then performs the promotion and
620 /// cross module importing on the files mentioned on the command line
621 /// (these must match the index content).
623 if (InputFilenames.size() != 1 && !OutputFilename.empty())
624 report_fatal_error("Can't handle a single output filename and multiple "
625 "input files, do not provide an output filename and "
626 "the output files will be suffixed from the input "
629 auto Index = loadCombinedIndex();
630 auto InputBuffers = loadAllFilesForIndex(*Index);
631 for (auto &MemBuffer : InputBuffers)
632 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
633 MemBuffer->getBuffer());
635 for (auto &Filename : InputFilenames) {
637 auto TheModule = loadModule(Filename, Ctx);
639 ThinGenerator.crossModuleImport(*TheModule, *Index);
641 std::string OutputName = OutputFilename;
642 if (OutputName.empty()) {
643 OutputName = Filename + ".thinlto.imported.bc";
645 writeModuleToFile(*TheModule, OutputName);
650 if (InputFilenames.size() != 1 && !OutputFilename.empty())
651 report_fatal_error("Can't handle a single output filename and multiple "
652 "input files, do not provide an output filename and "
653 "the output files will be suffixed from the input "
656 if (ExportedSymbols.empty())
657 errs() << "Warning: -internalize will not perform without "
658 "-exported-symbol\n";
660 auto Index = loadCombinedIndex();
661 auto InputBuffers = loadAllFilesForIndex(*Index);
662 for (auto &MemBuffer : InputBuffers)
663 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
664 MemBuffer->getBuffer());
666 for (auto &Filename : InputFilenames) {
668 auto TheModule = loadModule(Filename, Ctx);
670 ThinGenerator.internalize(*TheModule, *Index);
672 std::string OutputName = OutputFilename;
673 if (OutputName.empty()) {
674 OutputName = Filename + ".thinlto.internalized.bc";
676 writeModuleToFile(*TheModule, OutputName);
681 if (InputFilenames.size() != 1 && !OutputFilename.empty())
682 report_fatal_error("Can't handle a single output filename and multiple "
683 "input files, do not provide an output filename and "
684 "the output files will be suffixed from the input "
686 if (!ThinLTOIndex.empty())
687 errs() << "Warning: -thinlto-index ignored for optimize stage";
689 for (auto &Filename : InputFilenames) {
691 auto TheModule = loadModule(Filename, Ctx);
693 ThinGenerator.optimize(*TheModule);
695 std::string OutputName = OutputFilename;
696 if (OutputName.empty()) {
697 OutputName = Filename + ".thinlto.imported.bc";
699 writeModuleToFile(*TheModule, OutputName);
704 if (InputFilenames.size() != 1 && !OutputFilename.empty())
705 report_fatal_error("Can't handle a single output filename and multiple "
706 "input files, do not provide an output filename and "
707 "the output files will be suffixed from the input "
709 if (!ThinLTOIndex.empty())
710 errs() << "Warning: -thinlto-index ignored for codegen stage";
712 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
713 for (auto &Filename : InputFilenames) {
715 auto InputOrErr = MemoryBuffer::getFile(Filename);
716 error(InputOrErr, "error " + CurrentActivity);
717 InputBuffers.push_back(std::move(*InputOrErr));
718 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
720 ThinGenerator.setCodeGenOnly(true);
723 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
724 std::string OutputName = OutputFilename;
725 if (OutputName.empty())
726 OutputName = std::get<1>(BinName) + ".thinlto.o";
727 else if (OutputName == "-") {
728 outs() << std::get<0>(BinName)->getBuffer();
733 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
734 error(EC, "error opening the file '" + OutputName + "'");
735 OS << std::get<0>(BinName)->getBuffer();
739 /// Full ThinLTO process
741 if (!OutputFilename.empty())
742 report_fatal_error("Do not provide an output filename for ThinLTO "
743 " processing, the output files will be suffixed from "
746 if (!ThinLTOIndex.empty())
747 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
750 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
751 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
752 auto &Filename = InputFilenames[i];
753 std::string CurrentActivity = "loading file '" + Filename + "'";
754 auto InputOrErr = MemoryBuffer::getFile(Filename);
755 error(InputOrErr, "error " + CurrentActivity);
756 InputBuffers.push_back(std::move(*InputOrErr));
757 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
760 if (!ThinLTOSaveTempsPrefix.empty())
761 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
763 if (!ThinLTOGeneratedObjectsDir.empty()) {
764 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
771 auto &Binaries = ThinGenerator.getProducedBinaries();
772 if (Binaries.size() != InputFilenames.size())
773 report_fatal_error("Number of output objects does not match the number "
776 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
777 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
779 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
780 error(EC, "error opening the file '" + OutputName + "'");
781 OS << Binaries[BufID]->getBuffer();
785 /// Load the combined index from disk, then load every file referenced by
788 } // end namespace thinlto
790 int main(int argc, char **argv) {
791 // Print a stack trace if we signal out.
792 sys::PrintStackTraceOnErrorSignal(argv[0]);
793 PrettyStackTraceProgram X(argc, argv);
795 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
796 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
798 if (OptLevel < '0' || OptLevel > '3')
799 error("optimization level must be between 0 and 3");
801 // Initialize the configured targets.
802 InitializeAllTargets();
803 InitializeAllTargetMCs();
804 InitializeAllAsmPrinters();
805 InitializeAllAsmParsers();
807 // set up the TargetOptions for the machine
808 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
810 if (ListSymbolsOnly) {
811 listSymbols(Options);
821 for (auto &Filename : InputFilenames) {
822 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
824 std::unique_ptr<MemoryBuffer> BufferOrErr =
825 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
826 auto Buffer = std::move(BufferOrErr.get());
827 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
828 outs() << "Bitcode " << Filename << " contains ObjC\n";
830 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
835 if (ThinLTOMode.getNumOccurrences()) {
836 if (ThinLTOMode.getNumOccurrences() > 1)
837 report_fatal_error("You can't specify more than one -thinlto-action");
838 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
839 ThinLTOProcessor.run();
844 createCombinedModuleSummaryIndex();
848 unsigned BaseArg = 0;
851 Context.setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
854 LTOCodeGenerator CodeGen(Context);
856 if (UseDiagnosticHandler)
857 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
859 CodeGen.setCodePICModel(getRelocModel());
860 CodeGen.setFreestanding(EnableFreestanding);
862 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
863 CodeGen.setTargetOptions(Options);
864 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
866 StringSet<MallocAllocator> DSOSymbolsSet;
867 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
868 DSOSymbolsSet.insert(DSOSymbols[i]);
870 std::vector<std::string> KeptDSOSyms;
872 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
873 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
874 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
875 LTOModule::createFromFile(Context, InputFilenames[i], Options);
876 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
877 CurrentActivity = "";
879 unsigned NumSyms = Module->getSymbolCount();
880 for (unsigned I = 0; I < NumSyms; ++I) {
881 StringRef Name = Module->getSymbolName(I);
882 if (!DSOSymbolsSet.count(Name))
884 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
885 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
886 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
887 KeptDSOSyms.push_back(Name);
890 // We use the first input module as the destination module when
891 // SetMergedModule is true.
892 if (SetMergedModule && i == BaseArg) {
893 // Transfer ownership to the code generator.
894 CodeGen.setModule(std::move(Module));
895 } else if (!CodeGen.addModule(Module.get())) {
896 // Print a message here so that we know addModule() did not abort.
897 error("error adding file '" + InputFilenames[i] + "'");
901 // Add all the exported symbols to the table of symbols to preserve.
902 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
903 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
905 // Add all the dso symbols to the table of symbols to expose.
906 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
907 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
909 // Set cpu and attrs strings for the default target/subtarget.
910 CodeGen.setCpu(MCPU.c_str());
912 CodeGen.setOptLevel(OptLevel - '0');
915 for (unsigned i = 0; i < MAttrs.size(); ++i) {
918 attrs.append(MAttrs[i]);
922 CodeGen.setAttr(attrs);
924 if (FileType.getNumOccurrences())
925 CodeGen.setFileType(FileType);
927 if (!OutputFilename.empty()) {
928 if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
929 DisableLTOVectorization)) {
930 // Diagnostic messages should have been printed by the handler.
931 error("error optimizing the code");
934 if (SaveModuleFile) {
935 std::string ModuleFilename = OutputFilename;
936 ModuleFilename += ".merged.bc";
939 if (!CodeGen.writeMergedModules(ModuleFilename))
940 error("writing merged module failed.");
943 std::list<ToolOutputFile> OSs;
944 std::vector<raw_pwrite_stream *> OSPtrs;
945 for (unsigned I = 0; I != Parallelism; ++I) {
946 std::string PartFilename = OutputFilename;
947 if (Parallelism != 1)
948 PartFilename += "." + utostr(I);
950 OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
952 error("error opening the file '" + PartFilename + "': " + EC.message());
953 OSPtrs.push_back(&OSs.back().os());
956 if (!CodeGen.compileOptimized(OSPtrs))
957 // Diagnostic messages should have been printed by the handler.
958 error("error compiling the code");
960 for (ToolOutputFile &OS : OSs)
963 if (Parallelism != 1)
964 error("-j must be specified together with -o");
967 error(": -save-merged-module must be specified with -o");
969 const char *OutputName = nullptr;
970 if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
971 DisableGVNLoadPRE, DisableLTOVectorization))
972 error("error compiling the code");
973 // Diagnostic messages should have been printed by the handler.
975 outs() << "Wrote native object file '" << OutputName << "'\n";