Merge Slang with SlangRS, Backend with RSBackend.

Change-Id: I4721f92c10ec14a886923778595289f96d3a8de5
(cherry picked from commit 8024ed54c23c08534434da14d3be99c3efcc5754)
diff --git a/Android.mk b/Android.mk
index 72ab0a4..5e2afb5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -144,12 +144,10 @@
 LOCAL_SRC_FILES :=	\
 	llvm-rs-cc.cpp	\
 	rs_cc_options.cpp \
-	slang_rs.cpp	\
 	slang_rs_ast_replace.cpp	\
 	slang_rs_check_ast.cpp	\
 	slang_rs_context.cpp	\
 	slang_rs_pragma_handler.cpp	\
-	slang_rs_backend.cpp	\
 	slang_rs_exportable.cpp	\
 	slang_rs_export_type.cpp	\
 	slang_rs_export_element.cpp	\
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index 4730710..6b879e0 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -35,7 +35,6 @@
 #include "slang.h"
 #include "slang_assert.h"
 #include "slang_diagnostic_buffer.h"
-#include "slang_rs.h"
 #include "slang_rs_reflect_utils.h"
 
 #include <list>
@@ -181,7 +180,7 @@
     IOFiles->push_back(std::make_pair(InputFile, OutputFile));
   }
 
-  std::unique_ptr<slang::SlangRS> Compiler(new slang::SlangRS());
+  std::unique_ptr<slang::Slang> Compiler(new slang::Slang());
   Compiler->init(Opts.mBitWidth, DiagEngine, DiagClient);
   int CompileFailed = !Compiler->compile(*IOFiles, *IOFiles32, DepFiles, Opts);
   // We suppress warnings (via reset) if we are doing a second compilation.
diff --git a/slang.cpp b/slang.cpp
index 731e671..fd51e7a 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -18,7 +18,11 @@
 
 #include <stdlib.h>
 
+#include <cstring>
+#include <list>
+#include <sstream>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "clang/AST/ASTConsumer.h"
@@ -29,6 +33,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/FileSystemOptions.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
@@ -47,6 +52,8 @@
 
 #include "clang/Parse/ParseAST.h"
 
+#include "clang/Sema/SemaDiagnostic.h"
+
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 
 #include "llvm/Bitcode/ReaderWriter.h"
@@ -66,9 +73,19 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
 
+#include "os_sep.h"
+#include "rs_cc_options.h"
 #include "slang_assert.h"
 #include "slang_backend.h"
 
+#include "slang_backend.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_type.h"
+
+#include "slang_rs_reflection.h"
+#include "slang_rs_reflection_cpp.h"
+
+
 namespace {
 
 static const char *kRSTriple32 = "armv7-none-linux-gnueabi";
@@ -78,6 +95,32 @@
 
 namespace slang {
 
+
+#define FS_SUFFIX  "fs"
+
+#define RS_HEADER_SUFFIX  "rsh"
+
+/* RS_HEADER_ENTRY(name) */
+#define ENUM_RS_HEADER()  \
+  RS_HEADER_ENTRY(rs_allocation_data) \
+  RS_HEADER_ENTRY(rs_atomic) \
+  RS_HEADER_ENTRY(rs_convert) \
+  RS_HEADER_ENTRY(rs_core) \
+  RS_HEADER_ENTRY(rs_debug) \
+  RS_HEADER_ENTRY(rs_for_each) \
+  RS_HEADER_ENTRY(rs_graphics) \
+  RS_HEADER_ENTRY(rs_graphics_types) \
+  RS_HEADER_ENTRY(rs_io) \
+  RS_HEADER_ENTRY(rs_math) \
+  RS_HEADER_ENTRY(rs_matrix) \
+  RS_HEADER_ENTRY(rs_object_info) \
+  RS_HEADER_ENTRY(rs_object_types) \
+  RS_HEADER_ENTRY(rs_quaternion) \
+  RS_HEADER_ENTRY(rs_time) \
+  RS_HEADER_ENTRY(rs_value_types) \
+  RS_HEADER_ENTRY(rs_vector_math) \
+
+
 bool Slang::GlobalInitialized = false;
 
 // Language option (define the language feature for compiler such as C99)
@@ -216,27 +259,38 @@
 }
 
 void Slang::createASTContext() {
-  mASTContext.reset(new clang::ASTContext(LangOpts,
-                                          *mSourceMgr,
-                                          mPP->getIdentifierTable(),
-                                          mPP->getSelectorTable(),
-                                          mPP->getBuiltinInfo()));
+  mASTContext.reset(
+      new clang::ASTContext(LangOpts, *mSourceMgr, mPP->getIdentifierTable(),
+                            mPP->getSelectorTable(), mPP->getBuiltinInfo()));
   mASTContext->InitBuiltinTypes(getTargetInfo());
   initASTContext();
 }
 
 clang::ASTConsumer *
-Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
-                     llvm::raw_ostream *OS, OutputType OT) {
-  return new Backend(mDiagEngine, CodeGenOpts, getTargetOptions(),
-                     &mPragmas, OS, OT);
+Slang::createBackend(const clang::CodeGenOptions &CodeGenOpts,
+                     llvm::raw_ostream *OS, Slang::OutputType OT) {
+  return new Backend(mRSContext, &getDiagnostics(), CodeGenOpts,
+                     getTargetOptions(), &mPragmas, OS, OT, getSourceManager(),
+                     mAllowRSPrefix, mIsFilterscript);
 }
 
-Slang::Slang() : mInitialized(false), mDiagClient(nullptr),
-  mTargetOpts(new clang::TargetOptions()), mOT(OT_Default) {
+Slang::Slang()
+    : mInitialized(false), mDiagClient(nullptr),
+      mTargetOpts(new clang::TargetOptions()), mOT(OT_Default),
+      mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
+      mVerbose(false), mIsFilterscript(false) {
   GlobalInitialization();
 }
 
+Slang::~Slang() {
+  delete mRSContext;
+  for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
+                                           E = ReflectedDefinitions.end();
+       I != E; I++) {
+    delete I->getValue().first;
+  }
+}
+
 void Slang::init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
                  DiagnosticBuffer *DiagClient) {
   if (mInitialized)
@@ -264,26 +318,6 @@
   return clang::ModuleLoadResult();
 }
 
-bool Slang::setInputSource(llvm::StringRef InputFile,
-                           const char *Text,
-                           size_t TextLength) {
-  mInputFileName = InputFile.str();
-
-  // Reset the ID tables if we are reusing the SourceManager
-  mSourceMgr->clearIDTables();
-
-  // Load the source
-  std::unique_ptr<llvm::MemoryBuffer> SB =
-      llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
-  mSourceMgr->setMainFileID(mSourceMgr->createFileID(std::move(SB)));
-
-  if (mSourceMgr->getMainFileID().isInvalid()) {
-    mDiagEngine->Report(clang::diag::err_fe_error_reading) << InputFile;
-    return false;
-  }
-  return true;
-}
-
 bool Slang::setInputSource(llvm::StringRef InputFile) {
   mInputFileName = InputFile.str();
 
@@ -441,6 +475,10 @@
 }
 
 void Slang::reset(bool SuppressWarnings) {
+  delete mRSContext;
+  mRSContext = nullptr;
+  mGeneratedFileNames.clear();
+
   // Always print diagnostics if we had an error occur, but don't print
   // warnings if we suppressed them (i.e. we are doing the 64-bit compile after
   // an existing 32-bit compile).
@@ -459,7 +497,358 @@
   llvm::remove_fatal_error_handler();
 }
 
