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