LTOCodeGenerator.cpp revision 2deb58f72ec6547a2f760fc48f86b4d95d0a4a02
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
56using namespace llvm;
57
58static cl::opt<bool> DisableInline("disable-inlining",
59  cl::desc("Do not run the inliner pass"));
60
61
62const 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
72LTOCodeGenerator::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
83LTOCodeGenerator::~LTOCodeGenerator()
84{
85    delete _target;
86    delete _nativeObjectFile;
87}
88
89
90
91bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
92{
93    return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
94}
95
96
97bool 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
113bool 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
127void LTOCodeGenerator::setGccPath(const char* path)
128{
129    if ( _gccPath )
130        delete _gccPath;
131    _gccPath = new sys::Path(path);
132}
133
134void LTOCodeGenerator::setAssemblerPath(const char* path)
135{
136    if ( _assemblerPath )
137        delete _assemblerPath;
138    _assemblerPath = new sys::Path(path);
139}
140
141void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
142{
143    _mustPreserveSymbols[sym] = 1;
144}
145
146
147bool 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
175const 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
230bool 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        // add -static to assembler command line when code model requires
294        if ( (_assemblerPath != NULL) && (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) )
295            args.push_back("-static");
296    }
297    if ( needsCompilerOptions ) {
298        args.push_back("-c");
299        args.push_back("-x");
300        args.push_back("assembler");
301    }
302    args.push_back("-o");
303    args.push_back(objPath.c_str());
304    args.push_back(asmPath.c_str());
305    args.push_back(0);
306
307    // invoke assembler
308    if ( sys::Program::ExecuteAndWait(tool, &args[0], 0, 0, 0, 0, &errMsg) ) {
309        errMsg = "error in assembly";
310        return true;
311    }
312    return false; // success
313}
314
315
316
317bool LTOCodeGenerator::determineTarget(std::string& errMsg)
318{
319    if ( _target == NULL ) {
320        // create target machine from info for merged modules
321        Module* mergedModule = _linker.getModule();
322        const TargetMachineRegistry::entry* march =
323          TargetMachineRegistry::getClosestStaticTargetForModule(
324                                                       *mergedModule, errMsg);
325        if ( march == NULL )
326            return true;
327
328        // The relocation model is actually a static member of TargetMachine
329        // and needs to be set before the TargetMachine is instantiated.
330        switch( _codeModel ) {
331        case LTO_CODEGEN_PIC_MODEL_STATIC:
332            TargetMachine::setRelocationModel(Reloc::Static);
333            break;
334        case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
335            TargetMachine::setRelocationModel(Reloc::PIC_);
336            break;
337        case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
338            TargetMachine::setRelocationModel(Reloc::DynamicNoPIC);
339            break;
340        }
341
342        // construct LTModule, hand over ownership of module and target
343        std::string FeatureStr =
344          getFeatureString(_linker.getModule()->getTargetTriple().c_str());
345        _target = march->CtorFn(*mergedModule, FeatureStr.c_str());
346    }
347    return false;
348}
349
350void LTOCodeGenerator::applyScopeRestrictions()
351{
352    if ( !_scopeRestrictionsDone ) {
353        Module* mergedModule = _linker.getModule();
354
355        // Start off with a verification pass.
356        PassManager passes;
357        passes.add(createVerifierPass());
358
359        // mark which symbols can not be internalized
360        if ( !_mustPreserveSymbols.empty() ) {
361            Mangler mangler(*mergedModule,
362                                _target->getTargetAsmInfo()->getGlobalPrefix());
363            std::vector<const char*> mustPreserveList;
364            for (Module::iterator f = mergedModule->begin(),
365                                        e = mergedModule->end(); f != e; ++f) {
366                if ( !f->isDeclaration()
367                  && _mustPreserveSymbols.count(mangler.getValueName(f)) )
368                    mustPreserveList.push_back(::strdup(f->getName().c_str()));
369            }
370            for (Module::global_iterator v = mergedModule->global_begin(),
371                                 e = mergedModule->global_end(); v !=  e; ++v) {
372                if ( !v->isDeclaration()
373                  && _mustPreserveSymbols.count(mangler.getValueName(v)) )
374                    mustPreserveList.push_back(::strdup(v->getName().c_str()));
375            }
376            passes.add(createInternalizePass(mustPreserveList));
377        }
378        // apply scope restrictions
379        passes.run(*mergedModule);
380
381        _scopeRestrictionsDone = true;
382    }
383}
384
385/// Optimize merged modules using various IPO passes
386bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
387                                            std::string& errMsg)
388{
389    if (  this->determineTarget(errMsg) )
390        return true;
391
392    // mark which symbols can not be internalized
393    this->applyScopeRestrictions();
394
395    Module* mergedModule = _linker.getModule();
396
397     // If target supports exception handling then enable it now.
398    if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
399        llvm::ExceptionHandling = true;
400
401    // if options were requested, set them
402    if ( !_codegenOptions.empty() )
403        cl::ParseCommandLineOptions(_codegenOptions.size(),
404                                                (char**)&_codegenOptions[0]);
405
406    // Instantiate the pass manager to organize the passes.
407    PassManager passes;
408
409    // Start off with a verification pass.
410    passes.add(createVerifierPass());
411
412    // Add an appropriate TargetData instance for this module...
413    passes.add(new TargetData(*_target->getTargetData()));
414
415    createStandardLTOPasses(&passes, /*Internalize=*/ false, !DisableInline,
416                            /*VerifyEach=*/ false);
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,
430                                         CodeGenOpt::Aggressive)) {
431        case FileModel::MachOFile:
432            mce = AddMachOWriter(*codeGenPasses, out, *_target);
433            break;
434        case FileModel::ElfFile:
435            mce = AddELFWriter(*codeGenPasses, out, *_target);
436            break;
437        case FileModel::AsmFile:
438            break;
439        case FileModel::Error:
440        case FileModel::None:
441            errMsg = "target file type not supported";
442            return true;
443    }
444
445    if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce,
446                                           CodeGenOpt::Aggressive)) {
447        errMsg = "target does not support generation of this file type";
448        return true;
449    }
450
451    // Run our queue of passes all at once now, efficiently.
452    passes.run(*mergedModule);
453
454    // Run the code generator, and write assembly file
455    codeGenPasses->doInitialization();
456
457    for (Module::iterator
458           it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
459      if (!it->isDeclaration())
460        codeGenPasses->run(*it);
461
462    codeGenPasses->doFinalization();
463    return false; // success
464}
465
466
467/// Optimize merged modules using various IPO passes
468void LTOCodeGenerator::setCodeGenDebugOptions(const char* options)
469{
470    std::string ops(options);
471    for (std::string o = getToken(ops); !o.empty(); o = getToken(ops)) {
472        // ParseCommandLineOptions() expects argv[0] to be program name.
473        // Lazily add that.
474        if ( _codegenOptions.empty() )
475            _codegenOptions.push_back("libLTO");
476        _codegenOptions.push_back(strdup(o.c_str()));
477    }
478}
479