Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / tools / llvm-lto / llvm-lto.cpp
blob4090faf4e3fd95bce21ccafeaf04425d55e91c08
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.
12 //===----------------------------------------------------------------------===//
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>
63 using namespace llvm;
65 static codegen::RegisterCodeGenFlags CGF;
67 static cl::OptionCategory LTOCategory("LTO Options");
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));
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));
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));
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));
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));
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));
100 enum ThinLTOModes {
101 THINLINK,
102 THINDISTRIBUTE,
103 THINEMITIMPORTS,
104 THINPROMOTE,
105 THINIMPORT,
106 THININTERNALIZE,
107 THINOPT,
108 THINCODEGEN,
109 THINALL
112 cl::opt<ThinLTOModes> ThinLTOMode(
113 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
114 cl::values(
115 clEnumValN(
116 THINLINK, "thinlink",
117 "ThinLink: produces the index by linking only the summaries."),
118 clEnumValN(THINDISTRIBUTE, "distributedindexes",
119 "Produces individual indexes for distributed backends."),
120 clEnumValN(THINEMITIMPORTS, "emitimports",
121 "Emit imports files for distributed backends."),
122 clEnumValN(THINPROMOTE, "promote",
123 "Perform pre-import promotion (requires -thinlto-index)."),
124 clEnumValN(THINIMPORT, "import",
125 "Perform both promotion and "
126 "cross-module importing (requires "
127 "-thinlto-index)."),
128 clEnumValN(THININTERNALIZE, "internalize",
129 "Perform internalization driven by -exported-symbol "
130 "(requires -thinlto-index)."),
131 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
132 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
133 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")),
134 cl::cat(LTOCategory));
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));
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));
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));
156 static cl::opt<std::string> ThinLTOCacheDir("thinlto-cache-dir",
157 cl::desc("Enable ThinLTO caching."),
158 cl::cat(LTOCategory));
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));
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));
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));
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));
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));
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));
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));
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));
200 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
201 cl::desc("<input bitcode files>"),
202 cl::cat(LTOCategory));
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));
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));
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));
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));
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));
230 static cl::opt<bool> QueryHasCtorDtor(
231 "query-hasCtorDtor", cl::init(false),
232 cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
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));
239 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
240 cl::desc("Number of backend threads"),
241 cl::cat(LTOCategory));
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));
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));
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));
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));
263 static cl::opt<bool>
264 LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
265 cl::desc("Save the IR before running optimizations"));
267 static cl::opt<bool> TryUseNewDbgInfoFormat(
268 "try-experimental-debuginfo-iterators",
269 cl::desc("Enable debuginfo iterator positions, if they're built in"),
270 cl::init(false), cl::Hidden);
272 extern cl::opt<bool> UseNewDbgInfoFormat;
273 extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat;
274 extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
276 namespace {
278 struct ModuleInfo {
279 BitVector CanBeHidden;
282 } // end anonymous namespace
284 static 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;
301 errs() << Msg << "\n";
304 static std::string CurrentActivity;
306 namespace {
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;
325 if (!CurrentActivity.empty())
326 OS << ' ' << CurrentActivity;
327 OS << ": ";
329 DiagnosticPrinterRawOStream DP(OS);
330 DI.print(DP);
331 OS << '\n';
333 if (DI.getSeverity() == DS_Error)
334 exit(1);
335 return true;
340 static void error(const Twine &Msg) {
341 errs() << "llvm-lto: " << Msg << '\n';
342 exit(1);
345 static void error(std::error_code EC, const Twine &Prefix) {
346 if (EC)
347 error(Prefix + ": " + EC.message());
350 template <typename T>
351 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
352 error(V.getError(), Prefix);
355 static void maybeVerifyModule(const Module &Mod) {
356 if (!DisableVerify && verifyModule(Mod, &errs()))
357 error("Broken Module");
360 static std::unique_ptr<LTOModule>
361 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
362 const TargetOptions &Options) {
363 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
364 MemoryBuffer::getFile(Path);
365 error(BufferOrErr, "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(std::make_unique<LLVMLTODiagnosticHandler>(),
370 true);
371 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
372 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
373 Options, Path);
374 CurrentActivity = "";
375 maybeVerifyModule((*Ret)->getModule());
376 return std::move(*Ret);
379 /// Print some statistics on the index for each input files.
380 static 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(Filename));
385 // Skip files without a module summary.
386 if (!Index)
387 report_fatal_error(Twine(Filename) + " does not contain an index");
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>(Summary.get())) {
394 Functions++;
395 Calls += FuncSummary->calls().size();
396 } else if (isa<AliasSummary>(Summary.get()))
397 Alias++;
398 else
399 Globals++;
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";
410 /// Print the lto symbol attributes.
411 static void printLTOSymbolAttributes(lto_symbol_attributes Attrs) {
412 outs() << "{ ";
413 unsigned Permission = Attrs & LTO_SYMBOL_PERMISSIONS_MASK;
414 switch (Permission) {
415 case LTO_SYMBOL_PERMISSIONS_CODE:
416 outs() << "function ";
417 break;
418 case LTO_SYMBOL_PERMISSIONS_DATA:
419 outs() << "data ";
420 break;
421 case LTO_SYMBOL_PERMISSIONS_RODATA:
422 outs() << "constant ";
423 break;
425 unsigned Definition = Attrs & LTO_SYMBOL_DEFINITION_MASK;
426 switch (Definition) {
427 case LTO_SYMBOL_DEFINITION_REGULAR:
428 outs() << "defined ";
429 break;
430 case LTO_SYMBOL_DEFINITION_TENTATIVE:
431 outs() << "common ";
432 break;
433 case LTO_SYMBOL_DEFINITION_WEAK:
434 outs() << "weak ";
435 break;
436 case LTO_SYMBOL_DEFINITION_UNDEFINED:
437 outs() << "extern ";
438 break;
439 case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
440 outs() << "extern-weak ";
441 break;
443 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
444 switch (Scope) {
445 case LTO_SYMBOL_SCOPE_INTERNAL:
446 outs() << "internal ";
447 break;
448 case LTO_SYMBOL_SCOPE_HIDDEN:
449 outs() << "hidden ";
450 break;
451 case LTO_SYMBOL_SCOPE_PROTECTED:
452 outs() << "protected ";
453 break;
454 case LTO_SYMBOL_SCOPE_DEFAULT:
455 outs() << "default ";
456 break;
457 case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN:
458 outs() << "omitted ";
459 break;
461 if (Attrs & LTO_SYMBOL_COMDAT)
462 outs() << "comdat ";
463 if (Attrs & LTO_SYMBOL_ALIAS)
464 outs() << "alias ";
465 outs() << "}";
468 /// Load each IR file and dump certain information based on active flags.
470 /// The main point here is to provide lit-testable coverage for the LTOModule
471 /// functionality that's exposed by the C API. Moreover, this provides testing
472 /// coverage for modules that have been created in their own contexts.
473 static void testLTOModule(const TargetOptions &Options) {
474 for (auto &Filename : InputFilenames) {
475 std::unique_ptr<MemoryBuffer> Buffer;
476 std::unique_ptr<LTOModule> Module =
477 getLocalLTOModule(Filename, Buffer, Options);
479 if (ListSymbolsOnly) {
480 // List the symbols.
481 outs() << Filename << ":\n";
482 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I) {
483 outs() << Module->getSymbolName(I) << " ";
484 printLTOSymbolAttributes(Module->getSymbolAttributes(I));
485 outs() << "\n";
488 if (QueryHasCtorDtor)
489 outs() << Filename
490 << ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
491 << "\n";
495 static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
496 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
497 "': ");
498 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
501 static void listDependentLibraries() {
502 for (auto &Filename : InputFilenames) {
503 auto Buffer = loadFile(Filename);
504 std::string E;
505 std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
506 Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
507 E));
508 if (!Input)
509 error(E);
511 // List the dependent libraries.
512 outs() << Filename << ":\n";
513 for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
514 I != C; ++I) {
515 size_t L = 0;
516 const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
517 assert(S);
518 outs() << StringRef(S, L) << "\n";
523 static void printMachOCPUOnly() {
524 LLVMContext Context;
525 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
526 true);
527 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
528 for (auto &Filename : InputFilenames) {
529 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
530 LTOModule::createFromFile(Context, Filename, Options);
531 if (!ModuleOrErr)
532 error(ModuleOrErr, "llvm-lto: ");
534 Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
535 Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
536 if (!CPUType)
537 error("Error while printing mach-o cputype: " +
538 toString(CPUType.takeError()));
539 if (!CPUSubType)
540 error("Error while printing mach-o cpusubtype: " +
541 toString(CPUSubType.takeError()));
542 outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
543 Filename.c_str(), *CPUType, *CPUSubType);
547 /// Create a combined index file from the input IR files and write it.
549 /// This is meant to enable testing of ThinLTO combined index generation,
550 /// currently available via the gold plugin via -thinlto.
551 static void createCombinedModuleSummaryIndex() {
552 ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
553 for (auto &Filename : InputFilenames) {
554 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
555 std::unique_ptr<MemoryBuffer> MB =
556 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
557 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex));
559 // In order to use this index for testing, specifically import testing, we
560 // need to update any indirect call edges created from SamplePGO, so that they
561 // point to the correct GUIDs.
562 updateIndirectCalls(CombinedIndex);
563 std::error_code EC;
564 assert(!OutputFilename.empty());
565 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
566 sys::fs::OpenFlags::OF_None);
567 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
568 writeIndexToFile(CombinedIndex, OS);
569 OS.close();
572 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
573 /// \p NewPrefix strings, if it was specified.
574 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
575 std::string &NewPrefix) {
576 assert(ThinLTOPrefixReplace.empty() ||
577 ThinLTOPrefixReplace.find(';') != StringRef::npos);
578 StringRef PrefixReplace = ThinLTOPrefixReplace;
579 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
580 OldPrefix = Split.first.str();
581 NewPrefix = Split.second.str();
584 /// Given the original \p Path to an output file, replace any path
585 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
586 /// resulting directory if it does not yet exist.
587 static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
588 StringRef NewPrefix) {
589 if (OldPrefix.empty() && NewPrefix.empty())
590 return std::string(Path);
591 SmallString<128> NewPath(Path);
592 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
593 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
594 if (!ParentPath.empty()) {
595 // Make sure the new directory exists, creating it if necessary.
596 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
597 error(EC, "error creating the directory '" + ParentPath + "'");
599 return std::string(NewPath);
602 namespace thinlto {
604 std::vector<std::unique_ptr<MemoryBuffer>>
605 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
606 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
608 for (auto &ModPath : Index.modulePaths()) {
609 const auto &Filename = ModPath.first();
610 std::string CurrentActivity = ("loading file '" + Filename + "'").str();
611 auto InputOrErr = MemoryBuffer::getFile(Filename);
612 error(InputOrErr, "error " + CurrentActivity);
613 InputBuffers.push_back(std::move(*InputOrErr));
615 return InputBuffers;
618 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
619 if (ThinLTOIndex.empty())
620 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
621 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
622 "': ");
623 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
626 static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
627 ExitOnError ExitOnErr("llvm-lto: error loading input '" +
628 Buffer.getBufferIdentifier().str() + "': ");
629 return ExitOnErr(lto::InputFile::create(Buffer));
632 static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
633 LLVMContext &CTX) {
634 auto &Mod = File.getSingleBitcodeModule();
635 auto ModuleOrErr = Mod.parseModule(CTX);
636 if (!ModuleOrErr) {
637 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
638 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
639 SourceMgr::DK_Error, EIB.message());
640 Err.print("llvm-lto", errs());
642 report_fatal_error("Can't load module, abort.");
644 maybeVerifyModule(**ModuleOrErr);
645 if (ThinLTOModuleId.getNumOccurrences()) {
646 if (InputFilenames.size() != 1)
647 report_fatal_error("Can't override the module id for multiple files");
648 (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
650 return std::move(*ModuleOrErr);
653 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
654 std::error_code EC;
655 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
656 error(EC, "error opening the file '" + Filename + "'");
657 maybeVerifyModule(TheModule);
658 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
661 class ThinLTOProcessing {
662 public:
663 ThinLTOCodeGenerator ThinGenerator;
665 ThinLTOProcessing(const TargetOptions &Options) {
666 ThinGenerator.setCodePICModel(codegen::getExplicitRelocModel());
667 ThinGenerator.setTargetOptions(Options);
668 ThinGenerator.setCacheDir(ThinLTOCacheDir);
669 ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
670 ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
671 ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
672 ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
673 ThinGenerator.setFreestanding(EnableFreestanding);
674 ThinGenerator.setDebugPassManager(DebugPassManager);
676 // Add all the exported symbols to the table of symbols to preserve.
677 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
678 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
681 void run() {
682 switch (ThinLTOMode) {
683 case THINLINK:
684 return thinLink();
685 case THINDISTRIBUTE:
686 return distributedIndexes();
687 case THINEMITIMPORTS:
688 return emitImports();
689 case THINPROMOTE:
690 return promote();
691 case THINIMPORT:
692 return import();
693 case THININTERNALIZE:
694 return internalize();
695 case THINOPT:
696 return optimize();
697 case THINCODEGEN:
698 return codegen();
699 case THINALL:
700 return runAll();
704 private:
705 /// Load the input files, create the combined index, and write it out.
706 void thinLink() {
707 // Perform "ThinLink": just produce the index
708 if (OutputFilename.empty())
709 report_fatal_error(
710 "OutputFilename is necessary to store the combined index.\n");
712 LLVMContext Ctx;
713 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
714 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
715 auto &Filename = InputFilenames[i];
716 std::string CurrentActivity = "loading file '" + Filename + "'";
717 auto InputOrErr = MemoryBuffer::getFile(Filename);
718 error(InputOrErr, "error " + CurrentActivity);
719 InputBuffers.push_back(std::move(*InputOrErr));
720 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
723 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
724 if (!CombinedIndex)
725 report_fatal_error("ThinLink didn't create an index");
726 std::error_code EC;
727 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
728 error(EC, "error opening the file '" + OutputFilename + "'");
729 writeIndexToFile(*CombinedIndex, OS);
732 /// Load the combined index from disk, then compute and generate
733 /// individual index files suitable for ThinLTO distributed backend builds
734 /// on the files mentioned on the command line (these must match the index
735 /// content).
736 void distributedIndexes() {
737 if (InputFilenames.size() != 1 && !OutputFilename.empty())
738 report_fatal_error("Can't handle a single output filename and multiple "
739 "input files, do not provide an output filename and "
740 "the output files will be suffixed from the input "
741 "ones.");
743 std::string OldPrefix, NewPrefix;
744 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
746 auto Index = loadCombinedIndex();
747 for (auto &Filename : InputFilenames) {
748 LLVMContext Ctx;
749 auto Buffer = loadFile(Filename);
750 auto Input = loadInputFile(Buffer->getMemBufferRef());
751 auto TheModule = loadModuleFromInput(*Input, Ctx);
753 // Build a map of module to the GUIDs and summary objects that should
754 // be written to its index.
755 ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
756 GVSummaryPtrSet DecSummaries;
757 ThinGenerator.gatherImportedSummariesForModule(
758 *TheModule, *Index, ModuleToSummariesForIndex, DecSummaries, *Input);
760 std::string OutputName = OutputFilename;
761 if (OutputName.empty()) {
762 OutputName = Filename + ".thinlto.bc";
764 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
765 std::error_code EC;
766 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
767 error(EC, "error opening the file '" + OutputName + "'");
768 writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex, &DecSummaries);
772 /// Load the combined index from disk, compute the imports, and emit
773 /// the import file lists for each module to disk.
774 void emitImports() {
775 if (InputFilenames.size() != 1 && !OutputFilename.empty())
776 report_fatal_error("Can't handle a single output filename and multiple "
777 "input files, do not provide an output filename and "
778 "the output files will be suffixed from the input "
779 "ones.");
781 std::string OldPrefix, NewPrefix;
782 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
784 auto Index = loadCombinedIndex();
785 for (auto &Filename : InputFilenames) {
786 LLVMContext Ctx;
787 auto Buffer = loadFile(Filename);
788 auto Input = loadInputFile(Buffer->getMemBufferRef());
789 auto TheModule = loadModuleFromInput(*Input, Ctx);
790 std::string OutputName = OutputFilename;
791 if (OutputName.empty()) {
792 OutputName = Filename + ".imports";
794 OutputName =
795 getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
796 ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
800 /// Load the combined index from disk, then load every file referenced by
801 /// the index and add them to the generator, finally perform the promotion
802 /// on the files mentioned on the command line (these must match the index
803 /// content).
804 void promote() {
805 if (InputFilenames.size() != 1 && !OutputFilename.empty())
806 report_fatal_error("Can't handle a single output filename and multiple "
807 "input files, do not provide an output filename and "
808 "the output files will be suffixed from the input "
809 "ones.");
811 auto Index = loadCombinedIndex();
812 for (auto &Filename : InputFilenames) {
813 LLVMContext Ctx;
814 auto Buffer = loadFile(Filename);
815 auto Input = loadInputFile(Buffer->getMemBufferRef());
816 auto TheModule = loadModuleFromInput(*Input, Ctx);
818 ThinGenerator.promote(*TheModule, *Index, *Input);
820 std::string OutputName = OutputFilename;
821 if (OutputName.empty()) {
822 OutputName = Filename + ".thinlto.promoted.bc";
824 writeModuleToFile(*TheModule, OutputName);
828 /// Load the combined index from disk, then load every file referenced by
829 /// the index and add them to the generator, then performs the promotion and
830 /// cross module importing on the files mentioned on the command line
831 /// (these must match the index content).
832 void import() {
833 if (InputFilenames.size() != 1 && !OutputFilename.empty())
834 report_fatal_error("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.");
839 auto Index = loadCombinedIndex();
840 auto InputBuffers = loadAllFilesForIndex(*Index);
841 for (auto &MemBuffer : InputBuffers)
842 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
843 MemBuffer->getBuffer());
845 for (auto &Filename : InputFilenames) {
846 LLVMContext Ctx;
847 auto Buffer = loadFile(Filename);
848 auto Input = loadInputFile(Buffer->getMemBufferRef());
849 auto TheModule = loadModuleFromInput(*Input, Ctx);
851 ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
853 std::string OutputName = OutputFilename;
854 if (OutputName.empty()) {
855 OutputName = Filename + ".thinlto.imported.bc";
857 writeModuleToFile(*TheModule, OutputName);
861 void internalize() {
862 if (InputFilenames.size() != 1 && !OutputFilename.empty())
863 report_fatal_error("Can't handle a single output filename and multiple "
864 "input files, do not provide an output filename and "
865 "the output files will be suffixed from the input "
866 "ones.");
868 if (ExportedSymbols.empty())
869 errs() << "Warning: -internalize will not perform without "
870 "-exported-symbol\n";
872 auto Index = loadCombinedIndex();
873 auto InputBuffers = loadAllFilesForIndex(*Index);
874 for (auto &MemBuffer : InputBuffers)
875 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
876 MemBuffer->getBuffer());
878 for (auto &Filename : InputFilenames) {
879 LLVMContext Ctx;
880 auto Buffer = loadFile(Filename);
881 auto Input = loadInputFile(Buffer->getMemBufferRef());
882 auto TheModule = loadModuleFromInput(*Input, Ctx);
884 ThinGenerator.internalize(*TheModule, *Index, *Input);
886 std::string OutputName = OutputFilename;
887 if (OutputName.empty()) {
888 OutputName = Filename + ".thinlto.internalized.bc";
890 writeModuleToFile(*TheModule, OutputName);
894 void optimize() {
895 if (InputFilenames.size() != 1 && !OutputFilename.empty())
896 report_fatal_error("Can't handle a single output filename and multiple "
897 "input files, do not provide an output filename and "
898 "the output files will be suffixed from the input "
899 "ones.");
900 if (!ThinLTOIndex.empty())
901 errs() << "Warning: -thinlto-index ignored for optimize stage";
903 for (auto &Filename : InputFilenames) {
904 LLVMContext Ctx;
905 auto Buffer = loadFile(Filename);
906 auto Input = loadInputFile(Buffer->getMemBufferRef());
907 auto TheModule = loadModuleFromInput(*Input, Ctx);
909 ThinGenerator.optimize(*TheModule);
911 std::string OutputName = OutputFilename;
912 if (OutputName.empty()) {
913 OutputName = Filename + ".thinlto.imported.bc";
915 writeModuleToFile(*TheModule, OutputName);
919 void codegen() {
920 if (InputFilenames.size() != 1 && !OutputFilename.empty())
921 report_fatal_error("Can't handle a single output filename and multiple "
922 "input files, do not provide an output filename and "
923 "the output files will be suffixed from the input "
924 "ones.");
925 if (!ThinLTOIndex.empty())
926 errs() << "Warning: -thinlto-index ignored for codegen stage";
928 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
929 for (auto &Filename : InputFilenames) {
930 LLVMContext Ctx;
931 auto InputOrErr = MemoryBuffer::getFile(Filename);
932 error(InputOrErr, "error " + CurrentActivity);
933 InputBuffers.push_back(std::move(*InputOrErr));
934 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
936 ThinGenerator.setCodeGenOnly(true);
937 ThinGenerator.run();
938 for (auto BinName :
939 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
940 std::string OutputName = OutputFilename;
941 if (OutputName.empty())
942 OutputName = std::get<1>(BinName) + ".thinlto.o";
943 else if (OutputName == "-") {
944 outs() << std::get<0>(BinName)->getBuffer();
945 return;
948 std::error_code EC;
949 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
950 error(EC, "error opening the file '" + OutputName + "'");
951 OS << std::get<0>(BinName)->getBuffer();
955 /// Full ThinLTO process
956 void runAll() {
957 if (!OutputFilename.empty())
958 report_fatal_error("Do not provide an output filename for ThinLTO "
959 " processing, the output files will be suffixed from "
960 "the input ones.");
962 if (!ThinLTOIndex.empty())
963 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
965 LLVMContext Ctx;
966 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
967 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
968 auto &Filename = InputFilenames[i];
969 std::string CurrentActivity = "loading file '" + Filename + "'";
970 auto InputOrErr = MemoryBuffer::getFile(Filename);
971 error(InputOrErr, "error " + CurrentActivity);
972 InputBuffers.push_back(std::move(*InputOrErr));
973 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
976 if (!ThinLTOSaveTempsPrefix.empty())
977 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
979 if (!ThinLTOGeneratedObjectsDir.empty()) {
980 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
981 ThinGenerator.run();
982 return;
985 ThinGenerator.run();
987 auto &Binaries = ThinGenerator.getProducedBinaries();
988 if (Binaries.size() != InputFilenames.size())
989 report_fatal_error("Number of output objects does not match the number "
990 "of inputs");
992 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
993 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
994 std::error_code EC;
995 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
996 error(EC, "error opening the file '" + OutputName + "'");
997 OS << Binaries[BufID]->getBuffer();
1001 /// Load the combined index from disk, then load every file referenced by
1004 } // end namespace thinlto
1006 int main(int argc, char **argv) {
1007 InitLLVM X(argc, argv);
1008 cl::HideUnrelatedOptions({&LTOCategory, &getColorCategory()});
1009 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
1010 // Load bitcode into the new debug info format by default.
1011 if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET)
1012 LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE;
1014 // RemoveDIs debug-info transition: tests may request that we /try/ to use the
1015 // new debug-info format.
1016 if (TryUseNewDbgInfoFormat) {
1017 // Turn the new debug-info format on.
1018 UseNewDbgInfoFormat = true;
1020 // Since llvm-lto collects multiple IR modules together, for simplicity's sake
1021 // we disable the "PreserveInputDbgFormat" flag to enforce a single debug info
1022 // format.
1023 PreserveInputDbgFormat = cl::boolOrDefault::BOU_FALSE;
1025 if (OptLevel < '0' || OptLevel > '3')
1026 error("optimization level must be between 0 and 3");
1028 // Initialize the configured targets.
1029 InitializeAllTargets();
1030 InitializeAllTargetMCs();
1031 InitializeAllAsmPrinters();
1032 InitializeAllAsmParsers();
1034 // set up the TargetOptions for the machine
1035 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
1037 if (ListSymbolsOnly || QueryHasCtorDtor) {
1038 testLTOModule(Options);
1039 return 0;
1042 if (ListDependentLibrariesOnly) {
1043 listDependentLibraries();
1044 return 0;
1047 if (IndexStats) {
1048 printIndexStats();
1049 return 0;
1052 if (CheckHasObjC) {
1053 for (auto &Filename : InputFilenames) {
1054 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
1055 Filename + "': ");
1056 std::unique_ptr<MemoryBuffer> BufferOrErr =
1057 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
1058 auto Buffer = std::move(BufferOrErr.get());
1059 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
1060 outs() << "Bitcode " << Filename << " contains ObjC\n";
1061 else
1062 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
1064 return 0;
1067 if (PrintMachOCPUOnly) {
1068 printMachOCPUOnly();
1069 return 0;
1072 if (ThinLTOMode.getNumOccurrences()) {
1073 if (ThinLTOMode.getNumOccurrences() > 1)
1074 report_fatal_error("You can't specify more than one -thinlto-action");
1075 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
1076 ThinLTOProcessor.run();
1077 return 0;
1080 if (ThinLTO) {
1081 createCombinedModuleSummaryIndex();
1082 return 0;
1085 unsigned BaseArg = 0;
1087 LLVMContext Context;
1088 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
1089 true);
1091 LTOCodeGenerator CodeGen(Context);
1092 CodeGen.setDisableVerify(DisableVerify);
1094 if (UseDiagnosticHandler)
1095 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
1097 CodeGen.setCodePICModel(codegen::getExplicitRelocModel());
1098 CodeGen.setFreestanding(EnableFreestanding);
1099 CodeGen.setDebugPassManager(DebugPassManager);
1101 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
1102 CodeGen.setTargetOptions(Options);
1103 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
1105 StringSet<MallocAllocator> DSOSymbolsSet;
1106 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
1107 DSOSymbolsSet.insert(DSOSymbols[i]);
1109 std::vector<std::string> KeptDSOSyms;
1111 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
1112 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
1113 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
1114 LTOModule::createFromFile(Context, InputFilenames[i], Options);
1115 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
1116 CurrentActivity = "";
1118 unsigned NumSyms = Module->getSymbolCount();
1119 for (unsigned I = 0; I < NumSyms; ++I) {
1120 StringRef Name = Module->getSymbolName(I);
1121 if (!DSOSymbolsSet.count(Name))
1122 continue;
1123 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
1124 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
1125 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
1126 KeptDSOSyms.push_back(std::string(Name));
1129 // We use the first input module as the destination module when
1130 // SetMergedModule is true.
1131 if (SetMergedModule && i == BaseArg) {
1132 // Transfer ownership to the code generator.
1133 CodeGen.setModule(std::move(Module));
1134 } else if (!CodeGen.addModule(Module.get())) {
1135 // Print a message here so that we know addModule() did not abort.
1136 error("error adding file '" + InputFilenames[i] + "'");
1140 // Add all the exported symbols to the table of symbols to preserve.
1141 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
1142 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
1144 // Add all the dso symbols to the table of symbols to expose.
1145 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
1146 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
1148 // Set cpu and attrs strings for the default target/subtarget.
1149 CodeGen.setCpu(codegen::getMCPU());
1151 CodeGen.setOptLevel(OptLevel - '0');
1152 CodeGen.setAttrs(codegen::getMAttrs());
1154 if (auto FT = codegen::getExplicitFileType())
1155 CodeGen.setFileType(*FT);
1157 if (!OutputFilename.empty()) {
1158 if (LTOSaveBeforeOpt)
1159 CodeGen.setSaveIRBeforeOptPath(OutputFilename + ".0.preopt.bc");
1161 if (SaveLinkedModuleFile) {
1162 std::string ModuleFilename = OutputFilename;
1163 ModuleFilename += ".linked.bc";
1164 std::string ErrMsg;
1166 if (!CodeGen.writeMergedModules(ModuleFilename))
1167 error("writing linked module failed.");
1170 if (!CodeGen.optimize()) {
1171 // Diagnostic messages should have been printed by the handler.
1172 error("error optimizing the code");
1175 if (SaveModuleFile) {
1176 std::string ModuleFilename = OutputFilename;
1177 ModuleFilename += ".merged.bc";
1178 std::string ErrMsg;
1180 if (!CodeGen.writeMergedModules(ModuleFilename))
1181 error("writing merged module failed.");
1184 auto AddStream =
1185 [&](size_t Task,
1186 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
1187 std::string PartFilename = OutputFilename;
1188 if (Parallelism != 1)
1189 PartFilename += "." + utostr(Task);
1191 std::error_code EC;
1192 auto S =
1193 std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
1194 if (EC)
1195 error("error opening the file '" + PartFilename + "': " + EC.message());
1196 return std::make_unique<CachedFileStream>(std::move(S));
1199 if (!CodeGen.compileOptimized(AddStream, Parallelism))
1200 // Diagnostic messages should have been printed by the handler.
1201 error("error compiling the code");
1203 } else {
1204 if (Parallelism != 1)
1205 error("-j must be specified together with -o");
1207 if (SaveModuleFile)
1208 error(": -save-merged-module must be specified with -o");
1210 const char *OutputName = nullptr;
1211 if (!CodeGen.compile_to_file(&OutputName))
1212 error("error compiling the code");
1213 // Diagnostic messages should have been printed by the handler.
1215 outs() << "Wrote native object file '" << OutputName << "'\n";
1218 return 0;