1/*
2 * Copyright 2010-2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef BCC_COMPILER_H
18#define BCC_COMPILER_H
19
20namespace llvm {
21
22class raw_ostream;
23class DataLayout;
24class TargetMachine;
25
26namespace legacy {
27class PassManager;
28} // end namespace legacy
29
30using legacy::PassManager;
31
32} // end namespace llvm
33
34namespace bcc {
35
36class CompilerConfig;
37class OutputFile;
38class Script;
39
40//===----------------------------------------------------------------------===//
41// Design of Compiler
42//===----------------------------------------------------------------------===//
43// 1. A compiler instance can be constructed provided an "initial config."
44// 2. A compiler can later be re-configured using config().
45// 3. Once config() is invoked, it'll re-create TargetMachine instance (i.e.,
46//    mTarget) according to the configuration supplied. TargetMachine instance
47//    is *shared* across the different calls to compile() before the next call
48//    to config().
49// 4. Once a compiler instance is created, you can use the compile() service
50//    to compile the file over and over again. Each call uses TargetMachine
51//    instance to construct the compilation passes.
52class Compiler {
53public:
54  enum ErrorCode {
55    kSuccess,
56
57    kInvalidConfigNoTarget,
58    kErrCreateTargetMachine,
59    kErrSwitchTargetMachine,
60    kErrNoTargetMachine,
61    kErrDataLayoutNoMemory,
62    kErrMaterialization,
63    kErrInvalidOutputFileState,
64    kErrPrepareOutput,
65    kPrepareCodeGenPass,
66
67    kErrHookBeforeAddLTOPasses,
68    kErrHookAfterAddLTOPasses,
69    kErrHookAfterExecuteLTOPasses,
70
71    kErrHookBeforeAddCodeGenPasses,
72    kErrHookAfterAddCodeGenPasses,
73    kErrHookBeforeExecuteCodeGenPasses,
74    kErrHookAfterExecuteCodeGenPasses,
75
76    kErrInvalidSource
77  };
78
79  static const char *GetErrorString(enum ErrorCode pErrCode);
80
81private:
82  llvm::TargetMachine *mTarget;
83  // LTO is enabled by default.
84  bool mEnableLTO;
85
86  enum ErrorCode runLTO(Script &pScript);
87  enum ErrorCode runCodeGen(Script &pScript, llvm::raw_ostream &pResult);
88
89public:
90  Compiler();
91  Compiler(const CompilerConfig &pConfig);
92
93  enum ErrorCode config(const CompilerConfig &pConfig);
94
95  // Compile a script and output the result to a LLVM stream.
96  //
97  // @param IRStream If not NULL, the LLVM-IR that is fed to code generation
98  //                 will be written to IRStream.
99  enum ErrorCode compile(Script &pScript, llvm::raw_ostream &pResult,
100                         llvm::raw_ostream *IRStream);
101
102  // Compile a script and output the result to a file.
103  enum ErrorCode compile(Script &pScript, OutputFile &pResult,
104                         llvm::raw_ostream *IRStream = 0);
105
106  const llvm::TargetMachine& getTargetMachine() const
107  { return *mTarget; }
108
109  void enableLTO(bool pEnable = true)
110  { mEnableLTO = pEnable; }
111
112  virtual ~Compiler();
113
114protected:
115  //===--------------------------------------------------------------------===//
116  // Plugin callbacks for sub-class.
117  //===--------------------------------------------------------------------===//
118  // Called before adding first pass to code-generation passes.
119  virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
120  { return true; }
121
122  // Called after adding last pass to code-generation passes.
123  virtual bool afterAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
124  { return true; }
125
126  // Called before executing code-generation passes.
127  virtual bool beforeExecuteLTOPasses(Script &pScript,
128                                          llvm::PassManager &pPM)
129  { return true; }
130
131  // Called after executing code-generation passes.
132  virtual bool afterExecuteLTOPasses(Script &pScript)
133  { return true; }
134
135  // Called before adding first pass to code-generation passes.
136  virtual bool beforeAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
137  { return true; }
138
139  // Called after adding last pass to code-generation passes.
140  virtual bool afterAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
141  { return true; }
142
143  // Called before executing code-generation passes.
144  virtual bool beforeExecuteCodeGenPasses(Script &pScript,
145                                          llvm::PassManager &pPM)
146  { return true; }
147
148  // Called after executing code-generation passes.
149  virtual bool afterExecuteCodeGenPasses(Script &pScript)
150  { return true; }
151};
152
153} // end namespace bcc
154
155#endif // BCC_COMPILER_H
156