xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 static 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 
handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,const char * Msg,void *)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 {
handleDiagnostics__anon64d5c3870211::LLVMLTODiagnosticHandler299     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 
error(const Twine & Msg)331 static void error(const Twine &Msg) {
332   errs() << "llvm-lto: " << Msg << '\n';
333   exit(1);
334 }
335 
error(std::error_code EC,const Twine & Prefix)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>
error(const ErrorOr<T> & V,const Twine & Prefix)342 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
343   error(V.getError(), Prefix);
344 }
345 
maybeVerifyModule(const Module & Mod)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>
getLocalLTOModule(StringRef Path,std::unique_ptr<MemoryBuffer> & Buffer,const TargetOptions & Options)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.
printIndexStats()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 /// Print the lto symbol attributes.
printLTOSymbolAttributes(lto_symbol_attributes Attrs)402 static void printLTOSymbolAttributes(lto_symbol_attributes Attrs) {
403   outs() << "{ ";
404   unsigned Permission = Attrs & LTO_SYMBOL_PERMISSIONS_MASK;
405   switch (Permission) {
406   case LTO_SYMBOL_PERMISSIONS_CODE:
407     outs() << "function ";
408     break;
409   case LTO_SYMBOL_PERMISSIONS_DATA:
410     outs() << "data ";
411     break;
412   case LTO_SYMBOL_PERMISSIONS_RODATA:
413     outs() << "constant ";
414     break;
415   }
416   unsigned Definition = Attrs & LTO_SYMBOL_DEFINITION_MASK;
417   switch (Definition) {
418   case LTO_SYMBOL_DEFINITION_REGULAR:
419     outs() << "defined ";
420     break;
421   case LTO_SYMBOL_DEFINITION_TENTATIVE:
422     outs() << "common ";
423     break;
424   case LTO_SYMBOL_DEFINITION_WEAK:
425     outs() << "weak ";
426     break;
427   case LTO_SYMBOL_DEFINITION_UNDEFINED:
428     outs() << "extern ";
429     break;
430   case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
431     outs() << "extern-weak ";
432     break;
433   }
434   unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
435   switch (Scope) {
436   case LTO_SYMBOL_SCOPE_INTERNAL:
437     outs() << "internal ";
438     break;
439   case LTO_SYMBOL_SCOPE_HIDDEN:
440     outs() << "hidden ";
441     break;
442   case LTO_SYMBOL_SCOPE_PROTECTED:
443     outs() << "protected ";
444     break;
445   case LTO_SYMBOL_SCOPE_DEFAULT:
446     outs() << "default ";
447     break;
448   case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN:
449     outs() << "omitted ";
450     break;
451   }
452   if (Attrs & LTO_SYMBOL_COMDAT)
453     outs() << "comdat ";
454   if (Attrs & LTO_SYMBOL_ALIAS)
455     outs() << "alias ";
456   outs() << "}";
457 }
458 
459 /// Load each IR file and dump certain information based on active flags.
460 ///
461 /// The main point here is to provide lit-testable coverage for the LTOModule
462 /// functionality that's exposed by the C API. Moreover, this provides testing
463 /// coverage for modules that have been created in their own contexts.
testLTOModule(const TargetOptions & Options)464 static void testLTOModule(const TargetOptions &Options) {
465   for (auto &Filename : InputFilenames) {
466     std::unique_ptr<MemoryBuffer> Buffer;
467     std::unique_ptr<LTOModule> Module =
468         getLocalLTOModule(Filename, Buffer, Options);
469 
470     if (ListSymbolsOnly) {
471       // List the symbols.
472       outs() << Filename << ":\n";
473       for (int I = 0, E = Module->getSymbolCount(); I != E; ++I) {
474         outs() << Module->getSymbolName(I) << "    ";
475         printLTOSymbolAttributes(Module->getSymbolAttributes(I));
476         outs() << "\n";
477       }
478       for (int I = 0, E = Module->getAsmUndefSymbolCount(); I != E; ++I)
479         outs() << Module->getAsmUndefSymbolName(I) << "    { asm extern }\n";
480     }
481     if (QueryHasCtorDtor)
482       outs() << Filename
483              << ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
484              << "\n";
485   }
486 }
487 
loadFile(StringRef Filename)488 static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
489     ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
490         "': ");
491     return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
492 }
493 
listDependentLibraries()494 static void listDependentLibraries() {
495   for (auto &Filename : InputFilenames) {
496     auto Buffer = loadFile(Filename);
497     std::string E;
498     std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
499         Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
500         E));
501     if (!Input)
502       error(E);
503 
504     // List the dependent libraries.
505     outs() << Filename << ":\n";
506     for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
507          I != C; ++I) {
508       size_t L = 0;
509       const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
510       assert(S);
511       outs() << StringRef(S, L) << "\n";
512     }
513   }
514 }
515 
printMachOCPUOnly()516 static void printMachOCPUOnly() {
517   LLVMContext Context;
518   Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
519                                true);
520   TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
521   for (auto &Filename : InputFilenames) {
522     ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
523         LTOModule::createFromFile(Context, Filename, Options);
524     if (!ModuleOrErr)
525       error(ModuleOrErr, "llvm-lto: ");
526 
527     Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
528     Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
529     if (!CPUType)
530       error("Error while printing mach-o cputype: " +
531             toString(CPUType.takeError()));
532     if (!CPUSubType)
533       error("Error while printing mach-o cpusubtype: " +
534             toString(CPUSubType.takeError()));
535     outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
536                            Filename.c_str(), *CPUType, *CPUSubType);
537   }
538 }
539 
540 /// Create a combined index file from the input IR files and write it.
541 ///
542 /// This is meant to enable testing of ThinLTO combined index generation,
543 /// currently available via the gold plugin via -thinlto.
createCombinedModuleSummaryIndex()544 static void createCombinedModuleSummaryIndex() {
545   ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
546   for (auto &Filename : InputFilenames) {
547     ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
548     std::unique_ptr<MemoryBuffer> MB =
549         ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
550     ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex));
551   }
552   // In order to use this index for testing, specifically import testing, we
553   // need to update any indirect call edges created from SamplePGO, so that they
554   // point to the correct GUIDs.
555   updateIndirectCalls(CombinedIndex);
556   std::error_code EC;
557   assert(!OutputFilename.empty());
558   raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
559                     sys::fs::OpenFlags::OF_None);
560   error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
561   writeIndexToFile(CombinedIndex, OS);
562   OS.close();
563 }
564 
565 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
566 /// \p NewPrefix strings, if it was specified.
getThinLTOOldAndNewPrefix(std::string & OldPrefix,std::string & NewPrefix)567 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
568                                       std::string &NewPrefix) {
569   assert(ThinLTOPrefixReplace.empty() ||
570          ThinLTOPrefixReplace.find(';') != StringRef::npos);
571   StringRef PrefixReplace = ThinLTOPrefixReplace;
572   std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
573   OldPrefix = Split.first.str();
574   NewPrefix = Split.second.str();
575 }
576 
577 /// Given the original \p Path to an output file, replace any path
578 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
579 /// resulting directory if it does not yet exist.
getThinLTOOutputFile(StringRef Path,StringRef OldPrefix,StringRef NewPrefix)580 static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
581                                         StringRef NewPrefix) {
582   if (OldPrefix.empty() && NewPrefix.empty())
583     return std::string(Path);
584   SmallString<128> NewPath(Path);
585   llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
586   StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
587   if (!ParentPath.empty()) {
588     // Make sure the new directory exists, creating it if necessary.
589     if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
590       error(EC, "error creating the directory '" + ParentPath + "'");
591   }
592   return std::string(NewPath);
593 }
594 
595 namespace thinlto {
596 
597 std::vector<std::unique_ptr<MemoryBuffer>>
loadAllFilesForIndex(const ModuleSummaryIndex & Index)598 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
599   std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
600 
601   for (auto &ModPath : Index.modulePaths()) {
602     const auto &Filename = ModPath.first();
603     std::string CurrentActivity = ("loading file '" + Filename + "'").str();
604     auto InputOrErr = MemoryBuffer::getFile(Filename);
605     error(InputOrErr, "error " + CurrentActivity);
606     InputBuffers.push_back(std::move(*InputOrErr));
607   }
608   return InputBuffers;
609 }
610 
loadCombinedIndex()611 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
612   if (ThinLTOIndex.empty())
613     report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
614   ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
615                         "': ");
616   return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
617 }
618 
loadInputFile(MemoryBufferRef Buffer)619 static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
620   ExitOnError ExitOnErr("llvm-lto: error loading input '" +
621                         Buffer.getBufferIdentifier().str() + "': ");
622   return ExitOnErr(lto::InputFile::create(Buffer));
623 }
624 
loadModuleFromInput(lto::InputFile & File,LLVMContext & CTX)625 static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
626                                                    LLVMContext &CTX) {
627   auto &Mod = File.getSingleBitcodeModule();
628   auto ModuleOrErr = Mod.parseModule(CTX);
629   if (!ModuleOrErr) {
630     handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
631       SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
632                                       SourceMgr::DK_Error, EIB.message());
633       Err.print("llvm-lto", errs());
634     });
635     report_fatal_error("Can't load module, abort.");
636   }
637   maybeVerifyModule(**ModuleOrErr);
638   if (ThinLTOModuleId.getNumOccurrences()) {
639     if (InputFilenames.size() != 1)
640       report_fatal_error("Can't override the module id for multiple files");
641     (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
642   }
643   return std::move(*ModuleOrErr);
644 }
645 
writeModuleToFile(Module & TheModule,StringRef Filename)646 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
647   std::error_code EC;
648   raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
649   error(EC, "error opening the file '" + Filename + "'");
650   maybeVerifyModule(TheModule);
651   WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
652 }
653 
654 class ThinLTOProcessing {
655 public:
656   ThinLTOCodeGenerator ThinGenerator;
657 
ThinLTOProcessing(const TargetOptions & Options)658   ThinLTOProcessing(const TargetOptions &Options) {
659     ThinGenerator.setCodePICModel(codegen::getExplicitRelocModel());
660     ThinGenerator.setTargetOptions(Options);
661     ThinGenerator.setCacheDir(ThinLTOCacheDir);
662     ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
663     ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
664     ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
665     ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
666     ThinGenerator.setFreestanding(EnableFreestanding);
667     ThinGenerator.setDebugPassManager(DebugPassManager);
668 
669     // Add all the exported symbols to the table of symbols to preserve.
670     for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
671       ThinGenerator.preserveSymbol(ExportedSymbols[i]);
672   }
673 
run()674   void run() {
675     switch (ThinLTOMode) {
676     case THINLINK:
677       return thinLink();
678     case THINDISTRIBUTE:
679       return distributedIndexes();
680     case THINEMITIMPORTS:
681       return emitImports();
682     case THINPROMOTE:
683       return promote();
684     case THINIMPORT:
685       return import();
686     case THININTERNALIZE:
687       return internalize();
688     case THINOPT:
689       return optimize();
690     case THINCODEGEN:
691       return codegen();
692     case THINALL:
693       return runAll();
694     }
695   }
696 
697 private:
698   /// Load the input files, create the combined index, and write it out.
thinLink()699   void thinLink() {
700     // Perform "ThinLink": just produce the index
701     if (OutputFilename.empty())
702       report_fatal_error(
703           "OutputFilename is necessary to store the combined index.\n");
704 
705     LLVMContext Ctx;
706     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
707     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
708       auto &Filename = InputFilenames[i];
709       std::string CurrentActivity = "loading file '" + Filename + "'";
710       auto InputOrErr = MemoryBuffer::getFile(Filename);
711       error(InputOrErr, "error " + CurrentActivity);
712       InputBuffers.push_back(std::move(*InputOrErr));
713       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
714     }
715 
716     auto CombinedIndex = ThinGenerator.linkCombinedIndex();
717     if (!CombinedIndex)
718       report_fatal_error("ThinLink didn't create an index");
719     std::error_code EC;
720     raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
721     error(EC, "error opening the file '" + OutputFilename + "'");
722     writeIndexToFile(*CombinedIndex, OS);
723   }
724 
725   /// Load the combined index from disk, then compute and generate
726   /// individual index files suitable for ThinLTO distributed backend builds
727   /// on the files mentioned on the command line (these must match the index
728   /// content).
distributedIndexes()729   void distributedIndexes() {
730     if (InputFilenames.size() != 1 && !OutputFilename.empty())
731       report_fatal_error("Can't handle a single output filename and multiple "
732                          "input files, do not provide an output filename and "
733                          "the output files will be suffixed from the input "
734                          "ones.");
735 
736     std::string OldPrefix, NewPrefix;
737     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
738 
739     auto Index = loadCombinedIndex();
740     for (auto &Filename : InputFilenames) {
741       LLVMContext Ctx;
742       auto Buffer = loadFile(Filename);
743       auto Input = loadInputFile(Buffer->getMemBufferRef());
744       auto TheModule = loadModuleFromInput(*Input, Ctx);
745 
746       // Build a map of module to the GUIDs and summary objects that should
747       // be written to its index.
748       ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
749       GVSummaryPtrSet DecSummaries;
750       ThinGenerator.gatherImportedSummariesForModule(
751           *TheModule, *Index, ModuleToSummariesForIndex, DecSummaries, *Input);
752 
753       std::string OutputName = OutputFilename;
754       if (OutputName.empty()) {
755         OutputName = Filename + ".thinlto.bc";
756       }
757       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
758       std::error_code EC;
759       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
760       error(EC, "error opening the file '" + OutputName + "'");
761       writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex, &DecSummaries);
762     }
763   }
764 
765   /// Load the combined index from disk, compute the imports, and emit
766   /// the import file lists for each module to disk.
emitImports()767   void emitImports() {
768     if (InputFilenames.size() != 1 && !OutputFilename.empty())
769       report_fatal_error("Can't handle a single output filename and multiple "
770                          "input files, do not provide an output filename and "
771                          "the output files will be suffixed from the input "
772                          "ones.");
773 
774     std::string OldPrefix, NewPrefix;
775     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
776 
777     auto Index = loadCombinedIndex();
778     for (auto &Filename : InputFilenames) {
779       LLVMContext Ctx;
780       auto Buffer = loadFile(Filename);
781       auto Input = loadInputFile(Buffer->getMemBufferRef());
782       auto TheModule = loadModuleFromInput(*Input, Ctx);
783       std::string OutputName = OutputFilename;
784       if (OutputName.empty()) {
785         OutputName = Filename + ".imports";
786       }
787       OutputName =
788           getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
789       ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
790     }
791   }
792 
793   /// Load the combined index from disk, then load every file referenced by
794   /// the index and add them to the generator, finally perform the promotion
795   /// on the files mentioned on the command line (these must match the index
796   /// content).
promote()797   void promote() {
798     if (InputFilenames.size() != 1 && !OutputFilename.empty())
799       report_fatal_error("Can't handle a single output filename and multiple "
800                          "input files, do not provide an output filename and "
801                          "the output files will be suffixed from the input "
802                          "ones.");
803 
804     auto Index = loadCombinedIndex();
805     for (auto &Filename : InputFilenames) {
806       LLVMContext Ctx;
807       auto Buffer = loadFile(Filename);
808       auto Input = loadInputFile(Buffer->getMemBufferRef());
809       auto TheModule = loadModuleFromInput(*Input, Ctx);
810 
811       ThinGenerator.promote(*TheModule, *Index, *Input);
812 
813       std::string OutputName = OutputFilename;
814       if (OutputName.empty()) {
815         OutputName = Filename + ".thinlto.promoted.bc";
816       }
817       writeModuleToFile(*TheModule, OutputName);
818     }
819   }
820 
821   /// Load the combined index from disk, then load every file referenced by
822   /// the index and add them to the generator, then performs the promotion and
823   /// cross module importing on the files mentioned on the command line
824   /// (these must match the index content).
import()825   void import() {
826     if (InputFilenames.size() != 1 && !OutputFilename.empty())
827       report_fatal_error("Can't handle a single output filename and multiple "
828                          "input files, do not provide an output filename and "
829                          "the output files will be suffixed from the input "
830                          "ones.");
831 
832     auto Index = loadCombinedIndex();
833     auto InputBuffers = loadAllFilesForIndex(*Index);
834     for (auto &MemBuffer : InputBuffers)
835       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
836                               MemBuffer->getBuffer());
837 
838     for (auto &Filename : InputFilenames) {
839       LLVMContext Ctx;
840       auto Buffer = loadFile(Filename);
841       auto Input = loadInputFile(Buffer->getMemBufferRef());
842       auto TheModule = loadModuleFromInput(*Input, Ctx);
843 
844       ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
845 
846       std::string OutputName = OutputFilename;
847       if (OutputName.empty()) {
848         OutputName = Filename + ".thinlto.imported.bc";
849       }
850       writeModuleToFile(*TheModule, OutputName);
851     }
852   }
853 
internalize()854   void internalize() {
855     if (InputFilenames.size() != 1 && !OutputFilename.empty())
856       report_fatal_error("Can't handle a single output filename and multiple "
857                          "input files, do not provide an output filename and "
858                          "the output files will be suffixed from the input "
859                          "ones.");
860 
861     if (ExportedSymbols.empty())
862       errs() << "Warning: -internalize will not perform without "
863                 "-exported-symbol\n";
864 
865     auto Index = loadCombinedIndex();
866     auto InputBuffers = loadAllFilesForIndex(*Index);
867     for (auto &MemBuffer : InputBuffers)
868       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
869                               MemBuffer->getBuffer());
870 
871     for (auto &Filename : InputFilenames) {
872       LLVMContext Ctx;
873       auto Buffer = loadFile(Filename);
874       auto Input = loadInputFile(Buffer->getMemBufferRef());
875       auto TheModule = loadModuleFromInput(*Input, Ctx);
876 
877       ThinGenerator.internalize(*TheModule, *Index, *Input);
878 
879       std::string OutputName = OutputFilename;
880       if (OutputName.empty()) {
881         OutputName = Filename + ".thinlto.internalized.bc";
882       }
883       writeModuleToFile(*TheModule, OutputName);
884     }
885   }
886 
optimize()887   void optimize() {
888     if (InputFilenames.size() != 1 && !OutputFilename.empty())
889       report_fatal_error("Can't handle a single output filename and multiple "
890                          "input files, do not provide an output filename and "
891                          "the output files will be suffixed from the input "
892                          "ones.");
893     if (!ThinLTOIndex.empty())
894       errs() << "Warning: -thinlto-index ignored for optimize stage";
895 
896     for (auto &Filename : InputFilenames) {
897       LLVMContext Ctx;
898       auto Buffer = loadFile(Filename);
899       auto Input = loadInputFile(Buffer->getMemBufferRef());
900       auto TheModule = loadModuleFromInput(*Input, Ctx);
901 
902       ThinGenerator.optimize(*TheModule);
903 
904       std::string OutputName = OutputFilename;
905       if (OutputName.empty()) {
906         OutputName = Filename + ".thinlto.imported.bc";
907       }
908       writeModuleToFile(*TheModule, OutputName);
909     }
910   }
911 
codegen()912   void codegen() {
913     if (InputFilenames.size() != 1 && !OutputFilename.empty())
914       report_fatal_error("Can't handle a single output filename and multiple "
915                          "input files, do not provide an output filename and "
916                          "the output files will be suffixed from the input "
917                          "ones.");
918     if (!ThinLTOIndex.empty())
919       errs() << "Warning: -thinlto-index ignored for codegen stage";
920 
921     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
922     for (auto &Filename : InputFilenames) {
923       LLVMContext Ctx;
924       auto InputOrErr = MemoryBuffer::getFile(Filename);
925       error(InputOrErr, "error " + CurrentActivity);
926       InputBuffers.push_back(std::move(*InputOrErr));
927       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
928     }
929     ThinGenerator.setCodeGenOnly(true);
930     ThinGenerator.run();
931     for (auto BinName :
932          zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
933       std::string OutputName = OutputFilename;
934       if (OutputName.empty())
935         OutputName = std::get<1>(BinName) + ".thinlto.o";
936       else if (OutputName == "-") {
937         outs() << std::get<0>(BinName)->getBuffer();
938         return;
939       }
940 
941       std::error_code EC;
942       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
943       error(EC, "error opening the file '" + OutputName + "'");
944       OS << std::get<0>(BinName)->getBuffer();
945     }
946   }
947 
948   /// Full ThinLTO process
runAll()949   void runAll() {
950     if (!OutputFilename.empty())
951       report_fatal_error("Do not provide an output filename for ThinLTO "
952                          " processing, the output files will be suffixed from "
953                          "the input ones.");
954 
955     if (!ThinLTOIndex.empty())
956       errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
957 
958     LLVMContext Ctx;
959     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
960     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
961       auto &Filename = InputFilenames[i];
962       std::string CurrentActivity = "loading file '" + Filename + "'";
963       auto InputOrErr = MemoryBuffer::getFile(Filename);
964       error(InputOrErr, "error " + CurrentActivity);
965       InputBuffers.push_back(std::move(*InputOrErr));
966       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
967     }
968 
969     if (!ThinLTOSaveTempsPrefix.empty())
970       ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
971 
972     if (!ThinLTOGeneratedObjectsDir.empty()) {
973       ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
974       ThinGenerator.run();
975       return;
976     }
977 
978     ThinGenerator.run();
979 
980     auto &Binaries = ThinGenerator.getProducedBinaries();
981     if (Binaries.size() != InputFilenames.size())
982       report_fatal_error("Number of output objects does not match the number "
983                          "of inputs");
984 
985     for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
986       auto OutputName = InputFilenames[BufID] + ".thinlto.o";
987       std::error_code EC;
988       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
989       error(EC, "error opening the file '" + OutputName + "'");
990       OS << Binaries[BufID]->getBuffer();
991     }
992   }
993 
994   /// Load the combined index from disk, then load every file referenced by
995 };
996 
997 } // end namespace thinlto
998 
main(int argc,char ** argv)999 int main(int argc, char **argv) {
1000   InitLLVM X(argc, argv);
1001   cl::HideUnrelatedOptions({&LTOCategory, &getColorCategory()});
1002   cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
1003 
1004   if (OptLevel < '0' || OptLevel > '3')
1005     error("optimization level must be between 0 and 3");
1006 
1007   // Initialize the configured targets.
1008   InitializeAllTargets();
1009   InitializeAllTargetMCs();
1010   InitializeAllAsmPrinters();
1011   InitializeAllAsmParsers();
1012 
1013   // set up the TargetOptions for the machine
1014   TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
1015 
1016   if (ListSymbolsOnly || QueryHasCtorDtor) {
1017     testLTOModule(Options);
1018     return 0;
1019   }
1020 
1021   if (ListDependentLibrariesOnly) {
1022     listDependentLibraries();
1023     return 0;
1024   }
1025 
1026   if (IndexStats) {
1027     printIndexStats();
1028     return 0;
1029   }
1030 
1031   if (CheckHasObjC) {
1032     for (auto &Filename : InputFilenames) {
1033       ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
1034                             Filename + "': ");
1035       std::unique_ptr<MemoryBuffer> BufferOrErr =
1036           ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
1037       auto Buffer = std::move(BufferOrErr.get());
1038       if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
1039         outs() << "Bitcode " << Filename << " contains ObjC\n";
1040       else
1041         outs() << "Bitcode " << Filename << " does not contain ObjC\n";
1042     }
1043     return 0;
1044   }
1045 
1046   if (PrintMachOCPUOnly) {
1047     printMachOCPUOnly();
1048     return 0;
1049   }
1050 
1051   if (ThinLTOMode.getNumOccurrences()) {
1052     if (ThinLTOMode.getNumOccurrences() > 1)
1053       report_fatal_error("You can't specify more than one -thinlto-action");
1054     thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
1055     ThinLTOProcessor.run();
1056     return 0;
1057   }
1058 
1059   if (ThinLTO) {
1060     createCombinedModuleSummaryIndex();
1061     return 0;
1062   }
1063 
1064   unsigned BaseArg = 0;
1065 
1066   LLVMContext Context;
1067   Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
1068                                true);
1069 
1070   LTOCodeGenerator CodeGen(Context);
1071   CodeGen.setDisableVerify(DisableVerify);
1072 
1073   if (UseDiagnosticHandler)
1074     CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
1075 
1076   CodeGen.setCodePICModel(codegen::getExplicitRelocModel());
1077   CodeGen.setFreestanding(EnableFreestanding);
1078   CodeGen.setDebugPassManager(DebugPassManager);
1079 
1080   CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
1081   CodeGen.setTargetOptions(Options);
1082   CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
1083 
1084   StringSet<MallocAllocator> DSOSymbolsSet(llvm::from_range, DSOSymbols);
1085 
1086   std::vector<std::string> KeptDSOSyms;
1087 
1088   for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
1089     CurrentActivity = "loading file '" + InputFilenames[i] + "'";
1090     ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
1091         LTOModule::createFromFile(Context, InputFilenames[i], Options);
1092     std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
1093     CurrentActivity = "";
1094 
1095     unsigned NumSyms = Module->getSymbolCount();
1096     for (unsigned I = 0; I < NumSyms; ++I) {
1097       StringRef Name = Module->getSymbolName(I);
1098       if (!DSOSymbolsSet.count(Name))
1099         continue;
1100       lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
1101       unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
1102       if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
1103         KeptDSOSyms.push_back(std::string(Name));
1104     }
1105 
1106     // We use the first input module as the destination module when
1107     // SetMergedModule is true.
1108     if (SetMergedModule && i == BaseArg) {
1109       // Transfer ownership to the code generator.
1110       CodeGen.setModule(std::move(Module));
1111     } else if (!CodeGen.addModule(Module.get())) {
1112       // Print a message here so that we know addModule() did not abort.
1113       error("error adding file '" + InputFilenames[i] + "'");
1114     }
1115   }
1116 
1117   // Add all the exported symbols to the table of symbols to preserve.
1118   for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
1119     CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
1120 
1121   // Add all the dso symbols to the table of symbols to expose.
1122   for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
1123     CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
1124 
1125   // Set cpu and attrs strings for the default target/subtarget.
1126   CodeGen.setCpu(codegen::getMCPU());
1127 
1128   CodeGen.setOptLevel(OptLevel - '0');
1129   CodeGen.setAttrs(codegen::getMAttrs());
1130 
1131   if (auto FT = codegen::getExplicitFileType())
1132     CodeGen.setFileType(*FT);
1133 
1134   if (!OutputFilename.empty()) {
1135     if (LTOSaveBeforeOpt)
1136       CodeGen.setSaveIRBeforeOptPath(OutputFilename + ".0.preopt.bc");
1137 
1138     if (SaveLinkedModuleFile) {
1139       std::string ModuleFilename = OutputFilename;
1140       ModuleFilename += ".linked.bc";
1141 
1142       if (!CodeGen.writeMergedModules(ModuleFilename))
1143         error("writing linked module failed.");
1144     }
1145 
1146     if (!CodeGen.optimize()) {
1147       // Diagnostic messages should have been printed by the handler.
1148       error("error optimizing the code");
1149     }
1150 
1151     if (SaveModuleFile) {
1152       std::string ModuleFilename = OutputFilename;
1153       ModuleFilename += ".merged.bc";
1154 
1155       if (!CodeGen.writeMergedModules(ModuleFilename))
1156         error("writing merged module failed.");
1157     }
1158 
1159     auto AddStream =
1160         [&](size_t Task,
1161             const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
1162       std::string PartFilename = OutputFilename;
1163       if (Parallelism != 1)
1164         PartFilename += "." + utostr(Task);
1165 
1166       std::error_code EC;
1167       auto S =
1168           std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
1169       if (EC)
1170         error("error opening the file '" + PartFilename + "': " + EC.message());
1171       return std::make_unique<CachedFileStream>(std::move(S));
1172     };
1173 
1174     if (!CodeGen.compileOptimized(AddStream, Parallelism))
1175       // Diagnostic messages should have been printed by the handler.
1176       error("error compiling the code");
1177 
1178   } else {
1179     if (Parallelism != 1)
1180       error("-j must be specified together with -o");
1181 
1182     if (SaveModuleFile)
1183       error(": -save-merged-module must be specified with -o");
1184 
1185     const char *OutputName = nullptr;
1186     if (!CodeGen.compile_to_file(&OutputName))
1187       error("error compiling the code");
1188       // Diagnostic messages should have been printed by the handler.
1189 
1190     outs() << "Wrote native object file '" << OutputName << "'\n";
1191   }
1192 
1193   return 0;
1194 }
1195