slang.h revision 6315f76e3cc6ff2d012d1183a0b030d4ff0dc808
1#ifndef _SLANG_COMPILER_SLANG_H
2#define _SLANG_COMPILER_SLANG_H
3
4#include <cstdio>
5#include <string>
6#include <vector>
7
8#include "llvm/Support/raw_ostream.h"
9
10#include "llvm/ADT/OwningPtr.h"
11#include "llvm/ADT/StringRef.h"
12
13#include "clang/AST/ASTConsumer.h"
14#include "clang/AST/ASTContext.h"
15
16#include "clang/Lex/Preprocessor.h"
17#include "clang/Lex/HeaderSearch.h"
18
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/FileManager.h"
21#include "clang/Basic/TargetOptions.h"
22
23#include "clang/Sema/SemaDiagnostic.h"
24
25#include "slang_backend.h"
26#include "slang_rs_context.h"
27#include "slang_rs_backend.h"
28#include "slang_pragma_recorder.h"
29#include "slang_diagnostic_buffer.h"
30
31namespace llvm {
32  class TargetInfo;
33}
34
35namespace clang {
36  class LangOptions;
37  class CodeGenOptions;
38  class TargetOptions;
39}
40
41namespace slang {
42
43class Slang {
44  static clang::LangOptions LangOpts;
45  static clang::CodeGenOptions CodeGenOpts;
46
47  static bool GlobalInitialized;
48
49  static void GlobalInitialization();
50
51  static void LLVMErrorHandler(void *UserData, const std::string &Message);
52
53 private:
54  PragmaList mPragmas;
55
56  // The diagnostics engine instance (for status reporting during compilation)
57  llvm::OwningPtr<clang::Diagnostic> mDiagnostics;
58
59  llvm::OwningPtr<DiagnosticBuffer> mDiagClient;
60  inline void createDiagnostic() {
61    mDiagClient.reset(new DiagnosticBuffer());
62    mDiagnostics.reset(new clang::Diagnostic(mDiagClient.get()));
63    if (!mDiagnostics->setDiagnosticGroupMapping(
64            "implicit-function-declaration",
65            clang::diag::MAP_ERROR))
66      assert("Unable find option group implicit-function-declaration");
67    mDiagnostics->setDiagnosticMapping(
68        clang::diag::ext_typecheck_convert_discards_qualifiers,
69        clang::diag::MAP_ERROR);
70    return;
71  }
72
73  // The target being compiled for
74  clang::TargetOptions mTargetOpts;
75  llvm::OwningPtr<clang::TargetInfo> mTarget;
76  void createTarget(const char *Triple, const char *CPU, const char **Features);
77
78  // Below is for parsing
79
80  // The file manager (for prepocessor doing the job such as header file search)
81  llvm::OwningPtr<clang::FileManager> mFileMgr;
82  inline void createFileManager() {
83    mFileMgr.reset(new clang::FileManager());
84    return;
85  }
86
87  // The source manager (responsible for the source code handling)
88  llvm::OwningPtr<clang::SourceManager> mSourceMgr;
89  inline void createSourceManager() {
90    mSourceMgr.reset(new clang::SourceManager(*mDiagnostics));
91    return;
92  }
93
94  // The preprocessor (source code preprocessor)
95  llvm::OwningPtr<clang::Preprocessor> mPP;
96  void createPreprocessor();
97
98  // The AST context (the context to hold long-lived AST nodes)
99  llvm::OwningPtr<clang::ASTContext> mASTContext;
100  inline void createASTContext() {
101    mASTContext.reset(new clang::ASTContext(LangOpts,
102                                            *mSourceMgr,
103                                            *mTarget,
104                                            mPP->getIdentifierTable(),
105                                            mPP->getSelectorTable(),
106                                            mPP->getBuiltinInfo(),
107                                            /* size_reserve */0));
108    return;
109  }
110
111  // Context for RenderScript
112  llvm::OwningPtr<RSContext> mRSContext;
113  inline void createRSContext() {
114    mRSContext.reset(new RSContext(mPP.get(),
115                                   mASTContext.get(),
116                                   mTarget.get()));
117    return;
118  }
119
120  // The AST consumer, responsible for code generation
121  llvm::OwningPtr<Backend> mBackend;
122  inline void createBackend() {
123    mBackend.reset(new Backend(*mDiagnostics,
124                               CodeGenOpts,
125                               mTargetOpts,
126                               mPragmas,
127                               mOS.take(),
128                               mOutputType,
129                               *mSourceMgr,
130                               mAllowRSPrefix));
131
132    return;
133  }
134
135  inline void createRSBackend() {
136    mBackend.reset(new RSBackend(mRSContext.get(),
137                                 *mDiagnostics,
138                                 CodeGenOpts,
139                                 mTargetOpts,
140                                 mPragmas,
141                                 mOS.take(),
142                                 mOutputType,
143                                 *mSourceMgr,
144                                 mAllowRSPrefix));
145
146    return;
147  }
148
149  // Input file name
150  std::string mInputFileName;
151  std::string mOutputFileName;
152
153  SlangCompilerOutputTy mOutputType;
154
155  // Output stream
156  llvm::OwningPtr<llvm::raw_ostream> mOS;
157
158  bool mAllowRSPrefix;
159
160  std::vector<std::string> mIncludePaths;
161
162 public:
163  static const std::string TargetDescription;
164
165  static const llvm::StringRef PragmaMetadataName;
166
167  Slang(const char *Triple, const char *CPU, const char **Features);
168
169  bool setInputSource(llvm::StringRef inputFile, const char *text,
170                      size_t textLength);
171
172  bool setInputSource(llvm::StringRef inputFile);
173
174  void addIncludePath(const char *path);
175
176  void setOutputType(SlangCompilerOutputTy outputType);
177
178  inline bool setOutput(FILE *stream) {
179    if (stream == NULL)
180      return false;
181
182    mOS.reset(new llvm::raw_fd_ostream(fileno(stream),
183                                       /* shouldClose */false));
184    return true;
185  }
186
187  bool setOutput(const char *outputFile);
188
189  inline void allowRSPrefix() {
190    mAllowRSPrefix = true;
191  }
192
193  int compile();
194
195  // The package name that's really applied will be filled in realPackageName.
196  // bSize is the buffer realPackageName size.
197  bool reflectToJava(const char *outputPackageName,
198                     char *realPackageName, int bSize);
199  bool reflectToJavaPath(const char *outputPathName);
200
201  inline const char *getErrorMessage() {
202    return mDiagClient->str().c_str();
203  }
204
205  void getPragmas(size_t *actualStringCount, size_t maxStringCount,
206                  char **strings);
207
208  const char *exportFuncs();
209
210  // Reset the slang compiler state such that it can be reused to compile
211  // another file
212  inline void reset() {
213    // Seems there's no way to clear the diagnostics. We just re-create it.
214    createDiagnostic();
215    mOutputType = SlangCompilerOutput_Default;
216    return;
217  }
218
219  ~Slang();
220};
221}
222
223#endif  // _SLANG_COMPILER_SLANG_H
224