blob: 795aca01f566baa1d8e48c1b6a96e146d5c39aad [file] [log] [blame]
Nick Kledzik6d886992008-02-26 20:26:43 +00001//===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===//
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 file implements the Link Time Optimization library. This library is
11// intended to be used by linker to optimize code at link time.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Module.h"
16#include "llvm/PassManager.h"
17#include "llvm/Linker.h"
18#include "llvm/Constants.h"
19#include "llvm/DerivedTypes.h"
20#include "llvm/ModuleProvider.h"
21#include "llvm/Bitcode/ReaderWriter.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/FileUtilities.h"
24#include "llvm/Support/SystemUtils.h"
25#include "llvm/Support/Mangler.h"
26#include "llvm/Support/MemoryBuffer.h"
27#include "llvm/System/Program.h"
28#include "llvm/System/Signals.h"
29#include "llvm/Analysis/Passes.h"
30#include "llvm/Analysis/LoopPass.h"
31#include "llvm/Analysis/Verifier.h"
32#include "llvm/CodeGen/FileWriters.h"
33#include "llvm/Target/SubtargetFeature.h"
34#include "llvm/Target/TargetOptions.h"
35#include "llvm/Target/TargetData.h"
36#include "llvm/Target/TargetMachine.h"
37#include "llvm/Target/TargetMachineRegistry.h"
38#include "llvm/Target/TargetAsmInfo.h"
39#include "llvm/Transforms/IPO.h"
40#include "llvm/Transforms/Scalar.h"
41#include "llvm/Analysis/LoadValueNumbering.h"
42#include "llvm/Support/MathExtras.h"
43#include "llvm/Config/config.h"
44
45#include "LTOModule.h"
46#include "LTOCodeGenerator.h"
47
48#include <fstream>
49#include <unistd.h>
50#include <stdlib.h>
51#include <fcntl.h>
52
53
54using namespace llvm;
55
56
57
58const char* LTOCodeGenerator::getVersionString()
59{
60#ifdef LLVM_VERSION_INFO
61 return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
62#else
63 return PACKAGE_NAME " version " PACKAGE_VERSION;
64#endif
65}
66
67
68LTOCodeGenerator::LTOCodeGenerator()
69 : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL),
70 _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
71 _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC)
72{
73
74}
75
76LTOCodeGenerator::~LTOCodeGenerator()
77{
78 // FIXME
79}
80
81
82
83bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
84{
85 return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
86}
87
88
89bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg)
90{
91 switch (debug) {
92 case LTO_DEBUG_MODEL_NONE:
93 _emitDwarfDebugInfo = false;
94 return false;
95
96 case LTO_DEBUG_MODEL_DWARF:
97 _emitDwarfDebugInfo = true;
98 return false;
99 }
100 errMsg = "unknown debug format";
101 return true;
102}
103
104
105bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
106 std::string& errMsg)
107{
108 switch (model) {
109 case LTO_CODEGEN_PIC_MODEL_STATIC:
110 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
111 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
112 _codeModel = model;
113 return false;
114 }
115 errMsg = "unknown pic model";
116 return true;
117}
118
119
120void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
121{
122 _mustPreserveSymbols[sym] = 1;
123}
124
125
126bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg)
127{
128 if ( this->determineTarget(errMsg) )
129 return true;
130
131 // mark which symbols can not be internalized
132 this->applyScopeRestrictions();
133
134 // create output file
135 std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary);
136 if ( out.fail() ) {
137 errMsg = "could not open bitcode file for writing: ";
138 errMsg += path;
139 return true;
140 }
141
142 // write bitcode to it
143 WriteBitcodeToFile(_linker.getModule(), out);
144 if ( out.fail() ) {
145 errMsg = "could not write bitcode file: ";
146 errMsg += path;
147 return true;
148 }
149
150 return false;
151}
152
153
154void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
155{
156 // make unqiue temp .s file to put generated assembly code
157 sys::Path uniqueAsmPath("lto-llvm.s");
158 if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) )
159 return NULL;
160 sys::RemoveFileOnSignal(uniqueAsmPath);
161
162 // generate assembly code
163 std::ofstream asmFile(uniqueAsmPath.c_str());
164 bool genResult = this->generateAssemblyCode(asmFile, errMsg);
165 asmFile.close();
166 if ( genResult ) {
167 if ( uniqueAsmPath.exists() )
168 uniqueAsmPath.eraseFromDisk();
169 return NULL;
170 }
171
172 // make unqiue temp .o file to put generated object file
173 sys::PathWithStatus uniqueObjPath("lto-llvm.o");
174 if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) {
175 if ( uniqueAsmPath.exists() )
176 uniqueAsmPath.eraseFromDisk();
177 return NULL;
178 }
179 sys::RemoveFileOnSignal(uniqueObjPath);
180
181 // assemble the assembly code
182 void* buffer = NULL;
183 bool asmResult = this->assemble(uniqueAsmPath.toString(),
184 uniqueObjPath.toString(), errMsg);
185 if ( !asmResult ) {
186 // read .o file into memory buffer
187 const sys::FileStatus* objStatus;
188 objStatus = uniqueObjPath.getFileStatus(false, &errMsg);
189 if ( objStatus != NULL ) {
190 *length = objStatus->getSize();
191 // use malloc() because caller will own this buffer and free() it
192 buffer = ::malloc(*length);
193 if ( buffer != NULL ) {
194 int fd = ::open(uniqueObjPath.c_str(), O_RDONLY, 0);
195 if ( fd != -1 ) {
196 // read object file contents into buffer
197 if ( ::read(fd, buffer, *length) != (ssize_t)*length ) {
198 errMsg = "error reading object file";
199 free(buffer);
200 buffer = NULL;
201 }
202 close(fd);
203 }
204 else {
205 errMsg = "error opening object file";
206 free(buffer);
207 buffer = NULL;
208 }
209 }
210 else {
211 errMsg = "error mallocing space for object file";
212 }
213 }
214 else {
215 errMsg = "error stat'ing object file";
216 }
217 }
218 // clean up temp files
219 uniqueAsmPath.eraseFromDisk();
220 uniqueObjPath.eraseFromDisk();
221 return buffer;
222}
223
224
225bool LTOCodeGenerator::assemble(const std::string& asmPath,
226 const std::string& objPath, std::string& errMsg)
227{
228 // find compiler driver
229 const sys::Path gcc = sys::Program::FindProgramByName("gcc");
230 if ( gcc.isEmpty() ) {
231 errMsg = "can't locate gcc";
232 return true;
233 }
234
235 // build argument list
236 std::vector<const char*> args;
237 std::string targetTriple = _linker.getModule()->getTargetTriple();
238 args.push_back(gcc.c_str());
239 if ( targetTriple.find("darwin") != targetTriple.size() ) {
240 if (strncmp(targetTriple.c_str(), "i686-apple-", 11) == 0) {
241 args.push_back("-arch");
242 args.push_back("i386");
243 }
244 else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
245 args.push_back("-arch");
246 args.push_back("x86_64");
247 }
248 else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
249 args.push_back("-arch");
250 args.push_back("ppc");
251 }
252 else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
253 args.push_back("-arch");
254 args.push_back("ppc64");
255 }
256 }
257 args.push_back("-c");
258 args.push_back("-x");
259 args.push_back("assembler");
260 args.push_back("-o");
261 args.push_back(objPath.c_str());
262 args.push_back(asmPath.c_str());
263 args.push_back(0);
264
265 // invoke assembler
266 if ( sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &errMsg) ) {
267 errMsg = "error in assembly";
268 return true;
269 }
270 return false; // success
271}
272
273
274
275bool LTOCodeGenerator::determineTarget(std::string& errMsg)
276{
277 if ( _target == NULL ) {
278 // create target machine from info for merged modules
279 Module* mergedModule = _linker.getModule();
280 const TargetMachineRegistry::entry* march =
281 TargetMachineRegistry::getClosestStaticTargetForModule(
282 *mergedModule, errMsg);
283 if ( march == NULL )
284 return true;
285 std::string features;
286 _target = march->CtorFn(*mergedModule, features);
287 }
288 return false;
289}
290
291void LTOCodeGenerator::applyScopeRestrictions()
292{
293 if ( !_scopeRestrictionsDone ) {
294 Module* mergedModule = _linker.getModule();
295
296 // Start off with a verification pass.
297 PassManager passes;
298 passes.add(createVerifierPass());
299
300 // mark which symbols can not be internalized
301 if ( !_mustPreserveSymbols.empty() ) {
302 Mangler mangler(*mergedModule,
303 _target->getTargetAsmInfo()->getGlobalPrefix());
304 std::vector<const char*> mustPreserveList;
305 for (Module::iterator f = mergedModule->begin(),
306 e = mergedModule->end(); f != e; ++f) {
307 if ( !f->isDeclaration()
308 && _mustPreserveSymbols.count(mangler.getValueName(f)) )
309 mustPreserveList.push_back(::strdup(f->getName().c_str()));
310 }
311 for (Module::global_iterator v = mergedModule->global_begin(),
312 e = mergedModule->global_end(); v != e; ++v) {
313 if ( !v->isDeclaration()
314 && _mustPreserveSymbols.count(mangler.getValueName(v)) )
315 mustPreserveList.push_back(::strdup(v->getName().c_str()));
316 }
317 passes.add(createInternalizePass(mustPreserveList));
318 }
319 // apply scope restrictions
320 passes.run(*mergedModule);
321
322 _scopeRestrictionsDone = true;
323 }
324}
325
326
327/// Optimize merged modules using various IPO passes
328bool LTOCodeGenerator::generateAssemblyCode(std::ostream& out, std::string& errMsg)
329{
330 if ( this->determineTarget(errMsg) )
331 return true;
332
333 // mark which symbols can not be internalized
334 this->applyScopeRestrictions();
335
336 Module* mergedModule = _linker.getModule();
337
338 // If target supports exception handling then enable it now.
339 if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
340 llvm::ExceptionHandling = true;
341
342 // set codegen model
343 switch( _codeModel ) {
344 case LTO_CODEGEN_PIC_MODEL_STATIC:
345 _target->setRelocationModel(Reloc::Static);
346 break;
347 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
348 _target->setRelocationModel(Reloc::PIC_);
349 break;
350 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
351 _target->setRelocationModel(Reloc::DynamicNoPIC);
352 break;
353 }
354
355 // Instantiate the pass manager to organize the passes.
356 PassManager passes;
357
358 // Start off with a verification pass.
359 passes.add(createVerifierPass());
360
361 // Add an appropriate TargetData instance for this module...
362 passes.add(new TargetData(*_target->getTargetData()));
363
364 // Now that we internalized some globals, see if we can hack on them!
365 passes.add(createGlobalOptimizerPass());
366
367 // Linking modules together can lead to duplicated global constants, only
368 // keep one copy of each constant...
369 passes.add(createConstantMergePass());
370
371 // If the -s command line option was specified, strip the symbols out of the
372 // resulting program to make it smaller. -s is a GLD option that we are
373 // supporting.
374 if( !llvm::ExceptionHandling ) {
375 // FIXME : This causes multiple nameless _.eh symbols on
376 // darwin when EH is ON.
377 passes.add(createStripSymbolsPass());
378 }
379
380 // Propagate constants at call sites into the functions they call.
381 passes.add(createIPConstantPropagationPass());
382
383 // Remove unused arguments from functions...
384 passes.add(createDeadArgEliminationPass());
385
386 passes.add(createFunctionInliningPass()); // Inline small functions
387
388 passes.add(createPruneEHPass()); // Remove dead EH info
389
390 passes.add(createGlobalDCEPass()); // Remove dead functions
391
392 // If we didn't decide to inline a function, check to see if we can
393 // transform it to pass arguments by value instead of by reference.
394 passes.add(createArgumentPromotionPass());
395
396 // The IPO passes may leave cruft around. Clean up after them.
397 passes.add(createInstructionCombiningPass());
398
399 passes.add(createScalarReplAggregatesPass()); // Break up allocas
400
401 // Run a few AA driven optimizations here and now, to cleanup the code.
402 passes.add(createGlobalsModRefPass()); // IP alias analysis
403
404 passes.add(createLICMPass()); // Hoist loop invariants
405 passes.add(createLoadValueNumberingPass()); // GVN for load instrs
406 passes.add(createGCSEPass()); // Remove common subexprs
407 passes.add(createDeadStoreEliminationPass()); // Nuke dead stores
408
409 // Cleanup and simplify the code after the scalar optimizations.
410 passes.add(createInstructionCombiningPass());
411
412 // Delete basic blocks, which optimization passes may have killed...
413 passes.add(createCFGSimplificationPass());
414
415 // Now that we have optimized the program, discard unreachable functions...
416 passes.add(createGlobalDCEPass());
417
418 // Make sure everything is still good.
419 passes.add(createVerifierPass());
420
421 FunctionPassManager* codeGenPasses =
422 new FunctionPassManager(new ExistingModuleProvider(mergedModule));
423
424 codeGenPasses->add(new TargetData(*_target->getTargetData()));
425
426 MachineCodeEmitter* mce = NULL;
427
428 switch (_target->addPassesToEmitFile(*codeGenPasses, out,
429 TargetMachine::AssemblyFile, true)) {
430 case FileModel::MachOFile:
431 mce = AddMachOWriter(*codeGenPasses, out, *_target);
432 break;
433 case FileModel::ElfFile:
434 mce = AddELFWriter(*codeGenPasses, out, *_target);
435 break;
436 case FileModel::AsmFile:
437 break;
438 case FileModel::Error:
439 case FileModel::None:
440 errMsg = "target file type not supported";
441 return true;
442 }
443
444 if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce, true)) {
445 errMsg = "target does not support generation of this file type";
446 return true;
447 }
448
449 // Run our queue of passes all at once now, efficiently.
450 passes.run(*mergedModule);
451
452 // Run the code generator, and write assembly file
453 codeGenPasses->doInitialization();
454 for (Module::iterator it = mergedModule->begin(),
455 e = mergedModule->end(); it != e; ++it) {
456 if (!it->isDeclaration())
457 codeGenPasses->run(*it);
458 }
459 codeGenPasses->doFinalization();
460
461 return false; // success
462}
463
464
465