Switch to use RSCompilerDriver.

This commit is large. It does:

1. Clean-up RSScript. ScriptCached and ScriptCompiled are removed.
2. Switch to use CompilerConfig.
3. Switch to use RSInfo. MCCacheReader and MCCacheWriter are removed.
4. Update C API implementation of libbcc (i.e., bcc.cpp). Note that
   it'll be completely removed once there's no clients relying on it.

Change-Id: I9cbe9f9441f73b7c0b3b84793cb35810dd3a9f4c
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index f9877d5..8c78cd0 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -34,10 +34,10 @@
   GDBJITRegistrar.cpp \
   Initialization.cpp \
   InputFile.cpp \
-  MCCacheWriter.cpp \
-  MCCacheReader.cpp \
   ObjectLoader.cpp \
   OutputFile.cpp \
+  RSCompiler.cpp \
+  RSCompilerDriver.cpp \
   RSExecutable.cpp \
   RSForEachExpand.cpp \
   RSInfo.cpp \
@@ -47,8 +47,6 @@
   RSScript.cpp \
   BCCRuntimeStub.c \
   Script.cpp \
-  ScriptCached.cpp \
-  ScriptCompiled.cpp \
   Sha1Helper.cpp \
   Source.cpp \
   SymbolResolverProxy.cpp \
diff --git a/lib/ExecutionEngine/BCCContext.cpp b/lib/ExecutionEngine/BCCContext.cpp
index 63df268..2c119b7 100644
--- a/lib/ExecutionEngine/BCCContext.cpp
+++ b/lib/ExecutionEngine/BCCContext.cpp
@@ -19,7 +19,6 @@
 #include <new>
 
 #include "BCCContextImpl.h"
-#include "Compiler.h"
 #include "DebugHelper.h"
 #include "Source.h"
 
@@ -42,10 +41,7 @@
   GlobalContext = NULL;
 }
 
-BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) {
-  // Initialize the LLVM compiler infrastructure.
-  Compiler::GlobalInitialization();
-}
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) { }
 
 BCCContext::~BCCContext() {
   delete mImpl;
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index 954e150..2348d56 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -16,657 +16,367 @@
 
 #include "Compiler.h"
 
-#include "Config.h"
-#include <bcinfo/MetadataExtractor.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/CodeGen/RegAllocRegistry.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/Scalar.h>
 
-#if USE_DISASSEMBLER
-#include "Disassembler/Disassembler.h"
-#endif
-
-#include "BCCRuntimeSymbolResolver.h"
+#include "CompilerConfig.h"
 #include "DebugHelper.h"
-#include "ScriptCompiled.h"
-#include "Sha1Helper.h"
-#include "CompilerOption.h"
-#include "SymbolResolverProxy.h"
-#include "SymbolResolvers.h"
+#include "OutputFile.h"
+#include "Script.h"
+#include "Source.h"
 
-#include "librsloader.h"
+using namespace bcc;
 
-#include "RSTransforms.h"
+const char *Compiler::GetErrorString(enum ErrorCode pErrCode) {
+  static const char *ErrorString[] = {
+    /* kSuccess */
+    "Successfully compiled.",
+    /* kInvalidConfigNoTarget */
+    "Invalid compiler config supplied (getTarget() returns NULL.) "
+    "(missing call to CompilerConfig::initialize()?)",
+    /* kErrCreateTargetMachine */
+    "Failed to create llvm::TargetMachine.",
+    /* kErrSwitchTargetMachine */
+    "Failed to switch llvm::TargetMachine.",
+    /* kErrNoTargetMachine */
+    "Failed to compile the script since there's no available TargetMachine."
+    " (missing call to Compiler::config()?)",
+    /* kErrTargetDataNoMemory */
+    "Out of memory when create TargetData during compilation.",
+    /* kErrMaterialization */
+    "Failed to materialize the module.",
+    /* kErrInvalidOutputFileState */
+    "Supplied output file was invalid (in the error state.)",
+    /* kErrPrepareOutput */
+    "Failed to prepare file for output.",
+    /* kPrepareCodeGenPass */
+    "Failed to construct pass list for code-generation.",
 
-#include "llvm/ADT/StringRef.h"
+    /* kErrHookBeforeAddLTOPasses */
+    "Error occurred during beforeAddLTOPasses() in subclass.",
+    /* kErrHookAfterAddLTOPasses */
+    "Error occurred during afterAddLTOPasses() in subclass.",
+    /* kErrHookBeforeExecuteLTOPasses */
+    "Error occurred during beforeExecuteLTOPasses() in subclass.",
+    /* kErrHookAfterExecuteLTOPasses */
+    "Error occurred during afterExecuteLTOPasses() in subclass.",
 
-#include "llvm/Analysis/Passes.h"
+    /* kErrHookBeforeAddCodeGenPasses */
+    "Error occurred during beforeAddCodeGenPasses() in subclass.",
+    /* kErrHookAfterAddCodeGenPasses */
+    "Error occurred during afterAddCodeGenPasses() in subclass.",
+    /* kErrHookBeforeExecuteCodeGenPasses */
+    "Error occurred during beforeExecuteCodeGenPasses() in subclass.",
+    /* kErrHookAfterExecuteCodeGenPasses */
+    "Error occurred during afterExecuteCodeGenPasses() in subclass.",
 
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/RegAllocRegistry.h"
-#include "llvm/CodeGen/SchedulerRegistry.h"
+    /* kMaxErrorCode */
+    "(Unknown error code)"
+  };
 
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/SubtargetFeature.h"
-
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Scalar.h"
-
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "llvm/Constants.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Linker.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
-#include "llvm/Type.h"
-#include "llvm/Value.h"
-
-#include <errno.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string.h>
-
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <vector>
-
-extern char* gDebugDumpDirectory;
-
-namespace bcc {
-
-//////////////////////////////////////////////////////////////////////////////
-// BCC Compiler Static Variables
-//////////////////////////////////////////////////////////////////////////////
-
-bool Compiler::GlobalInitialized = false;
-
-
-#if !defined(__HOST__)
-  #define TARGET_TRIPLE_STRING  DEFAULT_TARGET_TRIPLE_STRING
-#else
-// In host TARGET_TRIPLE_STRING is a variable to allow cross-compilation.
-  #if defined(__cplusplus)
-    extern "C" {
-  #endif
-      char *TARGET_TRIPLE_STRING = (char*)DEFAULT_TARGET_TRIPLE_STRING;
-  #if defined(__cplusplus)
-    };
-  #endif
-#endif
-
-// Code generation optimization level for the compiler
-llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
-
-std::string Compiler::Triple;
-llvm::Triple::ArchType Compiler::ArchType;
-
-std::string Compiler::CPU;
-
-std::vector<std::string> Compiler::Features;
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Compiler
-//////////////////////////////////////////////////////////////////////////////
-
-void Compiler::GlobalInitialization() {
-  if (GlobalInitialized) {
-    return;
+  if (pErrCode > kMaxErrorCode) {
+    pErrCode = kMaxErrorCode;
   }
 
-#if defined(PROVIDE_ARM_CODEGEN)
-  LLVMInitializeARMAsmPrinter();
-  LLVMInitializeARMTargetMC();
-  LLVMInitializeARMTargetInfo();
-  LLVMInitializeARMTarget();
-#endif
-
-#if defined(PROVIDE_MIPS_CODEGEN)
-  LLVMInitializeMipsAsmPrinter();
-  LLVMInitializeMipsTargetMC();
-  LLVMInitializeMipsTargetInfo();
-  LLVMInitializeMipsTarget();
-#endif
-
-#if defined(PROVIDE_X86_CODEGEN)
-  LLVMInitializeX86AsmPrinter();
-  LLVMInitializeX86TargetMC();
-  LLVMInitializeX86TargetInfo();
-  LLVMInitializeX86Target();
-#endif
-
-#if USE_DISASSEMBLER
-  InitializeDisassembler();
-#endif
-
-  // if (!llvm::llvm_is_multithreaded())
-  //   llvm::llvm_start_multithreaded();
-
-  // Set Triple, CPU and Features here
-  Triple = TARGET_TRIPLE_STRING;
-
-  // Determine ArchType
-#if defined(__HOST__)
-  {
-    std::string Err;
-    llvm::Target const *Target = llvm::TargetRegistry::lookupTarget(Triple, Err);
-    if (Target != NULL) {
-      ArchType = llvm::Triple::getArchTypeForLLVMName(Target->getName());
-    } else {
-      ArchType = llvm::Triple::UnknownArch;
-      ALOGE("%s", Err.c_str());
-    }
-  }
-#elif defined(DEFAULT_ARM_CODEGEN)
-  ArchType = llvm::Triple::arm;
-#elif defined(DEFAULT_MIPS_CODEGEN)
-  ArchType = llvm::Triple::mipsel;
-#elif defined(DEFAULT_X86_CODEGEN)
-  ArchType = llvm::Triple::x86;
-#elif defined(DEFAULT_X86_64_CODEGEN)
-  ArchType = llvm::Triple::x86_64;
-#else
-  ArchType = llvm::Triple::UnknownArch;
-#endif
-
-  if ((ArchType == llvm::Triple::arm) || (ArchType == llvm::Triple::thumb)) {
-#  if defined(ARCH_ARM_HAVE_VFP)
-    Features.push_back("+vfp3");
-#  if !defined(ARCH_ARM_HAVE_VFP_D32)
-    Features.push_back("+d16");
-#  endif
-#  endif
-
-#  if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_ARCH_ARM_HAVE_NEON)
-    Features.push_back("+neon");
-    Features.push_back("+neonfp");
-#  else
-    Features.push_back("-neon");
-    Features.push_back("-neonfp");
-#  endif
-  }
-
-  // Register the scheduler
-  llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
-
-  // Read in SHA1 checksum of libbcc and libRS.
-  readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1);
-
-  calcFileSHA1(sha1LibRS, pathLibRS);
-
-  GlobalInitialized = true;
+  return ErrorString[ static_cast<size_t>(pErrCode) ];
 }
 
-
-void Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) {
-  std::string *Error = static_cast<std::string*>(UserData);
-  Error->assign(Message);
-  ALOGE("%s", Message.c_str());
-  exit(1);
-}
-
-
-Compiler::Compiler(ScriptCompiled *result)
-  : mpResult(result),
-    mRSExecutable(NULL),
-    mpSymbolLookupFn(NULL),
-    mpSymbolLookupContext(NULL),
-    mModule(NULL) {
-  llvm::remove_fatal_error_handler();
-  llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
+//===----------------------------------------------------------------------===//
+// Instance Methods
+//===----------------------------------------------------------------------===//
+Compiler::Compiler() : mTarget(NULL), mEnableLTO(true) {
   return;
 }
 
-int Compiler::readModule(llvm::Module &pModule) {
-  mModule = &pModule;
-  if (pModule.getMaterializer() != NULL) {
-    // A module with non-null materializer means that it is a lazy-load module.
-    // Materialize it now via invoking MaterializeAllPermanently(). This
-    // function returns false when the materialization is successful.
-    if (pModule.MaterializeAllPermanently(&mError)) {
-      setError("Failed to materialize the module `" +
-               pModule.getModuleIdentifier() + "'! (" + mError + ")");
-      mModule = NULL;
-    }
+Compiler::Compiler(const CompilerConfig &pConfig) : mTarget(NULL),
+                                                    mEnableLTO(true) {
+  const std::string &triple = pConfig.getTriple();
+
+  enum ErrorCode err = config(pConfig);
+  if (err != kSuccess) {
+    ALOGE("%s (%s, features: %s)", GetErrorString(err),
+          triple.c_str(), pConfig.getFeatureString().c_str());
+    return;
   }
-  return hasError();
+
+  return;
 }
 
-int Compiler::compile(const CompilerOption &option) {
-  llvm::Target const *Target = NULL;
-  llvm::TargetData *TD = NULL;
-  llvm::TargetMachine *TM = NULL;
-
-  std::vector<std::string> ExtraFeatures;
-
-  std::string FeaturesStr;
-
-  if (mModule == NULL)  // No module was loaded
-    return 0;
-
-  bcinfo::MetadataExtractor ME(mModule);
-  ME.extract();
-
-  size_t VarCount = ME.getExportVarCount();
-  size_t FuncCount = ME.getExportFuncCount();
-  size_t ForEachSigCount = ME.getExportForEachSignatureCount();
-  size_t ObjectSlotCount = ME.getObjectSlotCount();
-  size_t PragmaCount = ME.getPragmaCount();
-
-  std::vector<std::string> &VarNameList = mpResult->mExportVarsName;
-  std::vector<std::string> &FuncNameList = mpResult->mExportFuncsName;
-  std::vector<std::string> &ForEachExpandList = mpResult->mExportForEachName;
-  RSInfo::ExportForeachFuncListTy ForEachFuncList;
-  std::vector<const char*> ExportSymbols;
-
-  // Defaults to maximum optimization level from MetadataExtractor.
-  uint32_t OptimizationLevel = ME.getOptimizationLevel();
-
-  if (OptimizationLevel == 0) {
-    CodeGenOptLevel = llvm::CodeGenOpt::None;
-  } else if (OptimizationLevel == 1) {
-    CodeGenOptLevel = llvm::CodeGenOpt::Less;
-  } else if (OptimizationLevel == 2) {
-    CodeGenOptLevel = llvm::CodeGenOpt::Default;
-  } else if (OptimizationLevel == 3) {
-    CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
+enum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) {
+  if (pConfig.getTarget() == NULL) {
+    return kInvalidConfigNoTarget;
   }
 
-  // not the best place for this, but we need to set the register allocation
-  // policy after we read the optimization_level metadata from the bitcode
+  llvm::TargetMachine *new_target =
+      (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(),
+                                                 pConfig.getCPU(),
+                                                 pConfig.getFeatureString(),
+                                                 pConfig.getTargetOptions(),
+                                                 pConfig.getRelocationModel(),
+                                                 pConfig.getCodeModel(),
+                                                 pConfig.getOptimizationLevel());
 
-  // Register allocation policy:
+  if (new_target == NULL) {
+    return ((mTarget != NULL) ? kErrSwitchTargetMachine :
+                                kErrCreateTargetMachine);
+  }
+
+  // Replace the old TargetMachine.
+  delete mTarget;
+  mTarget = new_target;
+
+  // Adjust register allocation policy according to the optimization level.
   //  createFastRegisterAllocator: fast but bad quality
   //  createLinearScanRegisterAllocator: not so fast but good quality
-  llvm::RegisterRegAlloc::setDefault
-    ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
-     llvm::createFastRegisterAllocator :
-     llvm::createGreedyRegisterAllocator);
-
-  // Find LLVM Target
-  Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
-  if (hasError())
-    goto on_bcc_compile_error;
-
-#if defined(ARCH_ARM_HAVE_NEON)
-  // Full-precision means we have to disable NEON
-  if (ME.getRSFloatPrecision() == bcinfo::RS_FP_Full) {
-    ExtraFeatures.push_back("-neon");
-    ExtraFeatures.push_back("-neonfp");
-  }
-#endif
-
-  if (!CPU.empty() || !Features.empty() || !ExtraFeatures.empty()) {
-    llvm::SubtargetFeatures F;
-
-    for (std::vector<std::string>::const_iterator
-         I = Features.begin(), E = Features.end(); I != E; I++) {
-      F.AddFeature(*I);
-    }
-
-    for (std::vector<std::string>::const_iterator
-         I = ExtraFeatures.begin(), E = ExtraFeatures.end(); I != E; I++) {
-      F.AddFeature(*I);
-    }
-
-    FeaturesStr = F.getString();
+  if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) {
+    llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator);
+  } else {
+    llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator);
   }
 
-  // Create LLVM Target Machine
-  TM = Target->createTargetMachine(Triple, CPU, FeaturesStr,
-                                   option.TargetOpt,
-                                   option.RelocModelOpt,
-                                   option.CodeModelOpt);
+  // Relax all machine instructions.
+  mTarget->setMCRelaxAll(true);
 
-  if (TM == NULL) {
-    setError("Failed to create target machine implementation for the"
-             " specified triple '" + Triple + "'");
-    goto on_bcc_compile_error;
-  }
-
-  // Get target data from Module
-  TD = new llvm::TargetData(mModule);
-
-  // Read pragma information from MetadataExtractor
-  if (PragmaCount) {
-    ScriptCompiled::PragmaList &PragmaPairs = mpResult->mPragmas;
-    const char **PragmaKeys = ME.getPragmaKeyList();
-    const char **PragmaValues = ME.getPragmaValueList();
-    for (size_t i = 0; i < PragmaCount; i++) {
-      PragmaPairs.push_back(std::make_pair(PragmaKeys[i], PragmaValues[i]));
-    }
-  }
-
-  if (VarCount) {
-    const char **VarNames = ME.getExportVarNameList();
-    for (size_t i = 0; i < VarCount; i++) {
-      VarNameList.push_back(VarNames[i]);
-      ExportSymbols.push_back(VarNames[i]);
-    }
-  }
-
-  if (FuncCount) {
-    const char **FuncNames = ME.getExportFuncNameList();
-    for (size_t i = 0; i < FuncCount; i++) {
-      FuncNameList.push_back(FuncNames[i]);
-      ExportSymbols.push_back(FuncNames[i]);
-    }
-  }
-
-  if (ForEachSigCount) {
-    const char **ForEachNames = ME.getExportForEachNameList();
-    const uint32_t *ForEachSigs = ME.getExportForEachSignatureList();
-    for (size_t i = 0; i < ForEachSigCount; i++) {
-      ForEachFuncList.push_back(std::make_pair(ForEachNames[i],
-                                               ForEachSigs[i]));
-      ForEachExpandList.push_back(std::string(ForEachNames[i]) + ".expand");
-    }
-
-    // Need to wait until ForEachExpandList is fully populated to fill in
-    // exported symbols.
-    for (size_t i = 0; i < ForEachSigCount; i++) {
-      ExportSymbols.push_back(ForEachExpandList[i].c_str());
-    }
-  }
-
-  if (ObjectSlotCount) {
-    ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots;
-    const uint32_t *ObjectSlots = ME.getObjectSlotList();
-    for (size_t i = 0; i < ObjectSlotCount; i++) {
-      objectSlotList.push_back(ObjectSlots[i]);
-    }
-  }
-
-  runInternalPasses(ForEachFuncList);
-
-  // Perform link-time optimization if we have multiple modules
-  if (option.RunLTO) {
-    runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel);
-  }
-
-  // Perform code generation
-  if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) {
-    goto on_bcc_compile_error;
-  }
-
-  if (!option.LoadAfterCompile)
-    return 0;
-
-  // Load the ELF Object
-  {
-    BCCRuntimeSymbolResolver BCCRuntimesResolver;
-    LookupFunctionSymbolResolver<void*> RSSymbolResolver(mpSymbolLookupFn,
-                                                         mpSymbolLookupContext);
-
-    SymbolResolverProxy Resolver;
-    Resolver.chainResolver(BCCRuntimesResolver);
-    Resolver.chainResolver(RSSymbolResolver);
-
-    mRSExecutable =
-        rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
-                           mEmittedELFExecutable.size(),
-                           SymbolResolverProxy::LookupFunction, &Resolver);
-  }
-
-  if (!mRSExecutable) {
-    setError("Fail to load emitted ELF relocatable file");
-    goto on_bcc_compile_error;
-  }
-
-  rsloaderUpdateSectionHeaders(mRSExecutable,
-      (unsigned char*) mEmittedELFExecutable.begin());
-
-  // Once the ELF object has been loaded, populate the various slots for RS
-  // with the appropriate relocated addresses.
-  if (VarCount) {
-    ScriptCompiled::ExportVarList &VarList = mpResult->mExportVars;
-    for (size_t i = 0; i < VarCount; i++) {
-      VarList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
-                                                 VarNameList[i].c_str()));
-    }
-  }
-
-  if (FuncCount) {
-    ScriptCompiled::ExportFuncList &FuncList = mpResult->mExportFuncs;
-    for (size_t i = 0; i < FuncCount; i++) {
-      FuncList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
-                                                  FuncNameList[i].c_str()));
-    }
-  }
-
-  if (ForEachSigCount) {
-    ScriptCompiled::ExportForEachList &ForEachList = mpResult->mExportForEach;
-    for (size_t i = 0; i < ForEachSigCount; i++) {
-      ForEachList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
-          ForEachExpandList[i].c_str()));
-    }
-  }
-
-#if DEBUG_MC_DISASSEMBLER
-  {
-    // Get MC codegen emitted function name list
-    size_t func_list_size = rsloaderGetFuncCount(mRSExecutable);
-    std::vector<char const *> func_list(func_list_size, NULL);
-    rsloaderGetFuncNameList(mRSExecutable, func_list_size, &*func_list.begin());
-
-    // Disassemble each function
-    for (size_t i = 0; i < func_list_size; ++i) {
-      void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]);
-      if (func) {
-        size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]);
-        Disassemble(DEBUG_MC_DISASSEMBLER_FILE,
-                    Target, TM, func_list[i], (unsigned char const *)func, size);
-      }
-    }
-  }
-#endif
-
-on_bcc_compile_error:
-  // ALOGE("on_bcc_compiler_error");
-  if (TD) {
-    delete TD;
-  }
-
-  if (TM) {
-    delete TM;
-  }
-
-  if (mError.empty()) {
-    return 0;
-  }
-
-  // ALOGE(getErrorMessage());
-  return 1;
+  return kSuccess;
 }
 
