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