52624ebe91001419ff0f8062f65be3e9ebb9d9f0
[oota-llvm.git] / tools / lto / LTOCodeGenerator.cpp
1 //===-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 "LTOModule.h"
16 #include "LTOCodeGenerator.h"
17
18
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Linker.h"
22 #include "llvm/Module.h"
23 #include "llvm/ModuleProvider.h"
24 #include "llvm/PassManager.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/Analysis/Passes.h"
27 #include "llvm/Analysis/LoopPass.h"
28 #include "llvm/Analysis/Verifier.h"
29 #include "llvm/Bitcode/ReaderWriter.h"
30 #include "llvm/CodeGen/FileWriters.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/Mangler.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/StandardPasses.h"
35 #include "llvm/Support/SystemUtils.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include "llvm/System/Signals.h"
38 #include "llvm/Target/SubtargetFeature.h"
39 #include "llvm/Target/TargetOptions.h"
40 #include "llvm/Target/TargetAsmInfo.h"
41 #include "llvm/Target/TargetData.h"
42 #include "llvm/Target/TargetMachine.h"
43 #include "llvm/Target/TargetMachineRegistry.h"
44 #include "llvm/Target/TargetSelect.h"
45 #include "llvm/Transforms/IPO.h"
46 #include "llvm/Transforms/Scalar.h"
47 #include "llvm/Config/config.h"
48
49
50 #include <cstdlib>
51 #include <fstream>
52 #include <unistd.h>
53 #include <fcntl.h>
54
55
56 using namespace llvm;
57
58 static cl::opt<bool> DisableInline("disable-inlining",
59   cl::desc("Do not run the inliner pass"));
60
61
62 const char* LTOCodeGenerator::getVersionString()
63 {
64 #ifdef LLVM_VERSION_INFO
65     return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
66 #else
67     return PACKAGE_NAME " version " PACKAGE_VERSION;
68 #endif
69 }
70
71
72 LTOCodeGenerator::LTOCodeGenerator() 
73     : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL),
74       _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
75       _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
76       _nativeObjectFile(NULL), _gccPath(NULL), _assemblerPath(NULL)
77 {
78   InitializeAllTargets();
79   InitializeAllAsmPrinters();
80
81 }
82
83 LTOCodeGenerator::~LTOCodeGenerator()
84 {
85     delete _target;
86     delete _nativeObjectFile;
87 }
88
89
90
91 bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
92 {
93     return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
94 }
95     
96
97 bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg)
98 {
99     switch (debug) {
100         case LTO_DEBUG_MODEL_NONE:
101             _emitDwarfDebugInfo = false;
102             return false;
103             
104         case LTO_DEBUG_MODEL_DWARF:
105             _emitDwarfDebugInfo = true;
106             return false;
107     }
108     errMsg = "unknown debug format";
109     return true;
110 }
111
112
113 bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, 
114                                        std::string& errMsg)
115 {
116     switch (model) {
117         case LTO_CODEGEN_PIC_MODEL_STATIC:
118         case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
119         case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
120             _codeModel = model;
121             return false;
122     }
123     errMsg = "unknown pic model";
124     return true;
125 }
126
127 void LTOCodeGenerator::setGccPath(const char* path)
128 {
129     if ( _gccPath )
130         delete _gccPath;
131     _gccPath = new sys::Path(path);
132 }
133
134 void LTOCodeGenerator::setAssemblerPath(const char* path)
135 {
136     if ( _assemblerPath )
137         delete _assemblerPath;
138     _assemblerPath = new sys::Path(path);
139 }
140
141 void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
142 {
143     _mustPreserveSymbols[sym] = 1;
144 }
145
146
147 bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg)
148 {
149     if ( this->determineTarget(errMsg) ) 
150         return true;
151
152     // mark which symbols can not be internalized 
153     this->applyScopeRestrictions();
154
155     // create output file
156     std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary);
157     if ( out.fail() ) {
158         errMsg = "could not open bitcode file for writing: ";
159         errMsg += path;
160         return true;
161     }
162     
163     // write bitcode to it
164     WriteBitcodeToFile(_linker.getModule(), out);
165     if ( out.fail() ) {
166         errMsg = "could not write bitcode file: ";
167         errMsg += path;
168         return true;
169     }
170     
171     return false;
172 }
173
174
175 const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
176 {
177     // make unique temp .s file to put generated assembly code
178     sys::Path uniqueAsmPath("lto-llvm.s");
179     if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) )
180         return NULL;
181     sys::RemoveFileOnSignal(uniqueAsmPath);
182        
183     // generate assembly code
184     bool genResult = false;
185     {
186       raw_fd_ostream asmFile(uniqueAsmPath.c_str(), false, errMsg);
187       if (!errMsg.empty())
188         return NULL;
189       genResult = this->generateAssemblyCode(asmFile, errMsg);
190     }
191     if ( genResult ) {
192         if ( uniqueAsmPath.exists() )
193             uniqueAsmPath.eraseFromDisk();
194         return NULL;
195     }
196     
197     // make unique temp .o file to put generated object file
198     sys::PathWithStatus uniqueObjPath("lto-llvm.o");
199     if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) {
200         if ( uniqueAsmPath.exists() )
201             uniqueAsmPath.eraseFromDisk();
202         return NULL;
203     }
204     sys::RemoveFileOnSignal(uniqueObjPath);
205
206     // assemble the assembly code
207     const std::string& uniqueObjStr = uniqueObjPath.toString();
208     bool asmResult = this->assemble(uniqueAsmPath.toString(), 
209                                                         uniqueObjStr, errMsg);
210     if ( !asmResult ) {
211         // remove old buffer if compile() called twice
212         delete _nativeObjectFile;
213         
214         // read .o file into memory buffer
215         _nativeObjectFile = MemoryBuffer::getFile(uniqueObjStr.c_str(),&errMsg);
216     }
217
218     // remove temp files
219     uniqueAsmPath.eraseFromDisk();
220     uniqueObjPath.eraseFromDisk();
221
222     // return buffer, unless error
223     if ( _nativeObjectFile == NULL )
224         return NULL;
225     *length = _nativeObjectFile->getBufferSize();
226     return _nativeObjectFile->getBufferStart();
227 }
228
229
230 bool LTOCodeGenerator::assemble(const std::string& asmPath, 
231                                 const std::string& objPath, std::string& errMsg)
232 {
233     sys::Path tool;
234     bool needsCompilerOptions = true;
235     if ( _assemblerPath ) {
236         tool = *_assemblerPath;
237         needsCompilerOptions = false;
238     }
239     else if ( _gccPath ) {
240         tool = *_gccPath;
241     } else {
242         // find compiler driver
243         tool = sys::Program::FindProgramByName("gcc");
244         if ( tool.isEmpty() ) {
245             errMsg = "can't locate gcc";
246             return true;
247         }
248     }
249
250     // build argument list
251     std::vector<const char*> args;
252     std::string targetTriple = _linker.getModule()->getTargetTriple();
253     args.push_back(tool.c_str());
254     if ( targetTriple.find("darwin") != std::string::npos ) {
255         // darwin specific command line options
256         if (strncmp(targetTriple.c_str(), "i386-apple-", 11) == 0) {
257             args.push_back("-arch");
258             args.push_back("i386");
259         }
260         else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
261             args.push_back("-arch");
262             args.push_back("x86_64");
263         }
264         else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
265             args.push_back("-arch");
266             args.push_back("ppc");
267         }
268         else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
269             args.push_back("-arch");
270             args.push_back("ppc64");
271         }
272         else if (strncmp(targetTriple.c_str(), "arm-apple-", 10) == 0) {
273             args.push_back("-arch");
274             args.push_back("arm");
275         }
276         else if ((strncmp(targetTriple.c_str(), "armv4t-apple-", 13) == 0) ||
277                  (strncmp(targetTriple.c_str(), "thumbv4t-apple-", 15) == 0)) {
278             args.push_back("-arch");
279             args.push_back("armv4t");
280         }
281         else if ((strncmp(targetTriple.c_str(), "armv5-apple-", 12) == 0) ||
282                  (strncmp(targetTriple.c_str(), "armv5e-apple-", 13) == 0) ||
283                  (strncmp(targetTriple.c_str(), "thumbv5-apple-", 14) == 0) ||
284                  (strncmp(targetTriple.c_str(), "thumbv5e-apple-", 15) == 0)) {
285             args.push_back("-arch");
286             args.push_back("armv5");
287         }
288         else if ((strncmp(targetTriple.c_str(), "armv6-apple-", 12) == 0) ||
289                  (strncmp(targetTriple.c_str(), "thumbv6-apple-", 14) == 0)) {
290             args.push_back("-arch");
291             args.push_back("armv6");
292         }
293         else if ((strncmp(targetTriple.c_str(), "armv7-apple-", 12) == 0) ||
294                  (strncmp(targetTriple.c_str(), "thumbv7-apple-", 14) == 0)) {
295             args.push_back("-arch");
296             args.push_back("armv7");
297         }
298         // add -static to assembler command line when code model requires
299         if ( (_assemblerPath != NULL) && (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) )
300             args.push_back("-static");
301     }
302     if ( needsCompilerOptions ) {
303         args.push_back("-c");
304         args.push_back("-x");
305         args.push_back("assembler");
306     }
307     args.push_back("-o");
308     args.push_back(objPath.c_str());
309     args.push_back(asmPath.c_str());
310     args.push_back(0);
311
312     // invoke assembler
313     if ( sys::Program::ExecuteAndWait(tool, &args[0], 0, 0, 0, 0, &errMsg) ) {
314         errMsg = "error in assembly";    
315         return true;
316     }
317     return false; // success
318 }
319
320
321
322 bool LTOCodeGenerator::determineTarget(std::string& errMsg)
323 {
324     if ( _target == NULL ) {
325         // create target machine from info for merged modules
326         Module* mergedModule = _linker.getModule();
327         const TargetMachineRegistry::entry* march = 
328           TargetMachineRegistry::getClosestStaticTargetForModule(
329                                                        *mergedModule, errMsg);
330         if ( march == NULL )
331             return true;
332
333         // The relocation model is actually a static member of TargetMachine
334         // and needs to be set before the TargetMachine is instantiated.
335         switch( _codeModel ) {
336         case LTO_CODEGEN_PIC_MODEL_STATIC:
337             TargetMachine::setRelocationModel(Reloc::Static);
338             break;
339         case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
340             TargetMachine::setRelocationModel(Reloc::PIC_);
341             break;
342         case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
343             TargetMachine::setRelocationModel(Reloc::DynamicNoPIC);
344             break;
345         }
346
347         // construct LTModule, hand over ownership of module and target
348         std::string FeatureStr =
349           getFeatureString(_linker.getModule()->getTargetTriple().c_str());
350         _target = march->CtorFn(*mergedModule, FeatureStr.c_str());
351     }
352     return false;
353 }
354
355 void LTOCodeGenerator::applyScopeRestrictions()
356 {
357     if ( !_scopeRestrictionsDone ) {
358         Module* mergedModule = _linker.getModule();
359
360         // Start off with a verification pass.
361         PassManager passes;
362         passes.add(createVerifierPass());
363
364         // mark which symbols can not be internalized 
365         if ( !_mustPreserveSymbols.empty() ) {
366             Mangler mangler(*mergedModule, 
367                                 _target->getTargetAsmInfo()->getGlobalPrefix());
368             std::vector<const char*> mustPreserveList;
369             for (Module::iterator f = mergedModule->begin(), 
370                                         e = mergedModule->end(); f != e; ++f) {
371                 if ( !f->isDeclaration() 
372                   && _mustPreserveSymbols.count(mangler.getValueName(f)) )
373                     mustPreserveList.push_back(::strdup(f->getName().c_str()));
374             }
375             for (Module::global_iterator v = mergedModule->global_begin(), 
376                                  e = mergedModule->global_end(); v !=  e; ++v) {
377                 if ( !v->isDeclaration()
378                   && _mustPreserveSymbols.count(mangler.getValueName(v)) )
379                     mustPreserveList.push_back(::strdup(v->getName().c_str()));
380             }
381             passes.add(createInternalizePass(mustPreserveList));
382         }
383         // apply scope restrictions
384         passes.run(*mergedModule);
385         
386         _scopeRestrictionsDone = true;
387     }
388 }
389
390 /// Optimize merged modules using various IPO passes
391 bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
392                                             std::string& errMsg)
393 {
394     if (  this->determineTarget(errMsg) ) 
395         return true;
396
397     // mark which symbols can not be internalized 
398     this->applyScopeRestrictions();
399
400     Module* mergedModule = _linker.getModule();
401
402      // If target supports exception handling then enable it now.
403     if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
404         llvm::ExceptionHandling = true;
405
406     // if options were requested, set them
407     if ( !_codegenOptions.empty() )
408         cl::ParseCommandLineOptions(_codegenOptions.size(), 
409                                                 (char**)&_codegenOptions[0]);
410
411     // Instantiate the pass manager to organize the passes.
412     PassManager passes;
413
414     // Start off with a verification pass.
415     passes.add(createVerifierPass());
416
417     // Add an appropriate TargetData instance for this module...
418     passes.add(new TargetData(*_target->getTargetData()));
419     
420     createStandardLTOPasses(&passes, /*Internalize=*/ false, !DisableInline,
421                             /*VerifyEach=*/ false);
422
423     // Make sure everything is still good.
424     passes.add(createVerifierPass());
425
426     FunctionPassManager* codeGenPasses =
427             new FunctionPassManager(new ExistingModuleProvider(mergedModule));
428
429     codeGenPasses->add(new TargetData(*_target->getTargetData()));
430
431     MachineCodeEmitter* mce = NULL;
432
433     switch (_target->addPassesToEmitFile(*codeGenPasses, out,
434                                          TargetMachine::AssemblyFile,
435                                          CodeGenOpt::Aggressive)) {
436         case FileModel::MachOFile:
437             mce = AddMachOWriter(*codeGenPasses, out, *_target);
438             break;
439         case FileModel::ElfFile:
440             mce = AddELFWriter(*codeGenPasses, out, *_target);
441             break;
442         case FileModel::AsmFile:
443             break;
444         case FileModel::Error:
445         case FileModel::None:
446             errMsg = "target file type not supported";
447             return true;
448     }
449
450     if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce,
451                                            CodeGenOpt::Aggressive)) {
452         errMsg = "target does not support generation of this file type";
453         return true;
454     }
455
456     // Run our queue of passes all at once now, efficiently.
457     passes.run(*mergedModule);
458
459     // Run the code generator, and write assembly file
460     codeGenPasses->doInitialization();
461
462     for (Module::iterator
463            it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
464       if (!it->isDeclaration())
465         codeGenPasses->run(*it);
466
467     codeGenPasses->doFinalization();
468     return false; // success
469 }
470
471
472 /// Optimize merged modules using various IPO passes
473 void LTOCodeGenerator::setCodeGenDebugOptions(const char* options)
474 {
475     std::string ops(options);
476     for (std::string o = getToken(ops); !o.empty(); o = getToken(ops)) {
477         // ParseCommandLineOptions() expects argv[0] to be program name.
478         // Lazily add that.
479         if ( _codegenOptions.empty() ) 
480             _codegenOptions.push_back("libLTO");
481         _codegenOptions.push_back(strdup(o.c_str()));
482     }
483 }