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

source code of llvm/tools/llvm-lto/llvm-lto.cpp