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