-Slang::~Slang() {
+// Returns true if \p Filename ends in ".fs".
+bool Slang::isFilterscript(const char *Filename) {
+  const char *c = strrchr(Filename, '.');
+  if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool Slang::generateJavaBitcodeAccessor(const std::string &OutputPathBase,
+                                          const std::string &PackageName,
+                                          const std::string *LicenseNote) {
+  RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;
+
+  BCAccessorContext.rsFileName = getInputFileName().c_str();
+  BCAccessorContext.bc32FileName = getOutput32FileName().c_str();
+  BCAccessorContext.bc64FileName = getOutputFileName().c_str();
+  BCAccessorContext.reflectPath = OutputPathBase.c_str();
+  BCAccessorContext.packageName = PackageName.c_str();
+  BCAccessorContext.licenseNote = LicenseNote;
+  BCAccessorContext.bcStorage = BCST_JAVA_CODE;   // Must be BCST_JAVA_CODE
+  BCAccessorContext.verbose = false;
+
+  return RSSlangReflectUtils::GenerateJavaBitCodeAccessor(BCAccessorContext);
+}
+
+bool Slang::checkODR(const char *CurInputFile) {
+  for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
+          E = mRSContext->exportable_end();
+       I != E;
+       I++) {
+    RSExportable *RSE = *I;
+    if (RSE->getKind() != RSExportable::EX_TYPE)
+      continue;
+
+    RSExportType *ET = static_cast<RSExportType *>(RSE);
+    if (ET->getClass() != RSExportType::ExportClassRecord)
+      continue;
+
+    RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);
+
+    // Artificial record types (create by us not by user in the source) always
+    // conforms the ODR.
+    if (ERT->isArtificial())
+      continue;
+
+    // Key to lookup ERT in ReflectedDefinitions
+    llvm::StringRef RDKey(ERT->getName());
+    ReflectedDefinitionListTy::const_iterator RD =
+        ReflectedDefinitions.find(RDKey);
+
+    if (RD != ReflectedDefinitions.end()) {
+      const RSExportRecordType *Reflected = RD->getValue().first;
+      // There's a record (struct) with the same name reflected before. Enforce
+      // ODR checking - the Reflected must hold *exactly* the same "definition"
+      // as the one defined previously. We say two record types A and B have the
+      // same definition iff:
+      //
+      //  struct A {              struct B {
+      //    Type(a1) a1,            Type(b1) b1,
+      //    Type(a2) a2,            Type(b1) b2,
+      //    ...                     ...
+      //    Type(aN) aN             Type(b3) b3,
+      //  };                      }
+      //  Cond. #1. They have same number of fields, i.e., N = M;
+      //  Cond. #2. for (i := 1 to N)
+      //              Type(ai) = Type(bi) must hold;
+      //  Cond. #3. for (i := 1 to N)
+      //              Name(ai) = Name(bi) must hold;
+      //
+      // where,
+      //  Type(F) = the type of field F and
+      //  Name(F) = the field name.
+
+      bool PassODR = false;
+      // Cond. #1 and Cond. #2
+      if (Reflected->equals(ERT)) {
+        // Cond #3.
+        RSExportRecordType::const_field_iterator AI = Reflected->fields_begin(),
+                                                 BI = ERT->fields_begin();
+
+        for (unsigned i = 0, e = Reflected->getFields().size(); i != e; i++) {
+          if ((*AI)->getName() != (*BI)->getName())
+            break;
+          AI++;
+          BI++;
+        }
+        PassODR = (AI == (Reflected->fields_end()));
+      }
+
+      if (!PassODR) {
+        getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
+                                               << getInputFileName()
+                                               << RD->getValue().second;
+        return false;
+      }
+    } else {
+      llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
+          llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey);
+      ME->setValue(std::make_pair(ERT, CurInputFile));
+
+      if (!ReflectedDefinitions.insert(ME))
+        delete ME;
+
+      // Take the ownership of ERT such that it won't be freed in ~RSContext().
+      ERT->keep();
+    }
+  }
+  return true;
+}
+
+void Slang::initDiagnostic() {
+  clang::DiagnosticsEngine &DiagEngine = getDiagnostics();
+  const auto Flavor = clang::diag::Flavor::WarningOrError;
+
+  if (DiagEngine.setSeverityForGroup(Flavor, "implicit-function-declaration",
+                                     clang::diag::Severity::Error)) {
+    DiagEngine.Report(clang::diag::warn_unknown_diag_option)
+      << /* clang::diag::Flavor::WarningOrError */ 0
+      << "implicit-function-declaration";
+  }
+
+  DiagEngine.setSeverity(
+    clang::diag::ext_typecheck_convert_discards_qualifiers,
+    clang::diag::Severity::Error,
+    clang::SourceLocation());
+
+  mDiagErrorInvalidOutputDepParameter =
+    DiagEngine.getCustomDiagID(
+      clang::DiagnosticsEngine::Error,
+      "invalid parameter for output dependencies files.");
+
+  mDiagErrorODR =
+    DiagEngine.getCustomDiagID(
+      clang::DiagnosticsEngine::Error,
+      "type '%0' in different translation unit (%1 v.s. %2) "
+      "has incompatible type definition");
+
+  mDiagErrorTargetAPIRange =
+    DiagEngine.getCustomDiagID(
+      clang::DiagnosticsEngine::Error,
+      "target API level '%0' is out of range ('%1' - '%2')");
+}
+
+void Slang::initPreprocessor() {
+  clang::Preprocessor &PP = getPreprocessor();
+
+  std::stringstream RSH;
+  RSH << PP.getPredefines();
+  RSH << "#define RS_VERSION " << mTargetAPI << "\n";
+  RSH << "#include \"rs_core." RS_HEADER_SUFFIX "\"\n";
+  PP.setPredefines(RSH.str());
+}
+
+void Slang::initASTContext() {
+  mRSContext = new RSContext(getPreprocessor(),
+                             getASTContext(),
+                             getTargetInfo(),
+                             &mPragmas,
+                             mTargetAPI,
+                             mVerbose);
+}
+
+bool Slang::IsRSHeaderFile(const char *File) {
+#define RS_HEADER_ENTRY(name)  \
+  if (::strcmp(File, #name "." RS_HEADER_SUFFIX) == 0)  \
+    return true;
+ENUM_RS_HEADER()
+#undef RS_HEADER_ENTRY
+  return false;
+}
+
+bool Slang::IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
+                                  const clang::SourceManager &SourceMgr) {
+  clang::FullSourceLoc FSL(Loc, SourceMgr);
+  clang::PresumedLoc PLoc = SourceMgr.getPresumedLoc(FSL);
+
+  const char *Filename = PLoc.getFilename();
+  if (!Filename) {
+    return false;
+  } else {
+    return IsRSHeaderFile(llvm::sys::path::filename(Filename).data());
+  }
+}
+
+bool Slang::compile(
+    const std::list<std::pair<const char*, const char*> > &IOFiles64,
+    const std::list<std::pair<const char*, const char*> > &IOFiles32,
+    const std::list<std::pair<const char*, const char*> > &DepFiles,
+    const RSCCOptions &Opts) {
+  if (IOFiles32.empty())
+    return true;
+
+  if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
+    getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
+    return false;
+  }
+
+  if (Opts.mEmit3264 && (IOFiles64.size() != IOFiles32.size())) {
+    slangAssert(false && "Should have equal number of 32/64-bit files");
+    return false;
+  }
+
+  std::string RealPackageName;
+
+  const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
+             *DepOutputFile;
+  std::list<std::pair<const char*, const char*> >::const_iterator
+      IOFile64Iter = IOFiles64.begin(),
+      IOFile32Iter = IOFiles32.begin(),
+      DepFileIter = DepFiles.begin();
+
+  setIncludePaths(Opts.mIncludePaths);
+  setOutputType(Opts.mOutputType);
+  if (Opts.mEmitDependency) {
+    setAdditionalDepTargets(Opts.mAdditionalDepTargets);
+  }
+
+  setDebugMetadataEmission(Opts.mDebugEmission);
+
+  setOptimizationLevel(Opts.mOptimizationLevel);
+
+  mAllowRSPrefix = Opts.mAllowRSPrefix;
+
+  mTargetAPI = Opts.mTargetAPI;
+  if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
+      (mTargetAPI < SLANG_MINIMUM_TARGET_API ||
+       mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
+    getDiagnostics().Report(mDiagErrorTargetAPIRange) << mTargetAPI
+        << SLANG_MINIMUM_TARGET_API << SLANG_MAXIMUM_TARGET_API;
+    return false;
+  }
+
+  mVerbose = Opts.mVerbose;
+
+  // Skip generation of warnings a second time if we are doing more than just
+  // a single pass over the input file.
+  bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
+
+  bool CompileSecondTimeFor64Bit = Opts.mEmit3264 && Opts.mBitWidth == 64;
+
+  for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
+    InputFile = IOFile64Iter->first;
+    Output64File = IOFile64Iter->second;
+    Output32File = IOFile32Iter->second;
+
+    // We suppress warnings (via reset) if we are doing a second compilation.
+    reset(CompileSecondTimeFor64Bit);
+
+    if (!setInputSource(InputFile))
+      return false;
+
+    if (!setOutput(Output64File))
+      return false;
+
+    setOutput32(Output32File);
+
+    mIsFilterscript = isFilterscript(InputFile);
+
+    if (Slang::compile() > 0)
+      return false;
+
+    if (!Opts.mJavaReflectionPackageName.empty()) {
+      mRSContext->setReflectJavaPackageName(Opts.mJavaReflectionPackageName);
+    }
+    const std::string &RealPackageName =
+        mRSContext->getReflectJavaPackageName();
+
+    bool doReflection = true;
+    if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
+      // Skip reflection on the 32-bit path if we are going to emit it on the
+      // 64-bit path.
+      doReflection = false;
+    }
+    if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {
+
+      if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
+        const std::string &outputFileName = (Opts.mBitWidth == 64) ?
+            getOutputFileName() : getOutput32FileName();
+        RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
+                          getInputFileName(), outputFileName);
+        if (!R.reflect()) {
+            return false;
+        }
+      } else {
+        if (!Opts.mRSPackageName.empty()) {
+          mRSContext->setRSPackageName(Opts.mRSPackageName);
+        }
+
+        RSReflectionJava R(mRSContext, &mGeneratedFileNames,
+                           Opts.mJavaReflectionPathBase, getInputFileName(),
+                           getOutputFileName(),
+                           Opts.mBitcodeStorage == BCST_JAVA_CODE);
+        if (!R.reflect()) {
+          // TODO Is this needed or will the error message have been printed
+          // already? and why not for the C++ case?
+          fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
+                          "(%s)\n",
+                  R.getLastError());
+          return false;
+        }
+
+        for (std::vector<std::string>::const_iterator
+                 I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
+             I != E;
+             I++) {
+          std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
+              Opts.mJavaReflectionPathBase.c_str(),
+              (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
+          appendGeneratedFileName(ReflectedName + ".java");
+        }
+
+        if ((Opts.mOutputType == Slang::OT_Bitcode) &&
+            (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
+            !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
+                                         RealPackageName.c_str(),
+                                         mRSContext->getLicenseNote())) {
+          return false;
+        }
+      }
+    }
+
+    if (Opts.mEmitDependency) {
+      BCOutputFile = DepFileIter->first;
+      DepOutputFile = DepFileIter->second;
+
+      setDepTargetBC(BCOutputFile);
+
+      if (!setDepOutput(DepOutputFile))
+        return false;
+
+      if (SuppressAllWarnings) {
+        getDiagnostics().setSuppressAllDiagnostics(true);
+      }
+      if (generateDepFile() > 0)
+        return false;
+      if (SuppressAllWarnings) {
+        getDiagnostics().setSuppressAllDiagnostics(false);
+      }
+
+      DepFileIter++;
+    }
+
+    if (!checkODR(InputFile))
+      return false;
+
+    IOFile64Iter++;
+    IOFile32Iter++;
+  }
+
+  return true;
 }
 
 }  // namespace slang
diff --git a/slang.h b/slang.h
index 6483c44..2b40adb 100644
--- a/slang.h
+++ b/slang.h
@@ -18,9 +18,16 @@
 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_H_
 
 #include <cstdio>
+#include <list>
 #include <string>
+#include <utility>
 #include <vector>
 