+Compiler::~Compiler() {
+  delete mTarget;
+}
 
-int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) {
-  // Decorate mEmittedELFExecutable with formatted ostream
-  llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable);
+enum Compiler::ErrorCode Compiler::runLTO(Script &pScript) {
+  llvm::TargetData *target_data = NULL;
 
-  // Relax all machine instructions
-  TM->setMCRelaxAll(/* RelaxAll= */ true);
+  // Pass manager for link-time optimization
+  llvm::PassManager lto_passes;
 
-  // Create MC code generation pass manager
-  llvm::PassManager MCCodeGenPasses;
-
-  // Add TargetData to MC code generation pass manager
-  MCCodeGenPasses.add(TD);
-
-  // Add MC code generation passes to pass manager
-  llvm::MCContext *Ctx = NULL;
-  if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) {
-    setError("Fail to add passes to emit file");
-    return 1;
+  // Prepare TargetData target data from Module
+  target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData());
+  if (target_data == NULL) {
+    return kErrTargetDataNoMemory;
   }
 
-  MCCodeGenPasses.run(*mModule);
-  OutSVOS.flush();
-  return 0;
-}
+  // Add TargetData to the pass manager.
+  lto_passes.add(target_data);
 
-int Compiler::runInternalPasses(RSInfo::ExportForeachFuncListTy pForEachFuncs) {
-  llvm::PassManager BCCPasses;
-
-  // Expand ForEach on CPU path to reduce launch overhead.
-  BCCPasses.add(createRSForEachExpandPass(pForEachFuncs));
-
-  BCCPasses.run(*mModule);
-
-  return 0;
-}
-
-int Compiler::runLTO(llvm::TargetData *TD,
-                     std::vector<const char*>& ExportSymbols,
-                     llvm::CodeGenOpt::Level OptimizationLevel) {
-  // Note: ExportSymbols is a workaround for getting all exported variable,
-  // function, and kernel names.
-  // We should refine it soon.
-
-  // TODO(logan): Remove this after we have finished the
-  // bccMarkExternalSymbol API.
-
-  // root(), init(), and .rs.dtor() are born to be exported
-  ExportSymbols.push_back("root");
-  ExportSymbols.push_back("init");
-  ExportSymbols.push_back(".rs.dtor");
-
-  // User-defined exporting symbols
-  std::vector<char const *> const &UserDefinedExternalSymbols =
-    mpResult->getUserDefinedExternalSymbols();
-
-  std::copy(UserDefinedExternalSymbols.begin(),
-            UserDefinedExternalSymbols.end(),
-            std::back_inserter(ExportSymbols));
-
-  llvm::PassManager LTOPasses;
-
-  // Add TargetData to LTO passes
-  LTOPasses.add(TD);
+  // Invokde "beforeAddLTOPasses" before adding the first pass.
+  if (!beforeAddLTOPasses(pScript, lto_passes)) {
+    return kErrHookBeforeAddLTOPasses;
+  }
 
   // We now create passes list performing LTO. These are copied from
-  // (including comments) llvm::createStandardLTOPasses().
-  // Only a subset of these LTO passes are enabled in optimization level 0
-  // as they interfere with interactive debugging.
-  // FIXME: figure out which passes (if any) makes sense for levels 1 and 2
-
-  if (OptimizationLevel != llvm::CodeGenOpt::None) {
-    // Internalize all other symbols not listed in ExportSymbols
-    LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
-
+  // (including comments) llvm::PassManagerBuilder::populateLTOPassManager().
+  // Only a subset of these LTO passes are enabled in optimization level 0 as
+  // they interfere with interactive debugging.
+  //
+  // FIXME: Figure out which passes (if any) makes sense for levels 1 and 2.
+  //if ( != llvm::CodeGenOpt::None) {
+  if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
+    lto_passes.add(llvm::createGlobalOptimizerPass());
+    lto_passes.add(llvm::createConstantMergePass());
+  } else {
     // Propagate constants at call sites into the functions they call. This
     // opens opportunities for globalopt (and inlining) by substituting
     // function pointers passed as arguments to direct uses of functions.
-    LTOPasses.add(llvm::createIPSCCPPass());
+    lto_passes.add(llvm::createIPSCCPPass());
 
     // Now that we internalized some globals, see if we can hack on them!
-    LTOPasses.add(llvm::createGlobalOptimizerPass());
+    lto_passes.add(llvm::createGlobalOptimizerPass());
 
     // Linking modules together can lead to duplicated global constants, only
     // keep one copy of each constant...
-    LTOPasses.add(llvm::createConstantMergePass());
+    lto_passes.add(llvm::createConstantMergePass());
 
     // Remove unused arguments from functions...
-    LTOPasses.add(llvm::createDeadArgEliminationPass());
+    lto_passes.add(llvm::createDeadArgEliminationPass());
 
     // Reduce the code after globalopt and ipsccp. Both can open up
     // significant simplification opportunities, and both can propagate
     // functions through function pointers. When this happens, we often have
     // to resolve varargs calls, etc, so let instcombine do this.
-    LTOPasses.add(llvm::createInstructionCombiningPass());
+    lto_passes.add(llvm::createInstructionCombiningPass());
 
     // Inline small functions
-    LTOPasses.add(llvm::createFunctionInliningPass());
+    lto_passes.add(llvm::createFunctionInliningPass());
 
     // Remove dead EH info.
-    LTOPasses.add(llvm::createPruneEHPass());
+    lto_passes.add(llvm::createPruneEHPass());
 
     // Internalize the globals again after inlining
-    LTOPasses.add(llvm::createGlobalOptimizerPass());
+    lto_passes.add(llvm::createGlobalOptimizerPass());
 
     // Remove dead functions.
-    LTOPasses.add(llvm::createGlobalDCEPass());
+    lto_passes.add(llvm::createGlobalDCEPass());
 
     // If we didn't decide to inline a function, check to see if we can
     // transform it to pass arguments by value instead of by reference.
-    LTOPasses.add(llvm::createArgumentPromotionPass());
+    lto_passes.add(llvm::createArgumentPromotionPass());
 
     // The IPO passes may leave cruft around.  Clean up after them.
-    LTOPasses.add(llvm::createInstructionCombiningPass());
-    LTOPasses.add(llvm::createJumpThreadingPass());
+    lto_passes.add(llvm::createInstructionCombiningPass());
+    lto_passes.add(llvm::createJumpThreadingPass());
 
     // Break up allocas
-    LTOPasses.add(llvm::createScalarReplAggregatesPass());
+    lto_passes.add(llvm::createScalarReplAggregatesPass());
 
     // Run a few AA driven optimizations here and now, to cleanup the code.
-    LTOPasses.add(llvm::createFunctionAttrsPass());  // Add nocapture.
-    LTOPasses.add(llvm::createGlobalsModRefPass());  // IP alias analysis.
+    lto_passes.add(llvm::createFunctionAttrsPass());  // Add nocapture.
+    lto_passes.add(llvm::createGlobalsModRefPass());  // IP alias analysis.
 
     // Hoist loop invariants.
-    LTOPasses.add(llvm::createLICMPass());
+    lto_passes.add(llvm::createLICMPass());
 
     // Remove redundancies.
-    LTOPasses.add(llvm::createGVNPass());
+    lto_passes.add(llvm::createGVNPass());
 
     // Remove dead memcpys.
-    LTOPasses.add(llvm::createMemCpyOptPass());
+    lto_passes.add(llvm::createMemCpyOptPass());
 
     // Nuke dead stores.
-    LTOPasses.add(llvm::createDeadStoreEliminationPass());
+    lto_passes.add(llvm::createDeadStoreEliminationPass());
 
     // Cleanup and simplify the code after the scalar optimizations.
-    LTOPasses.add(llvm::createInstructionCombiningPass());
+    lto_passes.add(llvm::createInstructionCombiningPass());
 
-    LTOPasses.add(llvm::createJumpThreadingPass());
+    lto_passes.add(llvm::createJumpThreadingPass());
 
     // Delete basic blocks, which optimization passes may have killed.
-    LTOPasses.add(llvm::createCFGSimplificationPass());
+    lto_passes.add(llvm::createCFGSimplificationPass());
 
     // Now that we have optimized the program, discard unreachable functions.
-    LTOPasses.add(llvm::createGlobalDCEPass());
-
-  } else {
-    LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
-    LTOPasses.add(llvm::createGlobalOptimizerPass());
-    LTOPasses.add(llvm::createConstantMergePass());
+    lto_passes.add(llvm::createGlobalDCEPass());
   }
 
-  LTOPasses.run(*mModule);
-
-#if ANDROID_ENGINEERING_BUILD
-  if (0 != gDebugDumpDirectory) {
-    std::string errs;
-    std::string Filename(gDebugDumpDirectory);
-    Filename += "/post-lto-module.ll";
-    llvm::raw_fd_ostream FS(Filename.c_str(), errs);
-    mModule->print(FS, 0);
-    FS.close();
+  // Invokde "afterAddLTOPasses" after pass manager finished its
+  // construction.
+  if (!afterAddLTOPasses(pScript, lto_passes)) {
+    return kErrHookAfterAddLTOPasses;
   }
-#endif
 
-  return 0;
+  // Invokde "beforeExecuteLTOPasses" before executing the passes.
+  if (!beforeExecuteLTOPasses(pScript, lto_passes)) {
+    return kErrHookBeforeExecuteLTOPasses;
+  }
+
+  lto_passes.run(pScript.getSource().getModule());
+
+  // Invokde "afterExecuteLTOPasses" before returning.
+  if (!afterExecuteLTOPasses(pScript)) {
+    return kErrHookAfterExecuteLTOPasses;
+  }
+
+  return kSuccess;
 }
 
+enum Compiler::ErrorCode Compiler::runCodeGen(Script &pScript,
+                                              llvm::raw_ostream &pResult) {
+  llvm::TargetData *target_data;
+  llvm::MCContext *mc_context = NULL;
 
-void *Compiler::getSymbolAddress(char const *name) {
-  return rsloaderGetSymbolAddress(mRSExecutable, name);
+  // Create pass manager for MC code generation.
+  llvm::PassManager codegen_passes;
+
+  // Prepare TargetData target data from Module
+  target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData());
+  if (target_data == NULL) {
+    return kErrTargetDataNoMemory;
+  }
+
+  // Add TargetData to the pass manager.
+  codegen_passes.add(target_data);
+
+  // Invokde "beforeAddCodeGenPasses" before adding the first pass.
+  if (!beforeAddCodeGenPasses(pScript, codegen_passes)) {
+    return kErrHookBeforeAddCodeGenPasses;
+  }
+
+  // Add passes to the pass manager to emit machine code through MC layer.
+  if (mTarget->addPassesToEmitMC(codegen_passes, mc_context, pResult,
+                                 /* DisableVerify */false)) {
+    return kPrepareCodeGenPass;
+  }
+
+  // Invokde "afterAddCodeGenPasses" after pass manager finished its
+  // construction.
+  if (!afterAddCodeGenPasses(pScript, codegen_passes)) {
+    return kErrHookAfterAddCodeGenPasses;
+  }
+
+  // Invokde "beforeExecuteCodeGenPasses" before executing the passes.
+  if (!beforeExecuteCodeGenPasses(pScript, codegen_passes)) {
+    return kErrHookBeforeExecuteCodeGenPasses;
+  }
+
+  // Execute the pass.
+  codegen_passes.run(pScript.getSource().getModule());
+
+  // Invokde "afterExecuteCodeGenPasses" before returning.
+  if (!afterExecuteCodeGenPasses(pScript)) {
+    return kErrHookAfterExecuteCodeGenPasses;
+  }
+
+  return kSuccess;
 }
 
-Compiler::~Compiler() {
-  rsloaderDisposeExec(mRSExecutable);
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+                                           llvm::raw_ostream &pResult) {
+  llvm::Module &module = pScript.getSource().getModule();
+  enum ErrorCode err;
 
-  // llvm::llvm_shutdown();
+  if (mTarget == NULL) {
+    return kErrNoTargetMachine;
+  }
+
+  // Materialize the bitcode module.
+  if (module.getMaterializer() != NULL) {
+    std::string error;
+    // A module with non-null materializer means that it is a lazy-load module.
+    // Materialize it now via invoking MaterializeAllPermanently(). This
+    // function returns false when the materialization is successful.
+    if (module.MaterializeAllPermanently(&error)) {
+      ALOGE("Failed to materialize the module `%s'! (%s)",
+            module.getModuleIdentifier().c_str(), error.c_str());
+      return kErrMaterialization;
+    }
+  }
+
+  if (mEnableLTO && ((err = runLTO(pScript)) != kSuccess)) {
+    return err;
+  }
+
+  if ((err = runCodeGen(pScript, pResult)) != kSuccess) {
+    return err;
+  }
+
+  return kSuccess;
 }
 
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+                                           OutputFile &pResult) {
+  // Check the state of the specified output file.
+  if (pResult.hasError()) {
+    return kErrInvalidOutputFileState;
+  }
 
-}  // namespace bcc
+  // Open the output file decorated in llvm::raw_ostream.
+  llvm::raw_ostream *out = pResult.dup();
+  if (out == NULL) {
+    return kErrPrepareOutput;
+  }
+
+  // Delegate the request.
+  enum Compiler::ErrorCode err = compile(pScript, *out);
+
+  // Close the output before return.
+  delete out;
+
+  return err;
+}
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index f0e75d1..5e37925 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -14,153 +14,130 @@
  * limitations under the License.
  */
 
