| #ifndef _SLANG_COMPILER_SLANG_HPP |
| # define _SLANG_COMPILER_SLANG_HPP |
| |
| #include "slang_backend.hpp" |
| #include "slang_rs_context.hpp" |
| #include "slang_rs_backend.hpp" |
| #include "slang_pragma_recorder.hpp" |
| #include "slang_diagnostic_buffer.hpp" |
| |
| #include <cstdio> |
| #include <string> |
| |
| #include "llvm/Support/raw_ostream.h" /* for class llvm::raw_ostream */ |
| |
| #include "llvm/ADT/OwningPtr.h" /* for class llvm::OwningPtr */ |
| #include "llvm/ADT/StringRef.h" /* for class llvm::StringRef */ |
| |
| #include "clang/AST/ASTConsumer.h" /* for class clang::ASTConsumer */ |
| #include "clang/AST/ASTContext.h" /* for class clang::ASTContext */ |
| |
| #include "clang/Lex/Preprocessor.h" /* for class clang::Preprocessor */ |
| #include "clang/Lex/HeaderSearch.h" /* for class clang::HeaderSearch */ |
| |
| #include "clang/Basic/Diagnostic.h" /* for class clang::Diagnostic, class clang::DiagnosticClient, class clang::DiagnosticInfo */ |
| #include "clang/Basic/FileManager.h" /* for class clang::FileManager and class clang::FileEntry */ |
| #include "clang/Basic/TargetOptions.h" /* for class clang::TargetOptions */ |
| |
| namespace llvm { |
| |
| class Twine; |
| class TargetInfo; |
| |
| } /* namespace llvm */ |
| |
| namespace clang { |
| |
| class LangOptions; |
| class CodeGenOptions; |
| |
| } /* namespace clang */ |
| |
| namespace slang { |
| |
| using namespace clang; |
| |
| class Slang { |
| static LangOptions LangOpts; |
| static CodeGenOptions CodeGenOpts; |
| |
| static bool GlobalInitialized; |
| |
| static void GlobalInitialization(); |
| |
| static void LLVMErrorHandler(void *UserData, const std::string &Message); |
| |
| private: |
| PragmaList mPragmas; |
| |
| /* The diagnostics engine instance (for status reporting during compilation) */ |
| llvm::OwningPtr<Diagnostic> mDiagnostics; |
| |
| llvm::OwningPtr<DiagnosticBuffer> mDiagClient; |
| inline void createDiagnostic() { |
| mDiagClient.reset(new DiagnosticBuffer()); |
| mDiagnostics.reset(new Diagnostic(mDiagClient.get())); |
| bool optionNotFound = mDiagnostics->setDiagnosticGroupMapping("implicit-function-declaration", clang::diag::MAP_ERROR); |
| assert(!optionNotFound && "Unable find option group implicit-function-declaration"); |
| return; |
| } |
| |
| /* The target being compiled for */ |
| TargetOptions mTargetOpts; |
| llvm::OwningPtr<TargetInfo> mTarget; |
| void createTarget(const char* Triple, const char* CPU, const char** Features); |
| |
| /**** Below is for parsing ****/ |
| |
| /* The file manager (for prepocessor doing the job such as header file search) */ |
| llvm::OwningPtr<FileManager> mFileMgr; |
| inline void createFileManager() { mFileMgr.reset(new FileManager()); return; } |
| |
| /* The source manager (responsible for the source code handling) */ |
| llvm::OwningPtr<SourceManager> mSourceMgr; /* The source manager */ |
| inline void createSourceManager() { mSourceMgr.reset(new SourceManager(*mDiagnostics)); return; } |
| |
| /* The preprocessor (source code preprocessor) */ |
| llvm::OwningPtr<Preprocessor> mPP; |
| inline void createPreprocessor() { |
| HeaderSearch* HeaderInfo = new HeaderSearch(*mFileMgr); /* Default only search header file in current dir */ |
| mPP.reset(new Preprocessor( *mDiagnostics, |
| LangOpts, |
| *mTarget, |
| *mSourceMgr, |
| *HeaderInfo, |
| NULL, |
| true /* OwnsHeaderSearch */)); |
| /* Initialize the prepocessor */ |
| mPragmas.clear(); |
| mPP->AddPragmaHandler(NULL, new PragmaRecorder(mPragmas)); |
| /* ApplyHeaderSearchOptions */ |
| return; |
| } |
| |
| /* The AST context (the context to hold long-lived AST nodes) */ |
| llvm::OwningPtr<ASTContext> mASTContext; |
| inline void createASTContext() { |
| mASTContext.reset(new ASTContext(LangOpts, |
| *mSourceMgr, |
| *mTarget, |
| mPP->getIdentifierTable(), |
| mPP->getSelectorTable(), |
| mPP->getBuiltinInfo())); |
| return; |
| } |
| |
| /* Context for RenderScript */ |
| llvm::OwningPtr<RSContext> mRSContext; |
| inline void createRSContext() { |
| mRSContext.reset(new RSContext(mPP.get(), |
| mASTContext.get(), |
| mTarget.get())); |
| return; |
| } |
| |
| /* The AST consumer, responsible for code generation */ |
| llvm::OwningPtr<Backend> mBackend; |
| inline void createBackend() { |
| mBackend.reset(new Backend(*mDiagnostics, |
| CodeGenOpts, |
| mTargetOpts, |
| mPragmas, |
| mOS.take(), |
| mOutputType, |
| *mSourceMgr, |
| mAllowRSPrefix)); |
| |
| return; |
| } |
| |
| inline void createRSBackend() { |
| mBackend.reset(new RSBackend(mRSContext.get(), |
| *mDiagnostics, |
| CodeGenOpts, |
| mTargetOpts, |
| mPragmas, |
| mOS.take(), |
| mOutputType, |
| *mSourceMgr, |
| mAllowRSPrefix)); |
| |
| return; |
| } |
| |
| /* Input file name */ |
| std::string mInputFileName; |
| std::string mOutputFileName; |
| |
| SlangCompilerOutputTy mOutputType; |
| |
| /* Output stream */ |
| llvm::OwningPtr<llvm::raw_ostream> mOS; |
| |
| bool mAllowRSPrefix; |
| |
| public: |
| static const std::string TargetDescription; |
| |
| static const llvm::Twine PragmaMetadataName; |
| |
| Slang(const char* Triple, const char* CPU, const char** Features); |
| |
| bool setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength); |
| |
| bool setInputSource(llvm::StringRef inputFile); |
| |
| void setOutputType(SlangCompilerOutputTy outputType); |
| |
| inline bool setOutput(FILE* stream) { |
| if(stream == NULL) |
| return false; |
| |
| mOS.reset( new llvm::raw_fd_ostream(fileno(stream), /* shouldClose */false) ); |
| return true; |
| } |
| |
| bool setOutput(const char* outputFile); |
| |
| inline void allowRSPrefix() { |
| mAllowRSPrefix = true; |
| } |
| |
| int compile(); |
| |
| bool reflectToJava(const char* outputPackageName); |
| |
| inline const char* getErrorMessage() { |
| return mDiagClient->str().c_str(); |
| } |
| |
| void getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings); |
| |
| /* Reset the slang compiler state such that it can be reused to compile another file */ |
| inline void reset() { |
| /* Seems there's no way to clear the diagnostics. We just re-create it. */ |
| createDiagnostic(); |
| mOutputType = SlangCompilerOutput_Default; |
| return; |
| } |
| |
| ~Slang(); |
| }; /* class Slang */ |
| |
| } /* namespace slang */ |
| |
| #endif /* _SLANG_COMPILER_SLANG_HPP */ |