1//===-- 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
15#include "llvm/ADT/StringSet.h"
16#include "llvm/CodeGen/CommandFlags.h"
17#include "llvm/LTO/LTOCodeGenerator.h"
18#include "llvm/LTO/LTOModule.h"
19#include "llvm/Support/CommandLine.h"
20#include "llvm/Support/FileSystem.h"
21#include "llvm/Support/ManagedStatic.h"
22#include "llvm/Support/PrettyStackTrace.h"
23#include "llvm/Support/Signals.h"
24#include "llvm/Support/TargetSelect.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace llvm;
28
29static cl::opt<char>
30OptLevel("O",
31         cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
32                  "(default = '-O2')"),
33         cl::Prefix,
34         cl::ZeroOrMore,
35         cl::init('2'));
36
37static cl::opt<bool>
38DisableInline("disable-inlining", cl::init(false),
39  cl::desc("Do not run the inliner pass"));
40
41static cl::opt<bool>
42DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
43  cl::desc("Do not run the GVN load PRE pass"));
44
45static cl::opt<bool>
46DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
47  cl::desc("Do not run loop or slp vectorization during LTO"));
48
49static cl::opt<bool>
50UseDiagnosticHandler("use-diagnostic-handler", cl::init(false),
51  cl::desc("Use a diagnostic handler to test the handler interface"));
52
53static cl::list<std::string>
54InputFilenames(cl::Positional, cl::OneOrMore,
55  cl::desc("<input bitcode files>"));
56
57static cl::opt<std::string>
58OutputFilename("o", cl::init(""),
59  cl::desc("Override output filename"),
60  cl::value_desc("filename"));
61
62static cl::list<std::string>
63ExportedSymbols("exported-symbol",
64  cl::desc("Symbol to export from the resulting object file"),
65  cl::ZeroOrMore);
66
67static cl::list<std::string>
68DSOSymbols("dso-symbol",
69  cl::desc("Symbol to put in the symtab in the resulting dso"),
70  cl::ZeroOrMore);
71
72static cl::opt<bool> ListSymbolsOnly(
73    "list-symbols-only", cl::init(false),
74    cl::desc("Instead of running LTO, list the symbols in each IR file"));
75
76static cl::opt<bool> SetMergedModule(
77    "set-merged-module", cl::init(false),
78    cl::desc("Use the first input module as the merged module"));
79
80namespace {
81struct ModuleInfo {
82  std::vector<bool> CanBeHidden;
83};
84}
85
86static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
87                              const char *Msg, void *) {
88  switch (Severity) {
89  case LTO_DS_NOTE:
90    errs() << "note: ";
91    break;
92  case LTO_DS_REMARK:
93    errs() << "remark: ";
94    break;
95  case LTO_DS_ERROR:
96    errs() << "error: ";
97    break;
98  case LTO_DS_WARNING:
99    errs() << "warning: ";
100    break;
101  }
102  errs() << Msg << "\n";
103}
104
105static std::unique_ptr<LTOModule>
106getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
107                  const TargetOptions &Options, std::string &Error) {
108  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
109      MemoryBuffer::getFile(Path);
110  if (std::error_code EC = BufferOrErr.getError()) {
111    Error = EC.message();
112    return nullptr;
113  }
114  Buffer = std::move(BufferOrErr.get());
115  return std::unique_ptr<LTOModule>(LTOModule::createInLocalContext(
116      Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path));
117}
118
119/// \brief List symbols in each IR file.
120///
121/// The main point here is to provide lit-testable coverage for the LTOModule
122/// functionality that's exposed by the C API to list symbols.  Moreover, this
123/// provides testing coverage for modules that have been created in their own
124/// contexts.
125static int listSymbols(StringRef Command, const TargetOptions &Options) {
126  for (auto &Filename : InputFilenames) {
127    std::string Error;
128    std::unique_ptr<MemoryBuffer> Buffer;
129    std::unique_ptr<LTOModule> Module =
130        getLocalLTOModule(Filename, Buffer, Options, Error);
131    if (!Module) {
132      errs() << Command << ": error loading file '" << Filename
133             << "': " << Error << "\n";
134      return 1;
135    }
136
137    // List the symbols.
138    outs() << Filename << ":\n";
139    for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
140      outs() << Module->getSymbolName(I) << "\n";
141  }
142  return 0;
143}
144
145int main(int argc, char **argv) {
146  // Print a stack trace if we signal out.
147  sys::PrintStackTraceOnErrorSignal();
148  PrettyStackTraceProgram X(argc, argv);
149
150  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
151  cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
152
153  if (OptLevel < '0' || OptLevel > '3') {
154    errs() << argv[0] << ": optimization level must be between 0 and 3\n";
155    return 1;
156  }
157
158  // Initialize the configured targets.
159  InitializeAllTargets();
160  InitializeAllTargetMCs();
161  InitializeAllAsmPrinters();
162  InitializeAllAsmParsers();
163
164  // set up the TargetOptions for the machine
165  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
166
167  if (ListSymbolsOnly)
168    return listSymbols(argv[0], Options);
169
170  unsigned BaseArg = 0;
171
172  LTOCodeGenerator CodeGen;
173
174  if (UseDiagnosticHandler)
175    CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
176
177  switch (RelocModel) {
178  case Reloc::Static:
179    CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC);
180    break;
181  case Reloc::PIC_:
182    CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC);
183    break;
184  case Reloc::DynamicNoPIC:
185    CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC);
186    break;
187  default:
188    CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT);
189  }
190
191  CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
192  CodeGen.setTargetOptions(Options);
193
194  llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
195  for (unsigned i = 0; i < DSOSymbols.size(); ++i)
196    DSOSymbolsSet.insert(DSOSymbols[i]);
197
198  std::vector<std::string> KeptDSOSyms;
199
200  for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
201    std::string error;
202    std::unique_ptr<LTOModule> Module(
203        LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
204    if (!error.empty()) {
205      errs() << argv[0] << ": error loading file '" << InputFilenames[i]
206             << "': " << error << "\n";
207      return 1;
208    }
209
210    LTOModule *LTOMod = Module.get();
211
212    // We use the first input module as the destination module when
213    // SetMergedModule is true.
214    if (SetMergedModule && i == BaseArg) {
215      // Transfer ownership to the code generator.
216      CodeGen.setModule(Module.release());
217    } else if (!CodeGen.addModule(Module.get()))
218      return 1;
219
220    unsigned NumSyms = LTOMod->getSymbolCount();
221    for (unsigned I = 0; I < NumSyms; ++I) {
222      StringRef Name = LTOMod->getSymbolName(I);
223      if (!DSOSymbolsSet.count(Name))
224        continue;
225      lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I);
226      unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
227      if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
228        KeptDSOSyms.push_back(Name);
229    }
230  }
231
232  // Add all the exported symbols to the table of symbols to preserve.
233  for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
234    CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
235
236  // Add all the dso symbols to the table of symbols to expose.
237  for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
238    CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str());
239
240  // Set cpu and attrs strings for the default target/subtarget.
241  CodeGen.setCpu(MCPU.c_str());
242
243  CodeGen.setOptLevel(OptLevel - '0');
244
245  std::string attrs;
246  for (unsigned i = 0; i < MAttrs.size(); ++i) {
247    if (i > 0)
248      attrs.append(",");
249    attrs.append(MAttrs[i]);
250  }
251
252  if (!attrs.empty())
253    CodeGen.setAttr(attrs.c_str());
254
255  if (!OutputFilename.empty()) {
256    size_t len = 0;
257    std::string ErrorInfo;
258    const void *Code =
259        CodeGen.compile(&len, DisableInline, DisableGVNLoadPRE,
260                        DisableLTOVectorization, ErrorInfo);
261    if (!Code) {
262      errs() << argv[0]
263             << ": error compiling the code: " << ErrorInfo << "\n";
264      return 1;
265    }
266
267    std::error_code EC;
268    raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None);
269    if (EC) {
270      errs() << argv[0] << ": error opening the file '" << OutputFilename
271             << "': " << EC.message() << "\n";
272      return 1;
273    }
274
275    FileStream.write(reinterpret_cast<const char *>(Code), len);
276  } else {
277    std::string ErrorInfo;
278    const char *OutputName = nullptr;
279    if (!CodeGen.compile_to_file(&OutputName, DisableInline,
280                                 DisableGVNLoadPRE, DisableLTOVectorization,
281                                 ErrorInfo)) {
282      errs() << argv[0]
283             << ": error compiling the code: " << ErrorInfo
284             << "\n";
285      return 1;
286    }
287
288    outs() << "Wrote native object file '" << OutputName << "'\n";
289  }
290
291  return 0;
292}
293