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