-#ifndef BCC_COMPILER_H
-#define BCC_COMPILER_H
-
-#include <bcc/bcc.h>
-
-#include <Config.h>
-
-#include "librsloader.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Target/TargetMachine.h"
-
-#include <stddef.h>
-
-#include <list>
-#include <string>
-#include <vector>
-#include <utility>
-
-#include "RSInfo.h"
-
+#ifndef BCC_EXECUTION_ENGINE_COMPILER_H
+#define BCC_EXECUTION_ENGINE_COMPILER_H
 
 namespace llvm {
-  class Module;
-  class NamedMDNode;
-  class TargetData;
-}
 
+class raw_ostream;
+class PassManager;
+class TargetData;
+class TargetMachine;
+
+} // end namespace llvm
 
 namespace bcc {
-  class ScriptCompiled;
-  struct CompilerOption;
 
-  class Compiler {
-  private:
-    //////////////////////////////////////////////////////////////////////////
-    // The variable section below (e.g., Triple, CodeGenOptLevel)
-    // is initialized in GlobalInitialization()
-    //
-    static bool GlobalInitialized;
+class CompilerConfig;
+class OutputFile;
+class Script;
 
-    // If given, this will be the name of the target triple to compile for.
-    // If not given, the initial values defined in this file will be used.
-    static std::string Triple;
-    static llvm::Triple::ArchType ArchType;
+//===----------------------------------------------------------------------===//
+// Design of Compiler
+//===----------------------------------------------------------------------===//
+// 1. A compiler instance can be constructed provided an "initial config."
+// 2. A compiler can later be re-configured using config().
+// 3. Once config() is invoked, it'll re-create TargetMachine instance (i.e.,
+//    mTarget) according to the configuration supplied. TargetMachine instance
+//    is *shared* across the different calls to compile() before the next call
+//    to config().
+// 4. Once a compiler instance is created, you can use the compile() service
+//    to compile the file over and over again. Each call uses TargetMachine
+//    instance to construct the compilation passes.
+class Compiler {
+public:
+  enum ErrorCode {
+    kSuccess,
 
-    static llvm::CodeGenOpt::Level CodeGenOptLevel;
+    kInvalidConfigNoTarget,
+    kErrCreateTargetMachine,
+    kErrSwitchTargetMachine,
+    kErrNoTargetMachine,
+    kErrTargetDataNoMemory,
+    kErrMaterialization,
+    kErrInvalidOutputFileState,
+    kErrPrepareOutput,
+    kPrepareCodeGenPass,
 
-    // End of section of GlobalInitializing variables
-    /////////////////////////////////////////////////////////////////////////
-    // If given, the name of the target CPU to generate code for.
-    static std::string CPU;
+    kErrHookBeforeAddLTOPasses,
+    kErrHookAfterAddLTOPasses,
+    kErrHookBeforeExecuteLTOPasses,
+    kErrHookAfterExecuteLTOPasses,
 
-    // The list of target specific features to enable or disable -- this should
-    // be a list of strings starting with '+' (enable) or '-' (disable).
-    static std::vector<std::string> Features;
+    kErrHookBeforeAddCodeGenPasses,
+    kErrHookAfterAddCodeGenPasses,
+    kErrHookBeforeExecuteCodeGenPasses,
+    kErrHookAfterExecuteCodeGenPasses,
 
-    static void LLVMErrorHandler(void *UserData, const std::string &Message);
+    kMaxErrorCode,
+  };
 
-    friend class CodeEmitter;
-    friend class CodeMemoryManager;
+  static const char *GetErrorString(enum ErrorCode pErrCode);
 
-  private:
-    ScriptCompiled *mpResult;
+private:
+  llvm::TargetMachine *mTarget;
+  // LTO is enabled by default.
+  bool mEnableLTO;
 
-    std::string mError;
+  enum ErrorCode runLTO(Script &pScript);
+  enum ErrorCode runCodeGen(Script &pScript, llvm::raw_ostream &pResult);
 
-    // Compilation buffer for MC
-    llvm::SmallVector<char, 1024> mEmittedELFExecutable;
+public:
+  Compiler();
+  Compiler(const CompilerConfig &pConfig);
 
-    // Loaded and relocated executable
-    RSExecRef mRSExecutable;
+  enum ErrorCode config(const CompilerConfig &pConfig);
 
-    BCCSymbolLookupFn mpSymbolLookupFn;
-    void *mpSymbolLookupContext;
+  // Compile a script and output the result to a LLVM stream.
+  enum ErrorCode compile(Script &pScript, llvm::raw_ostream &pResult);
 
-    llvm::Module *mModule;
+  // Compile a script and output the result to a file.
+  enum ErrorCode compile(Script &pScript, OutputFile &pResult);
 
-  public:
-    Compiler(ScriptCompiled *result);
+  void enableLTO(bool pEnable = true)
+  { mEnableLTO = pEnable; }
 
-    static void GlobalInitialization();
+  virtual ~Compiler();
 
-    static std::string const &getTargetTriple() {
-      return Triple;
-    }
+protected:
+  //===--------------------------------------------------------------------===//
+  // Plugin callbacks for sub-class.
+  //===--------------------------------------------------------------------===//
+  // Called before adding first pass to code-generation passes.
+  virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
+  { return true; }
 
-    static llvm::Triple::ArchType getTargetArchType() {
-      return ArchType;
-    }
+  // Called after adding last pass to code-generation passes.
+  virtual bool afterAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
+  { return true; }
 
-    void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
-      mpSymbolLookupFn = pFn;
-      mpSymbolLookupContext = pContext;
-    }
+  // Called before executing code-generation passes.
+  virtual bool beforeExecuteLTOPasses(Script &pScript,
+                                          llvm::PassManager &pPM)
+  { return true; }
 
-    void *getSymbolAddress(char const *name);
+  // Called after executing code-generation passes.
+  virtual bool afterExecuteLTOPasses(Script &pScript)
+  { return true; }
 
-    const llvm::SmallVector<char, 1024> &getELF() const {
-      return mEmittedELFExecutable;
-    }
+  // Called before adding first pass to code-generation passes.
+  virtual bool beforeAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
+  { return true; }
 
-    int readModule(llvm::Module &pModule);
+  // Called after adding last pass to code-generation passes.
+  virtual bool afterAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
+  { return true; }
 
-    int compile(const CompilerOption &option);
+  // Called before executing code-generation passes.
+  virtual bool beforeExecuteCodeGenPasses(Script &pScript,
+                                          llvm::PassManager &pPM)
+  { return true; }
 
-    char const *getErrorMessage() {
-      return mError.c_str();
-    }
+  // Called after executing code-generation passes.
+  virtual bool afterExecuteCodeGenPasses(Script &pScript)
+  { return true; }
+};
 
-    const llvm::Module *getModule() const {
-      return mModule;
-    }
+} // end namespace bcc
 
