Rename the file name (looks more similar to LLVM).
diff --git a/lib/bcc/CodeEmitter.cpp b/lib/bcc/CodeEmitter.cpp
new file mode 100644
index 0000000..38fc281
--- /dev/null
+++ b/lib/bcc/CodeEmitter.cpp
@@ -0,0 +1,1574 @@
+/*
+ * Copyright 2010, 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 "CodeEmitter.h"
+
+#include "CodeMemoryManager.h"
+#include "EmittedFuncEntry.h"
+#include "Runtime.h"
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_cache.h>
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRelocation.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/JITCodeEmitter.h"
+
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+#if defined(USE_DISASSEMBLER)
+#include "llvm/Support/MemoryObject.h"
+#endif
+
+#include "llvm/System/Host.h"
+
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetJITInfo.h"
+
+#include "llvm/Constant.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalAlias.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Instruction.h"
+#include "llvm/Type.h"
+
+#include <algorithm>
+#include <vector>
+#include <set>
+#include <string>
+
+#include <stddef.h>
+
+
+namespace {
+
+#if defined(USE_DISASSEMBLER)
+class BufferMemoryObject : public llvm::MemoryObject {
+private:
+  const uint8_t *mBytes;
+  uint64_t mLength;
+
+public:
+  BufferMemoryObject(const uint8_t *Bytes, uint64_t Length)
+    : mBytes(Bytes), mLength(Length) {
+  }
+
+  virtual uint64_t getBase() const { return 0; }
+  virtual uint64_t getExtent() const { return mLength; }
+
+  virtual int readByte(uint64_t Addr, uint8_t *Byte) const {
+    if (Addr > getExtent())
+      return -1;
+    *Byte = mBytes[Addr];
+    return 0;
+  }
+};
+#endif
+
+}; // namespace anonymous
+
+
+namespace bcc {
+
+// Will take the ownership of @MemMgr
+CodeEmitter::CodeEmitter(CodeMemoryManager *pMemMgr)
+    : mpMemMgr(pMemMgr),
+      mpTarget(NULL),
+      mpTJI(NULL),
+      mpTD(NULL),
+      mpCurEmitFunction(NULL),
+      mpConstantPool(NULL),
+      mpJumpTable(NULL),
+      mpMMI(NULL),
+#if defined(USE_DISASSEMBLER)
+      mpAsmInfo(NULL),
+      mpDisassmbler(NULL),
+      mpIP(NULL),
+#endif
+      mpSymbolLookupFn(NULL),
+      mpSymbolLookupContext(NULL) {
+}
+
+
+CodeEmitter::~CodeEmitter() {
+  delete mpMemMgr;
+#if defined(USE_DISASSEMBLER)
+  delete mpAsmInfo;
+  delete mpDisassmbler;
+  delete mpIP;
+#endif
+}
+
+
+// Once you finish the compilation on a translation unit, you can call this
+// function to recycle the memory (which is used at compilation time and not
+// needed for runtime).
+//
+//  NOTE: You should not call this funtion until the code-gen passes for a
+//        given module is done. Otherwise, the results is undefined and may
+//        cause the system crash!
+void CodeEmitter::releaseUnnecessary() {
+  mMBBLocations.clear();
+  mLabelLocations.clear();
+  mGlobalAddressMap.clear();
+  mFunctionToLazyStubMap.clear();
+  GlobalToIndirectSymMap.clear();
+  ExternalFnToStubMap.clear();
+  PendingFunctions.clear();
+}
+
+
+void CodeEmitter::reset() {
+  releaseUnnecessary();
+
+  mpSymbolLookupFn = NULL;
+  mpSymbolLookupContext = NULL;
+
+  mpTJI = NULL;
+  mpTD = NULL;
+
+  for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
+          E = mEmittedFunctions.end();
+       I != E;
+       I++)
+    if (I->second != NULL)
+      delete I->second;
+  mEmittedFunctions.clear();
+
+  mpMemMgr->reset();
+}
+
+
+void *CodeEmitter::UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
+  if (Addr == NULL) {
+    // Removing mapping
+    GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
+    void *OldVal;
+
+    if (I == mGlobalAddressMap.end()) {
+      OldVal = NULL;
+    } else {
+      OldVal = I->second;
+      mGlobalAddressMap.erase(I);
+    }
+
+    return OldVal;
+  }
+
+  void *&CurVal = mGlobalAddressMap[GV];
+  void *OldVal = CurVal;
+
+  CurVal = Addr;
+
+  return OldVal;
+}
+
+
+unsigned int CodeEmitter::GetConstantPoolSizeInBytes(
+                                    llvm::MachineConstantPool *MCP) {
+  const std::vector<llvm::MachineConstantPoolEntry> &Constants =
+      MCP->getConstants();
+
+  if (Constants.empty())
+    return 0;
+
+  unsigned int Size = 0;
+  for (int i = 0, e = Constants.size(); i != e; i++) {
+    llvm::MachineConstantPoolEntry CPE = Constants[i];
+    unsigned int AlignMask = CPE.getAlignment() - 1;
+    Size = (Size + AlignMask) & ~AlignMask;
+    const llvm::Type *Ty = CPE.getType();
+    Size += mpTD->getTypeAllocSize(Ty);
+  }
+
+  return Size;
+}
+
+// This function converts a Constant* into a GenericValue. The interesting
+// part is if C is a ConstantExpr.
+void CodeEmitter::GetConstantValue(const llvm::Constant *C,
+                                   llvm::GenericValue &Result) {
+  if (C->getValueID() == llvm::Value::UndefValueVal)
+    return;
+  else if (C->getValueID() == llvm::Value::ConstantExprVal) {
+    const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
+    const llvm::Constant *Op0 = CE->getOperand(0);
+
+    switch (CE->getOpcode()) {
+      case llvm::Instruction::GetElementPtr: {
+        // Compute the index
+        llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
+                                                   CE->op_end());
+        uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
+                                                 &Indices[0],
+                                                 Indices.size());
+
+        GetConstantValue(Op0, Result);
+        Result.PointerVal =
+            static_cast<uint8_t*>(Result.PointerVal) + Offset;
+
+        return;
+      }
+      case llvm::Instruction::Trunc: {
+        uint32_t BitWidth =
+            llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
+
+        GetConstantValue(Op0, Result);
+        Result.IntVal = Result.IntVal.trunc(BitWidth);
+
+        return;
+      }
+      case llvm::Instruction::ZExt: {
+        uint32_t BitWidth =
+            llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
+
+        GetConstantValue(Op0, Result);
+        Result.IntVal = Result.IntVal.zext(BitWidth);
+
+        return;
+      }
+      case llvm::Instruction::SExt: {
+        uint32_t BitWidth =
+            llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
+
+        GetConstantValue(Op0, Result);
+        Result.IntVal = Result.IntVal.sext(BitWidth);
+
+        return;
+      }
+      case llvm::Instruction::FPTrunc: {
+        // TODO(all): fixme: long double
+        GetConstantValue(Op0, Result);
+        Result.FloatVal = static_cast<float>(Result.DoubleVal);
+        return;
+      }
+      case llvm::Instruction::FPExt: {
+        // TODO(all): fixme: long double
+        GetConstantValue(Op0, Result);
+        Result.DoubleVal = static_cast<double>(Result.FloatVal);
+        return;
+      }
+      case llvm::Instruction::UIToFP: {
+        GetConstantValue(Op0, Result);
+        if (CE->getType()->isFloatTy())
+          Result.FloatVal =
+              static_cast<float>(Result.IntVal.roundToDouble());
+        else if (CE->getType()->isDoubleTy())
+          Result.DoubleVal = Result.IntVal.roundToDouble();
+        else if (CE->getType()->isX86_FP80Ty()) {
+          const uint64_t zero[] = { 0, 0 };
+          llvm::APFloat apf(llvm::APInt(80, 2, zero));
+          apf.convertFromAPInt(Result.IntVal,
+                               false,
+                               llvm::APFloat::rmNearestTiesToEven);
+          Result.IntVal = apf.bitcastToAPInt();
+        }
+        return;
+      }
+      case llvm::Instruction::SIToFP: {
+        GetConstantValue(Op0, Result);
+        if (CE->getType()->isFloatTy())
+          Result.FloatVal =
+              static_cast<float>(Result.IntVal.signedRoundToDouble());
+        else if (CE->getType()->isDoubleTy())
+          Result.DoubleVal = Result.IntVal.signedRoundToDouble();
+        else if (CE->getType()->isX86_FP80Ty()) {
+          const uint64_t zero[] = { 0, 0 };
+          llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
+          apf.convertFromAPInt(Result.IntVal,
+                               true,
+                               llvm::APFloat::rmNearestTiesToEven);
+          Result.IntVal = apf.bitcastToAPInt();
+        }
+        return;
+      }
+      // double->APInt conversion handles sign
+      case llvm::Instruction::FPToUI:
+      case llvm::Instruction::FPToSI: {
+        uint32_t BitWidth =
+            llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
+
+        GetConstantValue(Op0, Result);
+        if (Op0->getType()->isFloatTy())
+          Result.IntVal =
+           llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
+        else if (Op0->getType()->isDoubleTy())
+          Result.IntVal =
+              llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
+                                                 BitWidth);
+        else if (Op0->getType()->isX86_FP80Ty()) {
+          llvm::APFloat apf = llvm::APFloat(Result.IntVal);
+          uint64_t V;
+          bool Ignored;
+          apf.convertToInteger(&V,
+                               BitWidth,
+                               CE->getOpcode() == llvm::Instruction::FPToSI,
+                               llvm::APFloat::rmTowardZero,
+                               &Ignored);
+          Result.IntVal = V;  // endian?
+        }
+        return;
+      }
+      case llvm::Instruction::PtrToInt: {
+        uint32_t PtrWidth = mpTD->getPointerSizeInBits();
+
+        GetConstantValue(Op0, Result);
+        Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
+                                    (Result.PointerVal));
+
+        return;
+      }
+      case llvm::Instruction::IntToPtr: {
+        uint32_t PtrWidth = mpTD->getPointerSizeInBits();
+
+        GetConstantValue(Op0, Result);
+        if (PtrWidth != Result.IntVal.getBitWidth())
+          Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
+        assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
+
+        Result.PointerVal =
+            llvm::PointerTy(
+                static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
+
+        return;
+      }
+      case llvm::Instruction::BitCast: {
+        GetConstantValue(Op0, Result);
+        const llvm::Type *DestTy = CE->getType();
+
+        switch (Op0->getType()->getTypeID()) {
+          case llvm::Type::IntegerTyID: {
+            assert(DestTy->isFloatingPointTy() && "invalid bitcast");
+            if (DestTy->isFloatTy())
+              Result.FloatVal = Result.IntVal.bitsToFloat();
+            else if (DestTy->isDoubleTy())
+              Result.DoubleVal = Result.IntVal.bitsToDouble();
+            break;
+          }
+          case llvm::Type::FloatTyID: {
+            assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
+            Result.IntVal.floatToBits(Result.FloatVal);
+            break;
+          }
+          case llvm::Type::DoubleTyID: {
+            assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
+            Result.IntVal.doubleToBits(Result.DoubleVal);
+            break;
+          }
+          case llvm::Type::PointerTyID: {
+            assert(DestTy->isPointerTy() && "Invalid bitcast");
+            break;  // getConstantValue(Op0) above already converted it
+          }
+          default: {
+            llvm_unreachable("Invalid bitcast operand");
+          }
+        }
+        return;
+      }
+      case llvm::Instruction::Add:
+      case llvm::Instruction::FAdd:
+      case llvm::Instruction::Sub:
+      case llvm::Instruction::FSub:
+      case llvm::Instruction::Mul:
+      case llvm::Instruction::FMul:
+      case llvm::Instruction::UDiv:
+      case llvm::Instruction::SDiv:
+      case llvm::Instruction::URem:
+      case llvm::Instruction::SRem:
+      case llvm::Instruction::And:
+      case llvm::Instruction::Or:
+      case llvm::Instruction::Xor: {
+        llvm::GenericValue LHS, RHS;
+        GetConstantValue(Op0, LHS);
+        GetConstantValue(CE->getOperand(1), RHS);
+
+        switch (Op0->getType()->getTypeID()) {
+          case llvm::Type::IntegerTyID: {
+            switch (CE->getOpcode()) {
+              case llvm::Instruction::Add: {
+                Result.IntVal = LHS.IntVal + RHS.IntVal;
+                break;
+              }
+              case llvm::Instruction::Sub: {
+                Result.IntVal = LHS.IntVal - RHS.IntVal;
+                break;
+              }
+              case llvm::Instruction::Mul: {
+                Result.IntVal = LHS.IntVal * RHS.IntVal;
+                break;
+              }
+              case llvm::Instruction::UDiv: {
+                Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
+                break;
+              }
+              case llvm::Instruction::SDiv: {
+                Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
+                break;
+              }
+              case llvm::Instruction::URem: {
+                Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
+                break;
+              }
+              case llvm::Instruction::SRem: {
+                Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
+                break;
+              }
+              case llvm::Instruction::And: {
+                Result.IntVal = LHS.IntVal & RHS.IntVal;
+                break;
+              }
+              case llvm::Instruction::Or: {
+                Result.IntVal = LHS.IntVal | RHS.IntVal;
+                break;
+              }
+              case llvm::Instruction::Xor: {
+                Result.IntVal = LHS.IntVal ^ RHS.IntVal;
+                break;
+              }
+              default: {
+                llvm_unreachable("Invalid integer opcode");
+              }
+            }
+            break;
+          }
+          case llvm::Type::FloatTyID: {
+            switch (CE->getOpcode()) {
+              case llvm::Instruction::FAdd: {
+                Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
+                break;
+              }
+              case llvm::Instruction::FSub: {
+                Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
+                break;
+              }
+              case llvm::Instruction::FMul: {
+                Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
+                break;
+              }
+              case llvm::Instruction::FDiv: {
+                Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
+                break;
+              }
+              case llvm::Instruction::FRem: {
+                Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
+                break;
+              }
+              default: {
+                llvm_unreachable("Invalid float opcode");
+              }
+            }
+            break;
+          }
+          case llvm::Type::DoubleTyID: {
+            switch (CE->getOpcode()) {
+              case llvm::Instruction::FAdd: {
+                Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
+                break;
+              }
+              case llvm::Instruction::FSub: {
+                Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
+                break;
+              }
+              case llvm::Instruction::FMul: {
+                Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
+                break;
+              }
+              case llvm::Instruction::FDiv: {
+                Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
+                break;
+              }
+              case llvm::Instruction::FRem: {
+                Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
+                break;
+              }
+              default: {
+                llvm_unreachable("Invalid double opcode");
+              }
+            }
+            break;
+          }
+          case llvm::Type::X86_FP80TyID:
+          case llvm::Type::PPC_FP128TyID:
+          case llvm::Type::FP128TyID: {
+            llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
+            switch (CE->getOpcode()) {
+              case llvm::Instruction::FAdd: {
+                apfLHS.add(llvm::APFloat(RHS.IntVal),
+                           llvm::APFloat::rmNearestTiesToEven);
+                break;
+              }
+              case llvm::Instruction::FSub: {
+                apfLHS.subtract(llvm::APFloat(RHS.IntVal),
+                                llvm::APFloat::rmNearestTiesToEven);
+                break;
+              }
+              case llvm::Instruction::FMul: {
+                apfLHS.multiply(llvm::APFloat(RHS.IntVal),
+                                llvm::APFloat::rmNearestTiesToEven);
+                break;
+              }
+              case llvm::Instruction::FDiv: {
+                apfLHS.divide(llvm::APFloat(RHS.IntVal),
+                              llvm::APFloat::rmNearestTiesToEven);
+                break;
+              }
+              case llvm::Instruction::FRem: {
+                apfLHS.mod(llvm::APFloat(RHS.IntVal),
+                           llvm::APFloat::rmNearestTiesToEven);
+                break;
+              }
+              default: {
+                llvm_unreachable("Invalid long double opcode");
+              }
+            }
+            Result.IntVal = apfLHS.bitcastToAPInt();
+            break;
+          }
+          default: {
+            llvm_unreachable("Bad add type!");
+          }
+        }  // End switch (Op0->getType()->getTypeID())
+        return;
+      }
+      default: {
+        break;
+      }
+    }   // End switch (CE->getOpcode())
+
+    std::string msg;
+    llvm::raw_string_ostream Msg(msg);
+    Msg << "ConstantExpr not handled: " << *CE;
+    llvm::report_fatal_error(Msg.str());
+  }  // C->getValueID() == llvm::Value::ConstantExprVal
+
+  switch (C->getType()->getTypeID()) {
+    case llvm::Type::FloatTyID: {
+      Result.FloatVal =
+          llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
+      break;
+    }
+    case llvm::Type::DoubleTyID: {
+      Result.DoubleVal =
+          llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
+      break;
+    }
+    case llvm::Type::X86_FP80TyID:
+    case llvm::Type::FP128TyID:
+    case llvm::Type::PPC_FP128TyID: {
+      Result.IntVal =
+          llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
+      break;
+    }
+    case llvm::Type::IntegerTyID: {
+      Result.IntVal =
+          llvm::cast<llvm::ConstantInt>(C)->getValue();
+      break;
+    }
+    case llvm::Type::PointerTyID: {
+      switch (C->getValueID()) {
+        case llvm::Value::ConstantPointerNullVal: {
+          Result.PointerVal = NULL;
+          break;
+        }
+        case llvm::Value::FunctionVal: {
+          const llvm::Function *F = static_cast<const llvm::Function*>(C);
+          Result.PointerVal =
+              GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
+          break;
+        }
+        case llvm::Value::GlobalVariableVal: {
+          const llvm::GlobalVariable *GV =
+              static_cast<const llvm::GlobalVariable*>(C);
+          Result.PointerVal =
+            GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
+          break;
+        }
+        case llvm::Value::BlockAddressVal: {
+          assert(false && "JIT does not support address-of-label yet!");
+        }
+        default: {
+          llvm_unreachable("Unknown constant pointer type!");
+        }
+      }
+      break;
+    }
+    default: {
+      std::string msg;
+      llvm::raw_string_ostream Msg(msg);
+      Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
+      llvm::report_fatal_error(Msg.str());
+      break;
+    }
+  }
+  return;
+}
+
+
+// Stores the data in @Val of type @Ty at address @Addr.
+void CodeEmitter::StoreValueToMemory(const llvm::GenericValue &Val,
+                                     void *Addr,
+                                     const llvm::Type *Ty) {
+  const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
+
+  switch (Ty->getTypeID()) {
+    case llvm::Type::IntegerTyID: {
+      const llvm::APInt &IntVal = Val.IntVal;
+      assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
+          "Integer too small!");
+
+      const uint8_t *Src =
+        reinterpret_cast<const uint8_t*>(IntVal.getRawData());
+
+      if (llvm::sys::isLittleEndianHost()) {
+        // Little-endian host - the source is ordered from LSB to MSB.
+        // Order the destination from LSB to MSB: Do a straight copy.
+        memcpy(Addr, Src, StoreBytes);
+      } else {
+        // Big-endian host - the source is an array of 64 bit words
+        // ordered from LSW to MSW.
+        //
+        // Each word is ordered from MSB to LSB.
+        //
+        // Order the destination from MSB to LSB:
+        //  Reverse the word order, but not the bytes in a word.
+        unsigned int i = StoreBytes;
+        while (i > sizeof(uint64_t)) {
+          i -= sizeof(uint64_t);
+          ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
+              Src,
+              sizeof(uint64_t));
+          Src += sizeof(uint64_t);
+        }
+        ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
+      }
+      break;
+    }
+    case llvm::Type::FloatTyID: {
+      *reinterpret_cast<float*>(Addr) = Val.FloatVal;
+      break;
+    }
+    case llvm::Type::DoubleTyID: {
+      *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
+      break;
+    }
+    case llvm::Type::X86_FP80TyID: {
+      memcpy(Addr, Val.IntVal.getRawData(), 10);
+      break;
+    }
+    case llvm::Type::PointerTyID: {
+      // Ensure 64 bit target pointers are fully initialized on 32 bit
+      // hosts.
+      if (StoreBytes != sizeof(llvm::PointerTy))
+        memset(Addr, 0, StoreBytes);
+      *((llvm::PointerTy*) Addr) = Val.PointerVal;
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+
+  if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
+    std::reverse(reinterpret_cast<uint8_t*>(Addr),
+        reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
+
+  return;
+}
+
+
+// Recursive function to apply a @Constant value into the specified memory
+// location @Addr.
+void CodeEmitter::InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
+  switch (C->getValueID()) {
+    case llvm::Value::UndefValueVal: {
+      // Nothing to do
+      break;
+    }
+    case llvm::Value::ConstantVectorVal: {
+      // dynamic cast may hurt performance
+      const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
+
+      unsigned int ElementSize = mpTD->getTypeAllocSize
+        (CP->getType()->getElementType());
+
+      for (int i = 0, e = CP->getNumOperands(); i != e;i++)
+        InitializeConstantToMemory(
+            CP->getOperand(i),
+            reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
+      break;
+    }
+    case llvm::Value::ConstantAggregateZeroVal: {
+      memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
+      break;
+    }
+    case llvm::Value::ConstantArrayVal: {
+      const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
+      unsigned int ElementSize = mpTD->getTypeAllocSize
+        (CPA->getType()->getElementType());
+
+      for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
+        InitializeConstantToMemory(
+            CPA->getOperand(i),
+            reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
+      break;
+    }
+    case llvm::Value::ConstantStructVal: {
+      const llvm::ConstantStruct *CPS =
+          static_cast<const llvm::ConstantStruct*>(C);
+      const llvm::StructLayout *SL = mpTD->getStructLayout
+        (llvm::cast<llvm::StructType>(CPS->getType()));
+
+      for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
+        InitializeConstantToMemory(
+            CPS->getOperand(i),
+            reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
+      break;
+    }
+    default: {
+      if (C->getType()->isFirstClassType()) {
+        llvm::GenericValue Val;
+        GetConstantValue(C, Val);
+        StoreValueToMemory(Val, Addr, C->getType());
+      } else {
+        llvm_unreachable("Unknown constant type to initialize memory "
+                         "with!");
+      }
+      break;
+    }
+  }
+  return;
+}
+
+
+void CodeEmitter::emitConstantPool(llvm::MachineConstantPool *MCP) {
+  if (mpTJI->hasCustomConstantPool())
+    return;
+
+  // Constant pool address resolution is handled by the target itself in ARM
+  // (TargetJITInfo::hasCustomConstantPool() returns true).
+#if !defined(PROVIDE_ARM_CODEGEN)
+  const std::vector<llvm::MachineConstantPoolEntry> &Constants =
+    MCP->getConstants();
+
+  if (Constants.empty())
+    return;
+
+  unsigned Size = GetConstantPoolSizeInBytes(MCP);
+  unsigned Align = MCP->getConstantPoolAlignment();
+
+  mpConstantPoolBase = allocateSpace(Size, Align);
+  mpConstantPool = MCP;
+
+  if (mpConstantPoolBase == NULL)
+    return;  // out of memory
+
+  unsigned Offset = 0;
+  for (int i = 0, e = Constants.size(); i != e; i++) {
+    llvm::MachineConstantPoolEntry CPE = Constants[i];
+    unsigned AlignMask = CPE.getAlignment() - 1;
+    Offset = (Offset + AlignMask) & ~AlignMask;
+
+    uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
+    mConstPoolAddresses.push_back(CAddr);
+
+    if (CPE.isMachineConstantPoolEntry())
+      llvm::report_fatal_error
+        ("Initialize memory with machine specific constant pool"
+         " entry has not been implemented!");
+
+    InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
+
+    const llvm::Type *Ty = CPE.Val.ConstVal->getType();
+    Offset += mpTD->getTypeAllocSize(Ty);
+  }
+#endif
+  return;
+}
+
+
+void CodeEmitter::initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
+  if (mpTJI->hasCustomJumpTables())
+    return;
+
+  const std::vector<llvm::MachineJumpTableEntry> &JT =
+    MJTI->getJumpTables();
+  if (JT.empty())
+    return;
+
+  unsigned NumEntries = 0;
+  for (int i = 0, e = JT.size(); i != e; i++)
+    NumEntries += JT[i].MBBs.size();
+
+  unsigned EntrySize = MJTI->getEntrySize(*mpTD);
+
+  mpJumpTable = MJTI;
+  mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
+      MJTI->getEntryAlignment(*mpTD));
+
+  return;
+}
+
+
+void CodeEmitter::emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
+  if (mpTJI->hasCustomJumpTables())
+    return;
+
+  const std::vector<llvm::MachineJumpTableEntry> &JT =
+    MJTI->getJumpTables();
+  if (JT.empty() || mpJumpTableBase == 0)
+    return;
+
+  assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
+         (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
+         "Cross JIT'ing?");
+
+  // For each jump table, map each target in the jump table to the
+  // address of an emitted MachineBasicBlock.
+  intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
+  for (int i = 0, ie = JT.size(); i != ie; i++) {
+    const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
+    // Store the address of the basic block for this jump table slot in the
+    // memory we allocated for the jump table in 'initJumpTableInfo'
+    for (int j = 0, je = MBBs.size(); j != je; j++)
+      *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
+  }
+}
+
+
+void *CodeEmitter::GetPointerToGlobal(llvm::GlobalValue *V,
+                                      void *Reference,
+                                      bool MayNeedFarStub) {
+  switch (V->getValueID()) {
+    case llvm::Value::FunctionVal: {
+      llvm::Function *F = (llvm::Function*) V;
+
+      // If we have code, go ahead and return that.
+      if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
+        return ResultPtr;
+
+      if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
+        // Return the function stub if it's already created.
+        // We do this first so that:
+        //   we're returning the same address for the function as any
+        //   previous call.
+        //
+        // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
+        //                 guaranteed to be close enough to call.
+        return FnStub;
+
+      // If we know the target can handle arbitrary-distance calls, try to
+      //  return a direct pointer.
+      if (!MayNeedFarStub) {
+        //
+        // x86_64 architecture may encounter the bug:
+        //   http://llvm.org/bugs/show_bug.cgi?id=5201
+        // which generate instruction "call" instead of "callq".
+        //
+        // And once the real address of stub is greater than 64-bit
+        // long, the replacement will truncate to 32-bit resulting a
+        // serious problem.
+#if !defined(__x86_64__)
+        // If this is an external function pointer, we can force the JIT
+        // to 'compile' it, which really just adds it to the map.
+        if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
+          return GetPointerToFunction(F, /* AbortOnFailure = */false);
+          // Changing to false because wanting to allow later calls to
+          // mpTJI->relocate() without aborting. For caching purpose
+        }
+#endif
+      }
+
+      // Otherwise, we may need a to emit a stub, and, conservatively, we
+      // always do so.
+      return GetLazyFunctionStub(F);
+      break;
+    }
+    case llvm::Value::GlobalVariableVal: {
+      return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
+      break;
+    }
+    case llvm::Value::GlobalAliasVal: {
+      llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
+      const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
+
+      switch (GV->getValueID()) {
+        case llvm::Value::FunctionVal: {
+          // TODO(all): is there's any possibility that the function is not
+          // code-gen'd?
+          return GetPointerToFunction(
+              static_cast<const llvm::Function*>(GV),
+              /* AbortOnFailure = */false);
+          // Changing to false because wanting to allow later calls to
+          // mpTJI->relocate() without aborting. For caching purpose
+          break;
+        }
+        case llvm::Value::GlobalVariableVal: {
+          if (void *P = mGlobalAddressMap[GV])
+            return P;
+
+          llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
+          EmitGlobalVariable(GVar);
+
+          return mGlobalAddressMap[GV];
+          break;
+        }
+        case llvm::Value::GlobalAliasVal: {
+          assert(false && "Alias should be resolved ultimately!");
+        }
+      }
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+  llvm_unreachable("Unknown type of global value!");
+}
+
+
+// If the specified function has been code-gen'd, return a pointer to the
+// function. If not, compile it, or use a stub to implement lazy compilation
+// if available.
+void *CodeEmitter::GetPointerToFunctionOrStub(llvm::Function *F) {
+  // If we have already code generated the function, just return the
+  // address.
+  if (void *Addr = GetPointerToGlobalIfAvailable(F))
+    return Addr;
+
+  // Get a stub if the target supports it.
+  return GetLazyFunctionStub(F);
+}
+
+
+void *CodeEmitter::GetLazyFunctionStub(llvm::Function *F) {
+  // If we already have a lazy stub for this function, recycle it.
+  void *&Stub = mFunctionToLazyStubMap[F];
+  if (Stub)
+    return Stub;
+
+  // In any cases, we should NOT resolve function at runtime (though we are
+  // able to). We resolve this right now.
+  void *Actual = NULL;
+  if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
+    Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
+    // Changing to false because wanting to allow later calls to
+    // mpTJI->relocate() without aborting. For caching purpose
+  }
+
+  // Codegen a new stub, calling the actual address of the external
+  // function, if it was resolved.
+  llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
+  startGVStub(F, SL.Size, SL.Alignment);
+  Stub = mpTJI->emitFunctionStub(F, Actual, *this);
+  finishGVStub();
+
+  // We really want the address of the stub in the GlobalAddressMap for the
+  // JIT, not the address of the external function.
+  UpdateGlobalMapping(F, Stub);
+
+  if (!Actual)
+    PendingFunctions.insert(F);
+  else
+    Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
+                SL.Size, true);
+
+  return Stub;
+}
+
+
+void *CodeEmitter::GetPointerToFunction(const llvm::Function *F,
+                                        bool AbortOnFailure) {
+  void *Addr = GetPointerToGlobalIfAvailable(F);
+  if (Addr)
+    return Addr;
+
+  assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
+         "Internal error: only external defined function routes here!");
+
+  // Handle the failure resolution by ourselves.
+  Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
+                                 /* AbortOnFailure = */ false);
+
+  // If we resolved the symbol to a null address (eg. a weak external)
+  // return a null pointer let the application handle it.
+  if (Addr == NULL) {
+    if (AbortOnFailure)
+      llvm::report_fatal_error("Could not resolve external function "
+                               "address: " + F->getName());
+    else
+      return NULL;
+  }
+
+  AddGlobalMapping(F, Addr);
+
+  return Addr;
+}
+
+
+void *CodeEmitter::GetPointerToNamedSymbol(const std::string &Name,
+                                           bool AbortOnFailure) {
+  if (void *Addr = FindRuntimeFunction(Name.c_str()))
+    return Addr;
+
+  if (mpSymbolLookupFn)
+    if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
+      return Addr;
+
+  if (AbortOnFailure)
+    llvm::report_fatal_error("Program used external symbol '" + Name +
+                            "' which could not be resolved!");
+
+  return NULL;
+}
+
+
+// Return the address of the specified global variable, possibly emitting it
+// to memory if needed. This is used by the Emitter.
+void *CodeEmitter::GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
+  void *Ptr = GetPointerToGlobalIfAvailable(GV);
+  if (Ptr)
+    return Ptr;
+
+  if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
+    // If the global is external, just remember the address.
+    Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
+    AddGlobalMapping(GV, Ptr);
+  } else {
+    // If the global hasn't been emitted to memory yet, allocate space and
+    // emit it into memory.
+    Ptr = GetMemoryForGV(GV);
+    AddGlobalMapping(GV, Ptr);
+    EmitGlobalVariable(GV);
+  }
+
+  return Ptr;
+}
+
+
+// This method abstracts memory allocation of global variable so that the
+// JIT can allocate thread local variables depending on the target.
+void *CodeEmitter::GetMemoryForGV(const llvm::GlobalVariable *GV) {
+  void *Ptr;
+
+  const llvm::Type *GlobalType = GV->getType()->getElementType();
+  size_t S = mpTD->getTypeAllocSize(GlobalType);
+  size_t A = mpTD->getPreferredAlignment(GV);
+
+  if (GV->isThreadLocal()) {
+    // We can support TLS by
+    //
+    //  Ptr = TJI.allocateThreadLocalMemory(S);
+    //
+    // But I tend not to.
+    // (should we disable this in the front-end (i.e., slang)?).
+    llvm::report_fatal_error
+        ("Compilation of Thread Local Storage (TLS) is disabled!");
+
+  } else if (mpTJI->allocateSeparateGVMemory()) {
+    if (A <= 8) {
+      Ptr = malloc(S);
+    } else {
+      // Allocate (S + A) bytes of memory, then use an aligned pointer
+      // within that space.
+      Ptr = malloc(S + A);
+      unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
+      Ptr = reinterpret_cast<uint8_t*>(Ptr) +
+                (MisAligned ? (A - MisAligned) : 0);
+    }
+  } else {
+    Ptr = allocateGlobal(S, A);
+  }
+
+  return Ptr;
+}
+
+
+void CodeEmitter::EmitGlobalVariable(const llvm::GlobalVariable *GV) {
+  void *GA = GetPointerToGlobalIfAvailable(GV);
+
+  if (GV->isThreadLocal())
+    llvm::report_fatal_error
+        ("We don't support Thread Local Storage (TLS)!");
+
+  if (GA == NULL) {
+    // If it's not already specified, allocate memory for the global.
+    GA = GetMemoryForGV(GV);
+    AddGlobalMapping(GV, GA);
+  }
+
+  InitializeConstantToMemory(GV->getInitializer(), GA);
+
+  // You can do some statistics on global variable here.
+  return;
+}
+
+
+void *CodeEmitter::GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
+  // Make sure GV is emitted first, and create a stub containing the fully
+  // resolved address.
+  void *GVAddress = GetPointerToGlobal(V, Reference, false);
+
+  // If we already have a stub for this global variable, recycle it.
+  void *&IndirectSym = GlobalToIndirectSymMap[V];
+  // Otherwise, codegen a new indirect symbol.
+  if (!IndirectSym)
+    IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
+
+  return IndirectSym;
+}
+
+
+// Return a stub for the function at the specified address.
+void *CodeEmitter::GetExternalFunctionStub(void *FnAddr) {
+  void *&Stub = ExternalFnToStubMap[FnAddr];
+  if (Stub)
+    return Stub;
+
+  llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
+  startGVStub(0, SL.Size, SL.Alignment);
+  Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
+  finishGVStub();
+
+  return Stub;
+}
+
+
+void CodeEmitter::Disassemble(const llvm::StringRef &Name,
+                              uint8_t *Start, size_t Length, bool IsStub) {
+
+#if defined(USE_DISASSEMBLER)
+  llvm::raw_ostream *OS;
+
+#if defined(USE_DISASSEMBLER_FILE)
+  std::string ErrorInfo;
+  OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
+                                ErrorInfo,
+                                llvm::raw_fd_ostream::F_Append);
+
+  if (!ErrorInfo.empty()) {    // some errors occurred
+    // LOGE("Error in creating disassembly file");
+    delete OS;
+    return;
+  }
+#else
+  OS = &llvm::outs();
+#endif
+
+  *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
+      << "\n";
+
+  if (mpAsmInfo == NULL)
+    mpAsmInfo = mpTarget->createAsmInfo(Compiler::Triple);
+  if (mpDisassmbler == NULL)
+    mpDisassmbler = mpTarget->createMCDisassembler();
+  if (mpIP == NULL)
+    mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
+                                         *mpAsmInfo);
+
+  const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
+                                                                Length);
+  uint64_t Size;
+  uint64_t Index;
+
+  for (Index = 0; Index < Length; Index += Size) {
+    llvm::MCInst Inst;
+
+    if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
+          /* REMOVED */ llvm::nulls())) {
+      (*OS).indent(4)
+           .write("0x", 2)
+           .write_hex((uint32_t) Start + Index)
+           .write(':');
+      mpIP->printInst(&Inst, *OS);
+      *OS << "\n";
+    } else {
+      if (Size == 0)
+        Size = 1;  // skip illegible bytes
+    }
+  }
+
+  *OS << "\n";
+  delete BufferMObj;
+
+#if defined(USE_DISASSEMBLER_FILE)
+  // If you want the disassemble results write to file, uncomment this.
+  OS->close();
+  delete OS;
+#endif
+
+#endif // defined(USE_DISASSEMBLER)
+}
+
+
+void CodeEmitter::setTargetMachine(llvm::TargetMachine &TM) {
+  // Set Target
+  mpTarget = &TM.getTarget();
+  // Set TargetJITInfo
+  mpTJI = TM.getJITInfo();
+  // set TargetData
+  mpTD = TM.getTargetData();
+
+  assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
+
+  return;
+}
+
+
+// This callback is invoked when the specified function is about to be code
+// generated.  This initializes the BufferBegin/End/Ptr fields.
+void CodeEmitter::startFunction(llvm::MachineFunction &F) {
+  uintptr_t ActualSize = 0;
+
+  mpMemMgr->setMemoryWritable();
+
+  // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
+  // MachineCodeEmitter, which is the super class of the class
+  // JITCodeEmitter.
+  //
+  // BufferBegin/BufferEnd - Pointers to the start and end of the memory
+  //                         allocated for this code buffer.
+  //
+  // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
+  //                code. This is guranteed to be in the range
+  //                [BufferBegin, BufferEnd].  If this pointer is at
+  //                BufferEnd, it will never move due to code emission, and
+  //                all code emission requests will be ignored (this is the
+  //                buffer overflow condition).
+  BufferBegin = CurBufferPtr =
+      mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
+  BufferEnd = BufferBegin + ActualSize;
+
+  if (mpCurEmitFunction == NULL)
+    mpCurEmitFunction = new EmittedFuncEntry();
+  mpCurEmitFunction->FunctionBody = BufferBegin;
+
+  // Ensure the constant pool/jump table info is at least 4-byte aligned.
+  emitAlignment(16);
+
+  emitConstantPool(F.getConstantPool());
+  if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
+    initJumpTableInfo(MJTI);
+
+  // About to start emitting the machine code for the function.
+  emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
+
+  UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
+
+  mpCurEmitFunction->Code = CurBufferPtr;
+
+  mMBBLocations.clear();
+}
+
+
+// This callback is invoked when the specified function has finished code
+// generation. If a buffer overflow has occurred, this method returns true
+// (the callee is required to try again).
+bool CodeEmitter::finishFunction(llvm::MachineFunction &F) {
+  if (CurBufferPtr == BufferEnd) {
+    // No enough memory
+    mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
+    return false;
+  }
+
+  if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
+    emitJumpTableInfo(MJTI);
+
+  // FnStart is the start of the text, not the start of the constant pool
+  // and other per-function data.
+  uint8_t *FnStart =
+      reinterpret_cast<uint8_t*>(
+          GetPointerToGlobalIfAvailable(F.getFunction()));
+
+  // FnEnd is the end of the function's machine code.
+  uint8_t *FnEnd = CurBufferPtr;
+
+  if (!mRelocations.empty()) {
+    ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
+
+    // Resolve the relocations to concrete pointers.
+    for (int i = 0, e = mRelocations.size(); i != e; i++) {
+      llvm::MachineRelocation &MR = mRelocations[i];
+      void *ResultPtr = NULL;
+
+      if (!MR.letTargetResolve()) {
+        if (MR.isExternalSymbol()) {
+          ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
+
+          if (MR.mayNeedFarStub()) {
+            ResultPtr = GetExternalFunctionStub(ResultPtr);
+          }
+
+        } else if (MR.isGlobalValue()) {
+          ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
+                                         BufferBegin
+                                           + MR.getMachineCodeOffset(),
+                                         MR.mayNeedFarStub());
+        } else if (MR.isIndirectSymbol()) {
+          ResultPtr =
+              GetPointerToGVIndirectSym(
+                  MR.getGlobalValue(),
+                  BufferBegin + MR.getMachineCodeOffset());
+        } else if (MR.isBasicBlock()) {
+          ResultPtr =
+              (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
+        } else if (MR.isConstantPoolIndex()) {
+          ResultPtr =
+             (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
+        } else {
+          assert(MR.isJumpTableIndex() && "Unknown type of relocation");
+          ResultPtr =
+              (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
+        }
+
+        if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
+          // TODO(logan): Cache external symbol relocation entry.
+          // Currently, we are not caching them.  But since Android
+          // system is using prelink, it is not a problem.
+
+          // Cache the relocation result address
+          mCachingRelocations.push_back(
+            oBCCRelocEntry(MR.getRelocationType(),
+                           MR.getMachineCodeOffset() + BufferOffset,
+                           ResultPtr));
+        }
+
+        MR.setResultPointer(ResultPtr);
+      }
+    }
+
+    mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
+                    mpMemMgr->getGOTBase());
+  }
+
+  mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
+  // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
+  // global variables that were referenced in the relocations.
+  if (CurBufferPtr == BufferEnd)
+    return false;
+
+  // Now that we've succeeded in emitting the function.
+  mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
+  BufferBegin = CurBufferPtr = 0;
+
+  if (F.getFunction()->hasName())
+    mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
+  mpCurEmitFunction = NULL;
+
+  mRelocations.clear();
+  mConstPoolAddresses.clear();
+
+  if (mpMMI)
+    mpMMI->EndFunction();
+
+  updateFunctionStub(F.getFunction());
+
+  // Mark code region readable and executable if it's not so already.
+  mpMemMgr->setMemoryExecutable();
+
+  Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
+
+  return false;
+}
+
+
+void CodeEmitter::startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
+                 unsigned Alignment) {
+  mpSavedBufferBegin = BufferBegin;
+  mpSavedBufferEnd = BufferEnd;
+  mpSavedCurBufferPtr = CurBufferPtr;
+
+  BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
+                                                      Alignment);
+  BufferEnd = BufferBegin + StubSize + 1;
+
+  return;
+}
+
+
+void CodeEmitter::startGVStub(void *Buffer, unsigned StubSize) {
+  mpSavedBufferBegin = BufferBegin;
+  mpSavedBufferEnd = BufferEnd;
+  mpSavedCurBufferPtr = CurBufferPtr;
+
+  BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
+  BufferEnd = BufferBegin + StubSize + 1;
+
+  return;
+}
+
+
+void CodeEmitter::finishGVStub() {
+  assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
+
+  // restore
+  BufferBegin = mpSavedBufferBegin;
+  BufferEnd = mpSavedBufferEnd;
+  CurBufferPtr = mpSavedCurBufferPtr;
+}
+
+
+// Allocates and fills storage for an indirect GlobalValue, and returns the
+// address.
+void *CodeEmitter::allocIndirectGV(const llvm::GlobalValue *GV,
+                      const uint8_t *Buffer, size_t Size,
+                      unsigned Alignment) {
+  uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
+  memcpy(IndGV, Buffer, Size);
+  return IndGV;
+}
+
+
+// Allocate memory for a global. Unlike allocateSpace, this method does not
+// allocate memory in the current output buffer, because a global may live
+// longer than the current function.
+void *CodeEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) {
+  // Delegate this call through the memory manager.
+  return mpMemMgr->allocateGlobal(Size, Alignment);
+}
+
+
+// This should be called by the target when a new basic block is about to be
+// emitted. This way the MCE knows where the start of the block is, and can
+// implement getMachineBasicBlockAddress.
+void CodeEmitter::StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
+  if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
+    mMBBLocations.resize((MBB->getNumber() + 1) * 2);
+  mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
+  return;
+}
+
+
+// Return the address of the jump table with index @Index in the function
+// that last called initJumpTableInfo.
+uintptr_t CodeEmitter::getJumpTableEntryAddress(unsigned Index) const {
+  const std::vector<llvm::MachineJumpTableEntry> &JT =
+      mpJumpTable->getJumpTables();
+
+  assert((Index < JT.size()) && "Invalid jump table index!");
+
+  unsigned int Offset = 0;
+  unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
+
+  for (unsigned i = 0; i < Index; i++)
+    Offset += JT[i].MBBs.size();
+  Offset *= EntrySize;
+
+  return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
+}
+
+
+// Return the address of the specified MachineBasicBlock, only usable after
+// the label for the MBB has been emitted.
+uintptr_t CodeEmitter::getMachineBasicBlockAddress(
+                                        llvm::MachineBasicBlock *MBB) const {
+  assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
+         mMBBLocations[MBB->getNumber()] &&
+         "MBB not emitted!");
+  return mMBBLocations[MBB->getNumber()];
+}
+
+
+void CodeEmitter::updateFunctionStub(const llvm::Function *F) {
+  // Get the empty stub we generated earlier.
+  void *Stub;
+  std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
+  if (I != PendingFunctions.end())
+    Stub = mFunctionToLazyStubMap[F];
+  else
+    return;
+
+  void *Addr = GetPointerToGlobalIfAvailable(F);
+
+  assert(Addr != Stub &&
+         "Function must have non-stub address to be updated.");
+
+  // Tell the target jit info to rewrite the stub at the specified address,
+  // rather than creating a new one.
+  llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
+  startGVStub(Stub, SL.Size);
+  mpTJI->emitFunctionStub(F, Addr, *this);
+  finishGVStub();
+
+  Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
+              SL.Size, true);
+
+  PendingFunctions.erase(I);
+}
+
+
+void *CodeEmitter::lookup(const llvm::StringRef &Name) {
+  EmittedFunctionsMapTy::const_iterator
+    I = mEmittedFunctions.find(Name.str());
+
+  return (I == mEmittedFunctions.end()) ? NULL : I->second->Code;
+}
+
+
+void CodeEmitter::getFunctionNames(BCCsizei *actualFunctionCount,
+                                   BCCsizei maxFunctionCount,
+                                   BCCchar **functions) {
+  int functionCount = mEmittedFunctions.size();
+
+  if (actualFunctionCount)
+    *actualFunctionCount = functionCount;
+  if (functionCount > maxFunctionCount)
+    functionCount = maxFunctionCount;
+  if (functions)
+    for (EmittedFunctionsMapTy::const_iterator
+         I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
+         I != E && (functionCount > 0); I++, functionCount--) {
+      *functions++ = const_cast<BCCchar*>(I->first.c_str());
+    }
+}
+
+
+void CodeEmitter::getFunctionBinary(BCCchar *label,
+                                    BCCvoid **base,
+                                    BCCsizei *length) {
+  EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
+  if (I == mEmittedFunctions.end()) {
+    *base = NULL;
+    *length = 0;
+  } else {
+    *base = I->second->Code;
+    *length = I->second->Size;
+  }
+}
+
+} // namespace bcc
diff --git a/lib/bcc/CodeEmitter.h b/lib/bcc/CodeEmitter.h
new file mode 100644
index 0000000..90e95ca
--- /dev/null
+++ b/lib/bcc/CodeEmitter.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2010, 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_CODEEMITTER_H
+#define BCC_CODEEMITTER_H
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_cache.h>
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineRelocation.h"
+#include "llvm/CodeGen/JITCodeEmitter.h"
+#include "llvm/Support/ValueHandle.h"
+
+#include <map>
+#include <vector>
+#include <set>
+
+#include <assert.h>
+#include <stdint.h>
+
+namespace llvm {
+  class Constant;
+  class GenericValue;
+  class GlobalVariable;
+  class GlobalValue;
+  class Function;
+  class MachineBasicBlock;
+  class MachineConstantPool;
+  class MachineFunction;
+  class MachineJumpTableInfo;
+  class MachineModuleInfo;
+#if defined(USE_DISASSEMBLER)
+  class MCAsmInfo;
+  class MCDisassembler;
+  class MCInstPrinter;
+#endif
+  class MCSymbol;
+  class Target;
+  class TargetData;
+  class TargetJITInfo;
+  class TargetMachine;
+  class Type;
+}
+
+namespace bcc {
+  class CodeMemoryManager;
+  class EmittedFuncEntry;
+
+  class CodeEmitter : public llvm::JITCodeEmitter {
+  public:
+    typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
+    typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
+
+    GlobalAddressMapTy mGlobalAddressMap;
+
+  private:
+    CodeMemoryManager *mpMemMgr;
+
+    // The JITInfo for the target we are compiling to
+    const llvm::Target *mpTarget;
+
+    llvm::TargetJITInfo *mpTJI;
+
+    const llvm::TargetData *mpTD;
+
+    EmittedFuncEntry *mpCurEmitFunction;
+
+    typedef std::map<const std::string,
+                     EmittedFuncEntry *> EmittedFunctionsMapTy;
+    EmittedFunctionsMapTy mEmittedFunctions;
+
+    // This vector is a mapping from MBB ID's to their address. It is filled in
+    // by the StartMachineBasicBlock callback and queried by the
+    // getMachineBasicBlockAddress callback.
+    std::vector<uintptr_t> mMBBLocations;
+
+    // The constant pool for the current function.
+    llvm::MachineConstantPool *mpConstantPool;
+
+    // A pointer to the first entry in the constant pool.
+    void *mpConstantPoolBase;
+
+    // Addresses of individual constant pool entries.
+    llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
+
+    // The jump tables for the current function.
+    llvm::MachineJumpTableInfo *mpJumpTable;
+
+    // A pointer to the first entry in the jump table.
+    void *mpJumpTableBase;
+
+    // When outputting a function stub in the context of some other function, we
+    // save BufferBegin/BufferEnd/CurBufferPtr here.
+    uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
+
+    // These are the relocations that the function needs, as emitted.
+    std::vector<llvm::MachineRelocation> mRelocations;
+
+    std::vector<oBCCRelocEntry> mCachingRelocations;
+
+    // This vector is a mapping from Label ID's to their address.
+    llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
+
+    // Machine module info for exception informations
+    llvm::MachineModuleInfo *mpMMI;
+
+    // Replace an existing mapping for GV with a new address. This updates both
+    // maps as required. If Addr is null, the entry for the global is removed
+    // from the mappings.
+    void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr);
+
+    // Tell the execution engine that the specified global is at the specified
+    // location. This is used internally as functions are JIT'd and as global
+    // variables are laid out in memory.
+    void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
+       void *&CurVal = mGlobalAddressMap[GV];
+       assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
+       CurVal = Addr;
+    }
+
+    // This returns the address of the specified global value if it is has
+    // already been codegen'd, otherwise it returns null.
+    void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
+      GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
+      return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
+    }
+
+    unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP);
+
+    // This function converts a Constant* into a GenericValue. The interesting
+    // part is if C is a ConstantExpr.
+    void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result);
+
+    // Stores the data in @Val of type @Ty at address @Addr.
+    void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
+                            const llvm::Type *Ty);
+
+    // Recursive function to apply a @Constant value into the specified memory
+    // location @Addr.
+    void InitializeConstantToMemory(const llvm::Constant *C, void *Addr);
+
+    void emitConstantPool(llvm::MachineConstantPool *MCP);
+
+    void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI);
+
+    void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI);
+
+    void *GetPointerToGlobal(llvm::GlobalValue *V,
+                             void *Reference,
+                             bool MayNeedFarStub);
+
+    // If the specified function has been code-gen'd, return a pointer to the
+    // function. If not, compile it, or use a stub to implement lazy compilation
+    // if available.
+    void *GetPointerToFunctionOrStub(llvm::Function *F);
+
+    typedef llvm::DenseMap<const llvm::Function*,
+                           void*> FunctionToLazyStubMapTy;
+    FunctionToLazyStubMapTy mFunctionToLazyStubMap;
+
+    void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
+      return mFunctionToLazyStubMap.lookup(F);
+    }
+
+    std::set<const llvm::Function*> PendingFunctions;
+    void *GetLazyFunctionStub(llvm::Function *F);
+
+    void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure);
+
+    void *GetPointerToNamedSymbol(const std::string &Name,
+                                  bool AbortOnFailure);
+
+    // Return the address of the specified global variable, possibly emitting it
+    // to memory if needed. This is used by the Emitter.
+    void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV);
+
+    // This method abstracts memory allocation of global variable so that the
+    // JIT can allocate thread local variables depending on the target.
+    void *GetMemoryForGV(const llvm::GlobalVariable *GV);
+
+    void EmitGlobalVariable(const llvm::GlobalVariable *GV);
+
+    typedef std::map<llvm::AssertingVH<llvm::GlobalValue>,
+                     void *> GlobalToIndirectSymMapTy;
+
+    GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
+
+    void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference);
+
+    // This is the equivalent of FunctionToLazyStubMap for external functions.
+    //
+    // TODO(llvm.org): Of course, external functions don't need a lazy stub.
+    //                 It's actually here to make it more likely that far calls
+    //                 succeed, but no single stub can guarantee that. I'll
+    //                 remove this in a subsequent checkin when I actually fix
+    //                 far calls.
+    std::map<void*, void*> ExternalFnToStubMap;
+
+    // Return a stub for the function at the specified address.
+    void *GetExternalFunctionStub(void *FnAddr);
+
+#if defined(USE_DISASSEMBLER)
+    const llvm::MCAsmInfo *mpAsmInfo;
+    const llvm::MCDisassembler *mpDisassmbler;
+    llvm::MCInstPrinter *mpIP;
+#endif
+
+  public:
+    void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
+                     size_t Length, bool IsStub);
+
+  private:
+    // Resolver to undefined symbol in CodeEmitter
+    BCCSymbolLookupFn mpSymbolLookupFn;
+    void *mpSymbolLookupContext;
+
+  public:
+    // Will take the ownership of @MemMgr
+    explicit CodeEmitter(CodeMemoryManager *pMemMgr);
+
+    virtual ~CodeEmitter();
+
+    global_addresses_const_iterator global_address_begin() const {
+      return mGlobalAddressMap.begin();
+    }
+
+    global_addresses_const_iterator global_address_end() const {
+      return mGlobalAddressMap.end();
+    }
+
+    std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
+      return mCachingRelocations;
+    }
+
+    void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
+      mpSymbolLookupFn = pFn;
+      mpSymbolLookupContext = pContext;
+    }
+
+    void setTargetMachine(llvm::TargetMachine &TM);
+
+    // This callback is invoked when the specified function is about to be code
+    // generated.  This initializes the BufferBegin/End/Ptr fields.
+    virtual void startFunction(llvm::MachineFunction &F);
+
+    // This callback is invoked when the specified function has finished code
+    // generation. If a buffer overflow has occurred, this method returns true
+    // (the callee is required to try again).
+    virtual bool finishFunction(llvm::MachineFunction &F);
+
+    void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
+                     unsigned Alignment);
+
+    void startGVStub(void *Buffer, unsigned StubSize);
+
+    void finishGVStub();
+
+    // Allocates and fills storage for an indirect GlobalValue, and returns the
+    // address.
+    virtual void *allocIndirectGV(const llvm::GlobalValue *GV,
+                                  const uint8_t *Buffer, size_t Size,
+                                  unsigned Alignment);
+
+    // Emits a label
+    void emitLabel(llvm::MCSymbol *Label) {
+      mLabelLocations[Label] = getCurrentPCValue();
+    }
+
+    // Allocate memory for a global. Unlike allocateSpace, this method does not
+    // allocate memory in the current output buffer, because a global may live
+    // longer than the current function.
+    virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment);
+
+    // This should be called by the target when a new basic block is about to be
+    // emitted. This way the MCE knows where the start of the block is, and can
+    // implement getMachineBasicBlockAddress.
+    virtual void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB);
+
+    // Whenever a relocatable address is needed, it should be noted with this
+    // interface.
+    virtual void addRelocation(const llvm::MachineRelocation &MR) {
+      mRelocations.push_back(MR);
+    }
+
+    // Return the address of the @Index entry in the constant pool that was
+    // last emitted with the emitConstantPool method.
+    virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
+      assert(Index < mpConstantPool->getConstants().size() &&
+             "Invalid constant pool index!");
+      return mConstPoolAddresses[Index];
+    }
+
+    // Return the address of the jump table with index @Index in the function
+    // that last called initJumpTableInfo.
+    virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const;
+
+    // Return the address of the specified MachineBasicBlock, only usable after
+    // the label for the MBB has been emitted.
+    virtual uintptr_t getMachineBasicBlockAddress(
+                                        llvm::MachineBasicBlock *MBB) const;
+
+    // Return the address of the specified LabelID, only usable after the
+    // LabelID has been emitted.
+    virtual uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
+      assert(mLabelLocations.count(Label) && "Label not emitted!");
+      return mLabelLocations.find(Label)->second;
+    }
+
+    // Specifies the MachineModuleInfo object. This is used for exception
+    // handling purposes.
+    virtual void setModuleInfo(llvm::MachineModuleInfo *Info) {
+      mpMMI = Info;
+    }
+
+    void updateFunctionStub(const llvm::Function *F);
+
+    void releaseUnnecessary();
+
+    void reset();
+
+    void *lookup(const char *Name) {
+      return lookup( llvm::StringRef(Name) );
+    }
+
+    void *lookup(const llvm::StringRef &Name);
+
+    void getFunctionNames(BCCsizei *actualFunctionCount,
+                          BCCsizei maxFunctionCount,
+                          BCCchar **functions);
+
+    void getFunctionBinary(BCCchar *label,
+                           BCCvoid **base,
+                           BCCsizei *length);
+  };
+
+} // namespace bcc
+
+#endif // BCC_CODEEMITTER_H
diff --git a/lib/bcc/CodeMemoryManager.cpp b/lib/bcc/CodeMemoryManager.cpp
new file mode 100644
index 0000000..62478be
--- /dev/null
+++ b/lib/bcc/CodeMemoryManager.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2010, 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.
+ */
+
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+
+#include "CodeMemoryManager.h"
+
+#include "llvm/Support/ErrorHandling.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <map>
+#include <string>
+#include <utility>
+
+
+namespace bcc {
+
+
+const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
+const unsigned int MaxGOTSize = 1 * 1024;
+const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
+
+
+CodeMemoryManager::CodeMemoryManager()
+  : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
+
+  reset();
+  std::string ErrMsg;
+
+  // Try to use fixed address
+
+  // Note: If we failed to allocate mpCodeMem at fixed address,
+  // the caching mechanism has to either perform relocation or
+  // give up.  If the caching mechanism gives up, then we have to
+  // recompile the bitcode and wasting a lot of time.
+
+  for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
+    if (Compiler::BccMmapImgAddrTaken[i]) {
+      // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
+      // been taken.
+      continue;
+    }
+
+    // Occupy the mmap image address first (No matter allocation
+    // success or not.  Keep occupying if succeed; otherwise,
+    // keep occupying as a mark of failure.)
+    Compiler::BccMmapImgAddrTaken[i] = true;
+
+    void *currMmapImgAddr =
+      reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
+
+    mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
+                     PROT_READ | PROT_EXEC | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                     -1, 0);
+
+    if (mpCodeMem == MAP_FAILED) {
+      LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
+           currMmapImgAddr, strerror(errno));
+    } else {
+      // Good, we have got one mmap image address.
+      break;
+    }
+  }
+
+  if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
+    LOGE("Try to allocate mpCodeMem at arbitary address.\n");
+
+    mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
+                     PROT_READ | PROT_EXEC | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANON,
+                     -1, 0);
+
+    if (mpCodeMem == MAP_FAILED) {
+      LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
+      llvm::report_fatal_error("Failed to allocate memory for emitting "
+                               "codes\n" + ErrMsg);
+    }
+  }
+
+  LOGE("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
+
+  // Set global variable pool
+  mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
+
+  return;
+}
+
+
+CodeMemoryManager::~CodeMemoryManager() {
+  if (mpCodeMem && mpCodeMem != MAP_FAILED) {
+    munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
+
+    // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
+    // that the address can be reused.
+  }
+
+  mpCodeMem = 0;
+  mpGVMem = 0;
+}
+
+
+uint8_t *CodeMemoryManager::allocateSGMemory(uintptr_t Size,
+                                             unsigned Alignment) {
+
+  intptr_t FreeMemSize = getFreeCodeMemSize();
+  if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
+    // The code size excesses our limit
+    return NULL;
+
+  if (Alignment == 0)
+    Alignment = 1;
+
+  uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
+  result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
+
+  mCurSGMemIdx = result - getCodeMemBase();
+
+  return result;
+}
+
+
+// setMemoryWritable - When code generation is in progress, the code pages
+//                     may need permissions changed.
+void CodeMemoryManager::setMemoryWritable() {
+  mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
+}
+
+
+// When code generation is done and we're ready to start execution, the
+// code pages may need permissions changed.
+void CodeMemoryManager::setMemoryExecutable() {
+  mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
+}
+
+
+// Setting this flag to true makes the memory manager garbage values over
+// freed memory.  This is useful for testing and debugging, and is to be
+// turned on by default in debug mode.
+void CodeMemoryManager::setPoisonMemory(bool poison) {
+  // no effect
+}
+
+
+// Global Offset Table Management
+
+// If the current table requires a Global Offset Table, this method is
+// invoked to allocate it.  This method is required to set HasGOT to true.
+void CodeMemoryManager::AllocateGOT() {
+  assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
+  mpGOTBase = allocateSGMemory(MaxGOTSize);
+  HasGOT = true;
+}
+
+
+// Main Allocation Functions
+
+// When we start JITing a function, the JIT calls this method to allocate a
+// block of free RWX memory, which returns a pointer to it. If the JIT wants
+// to request a block of memory of at least a certain size, it passes that
+// value as ActualSize, and this method returns a block with at least that
+// much space. If the JIT doesn't know ahead of time how much space it will
+// need to emit the function, it passes 0 for the ActualSize. In either
+// case, this method is required to pass back the size of the allocated
+// block through ActualSize. The JIT will be careful to not write more than
+// the returned ActualSize bytes of memory.
+uint8_t *CodeMemoryManager::startFunctionBody(const llvm::Function *F,
+                                              uintptr_t &ActualSize) {
+  intptr_t FreeMemSize = getFreeCodeMemSize();
+  if ((FreeMemSize < 0) ||
+      (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
+    // The code size excesses our limit
+    return NULL;
+
+  ActualSize = getFreeCodeMemSize();
+  return (getCodeMemBase() + mCurFuncMemIdx);
+}
+
+// This method is called when the JIT is done codegen'ing the specified
+// function. At this point we know the size of the JIT compiled function.
+// This passes in FunctionStart (which was returned by the startFunctionBody
+// method) and FunctionEnd which is a pointer to the actual end of the
+// function. This method should mark the space allocated and remember where
+// it is in case the client wants to deallocate it.
+void CodeMemoryManager::endFunctionBody(const llvm::Function *F,
+                                        uint8_t *FunctionStart,
+                                        uint8_t *FunctionEnd) {
+  assert(FunctionEnd > FunctionStart);
+  assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
+         "Mismatched function start/end!");
+
+  // Advance the pointer
+  intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
+  assert(FunctionCodeSize <= getFreeCodeMemSize() &&
+         "Code size excess the limitation!");
+  mCurFuncMemIdx += FunctionCodeSize;
+
+  // Record there's a function in our memory start from @FunctionStart
+  assert(mFunctionMap.find(F) == mFunctionMap.end() &&
+         "Function already emitted!");
+  mFunctionMap.insert(
+      std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
+          F, std::make_pair(FunctionStart, FunctionEnd)));
+
+  return;
+}
+
+// Allocate a (function code) memory block of the given size. This method
+// cannot be called between calls to startFunctionBody and endFunctionBody.
+uint8_t *CodeMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
+  if (getFreeCodeMemSize() < Size) {
+    // The code size excesses our limit
+    return NULL;
+  }
+
+  if (Alignment == 0)
+    Alignment = 1;
+
+  uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
+  result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
+                       ~(intptr_t) (Alignment - 1));
+
+  mCurFuncMemIdx = (result + Size) - getCodeMemBase();
+
+  return result;
+}
+
+// Allocate memory for a global variable.
+uint8_t *CodeMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
+  if (getFreeGVMemSize() < Size) {
+    // The code size excesses our limit
+    LOGE("No Global Memory");
+    return NULL;
+  }
+
+  if (Alignment == 0)
+    Alignment = 1;
+
+  uint8_t *result = getGVMemBase() + mCurGVMemIdx;
+  result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
+                       ~(intptr_t) (Alignment - 1));
+
+  mCurGVMemIdx = (result + Size) - getGVMemBase();
+
+  return result;
+}
+
+// Free the specified function body. The argument must be the return value
+// from a call to startFunctionBody() that hasn't been deallocated yet. This
+// is never called when the JIT is currently emitting a function.
+void CodeMemoryManager::deallocateFunctionBody(void *Body) {
+  // linear search
+  uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
+  for (FunctionMapTy::iterator I = mFunctionMap.begin(),
+          E = mFunctionMap.end(); I != E; I++) {
+    if (I->second.first == Body) {
+      FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
+      FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
+      break;
+    }
+  }
+
+  assert((FunctionStart == NULL) && "Memory is never allocated!");
+
+  // free the memory
+  intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
+
+  assert(SizeNeedMove >= 0 &&
+         "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
+         " be correctly calculated!");
+
+  if (SizeNeedMove > 0) {
+    // there's data behind deallocating function
+    memmove(FunctionStart, FunctionEnd, SizeNeedMove);
+  }
+
+  mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
+}
+
+// Below are the methods we create
+void CodeMemoryManager::reset() {
+  mpGOTBase = NULL;
+  HasGOT = false;
+
+  mCurFuncMemIdx = 0;
+  mCurSGMemIdx = MaxCodeSize - 1;
+  mCurGVMemIdx = 0;
+
+  mFunctionMap.clear();
+}
+
+} // namespace bcc
diff --git a/lib/bcc/CodeMemoryManager.h b/lib/bcc/CodeMemoryManager.h
new file mode 100644
index 0000000..4a25ee6
--- /dev/null
+++ b/lib/bcc/CodeMemoryManager.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2010, 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_CODEMEMORYMANAGER_H
+#define BCC_CODEMEMORYMANAGER_H
+
+#include "Compiler.h"
+
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+
+#include <map>
+#include <utility>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+
+namespace llvm {
+  // Forward Declaration
+  class Function;
+  class GlobalValue;
+};
+
+
+namespace bcc {
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Memory manager for the code reside in memory
+  //
+  // The memory for our code emitter is very simple and is conforming to the
+  // design decisions of Android RenderScript's Exection Environment:
+  //   The code, data, and symbol sizes are limited (currently 100KB.)
+  //
+  // It's very different from typical compiler, which has no limitation
+  // on the code size. How does code emitter know the size of the code
+  // it is about to emit? It does not know beforehand. We want to solve
+  // this without complicating the code emitter too much.
+  //
+  // We solve this by pre-allocating a certain amount of memory,
+  // and then start the code emission. Once the buffer overflows, the emitter
+  // simply discards all the subsequent emission but still has a counter
+  // on how many bytes have been emitted.
+  //
+  // So once the whole emission is done, if there's a buffer overflow,
+  // it re-allocates the buffer with enough size (based on the
+  //  counter from previous emission) and re-emit again.
+
+  extern const unsigned int MaxCodeSize;
+  extern const unsigned int MaxGOTSize;
+  extern const unsigned int MaxGlobalVarSize;
+
+
+  class CodeMemoryManager : public llvm::JITMemoryManager {
+  private:
+    //
+    // Our memory layout is as follows:
+    //
+    //  The direction of arrows (-> and <-) shows memory's growth direction
+    //  when more space is needed.
+    //
+    // @mpCodeMem:
+    //  +--------------------------------------------------------------+
+    //  | Function Memory ... ->                <- ...        Stub/GOT |
+    //  +--------------------------------------------------------------+
+    //  |<------------------ Total: @MaxCodeSize KiB ----------------->|
+    //
+    //  Where size of GOT is @MaxGOTSize KiB.
+    //
+    // @mpGVMem:
+    //  +--------------------------------------------------------------+
+    //  | Global variable ... ->                                       |
+    //  +--------------------------------------------------------------+
+    //  |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
+    //
+    //
+    // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
+    //                    of function code's memory usage
+    // @mCurSGMemIdx: The current index (starting from tail) of the last byte
+    //                    of stub/GOT's memory usage
+    // @mCurGVMemIdx: The current index (starting from tail) of the last byte
+    //                    of global variable's memory usage
+    //
+    uintptr_t mCurFuncMemIdx;
+    uintptr_t mCurSGMemIdx;
+    uintptr_t mCurGVMemIdx;
+    void *mpCodeMem;
+    void *mpGVMem;
+
+    // GOT Base
+    uint8_t *mpGOTBase;
+
+    typedef std::map<const llvm::Function*,
+                     std::pair<void * /* start address */,
+                               void * /* end address */> > FunctionMapTy;
+
+    FunctionMapTy mFunctionMap;
+
+    intptr_t getFreeCodeMemSize() const {
+      return mCurSGMemIdx - mCurFuncMemIdx;
+    }
+
+    uint8_t *allocateSGMemory(uintptr_t Size,
+                              unsigned Alignment = 1 /* no alignment */);
+
+    uintptr_t getFreeGVMemSize() const {
+      return MaxGlobalVarSize - mCurGVMemIdx;
+    }
+
+    uint8_t *getGVMemBase() const {
+      return reinterpret_cast<uint8_t*>(mpGVMem);
+    }
+
+  public:
+
+    CodeMemoryManager();
+    virtual ~CodeMemoryManager();
+
+    uint8_t *getCodeMemBase() const {
+      return reinterpret_cast<uint8_t*>(mpCodeMem);
+    }
+
+    // setMemoryWritable - When code generation is in progress, the code pages
+    //                     may need permissions changed.
+    virtual void setMemoryWritable();
+
+    // When code generation is done and we're ready to start execution, the
+    // code pages may need permissions changed.
+    virtual void setMemoryExecutable();
+
+    // Setting this flag to true makes the memory manager garbage values over
+    // freed memory.  This is useful for testing and debugging, and is to be
+    // turned on by default in debug mode.
+    virtual void setPoisonMemory(bool poison);
+
+
+    // Global Offset Table Management
+
+    // If the current table requires a Global Offset Table, this method is
+    // invoked to allocate it.  This method is required to set HasGOT to true.
+    virtual void AllocateGOT();
+
+    // If this is managing a Global Offset Table, this method should return a
+    // pointer to its base.
+    virtual uint8_t *getGOTBase() const {
+      return mpGOTBase;
+    }
+
+    // Main Allocation Functions
+
+    // When we start JITing a function, the JIT calls this method to allocate a
+    // block of free RWX memory, which returns a pointer to it. If the JIT wants
+    // to request a block of memory of at least a certain size, it passes that
+    // value as ActualSize, and this method returns a block with at least that
+    // much space. If the JIT doesn't know ahead of time how much space it will
+    // need to emit the function, it passes 0 for the ActualSize. In either
+    // case, this method is required to pass back the size of the allocated
+    // block through ActualSize. The JIT will be careful to not write more than
+    // the returned ActualSize bytes of memory.
+    virtual uint8_t *startFunctionBody(const llvm::Function *F,
+                                       uintptr_t &ActualSize);
+
+    // This method is called by the JIT to allocate space for a function stub
+    // (used to handle limited branch displacements) while it is JIT compiling a
+    // function. For example, if foo calls bar, and if bar either needs to be
+    // lazily compiled or is a native function that exists too far away from the
+    // call site to work, this method will be used to make a thunk for it. The
+    // stub should be "close" to the current function body, but should not be
+    // included in the 'actualsize' returned by startFunctionBody.
+    virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
+                                  unsigned StubSize,
+                                  unsigned Alignment) {
+      return allocateSGMemory(StubSize, Alignment);
+    }
+
+    // This method is called when the JIT is done codegen'ing the specified
+    // function. At this point we know the size of the JIT compiled function.
+    // This passes in FunctionStart (which was returned by the startFunctionBody
+    // method) and FunctionEnd which is a pointer to the actual end of the
+    // function. This method should mark the space allocated and remember where
+    // it is in case the client wants to deallocate it.
+    virtual void endFunctionBody(const llvm::Function *F,
+                                 uint8_t *FunctionStart,
+                                 uint8_t *FunctionEnd);
+
+    // Allocate a (function code) memory block of the given size. This method
+    // cannot be called between calls to startFunctionBody and endFunctionBody.
+    virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
+
+    // Allocate memory for a global variable.
+    virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
+
+    // Free the specified function body. The argument must be the return value
+    // from a call to startFunctionBody() that hasn't been deallocated yet. This
+    // is never called when the JIT is currently emitting a function.
+    virtual void deallocateFunctionBody(void *Body);
+
+    // When we finished JITing the function, if exception handling is set, we
+    // emit the exception table.
+    virtual uint8_t *startExceptionTable(const llvm::Function *F,
+                                         uintptr_t &ActualSize) {
+      assert(false && "Exception is not allowed in our language specification");
+      return NULL;
+    }
+
+    // This method is called when the JIT is done emitting the exception table.
+    virtual void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
+                                   uint8_t *TableEnd, uint8_t *FrameRegister) {
+      assert(false && "Exception is not allowed in our language specification");
+    }
+
+    // Free the specified exception table's memory. The argument must be the
+    // return value from a call to startExceptionTable() that hasn't been
+    // deallocated yet. This is never called when the JIT is currently emitting
+    // an exception table.
+    virtual void deallocateExceptionTable(void *ET) {
+      assert(false && "Exception is not allowed in our language specification");
+    }
+
+    // Below are the methods we create
+    void reset();
+
+  };
+
+} // namespace bcc
+
+#endif  // BCC_CODEMEMORYMANAGER_H
diff --git a/lib/bcc/Compiler.cpp b/lib/bcc/Compiler.cpp
new file mode 100644
index 0000000..50aeaa2
--- /dev/null
+++ b/lib/bcc/Compiler.cpp
@@ -0,0 +1,1776 @@
+/*
+ * Copyright 2010, 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.
+ */
+
+#define LOG_TAG "bcc"
+#include <cutils/log.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 "Compiler.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/Analysis/Passes.h"
+
+#include "llvm/Bitcode/ReaderWriter.h"
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "llvm/GlobalValue.h"
+#include "llvm/Linker.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Metadata.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Value.h"
+
+#include <errno.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+
+namespace {
+
+#define TEMP_FAILURE_RETRY1(exp) ({        \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+
+
+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 anonymous
+
+
+namespace bcc {
+
+//////////////////////////////////////////////////////////////////////////////
+// BCC Compiler Static Variables
+//////////////////////////////////////////////////////////////////////////////
+
+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";
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Compiler
+//////////////////////////////////////////////////////////////////////////////
+
+void Compiler::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;
+}
+
+
+void Compiler::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);
+}
+
+
+CodeMemoryManager *Compiler::createCodeMemoryManager() {
+  mCodeMemMgr.reset(new CodeMemoryManager());
+  return mCodeMemMgr.get();
+}
+
+
+CodeEmitter *Compiler::createCodeEmitter() {
+  mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
+  return mCodeEmitter.get();
+}
+
+
+Compiler::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;
+}
+
+
+int Compiler::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 Compiler::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 Compiler::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 Compiler::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 bccGetScriptLabel()
+void *Compiler::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 Compiler::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 Compiler::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 Compiler::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 Compiler::getFunctions(BCCsizei *actualFunctionCount,
+                            BCCsizei maxFunctionCount,
+                            BCCchar **functions) {
+  if (mCodeEmitter.get())
+    mCodeEmitter->getFunctionNames(actualFunctionCount,
+                                   maxFunctionCount,
+                                   functions);
+  else
+    *actualFunctionCount = 0;
+
+  return;
+}
+
+
+// Interface for bccGetFunctionBinary()
+void Compiler::getFunctionBinary(BCCchar *function,
+                                 BCCvoid **base,
+                                 BCCsizei *length) {
+  if (mCodeEmitter.get()) {
+    mCodeEmitter->getFunctionBinary(function, base, length);
+  } else {
+    *base = NULL;
+    *length = 0;
+  }
+  return;
+}
+
+
+Compiler::~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;
+  delete mContext;
+
+  // llvm::llvm_shutdown();
+}
+
+
+// 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
+
+// Note: loadCacheFile() and genCacheFile() go hand in hand
+void Compiler::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
+
+  {  // Always pad to the page boundary for now
+    long pagesize = sysconf(_SC_PAGESIZE);
+
+    if (offset % pagesize > 0) {
+      codeOffsetNeedPadding = true;
+      offset += pagesize - (offset % pagesize);
+    }
+  }
+
+  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;
+}
+
+
+// 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 Compiler::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 *Compiler::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 Compiler::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;
+}
+
+}  // namespace bcc
diff --git a/lib/bcc/Compiler.h b/lib/bcc/Compiler.h
new file mode 100644
index 0000000..08c92c5
--- /dev/null
+++ b/lib/bcc/Compiler.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2010, 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_H
+#define BCC_COMPILER_H
+
+#include <bcc/bcc.h>
+
+#include "CodeEmitter.h"
+#include "CodeMemoryManager.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Target/TargetMachine.h"
+
+#include <stddef.h>
+
+#include <list>
+#include <string>
+#include <vector>
+#include <utility>
+
+
+#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)
+
+
+namespace llvm {
+  class LLVMContext;
+  class Module;
+}
+
+
+namespace bcc {
+
+  class Compiler {
+    // This part is designed to be orthogonal to those exported bcc*() functions
+    // implementation and internal struct BCCscript.
+
+    //////////////////////////////////////////////////////////////////////////
+    // The variable section below (e.g., Triple, CodeGenOptLevel)
+    // is initialized in GlobalInitialization()
+    //
+    static bool GlobalInitialized;
+
+    static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
+
+    // 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::CodeGenOpt::Level CodeGenOptLevel;
+
+    // End of section of GlobalInitializing variables
+    /////////////////////////////////////////////////////////////////////////
+    // If given, the name of the target CPU to generate code for.
+    static std::string CPU;
+
+    // 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;
+
+    static void GlobalInitialization();
+
+    static void LLVMErrorHandler(void *UserData, const std::string &Message);
+
+    static const llvm::StringRef PragmaMetadataName;
+    static const llvm::StringRef ExportVarMetadataName;
+    static const llvm::StringRef ExportFuncMetadataName;
+
+    friend class CodeEmitter;
+    friend class CodeMemoryManager;
+
+  private:
+    std::string mError;
+
+    bool hasError() const {
+      return !mError.empty();
+    }
+
+    void setError(const char *Error) {
+      mError.assign(Error);  // Copying
+    }
+
+    void setError(const std::string &Error) {
+      mError = Error;
+    }
+
+  private:
+    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();
+
+    // The CodeEmitter
+    llvm::OwningPtr<CodeEmitter> mCodeEmitter;
+    CodeEmitter *createCodeEmitter();
+
+    BCCSymbolLookupFn mpSymbolLookupFn;
+    void *mpSymbolLookupContext;
+
+    llvm::LLVMContext *mContext;
+    llvm::Module *mModule;
+
+    bool mHasLinked;
+
+  public:
+    Compiler();
+
+    // interface for BCCscript::registerSymbolCallback()
+    void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
+      mpSymbolLookupFn = pFn;
+      mpSymbolLookupContext = pContext;
+    }
+
+    int readModule(llvm::Module *module) {
+      GlobalInitialization();
+      mModule = module;
+      return hasError();
+    }
+
+    int readBC(const char *bitcode, size_t bitcodeSize,const BCCchar *resName);
+
+    int linkBC(const char *bitcode, size_t bitcodeSize);
+
+    // interface for bccLoadBinary()
+    int loadCacheFile();
+
+    // interace for bccCompileBC()
+    int compile();
+
+    // interface for bccGetScriptInfoLog()
+    char *getErrorMessage() {
+      return const_cast<char*>(mError.c_str());
+    }
+
+    // interface for bccGetScriptLabel()
+    void *lookup(const char *name);
+
+    // Interface for bccGetExportVars()
+    void getExportVars(BCCsizei *actualVarCount,
+                       BCCsizei maxVarCount,
+                       BCCvoid **vars);
+
+    // Interface for bccGetExportFuncs()
+    void getExportFuncs(BCCsizei *actualFuncCount,
+                        BCCsizei maxFuncCount,
+                        BCCvoid **funcs);
+
+    // Interface for bccGetPragmas()
+    void getPragmas(BCCsizei *actualStringCount,
+                    BCCsizei maxStringCount,
+                    BCCchar **strings);
+
+    // Interface for bccGetFunctions()
+    void getFunctions(BCCsizei *actualFunctionCount,
+                      BCCsizei maxFunctionCount,
+                      BCCchar **functions);
+
+    // Interface for bccGetFunctionBinary()
+    void getFunctionBinary(BCCchar *function,
+                           BCCvoid **base,
+                           BCCsizei *length);
+
+    const llvm::Module *getModule() const {
+      return mModule;
+    }
+
+    ~Compiler();
+
+  private:
+    // Note: loadCacheFile() and genCacheFile() go hand in hand
+    void genCacheFile();
+
+    // 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);
+
+    char *genCacheFileName(const char *fileName, const char *subFileName);
+
+    /*
+     * 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);
+
+  };
+
+
+
+} // namespace bcc
+
+#endif // BCC_COMPILER_H
diff --git a/lib/bcc/EmittedFuncEntry.h b/lib/bcc/EmittedFuncEntry.h
new file mode 100644
index 0000000..798c354
--- /dev/null
+++ b/lib/bcc/EmittedFuncEntry.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010, 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_EMITTEDFUNCENTRY_H
+#define BCC_EMITTEDFUNCENTRY_H
+
+#include <stddef.h>
+
+namespace bcc {
+
+  class EmittedFuncEntry {
+  public:
+    // Beginning of the function's allocation.
+    void *FunctionBody;
+
+    // The address the function's code actually starts at.
+    void *Code;
+
+    // The size of the function code
+    int Size;
+
+    EmittedFuncEntry() : FunctionBody(NULL), Code(NULL) {
+    }
+
+  };
+
+} // namespace bcc
+
+#endif // BCC_EMITTEDFUNCENTRY_H
diff --git a/lib/bcc/Runtime.c b/lib/bcc/Runtime.c
new file mode 100644
index 0000000..3f690aa
--- /dev/null
+++ b/lib/bcc/Runtime.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010, 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 "runtime/lib/absvdi2.c"
+#include "runtime/lib/absvsi2.c"
+#include "runtime/lib/addvdi3.c"
+#include "runtime/lib/addvsi3.c"
+#include "runtime/lib/ashldi3.c"
+#ifndef ANDROID
+#   include "runtime/lib/ashrdi3.c"
+#endif
+#include "runtime/lib/clzdi2.c"
+#include "runtime/lib/clzsi2.c"
+#include "runtime/lib/cmpdi2.c"
+#include "runtime/lib/ctzdi2.c"
+#include "runtime/lib/ctzsi2.c"
+#ifndef ANDROID // no complex.h
+#   include "runtime/lib/divdc3.c"
+#endif
+#include "runtime/lib/divdi3.c"
+#ifndef ANDROID // no complex.h
+#   include "runtime/lib/divsc3.c"
+#endif
+#include "runtime/lib/ffsdi2.c"
+#include "runtime/lib/fixdfdi.c"
+#include "runtime/lib/fixsfdi.c"
+#include "runtime/lib/fixunsdfdi.c"
+#include "runtime/lib/fixunsdfsi.c"
+#include "runtime/lib/fixunssfdi.c"
+#include "runtime/lib/fixunssfsi.c"
+#include "runtime/lib/floatdidf.c"
+#include "runtime/lib/floatdisf.c"
+#include "runtime/lib/floatundidf.c"
+#include "runtime/lib/floatundisf.c"
+#include "runtime/lib/lshrdi3.c"
+#include "runtime/lib/moddi3.c"
+#ifndef ANDROID // no complex.h
+#   include "runtime/lib/muldc3.c"
+#endif
+#include "runtime/lib/muldi3.c"
+#ifndef ANDROID // no complex.h
+#   include "runtime/lib/mulsc3.c"
+#endif
+#include "runtime/lib/mulvdi3.c"
+#include "runtime/lib/mulvsi3.c"
+#include "runtime/lib/negdi2.c"
+#include "runtime/lib/negvdi2.c"
+#include "runtime/lib/negvsi2.c"
+#include "runtime/lib/paritydi2.c"
+#include "runtime/lib/paritysi2.c"
+#include "runtime/lib/popcountdi2.c"
+#include "runtime/lib/popcountsi2.c"
+#include "runtime/lib/powidf2.c"
+#include "runtime/lib/powisf2.c"
+#include "runtime/lib/subvdi3.c"
+#include "runtime/lib/subvsi3.c"
+#include "runtime/lib/ucmpdi2.c"
+#include "runtime/lib/udivdi3.c"
+#include "runtime/lib/udivsi3.c"
+#include "runtime/lib/udivmoddi4.c"
+#include "runtime/lib/umoddi3.c"
+#include "runtime/lib/eprintf.c"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+typedef struct {
+  const char *mName;
+  void *mPtr;
+} RuntimeFunction;
+
+#define USE_VFP_RUNTIME 1
+
+#if defined(__arm__)
+  #define DEF_GENERIC_RUNTIME(func)   \
+    extern void *func;
+  #define DEF_VFP_RUNTIME(func) \
+    extern void *func ## vfp;
+  #define DEF_LLVM_RUNTIME(func)
+  #define DEF_BCC_RUNTIME(func)
+#include "Runtime.def"
+#endif
+
+static const RuntimeFunction gRuntimes[] = {
+#if defined(__arm__)
+  #define DEF_GENERIC_RUNTIME(func)   \
+    { #func, (void*) &func },
+  // TODO: enable only when target support VFP
+  #define DEF_VFP_RUNTIME(func) \
+    { #func, (void*) &func ## vfp },
+#else
+  // host compiler library must contain generic runtime
+  #define DEF_GENERIC_RUNTIME(func)
+  #define DEF_VFP_RUNTIME(func)
+#endif
+#define DEF_LLVM_RUNTIME(func)   \
+  { #func, (void*) &func },
+#define DEF_BCC_RUNTIME(func) \
+  { #func, &func ## _bcc },
+#include "Runtime.def"
+};
+
+static int CompareRuntimeFunction(const void *a, const void *b) {
+  return strcmp(((const RuntimeFunction*) a)->mName,
+               ((const RuntimeFunction*) b)->mName);
+}
+
+void *FindRuntimeFunction(const char *Name) {
+  // binary search
+  const RuntimeFunction Key = { Name, NULL };
+  const RuntimeFunction *R =
+      bsearch(&Key,
+              gRuntimes,
+              sizeof(gRuntimes) / sizeof(RuntimeFunction),
+              sizeof(RuntimeFunction),
+              CompareRuntimeFunction);
+
+  return ((R) ? R->mPtr : NULL);
+}
+
+void VerifyRuntimesTable() {
+  unsigned N = sizeof(gRuntimes) / sizeof(RuntimeFunction), i;
+  for(i = 0; i < N; i++) {
+    const char *Name = gRuntimes[i].mName;
+    int *Ptr = FindRuntimeFunction(Name);
+
+    if (Ptr != (int*) gRuntimes[i].mPtr)
+      assert(false && "Table is corrupted (runtime name should be sorted in "
+                      "Runtime.def).");
+  }
+}
diff --git a/lib/bcc/Runtime.def b/lib/bcc/Runtime.def
new file mode 100644
index 0000000..484915f
--- /dev/null
+++ b/lib/bcc/Runtime.def
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2010, 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.
+ */
+
+#ifdef USE_VFP_RUNTIME
+#   define DEF_GENERIC_OR_VFP_RUNTIME(func) DEF_VFP_RUNTIME(func)
+#   define DEF_LLVM_OR_VFP_RUNTIME(func) DEF_VFP_RUNTIME(func)
+#else
+#   undef DEF_VFP_RUNTIME
+#   define DEF_VFP_RUNTIME(func)
+#   define DEF_GENERIC_OR_VFP_RUNTIME(func) DEF_GENERIC_RUNTIME(func)
+#   define DEF_LLVM_OR_VFP_RUNTIME(func) DEF_LLVM_RUNTIME(func)
+#endif
+
+// Sorted
+DEF_LLVM_RUNTIME(__absvdi2)
+DEF_LLVM_RUNTIME(__absvsi2)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__adddf3)
+DEF_GENERIC_OR_VFP_RUNTIME(__addsf3)
+
+DEF_LLVM_RUNTIME(__addvdi3)
+DEF_LLVM_RUNTIME(__addvsi3)
+DEF_LLVM_RUNTIME(__ashldi3)
+#ifndef ANDROID // has one in bionic
+    DEF_LLVM_RUNTIME(__ashrdi3)
+#endif
+
+#ifdef USE_VFP_RUNTIME
+//    DEF_GENERIC_RUNTIME(__bswapdi2)
+//    DEF_GENERIC_RUNTIME(__bswapsi2)
+#endif
+
+DEF_LLVM_RUNTIME(__clzdi2)
+DEF_LLVM_RUNTIME(__clzsi2)
+DEF_LLVM_RUNTIME(__cmpdi2)
+DEF_LLVM_RUNTIME(__ctzdi2)
+DEF_LLVM_RUNTIME(__ctzsi2)
+
+#ifndef ANDROID // no complex extension
+    DEF_LLVM_RUNTIME(__divdc3)
+#endif
+
+DEF_GENERIC_OR_VFP_RUNTIME(__divdf3)
+
+DEF_LLVM_RUNTIME(__divdi3)
+
+#ifndef ANDROID // no complex extension
+    DEF_LLVM_RUNTIME(__divsc3)
+#endif
+
+DEF_GENERIC_OR_VFP_RUNTIME(__divsf3)
+
+DEF_LLVM_RUNTIME(__eprintf)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__eqdf2)
+DEF_GENERIC_OR_VFP_RUNTIME(__eqsf2)
+DEF_GENERIC_OR_VFP_RUNTIME(__extendsfdf2)
+
+DEF_LLVM_RUNTIME(__ffsdi2)
+DEF_LLVM_RUNTIME(__fixdfdi)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__fixdfsi)
+
+DEF_LLVM_RUNTIME(__fixsfdi)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__fixsfsi)
+
+DEF_LLVM_RUNTIME(__fixunsdfdi)
+DEF_LLVM_OR_VFP_RUNTIME(__fixunsdfsi)
+DEF_LLVM_RUNTIME(__fixunssfdi)
+
+DEF_LLVM_OR_VFP_RUNTIME(__fixunssfsi)
+
+DEF_LLVM_RUNTIME(__floatdidf)
+DEF_LLVM_RUNTIME(__floatdisf)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__floatsidf)
+DEF_GENERIC_OR_VFP_RUNTIME(__floatsisf)
+
+DEF_LLVM_RUNTIME(__floatundidf)
+DEF_LLVM_RUNTIME(__floatundisf)
+
+DEF_GENERIC_RUNTIME(__floatunsidf)
+DEF_GENERIC_RUNTIME(__floatunsisf)
+
+DEF_VFP_RUNTIME(__floatunssidf)
+DEF_VFP_RUNTIME(__floatunssisf)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__gedf2)
+DEF_GENERIC_OR_VFP_RUNTIME(__gesf2)
+DEF_VFP_RUNTIME(__gtdf2)
+DEF_VFP_RUNTIME(__gtsf2)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__ledf2)
+DEF_GENERIC_OR_VFP_RUNTIME(__lesf2)
+
+DEF_LLVM_RUNTIME(__lshrdi3)
+
+DEF_VFP_RUNTIME(__ltdf2)
+DEF_VFP_RUNTIME(__ltsf2)
+
+DEF_LLVM_RUNTIME(__moddi3)
+
+#ifndef ANDROID // no complex extension
+    DEF_LLVM_RUNTIME(__muldc3)
+#endif
+
+DEF_GENERIC_OR_VFP_RUNTIME(__muldf3)
+DEF_LLVM_RUNTIME(__muldi3)
+DEF_LLVM_RUNTIME(__muldsi3)
+
+#ifndef ANDROID // no complex extension
+    DEF_LLVM_RUNTIME(__mulsc3)
+#endif
+
+DEF_GENERIC_OR_VFP_RUNTIME(__mulsf3)
+
+DEF_LLVM_RUNTIME(__mulvdi3)
+DEF_LLVM_RUNTIME(__mulvsi3)
+
+DEF_VFP_RUNTIME(__nedf2)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__negdf2)
+
+DEF_LLVM_RUNTIME(__negdi2)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__negsf2)
+
+DEF_LLVM_RUNTIME(__negvdi2)
+DEF_LLVM_RUNTIME(__negvsi2)
+
+DEF_VFP_RUNTIME(__nesf2)
+
+DEF_LLVM_RUNTIME(__paritydi2)
+DEF_LLVM_RUNTIME(__paritysi2)
+DEF_LLVM_RUNTIME(__popcountdi2)
+DEF_LLVM_RUNTIME(__popcountsi2)
+DEF_LLVM_RUNTIME(__powidf2)
+DEF_LLVM_RUNTIME(__powisf2)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__subdf3)
+DEF_GENERIC_OR_VFP_RUNTIME(__subsf3)
+
+DEF_LLVM_RUNTIME(__subvdi3)
+DEF_LLVM_RUNTIME(__subvsi3)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__truncdfsf2)
+
+DEF_LLVM_RUNTIME(__ucmpdi2)
+DEF_LLVM_RUNTIME(__udivdi3)
+DEF_LLVM_RUNTIME(__udivmoddi4)
+DEF_LLVM_RUNTIME(__udivsi3)
+DEF_LLVM_RUNTIME(__umoddi3)
+
+DEF_GENERIC_OR_VFP_RUNTIME(__unorddf2)
+DEF_GENERIC_OR_VFP_RUNTIME(__unordsf2)
+
+#undef DEF_GENERIC_RUNTIME
+#undef DEF_LLVM_RUNTIME
+#undef DEF_VFP_RUNTIME
+#undef DEF_BCC_RUNTIME
diff --git a/lib/bcc/Runtime.h b/lib/bcc/Runtime.h
new file mode 100644
index 0000000..c0b7ad8
--- /dev/null
+++ b/lib/bcc/Runtime.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010, 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_RUNTIME_H
+#define BCC_RUNTIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *FindRuntimeFunction(const char *Name);
+void VerifyRuntimesTable();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif  /* BCC_RUNTIME_H */
diff --git a/lib/bcc/Script.h b/lib/bcc/Script.h
new file mode 100644
index 0000000..5307f07
--- /dev/null
+++ b/lib/bcc/Script.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010, 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_SCRIPT_H
+#define BCC_SCRIPT_H
+
+#include "Compiler.h"
+
+#include <bcc/bcc.h>
+
+namespace bcc {
+
+  class BCCscript {
+  public:
+    //////////////////////////////////////////////////////////////////////////
+    // 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;
+  };
+
+} // namespace bcc
+
+#endif // BCC_SCRIPT_H
diff --git a/lib/bcc/bcc.cpp b/lib/bcc/bcc.cpp
new file mode 100644
index 0000000..6b64d36
--- /dev/null
+++ b/lib/bcc/bcc.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2010, 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.
+ */
+
+// Bitcode compiler (bcc) for Android:
+//    This is an eager-compilation JIT running on Android.
+
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+
+#include "Compiler.h"
+#include "Script.h"
+
+#include <bcc/bcc.h>
+
+#include <utils/StopWatch.h>
+
+
+namespace llvm {
+  class Module;
+}
+
+
+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" int bccLoadBinary(BCCscript *script) {
+  int result = script->compiler.loadCacheFile();
+  if (result)
+    script->setError(BCC_INVALID_OPERATION);
+  return result;
+}
+
+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 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 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 bccGetExportVars(BCCscript *script,
+                                 BCCsizei *actualVarCount,
+                                 BCCsizei maxVarCount,
+                                 BCCvoid **vars) {
+  script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
+}
+
+extern "C" void bccGetExportFuncs(BCCscript *script,
+                                  BCCsizei *actualFuncCount,
+                                  BCCsizei maxFuncCount,
+                                  BCCvoid **funcs) {
+  script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
+}
+
+extern "C" void bccGetPragmas(BCCscript *script,
+                              BCCsizei *actualStringCount,
+                              BCCsizei maxStringCount,
+                              BCCchar **strings) {
+  script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
+}
+
+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);
+}