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