-    ~Compiler();
-
-  private:
-
-    int runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
-                   llvm::NamedMDNode const *ExportVarMetadata,
-                   llvm::NamedMDNode const *ExportFuncMetadata);
-
-    int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);
-
-    int runInternalPasses(RSInfo::ExportForeachFuncListTy pForEachFuncs);
-
-    int runLTO(llvm::TargetData *TD,
-               std::vector<const char*>& ExportSymbols,
-               llvm::CodeGenOpt::Level OptimizationLevel);
-
-    bool hasError() const {
-      return !mError.empty();
-    }
-
-    void setError(const char *Error) {
-      mError.assign(Error);  // Copying
-    }
-
-    void setError(const std::string &Error) {
-      mError = Error;
-    }
-
-  };  // End of class Compiler
-
-} // namespace bcc
-
-#endif // BCC_COMPILER_H
+#endif // BCC_EXECUTION_ENGINE_COMPILER_H
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
deleted file mode 100644
index f7c1e50..0000000
--- a/lib/ExecutionEngine/CompilerOption.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 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 BCC_COMPILER_OPTION_H
-#define BCC_COMPILER_OPTION_H
-
-#include "Config.h"
-#include "Compiler.h"
-
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Support/CodeGen.h"
-
-namespace bcc {
-
-class CompilerOption {
- public:
-  // Constructor setup "default configuration". The "default configuration"
-  // here means the configuration for running RenderScript (more specifically,
-  // one can declare a CompilerOption object (call default constructor) and then
-  // pass to the Compiler::compiler() without any modification for RenderScript,
-  // see Script::prepareExecutable(...)).
-  //
-  // Must be invoked after calling Compiler::GlobalInitialization() at least once.
-  //
-  CompilerOption() {
-    //-- Setup options to llvm::TargetMachine --//
-
-    //-- Setup Frame Pointer Elimination Optimization --//
-#if defined(__HOST__)
-    // Disable frame pointer elimination optimization for X86_64 and X86
-    if ((Compiler::getTargetArchType() == llvm::Triple::x86_64) ||
-        (Compiler::getTargetArchType() == llvm::Triple::x86)) {
-      TargetOpt.NoFramePointerElim = true;
-    } else {
-      TargetOpt.NoFramePointerElim = false;
-    }
-#elif defined(DEFAULT_X86_64_CODEGEN)
-    TargetOpt.NoFramePointerElim = true;
-#elif defined(DEFAULT_X86_CODEGEN)
-    TargetOpt.NoFramePointerElim = true;
-#else
-    TargetOpt.NoFramePointerElim = false;
-#endif
-
-    // Use hardfloat ABI
-    //
-    // TODO(all): Need to detect the CPU capability and decide whether to use
-    // softfp. To use softfp, change following 2 lines to
-    //
-    // options.FloatABIType = llvm::FloatABI::Soft;
-    // options.UseSoftFloat = true;
-    TargetOpt.FloatABIType = llvm::FloatABI::Soft;
-    TargetOpt.UseSoftFloat = false;
-
-    //-- Setup relocation model  --//
-    RelocModelOpt = llvm::Reloc::Static;
-
-    //-- Setup code model  --//
-#if defined(__HOST__)
-    // Data address in X86_64 architecture may reside in a far-away place
-    if (Compiler::getTargetArchType() == llvm::Triple::x86_64) {
-      CodeModelOpt = llvm::CodeModel::Medium;
-    } else {
-      CodeModelOpt = llvm::CodeModel::Small;
-    }
-#elif defined(DEFAULT_X86_64_CODEGEN)
-    CodeModelOpt = llvm::CodeModel::Medium;
-#else
-    CodeModelOpt = llvm::CodeModel::Small;
-#endif
-
-    //-- Run LTO passes --//
-    RunLTO = true;
-
-    //-- Load the result object after successful compilation  --//
-    LoadAfterCompile = true;
-  }
-
-  llvm::TargetOptions TargetOpt;
-  llvm::CodeModel::Model CodeModelOpt;
-  llvm::Reloc::Model RelocModelOpt;
-  bool RunLTO;
-  bool LoadAfterCompile;
-
-};
-
-} // namespace bcc
-
-#endif  // BCC_COMPILER_OPTION_H
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
deleted file mode 100644
index dc4ba92..0000000
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ /dev/null
@@ -1,478 +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 "MCCacheReader.h"
-
-#include "BCCRuntimeSymbolResolver.h"
-#include "DebugHelper.h"
-#include "InputFile.h"
-#include "ScriptCached.h"
-#include "SymbolResolverProxy.h"
-#include "SymbolResolvers.h"
-
-#include <bcc/bcc_mccache.h>
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <utility>
-#include <vector>
-
-#include <new>
-
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-namespace bcc {
-
-MCCacheReader::~MCCacheReader() {
-  if (mpHeader) { free(mpHeader); }
-  if (mpCachedDependTable) { free(mpCachedDependTable); }
-  if (mpPragmaList) { free(mpPragmaList); }
-  if (mpVarNameList) { free(mpVarNameList); }
-  if (mpFuncNameList) { free(mpFuncNameList); }
-}
-
-ScriptCached *MCCacheReader::readCacheFile(InputFile &objFile,
-                                           InputFile &infoFile,
-                                           Script *S) {
-  bool result = checkCacheFile(objFile, infoFile, S)
-             && readPragmaList()
-             && readObjectSlotList()
-             && readObjFile()
-             && readVarNameList()
-             && readFuncNameList()
-             && readForEachNameList()
-             //&& relocate()
-             ;
-
-  return result ? mpResult.take() : NULL;
-}
-
-bool MCCacheReader::checkCacheFile(InputFile &objFile,
-                                   InputFile &infoFile,
-                                   Script *S) {
-  // Check file handle
-  if (objFile.hasError() || infoFile.hasError()) {
-    return false;
-  }
-
-  mObjFile = &objFile;
-  mInfoFile = &infoFile;
-
-  // Allocate ScriptCached object
-  mpResult.reset(new (nothrow) ScriptCached(S));
-
-  if (!mpResult) {
-    ALOGE("Unable to allocate ScriptCached object.\n");
-    return false;
-  }
-
-  bool result = checkFileSize()
-             && readHeader()
-             && checkHeader()
-             && checkMachineIntType()
-             && checkSectionOffsetAndSize()
-             && readStringPool()
-             && checkStringPool()
-             && readDependencyTable()
-             && checkDependency()
-             ;
-
-  return result;
-}
-
-
-bool MCCacheReader::checkFileSize() {
-  struct stat stfile;
-  if (::stat(mInfoFile->getName().c_str(), &stfile) < 0) {
-    ALOGE("Unable to stat cache file.\n");
-    return false;
-  }
-
-  mInfoFileSize = stfile.st_size;
-
-  if (mInfoFileSize < (off_t)sizeof(MCO_Header)) {
-    ALOGE("Cache file is too small to be correct.\n");
-    return false;
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::readHeader() {
-  if (mInfoFile->seek(0) != 0) {
-    ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
-    return false;
-  }
-
-  mpHeader = (MCO_Header *)malloc(sizeof(MCO_Header));
-  if (!mpHeader) {
-    ALOGE("Unable to allocate for cache header.\n");
-    return false;
-  }
-
-  if (mInfoFile->read(reinterpret_cast<char *>(mpHeader), sizeof(MCO_Header)) !=
-      (ssize_t)sizeof(MCO_Header)) {
-    ALOGE("Unable to read cache header.\n");
-    return false;
-  }
-
-  // Dirty hack for libRS.
-  // TODO(all): This should be removed in the future.
-  if (mpHeader->libRS_threadable) {
-    mpResult->mLibRSThreadable = true;
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::checkHeader() {
-  if (memcmp(mpHeader->magic, MCO_MAGIC, 4) != 0) {
-    ALOGE("Bad magic word\n");
-    return false;
-  }
-
-  if (memcmp(mpHeader->version, MCO_VERSION, 4) != 0) {
-    mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
-    ALOGI("Cache file format version mismatch: now %s cached %s\n",
-         MCO_VERSION, mpHeader->version);
-    return false;
-  }
-  return true;
-}
-
-
-bool MCCacheReader::checkMachineIntType() {
-  uint32_t number = 0x00000001;
-
-  bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
-  if ((isLittleEndian && mpHeader->endianness != 'e') ||
-      (!isLittleEndian && mpHeader->endianness != 'E')) {
-    ALOGE("Machine endianness mismatch.\n");
-    return false;
-  }
-
-  if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
-      (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
-      (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
-    ALOGE("Machine integer size mismatch.\n");
-    return false;
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::checkSectionOffsetAndSize() {
-#define CHECK_SECTION_OFFSET(NAME)                                          \
-  do {                                                                      \
-    off_t offset = mpHeader-> NAME##_offset;                                \
-    off_t size = (off_t)mpHeader-> NAME##_size;                             \
-                                                                            \
-    if (mInfoFileSize < offset || mInfoFileSize < offset + size) {          \
-      ALOGE(#NAME " section overflow.\n");                                   \
-      return false;                                                         \
-    }                                                                       \
-                                                                            \
-    if (offset % sizeof(int) != 0) {                                        \
-      ALOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int));        \
-      return false;                                                         \
-    }                                                                       \
-                                                                            \
-    if (size < static_cast<off_t>(sizeof(size_t))) {                        \
-      ALOGE(#NAME " size is too small to be correct.\n");                    \
-      return false;                                                         \
-    }                                                                       \
-  } while (0)
-
-  CHECK_SECTION_OFFSET(str_pool);
-  CHECK_SECTION_OFFSET(depend_tab);
-  //CHECK_SECTION_OFFSET(reloc_tab);
-  CHECK_SECTION_OFFSET(pragma_list);
-
-#undef CHECK_SECTION_OFFSET
-
-  return true;
-}
-
-
-#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME)          \
-  TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size);                 \
-                                                                            \
-  if (!NAME##_raw) {                                                        \
-    ALOGE("Unable to allocate for " #NAME "\n");                             \
-    return false;                                                           \
-  }                                                                         \
-                                                                            \
-  /* We have to ensure that some one will deallocate NAME##_raw */          \
-  AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
-                                                                            \
-  if (mInfoFile->seek(mpHeader->NAME##_offset) == -1) {                     \
-    ALOGE("Unable to seek to " #NAME " section\n");                          \
-    return false;                                                           \
-  }                                                                         \
-                                                                            \
-  if (mInfoFile->read(reinterpret_cast<char *>(NAME##_raw),                 \
-                  mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
-  {                                                                         \
-    ALOGE("Unable to read " #NAME ".\n");                                    \
-    return false;                                                           \
-  }
-
-
-bool MCCacheReader::readStringPool() {
-  CACHE_READER_READ_SECTION(MCO_StringPool,
-                            mpResult->mpStringPoolRaw, str_pool);
-
-  char *str_base = reinterpret_cast<char *>(str_pool_raw);
-
-  vector<char const *> &pool = mpResult->mStringPool;
-  for (size_t i = 0; i < str_pool_raw->count; ++i) {
-    char *str = str_base + str_pool_raw->list[i].offset;
-    pool.push_back(str);
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::checkStringPool() {
-  MCO_StringPool *poolR = mpResult->mpStringPoolRaw;
-  vector<char const *> &pool = mpResult->mStringPool;
-
-  // Ensure that every c-style string is ended with '\0'
-  for (size_t i = 0; i < poolR->count; ++i) {
-    if (pool[i][poolR->list[i].length] != '\0') {
-      ALOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::readDependencyTable() {
-  CACHE_READER_READ_SECTION(MCO_DependencyTable, mpCachedDependTable,
-                            depend_tab);
-  return true;
-}
-
-
-bool MCCacheReader::checkDependency() {
-  if (mDependencies.size() != mpCachedDependTable->count) {
-    ALOGE("Dependencies count mismatch. (%lu vs %lu)\n",
-         (unsigned long)mDependencies.size(),
-         (unsigned long)mpCachedDependTable->count);
-    return false;
-  }
-
-  vector<char const *> &strPool = mpResult->mStringPool;
-  map<string, unsigned char const *>::iterator dep;
-
-  dep = mDependencies.begin();
-  for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
-    string const &depName = dep->first;
-    unsigned char const *depSHA1 = dep->second;
-
-    MCO_Dependency *depCached =&mpCachedDependTable->table[i];
-    char const *depCachedName = strPool[depCached->res_name_strp_index];
-    //uint32_t depCachedType = depCached->res_type;
-    unsigned char const *depCachedSHA1 = depCached->sha1;
-
-    if (depName != depCachedName) {
-      ALOGE("Cache dependency name mismatch:\n");
-      ALOGE("  given:  %s\n", depName.c_str());
-      ALOGE("  cached: %s\n", depCachedName);
-
-      return false;
-    }
-
-    if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
-      ALOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
-
-#define PRINT_SHA1(PREFIX, X, POSTFIX) \
-      ALOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
-                  "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
-           X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
-           X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
-
-      PRINT_SHA1("  given:  ", depSHA1, "\n");
-      PRINT_SHA1("  cached: ", depCachedSHA1, "\n");
-
-#undef PRINT_SHA1
-
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool MCCacheReader::readVarNameList() {
-  CACHE_READER_READ_SECTION(MCO_String_Ptr, mpVarNameList, export_var_name_list);
-  vector<char const *> const &strPool = mpResult->mStringPool;
-
-  mpResult->mpExportVars = (MCO_ExportVarList*)
-                            malloc(sizeof(size_t) +
-                                   sizeof(void*) * export_var_name_list_raw->count);
-  if (!mpResult->mpExportVars) {
-    ALOGE("Unable to allocate for mpExportVars\n");
-    return false;
-  }
-  mpResult->mpExportVars->count = export_var_name_list_raw->count;
-
-  for (size_t i = 0; i < export_var_name_list_raw->count; ++i) {
-    mpResult->mpExportVars->cached_addr_list[i] =
-      rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_var_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
-    ALOGD("Get symbol address: %s -> %p",
-      strPool[export_var_name_list_raw->strp_indexs[i]], mpResult->mpExportVars->cached_addr_list[i]);
-#endif
-  }
-  return true;
-}
-
-bool MCCacheReader::readFuncNameList() {
-  CACHE_READER_READ_SECTION(MCO_String_Ptr, mpFuncNameList, export_func_name_list);
-  vector<char const *> const &strPool = mpResult->mStringPool;
-
-  mpResult->mpExportFuncs = (MCO_ExportFuncList*)
-                            malloc(sizeof(size_t) +
-                                   sizeof(void*) * export_func_name_list_raw->count);
-  if (!mpResult->mpExportFuncs) {
-    ALOGE("Unable to allocate for mpExportFuncs\n");
-    return false;
-  }
-  mpResult->mpExportFuncs->count = export_func_name_list_raw->count;
-
-  for (size_t i = 0; i < export_func_name_list_raw->count; ++i) {
-    mpResult->mpExportFuncs->cached_addr_list[i] =
-      rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_func_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
-    ALOGD("Get function address: %s -> %p",
-      strPool[export_func_name_list_raw->strp_indexs[i]], mpResult->mpExportFuncs->cached_addr_list[i]);
-#endif
-  }
-  return true;
-}
-
-bool MCCacheReader::readForEachNameList() {
-  CACHE_READER_READ_SECTION(MCO_String_Ptr, mpForEachNameList, export_foreach_name_list);
-  vector<char const *> const &strPool = mpResult->mStringPool;
-
-  mpResult->mpExportForEach = (MCO_ExportForEachList*)
-                              malloc(sizeof(size_t) +
-                                     sizeof(void*) * export_foreach_name_list_raw->count);
-  if (!mpResult->mpExportForEach) {
-    ALOGE("Unable to allocate for mpExportForEach\n");
-    return false;
-  }
-  mpResult->mpExportForEach->count = export_foreach_name_list_raw->count;
-
-  for (size_t i = 0; i < export_foreach_name_list_raw->count; ++i) {
-    mpResult->mpExportForEach->cached_addr_list[i] =
-      rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_foreach_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
-    ALOGE("Get foreach function address: %s -> %p",
-      strPool[export_foreach_name_list_raw->strp_indexs[i]], mpResult->mpExportForEach->cached_addr_list[i]);
-#endif
-  }
-  return true;
-}
-
-bool MCCacheReader::readPragmaList() {
-  CACHE_READER_READ_SECTION(MCO_PragmaList, mpPragmaList, pragma_list);
-
-  vector<char const *> const &strPool = mpResult->mStringPool;
-  ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
-
-  for (size_t i = 0; i < pragma_list_raw->count; ++i) {
-    MCO_Pragma *pragma = &pragma_list_raw->list[i];
-    pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
-                                strPool[pragma->value_strp_index]));
-  }
-
-  return true;
-}
-
-
-bool MCCacheReader::readObjectSlotList() {
-  CACHE_READER_READ_SECTION(MCO_ObjectSlotList,
-                            mpResult->mpObjectSlotList, object_slot_list);
-  return true;
-}
-
-bool MCCacheReader::readObjFile() {
-  if (mpResult->mCachedELFExecutable.size() != 0) {
-    ALOGE("Attempted to read cached object into a non-empty script");
-    return false;
-  }
-  char readBuffer[1024];
-  int readSize;
-  while ((readSize = mObjFile->read(readBuffer, 1024)) > 0) {
-    mpResult->mCachedELFExecutable.append(readBuffer, readBuffer + readSize);
-  }
-  if (readSize != 0) {
-    ALOGE("Read file Error");
-    return false;
-  }
-  ALOGD("Read object file size %d", (int)mpResult->mCachedELFExecutable.size());
-
-  BCCRuntimeSymbolResolver bccRuntimesResolver;
-  LookupFunctionSymbolResolver<void *> rsSymbolResolver(mpSymbolLookupFn,
-                                                        mpSymbolLookupContext);
-
-  SymbolResolverProxy resolver;
-  resolver.chainResolver(bccRuntimesResolver);
-  resolver.chainResolver(rsSymbolResolver);
-
-  mpResult->mRSExecutable =
-  rsloaderCreateExec((unsigned char *)&*(mpResult->mCachedELFExecutable.begin()),
-                     mpResult->mCachedELFExecutable.size(),
-                     SymbolResolverProxy::LookupFunction, &resolver);
-
-  // Point ELF section headers to location of executable code, otherwise
-  // execution through GDB stops unexpectedly as GDB translates breakpoints
-  // in JITted code incorrectly (and complains about being unable to insert
-  // breakpoint at an invalid address)
-  rsloaderUpdateSectionHeaders(mpResult->mRSExecutable,
-    (unsigned char*) mpResult->mCachedELFExecutable.begin());
-
-  return true;
-}
-
-#undef CACHE_READER_READ_SECTION
-
-bool MCCacheReader::readRelocationTable() {
-  // TODO(logan): Not finished.
-  return true;
-}
-
-
-bool MCCacheReader::relocate() {
-  return true;
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
deleted file mode 100644
index e2d10c5..0000000
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ /dev/null
@@ -1,113 +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 BCC_MCCACHEREADER_H
-#define BCC_MCCACHEREADER_H
-
-#include "ScriptCached.h"
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct MCO_Header;
-
-namespace bcc {
-  class Script;
-  class InputFile;
-
-  class MCCacheReader {
-  private:
-    InputFile *mObjFile, *mInfoFile;
-    off_t mInfoFileSize;
-
-    MCO_Header *mpHeader;
-    MCO_DependencyTable *mpCachedDependTable;
-    MCO_PragmaList *mpPragmaList;
-    MCO_FuncTable *mpFuncTable;
-
-    MCO_String_Ptr *mpVarNameList;
-    MCO_String_Ptr *mpFuncNameList;
-    MCO_String_Ptr *mpForEachNameList;
-
-    llvm::OwningPtr<ScriptCached> mpResult;
-
-    std::map<std::string, unsigned char const *> mDependencies;
-
-    bool mIsContextSlotNotAvail;
-
-    BCCSymbolLookupFn mpSymbolLookupFn;
-    void *mpSymbolLookupContext;
-
-  public:
-    MCCacheReader()
-      : mObjFile(NULL), mInfoFile(NULL), mInfoFileSize(0), mpHeader(NULL),
-        mpCachedDependTable(NULL), mpPragmaList(NULL),
-        mpVarNameList(NULL), mpFuncNameList(NULL), mpForEachNameList(NULL),
-        mIsContextSlotNotAvail(false) {
-    }
-
-    ~MCCacheReader();
-
-    void addDependency(std::string const &resName,
-                       unsigned char const *sha1) {
-      mDependencies.insert(std::make_pair(resName, sha1));
-    }
-
-    ScriptCached *readCacheFile(InputFile &objFile, InputFile &infoFile, Script *s);
-    bool checkCacheFile(InputFile &objFile, InputFile &infoFile, Script *S);
-
-    bool isContextSlotNotAvail() const {
-      return mIsContextSlotNotAvail;
-    }
-
-    void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
-      mpSymbolLookupFn = pFn;
-      mpSymbolLookupContext = pContext;
-    }
-
-  private:
-    bool readHeader();
-    bool readStringPool();
-    bool readDependencyTable();
-    bool readPragmaList();
-    bool readObjectSlotList();
-    bool readObjFile();
-    bool readRelocationTable();
-
-    bool readVarNameList();
-    bool readFuncNameList();
-    bool readForEachNameList();
-
-    bool checkFileSize();
-    bool checkHeader();
-    bool checkMachineIntType();
-    bool checkSectionOffsetAndSize();
-    bool checkStringPool();
-    bool checkDependency();
-    bool checkContext();
-
-    bool relocate();
-  };
-
-} // namespace bcc
-
-#endif // BCC_MCCACHEREADER_H
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
deleted file mode 100644
index c667c19..0000000
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ /dev/null
@@ -1,387 +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 "MCCacheWriter.h"
-
-#include "DebugHelper.h"
-#include "OutputFile.h"
-#include "RSScript.h"
-
-#include <map>
-#include <string>
-#include <vector>
-#include <utility>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-namespace bcc {
-
-MCCacheWriter::~MCCacheWriter() {
-#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
-
-  CHECK_AND_FREE(mpHeaderSection);
-  CHECK_AND_FREE(mpStringPoolSection);
-  CHECK_AND_FREE(mpDependencyTableSection);
-  CHECK_AND_FREE(mpPragmaListSection);
-  CHECK_AND_FREE(mpObjectSlotSection);
-  CHECK_AND_FREE(mpExportVarNameListSection);
-  CHECK_AND_FREE(mpExportFuncNameListSection);
-
-#undef CHECK_AND_FREE
-}
-
-bool MCCacheWriter::writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
-                                   RSScript *S, uint32_t libRS_threadable) {
-  if (objFile.hasError() || infoFile.hasError()) {
-    return false;
-  }
-
-  mObjFile = &objFile;
-  mInfoFile = &infoFile;
-  mpOwner = S;
-
-  bool result = prepareHeader(libRS_threadable)
-             && prepareDependencyTable()
-             && preparePragmaList()
-             && prepareExportVarNameList()
-             && prepareExportFuncNameList()
-             && prepareExportForEachNameList()
-             && prepareStringPool()
-             && prepareObjectSlotList()
-             && calcSectionOffset()
-             && writeAll()
-             ;
-
-  return result;
-}
-
-
-bool MCCacheWriter::prepareHeader(uint32_t libRS_threadable) {
-  MCO_Header *header = (MCO_Header *)malloc(sizeof(MCO_Header));
-
-  if (!header) {
-    ALOGE("Unable to allocate for header.\n");
-    return false;
-  }
-
-  mpHeaderSection = header;
-
-  // Initialize
-  memset(header, '\0', sizeof(MCO_Header));
-
-  // Magic word and version
-  memcpy(header->magic, MCO_MAGIC, 4);
-  memcpy(header->version, MCO_VERSION, 4);
-
-  // Machine Integer Type
-  uint32_t number = 0x00000001;
-  header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
-  header->sizeof_off_t = sizeof(off_t);
-  header->sizeof_size_t = sizeof(size_t);
-  header->sizeof_ptr_t = sizeof(void *);
-
-  // libRS is threadable dirty hack
-  // TODO: This should be removed in the future
-  header->libRS_threadable = libRS_threadable;
-
-  return true;
-}
-
-
-bool MCCacheWriter::prepareDependencyTable() {
-  size_t tableSize = sizeof(MCO_DependencyTable) +
-                     sizeof(MCO_Dependency) * mDependencies.size();
-
-  MCO_DependencyTable *tab = (MCO_DependencyTable *)malloc(tableSize);
-
-  if (!tab) {
-    ALOGE("Unable to allocate for dependency table section.\n");
-    return false;
-  }
-
-  mpDependencyTableSection = tab;
-  mpHeaderSection->depend_tab_size = tableSize;
-
-  tab->count = mDependencies.size();
-
-  size_t i = 0;
-  for (map<string, unsigned char const *>::iterator
-       I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
-    MCO_Dependency *dep = &tab->table[i];
-
-    dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
-    memcpy(dep->sha1, I->second, 20);
-  }
-
-  return true;
-}
-
-bool MCCacheWriter::preparePragmaList() {
-  size_t pragmaCount = mpOwner->getPragmaCount();
-
-  size_t listSize = sizeof(MCO_PragmaList) +
-                    sizeof(MCO_Pragma) * pragmaCount;
-
-  MCO_PragmaList *list = (MCO_PragmaList *)malloc(listSize);
-
-  if (!list) {
-    ALOGE("Unable to allocate for pragma list\n");
-    return false;
-  }
-
-  mpPragmaListSection = list;
-  mpHeaderSection->pragma_list_size = listSize;
-
-  list->count = pragmaCount;
-
-  vector<char const *> keyList(pragmaCount);
-  vector<char const *> valueList(pragmaCount);
-  mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
-
-  for (size_t i = 0; i < pragmaCount; ++i) {
-    char const *key = keyList[i];
-    char const *value = valueList[i];
-
-    size_t keyLen = strlen(key);
-    size_t valueLen = strlen(value);
-
-    MCO_Pragma *pragma = &list->list[i];
-    pragma->key_strp_index = addString(key, keyLen);
-    pragma->value_strp_index = addString(value, valueLen);
-  }
-
-  return true;
-}
-
-bool MCCacheWriter::prepareStringPool() {
-  // Calculate string pool size
-  size_t size = sizeof(MCO_StringPool) +
-                sizeof(MCO_String) * mStringPool.size();
-
-  off_t strOffset = size;
-
-  for (size_t i = 0; i < mStringPool.size(); ++i) {
-    size += mStringPool[i].second + 1;
-  }
-
-  // Create string pool
-  MCO_StringPool *pool = (MCO_StringPool *)malloc(size);
-
-  if (!pool) {
-    ALOGE("Unable to allocate string pool.\n");
-    return false;
-  }
-
-  mpStringPoolSection = pool;
-  mpHeaderSection->str_pool_size = size;
-
-  pool->count = mStringPool.size();
-
-  char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
-
-  for (size_t i = 0; i < mStringPool.size(); ++i) {
-    MCO_String *str = &pool->list[i];
-
-    str->length = mStringPool[i].second;
-    str->offset = strOffset;
-    memcpy(strPtr, mStringPool[i].first, str->length);
-
-    strPtr += str->length;
-    *strPtr++ = '\0';
-
-    strOffset += str->length + 1;
-  }
-
-  return true;
-}
-
-
-bool MCCacheWriter::prepareExportVarNameList() {
-  size_t varCount = mpOwner->getExportVarCount();
-  size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * varCount;
-
-  MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
-  if (!list) {
-    ALOGE("Unable to allocate for export variable name list\n");
-    return false;
-  }
-
-  mpExportVarNameListSection = list;
-  mpHeaderSection->export_var_name_list_size = listSize;
-
-  list->count = static_cast<size_t>(varCount);
-
-  mpOwner->getExportVarNameList(varNameList);
-  for (size_t i = 0; i < varCount; ++i) {
-    list->strp_indexs[i] = addString(varNameList[i].c_str(), varNameList[i].length());
-  }
-  return true;
-}
-
-
-bool MCCacheWriter::prepareExportFuncNameList() {
-  size_t funcCount = mpOwner->getExportFuncCount();
-  size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * funcCount;
-
-  MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
-  if (!list) {
-    ALOGE("Unable to allocate for export function name list\n");
-    return false;
-  }
-
-  mpExportFuncNameListSection = list;
-  mpHeaderSection->export_func_name_list_size = listSize;
-
-  list->count = static_cast<size_t>(funcCount);
-
-  mpOwner->getExportFuncNameList(funcNameList);
-  for (size_t i = 0; i < funcCount; ++i) {
-    list->strp_indexs[i] = addString(funcNameList[i].c_str(), funcNameList[i].length());
-  }
-  return true;
-}
-
-
-bool MCCacheWriter::prepareExportForEachNameList() {
-  size_t forEachCount = mpOwner->getExportForEachCount();
-  size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * forEachCount;
-
-  MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
-  if (!list) {
-    ALOGE("Unable to allocate for export forEach name list\n");
-    return false;
-  }
-
-  mpExportForEachNameListSection = list;
-  mpHeaderSection->export_foreach_name_list_size = listSize;
-
-  list->count = static_cast<size_t>(forEachCount);
-
-  mpOwner->getExportForEachNameList(forEachNameList);
-  for (size_t i = 0; i < forEachCount; ++i) {
-    list->strp_indexs[i] = addString(forEachNameList[i].c_str(), forEachNameList[i].length());
-  }
-  return true;
-}
-
-
-bool MCCacheWriter::prepareObjectSlotList() {
-  size_t objectSlotCount = mpOwner->getObjectSlotCount();
-
-  size_t listSize = sizeof(MCO_ObjectSlotList) +
-                    sizeof(uint32_t) * objectSlotCount;
-
-  MCO_ObjectSlotList *list = (MCO_ObjectSlotList *)malloc(listSize);
-
-  if (!list) {
-    ALOGE("Unable to allocate for object slot list\n");
-    return false;
-  }
-
-  mpObjectSlotSection = list;
-  mpHeaderSection->object_slot_list_size = listSize;
-
-  list->count = objectSlotCount;
-
-  mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
-  return true;
-}
-
-
-bool MCCacheWriter::calcSectionOffset() {
-  size_t offset = sizeof(MCO_Header);
-
-#define OFFSET_INCREASE(NAME)                                               \
-  do {                                                                      \
-    /* Align to a word */                                                   \
-    size_t rem = offset % sizeof(int);                                      \
-    if (rem > 0) {                                                          \
-      offset += sizeof(int) - rem;                                          \
-    }                                                                       \
-                                                                            \
-    /* Save the offset and increase it */                                   \
-    mpHeaderSection->NAME##_offset = offset;                                \
-    offset += mpHeaderSection->NAME##_size;                                 \
-  } while (0)
-
-  OFFSET_INCREASE(str_pool);
-  OFFSET_INCREASE(depend_tab);
-  OFFSET_INCREASE(pragma_list);
-  OFFSET_INCREASE(func_table);
-  OFFSET_INCREASE(object_slot_list);
-  OFFSET_INCREASE(export_var_name_list);
-  OFFSET_INCREASE(export_func_name_list);
-  OFFSET_INCREASE(export_foreach_name_list);
-
-#undef OFFSET_INCREASE
-
-  return true;
-}
-
-
-bool MCCacheWriter::writeAll() {
-#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
-  do {                                                                      \
-    if (mInfoFile->seek(OFFSET) == -1) {                                    \
-      ALOGE("Unable to seek to " #NAME " section for writing.\n");          \
-      return false;                                                         \
-    }                                                                       \
-                                                                            \
-    if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=      \
-        static_cast<ssize_t>(SIZE)) {                                       \
-      ALOGE("Unable to write " #NAME " section to cache file.\n");          \
-      return false;                                                         \
-    }                                                                       \
-  } while (0)
-
-#define WRITE_SECTION_SIMPLE(NAME, SECTION)                                 \
-  WRITE_SECTION(NAME,                                                       \
-                mpHeaderSection->NAME##_offset,                             \
-                mpHeaderSection->NAME##_size,                               \
-                SECTION)
-
-  WRITE_SECTION(header, 0, sizeof(MCO_Header), mpHeaderSection);
-
-  WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
-  WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
-  WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
-  WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
-
-  WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
-  WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
-  WRITE_SECTION_SIMPLE(export_foreach_name_list, mpExportForEachNameListSection);
-
-#undef WRITE_SECTION_SIMPLE
-#undef WRITE_SECTION
-
-  if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
-                                          mpOwner->getELFSize()))
-      != mpOwner->getELFSize()) {
-      ALOGE("Unable to write ELF to cache file.\n");
-      return false;
-  }
-
-  return true;
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
deleted file mode 100644
index 47f1e40..0000000
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ /dev/null
@@ -1,97 +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 BCC_MCCACHEWRITER_H
-#define BCC_MCCACHEWRITER_H
-
-#include <bcc/bcc_mccache.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace bcc {
-  class OutputFile;
-  class RSScript;
-
-  class MCCacheWriter {
-  private:
-    RSScript *mpOwner;
-
-    OutputFile *mObjFile, *mInfoFile;
-
-    std::vector<std::pair<char const *, size_t> > mStringPool;
-
-    std::map<std::string, unsigned char const *> mDependencies;
-
-    MCO_Header *mpHeaderSection;
-    MCO_StringPool *mpStringPoolSection;
-    MCO_DependencyTable *mpDependencyTableSection;
-    MCO_PragmaList *mpPragmaListSection;
-    MCO_ObjectSlotList *mpObjectSlotSection;
-
-    MCO_String_Ptr *mpExportVarNameListSection;
-    MCO_String_Ptr *mpExportFuncNameListSection;
-    MCO_String_Ptr *mpExportForEachNameListSection;
-
-    std::vector<std::string> varNameList;
-    std::vector<std::string> funcNameList;
-    std::vector<std::string> forEachNameList;
-
-  public:
-    MCCacheWriter()
-      : mpHeaderSection(NULL), mpStringPoolSection(NULL),
-        mpDependencyTableSection(NULL), mpPragmaListSection(NULL),
-        mpObjectSlotSection(NULL) {
-    }
-
-    ~MCCacheWriter();
-
-    bool writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
-                        RSScript *S, uint32_t libRS_threadable);
-
-    void addDependency(std::string const &resName,
-                       unsigned char const *sha1) {
-      mDependencies.insert(std::make_pair(resName, sha1));
-    }
-
-  private:
-    bool prepareHeader(uint32_t libRS_threadable);
-    bool prepareStringPool();
-    bool prepareDependencyTable();
-    bool prepareRelocationTable();
-    bool preparePragmaList();
-    bool prepareObjectSlotList();
-
-    bool prepareExportVarNameList();
-    bool prepareExportFuncNameList();
-    bool prepareExportForEachNameList();
-
-    bool writeAll();
-
-    bool calcSectionOffset();
-
-    size_t addString(char const *str, size_t size) {
-      mStringPool.push_back(std::make_pair(str, size));
-      return mStringPool.size() - 1;
-    }
-
-  };
-
-} // namespace bcc
-
-#endif // BCC_MCCACHEWRITER_H
diff --git a/lib/ExecutionEngine/RSCompiler.cpp b/lib/ExecutionEngine/RSCompiler.cpp
new file mode 100644
index 0000000..37e13bb
--- /dev/null
+++ b/lib/ExecutionEngine/RSCompiler.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 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 "RSCompiler.h"
+
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Transforms/IPO.h>
+
+#include "DebugHelper.h"
+#include "RSExecutable.h"
+#include "RSInfo.h"
+#include "RSScript.h"
+#include "RSTransforms.h"
+#include "Source.h"
+
+using namespace bcc;
+
+bool RSCompiler::beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM) {
+  // Add a pass to internalize the symbols that don't need to have global
+  // visibility.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  const RSInfo *info = script.getInfo();
+
+  // The vector contains the symbols that should not be internalized.
+  std::vector<const char *> export_symbols;
+
+  // Special RS functions should always be global symbols.
+  const char **special_functions = RSExecutable::SpecialFunctionNames;
+  while (*special_functions != NULL) {
+    export_symbols.push_back(*special_functions);
+    special_functions++;
+  }
+
+  // Visibility of symbols appeared in rs_export_var and rs_export_func should
+  // also be preserved.
+  const RSInfo::ExportVarNameListTy &export_vars = info->getExportVarNames();
+  const RSInfo::ExportFuncNameListTy &export_funcs = info->getExportFuncNames();
+
+  for (RSInfo::ExportVarNameListTy::const_iterator
+           export_var_iter = export_vars.begin(),
+           export_var_end = export_vars.end();
+       export_var_iter != export_var_end; export_var_iter++) {
+    export_symbols.push_back(*export_var_iter);
+  }
+
+  for (RSInfo::ExportFuncNameListTy::const_iterator
+           export_func_iter = export_funcs.begin(),
+           export_func_end = export_funcs.end();
+       export_func_iter != export_func_end; export_func_iter++) {
+    export_symbols.push_back(*export_func_iter);
+  }
+
+  // Expanded foreach functions should not be internalized, too.
+  const RSInfo::ExportForeachFuncListTy &export_foreach_func =
+      info->getExportForeachFuncs();
+  std::vector<std::string> expanded_foreach_funcs;
+  for (RSInfo::ExportForeachFuncListTy::const_iterator
+           foreach_func_iter = export_foreach_func.begin(),
+           foreach_func_end = export_foreach_func.end();
+       foreach_func_iter != foreach_func_end; foreach_func_iter++) {
+    std::string name(foreach_func_iter->first);
+    expanded_foreach_funcs.push_back(name.append(".expand"));
+    export_symbols.push_back(expanded_foreach_funcs.back().c_str());
+  }
+
+  pPM.add(llvm::createInternalizePass(export_symbols));
+
+  return true;
+}
+
+bool RSCompiler::beforeExecuteLTOPasses(Script &pScript,
+                                        llvm::PassManager &pPM) {
+  // Execute a pass to expand foreach-able functions
+  llvm::PassManager rs_passes;
+
+  // Script passed to RSCompiler must be a RSScript.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  const RSInfo *info = script.getInfo();
+  llvm::Module &module = script.getSource().getModule();
+
+  if (info == NULL) {
+    ALOGE("Missing RSInfo in RSScript to run the pass for foreach expansion on "
+          "%s!", module.getModuleIdentifier().c_str());
+    return false;
+  }
+
+  // Expand ForEach on CPU path to reduce launch overhead.
+  rs_passes.add(createRSForEachExpandPass(info->getExportForeachFuncs()));
+
+  // Execute the pass.
+  rs_passes.run(module);
+
+  return true;
+}
diff --git a/lib/ExecutionEngine/RSCompiler.h b/lib/ExecutionEngine/RSCompiler.h
new file mode 100644
index 0000000..227727b
--- /dev/null
+++ b/lib/ExecutionEngine/RSCompiler.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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 BCC_EXECUTION_ENGINE_RS_COMPILER_H
+#define BCC_EXECUTION_ENGINE_RS_COMPILER_H
+
+#include "Compiler.h"
+
+namespace bcc {
+
+class RSCompiler : public Compiler {
+private:
+  virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM);
+  virtual bool beforeExecuteLTOPasses(Script &pScript, llvm::PassManager &pPM);
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_RS_COMPILER_H
diff --git a/lib/ExecutionEngine/RSScript.cpp b/lib/ExecutionEngine/RSScript.cpp
index cf84194..7ec84d9 100644
--- a/lib/ExecutionEngine/RSScript.cpp
+++ b/lib/ExecutionEngine/RSScript.cpp
@@ -14,47 +14,15 @@
  * limitations under the License.
  */
 
-#include "Script.h"
+#include "RSScript.h"
 
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <new>
 #include <cstring>
 
 #include <llvm/ADT/STLExtras.h>
 
-#include <cutils/properties.h>
-
-#include "Config.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
 #include "DebugHelper.h"
-#include "FileMutex.h"
-#include "GDBJITRegistrar.h"
-#include "InputFile.h"
-#include "OutputFile.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "Source.h"
 
-namespace {
-
-bool getBooleanProp(const char *str) {
-  char buf[PROPERTY_VALUE_MAX];
-  property_get(str, buf, "0");
-  return strcmp(buf, "0") != 0;
-}
-
-} // namespace anonymous
-
-namespace bcc {
+using namespace bcc;
 
 RSScript::SourceDependency::SourceDependency(const std::string &pSourceName,
                                              const uint8_t *pSHA1)
@@ -64,44 +32,18 @@
 }
 
 RSScript::RSScript(Source &pSource)
-  : Script(pSource),
-    mpExtSymbolLookupFn(NULL),
-    mpExtSymbolLookupFnContext(NULL) {
-  resetState();
-  return;
-}
+  : Script(pSource), mInfo(NULL), mCompilerVersion(0),
+    mOptimizationLevel(kOptLvl3) { }
 
 RSScript::~RSScript() {
-  switch (mStatus) {
-  case ScriptStatus::Compiled:
-    delete mCompiled;
-    break;
-
-  case ScriptStatus::Cached:
-    delete mCached;
-    break;
-
-  default:
-    break;
-  }
   llvm::DeleteContainerPointers(mSourceDependencies);
 }
 
-void RSScript::resetState() {
-  mErrorCode = BCC_NO_ERROR;
-  mStatus = ScriptStatus::Unknown;
-  mObjectType = ScriptObject::Unknown;
-  mIsContextSlotNotAvail = false;
-  // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
-  //        to NULL during state resetting.
-  //mpExtSymbolLookupFn = NULL;
-  //mpExtSymbolLookupFnContext = NULL;
-  llvm::DeleteContainerPointers(mSourceDependencies);
-  return;
-}
-
 bool RSScript::doReset() {
-  resetState();
+  mInfo = NULL;
+  mCompilerVersion = 0;
+  mOptimizationLevel = kOptLvl3;
+  llvm::DeleteContainerPointers(mSourceDependencies);
   return true;
 }
 
@@ -118,647 +60,3 @@
   mSourceDependencies.push_back(source_dep);
   return true;
 }
-
-int RSScript::prepareRelocatable(char const *objPath,
-                               llvm::Reloc::Model RelocModel,
-                               unsigned long flags) {
-  CompilerOption option;
-  option.RelocModelOpt = RelocModel;
-  option.LoadAfterCompile = false;
-
-  int status = internalCompile(option);
-  if (status != 0) {
-    ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
-    return status;
-  }
-
-  OutputFile objFile(objPath);
-  if (objFile.hasError()) {
-    ALOGE("Failed to open %s for write. (%s)", objPath,
-          objFile.getErrorMessage().c_str());
-    return 1;
-  }
-
-  if (static_cast<size_t>(objFile.write(getELF(),
-                                        getELFSize())) != getELFSize()) {
-      objFile.close();
-      ::unlink(objPath);
-      ALOGE("Unable to write ELF to file %s.\n", objPath);
-      return false;
-  }
-
-  mObjectType = ScriptObject::Relocatable;
-
-  return 0;
-}
-
-
-int RSScript::prepareSharedObject(char const *objPath,
-                                char const *dsoPath,
-                                unsigned long flags) {
-  // TODO: Support cached shared object.
-  return 1;
-}
-
-
-int RSScript::prepareExecutable(char const *cacheDir,
-                              char const *cacheName,
-                              unsigned long flags) {
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Invalid operation: %s\n", __func__);
-    return 1;
-  }
-
-  int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
-
-  if (status != 0) {
-    CompilerOption option;
-    status = internalCompile(option);
-
-    if (status != 0) {
-      ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
-      return status;
-    }
-
-    status = writeCache();
-    if (status != 0) {
-      ALOGE("Failed to write the cache for %s\n", cacheName);
-      return status;
-    }
-  }
-
-  // FIXME: Registration can be conditional on the presence of debug metadata
-  registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
-
-  mObjectType = ScriptObject::Executable;
-
-  return status;
-}
-
-int RSScript::internalLoadCache(char const *cacheDir, char const *cacheName,
-                              bool checkOnly) {
-  if ((cacheDir == NULL) || (cacheName == NULL)) {
-    return 1;
-  }
-
-  // Set cache file Name
-  mCacheName = cacheName;
-
-  // Sanitize mCacheDir. Ensure that mCacheDir ends with '/'.
-  mCacheDir = cacheDir;
-  if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
-    mCacheDir.push_back('/');
-  }
-
-  if (!isCacheable()) {
-    return 1;
-  }
-
-  std::string objPath = getCachedObjectPath();
-  std::string infoPath = getCacheInfoPath();
-
-  // Locks for reading object file and info file.
-  FileMutex<FileBase::kReadLock> objFileMutex(objPath);
-  FileMutex<FileBase::kReadLock> infoFileMutex(infoPath);
-
-  // Aquire read lock for object file.
-  if (objFileMutex.hasError() || !objFileMutex.lock()) {
-    ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
-          objFileMutex.getErrorMessage().c_str());
-    return 1;
-  }
-
-  // Aquire read lock for info file.
-  if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
-    ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
-          infoFileMutex.getErrorMessage().c_str());
-    return 1;
-  }
-
-  // Open the object file and info file
-  InputFile objFile(objPath);
-  InputFile infoFile(infoPath);
-
-  if (objFile.hasError()) {
-    ALOGE("Unable to open %s for reading! (%s)", objPath.c_str(),
-          objFile.getErrorMessage().c_str());
-    return 1;
-  }
-
-  if (infoFile.hasError()) {
-    ALOGE("Unable to open %s for reading! (%s)", infoPath.c_str(),
-          infoFile.getErrorMessage().c_str());
-    return 1;
-  }
-
-  MCCacheReader reader;
-
-  // Register symbol lookup function
-  if (mpExtSymbolLookupFn) {
-    reader.registerSymbolCallback(mpExtSymbolLookupFn,
-                                      mpExtSymbolLookupFnContext);
-  }
-
-  // Dependencies
-  reader.addDependency(pathLibBCC_SHA1, sha1LibBCC_SHA1);
-  reader.addDependency(pathLibRS, sha1LibRS);
-
-  for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
-    const SourceDependency *source_dep = mSourceDependencies[i];
-    reader.addDependency(source_dep->getSourceName(),
-                         source_dep->getSHA1Checksum());
-  }
-
-  if (checkOnly)
-    return !reader.checkCacheFile(objFile, infoFile, this);
-
-  // Read cache file
-  ScriptCached *cached = reader.readCacheFile(objFile, infoFile, this);
-
-  if (!cached) {
-    mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
-    return 1;
-  }
-
-  mCached = cached;
-  mStatus = ScriptStatus::Cached;
-
-  // Dirty hack for libRS.
-  // TODO(all):  This dirty hack should be removed in the future.
-  if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
-    mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
-  }
-
-  return 0;
-}
-
-int RSScript::internalCompile(const CompilerOption &option) {
-  // Create the ScriptCompiled object
-  mCompiled = new (std::nothrow) ScriptCompiled(this);
-
-  if (!mCompiled) {
-    mErrorCode = BCC_OUT_OF_MEMORY;
-    ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
-    return 1;
-  }
-
-  mStatus = ScriptStatus::Compiled;
-
-  // Register symbol lookup function
-  if (mpExtSymbolLookupFn) {
-    mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
-                                      mpExtSymbolLookupFnContext);
-  }
-
-  // Set the main source module
-  if (mCompiled->readModule(getSource().getModule()) != 0) {
-    ALOGE("Unable to read source module\n");
-    return 1;
-  }
-
-  // Compile and JIT the code
-  if (mCompiled->compile(option) != 0) {
-    ALOGE("Unable to compile.\n");
-    return 1;
-  }
-
-  return 0;
-}
-
-int RSScript::writeCache() {
-  // Not compiled script or encountered error during the compilation.
-  if ((mStatus != ScriptStatus::Compiled) ||
-      (getCompilerErrorMessage() == NULL))
-    return 1;
-
-  if (isCacheable()) {
-    std::string objPath = getCachedObjectPath();
-    std::string infoPath = getCacheInfoPath();
-
-    // Locks for writing object file and info file.
-    FileMutex<FileBase::kWriteLock> objFileMutex(objPath);
-    FileMutex<FileBase::kWriteLock> infoFileMutex(infoPath);
-
-    // Acquire write lock for object file.
-    if (objFileMutex.hasError() || !objFileMutex.lock()) {
-      ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
-            objFileMutex.getErrorMessage().c_str());
-      return 1;
-    }
-
-    // Acquire write lock for info file.
-    if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
-      ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
-            infoFileMutex.getErrorMessage().c_str());
-      return 1;
-    }
-
-    // Open the object file and info file
-    OutputFile objFile(objPath);
-    OutputFile infoFile(infoPath);
-
-    if (objFile.hasError()) {
-      ALOGE("Unable to open %s for writing! (%s)", objPath.c_str(),
-            objFile.getErrorMessage().c_str());
-      return 1;
-    }
-
-    if (infoFile.hasError()) {
-      ALOGE("Unable to open %s for writing! (%s)", infoPath.c_str(),
-            infoFile.getErrorMessage().c_str());
-      return 1;
-    }
-
-    MCCacheWriter writer;
-
-#ifdef TARGET_BUILD
-    // Dependencies
-    writer.addDependency(pathLibBCC_SHA1, sha1LibBCC_SHA1);
-    writer.addDependency(pathLibRS, sha1LibRS);
-#endif
-
-    for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
-      const SourceDependency *source_dep = mSourceDependencies[i];
-      writer.addDependency(source_dep->getSourceName(),
-                           source_dep->getSHA1Checksum());
-    }
-
-
-    // libRS is threadable dirty hack
-    // TODO: This should be removed in the future
-    uint32_t libRS_threadable = 0;
-    if (mpExtSymbolLookupFn) {
-      libRS_threadable =
-        (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
-                                      "__isThreadable");
-    }
-
-    if (!writer.writeCacheFile(objFile, infoFile, this, libRS_threadable)) {
-      // Erase the file contents.
-      objFile.truncate();
-      infoFile.truncate();
-
-      // Close the file such that we can remove it from the filesystem.
-      objFile.close();
-      infoFile.close();
-
-      if (::unlink(objPath.c_str()) != 0) {
-        ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-             objPath.c_str(), ::strerror(errno));
-      }
-
-      if (::unlink(infoPath.c_str()) != 0) {
-        ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-             infoPath.c_str(), ::strerror(errno));
-      }
-    }
-  } // isCacheable()
-
-  return 0;
-}
-
-char const *RSScript::getCompilerErrorMessage() {
-  if (mStatus != ScriptStatus::Compiled) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    return NULL;
-  }
-
-  return mCompiled->getCompilerErrorMessage();
-}
-
-
-void *RSScript::lookup(const char *name) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->lookup(name);
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->lookup(name);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-      return NULL;
-    }
-  }
-}
-
-
-size_t RSScript::getExportVarCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportVarCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportVarCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getExportFuncCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportFuncCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportFuncCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getExportForEachCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportForEachCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportForEachCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getPragmaCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getPragmaCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getPragmaCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getFuncCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getFuncCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getFuncCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getObjectSlotCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getObjectSlotCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getObjectSlotCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-void RSScript::getExportVarList(size_t varListSize, void **varList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                           \
-      m##STATUS->getExportVarList(varListSize, varList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportVarNameList(std::vector<std::string> &varList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportVarNameList(varList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getExportFuncList(size_t funcListSize, void **funcList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                              \
-      m##STATUS->getExportFuncList(funcListSize, funcList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportFuncNameList(std::vector<std::string> &funcList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportFuncNameList(funcList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportForEachList(size_t funcListSize, void **funcList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                 \
-      m##STATUS->getExportForEachList(funcListSize, funcList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportForEachNameList(std::vector<std::string> &forEachList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportForEachNameList(forEachList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getPragmaList(size_t pragmaListSize,
-                           char const **keyList,
-                           char const **valueList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                      \
-      m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getFuncInfoList(size_t funcInfoListSize,
-                             FuncInfo *funcInfoList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                    \
-      m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getObjectSlotList(size_t objectSlotListSize,
-                               uint32_t *objectSlotList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS)     \
-    case ScriptStatus::STATUS:                                          \
-      m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-int RSScript::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
-  mpExtSymbolLookupFn = pFn;
-  mpExtSymbolLookupFnContext = pContext;
-
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Invalid operation: %s\n", __func__);
-    return 1;
-  }
-  return 0;
-}
-
-bool RSScript::isCacheable() const {
-  if (getBooleanProp("debug.bcc.nocache")) {
-    // Android system environment property: Disables the cache mechanism by
-    // setting "debug.bcc.nocache".  So we will not load the cache file any
-    // way.
-    return false;
-  }
-
-  if (mCacheDir.empty() || mCacheName.empty()) {
-    // The application developer has not specified the cachePath, so
-    // we don't know where to open the cache file.
-    return false;
-  }
-
-  return true;
-}
-
-size_t RSScript::getELFSize() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getELFSize();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getELFSize();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-const char *RSScript::getELF() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getELF();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getELF();
-    }
-
-    default: {
-      return NULL;
-    }
-  }
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/RSScript.h b/lib/ExecutionEngine/RSScript.h
index 4fc1f90..1ae9c9d 100644
--- a/lib/ExecutionEngine/RSScript.h
+++ b/lib/ExecutionEngine/RSScript.h
@@ -17,237 +17,94 @@
 #ifndef BCC_EXECUTION_ENGINE_RS_SCRIPT_H
 #define BCC_EXECUTION_ENGINE_RS_SCRIPT_H
 
