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