blob: f2419949d4a264cfdafe2ee62cf715a60d2e3980 [file] [log] [blame]
Peter Collingbourne4e380b02013-09-19 22:15:52 +00001//===-- llvm-lto: a simple command-line program to link modules with LTO --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This program takes in a list of bitcode files, links them, performs link-time
11// optimization, and outputs an object file.
12//
13//===----------------------------------------------------------------------===//
14
Rafael Espindola282a4702013-10-31 20:51:58 +000015#include "llvm/ADT/StringSet.h"
Teresa Johnson91a88bb2015-10-19 14:30:44 +000016#include "llvm/Bitcode/ReaderWriter.h"
Rafael Espindola0b385c72013-09-30 16:39:19 +000017#include "llvm/CodeGen/CommandFlags.h"
Mehdi Amini354f5202015-11-19 05:52:29 +000018#include "llvm/IR/DiagnosticPrinter.h"
Teresa Johnson91a88bb2015-10-19 14:30:44 +000019#include "llvm/IR/LLVMContext.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000020#include "llvm/IRReader/IRReader.h"
Peter Collingbourne4ccf0f12013-09-24 23:52:22 +000021#include "llvm/LTO/LTOCodeGenerator.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000022#include "llvm/LTO/ThinLTOCodeGenerator.h"
Peter Collingbourne4ccf0f12013-09-24 23:52:22 +000023#include "llvm/LTO/LTOModule.h"
Teresa Johnson91a88bb2015-10-19 14:30:44 +000024#include "llvm/Object/FunctionIndexObjectFile.h"
Peter Collingbourne4e380b02013-09-19 22:15:52 +000025#include "llvm/Support/CommandLine.h"
Benjamin Kramerd59664f2014-04-29 23:26:49 +000026#include "llvm/Support/FileSystem.h"
Peter Collingbourne4e380b02013-09-19 22:15:52 +000027#include "llvm/Support/ManagedStatic.h"
28#include "llvm/Support/PrettyStackTrace.h"
29#include "llvm/Support/Signals.h"
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000030#include "llvm/Support/SourceMgr.h"
Peter Collingbourne4ccf0f12013-09-24 23:52:22 +000031#include "llvm/Support/TargetSelect.h"
Peter Collingbournec269ed52015-08-27 23:37:36 +000032#include "llvm/Support/ToolOutputFile.h"
Chandler Carruth07baed52014-01-13 08:04:33 +000033#include "llvm/Support/raw_ostream.h"
Peter Collingbournec269ed52015-08-27 23:37:36 +000034#include <list>
Peter Collingbourne4e380b02013-09-19 22:15:52 +000035
36using namespace llvm;
37
Peter Collingbourne070843d2015-03-19 22:01:00 +000038static cl::opt<char>
39OptLevel("O",
40 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
41 "(default = '-O2')"),
42 cl::Prefix,
43 cl::ZeroOrMore,
44 cl::init('2'));
Peter Collingbourne4e380b02013-09-19 22:15:52 +000045
Duncan P. N. Exon Smithcff5fef2015-09-15 23:05:59 +000046static cl::opt<bool> DisableVerify(
47 "disable-verify", cl::init(false),
48 cl::desc("Do not run the verifier during the optimization pipeline"));
49
Rafael Espindola0b385c72013-09-30 16:39:19 +000050static cl::opt<bool>
51DisableInline("disable-inlining", cl::init(false),
52 cl::desc("Do not run the inliner pass"));
53
54static cl::opt<bool>
55DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
56 cl::desc("Do not run the GVN load PRE pass"));
57
Duncan P. N. Exon Smith30c92422014-10-01 18:36:03 +000058static cl::opt<bool>
Arnold Schwaighofereb1a38f2014-10-26 21:50:58 +000059DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
60 cl::desc("Do not run loop or slp vectorization during LTO"));
61
62static cl::opt<bool>
Duncan P. N. Exon Smith30c92422014-10-01 18:36:03 +000063UseDiagnosticHandler("use-diagnostic-handler", cl::init(false),
64 cl::desc("Use a diagnostic handler to test the handler interface"));
65
Teresa Johnsonf72278f2015-11-02 18:02:11 +000066static cl::opt<bool>
67 ThinLTO("thinlto", cl::init(false),
68 cl::desc("Only write combined global index for ThinLTO backends"));
Teresa Johnson91a88bb2015-10-19 14:30:44 +000069
Mehdi Amini7c4a1a82016-03-09 01:37:22 +000070enum ThinLTOModes {
71 THINLINK,
72 THINPROMOTE,
73 THINIMPORT,
74 THINOPT,
75 THINCODEGEN,
76 THINALL
77};
78
79cl::opt<ThinLTOModes> ThinLTOMode(
80 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
81 cl::values(
82 clEnumValN(
83 THINLINK, "thinlink",
84 "ThinLink: produces the index by linking only the summaries."),
85 clEnumValN(THINPROMOTE, "promote",
86 "Perform pre-import promotion (requires -thinlto-index)."),
87 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
88 "cross-module importing (requires "
89 "-thinlto-index)."),
90 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
91 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
92 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end"),
93 clEnumValEnd));
94
95static cl::opt<std::string>
96 ThinLTOIndex("thinlto-index",
97 cl::desc("Provide the index produced by a ThinLink, required "
98 "to perform the promotion and/or importing."));
99
Tobias Edler von Koch49c9a6e2015-11-20 00:13:05 +0000100static cl::opt<bool>
101SaveModuleFile("save-merged-module", cl::init(false),
102 cl::desc("Write merged LTO module to file before CodeGen"));
103
Rafael Espindola0b385c72013-09-30 16:39:19 +0000104static cl::list<std::string>
105InputFilenames(cl::Positional, cl::OneOrMore,
106 cl::desc("<input bitcode files>"));
107
108static cl::opt<std::string>
109OutputFilename("o", cl::init(""),
110 cl::desc("Override output filename"),
111 cl::value_desc("filename"));
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000112
Rafael Espindoladafc53d2013-10-02 14:12:56 +0000113static cl::list<std::string>
114ExportedSymbols("exported-symbol",
115 cl::desc("Symbol to export from the resulting object file"),
116 cl::ZeroOrMore);
117
Rafael Espindolacda29112013-10-03 18:29:09 +0000118static cl::list<std::string>
119DSOSymbols("dso-symbol",
120 cl::desc("Symbol to put in the symtab in the resulting dso"),
121 cl::ZeroOrMore);
Rafael Espindoladafc53d2013-10-02 14:12:56 +0000122
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000123static cl::opt<bool> ListSymbolsOnly(
124 "list-symbols-only", cl::init(false),
125 cl::desc("Instead of running LTO, list the symbols in each IR file"));
126
Manman Ren6487ce92015-02-24 00:45:56 +0000127static cl::opt<bool> SetMergedModule(
128 "set-merged-module", cl::init(false),
129 cl::desc("Use the first input module as the merged module"));
130
Peter Collingbournec269ed52015-08-27 23:37:36 +0000131static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
132 cl::desc("Number of backend threads"));
133
Tobias Edler von Koch3f4f6f3e2016-01-18 23:35:24 +0000134static cl::opt<bool> RestoreGlobalsLinkage(
135 "restore-linkage", cl::init(false),
136 cl::desc("Restore original linkage of globals prior to CodeGen"));
137
Rafael Espindola282a4702013-10-31 20:51:58 +0000138namespace {
139struct ModuleInfo {
140 std::vector<bool> CanBeHidden;
141};
142}
143
Benjamin Kramerf044d3f2015-03-09 16:23:46 +0000144static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
145 const char *Msg, void *) {
Yunzhong Gaoef436f02015-11-10 18:52:48 +0000146 errs() << "llvm-lto: ";
Duncan P. N. Exon Smith30c92422014-10-01 18:36:03 +0000147 switch (Severity) {
148 case LTO_DS_NOTE:
149 errs() << "note: ";
150 break;
151 case LTO_DS_REMARK:
152 errs() << "remark: ";
153 break;
154 case LTO_DS_ERROR:
155 errs() << "error: ";
156 break;
157 case LTO_DS_WARNING:
158 errs() << "warning: ";
159 break;
160 }
161 errs() << Msg << "\n";
162}
163
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000164static std::string CurrentActivity;
Mehdi Amini354f5202015-11-19 05:52:29 +0000165static void diagnosticHandler(const DiagnosticInfo &DI) {
166 raw_ostream &OS = errs();
167 OS << "llvm-lto: ";
168 switch (DI.getSeverity()) {
169 case DS_Error:
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000170 OS << "error";
Mehdi Amini354f5202015-11-19 05:52:29 +0000171 break;
172 case DS_Warning:
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000173 OS << "warning";
Mehdi Amini354f5202015-11-19 05:52:29 +0000174 break;
175 case DS_Remark:
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000176 OS << "remark";
Mehdi Amini354f5202015-11-19 05:52:29 +0000177 break;
178 case DS_Note:
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000179 OS << "note";
Mehdi Amini354f5202015-11-19 05:52:29 +0000180 break;
181 }
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000182 if (!CurrentActivity.empty())
183 OS << ' ' << CurrentActivity;
184 OS << ": ";
Mehdi Amini354f5202015-11-19 05:52:29 +0000185
186 DiagnosticPrinterRawOStream DP(OS);
187 DI.print(DP);
188 OS << '\n';
189
190 if (DI.getSeverity() == DS_Error)
191 exit(1);
192}
193
Petr Pavlu7ad9ec92016-03-01 13:13:49 +0000194static void diagnosticHandlerWithContext(const DiagnosticInfo &DI,
195 void *Context) {
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000196 diagnosticHandler(DI);
197}
198
Rafael Espindola5e128db2015-12-04 00:45:57 +0000199static void error(const Twine &Msg) {
200 errs() << "llvm-lto: " << Msg << '\n';
201 exit(1);
202}
203
204static void error(std::error_code EC, const Twine &Prefix) {
205 if (EC)
206 error(Prefix + ": " + EC.message());
207}
208
209template <typename T>
210static void error(const ErrorOr<T> &V, const Twine &Prefix) {
211 error(V.getError(), Prefix);
212}
213
Benjamin Kramerf044d3f2015-03-09 16:23:46 +0000214static std::unique_ptr<LTOModule>
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000215getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
Rafael Espindola5e128db2015-12-04 00:45:57 +0000216 const TargetOptions &Options) {
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000217 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
218 MemoryBuffer::getFile(Path);
Rafael Espindola5e128db2015-12-04 00:45:57 +0000219 error(BufferOrErr, "error loading file '" + Path + "'");
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000220 Buffer = std::move(BufferOrErr.get());
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000221 CurrentActivity = ("loading file '" + Path + "'").str();
Petr Pavlu7ad9ec92016-03-01 13:13:49 +0000222 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
223 Context->setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000224 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
Petr Pavlu7ad9ec92016-03-01 13:13:49 +0000225 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
226 Options, Path);
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000227 CurrentActivity = "";
228 return std::move(*Ret);
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000229}
230
231/// \brief List symbols in each IR file.
232///
233/// The main point here is to provide lit-testable coverage for the LTOModule
234/// functionality that's exposed by the C API to list symbols. Moreover, this
235/// provides testing coverage for modules that have been created in their own
236/// contexts.
Rafael Espindola5e128db2015-12-04 00:45:57 +0000237static void listSymbols(const TargetOptions &Options) {
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000238 for (auto &Filename : InputFilenames) {
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000239 std::unique_ptr<MemoryBuffer> Buffer;
240 std::unique_ptr<LTOModule> Module =
Rafael Espindola5e128db2015-12-04 00:45:57 +0000241 getLocalLTOModule(Filename, Buffer, Options);
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000242
243 // List the symbols.
244 outs() << Filename << ":\n";
245 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
246 outs() << Module->getSymbolName(I) << "\n";
247 }
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000248}
249
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000250/// Create a combined index file from the input IR files and write it.
251///
252/// This is meant to enable testing of ThinLTO combined index generation,
253/// currently available via the gold plugin via -thinlto.
Rafael Espindola5e128db2015-12-04 00:45:57 +0000254static void createCombinedFunctionIndex() {
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000255 FunctionInfoIndex CombinedIndex;
256 uint64_t NextModuleId = 0;
257 for (auto &Filename : InputFilenames) {
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000258 CurrentActivity = "loading file '" + Filename + "'";
Teresa Johnson6290dbc2015-11-21 21:55:48 +0000259 ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
Teresa Johnson6b923162015-11-23 19:19:11 +0000260 llvm::getFunctionIndexForFile(Filename, diagnosticHandler);
Teresa Johnson6290dbc2015-11-21 21:55:48 +0000261 std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get());
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000262 CurrentActivity = "";
Teresa Johnson6290dbc2015-11-21 21:55:48 +0000263 // Skip files without a function summary.
264 if (!Index)
265 continue;
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000266 CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
267 }
268 std::error_code EC;
269 assert(!OutputFilename.empty());
270 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
271 sys::fs::OpenFlags::F_None);
Rafael Espindola5e128db2015-12-04 00:45:57 +0000272 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
Teresa Johnson76a1c1d2016-03-11 18:52:24 +0000273 WriteIndexToFile(CombinedIndex, OS);
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000274 OS.close();
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000275}
276
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000277namespace thinlto {
278
279std::vector<std::unique_ptr<MemoryBuffer>>
280loadAllFilesForIndex(const FunctionInfoIndex &Index) {
281 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
282
283 for (auto &ModPath : Index.modPathStringEntries()) {
284 const auto &Filename = ModPath.first();
285 auto CurrentActivity = "loading file '" + Filename + "'";
286 auto InputOrErr = MemoryBuffer::getFile(Filename);
287 error(InputOrErr, "error " + CurrentActivity);
288 InputBuffers.push_back(std::move(*InputOrErr));
289 }
290 return InputBuffers;
291}
292
293std::unique_ptr<FunctionInfoIndex> loadCombinedIndex() {
294 if (ThinLTOIndex.empty())
295 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
296 auto CurrentActivity = "loading file '" + ThinLTOIndex + "'";
297 ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
298 llvm::getFunctionIndexForFile(ThinLTOIndex, diagnosticHandler);
299 error(IndexOrErr, "error " + CurrentActivity);
300 return std::move(IndexOrErr.get());
301}
302
303static std::unique_ptr<Module> loadModule(StringRef Filename,
304 LLVMContext &Ctx) {
305 SMDiagnostic Err;
306 std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
307 if (!M) {
308 Err.print("llvm-lto", errs());
309 report_fatal_error("Can't load module for file " + Filename);
310 }
311 return M;
312}
313
314static void writeModuleToFile(Module &TheModule, StringRef Filename) {
315 std::error_code EC;
316 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
317 error(EC, "error opening the file '" + Filename + "'");
318 WriteBitcodeToFile(&TheModule, OS, true, false);
319}
320
321class ThinLTOProcessing {
322public:
323 ThinLTOCodeGenerator ThinGenerator;
324
325 ThinLTOProcessing(const TargetOptions &Options) {
326 ThinGenerator.setCodePICModel(RelocModel);
327 ThinGenerator.setTargetOptions(Options);
328 }
329
330 void run() {
331 switch (ThinLTOMode) {
332 case THINLINK:
333 return thinLink();
334 case THINPROMOTE:
335 return promote();
336 case THINIMPORT:
337 return import();
338 case THINOPT:
339 return optimize();
340 case THINCODEGEN:
341 return codegen();
342 case THINALL:
343 return runAll();
344 }
345 }
346
347private:
348 /// Load the input files, create the combined index, and write it out.
349 void thinLink() {
350 // Perform "ThinLink": just produce the index
351 if (OutputFilename.empty())
352 report_fatal_error(
353 "OutputFilename is necessary to store the combined index.\n");
354
355 LLVMContext Ctx;
356 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
357 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
358 auto &Filename = InputFilenames[i];
359 StringRef CurrentActivity = "loading file '" + Filename + "'";
360 auto InputOrErr = MemoryBuffer::getFile(Filename);
361 error(InputOrErr, "error " + CurrentActivity);
362 InputBuffers.push_back(std::move(*InputOrErr));
363 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
364 }
365
366 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
367 std::error_code EC;
368 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
369 error(EC, "error opening the file '" + OutputFilename + "'");
Teresa Johnson76a1c1d2016-03-11 18:52:24 +0000370 WriteIndexToFile(*CombinedIndex, OS);
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000371 return;
372 }
373
374 /// Load the combined index from disk, then load every file referenced by
375 /// the index and add them to the generator, finally perform the promotion
376 /// on the files mentioned on the command line (these must match the index
377 /// content).
378 void promote() {
379 if (InputFilenames.size() != 1 && !OutputFilename.empty())
380 report_fatal_error("Can't handle a single output filename and multiple "
381 "input files, do not provide an output filename and "
382 "the output files will be suffixed from the input "
383 "ones.");
384
385 auto Index = loadCombinedIndex();
386 for (auto &Filename : InputFilenames) {
387 LLVMContext Ctx;
388 auto TheModule = loadModule(Filename, Ctx);
389
390 ThinGenerator.promote(*TheModule, *Index);
391
392 std::string OutputName = OutputFilename;
393 if (OutputName.empty()) {
394 OutputName = Filename + ".thinlto.promoted.bc";
395 }
396 writeModuleToFile(*TheModule, OutputName);
397 }
398 }
399
400 /// Load the combined index from disk, then load every file referenced by
401 /// the index and add them to the generator, then performs the promotion and
402 /// cross module importing on the files mentioned on the command line
403 /// (these must match the index content).
404 void import() {
405 if (InputFilenames.size() != 1 && !OutputFilename.empty())
406 report_fatal_error("Can't handle a single output filename and multiple "
407 "input files, do not provide an output filename and "
408 "the output files will be suffixed from the input "
409 "ones.");
410
411 auto Index = loadCombinedIndex();
412 auto InputBuffers = loadAllFilesForIndex(*Index);
413 for (auto &MemBuffer : InputBuffers)
414 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
415 MemBuffer->getBuffer());
416
417 for (auto &Filename : InputFilenames) {
418 LLVMContext Ctx;
419 auto TheModule = loadModule(Filename, Ctx);
420
421 ThinGenerator.crossModuleImport(*TheModule, *Index);
422
423 std::string OutputName = OutputFilename;
424 if (OutputName.empty()) {
425 OutputName = Filename + ".thinlto.imported.bc";
426 }
427 writeModuleToFile(*TheModule, OutputName);
428 }
429 }
430
431 void optimize() {
432 if (InputFilenames.size() != 1 && !OutputFilename.empty())
433 report_fatal_error("Can't handle a single output filename and multiple "
434 "input files, do not provide an output filename and "
435 "the output files will be suffixed from the input "
436 "ones.");
437 if (!ThinLTOIndex.empty())
438 errs() << "Warning: -thinlto-index ignored for optimize stage";
439
440 for (auto &Filename : InputFilenames) {
441 LLVMContext Ctx;
442 auto TheModule = loadModule(Filename, Ctx);
443
444 ThinGenerator.optimize(*TheModule);
445
446 std::string OutputName = OutputFilename;
447 if (OutputName.empty()) {
448 OutputName = Filename + ".thinlto.imported.bc";
449 }
450 writeModuleToFile(*TheModule, OutputName);
451 }
452 }
453
454 void codegen() {
455 if (InputFilenames.size() != 1 && !OutputFilename.empty())
456 report_fatal_error("Can't handle a single output filename and multiple "
457 "input files, do not provide an output filename and "
458 "the output files will be suffixed from the input "
459 "ones.");
460 if (!ThinLTOIndex.empty())
461 errs() << "Warning: -thinlto-index ignored for codegen stage";
462
463 for (auto &Filename : InputFilenames) {
464 LLVMContext Ctx;
465 auto TheModule = loadModule(Filename, Ctx);
466
467 auto Buffer = ThinGenerator.codegen(*TheModule);
468 std::string OutputName = OutputFilename;
469 if (OutputName.empty()) {
470 OutputName = Filename + ".thinlto.o";
471 }
472 if (OutputName == "-") {
473 outs() << Buffer->getBuffer();
474 return;
475 }
476
477 std::error_code EC;
478 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
479 error(EC, "error opening the file '" + OutputName + "'");
480 OS << Buffer->getBuffer();
481 }
482 }
483
484 /// Full ThinLTO process
485 void runAll() {
486 if (!OutputFilename.empty())
487 report_fatal_error("Do not provide an output filename for ThinLTO "
488 " processing, the output files will be suffixed from "
489 "the input ones.");
490
491 if (!ThinLTOIndex.empty())
492 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
493
494 LLVMContext Ctx;
495 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
496 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
497 auto &Filename = InputFilenames[i];
498 StringRef CurrentActivity = "loading file '" + Filename + "'";
499 auto InputOrErr = MemoryBuffer::getFile(Filename);
500 error(InputOrErr, "error " + CurrentActivity);
501 InputBuffers.push_back(std::move(*InputOrErr));
502 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
503 }
504
505 ThinGenerator.run();
506
507 auto &Binaries = ThinGenerator.getProducedBinaries();
508 if (Binaries.size() != InputFilenames.size())
509 report_fatal_error("Number of output objects does not match the number "
510 "of inputs");
511
512 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
513 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
514 std::error_code EC;
515 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
516 error(EC, "error opening the file '" + OutputName + "'");
517 OS << Binaries[BufID]->getBuffer();
518 }
519 }
520
521 /// Load the combined index from disk, then load every file referenced by
522};
523
524} // namespace thinlto
525
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000526int main(int argc, char **argv) {
527 // Print a stack trace if we signal out.
528 sys::PrintStackTraceOnErrorSignal();
529 PrettyStackTraceProgram X(argc, argv);
530
531 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
532 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
533
Rafael Espindola5e128db2015-12-04 00:45:57 +0000534 if (OptLevel < '0' || OptLevel > '3')
535 error("optimization level must be between 0 and 3");
Peter Collingbourne070843d2015-03-19 22:01:00 +0000536
Peter Collingbourne4ccf0f12013-09-24 23:52:22 +0000537 // Initialize the configured targets.
538 InitializeAllTargets();
539 InitializeAllTargetMCs();
540 InitializeAllAsmPrinters();
541 InitializeAllAsmParsers();
542
Rafael Espindola0b385c72013-09-30 16:39:19 +0000543 // set up the TargetOptions for the machine
Eli Benderskyf0f21002014-02-19 17:09:35 +0000544 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Rafael Espindola0b385c72013-09-30 16:39:19 +0000545
Rafael Espindola5e128db2015-12-04 00:45:57 +0000546 if (ListSymbolsOnly) {
547 listSymbols(Options);
548 return 0;
549 }
Duncan P. N. Exon Smithf9abf4f2014-12-17 02:00:38 +0000550
Mehdi Amini7c4a1a82016-03-09 01:37:22 +0000551 if (ThinLTOMode.getNumOccurrences()) {
552 if (ThinLTOMode.getNumOccurrences() > 1)
553 report_fatal_error("You can't specify more than one -thinlto-action");
554 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
555 ThinLTOProcessor.run();
556 return 0;
557 }
558
Rafael Espindola5e128db2015-12-04 00:45:57 +0000559 if (ThinLTO) {
560 createCombinedFunctionIndex();
561 return 0;
562 }
Teresa Johnson91a88bb2015-10-19 14:30:44 +0000563
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000564 unsigned BaseArg = 0;
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000565
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000566 LLVMContext Context;
Petr Pavlu7ad9ec92016-03-01 13:13:49 +0000567 Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000568
569 LTOCodeGenerator CodeGen(Context);
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000570
Duncan P. N. Exon Smith30c92422014-10-01 18:36:03 +0000571 if (UseDiagnosticHandler)
572 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
573
Peter Collingbourne44ee84e2015-08-21 22:57:17 +0000574 CodeGen.setCodePICModel(RelocModel);
James Molloy951e5292014-04-14 13:54:16 +0000575
Peter Collingbourne4ccf0f12013-09-24 23:52:22 +0000576 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
Rafael Espindola0b385c72013-09-30 16:39:19 +0000577 CodeGen.setTargetOptions(Options);
Tobias Edler von Koch3f4f6f3e2016-01-18 23:35:24 +0000578 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000579
Rafael Espindola282a4702013-10-31 20:51:58 +0000580 llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
581 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
582 DSOSymbolsSet.insert(DSOSymbols[i]);
583
584 std::vector<std::string> KeptDSOSyms;
585
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000586 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
Rafael Espindolaa7612b42015-12-04 16:14:31 +0000587 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
588 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
589 LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options);
590 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
591 CurrentActivity = "";
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000592
Peter Collingbourne552174392015-08-21 19:09:42 +0000593 unsigned NumSyms = Module->getSymbolCount();
594 for (unsigned I = 0; I < NumSyms; ++I) {
595 StringRef Name = Module->getSymbolName(I);
596 if (!DSOSymbolsSet.count(Name))
597 continue;
598 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
599 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
600 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
601 KeptDSOSyms.push_back(Name);
602 }
Manman Ren6487ce92015-02-24 00:45:56 +0000603
604 // We use the first input module as the destination module when
605 // SetMergedModule is true.
606 if (SetMergedModule && i == BaseArg) {
607 // Transfer ownership to the code generator.
Peter Collingbourne9c8909d2015-08-24 22:22:53 +0000608 CodeGen.setModule(std::move(Module));
Yunzhong Gao46261a72015-09-11 20:01:53 +0000609 } else if (!CodeGen.addModule(Module.get())) {
610 // Print a message here so that we know addModule() did not abort.
611 errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n";
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000612 return 1;
Yunzhong Gao46261a72015-09-11 20:01:53 +0000613 }
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000614 }
615
Rafael Espindoladafc53d2013-10-02 14:12:56 +0000616 // Add all the exported symbols to the table of symbols to preserve.
617 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
618 CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
619
Rafael Espindolacda29112013-10-03 18:29:09 +0000620 // Add all the dso symbols to the table of symbols to expose.
Rafael Espindola282a4702013-10-31 20:51:58 +0000621 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
622 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str());
Rafael Espindolacda29112013-10-03 18:29:09 +0000623
Akira Hatanaka23b5f672015-01-30 01:14:28 +0000624 // Set cpu and attrs strings for the default target/subtarget.
625 CodeGen.setCpu(MCPU.c_str());
626
Peter Collingbourne070843d2015-03-19 22:01:00 +0000627 CodeGen.setOptLevel(OptLevel - '0');
628
Tom Roederfd1bc602014-04-25 21:46:51 +0000629 std::string attrs;
630 for (unsigned i = 0; i < MAttrs.size(); ++i) {
631 if (i > 0)
632 attrs.append(",");
633 attrs.append(MAttrs[i]);
634 }
635
636 if (!attrs.empty())
637 CodeGen.setAttr(attrs.c_str());
638
Tobias Edler von Koch49c9a6e2015-11-20 00:13:05 +0000639 if (FileType.getNumOccurrences())
640 CodeGen.setFileType(FileType);
641
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000642 if (!OutputFilename.empty()) {
Duncan P. N. Exon Smithcff5fef2015-09-15 23:05:59 +0000643 if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
Yunzhong Gao8e348cc2015-11-17 19:48:12 +0000644 DisableLTOVectorization)) {
645 // Diagnostic messages should have been printed by the handler.
646 errs() << argv[0] << ": error optimizing the code\n";
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000647 return 1;
648 }
649
Tobias Edler von Koch49c9a6e2015-11-20 00:13:05 +0000650 if (SaveModuleFile) {
651 std::string ModuleFilename = OutputFilename;
652 ModuleFilename += ".merged.bc";
653 std::string ErrMsg;
654
655 if (!CodeGen.writeMergedModules(ModuleFilename.c_str())) {
656 errs() << argv[0] << ": writing merged module failed.\n";
657 return 1;
658 }
659 }
660
Peter Collingbournec269ed52015-08-27 23:37:36 +0000661 std::list<tool_output_file> OSs;
662 std::vector<raw_pwrite_stream *> OSPtrs;
663 for (unsigned I = 0; I != Parallelism; ++I) {
664 std::string PartFilename = OutputFilename;
665 if (Parallelism != 1)
666 PartFilename += "." + utostr(I);
667 std::error_code EC;
668 OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
669 if (EC) {
670 errs() << argv[0] << ": error opening the file '" << PartFilename
671 << "': " << EC.message() << "\n";
672 return 1;
673 }
674 OSPtrs.push_back(&OSs.back().os());
675 }
676
Yunzhong Gao8e348cc2015-11-17 19:48:12 +0000677 if (!CodeGen.compileOptimized(OSPtrs)) {
678 // Diagnostic messages should have been printed by the handler.
679 errs() << argv[0] << ": error compiling the code\n";
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000680 return 1;
681 }
682
Peter Collingbournec269ed52015-08-27 23:37:36 +0000683 for (tool_output_file &OS : OSs)
684 OS.keep();
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000685 } else {
Peter Collingbournec269ed52015-08-27 23:37:36 +0000686 if (Parallelism != 1) {
687 errs() << argv[0] << ": -j must be specified together with -o\n";
688 return 1;
689 }
690
Tobias Edler von Koch49c9a6e2015-11-20 00:13:05 +0000691 if (SaveModuleFile) {
692 errs() << argv[0] << ": -save-merged-module must be specified with -o\n";
693 return 1;
694 }
695
Craig Toppere6cb63e2014-04-25 04:24:47 +0000696 const char *OutputName = nullptr;
Duncan P. N. Exon Smithcff5fef2015-09-15 23:05:59 +0000697 if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
Yunzhong Gao8e348cc2015-11-17 19:48:12 +0000698 DisableGVNLoadPRE, DisableLTOVectorization)) {
699 // Diagnostic messages should have been printed by the handler.
700 errs() << argv[0] << ": error compiling the code\n";
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000701 return 1;
702 }
703
704 outs() << "Wrote native object file '" << OutputName << "'\n";
705 }
706
Peter Collingbourne4e380b02013-09-19 22:15:52 +0000707 return 0;
708}