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