-#include <vector>
 #include <string>
 
-#include <stdint.h>
-#include <stddef.h>
-
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/Support/CodeGen.h>
 
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
 #include "Script.h"
 
-namespace llvm {
-  class Module;
-  class GDBJITRegistrar;
-}
-
 namespace bcc {
-  class RSInfo;
-  class ScriptCompiled;
-  class ScriptCached;
-  class Source;
-  struct CompilerOption;
 
-  namespace ScriptStatus {
-    enum StatusType {
-      Unknown,
-      Compiled,
-      Cached
-    };
-  }
+class RSInfo;
+class Source;
 
-  namespace ScriptObject {
-    enum ObjectType {
-      Unknown,
-      Relocatable,
-      SharedObject,
-      Executable,
-    };
-  }
-
-  class RSScript : public Script {
-  public:
-    class SourceDependency {
-    private:
-      std::string mSourceName;
-      uint8_t mSHA1[20];
-
-    public:
-      SourceDependency(const std::string &pSourceName,
-                       const uint8_t *pSHA1);
-
-      inline const std::string &getSourceName() const
-      { return mSourceName; }
-
-      inline const uint8_t *getSHA1Checksum() const
-      { return mSHA1; }
-    };
-    typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
-
+class RSScript : public Script {
+public:
+  class SourceDependency {
   private:
-    int mErrorCode;
-
-    ScriptStatus::StatusType mStatus;
-    // The type of the object behind this script after compilation. For
-    // example, after returning from a successful call to prepareRelocatable(),
-    // the value of mObjectType will be ScriptObject::Relocatable.
-    ScriptObject::ObjectType mObjectType;
-
-    union {
-      ScriptCompiled *mCompiled;
-      ScriptCached *mCached;
-    };
-
-    std::string mCacheDir;
-    std::string mCacheName;
-
-    inline std::string getCachedObjectPath() const {
-      return std::string(mCacheDir + mCacheName + ".o");
-    }
-
-    inline std::string getCacheInfoPath() const {
-      return getCachedObjectPath().append(".info");
-    }
-
-    bool mIsContextSlotNotAvail;
-
-    llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
-
-    const RSInfo *mInfo;
-
-    // External Function List
-    std::vector<char const *> mUserDefinedExternalSymbols;
-
-    // Register Symbol Lookup Function
-    BCCSymbolLookupFn mpExtSymbolLookupFn;
-    void *mpExtSymbolLookupFnContext;
-
-    // This will be invoked when the containing source has been reset.
-    virtual bool doReset();
-
-    // Reset the state of this script object
-    void resetState();
+    std::string mSourceName;
+    uint8_t mSHA1[20];
 
   public:
-    RSScript(Source &pSource);
+    SourceDependency(const std::string &pSourceName,
+                     const uint8_t *pSHA1);
 
-    ~RSScript();
+    inline const std::string &getSourceName() const
+    { return mSourceName; }
 
-    // Add dependency information for this script given the source named
-    // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
-    // false on error.
-    bool addSourceDependency(const std::string &pSourceName,
-                             const uint8_t *pSHA1);
+    inline const uint8_t *getSHA1Checksum() const
+    { return mSHA1; }
+  };
+  typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
 
-    const SourceDependencyListTy &getSourceDependencies() const
-    { return mSourceDependencies; }
-
-    // Set the associated RSInfo of the script.
-    void setInfo(const RSInfo *pInfo)
-    { mInfo = pInfo; }
-
-    const RSInfo *getInfo() const
-    { return mInfo; }
-
-    void markExternalSymbol(char const *name) {
-      mUserDefinedExternalSymbols.push_back(name);
-    }
-
-    std::vector<char const *> const &getUserDefinedExternalSymbols() const {
-      return mUserDefinedExternalSymbols;
-    }
-
-    int prepareExecutable(char const *cacheDir,
-                          char const *cacheName,
-                          unsigned long flags);
-    int writeCache();
-
-    /*
-     * Link the given bitcodes in mSource to shared object (.so).
-     *
-     * Currently, it requires one to provide the relocatable object files with
-     * given bitcodes to output a shared object.
-     *
-     * The usage of this function is flexible. You can have a relocatable object
-     * compiled before and pass it in objPath to generate shared object. If the
-     * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
-     * you haven't done that yet) and then link the output relocatable object
-     * file to .so in dsoPath.
-     *
-     * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
-     *
-     */
-    int prepareSharedObject(char const *objPath,
-                            char const *dsoPath,
-                            unsigned long flags);
-
-    int prepareRelocatable(char const *objPath,
-                           llvm::Reloc::Model RelocModel,
-                           unsigned long flags);
-
-    char const *getCompilerErrorMessage();
-
-    void *lookup(const char *name);
-
-    size_t getExportVarCount() const;
-
-    size_t getExportFuncCount() const;
-
-    size_t getExportForEachCount() const;
-
-    size_t getPragmaCount() const;
-
-    size_t getFuncCount() const;
-
-    size_t getObjectSlotCount() const;
-
-    void getExportVarList(size_t size, void **list);
-
-    void getExportFuncList(size_t size, void **list);
-
-    void getExportForEachList(size_t size, void **list);
-
-    void getExportVarNameList(std::vector<std::string> &list);
-
-    void getExportFuncNameList(std::vector<std::string> &list);
-
-    void getExportForEachNameList(std::vector<std::string> &list);
-
-    void getPragmaList(size_t size,
-                       char const **keyList,
-                       char const **valueList);
-
-    void getFuncInfoList(size_t size, FuncInfo *list);
-
-    void getObjectSlotList(size_t size, uint32_t *list);
-
-    size_t getELFSize() const;
-
-    const char *getELF() const;
-
-    int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
-
-    bool isCacheable() const;
-
-    void setError(int error) {
-      if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
-        mErrorCode = error;
-      }
-    }
-
-    int getError() {
-      int result = mErrorCode;
-      mErrorCode = BCC_NO_ERROR;
-      return result;
-    }
-
-  private:
-    //
-    // It returns 0 if there's a cache hit.
-    //
-    // Side effect: it will set mCacheDir, mCacheName.
-    int internalLoadCache(char const *cacheDir, char const *cacheName,
-                          bool checkOnly);
-
-    int internalCompile(const CompilerOption&);
+  // This is one-one mapping with the llvm::CodeGenOpt::Level in
+  // llvm/Support/CodeGen.h. Therefore, value of this type can safely cast
+  // to llvm::CodeGenOpt::Level. This makes RSScript LLVM-free.
+  enum OptimizationLevel {
+    kOptLvl0, // -O0
+    kOptLvl1, // -O1
+    kOptLvl2, // -O2, -Os
+    kOptLvl3  // -O3
   };
 
-} // namespace bcc
+private:
+  llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
+
+  const RSInfo *mInfo;
+
+  unsigned mCompilerVersion;
+
+  OptimizationLevel mOptimizationLevel;
+
+private:
+  // This will be invoked when the containing source has been reset.
+  virtual bool doReset();
+
+public:
+  RSScript(Source &pSource);
+
+  // Add dependency information for this script given the source named
+  // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
+  // false on error.
+  bool addSourceDependency(const std::string &pSourceName,
+                           const uint8_t *pSHA1);
+
+  const SourceDependencyListTy &getSourceDependencies() const
+  { return mSourceDependencies; }
+
+  // Set the associated RSInfo of the script.
+  void setInfo(const RSInfo *pInfo)
+  { mInfo = pInfo; }
+
+  const RSInfo *getInfo() const
+  { return mInfo; }
+
+  void setCompilerVersion(unsigned pCompilerVersion)
+  {  mCompilerVersion = pCompilerVersion; }
+
+  unsigned getCompilerVersion() const
+  {  return mCompilerVersion; }
+
+  void setOptimizationLevel(OptimizationLevel pOptimizationLevel)
+  {  mOptimizationLevel = pOptimizationLevel; }
+
+  OptimizationLevel getOptimizationLevel() const
+  {  return mOptimizationLevel; }
+
+  ~RSScript();
+};
+
+} // end namespace bcc
 
 #endif // BCC_EXECUTION_ENGINE_RS_SCRIPT_H
