llvm-lto.cpp revision 360784
1//===- llvm-lto: a simple command-line program to link modules with LTO ---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This program takes in a list of bitcode files, links them, performs link-time
10// optimization, and outputs an object file.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm-c/lto.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/SmallString.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/StringSet.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/Bitcode/BitcodeReader.h"
23#include "llvm/Bitcode/BitcodeWriter.h"
24#include "llvm/CodeGen/CommandFlags.inc"
25#include "llvm/IR/DiagnosticInfo.h"
26#include "llvm/IR/DiagnosticPrinter.h"
27#include "llvm/IR/LLVMContext.h"
28#include "llvm/IR/Module.h"
29#include "llvm/IR/ModuleSummaryIndex.h"
30#include "llvm/IR/Verifier.h"
31#include "llvm/IRReader/IRReader.h"
32#include "llvm/LTO/legacy/LTOCodeGenerator.h"
33#include "llvm/LTO/legacy/LTOModule.h"
34#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
35#include "llvm/Support/Allocator.h"
36#include "llvm/Support/Casting.h"
37#include "llvm/Support/CommandLine.h"
38#include "llvm/Support/Error.h"
39#include "llvm/Support/ErrorHandling.h"
40#include "llvm/Support/ErrorOr.h"
41#include "llvm/Support/FileSystem.h"
42#include "llvm/Support/InitLLVM.h"
43#include "llvm/Support/MemoryBuffer.h"
44#include "llvm/Support/Path.h"
45#include "llvm/Support/SourceMgr.h"
46#include "llvm/Support/TargetSelect.h"
47#include "llvm/Support/ToolOutputFile.h"
48#include "llvm/Support/raw_ostream.h"
49#include "llvm/Target/TargetOptions.h"
50#include <algorithm>
51#include <cassert>
52#include <cstdint>
53#include <cstdlib>
54#include <list>
55#include <map>
56#include <memory>
57#include <string>
58#include <system_error>
59#include <tuple>
60#include <utility>
61#include <vector>
62
63using namespace llvm;
64
65static cl::opt<char>
66    OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
67                           "(default = '-O2')"),
68             cl::Prefix, cl::ZeroOrMore, cl::init('2'));
69
70static cl::opt<bool>
71    IndexStats("thinlto-index-stats",
72               cl::desc("Print statistic for the index in every input files"),
73               cl::init(false));
74
75static cl::opt<bool> DisableVerify(
76    "disable-verify", cl::init(false),
77    cl::desc("Do not run the verifier during the optimization pipeline"));
78
79static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
80                                   cl::desc("Do not run the inliner pass"));
81
82static cl::opt<bool>
83    DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
84                      cl::desc("Do not run the GVN load PRE pass"));
85
86static cl::opt<bool> DisableLTOVectorization(
87    "disable-lto-vectorization", cl::init(false),
88    cl::desc("Do not run loop or slp vectorization during LTO"));
89
90static cl::opt<bool> EnableFreestanding(
91    "lto-freestanding", cl::init(false),
92    cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
93
94static cl::opt<bool> UseDiagnosticHandler(
95    "use-diagnostic-handler", cl::init(false),
96    cl::desc("Use a diagnostic handler to test the handler interface"));
97
98static cl::opt<bool>
99    ThinLTO("thinlto", cl::init(false),
100            cl::desc("Only write combined global index for ThinLTO backends"));
101
102enum ThinLTOModes {
103  THINLINK,
104  THINDISTRIBUTE,
105  THINEMITIMPORTS,
106  THINPROMOTE,
107  THINIMPORT,
108  THININTERNALIZE,
109  THINOPT,
110  THINCODEGEN,
111  THINALL
112};
113
114cl::opt<ThinLTOModes> ThinLTOMode(
115    "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
116    cl::values(
117        clEnumValN(
118            THINLINK, "thinlink",
119            "ThinLink: produces the index by linking only the summaries."),
120        clEnumValN(THINDISTRIBUTE, "distributedindexes",
121                   "Produces individual indexes for distributed backends."),
122        clEnumValN(THINEMITIMPORTS, "emitimports",
123                   "Emit imports files for distributed backends."),
124        clEnumValN(THINPROMOTE, "promote",
125                   "Perform pre-import promotion (requires -thinlto-index)."),
126        clEnumValN(THINIMPORT, "import", "Perform both promotion and "
127                                         "cross-module importing (requires "
128                                         "-thinlto-index)."),
129        clEnumValN(THININTERNALIZE, "internalize",
130                   "Perform internalization driven by -exported-symbol "
131                   "(requires -thinlto-index)."),
132        clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
133        clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
134        clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
135
136static cl::opt<std::string>
137    ThinLTOIndex("thinlto-index",
138                 cl::desc("Provide the index produced by a ThinLink, required "
139                          "to perform the promotion and/or importing."));
140
141static cl::opt<std::string> ThinLTOPrefixReplace(
142    "thinlto-prefix-replace",
143    cl::desc("Control where files for distributed backends are "
144             "created. Expects 'oldprefix;newprefix' and if path "
145             "prefix of output file is oldprefix it will be "
146             "replaced with newprefix."));
147
148static cl::opt<std::string> ThinLTOModuleId(
149    "thinlto-module-id",
150    cl::desc("For the module ID for the file to process, useful to "
151             "match what is in the index."));
152
153static cl::opt<std::string>
154    ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
155
156static cl::opt<int>
157    ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
158    cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
159
160static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
161    "thinlto-cache-max-size-bytes",
162    cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
163
164static cl::opt<int>
165    ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
166    cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
167
168static cl::opt<unsigned>
169    ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
170    cl::desc("Set ThinLTO cache entry expiration time."));
171
172static cl::opt<std::string> ThinLTOSaveTempsPrefix(
173    "thinlto-save-temps",
174    cl::desc("Save ThinLTO temp files using filenames created by adding "
175             "suffixes to the given file path prefix."));
176
177static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
178    "thinlto-save-objects",
179    cl::desc("Save ThinLTO generated object files using filenames created in "
180             "the given directory."));
181
182static cl::opt<bool>
183    SaveModuleFile("save-merged-module", cl::init(false),
184                   cl::desc("Write merged LTO module to file before CodeGen"));
185
186static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
187                                            cl::desc("<input bitcode files>"));
188
189static cl::opt<std::string> OutputFilename("o", cl::init(""),
190                                           cl::desc("Override output filename"),
191                                           cl::value_desc("filename"));
192
193static cl::list<std::string> ExportedSymbols(
194    "exported-symbol",
195    cl::desc("List of symbols to export from the resulting object file"),
196    cl::ZeroOrMore);
197
198static cl::list<std::string>
199    DSOSymbols("dso-symbol",
200               cl::desc("Symbol to put in the symtab in the resulting dso"),
201               cl::ZeroOrMore);
202
203static cl::opt<bool> ListSymbolsOnly(
204    "list-symbols-only", cl::init(false),
205    cl::desc("Instead of running LTO, list the symbols in each IR file"));
206
207static cl::opt<bool> ListDependentLibrariesOnly(
208    "list-dependent-libraries-only", cl::init(false),
209    cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
210
211static cl::opt<bool> SetMergedModule(
212    "set-merged-module", cl::init(false),
213    cl::desc("Use the first input module as the merged module"));
214
215static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
216                                     cl::desc("Number of backend threads"));
217
218static cl::opt<bool> RestoreGlobalsLinkage(
219    "restore-linkage", cl::init(false),
220    cl::desc("Restore original linkage of globals prior to CodeGen"));
221
222static cl::opt<bool> CheckHasObjC(
223    "check-for-objc", cl::init(false),
224    cl::desc("Only check if the module has objective-C defined in it"));
225
226namespace {
227
228struct ModuleInfo {
229  std::vector<bool> CanBeHidden;
230};
231
232} // end anonymous namespace
233
234static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
235                              const char *Msg, void *) {
236  errs() << "llvm-lto: ";
237  switch (Severity) {
238  case LTO_DS_NOTE:
239    errs() << "note: ";
240    break;
241  case LTO_DS_REMARK:
242    errs() << "remark: ";
243    break;
244  case LTO_DS_ERROR:
245    errs() << "error: ";
246    break;
247  case LTO_DS_WARNING:
248    errs() << "warning: ";
249    break;
250  }
251  errs() << Msg << "\n";
252}
253
254static std::string CurrentActivity;
255
256namespace {
257  struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
258    bool handleDiagnostics(const DiagnosticInfo &DI) override {
259      raw_ostream &OS = errs();
260      OS << "llvm-lto: ";
261      switch (DI.getSeverity()) {
262      case DS_Error:
263        OS << "error";
264        break;
265      case DS_Warning:
266        OS << "warning";
267        break;
268      case DS_Remark:
269        OS << "remark";
270        break;
271      case DS_Note:
272        OS << "note";
273        break;
274      }
275      if (!CurrentActivity.empty())
276        OS << ' ' << CurrentActivity;
277      OS << ": ";
278
279      DiagnosticPrinterRawOStream DP(OS);
280      DI.print(DP);
281      OS << '\n';
282
283      if (DI.getSeverity() == DS_Error)
284        exit(1);
285      return true;
286    }
287  };
288  }
289
290static void error(const Twine &Msg) {
291  errs() << "llvm-lto: " << Msg << '\n';
292  exit(1);
293}
294
295static void error(std::error_code EC, const Twine &Prefix) {
296  if (EC)
297    error(Prefix + ": " + EC.message());
298}
299
300template <typename T>
301static void error(const ErrorOr<T> &V, const Twine &Prefix) {
302  error(V.getError(), Prefix);
303}
304
305static void maybeVerifyModule(const Module &Mod) {
306  if (!DisableVerify && verifyModule(Mod, &errs()))
307    error("Broken Module");
308}
309
310static std::unique_ptr<LTOModule>
311getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
312                  const TargetOptions &Options) {
313  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
314      MemoryBuffer::getFile(Path);
315  error(BufferOrErr, "error loading file '" + Path + "'");
316  Buffer = std::move(BufferOrErr.get());
317  CurrentActivity = ("loading file '" + Path + "'").str();
318  std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
319  Context->setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
320                                true);
321  ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
322      std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
323      Options, Path);
324  CurrentActivity = "";
325  maybeVerifyModule((*Ret)->getModule());
326  return std::move(*Ret);
327}
328
329/// Print some statistics on the index for each input files.
330void printIndexStats() {
331  for (auto &Filename : InputFilenames) {
332    ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
333    std::unique_ptr<ModuleSummaryIndex> Index =
334        ExitOnErr(getModuleSummaryIndexForFile(Filename));
335    // Skip files without a module summary.
336    if (!Index)
337      report_fatal_error(Filename + " does not contain an index");
338
339    unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
340    for (auto &Summaries : *Index) {
341      for (auto &Summary : Summaries.second.SummaryList) {
342        Refs += Summary->refs().size();
343        if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
344          Functions++;
345          Calls += FuncSummary->calls().size();
346        } else if (isa<AliasSummary>(Summary.get()))
347          Alias++;
348        else
349          Globals++;
350      }
351    }
352    outs() << "Index " << Filename << " contains "
353           << (Alias + Globals + Functions) << " nodes (" << Functions
354           << " functions, " << Alias << " alias, " << Globals
355           << " globals) and " << (Calls + Refs) << " edges (" << Refs
356           << " refs and " << Calls << " calls)\n";
357  }
358}
359
360/// List symbols in each IR file.
361///
362/// The main point here is to provide lit-testable coverage for the LTOModule
363/// functionality that's exposed by the C API to list symbols.  Moreover, this
364/// provides testing coverage for modules that have been created in their own
365/// contexts.
366static void listSymbols(const TargetOptions &Options) {
367  for (auto &Filename : InputFilenames) {
368    std::unique_ptr<MemoryBuffer> Buffer;
369    std::unique_ptr<LTOModule> Module =
370        getLocalLTOModule(Filename, Buffer, Options);
371
372    // List the symbols.
373    outs() << Filename << ":\n";
374    for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
375      outs() << Module->getSymbolName(I) << "\n";
376  }
377}
378
379static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
380    ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
381        "': ");
382    return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
383}
384
385static void listDependentLibraries() {
386  for (auto &Filename : InputFilenames) {
387    auto Buffer = loadFile(Filename);
388    std::string E;
389    std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
390        Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
391        E));
392    if (!Input)
393      error(E);
394
395    // List the dependent libraries.
396    outs() << Filename << ":\n";
397    for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
398         I != C; ++I) {
399      size_t L = 0;
400      const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
401      assert(S);
402      outs() << StringRef(S, L) << "\n";
403    }
404  }
405}
406
407/// Create a combined index file from the input IR files and write it.
408///
409/// This is meant to enable testing of ThinLTO combined index generation,
410/// currently available via the gold plugin via -thinlto.
411static void createCombinedModuleSummaryIndex() {
412  ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
413  uint64_t NextModuleId = 0;
414  for (auto &Filename : InputFilenames) {
415    ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
416    std::unique_ptr<MemoryBuffer> MB =
417        ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
418    ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
419  }
420  std::error_code EC;
421  assert(!OutputFilename.empty());
422  raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
423                    sys::fs::OpenFlags::OF_None);
424  error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
425  WriteIndexToFile(CombinedIndex, OS);
426  OS.close();
427}
428
429/// Parse the thinlto_prefix_replace option into the \p OldPrefix and
430/// \p NewPrefix strings, if it was specified.
431static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
432                                      std::string &NewPrefix) {
433  assert(ThinLTOPrefixReplace.empty() ||
434         ThinLTOPrefixReplace.find(";") != StringRef::npos);
435  StringRef PrefixReplace = ThinLTOPrefixReplace;
436  std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
437  OldPrefix = Split.first.str();
438  NewPrefix = Split.second.str();
439}
440
441/// Given the original \p Path to an output file, replace any path
442/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
443/// resulting directory if it does not yet exist.
444static std::string getThinLTOOutputFile(const std::string &Path,
445                                        const std::string &OldPrefix,
446                                        const std::string &NewPrefix) {
447  if (OldPrefix.empty() && NewPrefix.empty())
448    return Path;
449  SmallString<128> NewPath(Path);
450  llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
451  StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
452  if (!ParentPath.empty()) {
453    // Make sure the new directory exists, creating it if necessary.
454    if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
455      error(EC, "error creating the directory '" + ParentPath + "'");
456  }
457  return NewPath.str();
458}
459
460namespace thinlto {
461
462std::vector<std::unique_ptr<MemoryBuffer>>
463loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
464  std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
465
466  for (auto &ModPath : Index.modulePaths()) {
467    const auto &Filename = ModPath.first();
468    std::string CurrentActivity = ("loading file '" + Filename + "'").str();
469    auto InputOrErr = MemoryBuffer::getFile(Filename);
470    error(InputOrErr, "error " + CurrentActivity);
471    InputBuffers.push_back(std::move(*InputOrErr));
472  }
473  return InputBuffers;
474}
475
476std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
477  if (ThinLTOIndex.empty())
478    report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
479  ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
480                        "': ");
481  return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
482}
483
484static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
485  ExitOnError ExitOnErr("llvm-lto: error loading input '" +
486                        Buffer.getBufferIdentifier().str() + "': ");
487  return ExitOnErr(lto::InputFile::create(Buffer));
488}
489
490static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
491                                                   LLVMContext &CTX) {
492  auto &Mod = File.getSingleBitcodeModule();
493  auto ModuleOrErr = Mod.parseModule(CTX);
494  if (!ModuleOrErr) {
495    handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
496      SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
497                                      SourceMgr::DK_Error, EIB.message());
498      Err.print("llvm-lto", errs());
499    });
500    report_fatal_error("Can't load module, abort.");
501  }
502  maybeVerifyModule(**ModuleOrErr);
503  if (ThinLTOModuleId.getNumOccurrences()) {
504    if (InputFilenames.size() != 1)
505      report_fatal_error("Can't override the module id for multiple files");
506    (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
507  }
508  return std::move(*ModuleOrErr);
509}
510
511static void writeModuleToFile(Module &TheModule, StringRef Filename) {
512  std::error_code EC;
513  raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
514  error(EC, "error opening the file '" + Filename + "'");
515  maybeVerifyModule(TheModule);
516  WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
517}
518
519class ThinLTOProcessing {
520public:
521  ThinLTOCodeGenerator ThinGenerator;
522
523  ThinLTOProcessing(const TargetOptions &Options) {
524    ThinGenerator.setCodePICModel(getRelocModel());
525    ThinGenerator.setTargetOptions(Options);
526    ThinGenerator.setCacheDir(ThinLTOCacheDir);
527    ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
528    ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
529    ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
530    ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
531    ThinGenerator.setFreestanding(EnableFreestanding);
532
533    // Add all the exported symbols to the table of symbols to preserve.
534    for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
535      ThinGenerator.preserveSymbol(ExportedSymbols[i]);
536  }
537
538  void run() {
539    switch (ThinLTOMode) {
540    case THINLINK:
541      return thinLink();
542    case THINDISTRIBUTE:
543      return distributedIndexes();
544    case THINEMITIMPORTS:
545      return emitImports();
546    case THINPROMOTE:
547      return promote();
548    case THINIMPORT:
549      return import();
550    case THININTERNALIZE:
551      return internalize();
552    case THINOPT:
553      return optimize();
554    case THINCODEGEN:
555      return codegen();
556    case THINALL:
557      return runAll();
558    }
559  }
560
561private:
562  /// Load the input files, create the combined index, and write it out.
563  void thinLink() {
564    // Perform "ThinLink": just produce the index
565    if (OutputFilename.empty())
566      report_fatal_error(
567          "OutputFilename is necessary to store the combined index.\n");
568
569    LLVMContext Ctx;
570    std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
571    for (unsigned i = 0; i < InputFilenames.size(); ++i) {
572      auto &Filename = InputFilenames[i];
573      std::string CurrentActivity = "loading file '" + Filename + "'";
574      auto InputOrErr = MemoryBuffer::getFile(Filename);
575      error(InputOrErr, "error " + CurrentActivity);
576      InputBuffers.push_back(std::move(*InputOrErr));
577      ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
578    }
579
580    auto CombinedIndex = ThinGenerator.linkCombinedIndex();
581    if (!CombinedIndex)
582      report_fatal_error("ThinLink didn't create an index");
583    std::error_code EC;
584    raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
585    error(EC, "error opening the file '" + OutputFilename + "'");
586    WriteIndexToFile(*CombinedIndex, OS);
587  }
588
589  /// Load the combined index from disk, then compute and generate
590  /// individual index files suitable for ThinLTO distributed backend builds
591  /// on the files mentioned on the command line (these must match the index
592  /// content).
593  void distributedIndexes() {
594    if (InputFilenames.size() != 1 && !OutputFilename.empty())
595      report_fatal_error("Can't handle a single output filename and multiple "
596                         "input files, do not provide an output filename and "
597                         "the output files will be suffixed from the input "
598                         "ones.");
599
600    std::string OldPrefix, NewPrefix;
601    getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
602
603    auto Index = loadCombinedIndex();
604    for (auto &Filename : InputFilenames) {
605      LLVMContext Ctx;
606      auto Buffer = loadFile(Filename);
607      auto Input = loadInputFile(Buffer->getMemBufferRef());
608      auto TheModule = loadModuleFromInput(*Input, Ctx);
609
610      // Build a map of module to the GUIDs and summary objects that should
611      // be written to its index.
612      std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
613      ThinGenerator.gatherImportedSummariesForModule(
614          *TheModule, *Index, ModuleToSummariesForIndex, *Input);
615
616      std::string OutputName = OutputFilename;
617      if (OutputName.empty()) {
618        OutputName = Filename + ".thinlto.bc";
619      }
620      OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
621      std::error_code EC;
622      raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
623      error(EC, "error opening the file '" + OutputName + "'");
624      WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
625    }
626  }
627
628  /// Load the combined index from disk, compute the imports, and emit
629  /// the import file lists for each module to disk.
630  void emitImports() {
631    if (InputFilenames.size() != 1 && !OutputFilename.empty())
632      report_fatal_error("Can't handle a single output filename and multiple "
633                         "input files, do not provide an output filename and "
634                         "the output files will be suffixed from the input "
635                         "ones.");
636
637    std::string OldPrefix, NewPrefix;
638    getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
639
640    auto Index = loadCombinedIndex();
641    for (auto &Filename : InputFilenames) {
642      LLVMContext Ctx;
643      auto Buffer = loadFile(Filename);
644      auto Input = loadInputFile(Buffer->getMemBufferRef());
645      auto TheModule = loadModuleFromInput(*Input, Ctx);
646      std::string OutputName = OutputFilename;
647      if (OutputName.empty()) {
648        OutputName = Filename + ".imports";
649      }
650      OutputName =
651          getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
652      ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
653    }
654  }
655
656  /// Load the combined index from disk, then load every file referenced by
657  /// the index and add them to the generator, finally perform the promotion
658  /// on the files mentioned on the command line (these must match the index
659  /// content).
660  void promote() {
661    if (InputFilenames.size() != 1 && !OutputFilename.empty())
662      report_fatal_error("Can't handle a single output filename and multiple "
663                         "input files, do not provide an output filename and "
664                         "the output files will be suffixed from the input "
665                         "ones.");
666
667    auto Index = loadCombinedIndex();
668    for (auto &Filename : InputFilenames) {
669      LLVMContext Ctx;
670      auto Buffer = loadFile(Filename);
671      auto Input = loadInputFile(Buffer->getMemBufferRef());
672      auto TheModule = loadModuleFromInput(*Input, Ctx);
673
674      ThinGenerator.promote(*TheModule, *Index, *Input);
675
676      std::string OutputName = OutputFilename;
677      if (OutputName.empty()) {
678        OutputName = Filename + ".thinlto.promoted.bc";
679      }
680      writeModuleToFile(*TheModule, OutputName);
681    }
682  }
683
684  /// Load the combined index from disk, then load every file referenced by
685  /// the index and add them to the generator, then performs the promotion and
686  /// cross module importing on the files mentioned on the command line
687  /// (these must match the index content).
688  void import() {
689    if (InputFilenames.size() != 1 && !OutputFilename.empty())
690      report_fatal_error("Can't handle a single output filename and multiple "
691                         "input files, do not provide an output filename and "
692                         "the output files will be suffixed from the input "
693                         "ones.");
694
695    auto Index = loadCombinedIndex();
696    auto InputBuffers = loadAllFilesForIndex(*Index);
697    for (auto &MemBuffer : InputBuffers)
698      ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
699                              MemBuffer->getBuffer());
700
701    for (auto &Filename : InputFilenames) {
702      LLVMContext Ctx;
703      auto Buffer = loadFile(Filename);
704      auto Input = loadInputFile(Buffer->getMemBufferRef());
705      auto TheModule = loadModuleFromInput(*Input, Ctx);
706
707      ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
708
709      std::string OutputName = OutputFilename;
710      if (OutputName.empty()) {
711        OutputName = Filename + ".thinlto.imported.bc";
712      }
713      writeModuleToFile(*TheModule, OutputName);
714    }
715  }
716
717  void internalize() {
718    if (InputFilenames.size() != 1 && !OutputFilename.empty())
719      report_fatal_error("Can't handle a single output filename and multiple "
720                         "input files, do not provide an output filename and "
721                         "the output files will be suffixed from the input "
722                         "ones.");
723
724    if (ExportedSymbols.empty())
725      errs() << "Warning: -internalize will not perform without "
726                "-exported-symbol\n";
727
728    auto Index = loadCombinedIndex();
729    auto InputBuffers = loadAllFilesForIndex(*Index);
730    for (auto &MemBuffer : InputBuffers)
731      ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
732                              MemBuffer->getBuffer());
733
734    for (auto &Filename : InputFilenames) {
735      LLVMContext Ctx;
736      auto Buffer = loadFile(Filename);
737      auto Input = loadInputFile(Buffer->getMemBufferRef());
738      auto TheModule = loadModuleFromInput(*Input, Ctx);
739
740      ThinGenerator.internalize(*TheModule, *Index, *Input);
741
742      std::string OutputName = OutputFilename;
743      if (OutputName.empty()) {
744        OutputName = Filename + ".thinlto.internalized.bc";
745      }
746      writeModuleToFile(*TheModule, OutputName);
747    }
748  }
749
750  void optimize() {
751    if (InputFilenames.size() != 1 && !OutputFilename.empty())
752      report_fatal_error("Can't handle a single output filename and multiple "
753                         "input files, do not provide an output filename and "
754                         "the output files will be suffixed from the input "
755                         "ones.");
756    if (!ThinLTOIndex.empty())
757      errs() << "Warning: -thinlto-index ignored for optimize stage";
758
759    for (auto &Filename : InputFilenames) {
760      LLVMContext Ctx;
761      auto Buffer = loadFile(Filename);
762      auto Input = loadInputFile(Buffer->getMemBufferRef());
763      auto TheModule = loadModuleFromInput(*Input, Ctx);
764
765      ThinGenerator.optimize(*TheModule);
766
767      std::string OutputName = OutputFilename;
768      if (OutputName.empty()) {
769        OutputName = Filename + ".thinlto.imported.bc";
770      }
771      writeModuleToFile(*TheModule, OutputName);
772    }
773  }
774
775  void codegen() {
776    if (InputFilenames.size() != 1 && !OutputFilename.empty())
777      report_fatal_error("Can't handle a single output filename and multiple "
778                         "input files, do not provide an output filename and "
779                         "the output files will be suffixed from the input "
780                         "ones.");
781    if (!ThinLTOIndex.empty())
782      errs() << "Warning: -thinlto-index ignored for codegen stage";
783
784    std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
785    for (auto &Filename : InputFilenames) {
786      LLVMContext Ctx;
787      auto InputOrErr = MemoryBuffer::getFile(Filename);
788      error(InputOrErr, "error " + CurrentActivity);
789      InputBuffers.push_back(std::move(*InputOrErr));
790      ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
791    }
792    ThinGenerator.setCodeGenOnly(true);
793    ThinGenerator.run();
794    for (auto BinName :
795         zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
796      std::string OutputName = OutputFilename;
797      if (OutputName.empty())
798        OutputName = std::get<1>(BinName) + ".thinlto.o";
799      else if (OutputName == "-") {
800        outs() << std::get<0>(BinName)->getBuffer();
801        return;
802      }
803
804      std::error_code EC;
805      raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
806      error(EC, "error opening the file '" + OutputName + "'");
807      OS << std::get<0>(BinName)->getBuffer();
808    }
809  }
810
811  /// Full ThinLTO process
812  void runAll() {
813    if (!OutputFilename.empty())
814      report_fatal_error("Do not provide an output filename for ThinLTO "
815                         " processing, the output files will be suffixed from "
816                         "the input ones.");
817
818    if (!ThinLTOIndex.empty())
819      errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
820
821    LLVMContext Ctx;
822    std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
823    for (unsigned i = 0; i < InputFilenames.size(); ++i) {
824      auto &Filename = InputFilenames[i];
825      std::string CurrentActivity = "loading file '" + Filename + "'";
826      auto InputOrErr = MemoryBuffer::getFile(Filename);
827      error(InputOrErr, "error " + CurrentActivity);
828      InputBuffers.push_back(std::move(*InputOrErr));
829      ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
830    }
831
832    if (!ThinLTOSaveTempsPrefix.empty())
833      ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
834
835    if (!ThinLTOGeneratedObjectsDir.empty()) {
836      ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
837      ThinGenerator.run();
838      return;
839    }
840
841    ThinGenerator.run();
842
843    auto &Binaries = ThinGenerator.getProducedBinaries();
844    if (Binaries.size() != InputFilenames.size())
845      report_fatal_error("Number of output objects does not match the number "
846                         "of inputs");
847
848    for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
849      auto OutputName = InputFilenames[BufID] + ".thinlto.o";
850      std::error_code EC;
851      raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
852      error(EC, "error opening the file '" + OutputName + "'");
853      OS << Binaries[BufID]->getBuffer();
854    }
855  }
856
857  /// Load the combined index from disk, then load every file referenced by
858};
859
860} // end namespace thinlto
861
862int main(int argc, char **argv) {
863  InitLLVM X(argc, argv);
864  cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
865
866  if (OptLevel < '0' || OptLevel > '3')
867    error("optimization level must be between 0 and 3");
868
869  // Initialize the configured targets.
870  InitializeAllTargets();
871  InitializeAllTargetMCs();
872  InitializeAllAsmPrinters();
873  InitializeAllAsmParsers();
874
875  // set up the TargetOptions for the machine
876  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
877
878  if (ListSymbolsOnly) {
879    listSymbols(Options);
880    return 0;
881  }
882
883  if (ListDependentLibrariesOnly) {
884    listDependentLibraries();
885    return 0;
886  }
887
888  if (IndexStats) {
889    printIndexStats();
890    return 0;
891  }
892
893  if (CheckHasObjC) {
894    for (auto &Filename : InputFilenames) {
895      ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
896                            Filename + "': ");
897      std::unique_ptr<MemoryBuffer> BufferOrErr =
898          ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
899      auto Buffer = std::move(BufferOrErr.get());
900      if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
901        outs() << "Bitcode " << Filename << " contains ObjC\n";
902      else
903        outs() << "Bitcode " << Filename << " does not contain ObjC\n";
904    }
905    return 0;
906  }
907
908  if (ThinLTOMode.getNumOccurrences()) {
909    if (ThinLTOMode.getNumOccurrences() > 1)
910      report_fatal_error("You can't specify more than one -thinlto-action");
911    thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
912    ThinLTOProcessor.run();
913    return 0;
914  }
915
916  if (ThinLTO) {
917    createCombinedModuleSummaryIndex();
918    return 0;
919  }
920
921  unsigned BaseArg = 0;
922
923  LLVMContext Context;
924  Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
925                               true);
926
927  LTOCodeGenerator CodeGen(Context);
928
929  if (UseDiagnosticHandler)
930    CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
931
932  CodeGen.setCodePICModel(getRelocModel());
933  CodeGen.setFreestanding(EnableFreestanding);
934
935  CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
936  CodeGen.setTargetOptions(Options);
937  CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
938
939  StringSet<MallocAllocator> DSOSymbolsSet;
940  for (unsigned i = 0; i < DSOSymbols.size(); ++i)
941    DSOSymbolsSet.insert(DSOSymbols[i]);
942
943  std::vector<std::string> KeptDSOSyms;
944
945  for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
946    CurrentActivity = "loading file '" + InputFilenames[i] + "'";
947    ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
948        LTOModule::createFromFile(Context, InputFilenames[i], Options);
949    std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
950    CurrentActivity = "";
951
952    unsigned NumSyms = Module->getSymbolCount();
953    for (unsigned I = 0; I < NumSyms; ++I) {
954      StringRef Name = Module->getSymbolName(I);
955      if (!DSOSymbolsSet.count(Name))
956        continue;
957      lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
958      unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
959      if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
960        KeptDSOSyms.push_back(Name);
961    }
962
963    // We use the first input module as the destination module when
964    // SetMergedModule is true.
965    if (SetMergedModule && i == BaseArg) {
966      // Transfer ownership to the code generator.
967      CodeGen.setModule(std::move(Module));
968    } else if (!CodeGen.addModule(Module.get())) {
969      // Print a message here so that we know addModule() did not abort.
970      error("error adding file '" + InputFilenames[i] + "'");
971    }
972  }
973
974  // Add all the exported symbols to the table of symbols to preserve.
975  for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
976    CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
977
978  // Add all the dso symbols to the table of symbols to expose.
979  for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
980    CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
981
982  // Set cpu and attrs strings for the default target/subtarget.
983  CodeGen.setCpu(MCPU.c_str());
984
985  CodeGen.setOptLevel(OptLevel - '0');
986
987  std::string attrs;
988  for (unsigned i = 0; i < MAttrs.size(); ++i) {
989    if (i > 0)
990      attrs.append(",");
991    attrs.append(MAttrs[i]);
992  }
993
994  if (!attrs.empty())
995    CodeGen.setAttr(attrs);
996
997  if (FileType.getNumOccurrences())
998    CodeGen.setFileType(FileType);
999
1000  if (!OutputFilename.empty()) {
1001    if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
1002                          DisableLTOVectorization)) {
1003      // Diagnostic messages should have been printed by the handler.
1004      error("error optimizing the code");
1005    }
1006
1007    if (SaveModuleFile) {
1008      std::string ModuleFilename = OutputFilename;
1009      ModuleFilename += ".merged.bc";
1010      std::string ErrMsg;
1011
1012      if (!CodeGen.writeMergedModules(ModuleFilename))
1013        error("writing merged module failed.");
1014    }
1015
1016    std::list<ToolOutputFile> OSs;
1017    std::vector<raw_pwrite_stream *> OSPtrs;
1018    for (unsigned I = 0; I != Parallelism; ++I) {
1019      std::string PartFilename = OutputFilename;
1020      if (Parallelism != 1)
1021        PartFilename += "." + utostr(I);
1022      std::error_code EC;
1023      OSs.emplace_back(PartFilename, EC, sys::fs::OF_None);
1024      if (EC)
1025        error("error opening the file '" + PartFilename + "': " + EC.message());
1026      OSPtrs.push_back(&OSs.back().os());
1027    }
1028
1029    if (!CodeGen.compileOptimized(OSPtrs))
1030      // Diagnostic messages should have been printed by the handler.
1031      error("error compiling the code");
1032
1033    for (ToolOutputFile &OS : OSs)
1034      OS.keep();
1035  } else {
1036    if (Parallelism != 1)
1037      error("-j must be specified together with -o");
1038
1039    if (SaveModuleFile)
1040      error(": -save-merged-module must be specified with -o");
1041
1042    const char *OutputName = nullptr;
1043    if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
1044                                 DisableGVNLoadPRE, DisableLTOVectorization))
1045      error("error compiling the code");
1046      // Diagnostic messages should have been printed by the handler.
1047
1048    outs() << "Wrote native object file '" << OutputName << "'\n";
1049  }
1050
1051  return 0;
1052}
1053