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