Remove Compiler class from bcc.cpp.
diff --git a/bcc.cpp b/bcc.cpp
index 1c7cd49..6b0dcc8 100644
--- a/bcc.cpp
+++ b/bcc.cpp
@@ -17,2114 +17,177 @@
 // Bitcode compiler (bcc) for Android:
 //    This is an eager-compilation JIT running on Android.
 
-#define BCC_MMAP_IMG_BEGIN 0x7e000000
-#define BCC_MMAP_IMG_COUNT 5
-
-#define BCC_MMAP_IMG_CODE_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_DATA_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_SIZE (BCC_MMAP_IMG_CODE_SIZE + BCC_MMAP_IMG_DATA_SIZE)
-
-
-// Design of caching EXE:
-// ======================
-// 1. Each process will have virtual address available starting at 0x7e00000.
-//    E.g., Books and Youtube all have its own 0x7e00000. Next, we should
-//    minimize the chance of needing to do relocation INSIDE an app too.
-//
-// 2. Each process will have ONE class static variable called BccCodeAddr.
-//    I.e., even though the Compiler class will have multiple Compiler objects,
-//    e.g, one object for carousel.rs and the other for pageturn.rs,
-//    both Compiler objects will share 1 static variable called BccCodeAddr.
-//
-// Key observation: Every app (process) initiates, say 3, scripts (which
-// correspond to 3 Compiler objects) in the same order, usually.
-//
-// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
-// scripts, respectively. Each time, BccCodeAddr should be updated after
-// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
-// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
-// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
-// ever be needed.)
-//
-// If we are lucky, then we don't need relocation ever, since next time the
-// application gets run, the 3 scripts are likely created in the SAME order.
-//
-//
-// End-to-end algorithm on when to caching and when to JIT:
-// ========================================================
-// Prologue:
-// ---------
-// Assertion: bccReadBC() is always called and is before bccCompileBC(),
-// bccLoadBinary(), ...
-//
-// Key variable definitions: Normally,
-//  Compiler::BccCodeAddr: non-zero if (USE_CACHE)
-//  | (Stricter, because currently relocation doesn't work. So mUseCache only
-//  |  when BccCodeAddr is nonzero.)
-//  V
-//  mUseCache: In addition to (USE_CACHE), resName is non-zero
-//  Note: mUseCache will be set to false later on whenever we find that caching
-//        won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
-//        This is because currently relocation doesn't work.
-//  | (Stricter, initially)
-//  V
-//  mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
-//  | (Stricter)
-//  V
-//  mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
-//             at the end of compile()
-//
-//
-// Main algorithm:
-// ---------------
-// #if !USE_RELOCATE
-// Case 1. ReadBC() doesn't detect a cache file:
-//   compile(), which calls genCacheFile() at the end.
-//   Note: mCacheNew will guard the invocation of genCacheFile()
-// Case 2. ReadBC() find a cache file
-//   loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
-// #endif
-
 #define LOG_TAG "bcc"
 #include <cutils/log.h>
 
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include <bcc/bcc.h>
 
-#include <cutils/hashmap.h>
+#include "bcc_compiler.h"
+
 #include <utils/StopWatch.h>
 
-#if defined(__arm__)
-#   define DEFAULT_ARM_CODEGEN
-#   define PROVIDE_ARM_CODEGEN
-#elif defined(__i386__)
-#   define DEFAULT_X86_CODEGEN
-#   define PROVIDE_X86_CODEGEN
-#elif defined(__x86_64__)
-#   define DEFAULT_X64_CODEGEN
-#   define PROVIDE_X64_CODEGEN
-#endif
 
