Initialize slang and Android.mk.

Change-Id: If74da8e54d45511c8c9bb236bcfeec508f4f2439
diff --git a/slang.hpp b/slang.hpp
new file mode 100644
index 0000000..8be32a6
--- /dev/null
+++ b/slang.hpp
@@ -0,0 +1,202 @@
+#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()));
+        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;
+    }
+
+    /* Context of Slang compiler for RenderScript */
+    llvm::OwningPtr<RSContext> mRSContext;
+    inline void createRSContext() {
+        mRSContext.reset(new RSContext(mPP.get(),
+                                       mTarget.get()));
+        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;
+    }
+
+    /* 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));
+
+        return;
+    }
+
+    inline void createRSBackend() {
+        mBackend.reset(new RSBackend(mRSContext.get(),
+                                     *mDiagnostics,
+                                     CodeGenOpts,
+                                     mTargetOpts,
+                                     mPragmas,
+                                     mOS.take(),
+                                     mOutputType));
+
+        return;
+    }
+
+    /* Input file name */
+    std::string mInputFileName;
+    std::string mOutputFileName;
+
+    SlangCompilerOutputTy mOutputType;
+
+    /* Output stream */
+    llvm::OwningPtr<llvm::raw_ostream> mOS;
+
+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);
+
+    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 */