+#include "llvm/ADT/StringMap.h"
+
+#include "slang_rs_reflect_utils.h"
+#include "slang_version.h"
+
 // Terrible workaround for TargetOptions.h not using llvm::RefCountedBase!
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 using llvm::RefCountedBase;
@@ -56,15 +63,11 @@
 
 namespace slang {
 
+class RSCCOptions;
+class RSContext;
+class RSExportRecordType;
+
 class Slang : public clang::ModuleLoader {
-  static clang::LangOptions LangOpts;
-  static clang::CodeGenOptions CodeGenOpts;
-
-  static bool GlobalInitialized;
-
-  static void LLVMErrorHandler(void *UserData, const std::string &Message,
-                               bool GenCrashDialog);
-
  public:
   enum OutputType {
     OT_Dependency,
@@ -78,6 +81,17 @@
   };
 
  private:
+  static clang::LangOptions LangOpts;
+  static clang::CodeGenOptions CodeGenOpts;
+
+  static bool GlobalInitialized;
+
+  static void LLVMErrorHandler(void *UserData, const std::string &Message,
+                               bool GenCrashDialog);
+
+  // Returns true if this is a Filterscript file.
+  static bool isFilterscript(const char *Filename);
+
   bool mInitialized;
 
   // Diagnostics Mediator (An interface for both Producer and Consumer)
@@ -95,32 +109,26 @@
   std::unique_ptr<clang::TargetInfo> mTarget;
   void createTarget(uint32_t BitWidth);
 
-
   // File manager (for prepocessor doing the job such as header file search)
   std::unique_ptr<clang::FileManager> mFileMgr;
   std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
   void createFileManager();
 
-
   // Source manager (responsible for the source code handling)
   std::unique_ptr<clang::SourceManager> mSourceMgr;
   void createSourceManager();
 
-
   // Preprocessor (source code preprocessor)
   std::unique_ptr<clang::Preprocessor> mPP;
   void createPreprocessor();
 
-
   // AST context (the context to hold long-lived AST nodes)
   std::unique_ptr<clang::ASTContext> mASTContext;
   void createASTContext();
 
-
   // AST consumer, responsible for code generation
   std::unique_ptr<clang::ASTConsumer> mBackend;
 
-
   // File names
   std::string mInputFileName;
   std::string mOutputFileName;
@@ -129,7 +137,6 @@
   std::string mDepOutputFileName;
   std::string mDepTargetBCFileName;
   std::vector<std::string> mAdditionalDepTargets;
-  std::vector<std::string> mGeneratedFileNames;
 
   OutputType mOT;
 
@@ -141,9 +148,45 @@
 
   std::vector<std::string> mIncludePaths;
 
- protected:
+  // Context for Renderscript
+  RSContext *mRSContext;
+
+  bool mAllowRSPrefix;
+
+  unsigned int mTargetAPI;
+
+  bool mVerbose;
+
+  bool mIsFilterscript;
+
+  // Custom diagnostic identifiers
+  unsigned mDiagErrorInvalidOutputDepParameter;
+  unsigned mDiagErrorODR;
+  unsigned mDiagErrorTargetAPIRange;
+
+  // Collect generated filenames (without the .java) for dependency generation
+  std::vector<std::string> mGeneratedFileNames;
+
   PragmaList mPragmas;
 
+  // FIXME: Should be std::list<RSExportable *> here. But currently we only
+  //        check ODR on record type.
+  //
+  // ReflectedDefinitions maps record type name to a pair:
+  //  <its RSExportRecordType instance,
+  //   the first file contains this record type definition>
+  typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
+  typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
+  ReflectedDefinitionListTy ReflectedDefinitions;
+
+  bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
+                                   const std::string &PackageName,
+                                   const std::string *LicenseNote);
+
+  // CurInputFile is the pointer to a char array holding the input filename
+  // and is valid before compile() ends.
+  bool checkODR(const char *CurInputFile);
+
   clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
   clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
   clang::FileManager &getFileManager() { return *mFileMgr; }
@@ -154,34 +197,32 @@
   inline clang::TargetOptions const &getTargetOptions() const
     { return *mTargetOpts.get(); }
 
-  virtual void initDiagnostic() {}
-  virtual void initPreprocessor() {}
-  virtual void initASTContext() {}
+  void initDiagnostic();
+  void initPreprocessor();
+  void initASTContext();
 
-  virtual clang::ASTConsumer *
-    createBackend(const clang::CodeGenOptions& CodeGenOpts,
-                  llvm::raw_ostream *OS,
-                  OutputType OT);
+  clang::ASTConsumer *createBackend(const clang::CodeGenOptions &CodeGenOpts,
+                                    llvm::raw_ostream *OS,
+                                    Slang::OutputType OT);
 
  public:
   static const llvm::StringRef PragmaMetadataName;
 
   static void GlobalInitialization();
 
+  static bool IsRSHeaderFile(const char *File);
+  // FIXME: Determine whether a location is in RS header (i.e., one of the RS
+  //        built-in APIs) should only need its names (we need a "list" of RS
+  //        built-in APIs).
+  static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
+                                  const clang::SourceManager &SourceMgr);
+
   Slang();
+  virtual ~Slang();
 
   void init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
             DiagnosticBuffer *DiagClient);
 
-  virtual clang::ModuleLoadResult loadModule(
-      clang::SourceLocation ImportLoc,
-      clang::ModuleIdPath Path,
-      clang::Module::NameVisibilityKind VK,
-      bool IsInclusionDirective);
-
-  bool setInputSource(llvm::StringRef InputFile, const char *Text,
-                      size_t TextLength);
-
   bool setInputSource(llvm::StringRef InputFile);
 
   std::string const &getInputFileName() const { return mInputFileName; }
@@ -235,11 +276,41 @@
 
   // Reset the slang compiler state such that it can be reused to compile
   // another file
-  virtual void reset(bool SuppressWarnings = false);
+  void reset(bool SuppressWarnings = false);
 
-  virtual ~Slang();
+  // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
+  // all given input files are successfully compiled without errors.
+  //
+  // @IOFiles - List of pairs of <input file path, output file path>.
+  //
+  // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
+  //             target>. If @OutputDep is true, this parameter must be given
+  //             with the same number of pairs given in @IOFiles.
+  //
+  // @Opts - Selection of options defined from invoking llvm-rs-cc
+  bool
+  compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
+          const std::list<std::pair<const char *, const char *>> &IOFiles32,
+          const std::list<std::pair<const char *, const char *>> &DepFiles,
+          const RSCCOptions &Opts);
+
+  clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
+                                     clang::ModuleIdPath Path,
+                                     clang::Module::NameVisibilityKind VK,
+                                     bool IsInclusionDirective) override;
+
+  void makeModuleVisible(clang::Module *Mod,
+                         clang::Module::NameVisibilityKind Visibility,
+                         clang::SourceLocation ImportLoc,
+                         bool Complain = false) override {}
+
+  clang::GlobalModuleIndex *
+  loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override {}
+
+  bool lookupMissingImports(llvm::StringRef Name,
+                            clang::SourceLocation TriggerLoc) override {}
 };
 
-}  // namespace slang
+} // namespace slang
 
 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
diff --git a/slang_backend.cpp b/slang_backend.cpp
index 9ed1a88..1a45b41 100644
--- a/slang_backend.cpp
+++ b/slang_backend.cpp
@@ -34,20 +34,28 @@
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 
-#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/StringExtras.h"
 
 #include "llvm/Bitcode/ReaderWriter.h"
 
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
 
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
 
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
-#include "llvm/IR/DataLayout.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -55,6 +63,14 @@
 #include "llvm/MC/SubtargetFeature.h"
 
 #include "slang_assert.h"
+#include "slang.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_foreach.h"
+#include "slang_rs_export_func.h"
+#include "slang_rs_export_type.h"
+#include "slang_rs_export_var.h"
+#include "slang_rs_metadata.h"
+
 #include "strip_unknown_attributes.h"
 #include "BitWriter_2_9/ReaderWriter_2_9.h"
 #include "BitWriter_2_9_func/ReaderWriter_2_9_func.h"
@@ -198,25 +214,23 @@
   return true;
 }
 
-Backend::Backend(clang::DiagnosticsEngine *DiagEngine,
+Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
                  const clang::CodeGenOptions &CodeGenOpts,
-                 const clang::TargetOptions &TargetOpts,
-                 PragmaList *Pragmas,
-                 llvm::raw_ostream *OS,
-                 Slang::OutputType OT)
-    : ASTConsumer(),
-      mTargetOpts(TargetOpts),
-      mpModule(nullptr),
-      mpOS(OS),
-      mOT(OT),
-      mGen(nullptr),
-      mPerFunctionPasses(nullptr),
-      mPerModulePasses(nullptr),
-      mCodeGenPasses(nullptr),
-      mLLVMContext(llvm::getGlobalContext()),
-      mDiagEngine(*DiagEngine),
-      mCodeGenOpts(CodeGenOpts),
-      mPragmas(Pragmas) {
+                 const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
+                 llvm::raw_ostream *OS, Slang::OutputType OT,
+                 clang::SourceManager &SourceMgr, bool AllowRSPrefix,
+                 bool IsFilterscript)
+    : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
+      mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
+      mPerModulePasses(nullptr), mCodeGenPasses(nullptr), mContext(Context),
+      mSourceMgr(SourceMgr), mAllowRSPrefix(AllowRSPrefix),
+      mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
+      mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
+      mExportForEachSignatureMetadata(nullptr), mExportTypeMetadata(nullptr),
+      mRSObjectSlotsMetadata(nullptr), mRefCount(mContext->getASTContext()),
+      mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
+      mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
+      mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
   FormattedOutStream.setStream(*mpOS,
                                llvm::formatted_raw_ostream::PRESERVE_STREAM);
   mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
@@ -244,10 +258,6 @@
   FormattedOutStream << Bitcode.str();
 }
 
-bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
-  return mGen->HandleTopLevelDecl(D);
-}
-
 void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
   HandleTranslationUnitPre(Ctx);
 
@@ -400,4 +410,455 @@
   delete mCodeGenPasses;
 }
 
