summaryrefslogtreecommitdiff
path: root/tools/lto/LTOCodeGenerator.h
blob: 5dda5d9c3ee643ef7d374687476cbee49635bf7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the LTOCodeGenerator class.
//
//   LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. 
//
//   The Pre-IPO phase compiles source code into bitcode file. The resulting
// bitcode files, along with object files and libraries, will be fed to the
// linker to through the IPO and Post-IPO phases. By using obj-file extension,
// the resulting bitcode file disguises itself as an object file, and therefore
// obviates the need of writing a special set of the make-rules only for LTO
// compilation.
//
//   The IPO phase perform inter-procedural analyses and optimizations, and
// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations
// (SOPT), and intra-procedural target-dependent code generator (CG).
// 
//   As of this writing, we don't separate IPO and the Post-IPO SOPT. They
// are intermingled together, and are driven by a single pass manager (see
// PassManagerBuilder::populateLTOPassManager()).
// 
//   The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. 
// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator"
// with the machine specific code generator.
//
//===----------------------------------------------------------------------===//

#ifndef LTO_CODE_GENERATOR_H
#define LTO_CODE_GENERATOR_H

#include "llvm-c/lto.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Linker.h"
#include <string>
#include <vector>
#include "LTOPartition.h"

namespace llvm {
  class LLVMContext;
  class GlobalValue;
  class Mangler;
  class MemoryBuffer;
  class TargetMachine;
  class raw_ostream;
}

//===----------------------------------------------------------------------===//
/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t
/// type.
///
struct LTOCodeGenerator {
  static const char *getVersionString();

  LTOCodeGenerator();
  ~LTOCodeGenerator();

  // Merge given module, return true on success.
  bool addModule(struct LTOModule*, std::string &errMsg);

  void setDebugInfo(lto_debug_model);
  void setCodePICModel(lto_codegen_model);

  void setCpu(const char* mCpu) { _mCpu = mCpu; }

  void addMustPreserveSymbol(const char* sym) {
    _mustPreserveSymbols[sym] = 1;
  }

  // To pass options to the driver and optimization passes. These options are
  // not necessarily for debugging purpose (The function name is misleading).
  // This function should be called before LTOCodeGenerator::compilexxx(),
  // and LTOCodeGenerator::writeMergedModules().
  //
  void setCodeGenDebugOptions(const char *opts);

  // Write the merged module to the file specified by the given path.
  // Return true on success.
  bool writeMergedModules(const char *path, std::string &errMsg);

  // Compile the merged module into a *single* object file; the path to object
  // file is returned to the caller via argument "name". Return true on
  // success.
  //
  // NOTE that it is up to the linker to remove the intermediate object file.
  //  Do not try to remove the object file in LTOCodeGenerator's destructor
  //  as we don't who (LTOCodeGenerator or the obj file) will last longer.
  // 
  bool compile_to_file(const char **name, std::string &errMsg);

  // As with compile_to_file(), this function compiles the merged module into
  // single object file. Instead of returning the object-file-path to the caller
  // (linker), it brings the object to a buffer, and return the buffer to the
  // caller. This function should delete intermediate object file once its content
  // is brought to memory. Return NULL is the compilation was not successful. 
  //
  const void *compile(size_t *length, std::string &errMsg);

  // Return the paths of the intermediate files that linker needs to delete
  // before it exits. The paths are delimited by a single '\0', and the last
  // path is ended by double '\0's. The file could be a directory. In that
  // case, the entire directory should be erased recusively. This function
  // must be called after the compilexxx() is successfuly called, because
  // only after that moment, compiler is aware which files need to be removed.
  // If calling compilexxx() is not successful, it is up to compiler to clean
  // up all the intermediate files generated during the compilation process.
  //
  const char *getFilesNeedToRemove();

private:
  void initializeLTOPasses();
  bool determineTarget(std::string &errMsg);
  void parseOptions();
  bool prepareBeforeCompile(std::string &ErrMsg);

  void performIPO(bool PerformPartition, std::string &ErrMsg);
  bool performPostIPO(std::string &ErrMsg, bool MergeObjs = false,
                      const char **MergObjPath = 0);
  bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg);

  void applyScopeRestrictions();
  void applyRestriction(llvm::GlobalValue &GV,
                        std::vector<const char*> &mustPreserveList,
                        llvm::SmallPtrSet<llvm::GlobalValue*, 8> &asmUsed,
                        llvm::Mangler &mangler);
  

  typedef llvm::StringMap<uint8_t> StringSet;

  llvm::LLVMContext&          _context;
  llvm::Linker                _linker;
  llvm::TargetMachine*        _target;
  bool                        _emitDwarfDebugInfo;
  bool                        _scopeRestrictionsDone;
  lto_codegen_model           _codeModel;
  StringSet                   _mustPreserveSymbols;
  StringSet                   _asmUndefinedRefs;
  llvm::MemoryBuffer*         _nativeObjectFile;
  std::vector<char*>          _codegenOptions;
  std::string                 _mCpu;
  std::string                 _nativeObjectPath;

  // To manage the partitions. If partition is not enabled, the whole merged
  // module is considered as a single degenerated partition, and the "manager"
  // is still active.
  lto::IPOPartMgr PartitionMgr;

  // To manage the intermediate files during the compilations.
  lto::IPOFileMgr FileMgr;

  // Sometimes we need to return a vector of strings in a "C" way (to work with
  // the C-APIs). We encode such C-thinking string vector by concatenating all
  // strings tegother with a single '\0' as the delimitor, the last string ended
  // by double '\0's.
  SmallVector<char, 4> ConcatStrings;

  // Make sure command line is parsed only once. It would otherwise complain
  // and quite prematurely.
  bool OptionsParsed;
};

#endif // LTO_CODE_GENERATOR_H