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