xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp (revision 62cfcf62f627e5093fb37026a6d8c98e4d2ef04c)
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 
63 using namespace llvm;
64 
65 static 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 
70 static 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 
75 static cl::opt<bool> DisableVerify(
76     "disable-verify", cl::init(false),
77     cl::desc("Do not run the verifier during the optimization pipeline"));
78 
79 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
80                                    cl::desc("Do not run the inliner pass"));
81 
82 static cl::opt<bool>
83     DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
84                       cl::desc("Do not run the GVN load PRE pass"));
85 
86 static cl::opt<bool> DisableLTOVectorization(
87     "disable-lto-vectorization", cl::init(false),
88     cl::desc("Do not run loop or slp vectorization during LTO"));
89 
90 static cl::opt<bool> EnableFreestanding(
91     "lto-freestanding", cl::init(false),
92     cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
93 
94 static cl::opt<bool> UseDiagnosticHandler(
95     "use-diagnostic-handler", cl::init(false),
96     cl::desc("Use a diagnostic handler to test the handler interface"));
97 
98 static cl::opt<bool>
99     ThinLTO("thinlto", cl::init(false),
100             cl::desc("Only write combined global index for ThinLTO backends"));
101 
102 enum ThinLTOModes {
103   THINLINK,
104   THINDISTRIBUTE,
105   THINEMITIMPORTS,
106   THINPROMOTE,
107   THINIMPORT,
108   THININTERNALIZE,
109   THINOPT,
110   THINCODEGEN,
111   THINALL
112 };
113 
114 cl::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 
136 static 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 
141 static 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 
148 static 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 
153 static cl::opt<std::string>
154     ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
155 
156 static cl::opt<int>
157     ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
158     cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
159 
160 static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
161     "thinlto-cache-max-size-bytes",
162     cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
163 
164 static 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 
168 static cl::opt<unsigned>
169     ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
170     cl::desc("Set ThinLTO cache entry expiration time."));
171 
172 static 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 
177 static 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 
182 static cl::opt<bool>
183     SaveModuleFile("save-merged-module", cl::init(false),
184                    cl::desc("Write merged LTO module to file before CodeGen"));
185 
186 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
187                                             cl::desc("<input bitcode files>"));
188 
189 static cl::opt<std::string> OutputFilename("o", cl::init(""),
190                                            cl::desc("Override output filename"),
191                                            cl::value_desc("filename"));
192 
193 static 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 
198 static 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 
203 static 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 
207 static 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 
211 static cl::opt<bool> SetMergedModule(
212     "set-merged-module", cl::init(false),
213     cl::desc("Use the first input module as the merged module"));
214 
215 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
216                                      cl::desc("Number of backend threads"));
217 
218 static cl::opt<bool> RestoreGlobalsLinkage(
219     "restore-linkage", cl::init(false),
220     cl::desc("Restore original linkage of globals prior to CodeGen"));
221 
222 static 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 
226 namespace {
227 
228 struct ModuleInfo {
229   std::vector<bool> CanBeHidden;
230 };
231 
232 } // end anonymous namespace
233 
234 static 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 
254 static std::string CurrentActivity;
255 
256 namespace {
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 
290 static void error(const Twine &Msg) {
291   errs() << "llvm-lto: " << Msg << '\n';
292   exit(1);
293 }
294 
295 static void error(std::error_code EC, const Twine &Prefix) {
296   if (EC)
297     error(Prefix + ": " + EC.message());
298 }
299 
300 template <typename T>
301 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
302   error(V.getError(), Prefix);
303 }
304 
305 static void maybeVerifyModule(const Module &Mod) {
306   if (!DisableVerify && verifyModule(Mod, &errs()))
307     error("Broken Module");
308 }
309 
310 static std::unique_ptr<LTOModule>
311 getLocalLTOModule(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.
330 void 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.
366 static 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 
379 static 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 
385 static 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.
411 static 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.
431 static 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.
444 static 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 
460 namespace thinlto {
461 
462 std::vector<std::unique_ptr<MemoryBuffer>>
463 loadAllFilesForIndex(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 
476 std::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 
484 static 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 
490 static 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 
511 static 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 
519 class ThinLTOProcessing {
520 public:
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 
561 private:
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 
862 int 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