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