+// 1) Add zero initialization of local RS object types
+void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
+  if (FD &&
+      FD->hasBody() &&
+      !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
+    mRefCount.Init();
+    mRefCount.Visit(FD->getBody());
+  }
+}
+
+bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
+  // Disallow user-defined functions with prefix "rs"
+  if (!mAllowRSPrefix) {
+    // Iterate all function declarations in the program.
+    for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
+         I != E; I++) {
+      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
+      if (FD == nullptr)
+        continue;
+      if (!FD->getName().startswith("rs"))  // Check prefix
+        continue;
+      if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
+        mContext->ReportError(FD->getLocation(),
+                              "invalid function name prefix, "
+                              "\"rs\" is reserved: '%0'")
+            << FD->getName();
+    }
+  }
+
+  // Process any non-static function declarations
+  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
+    clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
+    if (FD && FD->isGlobal()) {
+      // Check that we don't have any array parameters being misintrepeted as
+      // kernel pointers due to the C type system's array to pointer decay.
+      size_t numParams = FD->getNumParams();
+      for (size_t i = 0; i < numParams; i++) {
+        const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
+        clang::QualType QT = PVD->getOriginalType();
+        if (QT->isArrayType()) {
+          mContext->ReportError(
+              PVD->getTypeSpecStartLoc(),
+              "exported function parameters may not have array type: %0")
+              << QT;
+        }
+      }
+      AnnotateFunction(FD);
+    }
+  }
+  return mGen->HandleTopLevelDecl(D);
+}
+
+void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
+  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
+
+  // If we have an invalid RS/FS AST, don't check further.
+  if (!mASTChecker.Validate()) {
+    return;
+  }
+
+  if (mIsFilterscript) {
+    mContext->addPragma("rs_fp_relaxed", "");
+  }
+
+  int version = mContext->getVersion();
+  if (version == 0) {
+    // Not setting a version is an error
+    mDiagEngine.Report(
+        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
+        mDiagEngine.getCustomDiagID(
+            clang::DiagnosticsEngine::Error,
+            "missing pragma for version in source file"));
+  } else {
+    slangAssert(version == 1);
+  }
+
+  if (mContext->getReflectJavaPackageName().empty()) {
+    mDiagEngine.Report(
+        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
+        mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
+                                    "missing \"#pragma rs "
+                                    "java_package_name(com.foo.bar)\" "
+                                    "in source file"));
+    return;
+  }
+
+  // Create a static global destructor if necessary (to handle RS object
+  // runtime cleanup).
+  clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
+  if (FD) {
+    HandleTopLevelDecl(clang::DeclGroupRef(FD));
+  }
+
+  // Process any static function declarations
+  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
+          E = TUDecl->decls_end(); I != E; I++) {
+    if ((I->getKind() >= clang::Decl::firstFunction) &&
+        (I->getKind() <= clang::Decl::lastFunction)) {
+      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
+      if (FD && !FD->isGlobal()) {
+        AnnotateFunction(FD);
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Backend::dumpExportVarInfo(llvm::Module *M) {
+  int slotCount = 0;
+  if (mExportVarMetadata == nullptr)
+    mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
+
+  llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
+
+  // We emit slot information (#rs_object_slots) for any reference counted
+  // RS type or pointer (which can also be bound).
+
+  for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
+          E = mContext->export_vars_end();
+       I != E;
+       I++) {
+    const RSExportVar *EV = *I;
+    const RSExportType *ET = EV->getType();
+    bool countsAsRSObject = false;
+
+    // Variable name
+    ExportVarInfo.push_back(
+        llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
+
+    // Type name
+    switch (ET->getClass()) {
+      case RSExportType::ExportClassPrimitive: {
+        const RSExportPrimitiveType *PT =
+            static_cast<const RSExportPrimitiveType*>(ET);
+        ExportVarInfo.push_back(
+            llvm::MDString::get(
+              mLLVMContext, llvm::utostr_32(PT->getType())));
+        if (PT->isRSObjectType()) {
+          countsAsRSObject = true;
+        }
+        break;
+      }
+      case RSExportType::ExportClassPointer: {
+        ExportVarInfo.push_back(
+            llvm::MDString::get(
+              mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
+                ->getPointeeType()->getName()).c_str()));
+        break;
+      }
+      case RSExportType::ExportClassMatrix: {
+        ExportVarInfo.push_back(
+            llvm::MDString::get(
+              mLLVMContext, llvm::utostr_32(
+                  /* TODO Strange value.  This pushes just a number, quite
+                   * different than the other cases.  What is this used for?
+                   * These are the metadata values that some partner drivers
+                   * want to reference (for TBAA, etc.). We may want to look
+                   * at whether these provide any reasonable value (or have
+                   * distinct enough values to actually depend on).
+                   */
+                DataTypeRSMatrix2x2 +
+                static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
+        break;
+      }
+      case RSExportType::ExportClassVector:
+      case RSExportType::ExportClassConstantArray:
+      case RSExportType::ExportClassRecord: {
+        ExportVarInfo.push_back(
+            llvm::MDString::get(mLLVMContext,
+              EV->getType()->getName().c_str()));
+        break;
+      }
+    }
+
+    mExportVarMetadata->addOperand(
+        llvm::MDNode::get(mLLVMContext, ExportVarInfo));
+    ExportVarInfo.clear();
+
+    if (mRSObjectSlotsMetadata == nullptr) {
+      mRSObjectSlotsMetadata =
+          M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
+    }
+
+    if (countsAsRSObject) {
+      mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
+          llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
+    }
+
+    slotCount++;
+  }
+}
+
+void Backend::dumpExportFunctionInfo(llvm::Module *M) {
+  if (mExportFuncMetadata == nullptr)
+    mExportFuncMetadata =
+        M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
+
+  llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
+
+  for (RSContext::const_export_func_iterator
+          I = mContext->export_funcs_begin(),
+          E = mContext->export_funcs_end();
+       I != E;
+       I++) {
+    const RSExportFunc *EF = *I;
+
+    // Function name
+    if (!EF->hasParam()) {
+      ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
+                                                   EF->getName().c_str()));
+    } else {
+      llvm::Function *F = M->getFunction(EF->getName());
+      llvm::Function *HelperFunction;
+      const std::string HelperFunctionName(".helper_" + EF->getName());
+
+      slangAssert(F && "Function marked as exported disappeared in Bitcode");
+
+      // Create helper function
+      {
+        llvm::StructType *HelperFunctionParameterTy = nullptr;
+        std::vector<bool> isStructInput;
+
+        if (!F->getArgumentList().empty()) {
+          std::vector<llvm::Type*> HelperFunctionParameterTys;
+          for (llvm::Function::arg_iterator AI = F->arg_begin(),
+                   AE = F->arg_end(); AI != AE; AI++) {
+              if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
+                  HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
+                  isStructInput.push_back(true);
+              } else {
+                  HelperFunctionParameterTys.push_back(AI->getType());
+                  isStructInput.push_back(false);
+              }
+          }
+          HelperFunctionParameterTy =
+              llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
+        }
+
+        if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
+          fprintf(stderr, "Failed to export function %s: parameter type "
+                          "mismatch during creation of helper function.\n",
+                  EF->getName().c_str());
+
+          const RSExportRecordType *Expected = EF->getParamPacketType();
+          if (Expected) {
+            fprintf(stderr, "Expected:\n");
+            Expected->getLLVMType()->dump();
+          }
+          if (HelperFunctionParameterTy) {
+            fprintf(stderr, "Got:\n");
+            HelperFunctionParameterTy->dump();
+          }
+        }
+
+        std::vector<llvm::Type*> Params;
+        if (HelperFunctionParameterTy) {
+          llvm::PointerType *HelperFunctionParameterTyP =
+              llvm::PointerType::getUnqual(HelperFunctionParameterTy);
+          Params.push_back(HelperFunctionParameterTyP);
+        }
+
+        llvm::FunctionType * HelperFunctionType =
+            llvm::FunctionType::get(F->getReturnType(),
+                                    Params,
+                                    /* IsVarArgs = */false);
+
+        HelperFunction =
+            llvm::Function::Create(HelperFunctionType,
+                                   llvm::GlobalValue::ExternalLinkage,
+                                   HelperFunctionName,
+                                   M);
+
+        HelperFunction->addFnAttr(llvm::Attribute::NoInline);
+        HelperFunction->setCallingConv(F->getCallingConv());
+
+        // Create helper function body
+        {
+          llvm::Argument *HelperFunctionParameter =
+              &(*HelperFunction->arg_begin());
+          llvm::BasicBlock *BB =
+              llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
+          llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
+          llvm::SmallVector<llvm::Value*, 6> Params;
+          llvm::Value *Idx[2];
+
+          Idx[0] =
+              llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
+
+          // getelementptr and load instruction for all elements in
+          // parameter .p
+          for (size_t i = 0; i < EF->getNumParameters(); i++) {
+            // getelementptr
+            Idx[1] = llvm::ConstantInt::get(
+              llvm::Type::getInt32Ty(mLLVMContext), i);
+
+            llvm::Value *Ptr = NULL;
+
+            Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
+
+            // Load is only required for non-struct ptrs
+            if (isStructInput[i]) {
+                Params.push_back(Ptr);
+            } else {
+                llvm::Value *V = IB->CreateLoad(Ptr);
+                Params.push_back(V);
+            }
+          }
+
+          // Call and pass the all elements as parameter to F
+          llvm::CallInst *CI = IB->CreateCall(F, Params);
+
+          CI->setCallingConv(F->getCallingConv());
+
+          if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
+            IB->CreateRetVoid();
+          else
+            IB->CreateRet(CI);
+
+          delete IB;
+        }
+      }
+
+      ExportFuncInfo.push_back(
+          llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
+    }
+
+    mExportFuncMetadata->addOperand(
+        llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
+    ExportFuncInfo.clear();
+  }
+}
+
+void Backend::dumpExportForEachInfo(llvm::Module *M) {
+  if (mExportForEachNameMetadata == nullptr) {
+    mExportForEachNameMetadata =
+        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
+  }
+  if (mExportForEachSignatureMetadata == nullptr) {
+    mExportForEachSignatureMetadata =
+        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
+  }
+
+  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
+  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
+
+  for (RSContext::const_export_foreach_iterator
+          I = mContext->export_foreach_begin(),
+          E = mContext->export_foreach_end();
+       I != E;
+       I++) {
+    const RSExportForEach *EFE = *I;
+
+    ExportForEachName.push_back(
+        llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
+
+    mExportForEachNameMetadata->addOperand(
+        llvm::MDNode::get(mLLVMContext, ExportForEachName));
+    ExportForEachName.clear();
+
+    ExportForEachInfo.push_back(
+        llvm::MDString::get(mLLVMContext,
+                            llvm::utostr_32(EFE->getSignatureMetadata())));
+
+    mExportForEachSignatureMetadata->addOperand(
+        llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
+    ExportForEachInfo.clear();
+  }
+}
+
+void Backend::dumpExportTypeInfo(llvm::Module *M) {
+  llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
+
+  for (RSContext::const_export_type_iterator
+          I = mContext->export_types_begin(),
+          E = mContext->export_types_end();
+       I != E;
+       I++) {
+    // First, dump type name list to export
+    const RSExportType *ET = I->getValue();
+
+    ExportTypeInfo.clear();
+    // Type name
+    ExportTypeInfo.push_back(
+        llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
+
+    if (ET->getClass() == RSExportType::ExportClassRecord) {
+      const RSExportRecordType *ERT =
+          static_cast<const RSExportRecordType*>(ET);
+
+      if (mExportTypeMetadata == nullptr)
+        mExportTypeMetadata =
+            M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
+
+      mExportTypeMetadata->addOperand(
+          llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
+
+      // Now, export struct field information to %[struct name]
+      std::string StructInfoMetadataName("%");
+      StructInfoMetadataName.append(ET->getName());
+      llvm::NamedMDNode *StructInfoMetadata =
+          M->getOrInsertNamedMetadata(StructInfoMetadataName);
+      llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
+
+      slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
+                  "Metadata with same name was created before");
+      for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
+              FE = ERT->fields_end();
+           FI != FE;
+           FI++) {
+        const RSExportRecordType::Field *F = *FI;
+
+        // 1. field name
+        FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
+                                                F->getName().c_str()));
+
+        // 2. field type name
+        FieldInfo.push_back(
+            llvm::MDString::get(mLLVMContext,
+                                F->getType()->getName().c_str()));
+
+        StructInfoMetadata->addOperand(
+            llvm::MDNode::get(mLLVMContext, FieldInfo));
+        FieldInfo.clear();
+      }
+    }   // ET->getClass() == RSExportType::ExportClassRecord
+  }
+}
+
+void Backend::HandleTranslationUnitPost(llvm::Module *M) {
+
+  if (!mContext->is64Bit()) {
+    M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
+  }
+
+  if (!mContext->processExport()) {
+    return;
+  }
+
+  if (mContext->hasExportVar())
+    dumpExportVarInfo(M);
+
+  if (mContext->hasExportFunc())
+    dumpExportFunctionInfo(M);
+
+  if (mContext->hasExportForEach())
+    dumpExportForEachInfo(M);
+
+  if (mContext->hasExportType())
+    dumpExportTypeInfo(M);
+}
+
 }  // namespace slang
diff --git a/slang_backend.h b/slang_backend.h
index f7075dd..1a97bd6 100644
--- a/slang_backend.h
+++ b/slang_backend.h
@@ -25,6 +25,8 @@
 
 #include "slang.h"
 #include "slang_pragma_recorder.h"
+#include "slang_rs_check_ast.h"
+#include "slang_rs_object_ref_count.h"
 #include "slang_version.h"
 
 namespace llvm {
@@ -35,15 +37,22 @@
 }
 
 namespace clang {
+  class ASTConsumer;
+  class ASTContext;
   class CodeGenOptions;
   class CodeGenerator;
   class DeclGroupRef;
+  class DiagnosticsEngine;
+  class FunctionDecl;
   class TagDecl;
+  class TargetOptions;
   class VarDecl;
 }
 
 namespace slang {
 
+class RSContext;
+
 class Backend : public clang::ASTConsumer {
  private:
   const clang::TargetOptions &mTargetOpts;
@@ -74,6 +83,32 @@
 
   void WrapBitcode(llvm::raw_string_ostream &Bitcode);
 
+  RSContext *mContext;
+
+  clang::SourceManager &mSourceMgr;
+
+  bool mAllowRSPrefix;
+
+  bool mIsFilterscript;
+
+  llvm::NamedMDNode *mExportVarMetadata;
+  llvm::NamedMDNode *mExportFuncMetadata;
+  llvm::NamedMDNode *mExportForEachNameMetadata;
+  llvm::NamedMDNode *mExportForEachSignatureMetadata;
+  llvm::NamedMDNode *mExportTypeMetadata;
+  llvm::NamedMDNode *mRSObjectSlotsMetadata;
+
+  RSObjectRefCount mRefCount;
+
+  RSCheckAST mASTChecker;
+
+  void AnnotateFunction(clang::FunctionDecl *FD);
+
+  void dumpExportVarInfo(llvm::Module *M);
+  void dumpExportFunctionInfo(llvm::Module *M);
+  void dumpExportForEachInfo(llvm::Module *M);
+  void dumpExportTypeInfo(llvm::Module *M);
+
  protected:
   llvm::LLVMContext &mLLVMContext;
   clang::DiagnosticsEngine &mDiagEngine;
@@ -81,9 +116,9 @@
 
   PragmaList *mPragmas;
 
-  virtual unsigned int getTargetAPI() const {
-    return SLANG_MAXIMUM_TARGET_API;
-  }
+  unsigned int getTargetAPI() const { return mContext->getTargetAPI(); }
+
+  // TODO These are no longer virtual from base.  Look into merging into caller.
 
   // This handler will be invoked before Clang translates @Ctx to LLVM IR. This
   // give you an opportunity to modified the IR in AST level (scope information,
@@ -91,47 +126,54 @@
   // translate @Ctx into LLVM IR. One should not operate on @Ctx afterwards
   // since the changes applied on that never reflects to the LLVM module used
   // in the final codegen.
-  virtual void HandleTranslationUnitPre(clang::ASTContext &Ctx) { }
+  void HandleTranslationUnitPre(clang::ASTContext &Ctx);
 
   // This handler will be invoked when Clang have converted AST tree to LLVM IR.
   // The @M contains the resulting LLVM IR tree. After the return from this
   // method, slang will start doing optimization and code generation for @M.
-  virtual void HandleTranslationUnitPost(llvm::Module *M) { }
+  void HandleTranslationUnitPost(llvm::Module *M);
 
  public:
-  Backend(clang::DiagnosticsEngine *DiagEngine,
-          const clang::CodeGenOptions &CodeGenOpts,
-          const clang::TargetOptions &TargetOpts,
-          PragmaList *Pragmas,
-          llvm::raw_ostream *OS,
-          Slang::OutputType OT);
+  Backend(RSContext *Context,
+            clang::DiagnosticsEngine *DiagEngine,
+            const clang::CodeGenOptions &CodeGenOpts,
+            const clang::TargetOptions &TargetOpts,
+            PragmaList *Pragmas,
+            llvm::raw_ostream *OS,
+            Slang::OutputType OT,
+            clang::SourceManager &SourceMgr,
+            bool AllowRSPrefix,
+            bool IsFilterscript);
+
+  virtual ~Backend();
 
   // Initialize - This is called to initialize the consumer, providing the
   // ASTContext.
-  virtual void Initialize(clang::ASTContext &Ctx);
+  void Initialize(clang::ASTContext &Ctx) override;
+
+  // TODO Clean up what should be private, protected
+  // TODO Also clean up the include files
 
   // HandleTopLevelDecl - Handle the specified top-level declaration.  This is
   // called by the parser to process every top-level Decl*. Note that D can be
   // the head of a chain of Decls (e.g. for `int a, b` the chain will have two
   // elements). Use Decl::getNextDeclarator() to walk the chain.
-  virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
+  bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
 
   // HandleTranslationUnit - This method is called when the ASTs for entire
   // translation unit have been parsed.
-  virtual void HandleTranslationUnit(clang::ASTContext &Ctx);
+  void HandleTranslationUnit(clang::ASTContext &Ctx) override;
 
   // HandleTagDeclDefinition - This callback is invoked each time a TagDecl
   // (e.g. struct, union, enum, class) is completed.  This allows the client to
   // hack on the type, which can occur at any point in the file (because these
   // can be defined in declspecs).
-  virtual void HandleTagDeclDefinition(clang::TagDecl *D);
+  void HandleTagDeclDefinition(clang::TagDecl *D) override;
 
   // CompleteTentativeDefinition - Callback invoked at the end of a translation
   // unit to notify the consumer that the given tentative definition should be
   // completed.
-  virtual void CompleteTentativeDefinition(clang::VarDecl *D);
-
-  virtual ~Backend();
+  void CompleteTentativeDefinition(clang::VarDecl *D) override;
 };
 
 }   // namespace slang
diff --git a/slang_rs.cpp b/slang_rs.cpp
deleted file mode 100644
index a388bfa..0000000
--- a/slang_rs.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "slang_rs.h"
-
-#include <cstring>
-#include <list>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "clang/Basic/SourceLocation.h"
-
-#include "clang/Frontend/FrontendDiagnostic.h"
-
-#include "clang/Sema/SemaDiagnostic.h"
-
-#include "llvm/Support/Path.h"
-
-#include "os_sep.h"
-#include "rs_cc_options.h"
-#include "slang_rs_backend.h"
-#include "slang_rs_context.h"
-#include "slang_rs_export_type.h"
-
-#include "slang_rs_reflection.h"
-#include "slang_rs_reflection_cpp.h"
-
-namespace slang {
-
-#define FS_SUFFIX  "fs"
-
-#define RS_HEADER_SUFFIX  "rsh"
-
-/* RS_HEADER_ENTRY(name) */
-#define ENUM_RS_HEADER()  \
-  RS_HEADER_ENTRY(rs_allocation_data) \
-  RS_HEADER_ENTRY(rs_atomic) \
-  RS_HEADER_ENTRY(rs_convert) \
-  RS_HEADER_ENTRY(rs_core) \
-  RS_HEADER_ENTRY(rs_debug) \
-  RS_HEADER_ENTRY(rs_for_each) \
-  RS_HEADER_ENTRY(rs_graphics) \
-  RS_HEADER_ENTRY(rs_graphics_types) \
-  RS_HEADER_ENTRY(rs_io) \
-  RS_HEADER_ENTRY(rs_math) \
-  RS_HEADER_ENTRY(rs_matrix) \
-  RS_HEADER_ENTRY(rs_object_info) \
-  RS_HEADER_ENTRY(rs_object_types) \
-  RS_HEADER_ENTRY(rs_quaternion) \
-  RS_HEADER_ENTRY(rs_time) \
-  RS_HEADER_ENTRY(rs_value_types) \
-  RS_HEADER_ENTRY(rs_vector_math) \
-
-// Returns true if \p Filename ends in ".fs".
-bool SlangRS::isFilterscript(const char *Filename) {
-  const char *c = strrchr(Filename, '.');
-  if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-bool SlangRS::generateJavaBitcodeAccessor(const std::string &OutputPathBase,
-                                          const std::string &PackageName,
-                                          const std::string *LicenseNote) {
-  RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;
-
-  BCAccessorContext.rsFileName = getInputFileName().c_str();
-  BCAccessorContext.bc32FileName = getOutput32FileName().c_str();
-  BCAccessorContext.bc64FileName = getOutputFileName().c_str();
-  BCAccessorContext.reflectPath = OutputPathBase.c_str();
-  BCAccessorContext.packageName = PackageName.c_str();
-  BCAccessorContext.licenseNote = LicenseNote;
-  BCAccessorContext.bcStorage = BCST_JAVA_CODE;   // Must be BCST_JAVA_CODE
-  BCAccessorContext.verbose = false;
-
-  return RSSlangReflectUtils::GenerateJavaBitCodeAccessor(BCAccessorContext);
-}
-
-bool SlangRS::checkODR(const char *CurInputFile) {
-  for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
-          E = mRSContext->exportable_end();
-       I != E;
-       I++) {
-    RSExportable *RSE = *I;
-    if (RSE->getKind() != RSExportable::EX_TYPE)
-      continue;
-
-    RSExportType *ET = static_cast<RSExportType *>(RSE);
-    if (ET->getClass() != RSExportType::ExportClassRecord)
-      continue;
-
-    RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);
-
-    // Artificial record types (create by us not by user in the source) always
-    // conforms the ODR.
-    if (ERT->isArtificial())
-      continue;
-
-    // Key to lookup ERT in ReflectedDefinitions
-    llvm::StringRef RDKey(ERT->getName());
-    ReflectedDefinitionListTy::const_iterator RD =
-        ReflectedDefinitions.find(RDKey);
-
-    if (RD != ReflectedDefinitions.end()) {
-      const RSExportRecordType *Reflected = RD->getValue().first;
-      // There's a record (struct) with the same name reflected before. Enforce
-      // ODR checking - the Reflected must hold *exactly* the same "definition"
-      // as the one defined previously. We say two record types A and B have the
-      // same definition iff:
-      //
-      //  struct A {              struct B {
-      //    Type(a1) a1,            Type(b1) b1,
-      //    Type(a2) a2,            Type(b1) b2,
-      //    ...                     ...
-      //    Type(aN) aN             Type(b3) b3,
-      //  };                      }
-      //  Cond. #1. They have same number of fields, i.e., N = M;
-      //  Cond. #2. for (i := 1 to N)
-      //              Type(ai) = Type(bi) must hold;
-      //  Cond. #3. for (i := 1 to N)
-      //              Name(ai) = Name(bi) must hold;
-      //
-      // where,
-      //  Type(F) = the type of field F and
-      //  Name(F) = the field name.
-
-      bool PassODR = false;
-      // Cond. #1 and Cond. #2
-      if (Reflected->equals(ERT)) {
-        // Cond #3.
-        RSExportRecordType::const_field_iterator AI = Reflected->fields_begin(),
-                                                 BI = ERT->fields_begin();
-
-        for (unsigned i = 0, e = Reflected->getFields().size(); i != e; i++) {
-          if ((*AI)->getName() != (*BI)->getName())
-            break;
-          AI++;
-          BI++;
-        }
-        PassODR = (AI == (Reflected->fields_end()));
-      }
-
-      if (!PassODR) {
-        getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
-                                               << getInputFileName()
-                                               << RD->getValue().second;
-        return false;
-      }
-    } else {
-      llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
-          llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey);
-      ME->setValue(std::make_pair(ERT, CurInputFile));
-
-      if (!ReflectedDefinitions.insert(ME))
-        delete ME;
-
-      // Take the ownership of ERT such that it won't be freed in ~RSContext().
-      ERT->keep();
-    }
-  }
-  return true;
-}
-
-void SlangRS::initDiagnostic() {
-  clang::DiagnosticsEngine &DiagEngine = getDiagnostics();
-  const auto Flavor = clang::diag::Flavor::WarningOrError;
-
-  if (DiagEngine.setSeverityForGroup(Flavor, "implicit-function-declaration",
-                                     clang::diag::Severity::Error)) {
-    DiagEngine.Report(clang::diag::warn_unknown_diag_option)
-      << /* clang::diag::Flavor::WarningOrError */ 0
-      << "implicit-function-declaration";
-  }
-
-  DiagEngine.setSeverity(
-    clang::diag::ext_typecheck_convert_discards_qualifiers,
-    clang::diag::Severity::Error,
-    clang::SourceLocation());
-
-  mDiagErrorInvalidOutputDepParameter =
-    DiagEngine.getCustomDiagID(
-      clang::DiagnosticsEngine::Error,
-      "invalid parameter for output dependencies files.");
-
-  mDiagErrorODR =
-    DiagEngine.getCustomDiagID(
-      clang::DiagnosticsEngine::Error,
-      "type '%0' in different translation unit (%1 v.s. %2) "
-      "has incompatible type definition");
-
-  mDiagErrorTargetAPIRange =
-    DiagEngine.getCustomDiagID(
-      clang::DiagnosticsEngine::Error,
-      "target API level '%0' is out of range ('%1' - '%2')");
-}
-
-void SlangRS::initPreprocessor() {
-  clang::Preprocessor &PP = getPreprocessor();
-
-  std::stringstream RSH;
-  RSH << PP.getPredefines();
-  RSH << "#define RS_VERSION " << mTargetAPI << "\n";
-  RSH << "#include \"rs_core." RS_HEADER_SUFFIX "\"\n";
-  PP.setPredefines(RSH.str());
-}
-
-void SlangRS::initASTContext() {
-  mRSContext = new RSContext(getPreprocessor(),
-                             getASTContext(),
-                             getTargetInfo(),
-                             &mPragmas,
-                             mTargetAPI,
-                             mVerbose);
-}
-
-clang::ASTConsumer
-*SlangRS::createBackend(const clang::CodeGenOptions& CodeGenOpts,
-                        llvm::raw_ostream *OS,
-                        Slang::OutputType OT) {
-    return new RSBackend(mRSContext,
-                         &getDiagnostics(),
-                         CodeGenOpts,
-                         getTargetOptions(),
-                         &mPragmas,
-                         OS,
-                         OT,
-                         getSourceManager(),
-                         mAllowRSPrefix,
-                         mIsFilterscript);
-}
-
-bool SlangRS::IsRSHeaderFile(const char *File) {
-#define RS_HEADER_ENTRY(name)  \
-  if (::strcmp(File, #name "." RS_HEADER_SUFFIX) == 0)  \
-    return true;
-ENUM_RS_HEADER()
-#undef RS_HEADER_ENTRY
-  return false;
-}
-
-bool SlangRS::IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
-                                  const clang::SourceManager &SourceMgr) {
-  clang::FullSourceLoc FSL(Loc, SourceMgr);
-  clang::PresumedLoc PLoc = SourceMgr.getPresumedLoc(FSL);
-
-  const char *Filename = PLoc.getFilename();
-  if (!Filename) {
-    return false;
-  } else {
-    return IsRSHeaderFile(llvm::sys::path::filename(Filename).data());
-  }
-}
-
-SlangRS::SlangRS()
-  : Slang(), mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
-    mVerbose(false), mIsFilterscript(false) {
-}
-
-bool SlangRS::compile(
-    const std::list<std::pair<const char*, const char*> > &IOFiles64,
-    const std::list<std::pair<const char*, const char*> > &IOFiles32,
-    const std::list<std::pair<const char*, const char*> > &DepFiles,
-    const RSCCOptions &Opts) {
-  if (IOFiles32.empty())
-    return true;
-
-  if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
-    getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
-    return false;
-  }
-
-  if (Opts.mEmit3264 && (IOFiles64.size() != IOFiles32.size())) {
-    slangAssert(false && "Should have equal number of 32/64-bit files");
-    return false;
-  }
-
-  std::string RealPackageName;
-
-  const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
-             *DepOutputFile;
-  std::list<std::pair<const char*, const char*> >::const_iterator
-      IOFile64Iter = IOFiles64.begin(),
-      IOFile32Iter = IOFiles32.begin(),
-      DepFileIter = DepFiles.begin();
-
-  setIncludePaths(Opts.mIncludePaths);
-  setOutputType(Opts.mOutputType);
-  if (Opts.mEmitDependency) {
-    setAdditionalDepTargets(Opts.mAdditionalDepTargets);
-  }
-
-  setDebugMetadataEmission(Opts.mDebugEmission);
-
-  setOptimizationLevel(Opts.mOptimizationLevel);
-
-  mAllowRSPrefix = Opts.mAllowRSPrefix;
-
-  mTargetAPI = Opts.mTargetAPI;
-  if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
-      (mTargetAPI < SLANG_MINIMUM_TARGET_API ||
-       mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
-    getDiagnostics().Report(mDiagErrorTargetAPIRange) << mTargetAPI
-        << SLANG_MINIMUM_TARGET_API << SLANG_MAXIMUM_TARGET_API;
-    return false;
-  }
-
-  mVerbose = Opts.mVerbose;
-
-  // Skip generation of warnings a second time if we are doing more than just
-  // a single pass over the input file.
-  bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
-
-  bool CompileSecondTimeFor64Bit = Opts.mEmit3264 && Opts.mBitWidth == 64;
-
-  for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
-    InputFile = IOFile64Iter->first;
-    Output64File = IOFile64Iter->second;
-    Output32File = IOFile32Iter->second;
-
-    // We suppress warnings (via reset) if we are doing a second compilation.
-    reset(CompileSecondTimeFor64Bit);
-
-    if (!setInputSource(InputFile))
-      return false;
-
-    if (!setOutput(Output64File))
-      return false;
-
-    setOutput32(Output32File);
-
-    mIsFilterscript = isFilterscript(InputFile);
-
-    if (Slang::compile() > 0)
-      return false;
-
-    if (!Opts.mJavaReflectionPackageName.empty()) {
-      mRSContext->setReflectJavaPackageName(Opts.mJavaReflectionPackageName);
-    }
-    const std::string &RealPackageName =
-        mRSContext->getReflectJavaPackageName();
-
-    bool doReflection = true;
-    if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
-      // Skip reflection on the 32-bit path if we are going to emit it on the
-      // 64-bit path.
-      doReflection = false;
-    }
-    if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {
-
-      if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
-        const std::string &outputFileName = (Opts.mBitWidth == 64) ?
-            getOutputFileName() : getOutput32FileName();
-        RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
-                          getInputFileName(), outputFileName);
-        if (!R.reflect()) {
-            return false;
-        }
-      } else {
-        if (!Opts.mRSPackageName.empty()) {
-          mRSContext->setRSPackageName(Opts.mRSPackageName);
-        }
-
-        RSReflectionJava R(mRSContext, &mGeneratedFileNames,
-                           Opts.mJavaReflectionPathBase, getInputFileName(),
-                           getOutputFileName(),
-                           Opts.mBitcodeStorage == BCST_JAVA_CODE);
-        if (!R.reflect()) {
-          // TODO Is this needed or will the error message have been printed
-          // already? and why not for the C++ case?
-          fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
-                          "(%s)\n",
-                  R.getLastError());
-          return false;
-        }
-
-        for (std::vector<std::string>::const_iterator
-                 I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
-             I != E;
-             I++) {
-          std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
-              Opts.mJavaReflectionPathBase.c_str(),
-              (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
-          appendGeneratedFileName(ReflectedName + ".java");
-        }
-
-        if ((Opts.mOutputType == Slang::OT_Bitcode) &&
-            (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
-            !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
-                                         RealPackageName.c_str(),
-                                         mRSContext->getLicenseNote())) {
-          return false;
-        }
-      }
-    }
-
-    if (Opts.mEmitDependency) {
-      BCOutputFile = DepFileIter->first;
-      DepOutputFile = DepFileIter->second;
-
-      setDepTargetBC(BCOutputFile);
-
-      if (!setDepOutput(DepOutputFile))
-        return false;
-
-      if (SuppressAllWarnings) {
-        getDiagnostics().setSuppressAllDiagnostics(true);
-      }
-      if (generateDepFile() > 0)
-        return false;
-      if (SuppressAllWarnings) {
-        getDiagnostics().setSuppressAllDiagnostics(false);
-      }
-
-      DepFileIter++;
-    }
-
-    if (!checkODR(InputFile))
-      return false;
-
-    IOFile64Iter++;
-    IOFile32Iter++;
-  }
-
-  return true;
-}
-
-void SlangRS::reset(bool SuppressWarnings) {
-  delete mRSContext;
-  mRSContext = nullptr;
-  mGeneratedFileNames.clear();
-  Slang::reset(SuppressWarnings);
-}
-
-SlangRS::~SlangRS() {
-  delete mRSContext;
-  for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
-          E = ReflectedDefinitions.end();
-       I != E;
-       I++) {
-    delete I->getValue().first;
-  }
-}
-
-}  // namespace slang
diff --git a/slang_rs.h b/slang_rs.h
deleted file mode 100644
index 828b656..0000000
--- a/slang_rs.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_H_  // NOLINT
-#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_H_
-
-#include "slang.h"
-
-#include <list>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "llvm/ADT/StringMap.h"
-
-#include "slang_rs_reflect_utils.h"
-#include "slang_version.h"
-
-namespace slang {
-  class RSCCOptions;
-  class RSContext;
-  class RSExportRecordType;
-
-class SlangRS : public Slang {
- private:
-  // Context for Renderscript
-  RSContext *mRSContext;
-
-  bool mAllowRSPrefix;
-
-  unsigned int mTargetAPI;
-
-  bool mVerbose;
-
-  bool mIsFilterscript;
-
-  // Custom diagnostic identifiers
-  unsigned mDiagErrorInvalidOutputDepParameter;
-  unsigned mDiagErrorODR;
-  unsigned mDiagErrorTargetAPIRange;
-
-  // Collect generated filenames (without the .java) for dependency generation
-  std::vector<std::string> mGeneratedFileNames;
-
-  // FIXME: Should be std::list<RSExportable *> here. But currently we only
-  //        check ODR on record type.
-  //
-  // ReflectedDefinitions maps record type name to a pair:
-  //  <its RSExportRecordType instance,
-  //   the first file contains this record type definition>
-  typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
-  typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
-  ReflectedDefinitionListTy ReflectedDefinitions;
-
-  bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
-                                   const std::string &PackageName,
-                                   const std::string *LicenseNote);
-
-  // CurInputFile is the pointer to a char array holding the input filename
-  // and is valid before compile() ends.
-  bool checkODR(const char *CurInputFile);
-
-  // Returns true if this is a Filterscript file.
-  static bool isFilterscript(const char *Filename);
-
- protected:
-  virtual void initDiagnostic();
-  virtual void initPreprocessor();
-  virtual void initASTContext();
-
-  virtual clang::ASTConsumer
-  *createBackend(const clang::CodeGenOptions& CodeGenOpts,
-                 llvm::raw_ostream *OS,
-                 Slang::OutputType OT);
-
-
- public:
-  static bool IsRSHeaderFile(const char *File);
-  // FIXME: Determine whether a location is in RS header (i.e., one of the RS
-  //        built-in APIs) should only need its names (we need a "list" of RS
-  //        built-in APIs).
-  static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
-                                  const clang::SourceManager &SourceMgr);
-
-  SlangRS();
-
-  // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
-  // all given input files are successfully compiled without errors.
-  //
-  // @IOFiles - List of pairs of <input file path, output file path>.
-  //
-  // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
-  //             target>. If @OutputDep is true, this parameter must be given
-  //             with the same number of pairs given in @IOFiles.
-  //
-  // @Opts - Selection of options defined from invoking llvm-rs-cc
-  bool compile(const std::list<std::pair<const char*, const char*> > &IOFiles64,
-               const std::list<std::pair<const char*, const char*> > &IOFiles32,
-               const std::list<std::pair<const char*, const char*> > &DepFiles,
-               const RSCCOptions &Opts);
-
-  virtual void reset(bool SuppressWarnings = false);
-
-  virtual ~SlangRS();
-
-  virtual void makeModuleVisible(clang::Module *Mod,
-                                 clang::Module::NameVisibilityKind Visibility,
-                                 clang::SourceLocation ImportLoc,
-                                 bool Complain = false) { }
-
-  virtual clang::GlobalModuleIndex *loadGlobalModuleIndex(
-      clang::SourceLocation TriggerLoc) { }
-
-  virtual bool lookupMissingImports(llvm::StringRef Name,
-                                    clang::SourceLocation TriggerLoc) { }
-};
-}  // namespace slang
-
-#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_H_  NOLINT
diff --git a/slang_rs_backend.cpp b/slang_rs_backend.cpp
deleted file mode 100644
index eb59077..0000000
--- a/slang_rs_backend.cpp
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "slang_rs_backend.h"
-
-#include <string>
-#include <vector>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/StringExtras.h"
-
-#include "llvm/IR/Constant.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/Module.h"
-
-#include "llvm/IR/DebugLoc.h"
-
-#include "slang_assert.h"
-#include "slang_rs.h"
-#include "slang_rs_context.h"
-#include "slang_rs_export_foreach.h"
-#include "slang_rs_export_func.h"
-#include "slang_rs_export_type.h"
-#include "slang_rs_export_var.h"
-#include "slang_rs_metadata.h"
-
-namespace slang {
-
-RSBackend::RSBackend(RSContext *Context,
-                     clang::DiagnosticsEngine *DiagEngine,
-                     const clang::CodeGenOptions &CodeGenOpts,
-                     const clang::TargetOptions &TargetOpts,
-                     PragmaList *Pragmas,
-                     llvm::raw_ostream *OS,
-                     Slang::OutputType OT,
-                     clang::SourceManager &SourceMgr,
-                     bool AllowRSPrefix,
-                     bool IsFilterscript)
-  : Backend(DiagEngine, CodeGenOpts, TargetOpts, Pragmas, OS, OT),
-    mContext(Context),
-    mSourceMgr(SourceMgr),
-    mAllowRSPrefix(AllowRSPrefix),
-    mIsFilterscript(IsFilterscript),
-    mExportVarMetadata(nullptr),
-    mExportFuncMetadata(nullptr),
-    mExportForEachNameMetadata(nullptr),
-    mExportForEachSignatureMetadata(nullptr),
-    mExportTypeMetadata(nullptr),
-    mRSObjectSlotsMetadata(nullptr),
-    mRefCount(mContext->getASTContext()),
-    mASTChecker(Context, Context->getTargetAPI(), IsFilterscript) {
-}
-
-// 1) Add zero initialization of local RS object types
-void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
-  if (FD &&
-      FD->hasBody() &&
-      !SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
-    mRefCount.Init();
-    mRefCount.Visit(FD->getBody());
-  }
-}
-
-bool RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
-  // Disallow user-defined functions with prefix "rs"
-  if (!mAllowRSPrefix) {
-    // Iterate all function declarations in the program.
-    for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
-         I != E; I++) {
-      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
-      if (FD == nullptr)
-        continue;
-      if (!FD->getName().startswith("rs"))  // Check prefix
-        continue;
-      if (!SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
-        mContext->ReportError(FD->getLocation(),
-                              "invalid function name prefix, "
-                              "\"rs\" is reserved: '%0'")
-            << FD->getName();
-    }
-  }
-
-  // Process any non-static function declarations
-  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
-    clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
-    if (FD && FD->isGlobal()) {
-      // Check that we don't have any array parameters being misintrepeted as
-      // kernel pointers due to the C type system's array to pointer decay.
-      size_t numParams = FD->getNumParams();
-      for (size_t i = 0; i < numParams; i++) {
-        const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
-        clang::QualType QT = PVD->getOriginalType();
-        if (QT->isArrayType()) {
-          mContext->ReportError(
-              PVD->getTypeSpecStartLoc(),
-              "exported function parameters may not have array type: %0")
-              << QT;
-        }
-      }
-      AnnotateFunction(FD);
-    }
-  }
-
-  return Backend::HandleTopLevelDecl(D);
-}
-
-
-void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
-  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
-
-  // If we have an invalid RS/FS AST, don't check further.
-  if (!mASTChecker.Validate()) {
-    return;
-  }
-
-  if (mIsFilterscript) {
-    mContext->addPragma("rs_fp_relaxed", "");
-  }
-
-  int version = mContext->getVersion();
-  if (version == 0) {
-    // Not setting a version is an error
-    mDiagEngine.Report(
-        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
-        mDiagEngine.getCustomDiagID(
-            clang::DiagnosticsEngine::Error,
-            "missing pragma for version in source file"));
-  } else {
-    slangAssert(version == 1);
-  }
-
-  if (mContext->getReflectJavaPackageName().empty()) {
-    mDiagEngine.Report(
-        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
-        mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                    "missing \"#pragma rs "
-                                    "java_package_name(com.foo.bar)\" "
-                                    "in source file"));
-    return;
-  }
-
-  // Create a static global destructor if necessary (to handle RS object
-  // runtime cleanup).
-  clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
-  if (FD) {
-    HandleTopLevelDecl(clang::DeclGroupRef(FD));
-  }
-
-  // Process any static function declarations
-  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
-          E = TUDecl->decls_end(); I != E; I++) {
-    if ((I->getKind() >= clang::Decl::firstFunction) &&
-        (I->getKind() <= clang::Decl::lastFunction)) {
-      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
-      if (FD && !FD->isGlobal()) {
-        AnnotateFunction(FD);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-void RSBackend::dumpExportVarInfo(llvm::Module *M) {
-  int slotCount = 0;
-  if (mExportVarMetadata == nullptr)
-    mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
-
-  llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
-
-  // We emit slot information (#rs_object_slots) for any reference counted
-  // RS type or pointer (which can also be bound).
-
-  for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
-          E = mContext->export_vars_end();
-       I != E;
-       I++) {
-    const RSExportVar *EV = *I;
-    const RSExportType *ET = EV->getType();
-    bool countsAsRSObject = false;
-
-    // Variable name
-    ExportVarInfo.push_back(
-        llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
-
-    // Type name
-    switch (ET->getClass()) {
-      case RSExportType::ExportClassPrimitive: {
-        const RSExportPrimitiveType *PT =
-            static_cast<const RSExportPrimitiveType*>(ET);
-        ExportVarInfo.push_back(
-            llvm::MDString::get(
-              mLLVMContext, llvm::utostr_32(PT->getType())));
-        if (PT->isRSObjectType()) {
-          countsAsRSObject = true;
-        }
-        break;
-      }
-      case RSExportType::ExportClassPointer: {
-        ExportVarInfo.push_back(
-            llvm::MDString::get(
-              mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
-                ->getPointeeType()->getName()).c_str()));
-        break;
-      }
-      case RSExportType::ExportClassMatrix: {
-        ExportVarInfo.push_back(
-            llvm::MDString::get(
-              mLLVMContext, llvm::utostr_32(
-                  /* TODO Strange value.  This pushes just a number, quite
-                   * different than the other cases.  What is this used for?
-                   * These are the metadata values that some partner drivers
-                   * want to reference (for TBAA, etc.). We may want to look
-                   * at whether these provide any reasonable value (or have
-                   * distinct enough values to actually depend on).
-                   */
-                DataTypeRSMatrix2x2 +
-                static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
-        break;
-      }
-      case RSExportType::ExportClassVector:
-      case RSExportType::ExportClassConstantArray:
-      case RSExportType::ExportClassRecord: {
-        ExportVarInfo.push_back(
-            llvm::MDString::get(mLLVMContext,
-              EV->getType()->getName().c_str()));
-        break;
-      }
-    }
-
-    mExportVarMetadata->addOperand(
-        llvm::MDNode::get(mLLVMContext, ExportVarInfo));
-    ExportVarInfo.clear();
-
-    if (mRSObjectSlotsMetadata == nullptr) {
-      mRSObjectSlotsMetadata =
-          M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
-    }
-
-    if (countsAsRSObject) {
-      mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
-          llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
-    }
-
-    slotCount++;
-  }
-}
-
-void RSBackend::dumpExportFunctionInfo(llvm::Module *M) {
-  if (mExportFuncMetadata == nullptr)
-    mExportFuncMetadata =
-        M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
-
-  llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
-
-  for (RSContext::const_export_func_iterator
-          I = mContext->export_funcs_begin(),
-          E = mContext->export_funcs_end();
-       I != E;
-       I++) {
-    const RSExportFunc *EF = *I;
-
-    // Function name
-    if (!EF->hasParam()) {
-      ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
-                                                   EF->getName().c_str()));
-    } else {
-      llvm::Function *F = M->getFunction(EF->getName());
-      llvm::Function *HelperFunction;
-      const std::string HelperFunctionName(".helper_" + EF->getName());
-
-      slangAssert(F && "Function marked as exported disappeared in Bitcode");
-
-      // Create helper function
-      {
-        llvm::StructType *HelperFunctionParameterTy = nullptr;
-        std::vector<bool> isStructInput;
-
-        if (!F->getArgumentList().empty()) {
-          std::vector<llvm::Type*> HelperFunctionParameterTys;
-          for (llvm::Function::arg_iterator AI = F->arg_begin(),
-                   AE = F->arg_end(); AI != AE; AI++) {
-              if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
-                  HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
-                  isStructInput.push_back(true);
-              } else {
-                  HelperFunctionParameterTys.push_back(AI->getType());
-                  isStructInput.push_back(false);
-              }
-          }
-          HelperFunctionParameterTy =
-              llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
-        }
-
-        if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
-          fprintf(stderr, "Failed to export function %s: parameter type "
-                          "mismatch during creation of helper function.\n",
-                  EF->getName().c_str());
-
-          const RSExportRecordType *Expected = EF->getParamPacketType();
-          if (Expected) {
-            fprintf(stderr, "Expected:\n");
-            Expected->getLLVMType()->dump();
-          }
-          if (HelperFunctionParameterTy) {
-            fprintf(stderr, "Got:\n");
-            HelperFunctionParameterTy->dump();
-          }
-        }
-
-        std::vector<llvm::Type*> Params;
-        if (HelperFunctionParameterTy) {
-          llvm::PointerType *HelperFunctionParameterTyP =
-              llvm::PointerType::getUnqual(HelperFunctionParameterTy);
-          Params.push_back(HelperFunctionParameterTyP);
-        }
-
-        llvm::FunctionType * HelperFunctionType =
-            llvm::FunctionType::get(F->getReturnType(),
-                                    Params,
-                                    /* IsVarArgs = */false);
-
-        HelperFunction =
-            llvm::Function::Create(HelperFunctionType,
-                                   llvm::GlobalValue::ExternalLinkage,
-                                   HelperFunctionName,
-                                   M);
-
-        HelperFunction->addFnAttr(llvm::Attribute::NoInline);
-        HelperFunction->setCallingConv(F->getCallingConv());
-
-        // Create helper function body
-        {
-          llvm::Argument *HelperFunctionParameter =
-              &(*HelperFunction->arg_begin());
-          llvm::BasicBlock *BB =
-              llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
-          llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
-          llvm::SmallVector<llvm::Value*, 6> Params;
-          llvm::Value *Idx[2];
-
-          Idx[0] =
-              llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
-
-          // getelementptr and load instruction for all elements in
-          // parameter .p
-          for (size_t i = 0; i < EF->getNumParameters(); i++) {
-            // getelementptr
-            Idx[1] = llvm::ConstantInt::get(
-              llvm::Type::getInt32Ty(mLLVMContext), i);
-
-            llvm::Value *Ptr = NULL;
-
-            Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
-
-            // Load is only required for non-struct ptrs
-            if (isStructInput[i]) {
-                Params.push_back(Ptr);
-            } else {
-                llvm::Value *V = IB->CreateLoad(Ptr);
-                Params.push_back(V);
-            }
-          }
-
-          // Call and pass the all elements as parameter to F
-          llvm::CallInst *CI = IB->CreateCall(F, Params);
-
-          CI->setCallingConv(F->getCallingConv());
-
-          if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
-            IB->CreateRetVoid();
-          else
-            IB->CreateRet(CI);
-
-          delete IB;
-        }
-      }
-
-      ExportFuncInfo.push_back(
-          llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
-    }
-
-    mExportFuncMetadata->addOperand(
-        llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
-    ExportFuncInfo.clear();
-  }
-}
-
-void RSBackend::dumpExportForEachInfo(llvm::Module *M) {
-  if (mExportForEachNameMetadata == nullptr) {
-    mExportForEachNameMetadata =
-        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
-  }
-  if (mExportForEachSignatureMetadata == nullptr) {
-    mExportForEachSignatureMetadata =
-        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
-  }
-
-  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
-  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
-
-  for (RSContext::const_export_foreach_iterator
-          I = mContext->export_foreach_begin(),
-          E = mContext->export_foreach_end();
-       I != E;
-       I++) {
-    const RSExportForEach *EFE = *I;
-
-    ExportForEachName.push_back(
-        llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
-
-    mExportForEachNameMetadata->addOperand(
-        llvm::MDNode::get(mLLVMContext, ExportForEachName));
-    ExportForEachName.clear();
-
-    ExportForEachInfo.push_back(
-        llvm::MDString::get(mLLVMContext,
-                            llvm::utostr_32(EFE->getSignatureMetadata())));
-
-    mExportForEachSignatureMetadata->addOperand(
-        llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
-    ExportForEachInfo.clear();
-  }
-}
-
-void RSBackend::dumpExportTypeInfo(llvm::Module *M) {
-  llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
-
-  for (RSContext::const_export_type_iterator
-          I = mContext->export_types_begin(),
-          E = mContext->export_types_end();
-       I != E;
-       I++) {
-    // First, dump type name list to export
-    const RSExportType *ET = I->getValue();
-
-    ExportTypeInfo.clear();
-    // Type name
-    ExportTypeInfo.push_back(
-        llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
-
-    if (ET->getClass() == RSExportType::ExportClassRecord) {
-      const RSExportRecordType *ERT =
-          static_cast<const RSExportRecordType*>(ET);
-
-      if (mExportTypeMetadata == nullptr)
-        mExportTypeMetadata =
-            M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
-
-      mExportTypeMetadata->addOperand(
-          llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
-
-      // Now, export struct field information to %[struct name]
-      std::string StructInfoMetadataName("%");
-      StructInfoMetadataName.append(ET->getName());
-      llvm::NamedMDNode *StructInfoMetadata =
-          M->getOrInsertNamedMetadata(StructInfoMetadataName);
-      llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
-
-      slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
-                  "Metadata with same name was created before");
-      for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
-              FE = ERT->fields_end();
-           FI != FE;
-           FI++) {
-        const RSExportRecordType::Field *F = *FI;
-
-        // 1. field name
-        FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
-                                                F->getName().c_str()));
-
-        // 2. field type name
-        FieldInfo.push_back(
-            llvm::MDString::get(mLLVMContext,
-                                F->getType()->getName().c_str()));
-
-        StructInfoMetadata->addOperand(
-            llvm::MDNode::get(mLLVMContext, FieldInfo));
-        FieldInfo.clear();
-      }
-    }   // ET->getClass() == RSExportType::ExportClassRecord
-  }
-}
-
-void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
-
-  if (!mContext->is64Bit()) {
-    M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
-  }
-
-  if (!mContext->processExport()) {
-    return;
-  }
-
-
-
-  if (mContext->hasExportVar())
-    dumpExportVarInfo(M);
-
-  if (mContext->hasExportFunc())
-    dumpExportFunctionInfo(M);
-
-  if (mContext->hasExportForEach())
-    dumpExportForEachInfo(M);
-
-  if (mContext->hasExportType())
-    dumpExportTypeInfo(M);
-}
-
-RSBackend::~RSBackend() {
-}
-
-}  // namespace slang
diff --git a/slang_rs_backend.h b/slang_rs_backend.h
deleted file mode 100644
index a8fef0e..0000000
--- a/slang_rs_backend.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_BACKEND_H_  // NOLINT
-#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_BACKEND_H_
-
-#include "slang_backend.h"
-#include "slang_pragma_recorder.h"
-#include "slang_rs_check_ast.h"
-#include "slang_rs_object_ref_count.h"
-
-namespace llvm {
-  class NamedMDNode;
-}
-
-namespace clang {
-  class ASTConsumer;
-  class DiagnosticsEngine;
-  class TargetOptions;
-  class CodeGenerator;
-  class ASTContext;
-  class DeclGroupRef;
-  class FunctionDecl;
-}
-
-namespace slang {
-
-class RSContext;
-
-class RSBackend : public Backend {
- private:
-  RSContext *mContext;
-
-  clang::SourceManager &mSourceMgr;
-
-  bool mAllowRSPrefix;
-
-  bool mIsFilterscript;
-
-  llvm::NamedMDNode *mExportVarMetadata;
-  llvm::NamedMDNode *mExportFuncMetadata;
-  llvm::NamedMDNode *mExportForEachNameMetadata;
-  llvm::NamedMDNode *mExportForEachSignatureMetadata;
-  llvm::NamedMDNode *mExportTypeMetadata;
-  llvm::NamedMDNode *mRSObjectSlotsMetadata;
-
-  RSObjectRefCount mRefCount;
-
-  RSCheckAST mASTChecker;
-
-  void AnnotateFunction(clang::FunctionDecl *FD);
-
-  void dumpExportVarInfo(llvm::Module *M);
-  void dumpExportFunctionInfo(llvm::Module *M);
-  void dumpExportForEachInfo(llvm::Module *M);
-  void dumpExportTypeInfo(llvm::Module *M);
-
- protected:
-  virtual unsigned int getTargetAPI() const {
-    return mContext->getTargetAPI();
-  }
-
-  virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
-
-  virtual void HandleTranslationUnitPre(clang::ASTContext &C);
-
-  virtual void HandleTranslationUnitPost(llvm::Module *M);
-
- public:
-  RSBackend(RSContext *Context,
-            clang::DiagnosticsEngine *DiagEngine,
-            const clang::CodeGenOptions &CodeGenOpts,
-            const clang::TargetOptions &TargetOpts,
-            PragmaList *Pragmas,
-            llvm::raw_ostream *OS,
-            Slang::OutputType OT,
-            clang::SourceManager &SourceMgr,
-            bool AllowRSPrefix,
-            bool IsFilterscript);
-
-  virtual ~RSBackend();
-};
-}  // namespace slang
-
-#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_BACKEND_H_  NOLINT
diff --git a/slang_rs_check_ast.cpp b/slang_rs_check_ast.cpp
index 848a176..a7c1025 100644
--- a/slang_rs_check_ast.cpp
+++ b/slang_rs_check_ast.cpp
@@ -17,7 +17,7 @@
 #include "slang_rs_check_ast.h"
 
 #include "slang_assert.h"
-#include "slang_rs.h"
+#include "slang.h"
 #include "slang_rs_export_foreach.h"
 #include "slang_rs_export_type.h"
 
@@ -218,7 +218,7 @@
 
 
 void RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) {
-  if (!SlangRS::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
+  if (!Slang::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
     for (clang::DeclStmt::decl_iterator I = DS->decl_begin(),
                                         E = DS->decl_end();
          I != E;
@@ -259,7 +259,7 @@
   // array accesses rely heavily on them and they are valid.
   E = E->IgnoreImpCasts();
   if (mIsFilterscript &&
-      !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
+      !Slang::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
       !RSExportType::ValidateType(Context, C, E->getType(), nullptr, E->getExprLoc(),
                                   mTargetAPI, mIsFilterscript)) {
     mValid = false;
@@ -276,7 +276,7 @@
           DE = TUDecl->decls_end();
        DI != DE;
        DI++) {
-    if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
+    if (!Slang::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
       if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) {
         ValidateVarDecl(VD);
       } else if (clang::FunctionDecl *FD =
diff --git a/slang_rs_object_ref_count.cpp b/slang_rs_object_ref_count.cpp
index 05722a2..853afeb 100644
--- a/slang_rs_object_ref_count.cpp
+++ b/slang_rs_object_ref_count.cpp
@@ -26,7 +26,7 @@
 #include "clang/AST/StmtVisitor.h"
 
 #include "slang_assert.h"
-#include "slang_rs.h"
+#include "slang.h"
 #include "slang_rs_ast_replace.h"
 #include "slang_rs_export_type.h"