1/*
2 * Copyright 2010, 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 _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  // NOLINT
18#define _FRAMEWORKS_COMPILE_SLANG_SLANG_H_
19
20#include <cstdio>
21#include <string>
22#include <vector>
23
24#include "clang/Basic/TargetOptions.h"
25#include "clang/Lex/ModuleLoader.h"
26
27#include "llvm/ADT/IntrusiveRefCntPtr.h"
28#include "llvm/ADT/OwningPtr.h"
29#include "llvm/ADT/StringRef.h"
30
31#include "llvm/Target/TargetMachine.h"
32
33#include "slang_diagnostic_buffer.h"
34#include "slang_pragma_recorder.h"
35
36namespace llvm {
37  class tool_output_file;
38}
39
40namespace clang {
41  class ASTConsumer;
42  class ASTContext;
43  class Backend;
44  class CodeGenOptions;
45  class Diagnostic;
46  class DiagnosticsEngine;
47  class FileManager;
48  class FileSystemOptions;
49  class LangOptions;
50  class Preprocessor;
51  class SourceManager;
52  class TargetInfo;
53  class TargetOptions;
54}  // namespace clang
55
56namespace slang {
57
58class Slang : public clang::ModuleLoader {
59  static clang::LangOptions LangOpts;
60  static clang::CodeGenOptions CodeGenOpts;
61
62  static bool GlobalInitialized;
63
64  static void LLVMErrorHandler(void *UserData, const std::string &Message);
65
66 public:
67  enum OutputType {
68    OT_Dependency,
69    OT_Assembly,
70    OT_LLVMAssembly,
71    OT_Bitcode,
72    OT_Nothing,
73    OT_Object,
74
75    OT_Default = OT_Bitcode
76  };
77
78 private:
79  bool mInitialized;
80
81  // Diagnostics Mediator (An interface for both Producer and Consumer)
82  llvm::OwningPtr<clang::Diagnostic> mDiag;
83
84  // Diagnostics Engine (Producer and Diagnostics Reporter)
85  clang::DiagnosticsEngine *mDiagEngine;
86
87  // Diagnostics Consumer
88  // NOTE: The ownership is taken by mDiagEngine after creation.
89  DiagnosticBuffer *mDiagClient;
90
91  // The target being compiled for
92  clang::TargetOptions mTargetOpts;
93  llvm::OwningPtr<clang::TargetInfo> mTarget;
94  void createTarget(std::string const &Triple, std::string const &CPU,
95                    std::vector<std::string> const &Features);
96
97
98  // File manager (for prepocessor doing the job such as header file search)
99  llvm::OwningPtr<clang::FileManager> mFileMgr;
100  llvm::OwningPtr<clang::FileSystemOptions> mFileSysOpt;
101  void createFileManager();
102
103
104  // Source manager (responsible for the source code handling)
105  llvm::OwningPtr<clang::SourceManager> mSourceMgr;
106  void createSourceManager();
107
108
109  // Preprocessor (source code preprocessor)
110  llvm::OwningPtr<clang::Preprocessor> mPP;
111  void createPreprocessor();
112
113
114  // AST context (the context to hold long-lived AST nodes)
115  llvm::OwningPtr<clang::ASTContext> mASTContext;
116  void createASTContext();
117
118
119  // AST consumer, responsible for code generation
120  llvm::OwningPtr<clang::ASTConsumer> mBackend;
121
122
123  // File names
124  std::string mInputFileName;
125  std::string mOutputFileName;
126
127  std::string mDepOutputFileName;
128  std::string mDepTargetBCFileName;
129  std::vector<std::string> mAdditionalDepTargets;
130  std::vector<std::string> mGeneratedFileNames;
131
132  OutputType mOT;
133
134  // Output stream
135  llvm::OwningPtr<llvm::tool_output_file> mOS;
136
137  // Dependency output stream
138  llvm::OwningPtr<llvm::tool_output_file> mDOS;
139
140  std::vector<std::string> mIncludePaths;
141
142 protected:
143  PragmaList mPragmas;
144
145  clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
146  clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
147  clang::FileManager &getFileManager() { return *mFileMgr; }
148  clang::SourceManager &getSourceManager() { return *mSourceMgr; }
149  clang::Preprocessor &getPreprocessor() { return *mPP; }
150  clang::ASTContext &getASTContext() { return *mASTContext; }
151
152  inline clang::TargetOptions const &getTargetOptions() const
153    { return mTargetOpts; }
154
155  virtual void initDiagnostic() {}
156  virtual void initPreprocessor() {}
157  virtual void initASTContext() {}
158
159  virtual clang::ASTConsumer *
160    createBackend(const clang::CodeGenOptions& CodeGenOpts,
161                  llvm::raw_ostream *OS,
162                  OutputType OT);
163
164 public:
165  static const llvm::StringRef PragmaMetadataName;
166
167  static void GlobalInitialization();
168
169  Slang();
170
171  void init(const std::string &Triple, const std::string &CPU,
172            const std::vector<std::string> &Features,
173            clang::DiagnosticsEngine *DiagEngine,
174            DiagnosticBuffer *DiagClient);
175
176  virtual clang::Module *loadModule(clang::SourceLocation ImportLoc,
177                                    clang::ModuleIdPath Path,
178                                    clang::Module::NameVisibilityKind VK,
179                                    bool IsInclusionDirective);
180
181  bool setInputSource(llvm::StringRef InputFile, const char *Text,
182                      size_t TextLength);
183
184  bool setInputSource(llvm::StringRef InputFile);
185
186  std::string const &getInputFileName() const { return mInputFileName; }
187
188  void setIncludePaths(const std::vector<std::string> &IncludePaths) {
189    mIncludePaths = IncludePaths;
190  }
191
192  void setOutputType(OutputType OT) { mOT = OT; }
193
194  bool setOutput(const char *OutputFile);
195
196  std::string const &getOutputFileName() const {
197    return mOutputFileName;
198  }
199
200  bool setDepOutput(const char *OutputFile);
201
202  void setDepTargetBC(const char *TargetBCFile) {
203    mDepTargetBCFileName = TargetBCFile;
204  }
205
206  void setAdditionalDepTargets(
207      std::vector<std::string> const &AdditionalDepTargets) {
208    mAdditionalDepTargets = AdditionalDepTargets;
209  }
210
211  void appendGeneratedFileName(std::string const &GeneratedFileName) {
212    mGeneratedFileNames.push_back(GeneratedFileName);
213  }
214
215  int generateDepFile();
216
217  int compile();
218
219  char const *getErrorMessage() { return mDiagClient->str().c_str(); }
220
221  void setDebugMetadataEmission(bool EmitDebug);
222
223  void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
224
225  // Reset the slang compiler state such that it can be reused to compile
226  // another file
227  virtual void reset();
228
229  virtual ~Slang();
230};
231
232}  // namespace slang
233
234#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
235