-#if defined(FORCE_ARM_CODEGEN)
-#   define DEFAULT_ARM_CODEGEN
-#   undef DEFAULT_X86_CODEGEN
-#   undef DEFAULT_X64_CODEGEN
-#   define PROVIDE_ARM_CODEGEN
-#   undef PROVIDE_X86_CODEGEN
-#   undef PROVIDE_X64_CODEGEN
-#elif defined(FORCE_X86_CODEGEN)
-#   undef DEFAULT_ARM_CODEGEN
-#   define DEFAULT_X86_CODEGEN
-#   undef DEFAULT_X64_CODEGEN
-#   undef PROVIDE_ARM_CODEGEN
-#   define PROVIDE_X86_CODEGEN
-#   undef PROVIDE_X64_CODEGEN
-#elif defined(FORCE_X64_CODEGEN)
-#   undef DEFAULT_ARM_CODEGEN
-#   undef DEFAULT_X86_CODEGEN
-#   define DEFAULT_X64_CODEGEN
-#   undef PROVIDE_ARM_CODEGEN
-#   undef PROVIDE_X86_CODEGEN
-#   define PROVIDE_X64_CODEGEN
-#endif
-
-#if defined(DEFAULT_ARM_CODEGEN)
-#   define TARGET_TRIPLE_STRING    "armv7-none-linux-gnueabi"
-#elif defined(DEFAULT_X86_CODEGEN)
-#   define TARGET_TRIPLE_STRING    "i686-unknown-linux"
-#elif defined(DEFAULT_X64_CODEGEN)
-#   define  TARGET_TRIPLE_STRING   "x86_64-unknown-linux"
-#endif
-
-#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
-#   define ARM_USE_VFP
-#endif
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_cache.h>
-#include "bcc_code_emitter.h"
-#include "bcc_code_mem_manager.h"
-#include "bcc_emitted_func_code.h"
-#include "bcc_runtime.h"
-
-#define LOG_API(...) do {} while (0)
-// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
-
-#define LOG_STACK(...) do {} while (0)
-// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
-
-// #define PROVIDE_TRACE_CODEGEN
-
-#if defined(USE_DISASSEMBLER)
-#   include "bcc_buff_mem_object.h"
-#   include "llvm/MC/MCInst.h"
-#   include "llvm/MC/MCAsmInfo.h"
-#   include "llvm/MC/MCInstPrinter.h"
-#   include "llvm/MC/MCDisassembler.h"
-// If you want the disassemble results written to file, define this:
-#   define USE_DISASSEMBLER_FILE
-#endif
-
-#include <set>
-#include <map>
-#include <list>
-#include <cmath>
-#include <string>
-#include <cstring>
-#include <algorithm>  // for std::reverse
-
-// VMCore
-#include "llvm/Use.h"
-#include "llvm/User.h"
-#include "llvm/Linker.h"
-#include "llvm/Module.h"
-#include "llvm/Function.h"
-#include "llvm/Constant.h"
-#include "llvm/Constants.h"
-#include "llvm/Instruction.h"
-#include "llvm/PassManager.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Instructions.h"
-#include "llvm/OperandTraits.h"
-#include "llvm/TypeSymbolTable.h"
-
-// System
-#include "llvm/System/Host.h"
-
-// ADT
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/ValueMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallString.h"
-
-// Target
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetJITInfo.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/SubtargetFeature.h"
-
-// Support
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/ValueHandle.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/StandardPasses.h"
-#include "llvm/Support/FormattedStream.h"
-
-// Bitcode
-#include "llvm/Bitcode/ReaderWriter.h"
-
-// CodeGen
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/JITCodeEmitter.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/RegAllocRegistry.h"
-#include "llvm/CodeGen/SchedulerRegistry.h"
-#include "llvm/CodeGen/MachineRelocation.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
-
-// ExecutionEngine
-#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-
-extern "C" void LLVMInitializeARMDisassembler();
-
-#define TEMP_FAILURE_RETRY1(exp) ({         \
-    typeof (exp) _rc;                      \
-    do {                                   \
-        _rc = (exp);                       \
-    } while (_rc == -1 && errno == EINTR); \
-    _rc; })
-
-static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
-{
-    while (count != 0) {
-        ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
-        if (actual < 0) {
-            int err = errno;
-            LOGE("%s: write failed: %s\n", logMsg, strerror(err));
-            return err;
-        } else if (actual != (ssize_t) count) {
-            LOGD("%s: partial write (will retry): (%d of %zd)\n",
-                logMsg, (int) actual, count);
-            buf = (const void*) (((const uint8_t*) buf) + actual);
-        }
-        count -= actual;
-    }
-
-    return 0;
+namespace llvm {
+  class Module;
 }
 
-//
-// Compilation class that suits Android's needs.
-// (Support: no argument passed, ...)
-//
+
 namespace bcc {
 
-class Compiler {
-  // This part is designed to be orthogonal to those exported bcc*() functions
-  // implementation and internal struct BCCscript.
+  struct BCCscript {
+    //////////////////////////////////////////////////////////////////////////
+    // Part I. Compiler
+    //////////////////////////////////////////////////////////////////////////
+    Compiler compiler;
 
-  //////////////////////////////////////////////////////////////////////////////
-  // The variable section below (e.g., Triple, CodeGenOptLevel)
-  // is initialized in GlobalInitialization()
-  //
-  static bool GlobalInitialized;
-  static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
+    void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
+      compiler.registerSymbolCallback(pFn, pContext);
+    }
 
-  // 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;
+    //////////////////////////////////////////////////////////////////////////
+    // Part II. Logistics & Error handling
+    //////////////////////////////////////////////////////////////////////////
+    BCCscript() {
+      bccError = BCC_NO_ERROR;
+    }
 
-  static llvm::CodeGenOpt::Level CodeGenOptLevel;
+    ~BCCscript() {
+    }
 
-  // End of section of GlobalInitializing variables
-  //////////////////////////////////////////////////////////////////////////////
+    void setError(BCCenum error) {
+      if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
+        bccError = error;
+      }
+    }
 
-  // If given, the name of the target CPU to generate code for.
-  static std::string CPU;
+    BCCenum getError() {
+      BCCenum result = bccError;
+      bccError = BCC_NO_ERROR;
+      return result;
+    }
 
-  // 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;
-
-  struct Runtime {
-      const char *mName;
-      void *mPtr;
+    BCCenum bccError;
   };
-  static struct Runtime Runtimes[];
 
-  static void GlobalInitialization() {
-    if (GlobalInitialized)
-      return;
 
-    // if (!llvm::llvm_is_multithreaded())
-    //   llvm::llvm_start_multithreaded();
-
-    // Set Triple, CPU and Features here
-    Triple = TARGET_TRIPLE_STRING;
-
-    // TODO(sliao): NEON for JIT
-    // Features.push_back("+neon");
-    // Features.push_back("+vmlx");
-    // Features.push_back("+neonfp");
-    Features.push_back("+vfp3");
-    Features.push_back("+d16");
-
-#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
-    LLVMInitializeARMTargetInfo();
-    LLVMInitializeARMTarget();
-#if defined(USE_DISASSEMBLER)
-    LLVMInitializeARMDisassembler();
-    LLVMInitializeARMAsmPrinter();
-#endif
-#endif
-
-#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
-    LLVMInitializeX86TargetInfo();
-    LLVMInitializeX86Target();
-#if defined(USE_DISASSEMBLER)
-    LLVMInitializeX86Disassembler();
-    LLVMInitializeX86AsmPrinter();
-#endif
-#endif
-
-#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
-    LLVMInitializeX86TargetInfo();
-    LLVMInitializeX86Target();
-#if defined(USE_DISASSEMBLER)
-    LLVMInitializeX86Disassembler();
-    LLVMInitializeX86AsmPrinter();
-#endif
-#endif
-
-     // -O0: llvm::CodeGenOpt::None
-     // -O1: llvm::CodeGenOpt::Less
-     // -O2: llvm::CodeGenOpt::Default
-     // -O3: llvm::CodeGenOpt::Aggressive
-    CodeGenOptLevel = llvm::CodeGenOpt::None;
-
-    // Below are the global settings to LLVM
-
-    // Disable frame pointer elimination optimization
-    llvm::NoFramePointerElim = false;
-
-     // 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
-     //
-     // llvm::FloatABIType = llvm::FloatABI::Soft;
-     // llvm::UseSoftFloat = true;
-     //
-    llvm::FloatABIType = llvm::FloatABI::Soft;
-    llvm::UseSoftFloat = false;
-
-    // BCC needs all unknown symbols resolved at JIT/compilation time.
-    // So we don't need any dynamic relocation model.
-    llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
-
-#if defined(DEFAULT_X64_CODEGEN)
-    // Data address in X86_64 architecture may reside in a far-away place
-    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
-#else
-    // This is set for the linker (specify how large of the virtual addresses
-    // we can access for all unknown symbols.)
-    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
-#endif
-
-    // Register the scheduler
-    llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
-
-    // Register allocation policy:
-    //  createFastRegisterAllocator: fast but bad quality
-    //  createLinearScanRegisterAllocator: not so fast but good quality
-    llvm::RegisterRegAlloc::setDefault
-        ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
-         llvm::createFastRegisterAllocator :
-         llvm::createLinearScanRegisterAllocator);
-
-    GlobalInitialized = true;
-    return;
+  extern "C" BCCscript *bccCreateScript() {
+    return new BCCscript();
   }
 
-  static void LLVMErrorHandler(void *UserData, const std::string &Message) {
-    std::string *Error = static_cast<std::string*>(UserData);
-    Error->assign(Message);
-    LOGE("%s", Message.c_str());
-    exit(1);
+  extern "C" BCCenum bccGetError(BCCscript *script) {
+    return script->getError();
   }
 
-  static const llvm::StringRef PragmaMetadataName;
-  static const llvm::StringRef ExportVarMetadataName;
-  static const llvm::StringRef ExportFuncMetadataName;
-
- private:
-  std::string mError;
-
-  inline bool hasError() const {
-    return !mError.empty();
-  }
-  inline void setError(const char *Error) {
-    mError.assign(Error);  // Copying
-    return;
-  }
-  inline void setError(const std::string &Error) {
-    mError = Error;
-    return;
+  extern "C" void bccDeleteScript(BCCscript *script) {
+    delete script;
   }
 
-  bool mUseCache;       // Set by readBC()
-  bool mCacheNew;         // Set by readBC()
-  int mCacheFd;           // Set by readBC()
-  char *mCacheMapAddr;    // Set by loadCacheFile() if mCacheNew is false
-  oBCCHeader *mCacheHdr;  // Set by loadCacheFile()
-  size_t mCacheSize;      // Set by loadCacheFile()
-  ptrdiff_t mCacheDiff;   // Set by loadCacheFile()
-  char *mCodeDataAddr;    // Set by CodeMemoryManager if mCacheNew is true.
-                          // Used by genCacheFile() for dumping
-
-  typedef std::list< std::pair<std::string, std::string> > PragmaList;
-  PragmaList mPragmas;
-
-  typedef std::list<void*> ExportVarList;
-  ExportVarList mExportVars;
-
-  typedef std::list<void*> ExportFuncList;
-  ExportFuncList mExportFuncs;
-
-  // The memory manager for code emitter
-  llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
-  CodeMemoryManager *createCodeMemoryManager() {
-    mCodeMemMgr.reset(new CodeMemoryManager());
-    return mCodeMemMgr.get();
+  extern "C" void bccRegisterSymbolCallback(BCCscript *script,
+                                            BCCSymbolLookupFn pFn,
+                                            BCCvoid *pContext) {
+    script->registerSymbolCallback(pFn, pContext);
   }
 
-  // The CodeEmitter
-  llvm::OwningPtr<CodeEmitter> mCodeEmitter;
-  CodeEmitter *createCodeEmitter() {
-    mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
-    return mCodeEmitter.get();
+  extern "C" int bccReadModule(BCCscript *script, BCCvoid *module) {
+    return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
   }
 
-  BCCSymbolLookupFn mpSymbolLookupFn;
-  void *mpSymbolLookupContext;
-
-  llvm::LLVMContext *mContext;
-  llvm::Module *mModule;
-
-  bool mHasLinked;
-
- public:
-  Compiler()
-      : mUseCache(false),
-        mCacheNew(false),
-        mCacheFd(-1),
-        mCacheMapAddr(NULL),
-        mCacheHdr(NULL),
-        mCacheSize(0),
-        mCacheDiff(0),
-        mCodeDataAddr(NULL),
-        mpSymbolLookupFn(NULL),
-        mpSymbolLookupContext(NULL),
-        mContext(NULL),
-        mModule(NULL),
-        mHasLinked(false) /* Turn off linker */ {
-    llvm::remove_fatal_error_handler();
-    llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
-    mContext = new llvm::LLVMContext();
-    return;
+  extern "C" int bccReadBC(BCCscript *script,
+                           const BCCchar *bitcode,
+                           BCCint size,
+                           const BCCchar *resName) {
+    return script->compiler.readBC(bitcode, size, resName);
   }
 
-  // interface for BCCscript::registerSymbolCallback()
-  void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
-    mpSymbolLookupFn = pFn;
-    mpSymbolLookupContext = pContext;
-    return;
+  extern "C" void bccLinkBC(BCCscript *script,
+                            const BCCchar *bitcode,
+                            BCCint size) {
+    script->compiler.linkBC(bitcode, size);
   }
 
-  int readModule(llvm::Module *module) {
-    GlobalInitialization();
-    mModule = module;
-    return hasError();
-  }
-
-  int readBC(const char *bitcode,
-             size_t bitcodeSize,
-             const BCCchar *resName) {
-    GlobalInitialization();
-
-    if (resName) {
-      // Turn on mUseCache mode iff
-      // 1. Has resName
-      // and, assuming USE_RELOCATE is false:
-      // 2. Later running code doesn't violate the following condition:
-      //    mCodeDataAddr (set in loadCacheFile()) ==
-      //        mCacheHdr->cachedCodeDataAddr
-      //
-      //    BTW, this condition is achievable only when in the earlier
-      //    cache-generating run,
-      //      mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
-      //      which means the mmap'ed is in the reserved area,
-      //
-      //    Note: Upon violation, mUseCache will be set back to false.
-      mUseCache = true;
-
-      mCacheFd = openCacheFile(resName, true /* createIfMissing */);
-      if (mCacheFd >= 0 && !mCacheNew) {  // Just use cache file
-        return -mCacheFd;
-      }
-    }
-
-    llvm::OwningPtr<llvm::MemoryBuffer> MEM;
-
-    if (bitcode == NULL || bitcodeSize <= 0)
-      return 0;
-
-    // Package input to object MemoryBuffer
-    MEM.reset(llvm::MemoryBuffer::getMemBuffer(
-                llvm::StringRef(bitcode, bitcodeSize)));
-
-    if (MEM.get() == NULL) {
-      setError("Error reading input program bitcode into memory");
-      return hasError();
-    }
-
-    // Read the input Bitcode as a Module
-    mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
-    MEM.reset();
-    return hasError();
-  }
-
-  int linkBC(const char *bitcode, size_t bitcodeSize) {
-    llvm::OwningPtr<llvm::MemoryBuffer> MEM;
-
-    if (bitcode == NULL || bitcodeSize <= 0)
-      return 0;
-
-    if (mModule == NULL) {
-      setError("No module presents for linking");
-      return hasError();
-    }
-
-    MEM.reset(llvm::MemoryBuffer::getMemBuffer(
-                llvm::StringRef(bitcode, bitcodeSize)));
-
-    if (MEM.get() == NULL) {
-      setError("Error reading input library bitcode into memory");
-      return hasError();
-    }
-
-    llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
-                                                             *mContext,
-                                                             &mError));
-    if (Lib.get() == NULL)
-      return hasError();
-
-    if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
-      return hasError();
-
-    // Everything for linking should be settled down here with no error occurs
-    mHasLinked = true;
-    return hasError();
-  }
-
-  // interface for bccLoadBinary()
-  int loadCacheFile() {
-    // Check File Descriptor
-    if (mCacheFd < 0) {
-      LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
-      goto giveup;
-    }
-
-    // Check File Size
-    struct stat statCacheFd;
-    if (fstat(mCacheFd, &statCacheFd) < 0) {
-      LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
-      goto giveup;
-    }
-
-    mCacheSize = statCacheFd.st_size;
-
-    if (mCacheSize < sizeof(oBCCHeader) ||
-        mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
-      LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
-      goto giveup;
-    }
-
-    if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
-      LOGE("Unable to seek to 0: %s\n", strerror(errno));
-      goto giveup;
-    }
-
-    // Part 1. Deal with the non-codedata section first
-    {
-      // Read cached file and perform quick integrity check
-
-      off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
-      LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
-           (unsigned int)mCacheSize,
-           (unsigned long long int)heuristicCodeOffset);
-
-      mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
-      if (!mCacheMapAddr) {
-          flock(mCacheFd, LOCK_UN);
-          LOGE("allocation failed.\n");
-          goto bail;
-      }
-
-      size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
-                                              heuristicCodeOffset));
-      if (nread != (size_t)heuristicCodeOffset) {
-        LOGE("read(mCacheFd) failed\n");
-        goto bail;
-      }
-
-      mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
-      // Sanity check
-      if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
-        LOGE("assertion failed: heuristic code offset is not correct.\n");
-        goto bail;
-      }
-      LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
-      LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
-      LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
-      LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
-      LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
-
-      // Verify the Cache File
-      if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
-        LOGE("bad magic word\n");
-        goto bail;
-      }
-
-      if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
-        LOGE("bad oBCC version 0x%08x\n",
-             *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->relocOffset +
-          mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
-        LOGE("relocate table overflow\n");
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->exportVarsOffset +
-          mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
-        LOGE("export variables table overflow\n");
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->exportFuncsOffset +
-          mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
-        LOGE("export functions table overflow\n");
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->exportPragmasOffset +
-          mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
-        LOGE("export pragmas table overflow\n");
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
-        LOGE("code cache overflow\n");
-        goto bail;
-      }
-
-      if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
-        LOGE("data (global variable) cache overflow\n");
-        goto bail;
-      }
-
-      long pagesize = sysconf(_SC_PAGESIZE);
-      if (mCacheHdr->codeOffset % pagesize != 0) {
-        LOGE("code offset must aligned to pagesize\n");
-        goto bail;
-      }
-    }
-
-    // Part 2. Deal with the codedata section
-    {
-      long pagesize = sysconf(_SC_PAGESIZE);
-
-      if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
-        void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
-
-        // Try to mmap at cached address directly.
-        mCodeDataAddr = (char *) mmap(addr,
-                                      BCC_MMAP_IMG_SIZE,
-                                      PROT_READ | PROT_EXEC | PROT_WRITE,
-                                      MAP_PRIVATE | MAP_FIXED,
-                                      mCacheFd,
-                                      mCacheHdr->codeOffset);
-
-        if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
-          // Cheers!  Mapped at the cached address successfully.
-
-          // Update the BccMmapImgAddrTaken table (if required)
-          if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
-            size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
-
-            if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
-                (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
-              Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
-            }
-          }
-
-#if 1
-          // Check the checksum of code and data
-          {
-            uint32_t sum = mCacheHdr->checksum;
-            uint32_t *ptr = (uint32_t *)mCodeDataAddr;
-
-            for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
-              sum ^= *ptr++;
-            }
-
-            if (sum != 0) {
-              LOGE("Checksum check failed\n");
-              goto bail;
-            }
-
-            LOGE("Passed checksum even parity verification.\n");
-          }
-#endif
-
-          flock(mCacheFd, LOCK_UN);
-          return 0; // loadCacheFile succeed!
-        }
-      }
-    }
-
-#if !USE_RELOCATE
-    // Note: Since this build does not support relocation, we have no
-    // choose but give up to load the cached file, and recompile the
-    // code.
-
-    flock(mCacheFd, LOCK_UN);
-    goto bail;
-#else
-
-    // Note: Currently, relocation code is not working.  Give up now.
-    flock(mCacheFd, LOCK_UN);
-    goto bail;
-
-    // TODO(logan): Following code is not working.  Don't use them.
-    // And rewrite them asap.
-#if 0
-    {
-      // Try to allocate at arbitary address.  And perform relocation.
-      mCacheMapAddr = (char *) mmap(0,
-                                    mCacheSize,
-                                    PROT_READ | PROT_EXEC | PROT_WRITE,
-                                    MAP_PRIVATE,
-                                    mCacheFd,
-                                    0);
-
-      if (mCacheMapAddr == MAP_FAILED) {
-        LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
-        flock(mCacheFd, LOCK_UN);
-        goto giveup;
-      }
-
-      flock(mCacheFd, LOCK_UN);
-      mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
-
-      // Relocate
-      mCacheDiff = mCodeDataAddr -
-                   reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
-
-      if (mCacheDiff) {  // To relocate
-        if (mCacheHdr->rootAddr) {
-          mCacheHdr->rootAddr += mCacheDiff;
-        }
-
-        if (mCacheHdr->initAddr) {
-          mCacheHdr->initAddr += mCacheDiff;
-        }
-
-        oBCCRelocEntry *cachedRelocTable =
-            reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
-                                               mCacheHdr->relocOffset);
-
-        std::vector<llvm::MachineRelocation> relocations;
-
-        // Read in the relocs
-        for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
-          oBCCRelocEntry *entry = &cachedRelocTable[i];
-
-          llvm::MachineRelocation reloc =
-              llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
-                                             (unsigned)entry->relocType, 0, 0);
-
-          reloc.setResultPointer(
-              reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
-
-          relocations.push_back(reloc);
-        }
-
-        // Rewrite machine code using llvm::TargetJITInfo relocate
-        {
-          llvm::TargetMachine *TM = NULL;
-          const llvm::Target *Target;
-          std::string FeaturesStr;
-
-          // Create TargetMachine
-          Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
-          if (hasError())
-            goto bail;
-
-          if (!CPU.empty() || !Features.empty()) {
-            llvm::SubtargetFeatures F;
-            F.setCPU(CPU);
-            for (std::vector<std::string>::const_iterator I = Features.begin(),
-                     E = Features.end(); I != E; I++)
-              F.AddFeature(*I);
-            FeaturesStr = F.getString();
-          }
-
-          TM = Target->createTargetMachine(Triple, FeaturesStr);
-          if (TM == NULL) {
-            setError("Failed to create target machine implementation for the"
-                     " specified triple '" + Triple + "'");
-            goto bail;
-          }
-
-          TM->getJITInfo()->relocate(mCodeDataAddr,
-                                     &relocations[0], relocations.size(),
-                                     (unsigned char *)mCodeDataAddr+MaxCodeSize);
-
-          if (mCodeEmitter.get()) {
-            mCodeEmitter->Disassemble(llvm::StringRef("cache"),
-                                      reinterpret_cast<uint8_t*>(mCodeDataAddr),
-                                      2 * 1024 /*MaxCodeSize*/,
-                                      false);
-          }
-
-          delete TM;
-        }
-      }  // End of if (mCacheDiff)
-
-      return 0; // Success!
-    }
-#endif
-#endif
-
- bail:
-    if (mCacheMapAddr) {
-      free(mCacheMapAddr);
-    }
-
-    if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
-      if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
-        LOGE("munmap failed: %s\n", strerror(errno));
-      }
-    }
-
-    mCacheMapAddr = NULL;
-    mCacheHdr = NULL;
-    mCodeDataAddr = NULL;
-
- giveup:
-    return 1;
-  }
-
-  // interace for bccCompileBC()
-  int compile() {
-    llvm::TargetData *TD = NULL;
-
-    llvm::TargetMachine *TM = NULL;
-    const llvm::Target *Target;
-    std::string FeaturesStr;
-
-    llvm::FunctionPassManager *CodeGenPasses = NULL;
-
-    const llvm::NamedMDNode *PragmaMetadata;
-    const llvm::NamedMDNode *ExportVarMetadata;
-    const llvm::NamedMDNode *ExportFuncMetadata;
-
-    if (mModule == NULL)  // No module was loaded
-      return 0;
-
-    // Create TargetMachine
-    Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
-    if (hasError())
-      goto on_bcc_compile_error;
-
-    if (!CPU.empty() || !Features.empty()) {
-      llvm::SubtargetFeatures F;
-      F.setCPU(CPU);
-      for (std::vector<std::string>::const_iterator I = Features.begin(),
-              E = Features.end();
-           I != E;
-           I++)
-        F.AddFeature(*I);
-      FeaturesStr = F.getString();
-    }
-
-    TM = Target->createTargetMachine(Triple, FeaturesStr);
-    if (TM == NULL) {
-      setError("Failed to create target machine implementation for the"
-               " specified triple '" + Triple + "'");
-      goto on_bcc_compile_error;
-    }
-
-    // Create memory manager for creation of code emitter later.
-    if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
-      setError("Failed to startup memory management for further compilation");
-      goto on_bcc_compile_error;
-    }
-    mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
-
-    // Create code emitter
-    if (!mCodeEmitter.get()) {
-      if (!createCodeEmitter()) {
-        setError("Failed to create machine code emitter to complete"
-                 " the compilation");
-        goto on_bcc_compile_error;
-      }
-    } else {
-      // Reuse the code emitter
-      mCodeEmitter->reset();
-    }
-
-    mCodeEmitter->setTargetMachine(*TM);
-    mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
-                                         mpSymbolLookupContext);
-
-    // Get target data from Module
-    TD = new llvm::TargetData(mModule);
-
-    // Load named metadata
-    ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
-    ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
-    PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
-
-    // Create LTO passes and run them on the mModule
-    if (mHasLinked) {
-      llvm::TimePassesIsEnabled = true;  // TODO(all)
-      llvm::PassManager LTOPasses;
-      LTOPasses.add(new llvm::TargetData(*TD));
-
-      std::vector<const char*> ExportSymbols;
-
-      // A workaround for getting export variable and function name. Will refine
-      // it soon.
-      if (ExportVarMetadata) {
-        for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
-          llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
-          if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
-            llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
-            if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
-              llvm::StringRef ExportVarName =
-                  static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
-              ExportSymbols.push_back(ExportVarName.data());
-            }
-          }
-        }
-      }
-
-      if (ExportFuncMetadata) {
-        for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
-          llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
-          if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
-            llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
-            if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
-              llvm::StringRef ExportFuncName =
-                  static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
-              ExportSymbols.push_back(ExportFuncName.data());
-            }
-          }
-        }
-      }
-      // root() and init() are born to be exported
-      ExportSymbols.push_back("root");
-      ExportSymbols.push_back("init");
-
-      // We now create passes list performing LTO. These are copied from
-      // (including comments) llvm::createStandardLTOPasses().
-
-      // Internalize all other symbols not listed in ExportSymbols
-      LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
-
-      // 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());
-
-      // Now that we internalized some globals, see if we can hack on them!
-      LTOPasses.add(llvm::createGlobalOptimizerPass());
-
-      // Linking modules together can lead to duplicated global constants, only
-      // keep one copy of each constant...
-      LTOPasses.add(llvm::createConstantMergePass());
-
-      // Remove unused arguments from functions...
-      LTOPasses.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());
-
-      // Inline small functions
-      LTOPasses.add(llvm::createFunctionInliningPass());
-
-      // Remove dead EH info.
-      LTOPasses.add(llvm::createPruneEHPass());
-
-      // Internalize the globals again after inlining
-      LTOPasses.add(llvm::createGlobalOptimizerPass());
-
-      // Remove dead functions.
-      LTOPasses.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());
-
-      // The IPO passes may leave cruft around.  Clean up after them.
-      LTOPasses.add(llvm::createInstructionCombiningPass());
-      LTOPasses.add(llvm::createJumpThreadingPass());
-
-      // Break up allocas
-      LTOPasses.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.
-
-      // Hoist loop invariants.
-      LTOPasses.add(llvm::createLICMPass());
-
-      // Remove redundancies.
-      LTOPasses.add(llvm::createGVNPass());
-
-      // Remove dead memcpys.
-      LTOPasses.add(llvm::createMemCpyOptPass());
-
-      // Nuke dead stores.
-      LTOPasses.add(llvm::createDeadStoreEliminationPass());
-
-      // Cleanup and simplify the code after the scalar optimizations.
-      LTOPasses.add(llvm::createInstructionCombiningPass());
-
-      LTOPasses.add(llvm::createJumpThreadingPass());
-
-      // Delete basic blocks, which optimization passes may have killed.
-      LTOPasses.add(llvm::createCFGSimplificationPass());
-
-      // Now that we have optimized the program, discard unreachable functions.
-      LTOPasses.add(llvm::createGlobalDCEPass());
-
-      LTOPasses.run(*mModule);
-    }
-
-    // Create code-gen pass to run the code emitter
-    CodeGenPasses = new llvm::FunctionPassManager(mModule);
-    CodeGenPasses->add(TD);  // Will take the ownership of TD
-
-    if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
-                                       *mCodeEmitter,
-                                       CodeGenOptLevel)) {
-      setError("The machine code emission is not supported by BCC on target '"
-               + Triple + "'");
-      goto on_bcc_compile_error;
-    }
-
-    // Run the pass (the code emitter) on every non-declaration function in the
-    // module
-    CodeGenPasses->doInitialization();
-    for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
-         I != E;
-         I++)
-      if (!I->isDeclaration())
-        CodeGenPasses->run(*I);
-
-    CodeGenPasses->doFinalization();
-
-    // Copy the global address mapping from code emitter and remapping
-    if (ExportVarMetadata) {
-      for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
-        llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
-        if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
-          llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
-          if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
-            llvm::StringRef ExportVarName =
-                static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
-            CodeEmitter::global_addresses_const_iterator I, E;
-            for (I = mCodeEmitter->global_address_begin(),
-                    E = mCodeEmitter->global_address_end();
-                 I != E;
-                 I++) {
-              if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
-                continue;
-              if (ExportVarName == I->first->getName()) {
-                mExportVars.push_back(I->second);
-                break;
-              }
-            }
-            if (I != mCodeEmitter->global_address_end())
-              continue;  // found
-          }
-        }
-        // if reaching here, we know the global variable record in metadata is
-        // not found. So we make an empty slot
-        mExportVars.push_back(NULL);
-      }
-      assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
-              "Number of slots doesn't match the number of export variables!");
-    }
-
-    if (ExportFuncMetadata) {
-      for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
-        llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
-        if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
-          llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
-          if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
-            llvm::StringRef ExportFuncName =
-                static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
-            mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
-          }
-        }
-      }
-    }
-
-    // Tell code emitter now can release the memory using during the JIT since
-    // we have done the code emission
-    mCodeEmitter->releaseUnnecessary();
-
-    // Finally, read pragma information from the metadata node of the @Module if
-    // any.
-    if (PragmaMetadata)
-      for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
-        llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
-        if (Pragma != NULL &&
-           Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
-          llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
-          llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
-
-          if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
-             (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
-            llvm::StringRef PragmaName =
-                static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
-            llvm::StringRef PragmaValue =
-                static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
-
-            mPragmas.push_back(
-                std::make_pair(std::string(PragmaName.data(),
-                                           PragmaName.size()),
-                               std::string(PragmaValue.data(),
-                                           PragmaValue.size())));
-          }
-        }
-      }
-
- on_bcc_compile_error:
-    // LOGE("on_bcc_compiler_error");
-    if (CodeGenPasses) {
-      delete CodeGenPasses;
-    } else if (TD) {
-      delete TD;
-    }
-    if (TM)
-      delete TM;
-
-    if (mError.empty()) {
-      if (mUseCache && mCacheFd >= 0 && mCacheNew) {
-        genCacheFile();
-        flock(mCacheFd, LOCK_UN);
-      }
-
-      return false;
-    }
-
-    // LOGE(getErrorMessage());
-    return true;
-  }
-
-  // interface for bccGetScriptInfoLog()
-  char *getErrorMessage() {
-    return const_cast<char*>(mError.c_str());
-  }
-
-  // interface for bccGetScriptLabel()
-  void *lookup(const char *name) {
-    void *addr = NULL;
-    if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
-      if (!strcmp(name, "root")) {
-        addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
-      } else if (!strcmp(name, "init")) {
-        addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
-      }
-      return addr;
-    }
-
-    if (mCodeEmitter.get())
-      // Find function pointer
-      addr = mCodeEmitter->lookup(name);
-    return addr;
-  }
-
-  // Interface for bccGetExportVars()
-  void getExportVars(BCCsizei *actualVarCount,
-                     BCCsizei maxVarCount,
-                     BCCvoid **vars) {
-    int varCount;
-
-    if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
-      varCount = static_cast<int>(mCacheHdr->exportVarsCount);
-      if (actualVarCount)
-        *actualVarCount = varCount;
-      if (varCount > maxVarCount)
-        varCount = maxVarCount;
-      if (vars) {
-        uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
-                                            mCacheHdr->exportVarsOffset);
-
-        for (int i = 0; i < varCount; i++) {
-          *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
-                                mCacheDiff);
-          cachedVars++;
-        }
-      }
-      return;
-    }
-
-    varCount = mExportVars.size();
-    if (actualVarCount)
-      *actualVarCount = varCount;
-    if (varCount > maxVarCount)
-      varCount = maxVarCount;
-    if (vars) {
-      for (ExportVarList::const_iterator I = mExportVars.begin(),
-              E = mExportVars.end();
-           I != E;
-           I++) {
-        *vars++ = *I;
-      }
-    }
-
-    return;
-  }
-
-  // Interface for bccGetExportFuncs()
-  void getExportFuncs(BCCsizei *actualFuncCount,
-                      BCCsizei maxFuncCount,
-                      BCCvoid **funcs) {
-    int funcCount;
-
-    if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
-      funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
-      if (actualFuncCount)
-        *actualFuncCount = funcCount;
-      if (funcCount > maxFuncCount)
-        funcCount = maxFuncCount;
-      if (funcs) {
-        uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
-                                             mCacheHdr->exportFuncsOffset);
-
-        for (int i = 0; i < funcCount; i++) {
-          *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
-                                 mCacheDiff);
-          cachedFuncs++;
-        }
-      }
-      return;
-    }
-
-    funcCount = mExportFuncs.size();
-    if (actualFuncCount)
-      *actualFuncCount = funcCount;
-    if (funcCount > maxFuncCount)
-      funcCount = maxFuncCount;
-    if (funcs) {
-      for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
-              E = mExportFuncs.end();
-           I != E;
-           I++) {
-        *funcs++ = *I;
-      }
-    }
-
-    return;
-  }
-
-  // Interface for bccGetPragmas()
-  void getPragmas(BCCsizei *actualStringCount,
-                  BCCsizei maxStringCount,
-                  BCCchar **strings) {
-    int stringCount;
-    if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
-      if (actualStringCount)
-        *actualStringCount = 0;  // XXX
-      return;
-    }
-
-    stringCount = mPragmas.size() * 2;
-
-    if (actualStringCount)
-      *actualStringCount = stringCount;
-    if (stringCount > maxStringCount)
-      stringCount = maxStringCount;
-    if (strings) {
-      for (PragmaList::const_iterator it = mPragmas.begin();
-           stringCount > 0;
-           stringCount -= 2, it++) {
-        *strings++ = const_cast<BCCchar*>(it->first.c_str());
-        *strings++ = const_cast<BCCchar*>(it->second.c_str());
-      }
-    }
-
-    return;
-  }
-
-  // Interface for bccGetFunctions()
-  void getFunctions(BCCsizei *actualFunctionCount,
-                 BCCsizei maxFunctionCount,
-                 BCCchar **functions) {
-    if (mCodeEmitter.get())
-      mCodeEmitter->getFunctionNames(actualFunctionCount,
-                                     maxFunctionCount,
-                                     functions);
-    else
-      *actualFunctionCount = 0;
-
-    return;
-  }
-
-  // Interface for bccGetFunctionBinary()
-  void getFunctionBinary(BCCchar *function,
-                         BCCvoid **base,
-                         BCCsizei *length) {
-    if (mCodeEmitter.get()) {
-      mCodeEmitter->getFunctionBinary(function, base, length);
-    } else {
-      *base = NULL;
-      *length = 0;
-    }
-    return;
-  }
-
-  inline const llvm::Module *getModule() const {
-    return mModule;
-  }
-
-  ~Compiler() {
-    if (!mCodeMemMgr.get()) {
-      // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
-      // managed by CodeMemoryManager.
-
-      if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
-        if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
-          LOGE("munmap failed while releasing mCodeDataAddr\n");
-        }
-      }
-
-      if (mCacheMapAddr) {
-        free(mCacheMapAddr);
-      }
-
-      mCodeDataAddr = 0;
-      mCacheMapAddr = 0;
-    }
-
-    delete mModule;
-    // llvm::llvm_shutdown();
-    delete mContext;
-    return;
-  }
-
- private:
-  // Note: loadCacheFile() and genCacheFile() go hand in hand
-  void genCacheFile() {
-    if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
-      LOGE("Unable to seek to 0: %s\n", strerror(errno));
-      return;
-    }
-
-    bool codeOffsetNeedPadding = false;
-
-    uint32_t offset = sizeof(oBCCHeader);
-
-    // BCC Cache File Header
-    oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
-
-    if (!hdr) {
-      LOGE("Unable to allocate oBCCHeader.\n");
-      return;
-    }
-
-    // Magic Words
-    memcpy(hdr->magic, OBCC_MAGIC, 4);
-    memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
-
-    // Timestamp
-    hdr->sourceWhen = 0; // TODO(all)
-    hdr->rslibWhen = 0; // TODO(all)
-    hdr->libRSWhen = 0; // TODO(all)
-    hdr->libbccWhen = 0; // TODO(all)
-
-    // Current Memory Address (Saved for Recalculation)
-    hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
-    hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
-    hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
-
-    // Relocation Table Offset and Entry Count
-    hdr->relocOffset = sizeof(oBCCHeader);
-    hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
-
-    offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
-
-    // Export Variable Table Offset and Entry Count
-    hdr->exportVarsOffset = offset;
-    hdr->exportVarsCount = mExportVars.size();
-
-    offset += hdr->exportVarsCount * sizeof(uint32_t);
-
-    // Export Function Table Offset and Entry Count
-    hdr->exportFuncsOffset = offset;
-    hdr->exportFuncsCount = mExportFuncs.size();
-
-    offset += hdr->exportFuncsCount * sizeof(uint32_t);
-
-    // Export Pragmas Table Offset and Entry Count
-    hdr->exportPragmasOffset = offset;
-    hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
-
-    offset += hdr->exportPragmasCount * sizeof(uint32_t);
-
-    // Code Offset and Size
-
-    //#ifdef BCC_CODE_ADDR
-    {  // Always pad to the page boundary for now
-      long pagesize = sysconf(_SC_PAGESIZE);
-
-      if (offset % pagesize > 0) {
-        codeOffsetNeedPadding = true;
-        offset += pagesize - (offset % pagesize);
-      }
-    }
-    /*#else
-    if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
-      codeOffsetNeedPadding = true;
-      offset += 0x08 - (offset & 0x07);
-    }
-    #endif*/
-
-    hdr->codeOffset = offset;
-    hdr->codeSize = MaxCodeSize;
-
-    offset += hdr->codeSize;
-
-    // Data (Global Variable) Offset and Size
-    hdr->dataOffset = offset;
-    hdr->dataSize = MaxGlobalVarSize;
-
-    offset += hdr->dataSize;
-
-    // Checksum
-#if 1
-    {
-      // Note: This is an simple checksum implementation that are using xor
-      // to calculate even parity (for code and data only).
-
-      uint32_t sum = 0;
-      uint32_t *ptr = (uint32_t *)mCodeDataAddr;
-
-      for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
-        sum ^= *ptr++;
-      }
-
-      hdr->checksum = sum;
-    }
-#else
-    hdr->checksum = 0; // Set Field checksum. TODO(all)
-#endif
-
-    // Write Header
-    sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
-                  sizeof(oBCCHeader), "Write oBCC header");
-
-    // Write Relocation Entry Table
-    {
-      size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
-
-      oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
-
-      sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
-                    allocSize, "Write Relocation Entries");
-    }
-
-    // Write Export Variables Table
-    {
-      uint32_t *record, *ptr;
-
-      record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
-      ptr = record;
-
-      if (!record) {
-        goto bail;
-      }
-
-      for (ExportVarList::const_iterator I = mExportVars.begin(),
-               E = mExportVars.end(); I != E; I++) {
-        *ptr++ = reinterpret_cast<uint32_t>(*I);
-      }
-
-      sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
-                    hdr->exportVarsCount * sizeof(uint32_t),
-                    "Write ExportVars");
-
-      free(record);
-    }
-
-    // Write Export Functions Table
-    {
-      uint32_t *record, *ptr;
-
-      record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
-      ptr = record;
-
-      if (!record) {
-        goto bail;
-      }
-
-      for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
-               E = mExportFuncs.end(); I != E; I++) {
-        *ptr++ = reinterpret_cast<uint32_t>(*I);
-      }
-
-      sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
-                    hdr->exportFuncsCount * sizeof(uint32_t),
-                    "Write ExportFuncs");
-
-      free(record);
-    }
-
-
-    // TODO(all): Write Export Pragmas Table
-#if 0
-#else
-    // Note: As long as we have comment out export pragmas table code,
-    // we have to seek the position to correct offset.
-
-    lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
-#endif
-
-    if (codeOffsetNeedPadding) {
-      // requires additional padding
-      lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
-    }
-
-    // Write Generated Code and Global Variable
-    sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
-                  "Write code and global variable");
-
-    goto close_return;
-
-  bail:
-    if (ftruncate(mCacheFd, 0) != 0) {
-      LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
-    }
-
-  close_return:
-    free(hdr);
-    close(mCacheFd);
-    mCacheFd = -1;
-    return;
-  }
-
-  // OpenCacheFile() returns fd of the cache file.
-  // Input:
-  //   BCCchar *resName: Used to genCacheFileName()
-  //   bool createIfMissing: If false, turn off caching
-  // Output:
-  //   returns fd: If -1: Failed
-  //   mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
-  //              cache file's file descriptor
-  //              Note: openCacheFile() will check the cache file's validity,
-  //              such as Magic number, sourceWhen... dependencies.
-  int openCacheFile(const BCCchar *resName, bool createIfMissing) {
-    int fd, cc;
-    struct stat fdStat, fileStat;
-    bool readOnly = false;
-
-    char *cacheFileName = genCacheFileName(resName, ".oBCC");
-
-    mCacheNew = false;
-
- retry:
-    /*
-     * Try to open the cache file.  If we've been asked to,
-     * create it if it doesn't exist.
-     */
-    fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
-    if (fd < 0) {
-      fd = open(cacheFileName, O_RDONLY, 0);
-      if (fd < 0) {
-        if (createIfMissing) {
-          LOGW("Can't open bcc-cache '%s': %s\n",
-               cacheFileName, strerror(errno));
-          mUseCache = false;
-        }
-        return fd;
-      }
-      readOnly = true;
-    }
-
-    /*
-     * Grab an exclusive lock on the cache file.  If somebody else is
-     * working on it, we'll block here until they complete.
-     */
-    LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
-         cacheFileName, fd);
-
-    cc = flock(fd, LOCK_EX | LOCK_NB);
-    if (cc != 0) {
-      LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
-      cc = flock(fd, LOCK_EX);
-    }
-
-    if (cc != 0) {
-      LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
-      close(fd);
-      return -1;
-    }
-    LOGV("bcc:  locked cache file\n");
-
-    /*
-     * Check to see if the fd we opened and locked matches the file in
-     * the filesystem.  If they don't, then somebody else unlinked ours
-     * and created a new file, and we need to use that one instead.  (If
-     * we caught them between the unlink and the create, we'll get an
-     * ENOENT from the file stat.)
-     */
-    cc = fstat(fd, &fdStat);
-    if (cc != 0) {
-      LOGE("Can't stat open file '%s'\n", cacheFileName);
-      LOGV("bcc: unlocking cache file %s\n", cacheFileName);
-      goto close_fail;
-    }
-    cc = stat(cacheFileName, &fileStat);
-    if (cc != 0 ||
-        fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
-      LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
-      LOGV("bcc: unlocking cache file %s\n", cacheFileName);
-      flock(fd, LOCK_UN);
-      close(fd);
-      usleep(250 * 1000);     // if something is hosed, don't peg machine
-      goto retry;
-    }
-
-    /*
-     * We have the correct file open and locked.  If the file size is zero,
-     * then it was just created by us, and we want to fill in some fields
-     * in the "bcc" header and set "mCacheNew".  Otherwise, we want to
-     * verify that the fields in the header match our expectations, and
-     * reset the file if they don't.
-     */
-    if (fdStat.st_size == 0) {
-      if (readOnly) {  // The device is readOnly --> close_fail
-        LOGW("bcc: file has zero length and isn't writable\n");
-        goto close_fail;
-      }
-      /*cc = createEmptyHeader(fd);
-      if (cc != 0)
-        goto close_fail;
-      */
-      mCacheNew = true;
-      LOGV("bcc: successfully initialized new cache file\n");
-    } else {
-      // Calculate sourceWhen
-      // XXX
-      uint32_t sourceWhen = 0;
-      uint32_t rslibWhen = 0;
-      uint32_t libRSWhen = 0;
-      uint32_t libbccWhen = 0;
-      if (!checkHeaderAndDependencies(fd,
-                                      sourceWhen,
-                                      rslibWhen,
-                                      libRSWhen,
-                                      libbccWhen)) {
-        // If checkHeaderAndDependencies returns 0: FAILED
-        // Will truncate the file and retry to createIfMissing the file
-
-        if (readOnly) {  // Shouldn't be readonly.
-          /*
-           * We could unlink and rewrite the file if we own it or
-           * the "sticky" bit isn't set on the directory.  However,
-           * we're not able to truncate it, which spoils things.  So,
-           * give up now.
-           */
-          if (createIfMissing) {
-            LOGW("Cached file %s is stale and not writable\n",
-                 cacheFileName);
-          }
-          goto close_fail;
-        }
-
-        /*
-         * If we truncate the existing file before unlinking it, any
-         * process that has it mapped will fail when it tries to touch
-         * the pages? Probably OK because we use MAP_PRIVATE.
-         */
-        LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
-             cacheFileName);
-        if (ftruncate(fd, 0) != 0) {
-          LOGW("Warning: unable to truncate cache file '%s': %s\n",
-               cacheFileName, strerror(errno));
-          /* keep going */
-        }
-        if (unlink(cacheFileName) != 0) {
-          LOGW("Warning: unable to remove cache file '%s': %d %s\n",
-               cacheFileName, errno, strerror(errno));
-          /* keep going; permission failure should probably be fatal */
-        }
-        LOGV("bcc: unlocking cache file %s\n", cacheFileName);
-        flock(fd, LOCK_UN);
-        close(fd);
-        goto retry;
-      } else {
-        // Got cacheFile! Good to go.
-        LOGV("Good cache file\n");
-      }
-    }
-
-    assert(fd >= 0);
-    return fd;
-
- close_fail:
-    flock(fd, LOCK_UN);
-    close(fd);
-    return -1;
-  }  // End of openCacheFile()
-
-  char *genCacheFileName(const char *fileName, const char *subFileName) {
-    char nameBuf[512];
-    static const char kCachePath[] = "bcc-cache";
-    char absoluteFile[sizeof(nameBuf)];
-    const size_t kBufLen = sizeof(nameBuf) - 1;
-    const char *dataRoot;
-    char *cp;
-
-    // Get the absolute path of the raw/***.bc file.
-    absoluteFile[0] = '\0';
-    if (fileName[0] != '/') {
-      /*
-       * Generate the absolute path.  This doesn't do everything it
-       * should, e.g. if filename is "./out/whatever" it doesn't crunch
-       * the leading "./" out, but it'll do.
-       */
-      if (getcwd(absoluteFile, kBufLen) == NULL) {
-        LOGE("Can't get CWD while opening raw/***.bc file\n");
-        return NULL;
-      }
-      // TODO(srhines): strncat() is a bit dangerous
-      strncat(absoluteFile, "/", kBufLen);
-    }
-    strncat(absoluteFile, fileName, kBufLen);
-
-    if (subFileName != NULL) {
-      strncat(absoluteFile, "/", kBufLen);
-      strncat(absoluteFile, subFileName, kBufLen);
-    }
-
-    /* Turn the path into a flat filename by replacing
-     * any slashes after the first one with '@' characters.
-     */
-    cp = absoluteFile + 1;
-    while (*cp != '\0') {
-      if (*cp == '/') {
-        *cp = '@';
-      }
-      cp++;
-    }
-
-    /* Build the name of the cache directory.
-     */
-    dataRoot = getenv("ANDROID_DATA");
-    if (dataRoot == NULL)
-      dataRoot = "/data";
-    snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
-
-    /* Tack on the file name for the actual cache file path.
-     */
-    strncat(nameBuf, absoluteFile, kBufLen);
-
-    LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
-    return strdup(nameBuf);
-  }
-
-  /*
-   * Read the oBCC header, verify it, then read the dependent section
-   * and verify that data as well.
-   *
-   * On successful return, the file will be seeked immediately past the
-   * oBCC header.
-   */
-  bool checkHeaderAndDependencies(int fd,
-                                  uint32_t sourceWhen,
-                                  uint32_t rslibWhen,
-                                  uint32_t libRSWhen,
-                                  uint32_t libbccWhen) {
-    ssize_t actual;
-    oBCCHeader optHdr;
-    uint32_t val;
-    uint8_t const *magic, *magicVer;
-
-    /*
-     * Start at the start.  The "bcc" header, when present, will always be
-     * the first thing in the file.
-     */
-    if (lseek(fd, 0, SEEK_SET) != 0) {
-      LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
-      goto bail;
-    }
-
-    /*
-     * Read and do trivial verification on the bcc header.  The header is
-     * always in host byte order.
-     */
-    actual = read(fd, &optHdr, sizeof(optHdr));
-    if (actual < 0) {
-      LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
-      goto bail;
-    } else if (actual != sizeof(optHdr)) {
-      LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
-           (int) actual, sizeof(optHdr));
-      goto bail;
-    }
-
-    magic = optHdr.magic;
-    if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
-      /* not an oBCC file, or previous attempt was interrupted */
-      LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
-           magic[0], magic[1], magic[2], magic[3]);
-      goto bail;
-    }
-
-    magicVer = optHdr.magicVersion;
-    if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
-      LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
-           magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
-      goto bail;
-    }
-
-    /*
-     * Do the header flags match up with what we want?
-     *
-     * This is useful because it allows us to automatically regenerate
-     * a file when settings change (e.g. verification is now mandatory),
-     * but can cause difficulties if the thing we depend upon
-     * were handled differently than the current options specify.
-     *
-     * So, for now, we essentially ignore "expectVerify" and "expectOpt"
-     * by limiting the match mask.
-     *
-     * The only thing we really can't handle is incorrect byte-ordering.
-     */
-
-    val = optHdr.sourceWhen;
-    if (val && (val != sourceWhen)) {
-      LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
-           val, sourceWhen);
-      goto bail;
-    }
-    val = optHdr.rslibWhen;
-    if (val && (val != rslibWhen)) {
-      LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
-           val, rslibWhen);
-      goto bail;
-    }
-    val = optHdr.libRSWhen;
-    if (val && (val != libRSWhen)) {
-      LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
-           val, libRSWhen);
-      goto bail;
-    }
-    val = optHdr.libbccWhen;
-    if (val && (val != libbccWhen)) {
-      LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
-           val, libbccWhen);
-      goto bail;
-    }
-
-    return true;
-
- bail:
-    return false;
- }
-
-};
-// End of Class Compiler
-////////////////////////////////////////////////////////////////////////////////
-
-
-bool Compiler::GlobalInitialized = false;
-
-bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
-
-// Code generation optimization level for the compiler
-llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
-
-std::string Compiler::Triple;
-
-std::string Compiler::CPU;
-
-std::vector<std::string> Compiler::Features;
-
-// The named of metadata node that pragma resides (should be synced with
-// slang.cpp)
-const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
-
-// The named of metadata node that export variable name resides (should be
-// synced with slang_rs_metadata.h)
-const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
-
-// The named of metadata node that export function name resides (should be
-// synced with slang_rs_metadata.h)
-const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
-
-struct BCCscript {
-  //////////////////////////////////////////////////////////////////////////////
-  // Part I. Compiler
-  //////////////////////////////////////////////////////////////////////////////
-  Compiler compiler;
-
-  void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
-    compiler.registerSymbolCallback(pFn, pContext);
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  // Part II. Logistics & Error handling
-  //////////////////////////////////////////////////////////////////////////////
-  BCCscript() {
-    bccError = BCC_NO_ERROR;
-  }
-
-  ~BCCscript() {
-  }
-
-  void setError(BCCenum error) {
-    if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
-      bccError = error;
-    }
-  }
-
-  BCCenum getError() {
-    BCCenum result = bccError;
-    bccError = BCC_NO_ERROR;
-    return result;
-  }
-
-  BCCenum bccError;
-};
-
-
-extern "C"
-BCCscript *bccCreateScript() {
-  return new BCCscript();
-}
-
-extern "C"
-BCCenum bccGetError(BCCscript *script) {
-  return script->getError();
-}
-
-extern "C"
-void bccDeleteScript(BCCscript *script) {
-  delete script;
-}
-
-extern "C"
-void bccRegisterSymbolCallback(BCCscript *script,
-                               BCCSymbolLookupFn pFn,
-                               BCCvoid *pContext) {
-  script->registerSymbolCallback(pFn, pContext);
-}
-
-extern "C"
-int bccReadModule(BCCscript *script,
-                     BCCvoid *module) {
-  return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
-}
-
-extern "C"
-int bccReadBC(BCCscript *script,
-              const BCCchar *bitcode,
-              BCCint size,
-              const BCCchar *resName) {
-  return script->compiler.readBC(bitcode, size, resName);
-}
-
-extern "C"
-void bccLinkBC(BCCscript *script,
-                    const BCCchar *bitcode,
-                    BCCint size) {
-  script->compiler.linkBC(bitcode, size);
-}
-
-extern "C"
-void bccLoadBinary(BCCscript *script) {
-  int result = script->compiler.loadCacheFile();
-  if (result)
-    script->setError(BCC_INVALID_OPERATION);
-}
-
-extern "C"
-void bccCompileBC(BCCscript *script) {
-  {
-#if defined(__arm__)
-    android::StopWatch compileTimer("RenderScript compile time");
-#endif
-    int result = script->compiler.compile();
+  extern "C" void bccLoadBinary(BCCscript *script) {
+    int result = script->compiler.loadCacheFile();
     if (result)
       script->setError(BCC_INVALID_OPERATION);
   }
-}
 
-extern "C"
-void bccGetScriptInfoLog(BCCscript *script,
-                         BCCsizei maxLength,
-                         BCCsizei *length,
-                         BCCchar *infoLog) {
-  char *message = script->compiler.getErrorMessage();
-  int messageLength = strlen(message) + 1;
-  if (length)
-    *length = messageLength;
-
-  if (infoLog && maxLength > 0) {
-    int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
-    memcpy(infoLog, message, trimmedLength);
-    infoLog[trimmedLength] = 0;
+  extern "C" void bccCompileBC(BCCscript *script) {
+    {
+#if defined(__arm__)
+      android::StopWatch compileTimer("RenderScript compile time");
+#endif
+      int result = script->compiler.compile();
+      if (result)
+        script->setError(BCC_INVALID_OPERATION);
+    }
   }
-}
 
-extern "C"
-void bccGetScriptLabel(BCCscript *script,
-                       const BCCchar  *name,
-                       BCCvoid **address) {
-  void *value = script->compiler.lookup(name);
-  if (value)
-    *address = value;
-  else
-    script->setError(BCC_INVALID_VALUE);
-}
+  extern "C" void bccGetScriptInfoLog(BCCscript *script,
+                                      BCCsizei maxLength,
+                                      BCCsizei *length,
+                                      BCCchar *infoLog) {
+    char *message = script->compiler.getErrorMessage();
+    int messageLength = strlen(message) + 1;
+    if (length)
+      *length = messageLength;
 
-extern "C"
-void bccGetExportVars(BCCscript *script,
-                      BCCsizei *actualVarCount,
-                      BCCsizei maxVarCount,
-                      BCCvoid **vars) {
-  script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
-}
+    if (infoLog && maxLength > 0) {
+      int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
+      memcpy(infoLog, message, trimmedLength);
+      infoLog[trimmedLength] = 0;
+    }
+  }
 
-extern "C"
-void bccGetExportFuncs(BCCscript *script,
-                       BCCsizei *actualFuncCount,
-                       BCCsizei maxFuncCount,
-                       BCCvoid **funcs) {
-  script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
-}
+  extern "C" void bccGetScriptLabel(BCCscript *script,
+                                    const BCCchar *name,
+                                    BCCvoid **address) {
+    void *value = script->compiler.lookup(name);
+    if (value)
+      *address = value;
+    else
+      script->setError(BCC_INVALID_VALUE);
+  }
 
-extern "C"
-void bccGetPragmas(BCCscript *script,
-                   BCCsizei *actualStringCount,
-                   BCCsizei maxStringCount,
-                   BCCchar **strings) {
-  script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
-}
+  extern "C" void bccGetExportVars(BCCscript *script,
+                                   BCCsizei *actualVarCount,
+                                   BCCsizei maxVarCount,
+                                   BCCvoid **vars) {
+    script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
+  }
 
-extern "C"
-void bccGetFunctions(BCCscript *script,
-                     BCCsizei *actualFunctionCount,
-                     BCCsizei maxFunctionCount,
-                     BCCchar **functions) {
-  script->compiler.getFunctions(actualFunctionCount,
-                                maxFunctionCount,
-                                functions);
-}
+  extern "C" void bccGetExportFuncs(BCCscript *script,
+                                    BCCsizei *actualFuncCount,
+                                    BCCsizei maxFuncCount,
+                                    BCCvoid **funcs) {
+    script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
+  }
 
-extern "C"
-void bccGetFunctionBinary(BCCscript *script,
-                          BCCchar *function,
-                          BCCvoid **base,
-                          BCCsizei *length) {
-  script->compiler.getFunctionBinary(function, base, length);
-}
+  extern "C" void bccGetPragmas(BCCscript *script,
+                                BCCsizei *actualStringCount,
+                                BCCsizei maxStringCount,
+                                BCCchar **strings) {
+    script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
+  }
 
-struct BCCtype {
-  const Compiler *compiler;
-  const llvm::Type *t;
-};
+  extern "C" void bccGetFunctions(BCCscript *script,
+                                  BCCsizei *actualFunctionCount,
+                                  BCCsizei maxFunctionCount,
+                                  BCCchar **functions) {
+    script->compiler.getFunctions(actualFunctionCount,
+                                  maxFunctionCount,
+                                  functions);
+  }
+
+  extern "C" void bccGetFunctionBinary(BCCscript *script,
+                                       BCCchar *function,
+                                       BCCvoid **base,
+                                       BCCsizei *length) {
+    script->compiler.getFunctionBinary(function, base, length);
+  }
+
+  struct BCCtype {
+    const Compiler *compiler;
+    const llvm::Type *t;
+  };
 
 }  // namespace bcc