diff --git a/lib/ExecutionEngine/ScriptCached.cpp b/lib/ExecutionEngine/ScriptCached.cpp
deleted file mode 100644
index bbfac2b..0000000
--- a/lib/ExecutionEngine/ScriptCached.cpp
+++ /dev/null
@@ -1,141 +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 "Config.h"
-
-#include "ScriptCached.h"
-
-#include "DebugHelper.h"
-
-#include <stdlib.h>
-
-namespace bcc {
-
-ScriptCached::~ScriptCached() {
-  // Deallocate string pool, exported var list, exported func list
-  if (mpStringPoolRaw) { free(mpStringPoolRaw); }
-  if (mpExportVars) { free(mpExportVars); }
-  if (mpExportFuncs) { free(mpExportFuncs); }
-  if (mpExportForEach) { free(mpExportForEach); }
-  if (mpObjectSlotList) { free(mpObjectSlotList); }
-}
-
-void ScriptCached::getExportVarList(size_t varListSize, void **varList) {
-  if (varList) {
-    size_t varCount = getExportVarCount();
-
-    if (varCount > varListSize) {
-      varCount = varListSize;
-    }
-
-    memcpy(varList, mpExportVars->cached_addr_list, sizeof(void *) * varCount);
-  }
-}
-
-
-void ScriptCached::getExportFuncList(size_t funcListSize, void **funcList) {
-  if (funcList) {
-    size_t funcCount = getExportFuncCount();
-
-    if (funcCount > funcListSize) {
-      funcCount = funcListSize;
-    }
-
-    memcpy(funcList, mpExportFuncs->cached_addr_list,
-           sizeof(void *) * funcCount);
-  }
-}
-
-
-void ScriptCached::getExportForEachList(size_t forEachListSize,
-                                        void **forEachList) {
-  if (forEachList) {
-    size_t forEachCount = getExportForEachCount();
-
-    if (forEachCount > forEachListSize) {
-      forEachCount = forEachListSize;
-    }
-
-    memcpy(forEachList, mpExportForEach->cached_addr_list,
-           sizeof(void *) * forEachCount);
-  }
-}
-
-
-void ScriptCached::getPragmaList(size_t pragmaListSize,
-                                 char const **keyList,
-                                 char const **valueList) {
-  size_t pragmaCount = getPragmaCount();
-
-  if (pragmaCount > pragmaListSize) {
-    pragmaCount = pragmaListSize;
-  }
-
-  if (keyList) {
-    for (size_t i = 0; i < pragmaCount; ++i) {
-      *keyList++ = mPragmas[i].first;
-    }
-  }
-
-  if (valueList) {
-    for (size_t i = 0; i < pragmaCount; ++i) {
-      *valueList++ = mPragmas[i].second;
-    }
-  }
-}
-
-
-void ScriptCached::getObjectSlotList(size_t objectSlotListSize,
-                                     uint32_t *objectSlotList) {
-  if (objectSlotList) {
-    size_t objectSlotCount = getObjectSlotCount();
-
-    if (objectSlotCount > objectSlotListSize) {
-      objectSlotCount = objectSlotListSize;
-    }
-
-    memcpy(objectSlotList, mpObjectSlotList->object_slot_list,
-           sizeof(uint32_t) * objectSlotCount);
-  }
-}
-
-
-void *ScriptCached::lookup(const char *name) {
-  return rsloaderGetSymbolAddress(mRSExecutable, name);
-}
-
-void ScriptCached::getFuncInfoList(size_t funcInfoListSize,
-                                   FuncInfo *funcInfoList) {
-  if (funcInfoList) {
-    size_t funcCount = getFuncCount();
-
-    if (funcCount > funcInfoListSize) {
-      funcCount = funcInfoListSize;
-    }
-
-    FuncInfo *info = funcInfoList;
-    for (FuncTable::const_iterator
-         I = mFunctions.begin(), E = mFunctions.end();
-         I != E && funcCount > 0; ++I, ++info, --funcCount) {
-      info->name = I->first.c_str();
-      info->addr = I->second.first;
-      info->size = I->second.second;
-    }
-  }
-}
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/ScriptCached.h b/lib/ExecutionEngine/ScriptCached.h
deleted file mode 100644
index e24a714..0000000
--- a/lib/ExecutionEngine/ScriptCached.h
+++ /dev/null
@@ -1,153 +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 BCC_SCRIPTCACHED_H
-#define BCC_SCRIPTCACHED_H
-
-#include "Config.h"
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "librsloader.h"
-
-#include <llvm/ADT/SmallVector.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <stddef.h>
-
-namespace llvm {
-  class Module;
-}
-
-namespace bcc {
-  class Script;
-
-  class ScriptCached {
-    friend class CacheReader;
-    friend class MCCacheReader;
-
-  private:
-    enum { SMALL_VECTOR_QUICKN = 16 };
-
-    typedef llvm::SmallVector<std::pair<char const *, char const *>,
-                              SMALL_VECTOR_QUICKN> PragmaList;
-
-    typedef std::map<std::string, std::pair<void *, size_t> > FuncTable;
-
-  private:
-    Script *mpOwner;
-
-    MCO_ExportVarList *mpExportVars;
-    MCO_ExportFuncList *mpExportFuncs;
-    MCO_ExportForEachList *mpExportForEach;
-    PragmaList mPragmas;
-    MCO_ObjectSlotList *mpObjectSlotList;
-
-    FuncTable mFunctions;
-
-    RSExecRef mRSExecutable;
-    llvm::SmallVector<char, 1024> mCachedELFExecutable;
-
-    MCO_StringPool *mpStringPoolRaw;
-    std::vector<char const *> mStringPool;
-
-    bool mLibRSThreadable;
-
-  public:
-    ScriptCached(Script *owner)
-      : mpOwner(owner),
-        mpExportVars(NULL),
-        mpExportFuncs(NULL),
-        mpExportForEach(NULL),
-        mpObjectSlotList(NULL),
-        mpStringPoolRaw(NULL),
-        mLibRSThreadable(false) {
-    }
-
-    ~ScriptCached();
-
-    void *lookup(const char *name);
-
-
-    size_t getExportVarCount() const {
-      return mpExportVars->count;
-    }
-
-    size_t getExportFuncCount() const {
-      return mpExportFuncs->count;
-    }
-
-    size_t getExportForEachCount() const {
-      return mpExportForEach->count;
-    }
-
-    size_t getPragmaCount() const {
-      return mPragmas.size();
-    }
-
-    size_t getFuncCount() const {
-      return mFunctions.size();
-    }
-
-    size_t getObjectSlotCount() const {
-      return mpObjectSlotList->count;
-    }
-
-    void getExportVarList(size_t varListSize, void **varList);
-
-    void getExportFuncList(size_t funcListSize, void **funcList);
-
-    void getExportForEachList(size_t forEachListSize, void **forEachList);
-
-    void getPragmaList(size_t pragmaListSize,
-                       char const **keyList,
-                       char const **valueList);
-
-    void getFuncInfoList(size_t funcInfoListSize, FuncInfo *funcNameList);
-
-    void getObjectSlotList(size_t objectSlotListSize,
-                           uint32_t *objectSlotList);
-
-    const char *getELF() const {
-      return &*mCachedELFExecutable.begin();
-    }
-
-    size_t getELFSize() const {
-      return mCachedELFExecutable.size();
-    }
-
-    // Dirty hack for libRS.
-    // TODO(all): This should be removed in the future.
-    bool isLibRSThreadable() const {
-      return mLibRSThreadable;
-    }
-
-#if 0
-    void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
-      mCompiler.registerSymbolCallback(pFn, pContext);
-    }
-#endif
-  };
-
-} // namespace bcc
-
-#endif // BCC_SCRIPTCACHED_H
diff --git a/lib/ExecutionEngine/ScriptCompiled.cpp b/lib/ExecutionEngine/ScriptCompiled.cpp
deleted file mode 100644
index 4f2bb1b..0000000
--- a/lib/ExecutionEngine/ScriptCompiled.cpp
+++ /dev/null
@@ -1,154 +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 "ScriptCompiled.h"
-
-#include "bcc_internal.h"
-#include "DebugHelper.h"
-
-namespace bcc {
-
-ScriptCompiled::~ScriptCompiled() {
-}
-
-void ScriptCompiled::getExportVarList(size_t varListSize, void **varList) {
-  if (varList) {
-    size_t varCount = getExportVarCount();
-
-    if (varCount > varListSize) {
-      varCount = varListSize;
-    }
-
-    for (ExportVarList::const_iterator
-         I = mExportVars.begin(), E = mExportVars.end();
-         I != E && varCount > 0; ++I, --varCount) {
-      *varList++ = *I;
-    }
-  }
-}
-
-void ScriptCompiled::getExportVarNameList(std::vector<std::string> &varList) {
-  varList = mExportVarsName;
-}
-
-
-void ScriptCompiled::getExportFuncNameList(std::vector<std::string> &funcList) {
-  funcList = mExportFuncsName;
-}
-
-
-void ScriptCompiled::getExportForEachNameList(std::vector<std::string> &forEachList) {
-  forEachList = mExportForEachName;
-}
-
-
-void ScriptCompiled::getExportFuncList(size_t funcListSize, void **funcList) {
-  if (funcList) {
-    size_t funcCount = getExportFuncCount();
-
-    if (funcCount > funcListSize) {
-      funcCount = funcListSize;
-    }
-
-    for (ExportFuncList::const_iterator
-         I = mExportFuncs.begin(), E = mExportFuncs.end();
-         I != E && funcCount > 0; ++I, --funcCount) {
-      *funcList++ = *I;
-    }
-  }
-}
-
-
-void ScriptCompiled::getExportForEachList(size_t forEachListSize,
-                                          void **forEachList) {
-  if (forEachList) {
-    size_t forEachCount = getExportForEachCount();
-
-    if (forEachCount > forEachListSize) {
-      forEachCount = forEachListSize;
-    }
-
-    for (ExportForEachList::const_iterator
-         I = mExportForEach.begin(), E = mExportForEach.end();
-         I != E && forEachCount > 0; ++I, --forEachCount) {
-      *forEachList++ = *I;
-    }
-  }
-}
-
-
-void ScriptCompiled::getPragmaList(size_t pragmaListSize,
-                                   char const **keyList,
-                                   char const **valueList) {
-  size_t pragmaCount = getPragmaCount();
-
-  if (pragmaCount > pragmaListSize) {
-    pragmaCount = pragmaListSize;
-  }
-
-  for (PragmaList::const_iterator
-       I = mPragmas.begin(), E = mPragmas.end();
-       I != E && pragmaCount > 0; ++I, --pragmaCount) {
-    if (keyList) { *keyList++ = I->first.c_str(); }
-    if (valueList) { *valueList++ = I->second.c_str(); }
-  }
-}
-
-
-void *ScriptCompiled::lookup(const char *name) {
-  return mCompiler.getSymbolAddress(name);
-}
-
-
-void ScriptCompiled::getFuncInfoList(size_t funcInfoListSize,
-                                     FuncInfo *funcInfoList) {
-  if (funcInfoList) {
-    size_t funcCount = getFuncCount();
-
-    if (funcCount > funcInfoListSize) {
-      funcCount = funcInfoListSize;
-    }
-
-    FuncInfo *info = funcInfoList;
-    for (FuncInfoMap::const_iterator
-         I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
-         I != E && funcCount > 0; ++I, ++info, --funcCount) {
-      info->name = I->first.c_str();
-      info->addr = I->second->addr;
-      info->size = I->second->size;
-    }
-  }
-}
-
-void ScriptCompiled::getObjectSlotList(size_t objectSlotListSize,
-                                       uint32_t *objectSlotList) {
-  if (objectSlotList) {
-    size_t objectSlotCount = getObjectSlotCount();
-
-    if (objectSlotCount > objectSlotListSize) {
-      objectSlotCount = objectSlotListSize;
-    }
-
-    for (ObjectSlotList::const_iterator
-         I = mObjectSlots.begin(), E = mObjectSlots.end();
-         I != E && objectSlotCount > 0; ++I, --objectSlotCount) {
-      *objectSlotList++ = *I;
-    }
-  }
-
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
deleted file mode 100644
index ff006f9..0000000
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ /dev/null
@@ -1,155 +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 BCC_EXECUTION_ENGINE_SCRIPTCOMPILED_H
-#define BCC_EXECUTION_ENGINE_SCRIPTCOMPILED_H
-
-#include <list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <bcc/bcc.h>
-
-#include "Compiler.h"
-#include "RSScript.h"
-
-namespace llvm {
-  class Module;
-}
-
-namespace bcc {
-  struct CompilerOption;
-
-  class ScriptCompiled {
-    friend class Compiler;
-    friend class CodeEmitter;
-
-  private:
-    typedef std::list<std::pair<std::string, std::string> > PragmaList;
-    typedef std::list<void*> ExportVarList;
-    typedef std::list<void*> ExportFuncList;
-    typedef std::list<void*> ExportForEachList;
-    typedef std::map<std::string, FuncInfo *> FuncInfoMap;
-    typedef std::list<uint32_t> ObjectSlotList;
-
-  private:
-    RSScript *mpOwner;
-
-    Compiler mCompiler;
-
-    ExportVarList mExportVars;
-
-    std::vector<std::string> mExportVarsName;
-    std::vector<std::string> mExportFuncsName;
-    std::vector<std::string> mExportForEachName;
-
-    ExportFuncList mExportFuncs;
-    ExportForEachList mExportForEach;
-    PragmaList mPragmas;
-    ObjectSlotList mObjectSlots;
-
-    FuncInfoMap mEmittedFunctions;
-
-  public:
-    ScriptCompiled(RSScript *owner)
-      : mpOwner(owner), mCompiler(this)
-    {
-    }
-
-    ~ScriptCompiled();
-
-    int readModule(llvm::Module &pModule) {
-      return mCompiler.readModule(pModule);
-    }
-
-    int compile(const CompilerOption &option) {
-      return mCompiler.compile(option);
-    }
-
-    char const *getCompilerErrorMessage() {
-      return mCompiler.getErrorMessage();
-    }
-
-    void *lookup(const char *name);
-
-    size_t getExportVarCount() const {
-      return mExportVars.size();
-    }
-
-    size_t getExportFuncCount() const {
-      return mExportFuncs.size();
-    }
-
-    size_t getExportForEachCount() const {
-      return mExportForEach.size();
-    }
-
-    size_t getPragmaCount() const {
-      return mPragmas.size();
-    }
-
-    size_t getFuncCount() const {
-      return mEmittedFunctions.size();
-    }
-
-    size_t getObjectSlotCount() const {
-      return mObjectSlots.size();
-    }
-
-    void getExportVarList(size_t varListSize, void **varList);
-
-    void getExportFuncList(size_t funcListSize, void **funcList);
-
-    void getExportForEachList(size_t forEachListSize, void **forEachList);
-
-    void getExportVarNameList(std::vector<std::string> &varList);
-
-    void getExportFuncNameList(std::vector<std::string> &funcList);
-
-    void getExportForEachNameList(std::vector<std::string> &forEachList);
-
-    void getPragmaList(size_t pragmaListSize,
-                       char const **keyList,
-                       char const **valueList);
-
-    void getFuncInfoList(size_t funcInfoListSize,
-                         FuncInfo *funcInfoList);
-
-    void getObjectSlotList(size_t objectSlotListSize,
-                           uint32_t *objectSlotList);
-
-    std::vector<char const *> const & getUserDefinedExternalSymbols() const {
-      return mpOwner->getUserDefinedExternalSymbols();
-    }
-
-    const char *getELF() const {
-      return &*mCompiler.getELF().begin();
-    }
-
-    size_t getELFSize() const {
-      return mCompiler.getELF().size();
-    }
-
-    void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
-      mCompiler.registerSymbolCallback(pFn, pContext);
-    }
-  };
-
-} // namespace bcc
-
-#endif // BCC_EXECUTION_ENGINE_SCRIPTCOMPILED_H
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 4e8278d..6a3b8d3 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -19,22 +19,20 @@
 
 #include <bcc/bcc.h>
 
-#include <string>
+#include <llvm/Support/CodeGen.h>
 
 #include <utils/StopWatch.h>
 
-#include "Config.h"
-
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "BCCContext.h"
-#include "Compiler.h"
 #include "DebugHelper.h"
+#include "Initialization.h"
+#include "RSExecutable.h"
 #include "RSScript.h"
 #include "Sha1Helper.h"
 #include "Source.h"
 
+#include "bcc_internal.h"
+#include <bcinfo/BitcodeWrapper.h>
+
 using namespace bcc;
 
 namespace llvm {
@@ -54,21 +52,24 @@
 extern "C" BCCScriptRef bccCreateScript() {
   BCC_FUNC_LOGGER();
   bccPrintBuildStamp();
-  // FIXME: This is a workaround for this API: use global BCC context and
-  //        create an empty source to create a Script object.
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return NULL;
+  init::Initialize();
+  RSScriptContext *rsctx = new (std::nothrow) RSScriptContext();
+  if (rsctx != NULL) {
+    rsctx->script = NULL;
+    rsctx->result = NULL;
   }
-
-  Source *source = Source::CreateEmpty(*context, "empty");
-  return wrap(new RSScript(*source));
+  return wrap(rsctx);
 }
 
 
 extern "C" void bccDisposeScript(BCCScriptRef script) {
   BCC_FUNC_LOGGER();
-  delete unwrap(script);
+  RSScriptContext *rsctx = unwrap(script);
+  if (rsctx != NULL) {
+    delete rsctx->script;
+    delete rsctx->result;
+  }
+  delete rsctx;
 }
 
 
@@ -76,16 +77,18 @@
                                          BCCSymbolLookupFn pFn,
                                          void *pContext) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->registerSymbolCallback(pFn, pContext);
+  unwrap(script)->driver.setRSRuntimeLookupFunction(pFn);
+  unwrap(script)->driver.setRSRuntimeLookupContext(pContext);
+  return BCC_NO_ERROR;
 }
 
 
 extern "C" int bccGetError(BCCScriptRef script) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->getError();
