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