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