+  return BCC_DEPRECATED_API;
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
                               char const *pName,
                               char const *pBitcode,
                               size_t pBitcodeSize,
@@ -100,76 +103,119 @@
     ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to suppress this warning.\n");
   }
 
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return false;
-  }
-
-  Source *source = Source::CreateFromBuffer(*context, pName,
+  Source *source = Source::CreateFromBuffer(pCtx->context, pName,
                                             pBitcode, pBitcodeSize);
   if (source == NULL) {
     return false;
   }
 
+  if (pCtx->script == NULL) {
+    pCtx->script = new (std::nothrow) RSScript(*source);
+    if (pCtx->script == NULL) {
+      ALOGE("Out of memory during script creation.");
+      return false;
+    }
+  } else {
+    bool result;
+    if (pIsLink) {
+      result = pCtx->script->mergeSource(*source);
+    } else {
+      result = pCtx->script->reset(*source);
+    }
+    if (!result) {
+      return false;
+    } else {
+      bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
+      pCtx->script->setCompilerVersion(wrapper.getCompilerVersion());
+      pCtx->script->setOptimizationLevel(
+          static_cast<RSScript::OptimizationLevel>(
+              wrapper.getOptimizationLevel()));
+    }
+  }
+
   if (need_dependency_check) {
     uint8_t sha1[20];
     calcSHA1(sha1, pBitcode, pBitcodeSize);
-    if (!pScript->addSourceDependency(pName, sha1)) {
+    if (!pCtx->script->addSourceDependency(pName, sha1)) {
       return false;
     }
   }
 
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+  return true;
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
                               llvm::Module *pModule,
                               bool pIsLink) {
-  if (pModule == NULL)
-    return false;
-
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return false;
-  }
-
   if (pModule == NULL) {
     ALOGE("Cannot add null module to script!");
     return false;
   }
 
-  Source *source = Source::CreateFromModule(*context, *pModule, true);
+  Source *source = Source::CreateFromModule(pCtx->context, *pModule, true);
   if (source == NULL) {
     return false;
   }
 
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+  if (pCtx->script == NULL) {
+    pCtx->script = new (std::nothrow) RSScript(*source);
+    if (pCtx->script == NULL) {
+      ALOGE("Out of memory during script creation.");
+      return false;
+    }
+  } else {
+    bool result;
+    if (pIsLink) {
+      result = pCtx->script->mergeSource(*source);
+    } else {
+      result = pCtx->script->reset(*source);
+    }
+    if (!result) {
+      return false;
+    }
+  }
+
+  return true;
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
                               char const *pPath,
                               unsigned long pFlags,
                               bool pIsLink) {
   bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
+
+  Source *source = Source::CreateFromFile(pCtx->context, pPath);
+  if (source == NULL) {
     return false;
   }
 
-  Source *source = Source::CreateFromFile(*context, pPath);
-  if (source == NULL) {
-    return false;
+  if (pCtx->script == NULL) {
+    pCtx->script = new (std::nothrow) RSScript(*source);
+    if (pCtx->script == NULL) {
+      ALOGE("Out of memory during script creation.");
+      return false;
+    }
+  } else {
+    bool result;
+    if (pIsLink) {
+      result = pCtx->script->mergeSource(*source);
+    } else {
+      result = pCtx->script->reset(*source);
+    }
+    if (!result) {
+      return false;
+    }
   }
 
   if (need_dependency_check) {
     uint8_t sha1[20];
     calcFileSHA1(sha1, pPath);
-    if (!pScript->addSourceDependency(pPath, sha1)) {
+    if (!pCtx->script->addSourceDependency(pPath, sha1)) {
       return false;
     }
   }
 
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+  return true;
 }
 
 extern "C" int bccReadBC(BCCScriptRef script,
@@ -226,7 +272,7 @@
 
 extern "C" void bccMarkExternalSymbol(BCCScriptRef script, char const *name) {
   BCC_FUNC_LOGGER();
-  unwrap(script)->markExternalSymbol(name);
+  return /* BCC_DEPRECATED_API */;
 }
 
 
@@ -235,32 +281,7 @@
                                      bccRelocModelEnum RelocModel,
                                      unsigned long flags) {
   BCC_FUNC_LOGGER();
-  llvm::Reloc::Model RM;
-
-  switch (RelocModel) {
-    case bccRelocDefault: {
-      RM = llvm::Reloc::Default;
-      break;
-    }
-    case bccRelocStatic: {
-      RM = llvm::Reloc::Static;
-      break;
-    }
-    case bccRelocPIC: {
-      RM = llvm::Reloc::PIC_;
-      break;
-    }
-    case bccRelocDynamicNoPIC: {
-      RM = llvm::Reloc::DynamicNoPIC;
-      break;
-    }
-    default: {
-      ALOGE("Unrecognized relocation model for bccPrepareObject!");
-      return BCC_INVALID_VALUE;
-    }
-  }
-
-  return unwrap(script)->prepareRelocatable(objPath, RM, flags);
+  return BCC_DEPRECATED_API;
 }
 
 
@@ -269,7 +290,7 @@
                                       char const *dsoPath,
                                       unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->prepareSharedObject(objPath, dsoPath, flags);
+  return BCC_DEPRECATED_API;
 }
 
 
@@ -281,14 +302,41 @@
 
   android::StopWatch compileTimer("bcc: PrepareExecutable time");
 
-  return unwrap(script)->prepareExecutable(cacheDir, cacheName, flags);
+  RSScriptContext *rsctx = unwrap(script);
+
+  if (rsctx->script == NULL) {
+    return 1;
+  }
+
+  // Construct the output path.
+  std::string output_path(cacheDir);
+  if (!output_path.empty() && (*output_path.rbegin() != '/')) {
+    output_path.append(1, '/');
+  }
+  output_path.append(cacheName);
+  output_path.append(".o");
+
+  // Make sure the result container is clean.
+  if (rsctx->result != NULL) {
+    delete rsctx->result;
+    rsctx->result = NULL;
+  }
+
+  rsctx->result = rsctx->driver.build(*rsctx->script, output_path);
+
+  return (rsctx->result == NULL);
 }
 
 
 extern "C" void *bccGetFuncAddr(BCCScriptRef script, char const *funcname) {
   BCC_FUNC_LOGGER();
 
-  void *addr = unwrap(script)->lookup(funcname);
+  RSScriptContext *rsctx = unwrap(script);
+
+  void *addr = NULL;
+  if (rsctx->result != NULL) {
+    addr = rsctx->result->getSymbolAddress(funcname);
+  }
 
 #if DEBUG_BCC_REFLECT
   ALOGD("Function Address: %s --> %p\n", funcname, addr);
@@ -303,19 +351,27 @@
                                     void **varList) {
   BCC_FUNC_LOGGER();
 
-  if (varList) {
-    unwrap(script)->getExportVarList(varListSize, varList);
-
-#if DEBUG_BCC_REFLECT
-    size_t count = unwrap(script)->getExportVarCount();
-    ALOGD("ExportVarCount = %lu\n", (unsigned long)count);
+  const RSScriptContext *rsctx = unwrap(script);
+  if (varList && rsctx->result) {
+    const android::Vector<void *> &export_var_addrs =
+        rsctx->result->getExportVarAddrs();
+    size_t count = export_var_addrs.size();
 
     if (count > varListSize) {
       count = varListSize;
     }
 
     for (size_t i = 0; i < count; ++i) {
-      ALOGD("ExportVarList[%lu] = %p\n", (unsigned long)i, varList[i]);
+      varList[i] = export_var_addrs[i];
+    }
+
+#if DEBUG_BCC_REFLECT
+    ALOGD("ExportVarCount = %lu\n",
+          static_cast<unsigned long>(export_var_addrs.size()));
+
+    for (size_t i = 0; i < count; ++i) {
+      ALOGD("ExportVarList[%lu] = %p\n", static_cast<unsigned long>(i),
+            varList[i]);
     }
 #endif
   }
@@ -327,19 +383,27 @@
                                      void **funcList) {
   BCC_FUNC_LOGGER();
 
-  if (funcList) {
-    unwrap(script)->getExportFuncList(funcListSize, funcList);
-
-#if DEBUG_BCC_REFLECT
-    size_t count = unwrap(script)->getExportFuncCount();
-    ALOGD("ExportFuncCount = %lu\n", (unsigned long)count);
+  const RSScriptContext *rsctx = unwrap(script);
+  if (funcList && rsctx->result) {
+    const android::Vector<void *> &export_func_addrs =
+        rsctx->result->getExportFuncAddrs();
+    size_t count = export_func_addrs.size();
 
     if (count > funcListSize) {
       count = funcListSize;
     }
 
     for (size_t i = 0; i < count; ++i) {
-      ALOGD("ExportFuncList[%lu] = %p\n", (unsigned long)i, funcList[i]);
+      funcList[i] = export_func_addrs[i];
+    }
+
+#if DEBUG_BCC_REFLECT
+    ALOGD("ExportFuncCount = %lu\n",
+          static_cast<unsigned long>(export_var_addrs.size()));
+
+    for (size_t i = 0; i < count; ++i) {
+      ALOGD("ExportFuncList[%lu] = %p\n", static_cast<unsigned long>(i),
+            varList[i]);
     }
 #endif
   }
@@ -351,19 +415,27 @@
                                         void **forEachList) {
   BCC_FUNC_LOGGER();
 
-  if (forEachList) {
-    unwrap(script)->getExportForEachList(forEachListSize, forEachList);
-
-#if DEBUG_BCC_REFLECT
-    size_t count = unwrap(script)->getExportForEachCount();
-    ALOGD("ExportForEachCount = %lu\n", (unsigned long)count);
+  const RSScriptContext *rsctx = unwrap(script);
+  if (forEachList && rsctx->result) {
+    const android::Vector<void *> &export_foreach_func_addrs =
+        rsctx->result->getExportForeachFuncAddrs();
+    size_t count = export_foreach_func_addrs.size();
 
     if (count > forEachListSize) {
       count = forEachListSize;
     }
 
     for (size_t i = 0; i < count; ++i) {
-      ALOGD("ExportForEachList[%lu] = %p\n", (unsigned long)i, forEachList[i]);
+      forEachList[i] = export_foreach_func_addrs[i];
+    }
+
+#if DEBUG_BCC_REFLECT
+    ALOGD("ExportForEachCount = %lu\n",
+          static_cast<unsigned long>(export_foreach_func_addrs.size()));
+
+    for (size_t i = 0; i < count; ++i) {
+      ALOGD("ExportForEachList[%lu] = %p\n", static_cast<unsigned long>(i),
+            forEachList[i]);
     }
 #endif
   }
diff --git a/lib/ExecutionEngine/bcc_internal.h b/lib/ExecutionEngine/bcc_internal.h
index 553034c..c003d6c 100644
--- a/lib/ExecutionEngine/bcc_internal.h
+++ b/lib/ExecutionEngine/bcc_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * 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.
@@ -19,6 +19,9 @@
 
 #include <bcc/bcc.h>
 
+#include "BCCContext.h"
+#include "RSCompilerDriver.h"
+
 #if defined(__cplusplus)
 
 #define BCC_OPAQUE_TYPE_CONVERSION(TRANSPARENT_TYPE, OPAQUE_TYPE)           \
@@ -35,17 +38,23 @@
 }
 
 namespace bcc {
-  class RSScript;
 
-  /* Function information struct */
-  struct FuncInfo {
-    char const *name;
-    void *addr;
-    size_t size;
-  };
+class RSScript;
+class RSExecutable;
 
-  BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScript *, BCCScriptRef);
-  BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
+struct RSScriptContext {
+  // The context required in libbcc.
+  BCCContext context;
+  // The compiler driver
+  RSCompilerDriver driver;
+  // The script hold the source which is about to compile.
+  RSScript *script;
+  // The compilation result.
+  RSExecutable *result;
+};
+
+BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScriptContext *, BCCScriptRef);
+BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
 
 } // namespace bcc