resolved conflicts for merge of 7c75d915 to master

Change-Id: I25c1dc90af679e2463abffd33ee8838b4727396f
diff --git a/Android.mk b/Android.mk
index 2d1245b..b7f1dc6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2010 The Android Open Source Project
+# Copyright (C) 2010-2012 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -32,7 +32,8 @@
 
 libbcc_WHOLE_STATIC_LIBRARIES += \
   libbccExecutionEngine \
-  libbccHelper
+  libbccHelper \
+  libbccTransforms
 
 
 #=====================================================================
@@ -73,9 +74,11 @@
 
 LOCAL_SRC_FILES := lib/ExecutionEngine/bcc.cpp
 
-LOCAL_WHOLE_STATIC_LIBRARIES += \
-  $(libbcc_WHOLE_STATIC_LIBRARIES) \
-  libbccCompilerRT
+LOCAL_WHOLE_STATIC_LIBRARIES := $(libbcc_WHOLE_STATIC_LIBRARIES)
+
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm x86))
+LOCAL_WHOLE_STATIC_LIBRARIES += libbccCompilerRT
+endif
 
 ifeq ($(libbcc_USE_MCJIT),1)
   LOCAL_STATIC_LIBRARIES += librsloader
@@ -87,11 +90,15 @@
       libLLVMARMDisassembler \
       libLLVMARMAsmPrinter
   else
-    ifeq ($(TARGET_ARCH),x86)
-      LOCAL_STATIC_LIBRARIES += \
-        libLLVMX86Disassembler
+    ifeq ($(TARGET_ARCH),mips)
+	  $(error "Disassembler is not available for MIPS architecture")
     else
-      $(error Unsupported TARGET_ARCH $(TARGET_ARCH))
+      ifeq ($(TARGET_ARCH),x86)
+        LOCAL_STATIC_LIBRARIES += \
+          libLLVMX86Disassembler
+      else
+        $(error Unsupported TARGET_ARCH $(TARGET_ARCH))
+      endif
     endif
   endif
 endif
@@ -102,15 +109,23 @@
     libLLVMARMDesc \
     libLLVMARMInfo
 else
-  ifeq ($(TARGET_ARCH),x86) # We don't support x86-64 right now
+  ifeq ($(TARGET_ARCH), mips)
     LOCAL_STATIC_LIBRARIES += \
-      libLLVMX86CodeGen \
-      libLLVMX86Desc \
-      libLLVMX86Info \
-      libLLVMX86Utils \
-      libLLVMX86AsmPrinter
+      libLLVMMipsCodeGen \
+      libLLVMMipsAsmPrinter \
+      libLLVMMipsDesc \
+      libLLVMMipsInfo
   else
-    $(error Unsupported TARGET_ARCH $(TARGET_ARCH))
+    ifeq ($(TARGET_ARCH),x86) # We don't support x86-64 right now
+      LOCAL_STATIC_LIBRARIES += \
+        libLLVMX86CodeGen \
+        libLLVMX86Desc \
+        libLLVMX86Info \
+        libLLVMX86Utils \
+        libLLVMX86AsmPrinter
+    else
+      $(error Unsupported TARGET_ARCH $(TARGET_ARCH))
+    endif
   endif
 endif
 
@@ -135,13 +150,19 @@
 
 LOCAL_SHARED_LIBRARIES := libdl libcutils libutils libstlport
 
-# Modules that need get installed if and only if the target libbcc.so is installed.
+# Modules that need get installed if and only if the target libbcc.so is
+# installed.
 LOCAL_REQUIRED_MODULES := libclcore.bc libbcc.so.sha1
 
-# -Wl,--exclude-libs=ALL only applies to library archives. It would hide most of
-# the symbols in this shared library. As a result, it reduced the size of libbcc.so
-# by about 800k in 2010.
-# Note that libLLVMBitReader:libLLVMCore:libLLVMSupport are used by pixelflinger2.
+# Link-Time Optimization on libbcc.so
+#
+# -Wl,--exclude-libs=ALL only applies to library archives. It would hide most
+# of the symbols in this shared library. As a result, it reduced the size of
+# libbcc.so by about 800k in 2010.
+#
+# Note that libLLVMBitReader:libLLVMCore:libLLVMSupport are used by
+# pixelflinger2.
+
 LOCAL_LDFLAGS += -Wl,--exclude-libs=libLLVMARMDisassembler:libLLVMARMAsmPrinter:libLLVMX86Disassembler:libLLVMX86AsmPrinter:libLLVMMCParser:libLLVMARMCodeGen:libLLVMARMDesc:libLLVMARMInfo:libLLVMSelectionDAG:libLLVMAsmPrinter:libLLVMCodeGen:libLLVMLinker:libLLVMJIT:libLLVMTarget:libLLVMMC:libLLVMScalarOpts:libLLVMInstCombine:libLLVMipo:libLLVMipa:libLLVMTransformUtils:libLLVMAnalysis
 
 # Generate build stamp (Build time + Build git revision + Build Semi SHA1)
@@ -155,6 +176,7 @@
 #=====================================================================
 # Host Shared Library libbcc
 #=====================================================================
+
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libbcc
@@ -163,6 +185,7 @@
 LOCAL_IS_HOST_MODULE := true
 
 LOCAL_CFLAGS := $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
 LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := lib/ExecutionEngine/bcc.cpp
@@ -182,16 +205,24 @@
 endif
 
 LOCAL_STATIC_LIBRARIES += \
-  libcutils \
-  libutils \
   libLLVMARMCodeGen \
   libLLVMARMDesc \
-  libLLVMARMInfo \
+  libLLVMARMInfo
+
+LOCAL_STATIC_LIBRARIES += \
+  libLLVMMipsCodeGen \
+  libLLVMMipsAsmPrinter \
+  libLLVMMipsDesc \
+  libLLVMMipsInfo
+
+LOCAL_STATIC_LIBRARIES += \
   libLLVMX86CodeGen \
   libLLVMX86Desc \
-  libLLVMX86Info \
-  libLLVMX86Utils \
   libLLVMX86AsmPrinter \
+  libLLVMX86Info \
+  libLLVMX86Utils
+
+LOCAL_STATIC_LIBRARIES += \
   libLLVMAsmPrinter \
   libLLVMBitReader \
   libLLVMSelectionDAG \
@@ -210,24 +241,15 @@
   libLLVMCore \
   libLLVMSupport
 
+LOCAL_STATIC_LIBRARIES += \
+  libcutils \
+  libutils
+
 LOCAL_LDLIBS := -ldl -lpthread
 
 # Generate build stamp (Build time + Build git revision + Build Semi SHA1)
 include $(LOCAL_PATH)/libbcc-gen-build-stamp.mk
 
-# definitions for LLVM
-LOCAL_CFLAGS += -DDEBUG_CODEGEN=1
-
-ifeq ($(TARGET_ARCH),arm)
-  LOCAL_CFLAGS += -DFORCE_ARM_CODEGEN=1
-else
-  ifeq ($(TARGET_ARCH),x86)
-    LOCAL_CFLAGS += -DFORCE_X86_CODEGEN=1
-  else
-    $(error Unsupported TARGET_ARCH $(TARGET_ARCH))
-  endif
-endif
-
 include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
 include $(LLVM_ROOT_PATH)/llvm-host-build.mk
 include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/Config.h b/Config.h
index 4141491..ebe0044 100644
--- a/Config.h
+++ b/Config.h
@@ -30,13 +30,20 @@
 #define USE_DISASSEMBLER 0
 #endif
 
+#if defined(__HOST__)
+#define DEBUG_OLD_JIT_DISASSEMBLER_FILE "/tmp/oldjit-dis.s"
+#define DEBUG_MCJIT_DISASSEMBLER_FILE "/tmp/mcjit-dis.s"
+#else
 #define DEBUG_OLD_JIT_DISASSEMBLER_FILE "/data/local/tmp/oldjit-dis.s"
 #define DEBUG_MCJIT_DISASSEMBLER_FILE "/data/local/tmp/mcjit-dis.s"
+#endif // defined(__HOST__)
 
 //---------------------------------------------------------------------------
 // Configuration for ContextManager
 //---------------------------------------------------------------------------
 
+#if USE_OLD_JIT
+
 // Note: Most of the code should NOT use these constants.  Use the public
 // static member of ContextManager instead, which is type-safe.  For example,
 // if you need BCC_CONTEXT_FIXED_ADDR_, then you should write:
@@ -50,6 +57,8 @@
 
 #define BCC_CONTEXT_DATA_SIZE_ (128 * 1024)
 
+#endif // USE_OLD_JIT
+
 //---------------------------------------------------------------------------
 // Configuration for CodeGen and CompilerRT
 //---------------------------------------------------------------------------
@@ -58,6 +67,10 @@
   #define PROVIDE_ARM_CODEGEN
   #define DEFAULT_ARM_CODEGEN
 
+#elif defined(FORCE_MIPS_CODEGEN)
+  #define PROVIDE_MIPS_CODEGEN
+  #define DEFAULT_MIPS_CODEGEN
+
 #elif defined(FORCE_X86_CODEGEN)
   #define PROVIDE_X86_CODEGEN
 
@@ -69,10 +82,13 @@
 
 #else
   #define PROVIDE_ARM_CODEGEN
+  #define PROVIDE_MIPS_CODEGEN
   #define PROVIDE_X86_CODEGEN
 
   #if defined(__arm__)
     #define DEFAULT_ARM_CODEGEN
+  #elif defined(__mips__)
+    #define DEFAULT_MIPS_CODEGEN
   #elif defined(__i386__)
     #define DEFAULT_X86_CODEGEN
   #elif defined(__x86_64__)
@@ -81,11 +97,13 @@
 #endif
 
 #if defined(DEFAULT_ARM_CODEGEN)
-  #define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
+  #define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
+#elif defined(DEFAULT_MIPS_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING "mipsel-none-linux-gnueabi"
 #elif defined(DEFAULT_X86_CODEGEN)
-  #define TARGET_TRIPLE_STRING "i686-unknown-linux"
+  #define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
 #elif defined(DEFAULT_X86_64_CODEGEN)
-  #define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
+  #define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
 #endif
 
 #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
diff --git a/bcinfo/Android.mk b/bcinfo/Android.mk
index 3ca7fd6..f813e77 100644
--- a/bcinfo/Android.mk
+++ b/bcinfo/Android.mk
@@ -43,6 +43,7 @@
   libLLVMCore \
   libLLVMSupport \
   libLLVMBitReader_2_7 \
+  libLLVMBitReader_3_0
 
 LLVM_ROOT_PATH := external/llvm
 
diff --git a/bcinfo/BitReader_2_7/Android.mk b/bcinfo/BitReader_2_7/Android.mk
index 9ccc99f..f60dbbd 100644
--- a/bcinfo/BitReader_2_7/Android.mk
+++ b/bcinfo/BitReader_2_7/Android.mk
@@ -4,8 +4,7 @@
 include $(LLVM_ROOT_PATH)/llvm.mk
 
 bitcode_reader_2_7_SRC_FILES := \
-	BitReader.cpp \
-	BitcodeReader.cpp
+  BitcodeReader.cpp
 
 # For the host
 # =====================================================
@@ -13,6 +12,8 @@
 
 LOCAL_SRC_FILES := $(bitcode_reader_2_7_SRC_FILES)
 
+LOCAL_CFLAGS += -D__HOST__
+
 LOCAL_MODULE:= libLLVMBitReader_2_7
 
 LOCAL_MODULE_TAGS := optional
diff --git a/bcinfo/BitReader_2_7/BitcodeReader.cpp b/bcinfo/BitReader_2_7/BitcodeReader.cpp
index d2449de..c6d821f 100644
--- a/bcinfo/BitReader_2_7/BitcodeReader.cpp
+++ b/bcinfo/BitReader_2_7/BitcodeReader.cpp
@@ -40,6 +40,55 @@
 #define FUNC_CODE_INST_GETRESULT_2_7  25
 #define FUNC_CODE_DEBUG_LOC_2_7       32
 
+#define TYPE_BLOCK_ID_OLD_3_0         10
+#define TYPE_SYMTAB_BLOCK_ID_OLD_3_0  13
+#define TYPE_CODE_STRUCT_OLD_3_0      10
+
+namespace {
+  /// This function strips all debug info intrinsics, except for llvm.dbg.declare.
+  /// If an llvm.dbg.declare intrinsic is invalid, then this function simply
+  /// strips that use.
+  void CheckDebugInfoIntrinsics(Module *M) {
+    if (Function *FuncStart = M->getFunction("llvm.dbg.func.start")) {
+      while (!FuncStart->use_empty())
+        cast<CallInst>(FuncStart->use_back())->eraseFromParent();
+      FuncStart->eraseFromParent();
+    }
+    
+    if (Function *StopPoint = M->getFunction("llvm.dbg.stoppoint")) {
+      while (!StopPoint->use_empty())
+        cast<CallInst>(StopPoint->use_back())->eraseFromParent();
+      StopPoint->eraseFromParent();
+    }
+  
+    if (Function *RegionStart = M->getFunction("llvm.dbg.region.start")) {
+      while (!RegionStart->use_empty())
+        cast<CallInst>(RegionStart->use_back())->eraseFromParent();
+      RegionStart->eraseFromParent();
+    }
+  
+    if (Function *RegionEnd = M->getFunction("llvm.dbg.region.end")) {
+      while (!RegionEnd->use_empty())
+        cast<CallInst>(RegionEnd->use_back())->eraseFromParent();
+      RegionEnd->eraseFromParent();
+    }
+    
+    if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
+      if (!Declare->use_empty()) {
+        DbgDeclareInst *DDI = cast<DbgDeclareInst>(Declare->use_back());
+        if (!isa<MDNode>(DDI->getArgOperand(0)) ||
+            !isa<MDNode>(DDI->getArgOperand(1))) {
+          while (!Declare->use_empty()) {
+            CallInst *CI = cast<CallInst>(Declare->use_back());
+            CI->eraseFromParent();
+          }
+          Declare->eraseFromParent();
+        }
+      }
+    }
+  }
+} // end anonymous namespace
+
 void BitcodeReader::FreeState() {
   if (BufferOwned)
     delete Buffer;
@@ -590,7 +639,7 @@
       ResultTy = PointerType::get(ResultTy, AddressSpace);
       break;
     }
-    case bitc::TYPE_CODE_FUNCTION: {
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
       // FIXME: attrid is dead, remove it in LLVM 3.0
       // FUNCTION: [vararg, attrid, retty, paramty x N]
       if (Record.size() < 3)
@@ -705,7 +754,7 @@
 
 // FIXME: Remove in LLVM 3.1
 bool BitcodeReader::ParseOldTypeTable() {
-  if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_OLD))
+  if (Stream.EnterSubBlock(TYPE_BLOCK_ID_OLD_3_0))
     return Error("Malformed block record");
 
   if (!TypeList.empty())
@@ -808,7 +857,7 @@
       if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
         ResultTy = StructType::create(Context, "");
       break;
-    case bitc::TYPE_CODE_STRUCT_OLD: {// STRUCT_OLD
+    case TYPE_CODE_STRUCT_OLD_3_0: {// STRUCT_OLD
       if (NextTypeID >= TypeList.size()) break;
       // If we already read it, don't reprocess.
       if (TypeList[NextTypeID] &&
@@ -846,7 +895,7 @@
         ResultTy = PointerType::get(ResultTy, AddressSpace);
       break;
     }
-    case bitc::TYPE_CODE_FUNCTION: {
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
       // FIXME: attrid is dead, remove it in LLVM 3.0
       // FUNCTION: [vararg, attrid, retty, paramty x N]
       if (Record.size() < 3)
@@ -894,7 +943,7 @@
 
 
 bool BitcodeReader::ParseOldTypeSymbolTable() {
-  if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID_OLD))
+  if (Stream.EnterSubBlock(TYPE_SYMTAB_BLOCK_ID_OLD_3_0))
     return Error("Malformed block record");
 
   SmallVector<uint64_t, 64> Record;
@@ -1592,11 +1641,11 @@
         if (ParseTypeTable())
           return true;
         break;
-      case bitc::TYPE_BLOCK_ID_OLD:
+      case TYPE_BLOCK_ID_OLD_3_0:
         if (ParseOldTypeTable())
           return true;
         break;
-      case bitc::TYPE_SYMTAB_BLOCK_ID_OLD:
+      case TYPE_SYMTAB_BLOCK_ID_OLD_3_0:
         if (ParseOldTypeSymbolTable())
           return true;
         break;
diff --git a/bcinfo/BitReader_3_0/Android.mk b/bcinfo/BitReader_3_0/Android.mk
new file mode 100644
index 0000000..13b6137
--- /dev/null
+++ b/bcinfo/BitReader_3_0/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+
+LLVM_ROOT_PATH := $(LOCAL_PATH)/../../../../../external/llvm
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+bitcode_reader_3_0_SRC_FILES := \
+  BitcodeReader.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMBitReader_3_0
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(bitcode_reader_3_0_SRC_FILES)
+LOCAL_CFLAGS += -D__HOST__
+
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMBitReader_3_0
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(bitcode_reader_3_0_SRC_FILES)
+
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/bcinfo/BitReader_3_0/BitReader.cpp b/bcinfo/BitReader_3_0/BitReader.cpp
new file mode 100644
index 0000000..15844c0
--- /dev/null
+++ b/bcinfo/BitReader_3_0/BitReader.cpp
@@ -0,0 +1,88 @@
+//===-- BitReader.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/BitReader.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <string>
+#include <cstring>
+
+using namespace llvm;
+
+/* Builds a module from the bitcode in the specified memory buffer, returning a
+   reference to the module via the OutModule parameter. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */
+LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf,
+                          LLVMModuleRef *OutModule, char **OutMessage) {
+  return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule,
+                                   OutMessage);
+}
+
+LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef,
+                                   LLVMMemoryBufferRef MemBuf,
+                                   LLVMModuleRef *OutModule,
+                                   char **OutMessage) {
+  std::string Message;
+  
+  *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), *unwrap(ContextRef),
+                                     &Message));
+  if (!*OutModule) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+}
+
+/* Reads a module from the specified path, returning via the OutModule parameter
+   a module provider which performs lazy deserialization. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef,
+                                       LLVMMemoryBufferRef MemBuf,
+                                       LLVMModuleRef *OutM,
+                                       char **OutMessage) {
+  std::string Message;
+  
+  *OutM = wrap(getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef),
+                                    &Message));
+  if (!*OutM) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+
+}
+
+LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
+                              char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM,
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModuleInContext instead. */
+LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef,
+                                               LLVMMemoryBufferRef MemBuf,
+                                               LLVMModuleProviderRef *OutMP,
+                                               char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(ContextRef, MemBuf,
+                                       reinterpret_cast<LLVMModuleRef*>(OutMP),
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModule instead. */
+LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
+                                      LLVMModuleProviderRef *OutMP,
+                                      char **OutMessage) {
+  return LLVMGetBitcodeModuleProviderInContext(LLVMGetGlobalContext(), MemBuf,
+                                               OutMP, OutMessage);
+}
diff --git a/bcinfo/BitReader_3_0/BitReader_3_0.h b/bcinfo/BitReader_3_0/BitReader_3_0.h
new file mode 100644
index 0000000..2eb4d72
--- /dev/null
+++ b/bcinfo/BitReader_3_0/BitReader_3_0.h
@@ -0,0 +1,48 @@
+//===- BitReader_3_0.h - Internal BitcodeReader 3.0 impl --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BITREADER_3_0_H
+#define BITREADER_3_0_H
+
+#include "llvm/GVMaterializer.h"
+#include "llvm/Attributes.h"
+#include "llvm/Type.h"
+#include "llvm/OperandTraits.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Support/ValueHandle.h"
+#include "llvm/ADT/DenseMap.h"
+#include <string>
+
+namespace llvm {
+  class MemoryBuffer;
+  class LLVMContext;
+  class Module;
+} // End llvm namespace
+
+namespace llvm_3_0 {
+
+llvm::Module *ParseBitcodeFile(llvm::MemoryBuffer *Buffer,
+                               llvm::LLVMContext& Context,
+                               std::string *ErrMsg);
+
+std::string getBitcodeTargetTriple(llvm::MemoryBuffer *Buffer,
+                                   llvm::LLVMContext& Context,
+                                   std::string *ErrMsg);
+
+llvm::Module *getLazyBitcodeModule(llvm::MemoryBuffer *Buffer,
+                                   llvm::LLVMContext& Context,
+                                  std::string *ErrMsg);
+} // End llvm_3_0 namespace
+
+#endif
diff --git a/bcinfo/BitReader_3_0/BitcodeReader.cpp b/bcinfo/BitReader_3_0/BitcodeReader.cpp
new file mode 100644
index 0000000..3549b2c
--- /dev/null
+++ b/bcinfo/BitReader_3_0/BitcodeReader.cpp
@@ -0,0 +1,3348 @@
+//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "BitcodeReader.h"
+#include "BitReader_3_0.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Module.h"
+#include "llvm/Operator.h"
+#include "llvm/AutoUpgrade.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/OperandTraits.h"
+using namespace llvm;
+using namespace llvm_3_0;
+
+#define TYPE_BLOCK_ID_OLD_3_0         10
+#define TYPE_SYMTAB_BLOCK_ID_OLD_3_0  13
+#define TYPE_CODE_STRUCT_OLD_3_0      10
+
+namespace {
+  void FindExnAndSelIntrinsics(BasicBlock *BB, CallInst *&Exn,
+                                      CallInst *&Sel,
+                                      SmallPtrSet<BasicBlock*, 8> &Visited) {
+    if (!Visited.insert(BB)) return;
+
+    for (BasicBlock::iterator
+           I = BB->begin(), E = BB->end(); I != E; ++I) {
+      if (CallInst *CI = dyn_cast<CallInst>(I)) {
+        switch (CI->getCalledFunction()->getIntrinsicID()) {
+        default: break;
+        case Intrinsic::eh_exception:
+          assert(!Exn && "Found more than one eh.exception call!");
+          Exn = CI;
+          break;
+        case Intrinsic::eh_selector:
+          assert(!Sel && "Found more than one eh.selector call!");
+          Sel = CI;
+          break;
+        }
+
+        if (Exn && Sel) return;
+      }
+    }
+
+    if (Exn && Sel) return;
+
+    for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
+      FindExnAndSelIntrinsics(*I, Exn, Sel, Visited);
+      if (Exn && Sel) return;
+    }
+  }
+
+
+
+  /// TransferClausesToLandingPadInst - Transfer the exception handling clauses
+  /// from the eh_selector call to the new landingpad instruction.
+  void TransferClausesToLandingPadInst(LandingPadInst *LPI,
+                                              CallInst *EHSel) {
+    LLVMContext &Context = LPI->getContext();
+    unsigned N = EHSel->getNumArgOperands();
+
+    for (unsigned i = N - 1; i > 1; --i) {
+      if (const ConstantInt *CI = dyn_cast<ConstantInt>(EHSel->getArgOperand(i))){
+        unsigned FilterLength = CI->getZExtValue();
+        unsigned FirstCatch = i + FilterLength + !FilterLength;
+        assert(FirstCatch <= N && "Invalid filter length");
+
+        if (FirstCatch < N)
+          for (unsigned j = FirstCatch; j < N; ++j) {
+            Value *Val = EHSel->getArgOperand(j);
+            if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+              LPI->addClause(EHSel->getArgOperand(j));
+            } else {
+              GlobalVariable *GV = cast<GlobalVariable>(Val);
+              LPI->addClause(GV->getInitializer());
+            }
+          }
+
+        if (!FilterLength) {
+          // Cleanup.
+          LPI->setCleanup(true);
+        } else {
+          // Filter.
+          SmallVector<Constant *, 4> TyInfo;
+          TyInfo.reserve(FilterLength - 1);
+          for (unsigned j = i + 1; j < FirstCatch; ++j)
+            TyInfo.push_back(cast<Constant>(EHSel->getArgOperand(j)));
+          ArrayType *AType =
+            ArrayType::get(!TyInfo.empty() ? TyInfo[0]->getType() :
+                           PointerType::getUnqual(Type::getInt8Ty(Context)),
+                           TyInfo.size());
+          LPI->addClause(ConstantArray::get(AType, TyInfo));
+        }
+
+        N = i;
+      }
+    }
+
+    if (N > 2)
+      for (unsigned j = 2; j < N; ++j) {
+        Value *Val = EHSel->getArgOperand(j);
+        if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+          LPI->addClause(EHSel->getArgOperand(j));
+        } else {
+          GlobalVariable *GV = cast<GlobalVariable>(Val);
+          LPI->addClause(GV->getInitializer());
+        }
+      }
+  }
+
+
+  /// This function upgrades the old pre-3.0 exception handling system to the new
+  /// one. N.B. This will be removed in 3.1.
+  void UpgradeExceptionHandling(Module *M) {
+    Function *EHException = M->getFunction("llvm.eh.exception");
+    Function *EHSelector = M->getFunction("llvm.eh.selector");
+    if (!EHException || !EHSelector)
+      return;
+
+    LLVMContext &Context = M->getContext();
+    Type *ExnTy = PointerType::getUnqual(Type::getInt8Ty(Context));
+    Type *SelTy = Type::getInt32Ty(Context);
+    Type *LPadSlotTy = StructType::get(ExnTy, SelTy, NULL);
+
+    // This map links the invoke instruction with the eh.exception and eh.selector
+    // calls associated with it.
+    DenseMap<InvokeInst*, std::pair<Value*, Value*> > InvokeToIntrinsicsMap;
+    for (Module::iterator
+           I = M->begin(), E = M->end(); I != E; ++I) {
+      Function &F = *I;
+
+      for (Function::iterator
+             II = F.begin(), IE = F.end(); II != IE; ++II) {
+        BasicBlock *BB = &*II;
+        InvokeInst *Inst = dyn_cast<InvokeInst>(BB->getTerminator());
+        if (!Inst) continue;
+        BasicBlock *UnwindDest = Inst->getUnwindDest();
+        if (UnwindDest->isLandingPad()) continue; // Already converted.
+
+        SmallPtrSet<BasicBlock*, 8> Visited;
+        CallInst *Exn = 0;
+        CallInst *Sel = 0;
+        FindExnAndSelIntrinsics(UnwindDest, Exn, Sel, Visited);
+        assert(Exn && Sel && "Cannot find eh.exception and eh.selector calls!");
+        InvokeToIntrinsicsMap[Inst] = std::make_pair(Exn, Sel);
+      }
+    }
+
+    // This map stores the slots where the exception object and selector value are
+    // stored within a function.
+    DenseMap<Function*, std::pair<Value*, Value*> > FnToLPadSlotMap;
+    SmallPtrSet<Instruction*, 32> DeadInsts;
+    for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+           I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+         I != E; ++I) {
+      InvokeInst *Invoke = I->first;
+      BasicBlock *UnwindDest = Invoke->getUnwindDest();
+      Function *F = UnwindDest->getParent();
+      std::pair<Value*, Value*> EHIntrinsics = I->second;
+      CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+      CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+
+      // Store the exception object and selector value in the entry block.
+      Value *ExnSlot = 0;
+      Value *SelSlot = 0;
+      if (!FnToLPadSlotMap[F].first) {
+        BasicBlock *Entry = &F->front();
+        ExnSlot = new AllocaInst(ExnTy, "exn", Entry->getTerminator());
+        SelSlot = new AllocaInst(SelTy, "sel", Entry->getTerminator());
+        FnToLPadSlotMap[F] = std::make_pair(ExnSlot, SelSlot);
+      } else {
+        ExnSlot = FnToLPadSlotMap[F].first;
+        SelSlot = FnToLPadSlotMap[F].second;
+      }
+
+      if (!UnwindDest->getSinglePredecessor()) {
+        // The unwind destination doesn't have a single predecessor. Create an
+        // unwind destination which has only one predecessor.
+        BasicBlock *NewBB = BasicBlock::Create(Context, "new.lpad",
+                                               UnwindDest->getParent());
+        BranchInst::Create(UnwindDest, NewBB);
+        Invoke->setUnwindDest(NewBB);
+
+        // Fix up any PHIs in the original unwind destination block.
+        for (BasicBlock::iterator
+               II = UnwindDest->begin(); isa<PHINode>(II); ++II) {
+          PHINode *PN = cast<PHINode>(II);
+          int Idx = PN->getBasicBlockIndex(Invoke->getParent());
+          if (Idx == -1) continue;
+          PN->setIncomingBlock(Idx, NewBB);
+        }
+
+        UnwindDest = NewBB;
+      }
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(UnwindDest, UnwindDest->getFirstInsertionPt());
+
+      Value *PersFn = Sel->getArgOperand(1);
+      LandingPadInst *LPI = Builder.CreateLandingPad(LPadSlotTy, PersFn, 0);
+      Value *LPExn = Builder.CreateExtractValue(LPI, 0);
+      Value *LPSel = Builder.CreateExtractValue(LPI, 1);
+      Builder.CreateStore(LPExn, ExnSlot);
+      Builder.CreateStore(LPSel, SelSlot);
+
+      TransferClausesToLandingPadInst(LPI, Sel);
+
+      DeadInsts.insert(Exn);
+      DeadInsts.insert(Sel);
+    }
+
+    // Replace the old intrinsic calls with the values from the landingpad
+    // instruction(s). These values were stored in allocas for us to use here.
+    for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+           I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+         I != E; ++I) {
+      std::pair<Value*, Value*> EHIntrinsics = I->second;
+      CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+      CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+      BasicBlock *Parent = Exn->getParent();
+
+      std::pair<Value*,Value*> ExnSelSlots = FnToLPadSlotMap[Parent->getParent()];
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(Parent, Exn);
+      LoadInst *LPExn = Builder.CreateLoad(ExnSelSlots.first, "exn.load");
+      LoadInst *LPSel = Builder.CreateLoad(ExnSelSlots.second, "sel.load");
+
+      Exn->replaceAllUsesWith(LPExn);
+      Sel->replaceAllUsesWith(LPSel);
+    }
+
+    // Remove the dead instructions.
+    for (SmallPtrSet<Instruction*, 32>::iterator
+           I = DeadInsts.begin(), E = DeadInsts.end(); I != E; ++I) {
+      Instruction *Inst = *I;
+      Inst->eraseFromParent();
+    }
+
+    // Replace calls to "llvm.eh.resume" with the 'resume' instruction. Load the
+    // exception and selector values from the stored place.
+    Function *EHResume = M->getFunction("llvm.eh.resume");
+    if (!EHResume) return;
+
+    while (!EHResume->use_empty()) {
+      CallInst *Resume = cast<CallInst>(EHResume->use_back());
+      BasicBlock *BB = Resume->getParent();
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(BB, Resume);
+
+      Value *LPadVal =
+        Builder.CreateInsertValue(UndefValue::get(LPadSlotTy),
+                                  Resume->getArgOperand(0), 0, "lpad.val");
+      LPadVal = Builder.CreateInsertValue(LPadVal, Resume->getArgOperand(1),
+                                          1, "lpad.val");
+      Builder.CreateResume(LPadVal);
+
+      // Remove all instructions after the 'resume.'
+      BasicBlock::iterator I = Resume;
+      while (I != BB->end()) {
+        Instruction *Inst = &*I++;
+        Inst->eraseFromParent();
+      }
+    }
+  }
+
+
+  /// This function strips all debug info intrinsics, except for llvm.dbg.declare.
+  /// If an llvm.dbg.declare intrinsic is invalid, then this function simply
+  /// strips that use.
+  void CheckDebugInfoIntrinsics(Module *M) {
+    if (Function *FuncStart = M->getFunction("llvm.dbg.func.start")) {
+      while (!FuncStart->use_empty())
+        cast<CallInst>(FuncStart->use_back())->eraseFromParent();
+      FuncStart->eraseFromParent();
+    }
+
+    if (Function *StopPoint = M->getFunction("llvm.dbg.stoppoint")) {
+      while (!StopPoint->use_empty())
+        cast<CallInst>(StopPoint->use_back())->eraseFromParent();
+      StopPoint->eraseFromParent();
+    }
+
+    if (Function *RegionStart = M->getFunction("llvm.dbg.region.start")) {
+      while (!RegionStart->use_empty())
+        cast<CallInst>(RegionStart->use_back())->eraseFromParent();
+      RegionStart->eraseFromParent();
+    }
+
+    if (Function *RegionEnd = M->getFunction("llvm.dbg.region.end")) {
+      while (!RegionEnd->use_empty())
+        cast<CallInst>(RegionEnd->use_back())->eraseFromParent();
+      RegionEnd->eraseFromParent();
+    }
+
+    if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
+      if (!Declare->use_empty()) {
+        DbgDeclareInst *DDI = cast<DbgDeclareInst>(Declare->use_back());
+        if (!isa<MDNode>(DDI->getArgOperand(0)) ||
+            !isa<MDNode>(DDI->getArgOperand(1))) {
+          while (!Declare->use_empty()) {
+            CallInst *CI = cast<CallInst>(Declare->use_back());
+            CI->eraseFromParent();
+          }
+          Declare->eraseFromParent();
+        }
+      }
+    }
+  }
+} // end anonymous namespace
+
+void BitcodeReader::FreeState() {
+  if (BufferOwned)
+    delete Buffer;
+  Buffer = 0;
+  std::vector<Type*>().swap(TypeList);
+  ValueList.clear();
+  MDValueList.clear();
+
+  std::vector<AttrListPtr>().swap(MAttributes);
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  std::vector<Function*>().swap(FunctionsWithBodies);
+  DeferredFunctionInfo.clear();
+  MDKindMap.clear();
+}
+
+//===----------------------------------------------------------------------===//
+//  Helper functions to implement forward reference resolution, etc.
+//===----------------------------------------------------------------------===//
+
+/// ConvertToString - Convert a string from a record into an std::string, return
+/// true on failure.
+template<typename StrTy>
+static bool ConvertToString(SmallVector<uint64_t, 64> &Record, unsigned Idx,
+                            StrTy &Result) {
+  if (Idx > Record.size())
+    return true;
+
+  for (unsigned i = Idx, e = Record.size(); i != e; ++i)
+    Result += (char)Record[i];
+  return false;
+}
+
+static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown/new linkages to external
+  case 0:  return GlobalValue::ExternalLinkage;
+  case 1:  return GlobalValue::WeakAnyLinkage;
+  case 2:  return GlobalValue::AppendingLinkage;
+  case 3:  return GlobalValue::InternalLinkage;
+  case 4:  return GlobalValue::LinkOnceAnyLinkage;
+  case 5:  return GlobalValue::DLLImportLinkage;
+  case 6:  return GlobalValue::DLLExportLinkage;
+  case 7:  return GlobalValue::ExternalWeakLinkage;
+  case 8:  return GlobalValue::CommonLinkage;
+  case 9:  return GlobalValue::PrivateLinkage;
+  case 10: return GlobalValue::WeakODRLinkage;
+  case 11: return GlobalValue::LinkOnceODRLinkage;
+  case 12: return GlobalValue::AvailableExternallyLinkage;
+  case 13: return GlobalValue::LinkerPrivateLinkage;
+  case 14: return GlobalValue::LinkerPrivateWeakLinkage;
+  case 15: return GlobalValue::LinkerPrivateWeakDefAutoLinkage;
+  }
+}
+
+static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown visibilities to default.
+  case 0: return GlobalValue::DefaultVisibility;
+  case 1: return GlobalValue::HiddenVisibility;
+  case 2: return GlobalValue::ProtectedVisibility;
+  }
+}
+
+static int GetDecodedCastOpcode(unsigned Val) {
+  switch (Val) {
+  default: return -1;
+  case bitc::CAST_TRUNC   : return Instruction::Trunc;
+  case bitc::CAST_ZEXT    : return Instruction::ZExt;
+  case bitc::CAST_SEXT    : return Instruction::SExt;
+  case bitc::CAST_FPTOUI  : return Instruction::FPToUI;
+  case bitc::CAST_FPTOSI  : return Instruction::FPToSI;
+  case bitc::CAST_UITOFP  : return Instruction::UIToFP;
+  case bitc::CAST_SITOFP  : return Instruction::SIToFP;
+  case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
+  case bitc::CAST_FPEXT   : return Instruction::FPExt;
+  case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
+  case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
+  case bitc::CAST_BITCAST : return Instruction::BitCast;
+  }
+}
+static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) {
+  switch (Val) {
+  default: return -1;
+  case bitc::BINOP_ADD:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add;
+  case bitc::BINOP_SUB:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub;
+  case bitc::BINOP_MUL:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul;
+  case bitc::BINOP_UDIV: return Instruction::UDiv;
+  case bitc::BINOP_SDIV:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv;
+  case bitc::BINOP_UREM: return Instruction::URem;
+  case bitc::BINOP_SREM:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem;
+  case bitc::BINOP_SHL:  return Instruction::Shl;
+  case bitc::BINOP_LSHR: return Instruction::LShr;
+  case bitc::BINOP_ASHR: return Instruction::AShr;
+  case bitc::BINOP_AND:  return Instruction::And;
+  case bitc::BINOP_OR:   return Instruction::Or;
+  case bitc::BINOP_XOR:  return Instruction::Xor;
+  }
+}
+
+static AtomicRMWInst::BinOp GetDecodedRMWOperation(unsigned Val) {
+  switch (Val) {
+  default: return AtomicRMWInst::BAD_BINOP;
+  case bitc::RMW_XCHG: return AtomicRMWInst::Xchg;
+  case bitc::RMW_ADD: return AtomicRMWInst::Add;
+  case bitc::RMW_SUB: return AtomicRMWInst::Sub;
+  case bitc::RMW_AND: return AtomicRMWInst::And;
+  case bitc::RMW_NAND: return AtomicRMWInst::Nand;
+  case bitc::RMW_OR: return AtomicRMWInst::Or;
+  case bitc::RMW_XOR: return AtomicRMWInst::Xor;
+  case bitc::RMW_MAX: return AtomicRMWInst::Max;
+  case bitc::RMW_MIN: return AtomicRMWInst::Min;
+  case bitc::RMW_UMAX: return AtomicRMWInst::UMax;
+  case bitc::RMW_UMIN: return AtomicRMWInst::UMin;
+  }
+}
+
+static AtomicOrdering GetDecodedOrdering(unsigned Val) {
+  switch (Val) {
+  case bitc::ORDERING_NOTATOMIC: return NotAtomic;
+  case bitc::ORDERING_UNORDERED: return Unordered;
+  case bitc::ORDERING_MONOTONIC: return Monotonic;
+  case bitc::ORDERING_ACQUIRE: return Acquire;
+  case bitc::ORDERING_RELEASE: return Release;
+  case bitc::ORDERING_ACQREL: return AcquireRelease;
+  default: // Map unknown orderings to sequentially-consistent.
+  case bitc::ORDERING_SEQCST: return SequentiallyConsistent;
+  }
+}
+
+static SynchronizationScope GetDecodedSynchScope(unsigned Val) {
+  switch (Val) {
+  case bitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread;
+  default: // Map unknown scopes to cross-thread.
+  case bitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread;
+  }
+}
+
+namespace llvm {
+namespace {
+  /// @brief A class for maintaining the slot number definition
+  /// as a placeholder for the actual definition for forward constants defs.
+  class ConstantPlaceHolder : public ConstantExpr {
+    void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
+  public:
+    // allocate space for exactly one operand
+    void *operator new(size_t s) {
+      return User::operator new(s, 1);
+    }
+    explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context)
+      : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+      Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
+    }
+
+    /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+    //static inline bool classof(const ConstantPlaceHolder *) { return true; }
+    static bool classof(const Value *V) {
+      return isa<ConstantExpr>(V) &&
+             cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
+    }
+
+
+    /// Provide fast operand accessors
+    //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+  };
+}
+
+// FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> :
+  public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
+};
+}
+
+
+void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(V);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  WeakVH &OldV = ValuePtrs[Idx];
+  if (OldV == 0) {
+    OldV = V;
+    return;
+  }
+
+  // Handle constants and non-constants (e.g. instrs) differently for
+  // efficiency.
+  if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
+    ResolveConstants.push_back(std::make_pair(PHC, Idx));
+    OldV = V;
+  } else {
+    // If there was a forward reference to this value, replace it.
+    Value *PrevVal = OldV;
+    OldV->replaceAllUsesWith(V);
+    delete PrevVal;
+  }
+}
+
+
+Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+                                                    Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert(Ty == V->getType() && "Type mismatch in constant table!");
+    return cast<Constant>(V);
+  }
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Constant *C = new ConstantPlaceHolder(Ty, Context);
+  ValuePtrs[Idx] = C;
+  return C;
+}
+
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
+    return V;
+  }
+
+  // No type specified, must be invalid reference.
+  if (Ty == 0) return 0;
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Value *V = new Argument(Ty);
+  ValuePtrs[Idx] = V;
+  return V;
+}
+
+/// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+/// resolves any forward references.  The idea behind this is that we sometimes
+/// get constants (such as large arrays) which reference *many* forward ref
+/// constants.  Replacing each of these causes a lot of thrashing when
+/// building/reuniquing the constant.  Instead of doing this, we look at all the
+/// uses and rewrite all the place holders at once for any constant that uses
+/// a placeholder.
+void BitcodeReaderValueList::ResolveConstantForwardRefs() {
+  // Sort the values by-pointer so that they are efficient to look up with a
+  // binary search.
+  std::sort(ResolveConstants.begin(), ResolveConstants.end());
+
+  SmallVector<Constant*, 64> NewOps;
+
+  while (!ResolveConstants.empty()) {
+    Value *RealVal = operator[](ResolveConstants.back().second);
+    Constant *Placeholder = ResolveConstants.back().first;
+    ResolveConstants.pop_back();
+
+    // Loop over all users of the placeholder, updating them to reference the
+    // new value.  If they reference more than one placeholder, update them all
+    // at once.
+    while (!Placeholder->use_empty()) {
+      Value::use_iterator UI = Placeholder->use_begin();
+      User *U = *UI;
+
+      // If the using object isn't uniqued, just update the operands.  This
+      // handles instructions and initializers for global variables.
+      if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
+        UI.getUse().set(RealVal);
+        continue;
+      }
+
+      // Otherwise, we have a constant that uses the placeholder.  Replace that
+      // constant with a new constant that has *all* placeholder uses updated.
+      Constant *UserC = cast<Constant>(U);
+      for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
+           I != E; ++I) {
+        Value *NewOp;
+        if (!isa<ConstantPlaceHolder>(*I)) {
+          // Not a placeholder reference.
+          NewOp = *I;
+        } else if (*I == Placeholder) {
+          // Common case is that it just references this one placeholder.
+          NewOp = RealVal;
+        } else {
+          // Otherwise, look up the placeholder in ResolveConstants.
+          ResolveConstantsTy::iterator It =
+            std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(),
+                             std::pair<Constant*, unsigned>(cast<Constant>(*I),
+                                                            0));
+          assert(It != ResolveConstants.end() && It->first == *I);
+          NewOp = operator[](It->second);
+        }
+
+        NewOps.push_back(cast<Constant>(NewOp));
+      }
+
+      // Make the new constant.
+      Constant *NewC;
+      if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
+        NewC = ConstantArray::get(UserCA->getType(), NewOps);
+      } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
+        NewC = ConstantStruct::get(UserCS->getType(), NewOps);
+      } else if (isa<ConstantVector>(UserC)) {
+        NewC = ConstantVector::get(NewOps);
+      } else {
+        assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
+        NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
+      }
+
+      UserC->replaceAllUsesWith(NewC);
+      UserC->destroyConstant();
+      NewOps.clear();
+    }
+
+    // Update all ValueHandles, they should be the only users at this point.
+    Placeholder->replaceAllUsesWith(RealVal);
+    delete Placeholder;
+  }
+}
+
+void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(V);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  WeakVH &OldV = MDValuePtrs[Idx];
+  if (OldV == 0) {
+    OldV = V;
+    return;
+  }
+
+  // If there was a forward reference to this value, replace it.
+  MDNode *PrevVal = cast<MDNode>(OldV);
+  OldV->replaceAllUsesWith(V);
+  MDNode::deleteTemporary(PrevVal);
+  // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new
+  // value for Idx.
+  MDValuePtrs[Idx] = V;
+}
+
+Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = MDValuePtrs[Idx]) {
+    assert(V->getType()->isMetadataTy() && "Type mismatch in value table!");
+    return V;
+  }
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Value *V = MDNode::getTemporary(Context, ArrayRef<Value*>());
+  MDValuePtrs[Idx] = V;
+  return V;
+}
+
+Type *BitcodeReader::getTypeByID(unsigned ID) {
+  // The type table size is always specified correctly.
+  if (ID >= TypeList.size())
+    return 0;
+
+  if (Type *Ty = TypeList[ID])
+    return Ty;
+
+  // If we have a forward reference, the only possible case is when it is to a
+  // named struct.  Just create a placeholder for now.
+  return TypeList[ID] = StructType::create(Context);
+}
+
+/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
+Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
+  if (ID >= TypeList.size())
+    TypeList.resize(ID+1);
+
+  return TypeList[ID];
+}
+
+
+//===----------------------------------------------------------------------===//
+//  Functions for parsing blocks from the bitcode file
+//===----------------------------------------------------------------------===//
+
+bool BitcodeReader::ParseAttributeBlock() {
+  if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
+    return Error("Malformed block record");
+
+  if (!MAttributes.empty())
+    return Error("Multiple PARAMATTR blocks found!");
+
+  SmallVector<uint64_t, 64> Record;
+
+  SmallVector<AttributeWithIndex, 8> Attrs;
+
+  // Read all the records.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of PARAMATTR block");
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.ReadRecord(Code, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [paramidx0, attr0, ...]
+      if (Record.size() & 1)
+        return Error("Invalid ENTRY record");
+
+      // FIXME : Remove this autoupgrade code in LLVM 3.0.
+      // If Function attributes are using index 0 then transfer them
+      // to index ~0. Index 0 is used for return value attributes but used to be
+      // used for function attributes.
+      Attributes RetAttribute = Attribute::None;
+      Attributes FnAttribute = Attribute::None;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        // FIXME: remove in LLVM 3.0
+        // The alignment is stored as a 16-bit raw value from bits 31--16.
+        // We shift the bits above 31 down by 11 bits.
+
+        unsigned Alignment = (Record[i+1] & (0xffffull << 16)) >> 16;
+        if (Alignment && !isPowerOf2_32(Alignment))
+          return Error("Alignment is not a power of two.");
+
+        Attributes ReconstitutedAttr = Record[i+1] & 0xffff;
+        if (Alignment)
+          ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment);
+        ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11;
+        Record[i+1] = ReconstitutedAttr;
+
+        if (Record[i] == 0)
+          RetAttribute = Record[i+1];
+        else if (Record[i] == ~0U)
+          FnAttribute = Record[i+1];
+      }
+
+      unsigned OldRetAttrs = (Attribute::NoUnwind|Attribute::NoReturn|
+                              Attribute::ReadOnly|Attribute::ReadNone);
+
+      if (FnAttribute == Attribute::None && RetAttribute != Attribute::None &&
+          (RetAttribute & OldRetAttrs) != 0) {
+        if (FnAttribute == Attribute::None) { // add a slot so they get added.
+          Record.push_back(~0U);
+          Record.push_back(0);
+        }
+
+        FnAttribute  |= RetAttribute & OldRetAttrs;
+        RetAttribute &= ~OldRetAttrs;
+      }
+
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        if (Record[i] == 0) {
+          if (RetAttribute != Attribute::None)
+            Attrs.push_back(AttributeWithIndex::get(0, RetAttribute));
+        } else if (Record[i] == ~0U) {
+          if (FnAttribute != Attribute::None)
+            Attrs.push_back(AttributeWithIndex::get(~0U, FnAttribute));
+        } else if (Record[i+1] != Attribute::None)
+          Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1]));
+      }
+
+      MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end()));
+      Attrs.clear();
+      break;
+    }
+    }
+  }
+}
+
+bool BitcodeReader::ParseTypeTable() {
+  if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
+    return Error("Malformed block record");
+
+  return ParseTypeTableBody();
+}
+
+bool BitcodeReader::ParseTypeTableBody() {
+  if (!TypeList.empty())
+    return Error("Multiple TYPE_BLOCKs found!");
+
+  SmallVector<uint64_t, 64> Record;
+  unsigned NumRecords = 0;
+
+  SmallString<64> TypeName;
+
+  // Read all the records for this type table.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (NumRecords != TypeList.size())
+        return Error("Invalid type forward reference in TYPE_BLOCK");
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of type table block");
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = 0;
+    switch (Stream.ReadRecord(Code, Record)) {
+    default: return Error("unknown type in type table");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid TYPE_CODE_NUMENTRY record");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid Integer type record");
+
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+                                    //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid POINTER type record");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      ResultTy = getTypeByID(Record[0]);
+      if (ResultTy == 0) return Error("invalid element type in pointer type");
+      ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 3.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid FUNCTION type record");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          ArgTys.push_back(T);
+        else
+          break;
+      }
+
+      ResultTy = getTypeByID(Record[2]);
+      if (ResultTy == 0 || ArgTys.size() < Record.size()-3)
+        return Error("invalid type in function type");
+
+      ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION: {
+      // FUNCTION: [vararg, retty, paramty x N]
+      if (Record.size() < 2)
+        return Error("Invalid FUNCTION type record");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          ArgTys.push_back(T);
+        else
+          break;
+      }
+
+      ResultTy = getTypeByID(Record[1]);
+      if (ResultTy == 0 || ArgTys.size() < Record.size()-2)
+        return Error("invalid type in function type");
+
+      ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_ANON: {  // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid STRUCT type record");
+      std::vector<Type*> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("invalid type in struct type");
+      ResultTy = StructType::get(Context, EltTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_NAME:   // STRUCT_NAME: [strchr x N]
+      if (ConvertToString(Record, 0, TypeName))
+        return Error("Invalid STRUCT_NAME record");
+      continue;
+
+    case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid STRUCT type record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = 0;
+      } else  // Otherwise, create a new struct.
+        Res = StructType::create(Context, TypeName);
+      TypeName.clear();
+
+      SmallVector<Type*, 8> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("invalid STRUCT type record");
+      Res->setBody(EltTys, Record[0]);
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_OPAQUE: {       // OPAQUE: []
+      if (Record.size() != 1)
+        return Error("Invalid OPAQUE type record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = 0;
+      } else  // Otherwise, create a new struct with no body.
+        Res = StructType::create(Context, TypeName);
+      TypeName.clear();
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid ARRAY type record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid ARRAY type element");
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid VECTOR type record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid ARRAY type element");
+      break;
+    }
+
+    if (NumRecords >= TypeList.size())
+      return Error("invalid TYPE table");
+    assert(ResultTy && "Didn't read a type?");
+    assert(TypeList[NumRecords] == 0 && "Already read type?");
+    TypeList[NumRecords++] = ResultTy;
+  }
+}
+
+// FIXME: Remove in LLVM 3.1
+bool BitcodeReader::ParseOldTypeTable() {
+  if (Stream.EnterSubBlock(TYPE_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block record");
+
+  if (!TypeList.empty())
+    return Error("Multiple TYPE_BLOCKs found!");
+
+
+  // While horrible, we have no good ordering of types in the bc file.  Just
+  // iteratively parse types out of the bc file in multiple passes until we get
+  // them all.  Do this by saving a cursor for the start of the type block.
+  BitstreamCursor StartOfTypeBlockCursor(Stream);
+
+  unsigned NumTypesRead = 0;
+
+  SmallVector<uint64_t, 64> Record;
+RestartScan:
+  unsigned NextTypeID = 0;
+  bool ReadAnyTypes = false;
+
+  // Read all the records for this type table.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (NextTypeID != TypeList.size())
+        return Error("Invalid type forward reference in TYPE_BLOCK_ID_OLD");
+
+      // If we haven't read all of the types yet, iterate again.
+      if (NumTypesRead != TypeList.size()) {
+        // If we didn't successfully read any types in this pass, then we must
+        // have an unhandled forward reference.
+        if (!ReadAnyTypes)
+          return Error("Obsolete bitcode contains unhandled recursive type");
+
+        Stream = StartOfTypeBlockCursor;
+        goto RestartScan;
+      }
+
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of type table block");
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = 0;
+    switch (Stream.ReadRecord(Code, Record)) {
+    default: return Error("unknown type in type table");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid TYPE_CODE_NUMENTRY record");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid Integer type record");
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_OPAQUE:    // OPAQUE
+      if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
+        ResultTy = StructType::create(Context);
+      break;
+    case TYPE_CODE_STRUCT_OLD_3_0: {// STRUCT_OLD
+      if (NextTypeID >= TypeList.size()) break;
+      // If we already read it, don't reprocess.
+      if (TypeList[NextTypeID] &&
+          !cast<StructType>(TypeList[NextTypeID])->isOpaque())
+        break;
+
+      // Set a type.
+      if (TypeList[NextTypeID] == 0)
+        TypeList[NextTypeID] = StructType::create(Context);
+
+      std::vector<Type*> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          EltTys.push_back(Elt);
+        else
+          break;
+      }
+
+      if (EltTys.size() != Record.size()-1)
+        break;      // Not all elements are ready.
+
+      cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
+      ResultTy = TypeList[NextTypeID];
+      TypeList[NextTypeID] = 0;
+      break;
+    }
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+      //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid POINTER type record");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      if ((ResultTy = getTypeByIDOrNull(Record[0])))
+        ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 3.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid FUNCTION type record");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          ArgTys.push_back(Elt);
+        else
+          break;
+      }
+      if (ArgTys.size()+3 != Record.size())
+        break;  // Something was null.
+      if ((ResultTy = getTypeByIDOrNull(Record[2])))
+        ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION: {
+      // FUNCTION: [vararg, retty, paramty x N]
+      if (Record.size() < 2)
+        return Error("Invalid FUNCTION type record");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          ArgTys.push_back(Elt);
+        else
+          break;
+      }
+      if (ArgTys.size()+2 != Record.size())
+        break;  // Something was null.
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid ARRAY type record");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid VECTOR type record");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      break;
+    }
+
+    if (NextTypeID >= TypeList.size())
+      return Error("invalid TYPE table");
+
+    if (ResultTy && TypeList[NextTypeID] == 0) {
+      ++NumTypesRead;
+      ReadAnyTypes = true;
+
+      TypeList[NextTypeID] = ResultTy;
+    }
+
+    ++NextTypeID;
+  }
+}
+
+
+bool BitcodeReader::ParseOldTypeSymbolTable() {
+  if (Stream.EnterSubBlock(TYPE_SYMTAB_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this type table.
+  std::string TypeName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of type symbol table block");
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.ReadRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::TST_CODE_ENTRY:    // TST_ENTRY: [typeid, namechar x N]
+      if (ConvertToString(Record, 1, TypeName))
+        return Error("Invalid TST_ENTRY record");
+      unsigned TypeID = Record[0];
+      if (TypeID >= TypeList.size())
+        return Error("Invalid Type ID in TST_ENTRY record");
+
+      // Only apply the type name to a struct type with no name.
+      if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
+        if (!STy->isLiteral() && !STy->hasName())
+          STy->setName(TypeName);
+      TypeName.clear();
+      break;
+    }
+  }
+}
+
+bool BitcodeReader::ParseValueSymbolTable() {
+  if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  SmallString<128> ValueName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of value symbol table block");
+      return false;
+    }
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.ReadRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::VST_CODE_ENTRY: {  // VST_ENTRY: [valueid, namechar x N]
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid VST_ENTRY record");
+      unsigned ValueID = Record[0];
+      if (ValueID >= ValueList.size())
+        return Error("Invalid Value ID in VST_ENTRY record");
+      Value *V = ValueList[ValueID];
+
+      V->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    case bitc::VST_CODE_BBENTRY: {
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid VST_BBENTRY record");
+      BasicBlock *BB = getBasicBlock(Record[0]);
+      if (BB == 0)
+        return Error("Invalid BB ID in VST_BBENTRY record");
+
+      BB->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    }
+  }
+}
+
+bool BitcodeReader::ParseMetadata() {
+  unsigned NextMDValueNo = MDValueList.size();
+
+  if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of PARAMATTR block");
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    bool IsFunctionLocal = false;
+    // Read a record.
+    Record.clear();
+    Code = Stream.ReadRecord(Code, Record);
+    switch (Code) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::METADATA_NAME: {
+      // Read named of the named metadata.
+      unsigned NameLength = Record.size();
+      SmallString<8> Name;
+      Name.resize(NameLength);
+      for (unsigned i = 0; i != NameLength; ++i)
+        Name[i] = Record[i];
+      Record.clear();
+      Code = Stream.ReadCode();
+
+      // METADATA_NAME is always followed by METADATA_NAMED_NODE.
+      unsigned NextBitCode = Stream.ReadRecord(Code, Record);
+      assert(NextBitCode == bitc::METADATA_NAMED_NODE); (void)NextBitCode;
+
+      // Read named metadata elements.
+      unsigned Size = Record.size();
+      NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name);
+      for (unsigned i = 0; i != Size; ++i) {
+        MDNode *MD = dyn_cast<MDNode>(MDValueList.getValueFwdRef(Record[i]));
+        if (MD == 0)
+          return Error("Malformed metadata record");
+        NMD->addOperand(MD);
+      }
+      break;
+    }
+    case bitc::METADATA_FN_NODE:
+      IsFunctionLocal = true;
+      // fall-through
+    case bitc::METADATA_NODE: {
+      if (Record.size() % 2 == 1)
+        return Error("Invalid METADATA_NODE record");
+
+      unsigned Size = Record.size();
+      SmallVector<Value*, 8> Elts;
+      for (unsigned i = 0; i != Size; i += 2) {
+        Type *Ty = getTypeByID(Record[i]);
+        if (!Ty) return Error("Invalid METADATA_NODE record");
+        if (Ty->isMetadataTy())
+          Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
+        else if (!Ty->isVoidTy())
+          Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty));
+        else
+          Elts.push_back(NULL);
+      }
+      Value *V = MDNode::getWhenValsUnresolved(Context, Elts, IsFunctionLocal);
+      IsFunctionLocal = false;
+      MDValueList.AssignValue(V, NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_STRING: {
+      unsigned MDStringLength = Record.size();
+      SmallString<8> String;
+      String.resize(MDStringLength);
+      for (unsigned i = 0; i != MDStringLength; ++i)
+        String[i] = Record[i];
+      Value *V = MDString::get(Context,
+                               StringRef(String.data(), String.size()));
+      MDValueList.AssignValue(V, NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_KIND: {
+      unsigned RecordLength = Record.size();
+      if (Record.empty() || RecordLength < 2)
+        return Error("Invalid METADATA_KIND record");
+      SmallString<8> Name;
+      Name.resize(RecordLength-1);
+      unsigned Kind = Record[0];
+      for (unsigned i = 1; i != RecordLength; ++i)
+        Name[i-1] = Record[i];
+
+      unsigned NewKind = TheModule->getMDKindID(Name.str());
+      if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
+        return Error("Conflicting METADATA_KIND records");
+      break;
+    }
+    }
+  }
+}
+
+/// DecodeSignRotatedValue - Decode a signed value stored with the sign bit in
+/// the LSB for dense VBR encoding.
+static uint64_t DecodeSignRotatedValue(uint64_t V) {
+  if ((V & 1) == 0)
+    return V >> 1;
+  if (V != 1)
+    return -(V >> 1);
+  // There is no such thing as -0 with integers.  "-0" really means MININT.
+  return 1ULL << 63;
+}
+
+/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global
+/// values and aliases that we can.
+bool BitcodeReader::ResolveGlobalAndAliasInits() {
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+
+  GlobalInitWorklist.swap(GlobalInits);
+  AliasInitWorklist.swap(AliasInits);
+
+  while (!GlobalInitWorklist.empty()) {
+    unsigned ValID = GlobalInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      // Not ready to resolve this yet, it requires something later in the file.
+      GlobalInits.push_back(GlobalInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
+        GlobalInitWorklist.back().first->setInitializer(C);
+      else
+        return Error("Global variable initializer is not a constant!");
+    }
+    GlobalInitWorklist.pop_back();
+  }
+
+  while (!AliasInitWorklist.empty()) {
+    unsigned ValID = AliasInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      AliasInits.push_back(AliasInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
+        AliasInitWorklist.back().first->setAliasee(C);
+      else
+        return Error("Alias initializer is not a constant!");
+    }
+    AliasInitWorklist.pop_back();
+  }
+  return false;
+}
+
+bool BitcodeReader::ParseConstants() {
+  if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  Type *CurTy = Type::getInt32Ty(Context);
+  unsigned NextCstNo = ValueList.size();
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK)
+      break;
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Value *V = 0;
+    unsigned BitCode = Stream.ReadRecord(Code, Record);
+    switch (BitCode) {
+    default:  // Default behavior: unknown constant
+    case bitc::CST_CODE_UNDEF:     // UNDEF
+      V = UndefValue::get(CurTy);
+      break;
+    case bitc::CST_CODE_SETTYPE:   // SETTYPE: [typeid]
+      if (Record.empty())
+        return Error("Malformed CST_SETTYPE record");
+      if (Record[0] >= TypeList.size())
+        return Error("Invalid Type ID in CST_SETTYPE record");
+      CurTy = TypeList[Record[0]];
+      continue;  // Skip the ValueList manipulation.
+    case bitc::CST_CODE_NULL:      // NULL
+      V = Constant::getNullValue(CurTy);
+      break;
+    case bitc::CST_CODE_INTEGER:   // INTEGER: [intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid CST_INTEGER record");
+      V = ConstantInt::get(CurTy, DecodeSignRotatedValue(Record[0]));
+      break;
+    case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid WIDE_INTEGER record");
+
+      unsigned NumWords = Record.size();
+      SmallVector<uint64_t, 8> Words;
+      Words.resize(NumWords);
+      for (unsigned i = 0; i != NumWords; ++i)
+        Words[i] = DecodeSignRotatedValue(Record[i]);
+      V = ConstantInt::get(Context,
+                           APInt(cast<IntegerType>(CurTy)->getBitWidth(),
+                                 Words));
+      break;
+    }
+    case bitc::CST_CODE_FLOAT: {    // FLOAT: [fpval]
+      if (Record.empty())
+        return Error("Invalid FLOAT record");
+      if (CurTy->isFloatTy())
+        V = ConstantFP::get(Context, APFloat(APInt(32, (uint32_t)Record[0])));
+      else if (CurTy->isDoubleTy())
+        V = ConstantFP::get(Context, APFloat(APInt(64, Record[0])));
+      else if (CurTy->isX86_FP80Ty()) {
+        // Bits are not stored the same way as a normal i80 APInt, compensate.
+        uint64_t Rearrange[2];
+        Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
+        Rearrange[1] = Record[0] >> 48;
+        V = ConstantFP::get(Context, APFloat(APInt(80, Rearrange)));
+      } else if (CurTy->isFP128Ty())
+        V = ConstantFP::get(Context, APFloat(APInt(128, Record), true));
+      else if (CurTy->isPPC_FP128Ty())
+        V = ConstantFP::get(Context, APFloat(APInt(128, Record)));
+      else
+        V = UndefValue::get(CurTy);
+      break;
+    }
+
+    case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number]
+      if (Record.empty())
+        return Error("Invalid CST_AGGREGATE record");
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+
+      if (StructType *STy = dyn_cast<StructType>(CurTy)) {
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i],
+                                                     STy->getElementType(i)));
+        V = ConstantStruct::get(STy, Elts);
+      } else if (ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
+        Type *EltTy = ATy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantArray::get(ATy, Elts);
+      } else if (VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
+        Type *EltTy = VTy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantVector::get(Elts);
+      } else {
+        V = UndefValue::get(CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_STRING: { // STRING: [values]
+      if (Record.empty())
+        return Error("Invalid CST_AGGREGATE record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CSTRING: { // CSTRING: [values]
+      if (Record.empty())
+        return Error("Invalid CST_AGGREGATE record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      Elts.push_back(Constant::getNullValue(EltTy));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CE_BINOP: {  // CE_BINOP: [opcode, opval, opval]
+      if (Record.size() < 3) return Error("Invalid CE_BINOP record");
+      int Opc = GetDecodedBinaryOpcode(Record[0], CurTy);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown binop.
+      } else {
+        Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
+        Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
+        unsigned Flags = 0;
+        if (Record.size() >= 4) {
+          if (Opc == Instruction::Add ||
+              Opc == Instruction::Sub ||
+              Opc == Instruction::Mul ||
+              Opc == Instruction::Shl) {
+            if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoSignedWrap;
+            if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+          } else if (Opc == Instruction::SDiv ||
+                     Opc == Instruction::UDiv ||
+                     Opc == Instruction::LShr ||
+                     Opc == Instruction::AShr) {
+            if (Record[3] & (1 << bitc::PEO_EXACT))
+              Flags |= SDivOperator::IsExact;
+          }
+        }
+        V = ConstantExpr::get(Opc, LHS, RHS, Flags);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_CAST: {  // CE_CAST: [opcode, opty, opval]
+      if (Record.size() < 3) return Error("Invalid CE_CAST record");
+      int Opc = GetDecodedCastOpcode(Record[0]);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown cast.
+      } else {
+        Type *OpTy = getTypeByID(Record[1]);
+        if (!OpTy) return Error("Invalid CE_CAST record");
+        Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
+        V = ConstantExpr::getCast(Opc, Op, CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_INBOUNDS_GEP:
+    case bitc::CST_CODE_CE_GEP: {  // CE_GEP:        [n x operands]
+      if (Record.size() & 1) return Error("Invalid CE_GEP record");
+      SmallVector<Constant*, 16> Elts;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        Type *ElTy = getTypeByID(Record[i]);
+        if (!ElTy) return Error("Invalid CE_GEP record");
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+      }
+      ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
+      V = ConstantExpr::getGetElementPtr(Elts[0], Indices,
+                                         BitCode ==
+                                           bitc::CST_CODE_CE_INBOUNDS_GEP);
+      break;
+    }
+    case bitc::CST_CODE_CE_SELECT:  // CE_SELECT: [opval#, opval#, opval#]
+      if (Record.size() < 3) return Error("Invalid CE_SELECT record");
+      V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
+                                                              Type::getInt1Ty(Context)),
+                                  ValueList.getConstantFwdRef(Record[1],CurTy),
+                                  ValueList.getConstantFwdRef(Record[2],CurTy));
+      break;
+    case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval]
+      if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record");
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getExtractElement(Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || OpTy == 0)
+        return Error("Invalid CE_INSERTELT record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
+                                                  OpTy->getElementType());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || OpTy == 0)
+        return Error("Invalid CE_SHUFFLEVEC record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 OpTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval]
+      VectorType *RTy = dyn_cast<VectorType>(CurTy);
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (Record.size() < 4 || RTy == 0 || OpTy == 0)
+        return Error("Invalid CE_SHUFVEC_EX record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 RTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_CMP: {     // CE_CMP: [opty, opval, opval, pred]
+      if (Record.size() < 4) return Error("Invalid CE_CMP record");
+      Type *OpTy = getTypeByID(Record[0]);
+      if (OpTy == 0) return Error("Invalid CE_CMP record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+
+      if (OpTy->isFPOrFPVectorTy())
+        V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
+      else
+        V = ConstantExpr::getICmp(Record[3], Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_INLINEASM: {
+      if (Record.size() < 2) return Error("Invalid INLINEASM record");
+      std::string AsmStr, ConstrStr;
+      bool HasSideEffects = Record[0] & 1;
+      bool IsAlignStack = Record[0] >> 1;
+      unsigned AsmStrSize = Record[1];
+      if (2+AsmStrSize >= Record.size())
+        return Error("Invalid INLINEASM record");
+      unsigned ConstStrSize = Record[2+AsmStrSize];
+      if (3+AsmStrSize+ConstStrSize > Record.size())
+        return Error("Invalid INLINEASM record");
+
+      for (unsigned i = 0; i != AsmStrSize; ++i)
+        AsmStr += (char)Record[2+i];
+      for (unsigned i = 0; i != ConstStrSize; ++i)
+        ConstrStr += (char)Record[3+AsmStrSize+i];
+      PointerType *PTy = cast<PointerType>(CurTy);
+      V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
+                         AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+      break;
+    }
+    case bitc::CST_CODE_BLOCKADDRESS:{
+      if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record");
+      Type *FnTy = getTypeByID(Record[0]);
+      if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record");
+      Function *Fn =
+        dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
+      if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record");
+
+      GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
+                                                  Type::getInt8Ty(Context),
+                                            false, GlobalValue::InternalLinkage,
+                                                  0, "");
+      BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
+      V = FwdRef;
+      break;
+    }
+    }
+
+    ValueList.AssignValue(V, NextCstNo);
+    ++NextCstNo;
+  }
+
+  if (NextCstNo != ValueList.size())
+    return Error("Invalid constant reference!");
+
+  if (Stream.ReadBlockEnd())
+    return Error("Error at end of constants block");
+
+  // Once all the constants have been read, go through and resolve forward
+  // references.
+  ValueList.ResolveConstantForwardRefs();
+  return false;
+}
+
+/// RememberAndSkipFunctionBody - When we see the block for a function body,
+/// remember where it is and then skip it.  This lets us lazily deserialize the
+/// functions.
+bool BitcodeReader::RememberAndSkipFunctionBody() {
+  // Get the function we are talking about.
+  if (FunctionsWithBodies.empty())
+    return Error("Insufficient function protos");
+
+  Function *Fn = FunctionsWithBodies.back();
+  FunctionsWithBodies.pop_back();
+
+  // Save the current stream state.
+  uint64_t CurBit = Stream.GetCurrentBitNo();
+  DeferredFunctionInfo[Fn] = CurBit;
+
+  // Skip over the function block for now.
+  if (Stream.SkipBlock())
+    return Error("Malformed block record");
+  return false;
+}
+
+bool BitcodeReader::ParseModule() {
+  if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+  std::vector<std::string> SectionTable;
+  std::vector<std::string> GCTable;
+
+  // Read all the records for this module.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of module block");
+
+      // Patch the initializers for globals and aliases up.
+      ResolveGlobalAndAliasInits();
+      if (!GlobalInits.empty() || !AliasInits.empty())
+        return Error("Malformed global initializer set");
+      if (!FunctionsWithBodies.empty())
+        return Error("Too few function bodies found");
+
+      // Look for intrinsic functions which need to be upgraded at some point
+      for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
+           FI != FE; ++FI) {
+        Function* NewFn;
+        if (UpgradeIntrinsicFunction(FI, NewFn))
+          UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn));
+      }
+
+      // Look for global variables which need to be renamed.
+      for (Module::global_iterator
+             GI = TheModule->global_begin(), GE = TheModule->global_end();
+           GI != GE; ++GI)
+        UpgradeGlobalVariable(GI);
+
+      // Force deallocation of memory for these vectors to favor the client that
+      // want lazy deserialization.
+      std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
+      std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+      std::vector<Function*>().swap(FunctionsWithBodies);
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Malformed block record");
+        break;
+      case bitc::BLOCKINFO_BLOCK_ID:
+        if (Stream.ReadBlockInfoBlock())
+          return Error("Malformed BlockInfoBlock");
+        break;
+      case bitc::PARAMATTR_BLOCK_ID:
+        if (ParseAttributeBlock())
+          return true;
+        break;
+      case bitc::TYPE_BLOCK_ID_NEW:
+        if (ParseTypeTable())
+          return true;
+        break;
+      case TYPE_BLOCK_ID_OLD_3_0:
+        if (ParseOldTypeTable())
+          return true;
+        break;
+      case TYPE_SYMTAB_BLOCK_ID_OLD_3_0:
+        if (ParseOldTypeSymbolTable())
+          return true;
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (ParseValueSymbolTable())
+          return true;
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (ParseConstants() || ResolveGlobalAndAliasInits())
+          return true;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (ParseMetadata())
+          return true;
+        break;
+      case bitc::FUNCTION_BLOCK_ID:
+        // If this is the first function body we've seen, reverse the
+        // FunctionsWithBodies list.
+        if (!HasReversedFunctionsWithBodies) {
+          std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
+          HasReversedFunctionsWithBodies = true;
+        }
+
+        if (RememberAndSkipFunctionBody())
+          return true;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    switch (Stream.ReadRecord(Code, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION:  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Malformed MODULE_CODE_VERSION");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Unknown bitstream version!");
+      break;
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_TRIPLE record");
+      TheModule->setTargetTriple(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DATALAYOUT: {  // DATALAYOUT: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_DATALAYOUT record");
+      TheModule->setDataLayout(S);
+      break;
+    }
+    case bitc::MODULE_CODE_ASM: {  // ASM: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_ASM record");
+      TheModule->setModuleInlineAsm(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DEPLIB: {  // DEPLIB: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_DEPLIB record");
+      TheModule->addLibrary(S);
+      break;
+    }
+    case bitc::MODULE_CODE_SECTIONNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_SECTIONNAME record");
+      SectionTable.push_back(S);
+      break;
+    }
+    case bitc::MODULE_CODE_GCNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_GCNAME record");
+      GCTable.push_back(S);
+      break;
+    }
+    // GLOBALVAR: [pointer type, isconst, initid,
+    //             linkage, alignment, section, visibility, threadlocal,
+    //             unnamed_addr]
+    case bitc::MODULE_CODE_GLOBALVAR: {
+      if (Record.size() < 6)
+        return Error("Invalid MODULE_CODE_GLOBALVAR record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty) return Error("Invalid MODULE_CODE_GLOBALVAR record");
+      if (!Ty->isPointerTy())
+        return Error("Global not a pointer type!");
+      unsigned AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
+      Ty = cast<PointerType>(Ty)->getElementType();
+
+      bool isConstant = Record[1];
+      GlobalValue::LinkageTypes Linkage = GetDecodedLinkage(Record[3]);
+      unsigned Alignment = (1 << Record[4]) >> 1;
+      std::string Section;
+      if (Record[5]) {
+        if (Record[5]-1 >= SectionTable.size())
+          return Error("Invalid section ID");
+        Section = SectionTable[Record[5]-1];
+      }
+      GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+      if (Record.size() > 6)
+        Visibility = GetDecodedVisibility(Record[6]);
+      bool isThreadLocal = false;
+      if (Record.size() > 7)
+        isThreadLocal = Record[7];
+
+      bool UnnamedAddr = false;
+      if (Record.size() > 8)
+        UnnamedAddr = Record[8];
+
+      GlobalVariable *NewGV =
+        new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0,
+                           isThreadLocal, AddressSpace);
+      NewGV->setAlignment(Alignment);
+      if (!Section.empty())
+        NewGV->setSection(Section);
+      NewGV->setVisibility(Visibility);
+      NewGV->setThreadLocal(isThreadLocal);
+      NewGV->setUnnamedAddr(UnnamedAddr);
+
+      ValueList.push_back(NewGV);
+
+      // Remember which value to use for the global initializer.
+      if (unsigned InitID = Record[2])
+        GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
+      break;
+    }
+    // FUNCTION:  [type, callingconv, isproto, linkage, paramattr,
+    //             alignment, section, visibility, gc, unnamed_addr]
+    case bitc::MODULE_CODE_FUNCTION: {
+      if (Record.size() < 8)
+        return Error("Invalid MODULE_CODE_FUNCTION record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record");
+      if (!Ty->isPointerTy())
+        return Error("Function not a pointer type!");
+      FunctionType *FTy =
+        dyn_cast<FunctionType>(cast<PointerType>(Ty)->getElementType());
+      if (!FTy)
+        return Error("Function not a pointer to function type!");
+
+      Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
+                                        "", TheModule);
+
+      Func->setCallingConv(static_cast<CallingConv::ID>(Record[1]));
+      bool isProto = Record[2];
+      Func->setLinkage(GetDecodedLinkage(Record[3]));
+      Func->setAttributes(getAttributes(Record[4]));
+
+      Func->setAlignment((1 << Record[5]) >> 1);
+      if (Record[6]) {
+        if (Record[6]-1 >= SectionTable.size())
+          return Error("Invalid section ID");
+        Func->setSection(SectionTable[Record[6]-1]);
+      }
+      Func->setVisibility(GetDecodedVisibility(Record[7]));
+      if (Record.size() > 8 && Record[8]) {
+        if (Record[8]-1 > GCTable.size())
+          return Error("Invalid GC ID");
+        Func->setGC(GCTable[Record[8]-1].c_str());
+      }
+      bool UnnamedAddr = false;
+      if (Record.size() > 9)
+        UnnamedAddr = Record[9];
+      Func->setUnnamedAddr(UnnamedAddr);
+      ValueList.push_back(Func);
+
+      // If this is a function with a body, remember the prototype we are
+      // creating now, so that we can match up the body with them later.
+      if (!isProto)
+        FunctionsWithBodies.push_back(Func);
+      break;
+    }
+    // ALIAS: [alias type, aliasee val#, linkage]
+    // ALIAS: [alias type, aliasee val#, linkage, visibility]
+    case bitc::MODULE_CODE_ALIAS: {
+      if (Record.size() < 3)
+        return Error("Invalid MODULE_ALIAS record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty) return Error("Invalid MODULE_ALIAS record");
+      if (!Ty->isPointerTy())
+        return Error("Function not a pointer type!");
+
+      GlobalAlias *NewGA = new GlobalAlias(Ty, GetDecodedLinkage(Record[2]),
+                                           "", 0, TheModule);
+      // Old bitcode files didn't have visibility field.
+      if (Record.size() > 3)
+        NewGA->setVisibility(GetDecodedVisibility(Record[3]));
+      ValueList.push_back(NewGA);
+      AliasInits.push_back(std::make_pair(NewGA, Record[1]));
+      break;
+    }
+    /// MODULE_CODE_PURGEVALS: [numvals]
+    case bitc::MODULE_CODE_PURGEVALS:
+      // Trim down the value list to the specified size.
+      if (Record.size() < 1 || Record[0] > ValueList.size())
+        return Error("Invalid MODULE_PURGEVALS record");
+      ValueList.shrinkTo(Record[0]);
+      break;
+    }
+    Record.clear();
+  }
+
+  return Error("Premature end of bitstream");
+}
+
+bool BitcodeReader::ParseBitcodeInto(Module *M) {
+  TheModule = 0;
+
+  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
+  unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
+
+  if (Buffer->getBufferSize() & 3) {
+    if (!isRawBitcode(BufPtr, BufEnd) && !isBitcodeWrapper(BufPtr, BufEnd))
+      return Error("Invalid bitcode signature");
+    else
+      return Error("Bitcode stream should be a multiple of 4 bytes in length");
+  }
+
+  // If we have a wrapper header, parse it and ignore the non-bc file contents.
+  // The magic number is 0x0B17C0DE stored in little endian.
+  if (isBitcodeWrapper(BufPtr, BufEnd))
+    if (SkipBitcodeWrapperHeader(BufPtr, BufEnd))
+      return Error("Invalid bitcode wrapper header");
+
+  StreamFile.init(BufPtr, BufEnd);
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code != bitc::ENTER_SUBBLOCK) {
+
+      // The ranlib in xcode 4 will align archive members by appending newlines
+      // to the end of them. If this file size is a multiple of 4 but not 8, we
+      // have to read and ignore these final 4 bytes :-(
+      if (Stream.GetAbbrevIDWidth() == 2 && Code == 2 &&
+          Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a &&
+	  Stream.AtEndOfStream())
+        return false;
+
+      return Error("Invalid record at top-level");
+    }
+
+    unsigned BlockID = Stream.ReadSubBlockID();
+
+    // We only know the MODULE subblock ID.
+    switch (BlockID) {
+    case bitc::BLOCKINFO_BLOCK_ID:
+      if (Stream.ReadBlockInfoBlock())
+        return Error("Malformed BlockInfoBlock");
+      break;
+    case bitc::MODULE_BLOCK_ID:
+      // Reject multiple MODULE_BLOCK's in a single bitstream.
+      if (TheModule)
+        return Error("Multiple MODULE_BLOCKs in same stream");
+      TheModule = M;
+      if (ParseModule())
+        return true;
+      break;
+    default:
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      break;
+    }
+  }
+
+  return false;
+}
+
+bool BitcodeReader::ParseModuleTriple(std::string &Triple) {
+  if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this module.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of module block");
+
+      return false;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Malformed block record");
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    switch (Stream.ReadRecord(Code, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION:  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Malformed MODULE_CODE_VERSION");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Unknown bitstream version!");
+      break;
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid MODULE_CODE_TRIPLE record");
+      Triple = S;
+      break;
+    }
+    }
+    Record.clear();
+  }
+
+  return Error("Premature end of bitstream");
+}
+
+bool BitcodeReader::ParseTriple(std::string &Triple) {
+  if (Buffer->getBufferSize() & 3)
+    return Error("Bitcode stream should be a multiple of 4 bytes in length");
+
+  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
+  unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
+
+  // If we have a wrapper header, parse it and ignore the non-bc file contents.
+  // The magic number is 0x0B17C0DE stored in little endian.
+  if (isBitcodeWrapper(BufPtr, BufEnd))
+    if (SkipBitcodeWrapperHeader(BufPtr, BufEnd))
+      return Error("Invalid bitcode wrapper header");
+
+  StreamFile.init(BufPtr, BufEnd);
+  Stream.init(StreamFile);
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+
+    if (Code != bitc::ENTER_SUBBLOCK)
+      return Error("Invalid record at top-level");
+
+    unsigned BlockID = Stream.ReadSubBlockID();
+
+    // We only know the MODULE subblock ID.
+    switch (BlockID) {
+    case bitc::MODULE_BLOCK_ID:
+      if (ParseModuleTriple(Triple))
+        return true;
+      break;
+    default:
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      break;
+    }
+  }
+
+  return false;
+}
+
+/// ParseMetadataAttachment - Parse metadata attachments.
+bool BitcodeReader::ParseMetadataAttachment() {
+  if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
+    return Error("Malformed block record");
+
+  SmallVector<uint64_t, 64> Record;
+  while(1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of PARAMATTR block");
+      break;
+    }
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+    // Read a metadata attachment record.
+    Record.clear();
+    switch (Stream.ReadRecord(Code, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::METADATA_ATTACHMENT: {
+      unsigned RecordLength = Record.size();
+      if (Record.empty() || (RecordLength - 1) % 2 == 1)
+        return Error ("Invalid METADATA_ATTACHMENT reader!");
+      Instruction *Inst = InstructionList[Record[0]];
+      for (unsigned i = 1; i != RecordLength; i = i+2) {
+        unsigned Kind = Record[i];
+        DenseMap<unsigned, unsigned>::iterator I =
+          MDKindMap.find(Kind);
+        if (I == MDKindMap.end())
+          return Error("Invalid metadata kind ID");
+        Value *Node = MDValueList.getValueFwdRef(Record[i+1]);
+        Inst->setMetadata(I->second, cast<MDNode>(Node));
+      }
+      break;
+    }
+    }
+  }
+  return false;
+}
+
+/// ParseFunctionBody - Lazily parse the specified function body block.
+bool BitcodeReader::ParseFunctionBody(Function *F) {
+  if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
+    return Error("Malformed block record");
+
+  InstructionList.clear();
+  unsigned ModuleValueListSize = ValueList.size();
+  unsigned ModuleMDValueListSize = MDValueList.size();
+
+  // Add all the function arguments to the value table.
+  for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
+    ValueList.push_back(I);
+
+  unsigned NextValueNo = ValueList.size();
+  BasicBlock *CurBB = 0;
+  unsigned CurBBNo = 0;
+
+  DebugLoc LastLoc;
+
+  // Read all the records.
+  SmallVector<uint64_t, 64> Record;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of function block");
+      break;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Malformed block record");
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (ParseConstants()) return true;
+        NextValueNo = ValueList.size();
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (ParseValueSymbolTable()) return true;
+        break;
+      case bitc::METADATA_ATTACHMENT_ID:
+        if (ParseMetadataAttachment()) return true;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (ParseMetadata()) return true;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Instruction *I = 0;
+    unsigned BitCode = Stream.ReadRecord(Code, Record);
+    switch (BitCode) {
+    default: // Default behavior: reject
+      return Error("Unknown instruction");
+    case bitc::FUNC_CODE_DECLAREBLOCKS:     // DECLAREBLOCKS: [nblocks]
+      if (Record.size() < 1 || Record[0] == 0)
+        return Error("Invalid DECLAREBLOCKS record");
+      // Create all the basic blocks for the function.
+      FunctionBBs.resize(Record[0]);
+      for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
+        FunctionBBs[i] = BasicBlock::Create(Context, "", F);
+      CurBB = FunctionBBs[0];
+      continue;
+
+    case bitc::FUNC_CODE_DEBUG_LOC_AGAIN:  // DEBUG_LOC_AGAIN
+      // This record indicates that the last instruction is at the same
+      // location as the previous instruction with a location.
+      I = 0;
+
+      // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+
+      if (I == 0) return Error("Invalid DEBUG_LOC_AGAIN record");
+      I->setDebugLoc(LastLoc);
+      I = 0;
+      continue;
+
+    case bitc::FUNC_CODE_DEBUG_LOC: {      // DEBUG_LOC: [line, col, scope, ia]
+      I = 0;     // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+      if (I == 0 || Record.size() < 4)
+        return Error("Invalid FUNC_CODE_DEBUG_LOC record");
+
+      unsigned Line = Record[0], Col = Record[1];
+      unsigned ScopeID = Record[2], IAID = Record[3];
+
+      MDNode *Scope = 0, *IA = 0;
+      if (ScopeID) Scope = cast<MDNode>(MDValueList.getValueFwdRef(ScopeID-1));
+      if (IAID)    IA = cast<MDNode>(MDValueList.getValueFwdRef(IAID-1));
+      LastLoc = DebugLoc::get(Line, Col, Scope, IA);
+      I->setDebugLoc(LastLoc);
+      I = 0;
+      continue;
+    }
+
+    case bitc::FUNC_CODE_INST_BINOP: {    // BINOP: [opval, ty, opval, opcode]
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 > Record.size())
+        return Error("Invalid BINOP record");
+
+      int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
+      if (Opc == -1) return Error("Invalid BINOP record");
+      I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
+      InstructionList.push_back(I);
+      if (OpNum < Record.size()) {
+        if (Opc == Instruction::Add ||
+            Opc == Instruction::Sub ||
+            Opc == Instruction::Mul ||
+            Opc == Instruction::Shl) {
+          if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
+          if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
+        } else if (Opc == Instruction::SDiv ||
+                   Opc == Instruction::UDiv ||
+                   Opc == Instruction::LShr ||
+                   Opc == Instruction::AShr) {
+          if (Record[OpNum] & (1 << bitc::PEO_EXACT))
+            cast<BinaryOperator>(I)->setIsExact(true);
+        }
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CAST: {    // CAST: [opval, opty, destty, castopc]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid CAST record");
+
+      Type *ResTy = getTypeByID(Record[OpNum]);
+      int Opc = GetDecodedCastOpcode(Record[OpNum+1]);
+      if (Opc == -1 || ResTy == 0)
+        return Error("Invalid CAST record");
+      I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INBOUNDS_GEP:
+    case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands]
+      unsigned OpNum = 0;
+      Value *BasePtr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
+        return Error("Invalid GEP record");
+
+      SmallVector<Value*, 16> GEPIdx;
+      while (OpNum != Record.size()) {
+        Value *Op;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid GEP record");
+        GEPIdx.push_back(Op);
+      }
+
+      I = GetElementPtrInst::Create(BasePtr, GEPIdx);
+      InstructionList.push_back(I);
+      if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP)
+        cast<GetElementPtrInst>(I)->setIsInBounds(true);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTVAL: {
+                                       // EXTRACTVAL: [opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid EXTRACTVAL record");
+
+      SmallVector<unsigned, 4> EXTRACTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid EXTRACTVAL index");
+        EXTRACTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTVAL: {
+                           // INSERTVAL: [opty, opval, opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid INSERTVAL record");
+      Value *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Val))
+        return Error("Invalid INSERTVAL record");
+
+      SmallVector<unsigned, 4> INSERTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid INSERTVAL index");
+        INSERTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = InsertValueInst::Create(Agg, Val, INSERTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
+      // obsolete form of select
+      // handles select i1 ... in old bitcode
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValue(Record, OpNum, Type::getInt1Ty(Context), Cond))
+        return Error("Invalid SELECT record");
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred]
+      // new form of select
+      // handles select i1 or select [N x i1]
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValueTypePair(Record, OpNum, NextValueNo, Cond))
+        return Error("Invalid SELECT record");
+
+      // select condition can be either i1 or [N x i1]
+      if (VectorType* vector_type =
+          dyn_cast<VectorType>(Cond->getType())) {
+        // expect <n x i1>
+        if (vector_type->getElementType() != Type::getInt1Ty(Context))
+          return Error("Invalid SELECT condition type");
+      } else {
+        // expect i1
+        if (Cond->getType() != Type::getInt1Ty(Context))
+          return Error("Invalid SELECT condition type");
+      }
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid EXTRACTELT record");
+      I = ExtractElementInst::Create(Vec, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Elt, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum,
+                   cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid INSERTELT record");
+      I = InsertElementInst::Create(Vec, Elt, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec1, *Vec2, *Mask;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
+          getValue(Record, OpNum, Vec1->getType(), Vec2))
+        return Error("Invalid SHUFFLEVEC record");
+
+      if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
+        return Error("Invalid SHUFFLEVEC record");
+      I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_CMP:   // CMP: [opty, opval, opval, pred]
+      // Old form of ICmp/FCmp returning bool
+      // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were
+      // both legal on vectors but had different behaviour.
+    case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred]
+      // FCmp/ICmp returning bool or vector of bool
+
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 != Record.size())
+        return Error("Invalid CMP record");
+
+      if (LHS->getType()->isFPOrFPVectorTy())
+        I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS);
+      else
+        I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
+      {
+        unsigned Size = Record.size();
+        if (Size == 0) {
+          I = ReturnInst::Create(Context);
+          InstructionList.push_back(I);
+          break;
+        }
+
+        unsigned OpNum = 0;
+        Value *Op = NULL;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid RET record");
+        if (OpNum != Record.size())
+          return Error("Invalid RET record");
+
+        I = ReturnInst::Create(Context, Op);
+        InstructionList.push_back(I);
+        break;
+      }
+    case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
+      if (Record.size() != 1 && Record.size() != 3)
+        return Error("Invalid BR record");
+      BasicBlock *TrueDest = getBasicBlock(Record[0]);
+      if (TrueDest == 0)
+        return Error("Invalid BR record");
+
+      if (Record.size() == 1) {
+        I = BranchInst::Create(TrueDest);
+        InstructionList.push_back(I);
+      }
+      else {
+        BasicBlock *FalseDest = getBasicBlock(Record[1]);
+        Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context));
+        if (FalseDest == 0 || Cond == 0)
+          return Error("Invalid BR record");
+        I = BranchInst::Create(TrueDest, FalseDest, Cond);
+        InstructionList.push_back(I);
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
+      if (Record.size() < 3 || (Record.size() & 1) == 0)
+        return Error("Invalid SWITCH record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Cond = getFnValueByID(Record[1], OpTy);
+      BasicBlock *Default = getBasicBlock(Record[2]);
+      if (OpTy == 0 || Cond == 0 || Default == 0)
+        return Error("Invalid SWITCH record");
+      unsigned NumCases = (Record.size()-3)/2;
+      SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
+      InstructionList.push_back(SI);
+      for (unsigned i = 0, e = NumCases; i != e; ++i) {
+        ConstantInt *CaseVal =
+          dyn_cast_or_null<ConstantInt>(getFnValueByID(Record[3+i*2], OpTy));
+        BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]);
+        if (CaseVal == 0 || DestBB == 0) {
+          delete SI;
+          return Error("Invalid SWITCH record!");
+        }
+        SI->addCase(CaseVal, DestBB);
+      }
+      I = SI;
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...]
+      if (Record.size() < 2)
+        return Error("Invalid INDIRECTBR record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Address = getFnValueByID(Record[1], OpTy);
+      if (OpTy == 0 || Address == 0)
+        return Error("Invalid INDIRECTBR record");
+      unsigned NumDests = Record.size()-2;
+      IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests);
+      InstructionList.push_back(IBI);
+      for (unsigned i = 0, e = NumDests; i != e; ++i) {
+        if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
+          IBI->addDestination(DestBB);
+        } else {
+          delete IBI;
+          return Error("Invalid INDIRECTBR record!");
+        }
+      }
+      I = IBI;
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INVOKE: {
+      // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
+      if (Record.size() < 4) return Error("Invalid INVOKE record");
+      AttrListPtr PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+      BasicBlock *NormalBB = getBasicBlock(Record[2]);
+      BasicBlock *UnwindBB = getBasicBlock(Record[3]);
+
+      unsigned OpNum = 4;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid INVOKE record");
+
+      PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = !CalleeTy ? 0 :
+        dyn_cast<FunctionType>(CalleeTy->getElementType());
+
+      // Check that the right number of fixed parameters are here.
+      if (FTy == 0 || NormalBB == 0 || UnwindBB == 0 ||
+          Record.size() < OpNum+FTy->getNumParams())
+        return Error("Invalid INVOKE record");
+
+      SmallVector<Value*, 16> Ops;
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (Ops.back() == 0) return Error("Invalid INVOKE record");
+      }
+
+      if (!FTy->isVarArg()) {
+        if (Record.size() != OpNum)
+          return Error("Invalid INVOKE record");
+      } else {
+        // Read type/value pairs for varargs params.
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid INVOKE record");
+          Ops.push_back(Op);
+        }
+      }
+
+      I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops);
+      InstructionList.push_back(I);
+      cast<InvokeInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo));
+      cast<InvokeInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
+      unsigned Idx = 0;
+      Value *Val = 0;
+      if (getValueTypePair(Record, Idx, NextValueNo, Val))
+        return Error("Invalid RESUME record");
+      I = ResumeInst::Create(Val);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_UNWIND: // UNWIND
+      I = new UnwindInst(Context);
+      InstructionList.push_back(I);
+      break;
+    case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
+      I = new UnreachableInst(Context);
+      InstructionList.push_back(I);
+      break;
+    case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
+      if (Record.size() < 1 || ((Record.size()-1)&1))
+        return Error("Invalid PHI record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty) return Error("Invalid PHI record");
+
+      PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
+      InstructionList.push_back(PN);
+
+      for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
+        Value *V = getFnValueByID(Record[1+i], Ty);
+        BasicBlock *BB = getBasicBlock(Record[2+i]);
+        if (!V || !BB) return Error("Invalid PHI record");
+        PN->addIncoming(V, BB);
+      }
+      I = PN;
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_LANDINGPAD: {
+      // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?]
+      unsigned Idx = 0;
+      if (Record.size() < 4)
+        return Error("Invalid LANDINGPAD record");
+      Type *Ty = getTypeByID(Record[Idx++]);
+      if (!Ty) return Error("Invalid LANDINGPAD record");
+      Value *PersFn = 0;
+      if (getValueTypePair(Record, Idx, NextValueNo, PersFn))
+        return Error("Invalid LANDINGPAD record");
+
+      bool IsCleanup = !!Record[Idx++];
+      unsigned NumClauses = Record[Idx++];
+      LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, NumClauses);
+      LP->setCleanup(IsCleanup);
+      for (unsigned J = 0; J != NumClauses; ++J) {
+        LandingPadInst::ClauseType CT =
+          LandingPadInst::ClauseType(Record[Idx++]); (void)CT;
+        Value *Val;
+
+        if (getValueTypePair(Record, Idx, NextValueNo, Val)) {
+          delete LP;
+          return Error("Invalid LANDINGPAD record");
+        }
+
+        assert((CT != LandingPadInst::Catch ||
+                !isa<ArrayType>(Val->getType())) &&
+               "Catch clause has a invalid type!");
+        assert((CT != LandingPadInst::Filter ||
+                isa<ArrayType>(Val->getType())) &&
+               "Filter clause has invalid type!");
+        LP->addClause(Val);
+      }
+
+      I = LP;
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align]
+      if (Record.size() != 4)
+        return Error("Invalid ALLOCA record");
+      PointerType *Ty =
+        dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
+      Type *OpTy = getTypeByID(Record[1]);
+      Value *Size = getFnValueByID(Record[2], OpTy);
+      unsigned Align = Record[3];
+      if (!Ty || !Size) return Error("Invalid ALLOCA record");
+      I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid LOAD record");
+
+      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_LOADATOMIC: {
+       // LOADATOMIC: [opty, op, align, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid LOADATOMIC record");
+
+
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Release ||
+          Ordering == AcquireRelease)
+        return Error("Invalid LOADATOMIC record");
+      if (Ordering != NotAtomic && Record[OpNum] == 0)
+        return Error("Invalid LOADATOMIC record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+
+      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+                       Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_STORE: { // STORE2:[ptrty, ptr, val, align, vol]
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid STORE record");
+
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_STOREATOMIC: {
+      // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid STOREATOMIC record");
+
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Acquire ||
+          Ordering == AcquireRelease)
+        return Error("Invalid STOREATOMIC record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+      if (Ordering != NotAtomic && Record[OpNum] == 0)
+        return Error("Invalid STOREATOMIC record");
+
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+                        Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CMPXCHG: {
+      // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Ptr, *Cmp, *New;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Cmp) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), New) ||
+          OpNum+3 != Record.size())
+        return Error("Invalid CMPXCHG record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]);
+      if (Ordering == NotAtomic || Ordering == Unordered)
+        return Error("Invalid CMPXCHG record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
+      I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope);
+      cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_ATOMICRMW: {
+      // ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Ptr, *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid ATOMICRMW record");
+      AtomicRMWInst::BinOp Operation = GetDecodedRMWOperation(Record[OpNum]);
+      if (Operation < AtomicRMWInst::FIRST_BINOP ||
+          Operation > AtomicRMWInst::LAST_BINOP)
+        return Error("Invalid ATOMICRMW record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Unordered)
+        return Error("Invalid ATOMICRMW record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+      I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
+      cast<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_FENCE: { // FENCE:[ordering, synchscope]
+      if (2 != Record.size())
+        return Error("Invalid FENCE record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[0]);
+      if (Ordering == NotAtomic || Ordering == Unordered ||
+          Ordering == Monotonic)
+        return Error("Invalid FENCE record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[1]);
+      I = new FenceInst(Context, Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CALL: {
+      // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
+      if (Record.size() < 3)
+        return Error("Invalid CALL record");
+
+      AttrListPtr PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+
+      unsigned OpNum = 2;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid CALL record");
+
+      PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = 0;
+      if (OpTy) FTy = dyn_cast<FunctionType>(OpTy->getElementType());
+      if (!FTy || Record.size() < FTy->getNumParams()+OpNum)
+        return Error("Invalid CALL record");
+
+      SmallVector<Value*, 16> Args;
+      // Read the fixed params.
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        if (FTy->getParamType(i)->isLabelTy())
+          Args.push_back(getBasicBlock(Record[OpNum]));
+        else
+          Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (Args.back() == 0) return Error("Invalid CALL record");
+      }
+
+      // Read type/value pairs for varargs params.
+      if (!FTy->isVarArg()) {
+        if (OpNum != Record.size())
+          return Error("Invalid CALL record");
+      } else {
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid CALL record");
+          Args.push_back(Op);
+        }
+      }
+
+      I = CallInst::Create(Callee, Args);
+      InstructionList.push_back(I);
+      cast<CallInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo>>1));
+      cast<CallInst>(I)->setTailCall(CCInfo & 1);
+      cast<CallInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
+      if (Record.size() < 3)
+        return Error("Invalid VAARG record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Op = getFnValueByID(Record[1], OpTy);
+      Type *ResTy = getTypeByID(Record[2]);
+      if (!OpTy || !Op || !ResTy)
+        return Error("Invalid VAARG record");
+      I = new VAArgInst(Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    }
+
+    // Add instruction to end of current BB.  If there is no current BB, reject
+    // this file.
+    if (CurBB == 0) {
+      delete I;
+      return Error("Invalid instruction with no BB");
+    }
+    CurBB->getInstList().push_back(I);
+
+    // If this was a terminator instruction, move to the next block.
+    if (isa<TerminatorInst>(I)) {
+      ++CurBBNo;
+      CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0;
+    }
+
+    // Non-void values get registered in the value table for future use.
+    if (I && !I->getType()->isVoidTy())
+      ValueList.AssignValue(I, NextValueNo++);
+  }
+
+  // Check the function list for unresolved values.
+  if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
+    if (A->getParent() == 0) {
+      // We found at least one unresolved value.  Nuke them all to avoid leaks.
+      for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
+        if ((A = dyn_cast<Argument>(ValueList[i])) && A->getParent() == 0) {
+          A->replaceAllUsesWith(UndefValue::get(A->getType()));
+          delete A;
+        }
+      }
+      return Error("Never resolved value found in function!");
+    }
+  }
+
+  // FIXME: Check for unresolved forward-declared metadata references
+  // and clean up leaks.
+
+  // See if anything took the address of blocks in this function.  If so,
+  // resolve them now.
+  DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
+    BlockAddrFwdRefs.find(F);
+  if (BAFRI != BlockAddrFwdRefs.end()) {
+    std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
+    for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
+      unsigned BlockIdx = RefList[i].first;
+      if (BlockIdx >= FunctionBBs.size())
+        return Error("Invalid blockaddress block #");
+
+      GlobalVariable *FwdRef = RefList[i].second;
+      FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
+      FwdRef->eraseFromParent();
+    }
+
+    BlockAddrFwdRefs.erase(BAFRI);
+  }
+
+  // Trim the value list down to the size it was before we parsed this function.
+  ValueList.shrinkTo(ModuleValueListSize);
+  MDValueList.shrinkTo(ModuleMDValueListSize);
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// GVMaterializer implementation
+//===----------------------------------------------------------------------===//
+
+
+bool BitcodeReader::isMaterializable(const GlobalValue *GV) const {
+  if (const Function *F = dyn_cast<Function>(GV)) {
+    return F->isDeclaration() &&
+      DeferredFunctionInfo.count(const_cast<Function*>(F));
+  }
+  return false;
+}
+
+bool BitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) {
+  Function *F = dyn_cast<Function>(GV);
+  // If it's not a function or is already material, ignore the request.
+  if (!F || !F->isMaterializable()) return false;
+
+  DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
+  assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
+
+  // Move the bit stream to the saved position of the deferred function body.
+  Stream.JumpToBit(DFII->second);
+
+  if (ParseFunctionBody(F)) {
+    if (ErrInfo) *ErrInfo = ErrorString;
+    return true;
+  }
+
+  // Upgrade any old intrinsic calls in the function.
+  for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
+       E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (Value::use_iterator UI = I->first->use_begin(),
+           UE = I->first->use_end(); UI != UE; ) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+    }
+  }
+
+  return false;
+}
+
+bool BitcodeReader::isDematerializable(const GlobalValue *GV) const {
+  const Function *F = dyn_cast<Function>(GV);
+  if (!F || F->isDeclaration())
+    return false;
+  return DeferredFunctionInfo.count(const_cast<Function*>(F));
+}
+
+void BitcodeReader::Dematerialize(GlobalValue *GV) {
+  Function *F = dyn_cast<Function>(GV);
+  // If this function isn't dematerializable, this is a noop.
+  if (!F || !isDematerializable(F))
+    return;
+
+  assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
+
+  // Just forget the function body, we can remat it later.
+  F->deleteBody();
+}
+
+
+bool BitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) {
+  assert(M == TheModule &&
+         "Can only Materialize the Module this BitcodeReader is attached to.");
+  // Iterate over the module, deserializing any functions that are still on
+  // disk.
+  for (Module::iterator F = TheModule->begin(), E = TheModule->end();
+       F != E; ++F)
+    if (F->isMaterializable() &&
+        Materialize(F, ErrInfo))
+      return true;
+
+  // Upgrade any intrinsic calls that slipped through (should not happen!) and
+  // delete the old functions to clean up. We can't do this unless the entire
+  // module is materialized because there could always be another function body
+  // with calls to the old function.
+  for (std::vector<std::pair<Function*, Function*> >::iterator I =
+       UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (Value::use_iterator UI = I->first->use_begin(),
+           UE = I->first->use_end(); UI != UE; ) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+      if (!I->first->use_empty())
+        I->first->replaceAllUsesWith(I->second);
+      I->first->eraseFromParent();
+    }
+  }
+  std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
+
+  // Upgrade to new EH scheme. N.B. This will go away in 3.1.
+  UpgradeExceptionHandling(M);
+
+  // Check debug info intrinsics.
+  CheckDebugInfoIntrinsics(TheModule);
+
+  return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// External interface
+//===----------------------------------------------------------------------===//
+
+/// getLazyBitcodeModule - lazy function-at-a-time loading from a file.
+///
+Module *llvm_3_0::getLazyBitcodeModule(MemoryBuffer *Buffer,
+                                       LLVMContext& Context,
+                                       std::string *ErrMsg) {
+  Module *M = new Module(Buffer->getBufferIdentifier(), Context);
+  BitcodeReader *R = new BitcodeReader(Buffer, Context);
+  M->setMaterializer(R);
+  if (R->ParseBitcodeInto(M)) {
+    if (ErrMsg)
+      *ErrMsg = R->getErrorString();
+
+    delete M;  // Also deletes R.
+    return 0;
+  }
+  // Have the BitcodeReader dtor delete 'Buffer'.
+  R->setBufferOwned(true);
+  return M;
+}
+
+/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
+/// If an error occurs, return null and fill in *ErrMsg if non-null.
+Module *llvm_3_0::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
+                                   std::string *ErrMsg){
+  Module *M = llvm_3_0::getLazyBitcodeModule(Buffer, Context, ErrMsg);
+  if (!M) return 0;
+
+  // Don't let the BitcodeReader dtor delete 'Buffer', regardless of whether
+  // there was an error.
+  static_cast<BitcodeReader*>(M->getMaterializer())->setBufferOwned(false);
+
+  // Read in the entire module, and destroy the BitcodeReader.
+  if (M->MaterializeAllPermanently(ErrMsg)) {
+    delete M;
+    return 0;
+  }
+
+  return M;
+}
+
+std::string llvm_3_0::getBitcodeTargetTriple(MemoryBuffer *Buffer,
+                                             LLVMContext& Context,
+                                             std::string *ErrMsg) {
+  BitcodeReader *R = new BitcodeReader(Buffer, Context);
+  // Don't let the BitcodeReader dtor delete 'Buffer'.
+  R->setBufferOwned(false);
+
+  std::string Triple("");
+  if (R->ParseTriple(Triple))
+    if (ErrMsg)
+      *ErrMsg = R->getErrorString();
+
+  delete R;
+  return Triple;
+}
diff --git a/bcinfo/BitReader_3_0/BitcodeReader.h b/bcinfo/BitReader_3_0/BitcodeReader.h
new file mode 100644
index 0000000..7dcd331
--- /dev/null
+++ b/bcinfo/BitReader_3_0/BitcodeReader.h
@@ -0,0 +1,283 @@
+//===- BitcodeReader.h - Internal BitcodeReader impl ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BITCODE_READER_H
+#define BITCODE_READER_H
+
+#include "llvm/GVMaterializer.h"
+#include "llvm/Attributes.h"
+#include "llvm/Type.h"
+#include "llvm/OperandTraits.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Support/ValueHandle.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+
+namespace llvm {
+  class MemoryBuffer;
+  class LLVMContext;
+}
+
+namespace llvm_3_0 {
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderValueList {
+  std::vector<WeakVH> ValuePtrs;
+
+  /// ResolveConstants - As we resolve forward-referenced constants, we add
+  /// information about them to this vector.  This allows us to resolve them in
+  /// bulk instead of resolving each reference at a time.  See the code in
+  /// ResolveConstantForwardRefs for more information about this.
+  ///
+  /// The key of this vector is the placeholder constant, the value is the slot
+  /// number that holds the resolved value.
+  typedef std::vector<std::pair<Constant*, unsigned> > ResolveConstantsTy;
+  ResolveConstantsTy ResolveConstants;
+  LLVMContext &Context;
+public:
+  BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
+  ~BitcodeReaderValueList() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+  }
+
+  // vector compatibility methods
+  unsigned size() const { return ValuePtrs.size(); }
+  void resize(unsigned N) { ValuePtrs.resize(N); }
+  void push_back(Value *V) {
+    ValuePtrs.push_back(V);
+  }
+
+  void clear() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+    ValuePtrs.clear();
+  }
+
+  Value *operator[](unsigned i) const {
+    assert(i < ValuePtrs.size());
+    return ValuePtrs[i];
+  }
+
+  Value *back() const { return ValuePtrs.back(); }
+    void pop_back() { ValuePtrs.pop_back(); }
+  bool empty() const { return ValuePtrs.empty(); }
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    ValuePtrs.resize(N);
+  }
+
+  Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
+  Value *getValueFwdRef(unsigned Idx, Type *Ty);
+
+  void AssignValue(Value *V, unsigned Idx);
+
+  /// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+  /// resolves any forward references.
+  void ResolveConstantForwardRefs();
+};
+
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderMDValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderMDValueList {
+  std::vector<WeakVH> MDValuePtrs;
+
+  LLVMContext &Context;
+public:
+  BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {}
+
+  // vector compatibility methods
+  unsigned size() const       { return MDValuePtrs.size(); }
+  void resize(unsigned N)     { MDValuePtrs.resize(N); }
+  void push_back(Value *V)    { MDValuePtrs.push_back(V);  }
+  void clear()                { MDValuePtrs.clear();  }
+  Value *back() const         { return MDValuePtrs.back(); }
+  void pop_back()             { MDValuePtrs.pop_back(); }
+  bool empty() const          { return MDValuePtrs.empty(); }
+
+  Value *operator[](unsigned i) const {
+    assert(i < MDValuePtrs.size());
+    return MDValuePtrs[i];
+  }
+
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    MDValuePtrs.resize(N);
+  }
+
+  Value *getValueFwdRef(unsigned Idx);
+  void AssignValue(Value *V, unsigned Idx);
+};
+
+class BitcodeReader : public GVMaterializer {
+  LLVMContext &Context;
+  Module *TheModule;
+  MemoryBuffer *Buffer;
+  bool BufferOwned;
+  BitstreamReader StreamFile;
+  BitstreamCursor Stream;
+
+  const char *ErrorString;
+
+  std::vector<Type*> TypeList;
+  BitcodeReaderValueList ValueList;
+  BitcodeReaderMDValueList MDValueList;
+  SmallVector<Instruction *, 64> InstructionList;
+
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
+
+  /// MAttributes - The set of attributes by index.  Index zero in the
+  /// file is for null, and is thus not represented here.  As such all indices
+  /// are off by one.
+  std::vector<AttrListPtr> MAttributes;
+
+  /// FunctionBBs - While parsing a function body, this is a list of the basic
+  /// blocks for the function.
+  std::vector<BasicBlock*> FunctionBBs;
+
+  // When reading the module header, this list is populated with functions that
+  // have bodies later in the file.
+  std::vector<Function*> FunctionsWithBodies;
+
+  // When intrinsic functions are encountered which require upgrading they are
+  // stored here with their replacement function.
+  typedef std::vector<std::pair<Function*, Function*> > UpgradedIntrinsicMap;
+  UpgradedIntrinsicMap UpgradedIntrinsics;
+
+  // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
+  DenseMap<unsigned, unsigned> MDKindMap;
+
+  // After the module header has been read, the FunctionsWithBodies list is
+  // reversed.  This keeps track of whether we've done this yet.
+  bool HasReversedFunctionsWithBodies;
+
+  /// DeferredFunctionInfo - When function bodies are initially scanned, this
+  /// map contains info about where to find deferred function body in the
+  /// stream.
+  DenseMap<Function*, uint64_t> DeferredFunctionInfo;
+
+  /// BlockAddrFwdRefs - These are blockaddr references to basic blocks.  These
+  /// are resolved lazily when functions are loaded.
+  typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
+  DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+
+public:
+  explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
+    : Context(C), TheModule(0), Buffer(buffer), BufferOwned(false),
+      ErrorString(0), ValueList(C), MDValueList(C) {
+    HasReversedFunctionsWithBodies = false;
+  }
+  ~BitcodeReader() {
+    FreeState();
+  }
+
+  void FreeState();
+
+  /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer
+  /// when the reader is destroyed.
+  void setBufferOwned(bool Owned) { BufferOwned = Owned; }
+
+  virtual bool isMaterializable(const GlobalValue *GV) const;
+  virtual bool isDematerializable(const GlobalValue *GV) const;
+  virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0);
+  virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0);
+  virtual void Dematerialize(GlobalValue *GV);
+
+  bool Error(const char *Str) {
+    ErrorString = Str;
+    return true;
+  }
+  const char *getErrorString() const { return ErrorString; }
+
+  /// @brief Main interface to parsing a bitcode buffer.
+  /// @returns true if an error occurred.
+  bool ParseBitcodeInto(Module *M);
+
+  /// @brief Cheap mechanism to just extract module triple
+  /// @returns true if an error occurred.
+  bool ParseTriple(std::string &Triple);
+private:
+  Type *getTypeByID(unsigned ID);
+  Type *getTypeByIDOrNull(unsigned ID);
+  Value *getFnValueByID(unsigned ID, Type *Ty) {
+    if (Ty && Ty->isMetadataTy())
+      return MDValueList.getValueFwdRef(ID);
+    return ValueList.getValueFwdRef(ID, Ty);
+  }
+  BasicBlock *getBasicBlock(unsigned ID) const {
+    if (ID >= FunctionBBs.size()) return 0; // Invalid ID
+    return FunctionBBs[ID];
+  }
+  AttrListPtr getAttributes(unsigned i) const {
+    if (i-1 < MAttributes.size())
+      return MAttributes[i-1];
+    return AttrListPtr();
+  }
+
+  /// getValueTypePair - Read a value/type pair out of the specified record from
+  /// slot 'Slot'.  Increment Slot past the number of slots used in the record.
+  /// Return true on failure.
+  bool getValueTypePair(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+                        unsigned InstNum, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    if (ValNo < InstNum) {
+      // If this is not a forward reference, just return the value we already
+      // have.
+      ResVal = getFnValueByID(ValNo, 0);
+      return ResVal == 0;
+    } else if (Slot == Record.size()) {
+      return true;
+    }
+
+    unsigned TypeNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+    return ResVal == 0;
+  }
+  bool getValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+                Type *Ty, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, Ty);
+    return ResVal == 0;
+  }
+
+
+  bool ParseModule();
+  bool ParseAttributeBlock();
+  bool ParseTypeTable();
+  bool ParseOldTypeTable();         // FIXME: Remove in LLVM 3.1
+  bool ParseTypeTableBody();
+
+  bool ParseOldTypeSymbolTable();   // FIXME: Remove in LLVM 3.1
+  bool ParseValueSymbolTable();
+  bool ParseConstants();
+  bool RememberAndSkipFunctionBody();
+  bool ParseFunctionBody(Function *F);
+  bool ResolveGlobalAndAliasInits();
+  bool ParseMetadata();
+  bool ParseMetadataAttachment();
+  bool ParseModuleTriple(std::string &Triple);
+};
+
+} // End llvm_3_0 namespace
+
+#endif
diff --git a/bcinfo/BitReader_3_0/CMakeLists.txt b/bcinfo/BitReader_3_0/CMakeLists.txt
new file mode 100644
index 0000000..37bebc4
--- /dev/null
+++ b/bcinfo/BitReader_3_0/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_llvm_library(LLVMBitReader
+  BitReader.cpp
+  BitcodeReader.cpp
+  )
+
+add_llvm_library_dependencies(LLVMBitReader
+  LLVMCore
+  LLVMSupport
+  )
diff --git a/bcinfo/BitReader_3_0/LLVMBuild.txt b/bcinfo/BitReader_3_0/LLVMBuild.txt
new file mode 100644
index 0000000..948b335
--- /dev/null
+++ b/bcinfo/BitReader_3_0/LLVMBuild.txt
@@ -0,0 +1,23 @@
+;===- ./lib/Bitcode/Reader/LLVMBuild.txt -----------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = BitReader
+parent = Bitcode
+required_libraries = Core Support
+
diff --git a/bcinfo/BitReader_3_0/Makefile b/bcinfo/BitReader_3_0/Makefile
new file mode 100644
index 0000000..59af8d5
--- /dev/null
+++ b/bcinfo/BitReader_3_0/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMBitReader
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/bcinfo/BitcodeTranslator.cpp b/bcinfo/BitcodeTranslator.cpp
index 8756dfa..ba22e1f 100644
--- a/bcinfo/BitcodeTranslator.cpp
+++ b/bcinfo/BitcodeTranslator.cpp
@@ -17,6 +17,7 @@
 #include "bcinfo/BitcodeTranslator.h"
 
 #include "BitReader_2_7/BitReader_2_7.h"
+#include "BitReader_3_0/BitReader_3_0.h"
 
 #define LOG_TAG "bcinfo"
 #include <cutils/log.h>
@@ -36,10 +37,17 @@
  * Define minimum and maximum target API versions. These correspond to the
  * same API levels used by the standard Android SDK.
  *
- * 11 - Honeycomb
- * 12 - Honeycomb MR1
- * 13 - Honeycomb MR2
- * 14 - Ice Cream Sandwich
+ * LLVM 2.7
+ *  11 - Honeycomb
+ *  12 - Honeycomb MR1
+ *  13 - Honeycomb MR2
+ *
+ * LLVM 3.0
+ *  14 - Ice Cream Sandwich
+ *  15 - Ice Cream Sandwich MR1
+ *
+ * LLVM 3.1
+ *  16 - Ice Cream Sandwich MR2
  */
 static const unsigned int kMinimumAPIVersion = 11;
 static const unsigned int kMaximumAPIVersion = BCINFO_API_VERSION;
@@ -49,7 +57,9 @@
  * The minimum version which does not require translation (i.e. is already
  * compatible with LLVM's default bitcode reader).
  */
-static const unsigned int kMinimumUntranslatedVersion = 14;
+static const unsigned int kMinimumUntranslatedVersion = 16;
+static const unsigned int kMinimumCompatibleVersion_LLVM_3_0 = 14;
+static const unsigned int kMinimumCompatibleVersion_LLVM_2_7 = 11;
 
 
 BitcodeTranslator::BitcodeTranslator(const char *bitcode, size_t bitcodeSize,
@@ -73,14 +83,14 @@
 
 bool BitcodeTranslator::translate() {
   if (!mBitcode || !mBitcodeSize) {
-    LOGE("Invalid/empty bitcode");
+    ALOGE("Invalid/empty bitcode");
     return false;
   }
 
   if ((mVersion != kCurrentAPIVersion) &&
       ((mVersion < kMinimumAPIVersion) ||
        (mVersion > kMaximumAPIVersion))) {
-    LOGE("Invalid API version: %u is out of range ('%u' - '%u')", mVersion,
+    ALOGE("Invalid API version: %u is out of range ('%u' - '%u')", mVersion,
          kMinimumAPIVersion, kMaximumAPIVersion);
     return false;
   }
@@ -102,11 +112,20 @@
   std::string error;
 
   // Module ownership is handled by the context, so we don't need to free it.
-  llvm::Module *module =
-      llvm_2_7::ParseBitcodeFile(MEM.get(), *mContext, &error);
+  llvm::Module *module = NULL;
+
+  if (mVersion >= kMinimumCompatibleVersion_LLVM_3_0) {
+    module = llvm_3_0::ParseBitcodeFile(MEM.get(), *mContext, &error);
+  } else if (mVersion >= kMinimumCompatibleVersion_LLVM_2_7) {
+    module = llvm_2_7::ParseBitcodeFile(MEM.get(), *mContext, &error);
+  } else {
+    ALOGE("No compatible bitcode reader for API version %d", mVersion);
+    return false;
+  }
+
   if (!module) {
-    LOGE("Could not parse bitcode file");
-    LOGE("%s", error.c_str());
+    ALOGE("Could not parse bitcode file");
+    ALOGE("%s", error.c_str());
     return false;
   }
 
diff --git a/bcinfo/BitcodeWrapper.cpp b/bcinfo/BitcodeWrapper.cpp
index bf7e75b..c6f9c04 100644
--- a/bcinfo/BitcodeWrapper.cpp
+++ b/bcinfo/BitcodeWrapper.cpp
@@ -40,14 +40,14 @@
 
 bool BitcodeWrapper::unwrap() {
   if (!mBitcode || !mBitcodeSize) {
-    LOGE("Invalid/empty bitcode");
+    ALOGE("Invalid/empty bitcode");
     return false;
   }
 
   if (llvm::isBitcodeWrapper((const unsigned char*) mBitcode,
                              (const unsigned char*) mBitcodeEnd)) {
     if (mBitcodeSize < sizeof(mBCHeader)) {
-      LOGE("Invalid bitcode size");
+      ALOGE("Invalid bitcode size");
       return false;
     }
 
@@ -59,7 +59,7 @@
     mFileType = BC_RAW;
     return true;
   } else {
-    LOGE("Not bitcode");
+    ALOGE("Not bitcode");
     mFileType = BC_NOT_BC;
     return false;
   }
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index dadca08..5927f22 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2011-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,6 +42,11 @@
 // synced with slang_rs_metadata.h)
 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
 
+// Name of metadata node where exported ForEach name information resides
+// (should be synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportForEachNameMetadataName =
+    "#rs_export_foreach_name";
+
 // Name of metadata node where exported ForEach signature information resides
 // (should be synced with slang_rs_metadata.h)
 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
@@ -58,26 +63,33 @@
 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
     : mBitcode(bitcode), mBitcodeSize(bitcodeSize), mExportVarCount(0),
       mExportFuncCount(0), mExportForEachSignatureCount(0),
-      mExportForEachSignatureList(NULL), mPragmaCount(0), mPragmaKeyList(NULL),
-      mPragmaValueList(NULL), mObjectSlotCount(0), mObjectSlotList(NULL),
-      mOptimizationLevel(3) {
+      mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
+      mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
+      mObjectSlotCount(0), mObjectSlotList(NULL), mOptimizationLevel(3) {
 }
 
 
 MetadataExtractor::~MetadataExtractor() {
+  if (mExportForEachNameList) {
+    for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
+        delete [] mExportForEachNameList[i];
+        mExportForEachNameList[i] = NULL;
+    }
+  }
+  delete [] mExportForEachNameList;
+  mExportForEachNameList = NULL;
+
   delete [] mExportForEachSignatureList;
   mExportForEachSignatureList = NULL;
 
-  if (mPragmaCount > 0) {
-    for (size_t i = 0; i < mPragmaCount; i++) {
-      if (mPragmaKeyList) {
-        delete [] mPragmaKeyList[i];
-        mPragmaKeyList[i] = NULL;
-      }
-      if (mPragmaValueList) {
-        delete [] mPragmaValueList[i];
-        mPragmaValueList[i] = NULL;
-      }
+  for (size_t i = 0; i < mPragmaCount; i++) {
+    if (mPragmaKeyList) {
+      delete [] mPragmaKeyList[i];
+      mPragmaKeyList[i] = NULL;
+    }
+    if (mPragmaValueList) {
+      delete [] mPragmaValueList[i];
+      mPragmaValueList[i] = NULL;
     }
   }
   delete [] mPragmaKeyList;
@@ -116,7 +128,7 @@
             static_cast<llvm::MDString*>(SlotMDS)->getString();
         uint32_t USlot = 0;
         if (Slot.getAsInteger(10, USlot)) {
-          LOGE("Non-integer object slot value '%s'", Slot.str().c_str());
+          ALOGE("Non-integer object slot value '%s'", Slot.str().c_str());
           return false;
         }
         TmpSlotList[i] = USlot;
@@ -174,19 +186,25 @@
 
 
 bool MetadataExtractor::populateForEachMetadata(
-    const llvm::NamedMDNode *ExportForEachMetadata) {
-  if (!ExportForEachMetadata) {
+    const llvm::NamedMDNode *Names,
+    const llvm::NamedMDNode *Signatures) {
+  if (!Names || !Signatures) {
     // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
     // section for ForEach. We generate a full signature for a "root" function
     // which means that we need to set the bottom 5 bits in the mask.
     mExportForEachSignatureCount = 1;
+    char **TmpNameList = new char*[mExportForEachSignatureCount];
+    TmpNameList[0] = new char[5];
+    strncpy(TmpNameList[0], "root", 5);
+
     uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
     TmpSigList[0] = 0x1f;
+    mExportForEachNameList = (const char**)TmpNameList;
     mExportForEachSignatureList = TmpSigList;
     return true;
   }
 
-  mExportForEachSignatureCount = ExportForEachMetadata->getNumOperands();
+  mExportForEachSignatureCount = Signatures->getNumOperands();
   if (!mExportForEachSignatureCount) {
     return true;
   }
@@ -194,7 +212,7 @@
   uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
 
   for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
-    llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(i);
+    llvm::MDNode *SigNode = Signatures->getOperand(i);
     if (SigNode != NULL && SigNode->getNumOperands() == 1) {
       llvm::Value *SigVal = SigNode->getOperand(0);
       if (SigVal->getValueID() == llvm::Value::MDStringVal) {
@@ -202,7 +220,7 @@
             static_cast<llvm::MDString*>(SigVal)->getString();
         uint32_t Signature = 0;
         if (SigString.getAsInteger(10, Signature)) {
-          LOGE("Non-integer signature value '%s'", SigString.str().c_str());
+          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
           return false;
         }
         TmpSigList[i] = Signature;
@@ -212,6 +230,16 @@
 
   mExportForEachSignatureList = TmpSigList;
 
+
+  mExportForEachNameList = new const char*[mExportForEachSignatureCount];
+
+  for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
+    llvm::MDNode *Name = Names->getOperand(i);
+    if (Name != NULL && Name->getNumOperands() == 1) {
+      mExportForEachNameList[i] = createStringFromValue(Name->getOperand(0));
+    }
+  }
+
   return true;
 }
 
@@ -219,7 +247,7 @@
 
 bool MetadataExtractor::extract() {
   if (!mBitcode || !mBitcodeSize) {
-    LOGE("Invalid/empty bitcode");
+    ALOGE("Invalid/empty bitcode");
     return false;
   }
 
@@ -232,8 +260,8 @@
   // Module ownership is handled by the context, so we don't need to free it.
   llvm::Module *module = llvm::ParseBitcodeFile(MEM.get(), *mContext, &error);
   if (!module) {
-    LOGE("Could not parse bitcode file");
-    LOGE("%s", error.c_str());
+    ALOGE("Could not parse bitcode file");
+    ALOGE("%s", error.c_str());
     return false;
   }
 
@@ -241,6 +269,8 @@
       module->getNamedMetadata(ExportVarMetadataName);
   const llvm::NamedMDNode *ExportFuncMetadata =
       module->getNamedMetadata(ExportFuncMetadataName);
+  const llvm::NamedMDNode *ExportForEachNameMetadata =
+      module->getNamedMetadata(ExportForEachNameMetadataName);
   const llvm::NamedMDNode *ExportForEachMetadata =
       module->getNamedMetadata(ExportForEachMetadataName);
   const llvm::NamedMDNode *PragmaMetadata =
@@ -259,15 +289,16 @@
     mExportFuncCount = ExportFuncMetadata->getNumOperands();
   }
 
-  if (!populateForEachMetadata(ExportForEachMetadata)) {
-    LOGE("Could not populate ForEach signature metadata");
+  if (!populateForEachMetadata(ExportForEachNameMetadata,
+                               ExportForEachMetadata)) {
+    ALOGE("Could not populate ForEach signature metadata");
     return false;
   }
 
   populatePragmaMetadata(PragmaMetadata);
 
   if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
-    LOGE("Could not populate object slot metadata");
+    ALOGE("Could not populate object slot metadata");
     return false;
   }
 
diff --git a/bcinfo/tools/Android.mk b/bcinfo/tools/Android.mk
index 08b9ad7..0d99f71 100644
--- a/bcinfo/tools/Android.mk
+++ b/bcinfo/tools/Android.mk
@@ -28,6 +28,8 @@
 LOCAL_SHARED_LIBRARIES := \
   libbcinfo
 
+LOCAL_CFLAGS += -D__HOST__
+
 LOCAL_C_INCLUDES := \
   $(LOCAL_PATH)/../../include
 
diff --git a/bcinfo/tools/main.cpp b/bcinfo/tools/main.cpp
index 09b7992..daeea7d 100644
--- a/bcinfo/tools/main.cpp
+++ b/bcinfo/tools/main.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2011-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  */
 
 #include <bcinfo/BitcodeTranslator.h>
+#include <bcinfo/BitcodeWrapper.h>
 #include <bcinfo/MetadataExtractor.h>
 
 #include <ctype.h>
@@ -42,7 +43,7 @@
 extern int opterr;
 extern int optind;
 
-bool translate = false;
+bool translateFlag = false;
 
 static int parseOption(int argc, char** argv) {
   int c;
@@ -55,7 +56,7 @@
         break;
 
       case 't':
-        translate = true;
+        translateFlag = true;
         break;
 
       default:
@@ -85,9 +86,11 @@
 
   printf("exportForEachSignatureCount: %u\n",
          ME->getExportForEachSignatureCount());
+  const char **nameList = ME->getExportForEachNameList();
   const uint32_t *sigList = ME->getExportForEachSignatureList();
   for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
-    printf("exportForEachSignatureList[%u]: %u\n", i, sigList[i]);
+    printf("exportForEachSignatureList[%u]: %s - %u\n", i, nameList[i],
+           sigList[i]);
   }
 
   printf("pragmaCount: %u\n", ME->getPragmaCount());
@@ -164,17 +167,28 @@
   const char *translatedBitcode = NULL;
   size_t bitcodeSize = readBitcode(&bitcode);
 
-  unsigned int version = 14;
+  unsigned int version = 0;
 
-  if (translate) {
+  bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize);
+  if (!bcWrapper.unwrap()) {
+    fprintf(stderr, "failed to unwrap bitcode wrapper\n");
+    return 2;
+  }
+
+  if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
+    version = bcWrapper.getTargetAPI();
+    printf("Found bitcodeWrapper\n");
+  } else if (translateFlag) {
     version = 12;
   }
 
+  printf("bitcodeVersion: %u\n", version);
+
   bcinfo::BitcodeTranslator *BT =
       new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version);
   if (!BT->translate()) {
     fprintf(stderr, "failed to translate bitcode\n");
-    return 2;
+    return 3;
   }
 
   bcinfo::MetadataExtractor *ME =
@@ -182,7 +196,7 @@
                                     BT->getTranslatedBitcodeSize());
   if (!ME->extract()) {
     fprintf(stderr, "failed to get metadata\n");
-    return 3;
+    return 4;
   }
 
   dumpMetadata(ME);
diff --git a/helper/Android.mk b/helper/Android.mk
index b19c131..ecba95f 100644
--- a/helper/Android.mk
+++ b/helper/Android.mk
@@ -52,6 +52,8 @@
 LOCAL_IS_HOST_MODULE := true
 
 LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
+
 LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := \
diff --git a/helper/DebugHelper.c b/helper/DebugHelper.c
index 87f0102..5c01b1b 100644
--- a/helper/DebugHelper.c
+++ b/helper/DebugHelper.c
@@ -24,6 +24,6 @@
     tag = "";
   }
 
-  return fprintf(stderr, "[%s] %s", tag, msg);
+  return fprintf(stderr, "[%s] %s\n", tag, msg);
 }
 #endif // USE_LOGGER && !defined(__arm__)
diff --git a/helper/DebugHelper.h b/helper/DebugHelper.h
index 475ed2e..ae68e3a 100644
--- a/helper/DebugHelper.h
+++ b/helper/DebugHelper.h
@@ -26,18 +26,18 @@
 
 #else // !USE_LOGGER
 
-#undef LOGV
-#undef LOGI
-#undef LOGD
-#undef LOGW
-#undef LOGE
+#undef ALOGV
+#undef ALOGI
+#undef ALOGD
+#undef ALOGW
+#undef ALOGE
 #undef LOGA
 
-#define LOGV(...)
-#define LOGI(...)
-#define LOGD(...)
-#define LOGW(...)
-#define LOGE(...)
+#define ALOGV(...)
+#define ALOGI(...)
+#define ALOGD(...)
+#define ALOGW(...)
+#define ALOGE(...)
 #define LOGA(...)
 
 #endif
@@ -57,11 +57,11 @@
 
   public:
     FuncLogger(char const *name) : mFuncName(name) {
-      LOGD("---> BEGIN: libbcc [ %s ]\n", name);
+      ALOGD("---> BEGIN: libbcc [ %s ]\n", name);
     }
 
     ~FuncLogger() {
-      LOGD("---> END: libbcc [ %s ]\n", mFuncName);
+      ALOGD("---> END: libbcc [ %s ]\n", mFuncName);
     }
   };
 } // namespace bcc
diff --git a/include/bcc/bcc.h b/include/bcc/bcc.h
index e09b245..67a27d9 100644
--- a/include/bcc/bcc.h
+++ b/include/bcc/bcc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2010-2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,6 +53,18 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Relocation model when prepare object, it provides 1-1 mapping to the enum
+ * llvm::Reloc::Model in llvm/Support/CodeGen.h
+ */
+typedef enum bccRelocModelEnum {
+  bccRelocDefault,  // Use default target-defined relocation model
+  bccRelocStatic,
+  bccRelocPIC,
+  bccRelocDynamicNoPIC
+} bccRelocModelEnum;
+
+/*-------------------------------------------------------------------------*/
 
 #ifdef __cplusplus
 extern "C" {
@@ -97,10 +109,18 @@
 
 void bccMarkExternalSymbol(BCCScriptRef script, char const *name);
 
+int bccPrepareRelocatable(BCCScriptRef script,
+                          char const *cacheDir,
+                          char const *cacheName,
+                          bccRelocModelEnum RelocModel,
+                          unsigned long flags);
+
 int bccPrepareSharedObject(BCCScriptRef script,
-                         char const *cacheDir,
-                         char const *cacheName,
-                         unsigned long flags);
+                           char const *cacheDir,
+                           char const *cacheName,
+                           char const *dsoPath,
+                           char const *objPath,
+                           unsigned long flags);
 
 int bccPrepareExecutable(BCCScriptRef script,
                          char const *cacheDir,
@@ -117,6 +137,10 @@
                           size_t funcListSize,
                           void **funcList);
 
+void bccGetExportForEachList(BCCScriptRef script,
+                             size_t forEachListSize,
+                             void **forEachList);
+
 char const *bccGetBuildTime();
 
 char const *bccGetBuildRev();
diff --git a/include/bcc/bcc_cache.h b/include/bcc/bcc_cache.h
index 6d1941f..6809cce 100644
--- a/include/bcc/bcc_cache.h
+++ b/include/bcc/bcc_cache.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -77,6 +77,10 @@
   /* dirty hack for libRS */
   /* TODO: This should be removed in the future */
   uint32_t libRS_threadable;
+
+  /* export foreach list section */
+  off_t export_foreach_list_offset;
+  size_t export_foreach_list_size;
 };
 
 struct OBCC_String {
@@ -119,6 +123,11 @@
   void *cached_addr_list[];
 };
 
+struct OBCC_ExportForEachList {
+  size_t count;
+  void *cached_addr_list[];
+};
+
 struct OBCC_Pragma {
   size_t key_strp_index;
   size_t value_strp_index;
diff --git a/include/bcc/bcc_mccache.h b/include/bcc/bcc_mccache.h
index 2988afc..292165d 100644
--- a/include/bcc/bcc_mccache.h
+++ b/include/bcc/bcc_mccache.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -75,6 +75,10 @@
   /* dirty hack for libRS */
   /* TODO: This should be removed in the future */
   uint32_t libRS_threadable;
+
+  /* export foreach list section */
+  off_t export_foreach_name_list_offset;
+  size_t export_foreach_name_list_size;
 };
 
 
diff --git a/include/bcinfo/MetadataExtractor.h b/include/bcinfo/MetadataExtractor.h
index b773dd7..c2b7921 100644
--- a/include/bcinfo/MetadataExtractor.h
+++ b/include/bcinfo/MetadataExtractor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2011-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
   size_t mExportVarCount;
   size_t mExportFuncCount;
   size_t mExportForEachSignatureCount;
+  const char **mExportForEachNameList;
   const uint32_t *mExportForEachSignatureList;
 
   size_t mPragmaCount;
@@ -46,7 +47,8 @@
   uint32_t mOptimizationLevel;
 
   // Helper functions for extraction
-  bool populateForEachMetadata(const llvm::NamedMDNode *ExportForEachMetadata);
+  bool populateForEachMetadata(const llvm::NamedMDNode *Names,
+                               const llvm::NamedMDNode *Signatures);
   bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
   void populatePragmaMetadata(const llvm::NamedMDNode *PragmaMetadata);
 
@@ -97,6 +99,13 @@
   }
 
   /**
+   * \return array of ForEach function names.
+   */
+  const char **getExportForEachNameList() const {
+    return mExportForEachNameList;
+  }
+
+  /**
    * \return number of pragmas contained in pragmaKeyList and pragmaValueList.
    */
   size_t getPragmaCount() const {
diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
index 1e293b2..0eacfa1 100644
--- a/lib/CodeGen/Android.mk
+++ b/lib/CodeGen/Android.mk
@@ -60,6 +60,7 @@
 LOCAL_IS_HOST_MODULE := true
 
 LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
 LOCAL_C_INCLUDES += $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := $(libbcc_codegen_SRC_FILES)
diff --git a/lib/CodeGen/CodeEmitter.cpp b/lib/CodeGen/CodeEmitter.cpp
index fedb65b..c3f37e1 100644
--- a/lib/CodeGen/CodeEmitter.cpp
+++ b/lib/CodeGen/CodeEmitter.cpp
@@ -53,7 +53,7 @@
 
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Target/TargetJITInfo.h"
 
 #include "llvm/Constant.h"
diff --git a/lib/CodeGen/CodeMemoryManager.cpp b/lib/CodeGen/CodeMemoryManager.cpp
index 9ecc1c3..5f015cc 100644
--- a/lib/CodeGen/CodeMemoryManager.cpp
+++ b/lib/CodeGen/CodeMemoryManager.cpp
@@ -47,7 +47,7 @@
   mpCodeMem = ContextManager::get().allocateContext();
 
   if (!mpCodeMem) {
-    LOGE("Unable to allocate mpCodeMem\n");
+    ALOGE("Unable to allocate mpCodeMem\n");
     llvm::report_fatal_error("Failed to allocate memory for emitting "
                              "codes\n" + ErrMsg);
   }
@@ -194,7 +194,7 @@
 uint8_t *CodeMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
   if (getFreeGVMemSize() < Size) {
     // The code size excesses our limit
-    LOGE("No Global Memory");
+    ALOGE("No Global Memory");
     return NULL;
   }
 
diff --git a/lib/Disassembler/Android.mk b/lib/Disassembler/Android.mk
index 1b5ff4d..1d925ed 100644
--- a/lib/Disassembler/Android.mk
+++ b/lib/Disassembler/Android.mk
@@ -59,6 +59,7 @@
 LOCAL_IS_HOST_MODULE := true
 
 LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
 LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := $(libbcc_disassembler_SRC_FILES)
diff --git a/lib/Disassembler/Disassembler.cpp b/lib/Disassembler/Disassembler.cpp
index d0e6000..7e325ce 100644
--- a/lib/Disassembler/Disassembler.cpp
+++ b/lib/Disassembler/Disassembler.cpp
@@ -32,8 +32,8 @@
 #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/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
 
 #include "llvm/LLVMContext.h"
 
@@ -90,7 +90,7 @@
                           llvm::raw_fd_ostream::F_Append);
 
   if (!ErrorInfo.empty()) {
-    LOGE("Unable to open disassembler output file: %s\n", OutputFileName);
+    ALOGE("Unable to open disassembler output file: %s\n", OutputFileName);
     return;
   }
 
@@ -98,13 +98,15 @@
   OS << "Disassembled code: " << Name << "\n";
 
   const llvm::MCAsmInfo *AsmInfo;
+  const llvm::MCSubtargetInfo *SubtargetInfo;
   const llvm::MCDisassembler *Disassmbler;
   llvm::MCInstPrinter *IP;
 
   AsmInfo = Target->createMCAsmInfo(Compiler::getTargetTriple());
-  Disassmbler = Target->createMCDisassembler();
+  SubtargetInfo = Target->createMCSubtargetInfo(Compiler::getTargetTriple(), "", "");
+  Disassmbler = Target->createMCDisassembler(*SubtargetInfo);
   IP = Target->createMCInstPrinter(AsmInfo->getAssemblerDialect(),
-                                   *AsmInfo);
+                                   *AsmInfo, *SubtargetInfo);
 
   const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize);
 
@@ -115,13 +117,13 @@
     llvm::MCInst Inst;
 
     if (Disassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
-                                    /* REMOVED */ llvm::nulls())) {
+                           /* REMOVED */ llvm::nulls(), llvm::nulls())) {
       OS.indent(4);
       OS.write("0x", 2);
       OS.write_hex((uint32_t)Func + Index);
       OS.write(": 0x", 4);
       OS.write_hex(*(uint32_t *)(Func + Index));
-      IP->printInst(&Inst, OS);
+      IP->printInst(&Inst, OS, "");
       OS << "\n";
     } else {
       if (Size == 0)
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index 4aa6a3f..cc66435 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -91,6 +91,7 @@
 LOCAL_IS_HOST_MODULE := true
 
 LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
 LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := $(libbcc_executionengine_SRC_FILES)
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index b35b191..4199fb2 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,17 +31,18 @@
 #include "Runtime.h"
 #include "ScriptCompiled.h"
 #include "Sha1Helper.h"
+#include "CompilerOption.h"
 
 #if USE_MCJIT
 #include "librsloader.h"
 #endif
 
+#include "Transforms/BCCTransforms.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"
@@ -54,11 +55,9 @@
 
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
 
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
@@ -96,10 +95,25 @@
 
 bool Compiler::GlobalInitialized = false;
 
+
+#if !defined(__HOST__)
+  #define TARGET_TRIPLE_STRING  DEFAULT_TARGET_TRIPLE_STRING
+#else
+// In host TARGET_TRIPLE_STRING is a variable to allow cross-compilation.
+  #if defined(__cplusplus)
+    extern "C" {
+  #endif
+      char *TARGET_TRIPLE_STRING = (char*)DEFAULT_TARGET_TRIPLE_STRING;
+  #if defined(__cplusplus)
+    };
+  #endif
+#endif
+
 // Code generation optimization level for the compiler
 llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
 
 std::string Compiler::Triple;
+llvm::Triple::ArchType Compiler::ArchType;
 
 std::string Compiler::CPU;
 
@@ -117,6 +131,16 @@
 // synced with slang_rs_metadata.h)
 const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
 
+// Name of metadata node where exported ForEach name information resides
+// (should be synced with slang_rs_metadata.h)
+const llvm::StringRef Compiler::ExportForEachNameMetadataName =
+    "#rs_export_foreach_name";
+
+// Name of metadata node where exported ForEach signature information resides
+// (should be synced with slang_rs_metadata.h)
+const llvm::StringRef Compiler::ExportForEachMetadataName =
+    "#rs_export_foreach";
+
 // Name of metadata node where RS object slot info resides (should be
 // synced with slang_rs_metadata.h)
 const llvm::StringRef Compiler::ObjectSlotMetadataName = "#rs_object_slots";
@@ -132,37 +156,61 @@
 //////////////////////////////////////////////////////////////////////////////
 
 void Compiler::GlobalInitialization() {
-  if (GlobalInitialized)
+  if (GlobalInitialized) {
     return;
+  }
+
   // if (!llvm::llvm_is_multithreaded())
   //   llvm::llvm_start_multithreaded();
 
   // Set Triple, CPU and Features here
   Triple = TARGET_TRIPLE_STRING;
 
-#if defined(DEFAULT_ARM_CODEGEN)
-
-#if defined(ARCH_ARM_HAVE_VFP)
-  Features.push_back("+vfp3");
-#if !defined(ARCH_ARM_HAVE_VFP_D32)
-  Features.push_back("+d16");
-#endif
-#endif
-
-  // NOTE: Currently, we have to turn off the support for NEON explicitly.
-  // Since the ARMCodeEmitter.cpp is not ready for JITing NEON
-  // instructions.
-
-  // FIXME: Re-enable NEON when ARMCodeEmitter supports NEON.
-#define USE_ARM_NEON 0
-#if USE_ARM_NEON
-  Features.push_back("+neon");
-  Features.push_back("+neonfp");
+  // Determine ArchType
+#if defined(__HOST__)
+  {
+    std::string Err;
+    llvm::Target const *Target = llvm::TargetRegistry::lookupTarget(Triple, Err);
+    if (Target != NULL) {
+      ArchType = llvm::Triple::getArchTypeForLLVMName(Target->getName());
+    } else {
+      ArchType = llvm::Triple::UnknownArch;
+      ALOGE("%s", Err.c_str());
+    }
+  }
+#elif defined(DEFAULT_ARM_CODEGEN)
+  ArchType = llvm::Triple::arm;
+#elif defined(DEFAULT_MIPS_CODEGEN)
+  ArchType = llvm::Triple::mipsel;
+#elif defined(DEFAULT_X86_CODEGEN)
+  ArchType = llvm::Triple::x86;
+#elif defined(DEFAULT_X86_64_CODEGEN)
+  ArchType = llvm::Triple::x86_64;
 #else
-  Features.push_back("-neon");
-  Features.push_back("-neonfp");
-#endif // USE_ARM_NEON
-#endif // DEFAULT_ARM_CODEGEN
+  ArchType = llvm::Triple::UnknownArch;
+#endif
+
+  if ((ArchType == llvm::Triple::arm) || (ArchType == llvm::Triple::thumb)) {
+#  if defined(ARCH_ARM_HAVE_VFP)
+    Features.push_back("+vfp3");
+#  if !defined(ARCH_ARM_HAVE_VFP_D32)
+    Features.push_back("+d16");
+#  endif
+#  endif
+
+#  if defined(ARCH_ARM_HAVE_NEON)
+    Features.push_back("+neon");
+    Features.push_back("+neonfp");
+#  else
+    Features.push_back("-neon");
+    Features.push_back("-neonfp");
+#  endif
+
+#  if defined(DISABLE_ARCH_ARM_HAVE_NEON)
+    Features.push_back("-neon");
+    Features.push_back("-neonfp");
+#  endif
+  }
 
 #if defined(PROVIDE_ARM_CODEGEN)
   LLVMInitializeARMAsmPrinter();
@@ -171,6 +219,13 @@
   LLVMInitializeARMTarget();
 #endif
 
+#if defined(PROVIDE_MIPS_CODEGEN)
+  LLVMInitializeMipsAsmPrinter();
+  LLVMInitializeMipsTargetMC();
+  LLVMInitializeMipsTargetInfo();
+  LLVMInitializeMipsTarget();
+#endif
+
 #if defined(PROVIDE_X86_CODEGEN)
   LLVMInitializeX86AsmPrinter();
   LLVMInitializeX86TargetMC();
@@ -181,21 +236,6 @@
 #if USE_DISASSEMBLER
   InitializeDisassembler();
 #endif
-  // 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;
 
   // Register the scheduler
   llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
@@ -214,7 +254,7 @@
 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());
+  ALOGE("%s", Message.c_str());
   exit(1);
 }
 
@@ -242,31 +282,17 @@
 #endif
     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;
 }
 
 
-llvm::Module *Compiler::parseBitcodeFile(llvm::MemoryBuffer *MEM) {
-  llvm::Module *result = llvm::ParseBitcodeFile(MEM, *mContext, &mError);
-
-  if (!result) {
-    LOGE("Unable to ParseBitcodeFile: %s\n", mError.c_str());
-    return NULL;
-  }
-
-  return result;
-}
-
-
 int Compiler::linkModule(llvm::Module *moduleWith) {
   if (llvm::Linker::LinkModules(mModule, moduleWith,
-                                llvm::Linker::DestroySource,
+                                llvm::Linker::PreserveSource,
                                 &mError) != 0) {
     return hasError();
   }
@@ -277,7 +303,7 @@
 }
 
 
-int Compiler::compile(bool compileOnly) {
+int Compiler::compile(const CompilerOption &option) {
   llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
   llvm::TargetMachine *TM = NULL;
@@ -290,8 +316,14 @@
   llvm::NamedMDNode const *PragmaMetadata;
   llvm::NamedMDNode const *ExportVarMetadata;
   llvm::NamedMDNode const *ExportFuncMetadata;
+  llvm::NamedMDNode const *ExportForEachNameMetadata;
+  llvm::NamedMDNode const *ExportForEachMetadata;
   llvm::NamedMDNode const *ObjectSlotMetadata;
 
+  std::vector<std::string> ForEachNameList;
+  std::vector<std::string> ForEachExpandList;
+  std::vector<uint32_t> forEachSigList;
+
   llvm::NamedMDNode const *OptimizationLevelMetadata =
     mModule->getNamedMetadata(OptimizationLevelMetadataName);
 
@@ -322,10 +354,9 @@
   llvm::RegisterRegAlloc::setDefault
     ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
      llvm::createFastRegisterAllocator :
-     llvm::createLinearScanRegisterAllocator);
+     llvm::createGreedyRegisterAllocator);
 
-
-  // Create TargetMachine
+  // Find LLVM Target
   Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
   if (hasError())
     goto on_bcc_compile_error;
@@ -341,18 +372,12 @@
     FeaturesStr = F.getString();
   }
 
-#if defined(DEFAULT_X86_64_CODEGEN)
-  // Data address in X86_64 architecture may reside in a far-away place
+  // Create LLVM Target Machine
   TM = Target->createTargetMachine(Triple, CPU, FeaturesStr,
-                                   llvm::Reloc::Static,
-                                   llvm::CodeModel::Medium);
-#else
-  // This is set for the linker (specify how large of the virtual addresses
-  // we can access for all unknown symbols.)
-  TM = Target->createTargetMachine(Triple, CPU, FeaturesStr,
-                                   llvm::Reloc::Static,
-                                   llvm::CodeModel::Small);
-#endif
+                                   option.TargetOpt,
+                                   option.RelocModelOpt,
+                                   option.CodeModelOpt);
+
   if (TM == NULL) {
     setError("Failed to create target machine implementation for the"
              " specified triple '" + Triple + "'");
@@ -365,13 +390,56 @@
   // Load named metadata
   ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
   ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
+  ExportForEachNameMetadata =
+      mModule->getNamedMetadata(ExportForEachNameMetadataName);
+  ExportForEachMetadata =
+      mModule->getNamedMetadata(ExportForEachMetadataName);
   PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
   ObjectSlotMetadata = mModule->getNamedMetadata(ObjectSlotMetadataName);
 
+  if (ExportForEachNameMetadata) {
+    for (int i = 0, e = ExportForEachNameMetadata->getNumOperands();
+         i != e;
+         i++) {
+      llvm::MDNode *ExportForEach = ExportForEachNameMetadata->getOperand(i);
+      if (ExportForEach != NULL && ExportForEach->getNumOperands() > 0) {
+        llvm::Value *ExportForEachNameMDS = ExportForEach->getOperand(0);
+        if (ExportForEachNameMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef ExportForEachName =
+            static_cast<llvm::MDString*>(ExportForEachNameMDS)->getString();
+          ForEachNameList.push_back(ExportForEachName.str());
+          std::string ExpandName = ExportForEachName.str() + ".expand";
+          ForEachExpandList.push_back(ExpandName);
+        }
+      }
+    }
+  }
+
+  if (ExportForEachMetadata) {
+    for (int i = 0, e = ExportForEachMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(i);
+      if (SigNode != NULL && SigNode->getNumOperands() == 1) {
+        llvm::Value *SigVal = SigNode->getOperand(0);
+        if (SigVal->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef SigString =
+              static_cast<llvm::MDString*>(SigVal)->getString();
+          uint32_t Signature = 0;
+          if (SigString.getAsInteger(10, Signature)) {
+            ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
+            goto on_bcc_compile_error;
+          }
+          forEachSigList.push_back(Signature);
+        }
+      }
+    }
+  }
+
+  runInternalPasses(ForEachNameList, forEachSigList);
+
   // Perform link-time optimization if we have multiple modules
   if (mHasLinked) {
     runLTO(new llvm::TargetData(*TD), ExportVarMetadata, ExportFuncMetadata,
-      CodeGenOptLevel);
+           ForEachExpandList, CodeGenOptLevel);
   }
 
   // Perform code generation
@@ -387,7 +455,7 @@
     goto on_bcc_compile_error;
   }
 
-  if (compileOnly)
+  if (!option.LoadAfterCompile)
     return 0;
 
   // Load the ELF Object
@@ -421,7 +489,7 @@
                                      ExportVarName.str().c_str()));
           varNameList.push_back(ExportVarName.str());
 #if DEBUG_MCJIT_REFLECT
-          LOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(),
+          ALOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(),
                varList.back());
 #endif
           continue;
@@ -449,7 +517,7 @@
                                      ExportFuncName.str().c_str()));
           funcNameList.push_back(ExportFuncName.str());
 #if DEBUG_MCJIT_RELECT
-          LOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
+          ALOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
                funcList.back());
 #endif
         }
@@ -457,6 +525,29 @@
     }
   }
 
+  if (ExportForEachNameMetadata) {
+    ScriptCompiled::ExportForEachList &forEachList = mpResult->mExportForEach;
+    std::vector<std::string> &ForEachNameList = mpResult->mExportForEachName;
+
+    for (int i = 0, e = ExportForEachNameMetadata->getNumOperands();
+         i != e;
+         i++) {
+      llvm::MDNode *ExportForEach = ExportForEachNameMetadata->getOperand(i);
+      if (ExportForEach != NULL && ExportForEach->getNumOperands() > 0) {
+        llvm::Value *ExportForEachNameMDS = ExportForEach->getOperand(0);
+        if (ExportForEachNameMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef ExportForEachName =
+            static_cast<llvm::MDString*>(ExportForEachNameMDS)->getString();
+          std::string Name = ExportForEachName.str() + ".expand";
+
+          forEachList.push_back(
+              rsloaderGetSymbolAddress(mRSExecutable, Name.c_str()));
+          ForEachNameList.push_back(Name);
+        }
+      }
+    }
+  }
+
 #if DEBUG_MCJIT_DISASSEMBLER
   {
     // Get MC codegen emitted function name list
@@ -501,7 +592,7 @@
                            std::string(PragmaValue.data(),
                                        PragmaValue.size())));
 #if DEBUG_BCC_REFLECT
-          LOGD("compile(): Pragma: %s -> %s\n",
+          ALOGD("compile(): Pragma: %s -> %s\n",
                pragmaList.back().first.c_str(),
                pragmaList.back().second.c_str());
 #endif
@@ -528,7 +619,7 @@
           }
           objectSlotList.push_back(USlot);
 #if DEBUG_BCC_REFLECT
-          LOGD("compile(): RefCount Slot: %s @ %u\n", Slot.str().c_str(), USlot);
+          ALOGD("compile(): RefCount Slot: %s @ %u\n", Slot.str().c_str(), USlot);
 #endif
         }
       }
@@ -536,7 +627,7 @@
   }
 
 on_bcc_compile_error:
-  // LOGE("on_bcc_compiler_error");
+  // ALOGE("on_bcc_compiler_error");
   if (TD) {
     delete TD;
   }
@@ -549,7 +640,7 @@
     return 0;
   }
 
-  // LOGE(getErrorMessage());
+  // ALOGE(getErrorMessage());
   return 1;
 }
 
@@ -628,7 +719,7 @@
             if (ExportVarName == I->first->getName()) {
               varList.push_back(I->second);
 #if DEBUG_BCC_REFLECT
-              LOGD("runCodeGen(): Exported VAR: %s @ %p\n", ExportVarName.str().c_str(), I->second);
+              ALOGD("runCodeGen(): Exported VAR: %s @ %p\n", ExportVarName.str().c_str(), I->second);
 #endif
               break;
             }
@@ -637,7 +728,7 @@
             continue;  // found
 
 #if DEBUG_BCC_REFLECT
-          LOGD("runCodeGen(): Exported VAR: %s @ %p\n",
+          ALOGD("runCodeGen(): Exported VAR: %s @ %p\n",
                ExportVarName.str().c_str(), (void *)0);
 #endif
         }
@@ -663,7 +754,7 @@
             static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
           funcList.push_back(mpResult->lookup(ExportFuncName.str().c_str()));
 #if DEBUG_BCC_REFLECT
-          LOGD("runCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
+          ALOGD("runCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
                funcList.back());
 #endif
         }
@@ -696,8 +787,7 @@
 
   // Add MC code generation passes to pass manager
   llvm::MCContext *Ctx = NULL;
-  if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS,
-                            CodeGenOptLevel, false)) {
+  if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) {
     setError("Fail to add passes to emit file");
     return 1;
   }
@@ -708,10 +798,22 @@
 }
 #endif // USE_MCJIT
 
+int Compiler::runInternalPasses(std::vector<std::string>& Names,
+                                std::vector<uint32_t>& Signatures) {
+  llvm::PassManager BCCPasses;
+
+  // Expand ForEach on CPU path to reduce launch overhead.
+  BCCPasses.add(createForEachExpandPass(Names, Signatures));
+
+  BCCPasses.run(*mModule);
+
+  return 0;
+}
 
 int Compiler::runLTO(llvm::TargetData *TD,
                      llvm::NamedMDNode const *ExportVarMetadata,
                      llvm::NamedMDNode const *ExportFuncMetadata,
+                     std::vector<std::string>& ForEachExpandList,
                      llvm::CodeGenOpt::Level OptimizationLevel) {
   // Collect All Exported Symbols
   std::vector<const char*> ExportSymbols;
@@ -746,6 +848,10 @@
     }
   }
 
+  for (int i = 0, e = ForEachExpandList.size(); i != e; i++) {
+    ExportSymbols.push_back(ForEachExpandList[i].c_str());
+  }
+
   // TODO(logan): Remove this after we have finished the
   // bccMarkExternalSymbol API.
 
@@ -892,16 +998,13 @@
     }
   }
 
-  LOGE("Unable to resolve symbol: %s\n", name);
+  ALOGE("Unable to resolve symbol: %s\n", name);
   return NULL;
 }
 #endif
 
 
 Compiler::~Compiler() {
-  delete mModule;
-  delete mContext;
-
 #if USE_MCJIT
   rsloaderDisposeExec(mRSExecutable);
 #endif
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 4063edb..c70a920 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Target/TargetMachine.h"
 
 #include <stddef.h>
@@ -40,9 +41,7 @@
 
 
 namespace llvm {
-  class LLVMContext;
   class Module;
-  class MemoryBuffer;
   class NamedMDNode;
   class TargetData;
 }
@@ -50,6 +49,7 @@
 
 namespace bcc {
   class ScriptCompiled;
+  struct CompilerOption;
 
   class Compiler {
   private:
@@ -62,6 +62,7 @@
     // If given, this will be the name of the target triple to compile for.
     // If not given, the initial values defined in this file will be used.
     static std::string Triple;
+    static llvm::Triple::ArchType ArchType;
 
     static llvm::CodeGenOpt::Level CodeGenOptLevel;
 
@@ -79,6 +80,8 @@
     static const llvm::StringRef PragmaMetadataName;
     static const llvm::StringRef ExportVarMetadataName;
     static const llvm::StringRef ExportFuncMetadataName;
+    static const llvm::StringRef ExportForEachNameMetadataName;
+    static const llvm::StringRef ExportForEachMetadataName;
     static const llvm::StringRef ObjectSlotMetadataName;
 
     friend class CodeEmitter;
@@ -109,7 +112,6 @@
     BCCSymbolLookupFn mpSymbolLookupFn;
     void *mpSymbolLookupContext;
 
-    llvm::LLVMContext *mContext;
     llvm::Module *mModule;
 
     bool mHasLinked;
@@ -123,6 +125,10 @@
       return Triple;
     }
 
+    static llvm::Triple::ArchType getTargetArchType() {
+      return ArchType;
+    }
+
     void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
       mpSymbolLookupFn = pFn;
       mpSymbolLookupContext = pContext;
@@ -142,8 +148,6 @@
     }
 #endif
 
-    llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM);
-
     int readModule(llvm::Module *module) {
       mModule = module;
       return hasError();
@@ -151,7 +155,7 @@
 
     int linkModule(llvm::Module *module);
 
-    int compile(bool compileOnly);
+    int compile(const CompilerOption &option);
 
     char const *getErrorMessage() {
       return mError.c_str();
@@ -174,10 +178,13 @@
 #if USE_MCJIT
     static void *resolveSymbolAdapter(void *context, char const *name);
 #endif
+    int runInternalPasses(std::vector<std::string>& Names,
+                          std::vector<uint32_t>& Signatures);
 
     int runLTO(llvm::TargetData *TD,
                llvm::NamedMDNode const *ExportVarMetadata,
                llvm::NamedMDNode const *ExportFuncMetadata,
+               std::vector<std::string>& ForEachExpandList,
                llvm::CodeGenOpt::Level OptimizationLevel);
 
     bool hasError() const {
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
new file mode 100644
index 0000000..75278c7
--- /dev/null
+++ b/lib/ExecutionEngine/CompilerOption.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_COMPILER_OPTION_H
+#define BCC_COMPILER_OPTION_H
+
+#include "Config.h"
+#include "Compiler.h"
+
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/CodeGen.h"
+
+namespace bcc {
+
+class CompilerOption {
+ public:
+  // Constructor setup "default configuration". The "default configuration"
+  // here means the configuration for running RenderScript (more specifically,
+  // one can declare a CompilerOption object (call default constructor) and then
+  // pass to the Compiler::compiler() without any modification for RenderScript,
+  // see Script::prepareExecutable(...)).
+  //
+  // Must be invoked after calling Compiler::GlobalInitialization() at least once.
+  //
+  CompilerOption() {
+    //-- Setup options to llvm::TargetMachine --//
+
+    //-- Setup Frame Pointer Elimination Optimization --//
+#if defined(__HOST__)
+    // Disable frame pointer elimination optimization for X86_64 and X86
+    if ((Compiler::getTargetArchType() == llvm::Triple::x86_64) ||
+        (Compiler::getTargetArchType() == llvm::Triple::x86)) {
+      TargetOpt.NoFramePointerElim = true;
+    } else {
+      TargetOpt.NoFramePointerElim = false;
+    }
+#elif defined(DEFAULT_X86_64_CODEGEN)
+    TargetOpt.NoFramePointerElim = true;
+#elif defined(DEFAULT_X86_CODEGEN)
+    TargetOpt.NoFramePointerElim = true;
+#else
+    TargetOpt.NoFramePointerElim = false;
+#endif
+
+    // Use hardfloat ABI
+    //
+    // TODO(all): Need to detect the CPU capability and decide whether to use
+    // softfp. To use softfp, change following 2 lines to
+    //
+    // options.FloatABIType = llvm::FloatABI::Soft;
+    // options.UseSoftFloat = true;
+    TargetOpt.FloatABIType = llvm::FloatABI::Soft;
+    TargetOpt.UseSoftFloat = false;
+
+    //-- Setup relocation model  --//
+    RelocModelOpt = llvm::Reloc::Static;
+
+    //-- Setup code model  --//
+#if defined(__HOST__)
+    // Data address in X86_64 architecture may reside in a far-away place
+    if (Compiler::getTargetArchType() == llvm::Triple::x86_64) {
+      CodeModelOpt = llvm::CodeModel::Medium;
+    } else {
+      CodeModelOpt = llvm::CodeModel::Small;
+    }
+#elif defined(DEFAULT_X86_64_CODEGEN)
+    CodeModelOpt = llvm::CodeModel::Medium;
+#else
+    CodeModelOpt = llvm::CodeModel::Small;
+#endif
+
+    //-- Load the result object after successful compilation  --//
+    LoadAfterCompile = true;
+  }
+
+  llvm::TargetOptions TargetOpt;
+  llvm::CodeModel::Model CodeModelOpt;
+  llvm::Reloc::Model RelocModelOpt;
+  bool LoadAfterCompile;
+
+};
+
+} // namespace bcc
+
+#endif  // BCC_COMPILER_OPTION_H
diff --git a/lib/ExecutionEngine/FileHandle.cpp b/lib/ExecutionEngine/FileHandle.cpp
index 1055ea7..c0a344c 100644
--- a/lib/ExecutionEngine/FileHandle.cpp
+++ b/lib/ExecutionEngine/FileHandle.cpp
@@ -55,7 +55,7 @@
         continue;
       }
 
-      LOGW("Unable to open %s in %s mode.  (reason: %s)\n",
+      ALOGW("Unable to open %s in %s mode.  (reason: %s)\n",
            filename, open_mode_str[mode], strerror(errno));
 
       return -1;
@@ -63,10 +63,10 @@
 
     // Try to lock the file
     if (flock(mFD, lock_flags[mode] | LOCK_NB) < 0) {
-      LOGW("Unable to acquire the lock immediately, block and wait now ...\n");
+      ALOGW("Unable to acquire the lock immediately, block and wait now ...\n");
 
       if (flock(mFD, lock_flags[mode]) < 0) {
-        LOGE("Unable to acquire the lock. Retry ...\n");
+        ALOGE("Unable to acquire the lock. Retry ...\n");
 
         ::close(mFD);
         mFD = -1;
@@ -94,11 +94,11 @@
     }
 
     // Good, we have open and lock the file correctly.
-    LOGV("File opened. fd=%d\n", mFD);
+    ALOGV("File opened. fd=%d\n", mFD);
     return mFD;
   }
 
-  LOGW("Unable to open %s in %s mode.\n", filename, open_mode_str[mode]);
+  ALOGW("Unable to open %s in %s mode.\n", filename, open_mode_str[mode]);
   return -1;
 }
 
@@ -107,7 +107,7 @@
   if (mFD >= 0) {
     flock(mFD, LOCK_UN);
     ::close(mFD);
-    LOGV("File closed. fd=%d\n", mFD);
+    ALOGV("File closed. fd=%d\n", mFD);
     mFD = -1;
   }
 }
@@ -172,7 +172,7 @@
 void FileHandle::truncate() {
   if (mFD >= 0) {
     if (ftruncate(mFD, 0) != 0) {
-      LOGE("Unable to truncate the file.\n");
+      ALOGE("Unable to truncate the file.\n");
     }
   }
 }
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
index a88d4d4..5beff88 100644
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ b/lib/ExecutionEngine/MCCacheReader.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,6 +60,7 @@
              && readObjFile()
              && readVarNameList()
              && readFuncNameList()
+             && readForEachNameList()
              //&& relocate()
              ;
 
@@ -81,7 +82,7 @@
   mpResult.reset(new (nothrow) ScriptCached(S));
 
   if (!mpResult) {
-    LOGE("Unable to allocate ScriptCached object.\n");
+    ALOGE("Unable to allocate ScriptCached object.\n");
     return false;
   }
 
@@ -103,14 +104,14 @@
 bool MCCacheReader::checkFileSize() {
   struct stat stfile;
   if (fstat(mInfoFile->getFD(), &stfile) < 0) {
-    LOGE("Unable to stat cache file.\n");
+    ALOGE("Unable to stat cache file.\n");
     return false;
   }
 
   mInfoFileSize = stfile.st_size;
 
   if (mInfoFileSize < (off_t)sizeof(MCO_Header)) {
-    LOGE("Cache file is too small to be correct.\n");
+    ALOGE("Cache file is too small to be correct.\n");
     return false;
   }
 
@@ -120,19 +121,19 @@
 
 bool MCCacheReader::readHeader() {
   if (mInfoFile->seek(0, SEEK_SET) != 0) {
-    LOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
+    ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
     return false;
   }
 
   mpHeader = (MCO_Header *)malloc(sizeof(MCO_Header));
   if (!mpHeader) {
-    LOGE("Unable to allocate for cache header.\n");
+    ALOGE("Unable to allocate for cache header.\n");
     return false;
   }
 
   if (mInfoFile->read(reinterpret_cast<char *>(mpHeader), sizeof(MCO_Header)) !=
       (ssize_t)sizeof(MCO_Header)) {
-    LOGE("Unable to read cache header.\n");
+    ALOGE("Unable to read cache header.\n");
     return false;
   }
 
@@ -148,13 +149,13 @@
 
 bool MCCacheReader::checkHeader() {
   if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
-    LOGE("Bad magic word\n");
+    ALOGE("Bad magic word\n");
     return false;
   }
 
   if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
     mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
-    LOGI("Cache file format version mismatch: now %s cached %s\n",
+    ALOGI("Cache file format version mismatch: now %s cached %s\n",
          OBCC_VERSION, mpHeader->version);
     return false;
   }
@@ -168,14 +169,14 @@
   bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
   if ((isLittleEndian && mpHeader->endianness != 'e') ||
       (!isLittleEndian && mpHeader->endianness != 'E')) {
-    LOGE("Machine endianness mismatch.\n");
+    ALOGE("Machine endianness mismatch.\n");
     return false;
   }
 
   if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
       (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
       (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
-    LOGE("Machine integer size mismatch.\n");
+    ALOGE("Machine integer size mismatch.\n");
     return false;
   }
 
@@ -190,17 +191,17 @@
     off_t size = (off_t)mpHeader-> NAME##_size;                             \
                                                                             \
     if (mInfoFileSize < offset || mInfoFileSize < offset + size) {          \
-      LOGE(#NAME " section overflow.\n");                                   \
+      ALOGE(#NAME " section overflow.\n");                                   \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (offset % sizeof(int) != 0) {                                        \
-      LOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int));        \
+      ALOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int));        \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (size < static_cast<off_t>(sizeof(size_t))) {                        \
-      LOGE(#NAME " size is too small to be correct.\n");                    \
+      ALOGE(#NAME " size is too small to be correct.\n");                    \
       return false;                                                         \
     }                                                                       \
   } while (0)
@@ -220,7 +221,7 @@
   TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size);                 \
                                                                             \
   if (!NAME##_raw) {                                                        \
-    LOGE("Unable to allocate for " #NAME "\n");                             \
+    ALOGE("Unable to allocate for " #NAME "\n");                             \
     return false;                                                           \
   }                                                                         \
                                                                             \
@@ -228,14 +229,14 @@
   AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
                                                                             \
   if (mInfoFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) {           \
-    LOGE("Unable to seek to " #NAME " section\n");                          \
+    ALOGE("Unable to seek to " #NAME " section\n");                          \
     return false;                                                           \
   }                                                                         \
                                                                             \
   if (mInfoFile->read(reinterpret_cast<char *>(NAME##_raw),                 \
                   mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
   {                                                                         \
-    LOGE("Unable to read " #NAME ".\n");                                    \
+    ALOGE("Unable to read " #NAME ".\n");                                    \
     return false;                                                           \
   }
 
@@ -263,7 +264,7 @@
   // Ensure that every c-style string is ended with '\0'
   for (size_t i = 0; i < poolR->count; ++i) {
     if (pool[i][poolR->list[i].length] != '\0') {
-      LOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
+      ALOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
       return false;
     }
   }
@@ -281,7 +282,7 @@
 
 bool MCCacheReader::checkDependency() {
   if (mDependencies.size() != mpCachedDependTable->count) {
-    LOGE("Dependencies count mismatch. (%lu vs %lu)\n",
+    ALOGE("Dependencies count mismatch. (%lu vs %lu)\n",
          (unsigned long)mDependencies.size(),
          (unsigned long)mpCachedDependTable->count);
     return false;
@@ -302,18 +303,18 @@
     unsigned char const *depCachedSHA1 = depCached->sha1;
 
     if (depName != depCachedName) {
-      LOGE("Cache dependency name mismatch:\n");
-      LOGE("  given:  %s\n", depName.c_str());
-      LOGE("  cached: %s\n", depCachedName);
+      ALOGE("Cache dependency name mismatch:\n");
+      ALOGE("  given:  %s\n", depName.c_str());
+      ALOGE("  cached: %s\n", depCachedName);
 
       return false;
     }
 
     if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
-      LOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
+      ALOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
 
 #define PRINT_SHA1(PREFIX, X, POSTFIX) \
-      LOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
+      ALOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
                   "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
            X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
            X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
@@ -327,7 +328,7 @@
     }
 
     if (depType != depCachedType) {
-      LOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
+      ALOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
       return false;
     }
   }
@@ -343,7 +344,7 @@
                             malloc(sizeof(size_t) +
                                    sizeof(void*) * export_var_name_list_raw->count);
   if (!mpResult->mpExportVars) {
-    LOGE("Unable to allocate for mpExportVars\n");
+    ALOGE("Unable to allocate for mpExportVars\n");
     return false;
   }
   mpResult->mpExportVars->count = export_var_name_list_raw->count;
@@ -352,7 +353,7 @@
     mpResult->mpExportVars->cached_addr_list[i] =
       rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_var_name_list_raw->strp_indexs[i]]);
 #if DEBUG_MCJIT_REFLECT
-    LOGD("Get symbol address: %s -> %p",
+    ALOGD("Get symbol address: %s -> %p",
       strPool[export_var_name_list_raw->strp_indexs[i]], mpResult->mpExportVars->cached_addr_list[i]);
 #endif
   }
@@ -367,7 +368,7 @@
                             malloc(sizeof(size_t) +
                                    sizeof(void*) * export_func_name_list_raw->count);
   if (!mpResult->mpExportFuncs) {
-    LOGE("Unable to allocate for mpExportFuncs\n");
+    ALOGE("Unable to allocate for mpExportFuncs\n");
     return false;
   }
   mpResult->mpExportFuncs->count = export_func_name_list_raw->count;
@@ -376,13 +377,37 @@
     mpResult->mpExportFuncs->cached_addr_list[i] =
       rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_func_name_list_raw->strp_indexs[i]]);
 #if DEBUG_MCJIT_REFLECT
-    LOGD("Get function address: %s -> %p",
+    ALOGD("Get function address: %s -> %p",
       strPool[export_func_name_list_raw->strp_indexs[i]], mpResult->mpExportFuncs->cached_addr_list[i]);
 #endif
   }
   return true;
 }
 
+bool MCCacheReader::readForEachNameList() {
+  CACHE_READER_READ_SECTION(OBCC_String_Ptr, mpForEachNameList, export_foreach_name_list);
+  vector<char const *> const &strPool = mpResult->mStringPool;
+
+  mpResult->mpExportForEach = (OBCC_ExportForEachList*)
+                              malloc(sizeof(size_t) +
+                                     sizeof(void*) * export_foreach_name_list_raw->count);
+  if (!mpResult->mpExportForEach) {
+    ALOGE("Unable to allocate for mpExportForEach\n");
+    return false;
+  }
+  mpResult->mpExportForEach->count = export_foreach_name_list_raw->count;
+
+  for (size_t i = 0; i < export_foreach_name_list_raw->count; ++i) {
+    mpResult->mpExportForEach->cached_addr_list[i] =
+      rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_foreach_name_list_raw->strp_indexs[i]]);
+#if DEBUG_MCJIT_REFLECT
+    ALOGE("Get foreach function address: %s -> %p",
+      strPool[export_foreach_name_list_raw->strp_indexs[i]], mpResult->mpExportForEach->cached_addr_list[i]);
+#endif
+  }
+  return true;
+}
+
 bool MCCacheReader::readPragmaList() {
   CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
 
@@ -419,13 +444,13 @@
     }
   }
 
-  LOGE("Unable to resolve symbol: %s\n", name);
+  ALOGE("Unable to resolve symbol: %s\n", name);
   return NULL;
 }
 
 bool MCCacheReader::readObjFile() {
   if (mpResult->mCachedELFExecutable.size() != 0) {
-    LOGE("Attempted to read cached object into a non-empty script");
+    ALOGE("Attempted to read cached object into a non-empty script");
     return false;
   }
   char readBuffer[1024];
@@ -434,10 +459,10 @@
     mpResult->mCachedELFExecutable.append(readBuffer, readBuffer + readSize);
   }
   if (readSize != 0) {
-    LOGE("Read file Error");
+    ALOGE("Read file Error");
     return false;
   }
-  LOGD("Read object file size %d", (int)mpResult->mCachedELFExecutable.size());
+  ALOGD("Read object file size %d", (int)mpResult->mCachedELFExecutable.size());
   mpResult->mRSExecutable =
   rsloaderCreateExec((unsigned char *)&*(mpResult->mCachedELFExecutable.begin()),
                      mpResult->mCachedELFExecutable.size(),
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
index 7fcbe41..1e59111 100644
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ b/lib/ExecutionEngine/MCCacheReader.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
 
     OBCC_String_Ptr *mpVarNameList;
     OBCC_String_Ptr *mpFuncNameList;
+    OBCC_String_Ptr *mpForEachNameList;
 
     llvm::OwningPtr<ScriptCached> mpResult;
 
@@ -61,7 +62,7 @@
     MCCacheReader()
       : mObjFile(NULL), mInfoFile(NULL), mInfoFileSize(0), mpHeader(NULL),
         mpCachedDependTable(NULL), mpPragmaList(NULL),
-        mpVarNameList(NULL), mpFuncNameList(NULL),
+        mpVarNameList(NULL), mpFuncNameList(NULL), mpForEachNameList(NULL),
         mIsContextSlotNotAvail(false) {
     }
 
@@ -97,6 +98,7 @@
 
     bool readVarNameList();
     bool readFuncNameList();
+    bool readForEachNameList();
 
     bool checkFileSize();
     bool checkHeader();
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
index 6fbf4ba..cca724e 100644
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ b/lib/ExecutionEngine/MCCacheWriter.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,6 +63,7 @@
              && preparePragmaList()
              && prepareExportVarNameList()
              && prepareExportFuncNameList()
+             && prepareExportForEachNameList()
              && prepareStringPool()
              && prepareObjectSlotList()
              && calcSectionOffset()
@@ -77,7 +78,7 @@
   MCO_Header *header = (MCO_Header *)malloc(sizeof(MCO_Header));
 
   if (!header) {
-    LOGE("Unable to allocate for header.\n");
+    ALOGE("Unable to allocate for header.\n");
     return false;
   }
 
@@ -112,7 +113,7 @@
   OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
 
   if (!tab) {
-    LOGE("Unable to allocate for dependency table section.\n");
+    ALOGE("Unable to allocate for dependency table section.\n");
     return false;
   }
 
@@ -143,7 +144,7 @@
   OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for pragma list\n");
+    ALOGE("Unable to allocate for pragma list\n");
     return false;
   }
 
@@ -186,7 +187,7 @@
   OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
 
   if (!pool) {
-    LOGE("Unable to allocate string pool.\n");
+    ALOGE("Unable to allocate string pool.\n");
     return false;
   }
 
@@ -221,7 +222,7 @@
   OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for export variable name list\n");
+    ALOGE("Unable to allocate for export variable name list\n");
     return false;
   }
 
@@ -245,7 +246,7 @@
   OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for export function name list\n");
+    ALOGE("Unable to allocate for export function name list\n");
     return false;
   }
 
@@ -262,6 +263,30 @@
 }
 
 
+bool MCCacheWriter::prepareExportForEachNameList() {
+  size_t forEachCount = mpOwner->getExportForEachCount();
+  size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * forEachCount;
+
+  OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
+
+  if (!list) {
+    ALOGE("Unable to allocate for export forEach name list\n");
+    return false;
+  }
+
+  mpExportForEachNameListSection = list;
+  mpHeaderSection->export_foreach_name_list_size = listSize;
+
+  list->count = static_cast<size_t>(forEachCount);
+
+  mpOwner->getExportForEachNameList(forEachNameList);
+  for (size_t i = 0; i < forEachCount; ++i) {
+    list->strp_indexs[i] = addString(forEachNameList[i].c_str(), forEachNameList[i].length());
+  }
+  return true;
+}
+
+
 bool MCCacheWriter::prepareObjectSlotList() {
   size_t objectSlotCount = mpOwner->getObjectSlotCount();
 
@@ -271,7 +296,7 @@
   OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for object slot list\n");
+    ALOGE("Unable to allocate for object slot list\n");
     return false;
   }
 
@@ -308,6 +333,7 @@
   OFFSET_INCREASE(object_slot_list);
   OFFSET_INCREASE(export_var_name_list);
   OFFSET_INCREASE(export_func_name_list);
+  OFFSET_INCREASE(export_foreach_name_list);
 
 #undef OFFSET_INCREASE
 
@@ -319,13 +345,13 @@
 #define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
   do {                                                                      \
     if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) {                          \
-      LOGE("Unable to seek to " #NAME " section for writing.\n");           \
+      ALOGE("Unable to seek to " #NAME " section for writing.\n");           \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=      \
         static_cast<ssize_t>(SIZE)) {                                       \
-      LOGE("Unable to write " #NAME " section to cache file.\n");           \
+      ALOGE("Unable to write " #NAME " section to cache file.\n");           \
       return false;                                                         \
     }                                                                       \
   } while (0)
@@ -345,6 +371,7 @@
 
   WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
   WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
+  WRITE_SECTION_SIMPLE(export_foreach_name_list, mpExportForEachNameListSection);
 
 #undef WRITE_SECTION_SIMPLE
 #undef WRITE_SECTION
@@ -352,7 +379,7 @@
   if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
                                           mpOwner->getELFSize()))
       != mpOwner->getELFSize()) {
-      LOGE("Unable to write ELF to cache file.\n");
+      ALOGE("Unable to write ELF to cache file.\n");
       return false;
   }
 
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
index bd395d5..58f6ef5 100644
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ b/lib/ExecutionEngine/MCCacheWriter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -48,9 +48,11 @@
 
     OBCC_String_Ptr *mpExportVarNameListSection;
     OBCC_String_Ptr *mpExportFuncNameListSection;
+    OBCC_String_Ptr *mpExportForEachNameListSection;
 
     std::vector<std::string> varNameList;
     std::vector<std::string> funcNameList;
+    std::vector<std::string> forEachNameList;
 
   public:
     MCCacheWriter()
@@ -81,6 +83,7 @@
 
     bool prepareExportVarNameList();
     bool prepareExportFuncNameList();
+    bool prepareExportForEachNameList();
 
     bool writeAll();
 
diff --git a/lib/ExecutionEngine/OldJIT/CacheReader.cpp b/lib/ExecutionEngine/OldJIT/CacheReader.cpp
index c11a9e7..8eceb5f 100644
--- a/lib/ExecutionEngine/OldJIT/CacheReader.cpp
+++ b/lib/ExecutionEngine/OldJIT/CacheReader.cpp
@@ -65,7 +65,7 @@
   mpResult.reset(new (nothrow) ScriptCached(S));
 
   if (!mpResult) {
-    LOGE("Unable to allocate ScriptCached object.\n");
+    ALOGE("Unable to allocate ScriptCached object.\n");
     return NULL;
   }
 
@@ -97,24 +97,24 @@
   struct stat stfile;
 
   if (fstat(mInfoFile->getFD(), &stfile) < 0) {
-    LOGE("Unable to stat metadata information file.\n");
+    ALOGE("Unable to stat metadata information file.\n");
     return false;
   }
 
   mInfoFileSize = stfile.st_size;
 
   if (mInfoFileSize < (off_t)sizeof(OBCC_Header)) {
-    LOGE("Metadata information file is too small to be correct.\n");
+    ALOGE("Metadata information file is too small to be correct.\n");
     return false;
   }
 
   if (fstat(mObjFile->getFD(), &stfile) < 0) {
-    LOGE("Unable to stat executable file.\n");
+    ALOGE("Unable to stat executable file.\n");
     return false;
   }
 
   if (stfile.st_size < (off_t)ContextManager::ContextSize) {
-    LOGE("Executable file is too small to be correct.\n");
+    ALOGE("Executable file is too small to be correct.\n");
     return false;
   }
 
@@ -124,19 +124,19 @@
 
 bool CacheReader::readHeader() {
   if (mInfoFile->seek(0, SEEK_SET) != 0) {
-    LOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
+    ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
     return false;
   }
 
   mpHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
   if (!mpHeader) {
-    LOGE("Unable to allocate for cache header.\n");
+    ALOGE("Unable to allocate for cache header.\n");
     return false;
   }
 
   if (mInfoFile->read((char *)mpHeader, sizeof(OBCC_Header)) !=
       (ssize_t)sizeof(OBCC_Header)) {
-    LOGE("Unable to read cache header.\n");
+    ALOGE("Unable to read cache header.\n");
     return false;
   }
 
@@ -152,13 +152,13 @@
 
 bool CacheReader::checkHeader() {
   if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
-    LOGE("Bad magic word\n");
+    ALOGE("Bad magic word\n");
     return false;
   }
 
   if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
     mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
-    LOGI("Cache file format version mismatch: now %s cached %s\n",
+    ALOGI("Cache file format version mismatch: now %s cached %s\n",
          OBCC_VERSION, mpHeader->version);
     return false;
   }
@@ -172,14 +172,14 @@
   bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
   if ((isLittleEndian && mpHeader->endianness != 'e') ||
       (!isLittleEndian && mpHeader->endianness != 'E')) {
-    LOGE("Machine endianness mismatch.\n");
+    ALOGE("Machine endianness mismatch.\n");
     return false;
   }
 
   if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
       (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
       (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
-    LOGE("Machine integer size mismatch.\n");
+    ALOGE("Machine integer size mismatch.\n");
     return false;
   }
 
@@ -194,17 +194,17 @@
     off_t size = (off_t)mpHeader-> NAME##_size;                             \
                                                                             \
     if (mInfoFileSize < offset || mInfoFileSize < offset + size) {          \
-      LOGE(#NAME " section overflow.\n");                                   \
+      ALOGE(#NAME " section overflow.\n");                                   \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (offset % sizeof(int) != 0) {                                        \
-      LOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int));        \
+      ALOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int));        \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (size < static_cast<off_t>(sizeof(size_t))) {                        \
-      LOGE(#NAME " size is too small to be correct.\n");                    \
+      ALOGE(#NAME " size is too small to be correct.\n");                    \
       return false;                                                         \
     }                                                                       \
   } while (0)
@@ -221,7 +221,7 @@
   // TODO(logan): Move this to some where else.
   long pagesize = sysconf(_SC_PAGESIZE);
   if ((uintptr_t)mpHeader->context_cached_addr % pagesize != 0) {
-    LOGE("cached address is not aligned to pagesize.\n");
+    ALOGE("cached address is not aligned to pagesize.\n");
     return false;
   }
 
@@ -233,7 +233,7 @@
   TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size);                 \
                                                                             \
   if (!NAME##_raw) {                                                        \
-    LOGE("Unable to allocate for " #NAME "\n");                             \
+    ALOGE("Unable to allocate for " #NAME "\n");                             \
     return false;                                                           \
   }                                                                         \
                                                                             \
@@ -241,14 +241,14 @@
   AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
                                                                             \
   if (mInfoFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) {           \
-    LOGE("Unable to seek to " #NAME " section\n");                          \
+    ALOGE("Unable to seek to " #NAME " section\n");                          \
     return false;                                                           \
   }                                                                         \
                                                                             \
   if (mInfoFile->read(reinterpret_cast<char *>(NAME##_raw),                 \
                   mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
   {                                                                         \
-    LOGE("Unable to read " #NAME ".\n");                                    \
+    ALOGE("Unable to read " #NAME ".\n");                                    \
     return false;                                                           \
   }
 
@@ -276,7 +276,7 @@
   // Ensure that every c-style string is ended with '\0'
   for (size_t i = 0; i < poolR->count; ++i) {
     if (pool[i][poolR->list[i].length] != '\0') {
-      LOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
+      ALOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
       return false;
     }
   }
@@ -294,7 +294,7 @@
 
 bool CacheReader::checkDependency() {
   if (mDependencies.size() != mpCachedDependTable->count) {
-    LOGE("Dependencies count mismatch. (%lu vs %lu)\n",
+    ALOGE("Dependencies count mismatch. (%lu vs %lu)\n",
          (unsigned long)mDependencies.size(),
          (unsigned long)mpCachedDependTable->count);
     return false;
@@ -315,18 +315,18 @@
     unsigned char const *depCachedSHA1 = depCached->sha1;
 
     if (depName != depCachedName) {
-      LOGE("Cache dependency name mismatch:\n");
-      LOGE("  given:  %s\n", depName.c_str());
-      LOGE("  cached: %s\n", depCachedName);
+      ALOGE("Cache dependency name mismatch:\n");
+      ALOGE("  given:  %s\n", depName.c_str());
+      ALOGE("  cached: %s\n", depCachedName);
 
       return false;
     }
 
     if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
-      LOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
+      ALOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
 
 #define PRINT_SHA1(PREFIX, X, POSTFIX) \
-      LOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
+      ALOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
                   "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
            X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
            X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
@@ -340,7 +340,7 @@
     }
 
     if (depType != depCachedType) {
-      LOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
+      ALOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
       return false;
     }
   }
@@ -429,11 +429,11 @@
   }
 
   if (sum != 0) {
-    LOGE("Checksum check failed\n");
+    ALOGE("Checksum check failed\n");
     return false;
   }
 
-  LOGI("Passed checksum even parity verification.\n");
+  ALOGI("Passed checksum even parity verification.\n");
   return true;
 }
 
diff --git a/lib/ExecutionEngine/OldJIT/CacheWriter.cpp b/lib/ExecutionEngine/OldJIT/CacheWriter.cpp
index 4b53617..36bf281 100644
--- a/lib/ExecutionEngine/OldJIT/CacheWriter.cpp
+++ b/lib/ExecutionEngine/OldJIT/CacheWriter.cpp
@@ -85,7 +85,7 @@
   OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
 
   if (!header) {
-    LOGE("Unable to allocate for header.\n");
+    ALOGE("Unable to allocate for header.\n");
     return false;
   }
 
@@ -123,7 +123,7 @@
   OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
 
   if (!tab) {
-    LOGE("Unable to allocate for dependency table section.\n");
+    ALOGE("Unable to allocate for dependency table section.\n");
     return false;
   }
 
@@ -155,7 +155,7 @@
   OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
 
   if (!tab) {
-    LOGE("Unable to allocate for function table section.\n");
+    ALOGE("Unable to allocate for function table section.\n");
     return false;
   }
 
@@ -190,7 +190,7 @@
   OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for pragma list\n");
+    ALOGE("Unable to allocate for pragma list\n");
     return false;
   }
 
@@ -240,7 +240,7 @@
   OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
 
   if (!pool) {
-    LOGE("Unable to allocate string pool.\n");
+    ALOGE("Unable to allocate string pool.\n");
     return false;
   }
 
@@ -275,7 +275,7 @@
   OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for export variable list\n");
+    ALOGE("Unable to allocate for export variable list\n");
     return false;
   }
 
@@ -296,7 +296,7 @@
   OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for export function list\n");
+    ALOGE("Unable to allocate for export function list\n");
     return false;
   }
 
@@ -319,7 +319,7 @@
   OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
 
   if (!list) {
-    LOGE("Unable to allocate for object slot list\n");
+    ALOGE("Unable to allocate for object slot list\n");
     return false;
   }
 
@@ -380,13 +380,13 @@
 #define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
   do {                                                                      \
     if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) {                          \
-      LOGE("Unable to seek to " #NAME " section for writing.\n");           \
+      ALOGE("Unable to seek to " #NAME " section for writing.\n");           \
       return false;                                                         \
     }                                                                       \
                                                                             \
     if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=      \
         static_cast<ssize_t>(SIZE)) {                                       \
-      LOGE("Unable to write " #NAME " section to cache file.\n");           \
+      ALOGE("Unable to write " #NAME " section to cache file.\n");           \
       return false;                                                         \
     }                                                                       \
   } while (0)
@@ -416,7 +416,7 @@
   char const *context = (char const *)mpOwner->getContext();
   size_t context_size = ContextManager::ContextSize;
   if (mObjFile->write(context, context_size) != (ssize_t)context_size) {
-    LOGE("Unable to write context image to executable file\n");
+    ALOGE("Unable to write context image to executable file\n");
     return false;
   }
 
diff --git a/lib/ExecutionEngine/OldJIT/ContextManager.cpp b/lib/ExecutionEngine/OldJIT/ContextManager.cpp
index 4d13275..5dca382 100644
--- a/lib/ExecutionEngine/OldJIT/ContextManager.cpp
+++ b/lib/ExecutionEngine/OldJIT/ContextManager.cpp
@@ -62,17 +62,17 @@
                           MAP_PRIVATE | MAP_ANON, -1, 0);
 
       if (result == addr) {
-        LOGI("Allocate bcc context. addr=%p\n", result);
+        ALOGI("Allocate bcc context. addr=%p\n", result);
         mContextSlotOccupied[i] = true;
         return static_cast<char *>(result);
       }
 
       if (result && result != MAP_FAILED) {
-        LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
+        ALOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
         munmap(result, ContextSize);
       }
 
-      LOGE("Unable to allocate. addr=%p.  Retry ...\n", addr);
+      ALOGE("Unable to allocate. addr=%p.  Retry ...\n", addr);
     }
     // Release mContextSlotOccupiedLock
   }
@@ -82,11 +82,11 @@
                       MAP_PRIVATE | MAP_ANON, -1, 0);
 
   if (!result || result == MAP_FAILED) {
-    LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
+    ALOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
     return NULL;
   }
 
-  LOGI("Allocate bcc context. addr=%p\n", result);
+  ALOGI("Allocate bcc context. addr=%p\n", result);
   return static_cast<char *>(result);
 }
 
@@ -97,46 +97,46 @@
   // slot address.  And the image offset is aligned to the pagesize.
 
   if (imageFd < 0) {
-    LOGE("Invalid file descriptor for bcc context image\n");
+    ALOGE("Invalid file descriptor for bcc context image\n");
     return NULL;
   }
 
   unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
 
   if (imageOffset % pagesize > 0) {
-    LOGE("BCC context image offset is not aligned to page size\n");
+    ALOGE("BCC context image offset is not aligned to page size\n");
     return NULL;
   }
 
   ssize_t slot = getSlotIndexFromAddress(addr);
   if (slot < 0) {
-    LOGE("Suggested address is not a bcc context slot address\n");
+    ALOGE("Suggested address is not a bcc context slot address\n");
     return NULL;
   }
 
   llvm::MutexGuard Locked(mContextSlotOccupiedLock);
   if (mContextSlotOccupied[slot]) {
-    LOGW("Suggested bcc context slot has been occupied.\n");
+    ALOGW("Suggested bcc context slot has been occupied.\n");
     return NULL;
   }
 
-  // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
+  // ALOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
   void *result = mmap(addr, ContextSize,
                       PROT_READ | PROT_WRITE | PROT_EXEC,
                       MAP_PRIVATE, imageFd, imageOffset);
 
   if (!result || result == MAP_FAILED) {
-    LOGE("Unable to allocate. addr=%p\n", addr);
+    ALOGE("Unable to allocate. addr=%p\n", addr);
     return NULL;
   }
 
   if (result != addr) {
-    LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
+    ALOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
     munmap(result, ContextSize);
     return NULL;
   }
 
-  LOGI("Allocate bcc context. addr=%p\n", addr);
+  ALOGI("Allocate bcc context. addr=%p\n", addr);
   mContextSlotOccupied[slot] = true;
   return static_cast<char *>(result);
 }
@@ -149,11 +149,11 @@
 
   llvm::MutexGuard Locked(mContextSlotOccupiedLock);
 
-  LOGI("Deallocate bcc context. addr=%p\n", addr);
+  ALOGI("Deallocate bcc context. addr=%p\n", addr);
 
   // Unmap
   if (munmap(addr, ContextSize) < 0) {
-    LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
+    ALOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
     return;
   }
 
diff --git a/lib/ExecutionEngine/Runtime.c b/lib/ExecutionEngine/Runtime.c
index f940c35..6b9e20d 100644
--- a/lib/ExecutionEngine/Runtime.c
+++ b/lib/ExecutionEngine/Runtime.c
@@ -27,7 +27,7 @@
   void *mPtr;
 } RuntimeFunction;
 
-#if defined(__arm__)
+#if defined(__arm__) || defined(__mips__)
   #define DEF_GENERIC_RUNTIME(func)   \
     extern void *func;
   #define DEF_VFP_RUNTIME(func) \
@@ -38,7 +38,7 @@
 #endif
 
 static const RuntimeFunction gRuntimes[] = {
-#if defined(__arm__)
+#if defined(__arm__) || defined(__mips__)
   #define DEF_GENERIC_RUNTIME(func)   \
     { #func, (void*) &func },
   // TODO: enable only when target support VFP
diff --git a/lib/ExecutionEngine/Runtime.def b/lib/ExecutionEngine/Runtime.def
index e15aa11..e4a6875 100644
--- a/lib/ExecutionEngine/Runtime.def
+++ b/lib/ExecutionEngine/Runtime.def
@@ -93,9 +93,12 @@
 #if !defined(__i386__) && !defined(__SSE2__)
     DEF_LLVM_RUNTIME(__ashldi3)
 #endif
-#ifndef ANDROID // has one in bionic
+#if !defined(ANDROID) /* has one in bionic */
     DEF_LLVM_RUNTIME(__ashrdi3)
 #endif
+#if defined(__mips__)
+    DEF_GENERIC_RUNTIME(__ashrdi3)
+#endif
 
 #ifdef USE_VFP_RUNTIME
 //    DEF_GENERIC_RUNTIME(__bswapdi2)
@@ -108,7 +111,7 @@
 DEF_LLVM_RUNTIME(__ctzdi2)
 DEF_LLVM_RUNTIME(__ctzsi2)
 
-#ifndef ANDROID // no complex extension
+#if !defined(ANDROID) /* no complex extension */
     DEF_LLVM_RUNTIME(__divdc3)
 #endif
 
@@ -119,7 +122,7 @@
 #endif
 DEF_LLVM_RUNTIME(__divsi3)
 
-#ifndef ANDROID // no complex extension
+#if !defined(ANDROID) /* no complex extension */
     DEF_LLVM_RUNTIME(__divsc3)
 #endif
 
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 97d8803..14d38bf 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -1,5 +1,5 @@
 /*
- * copyright 2010, the android open source project
+ * copyright 2010-2012, the android open source project
  *
  * licensed under the apache license, version 2.0 (the "license");
  * you may not use this file except in compliance with the license.
@@ -25,6 +25,7 @@
 
 #include "MCCacheReader.h"
 #include "MCCacheWriter.h"
+#include "CompilerOption.h"
 
 #if USE_OLD_JIT
 #include "OldJIT/ContextManager.h"
@@ -89,19 +90,19 @@
 
   if (!resName) {
     mErrorCode = BCC_INVALID_VALUE;
-    LOGE("Invalid argument: resName = NULL\n");
+    ALOGE("Invalid argument: resName = NULL\n");
     return 1;
   }
 
   if (mStatus != ScriptStatus::Unknown) {
     mErrorCode = BCC_INVALID_OPERATION;
-    LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
     return 1;
   }
 
   if (!bitcode) {
     mErrorCode = BCC_INVALID_VALUE;
-    LOGE("Invalid argument: bitcode = NULL\n");
+    ALOGE("Invalid argument: bitcode = NULL\n");
     return 1;
   }
 
@@ -111,7 +112,7 @@
 
   if (!mSourceList[idx]) {
     mErrorCode = BCC_OUT_OF_MEMORY;
-    LOGE("Out of memory while adding source bitcode\n");
+    ALOGE("Out of memory while adding source bitcode\n");
     return 1;
   }
 
@@ -124,13 +125,13 @@
                             unsigned long flags) {
   if (mStatus != ScriptStatus::Unknown) {
     mErrorCode = BCC_INVALID_OPERATION;
-    LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
     return 1;
   }
 
   if (!module) {
     mErrorCode = BCC_INVALID_VALUE;
-    LOGE("Invalid argument: module = NULL\n");
+    ALOGE("Invalid argument: module = NULL\n");
     return 1;
   }
 
@@ -138,7 +139,7 @@
 
   if (!mSourceList[idx]) {
     mErrorCode = BCC_OUT_OF_MEMORY;
-    LOGE("Out of memory when add source module\n");
+    ALOGE("Out of memory when add source module\n");
     return 1;
   }
 
@@ -151,20 +152,20 @@
                           unsigned long flags) {
   if (mStatus != ScriptStatus::Unknown) {
     mErrorCode = BCC_INVALID_OPERATION;
-    LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
     return 1;
   }
 
   if (!path) {
     mErrorCode = BCC_INVALID_VALUE;
-    LOGE("Invalid argument: path = NULL\n");
+    ALOGE("Invalid argument: path = NULL\n");
     return 1;
   }
 
   struct stat sb;
   if (stat(path, &sb) != 0) {
     mErrorCode = BCC_INVALID_VALUE;
-    LOGE("File not found: %s\n", path);
+    ALOGE("File not found: %s\n", path);
     return 1;
   }
 
@@ -172,72 +173,69 @@
 
   if (!mSourceList[idx]) {
     mErrorCode = BCC_OUT_OF_MEMORY;
-    LOGE("Out of memory while adding source file\n");
+    ALOGE("Out of memory while adding source file\n");
     return 1;
   }
 
   return 0;
 }
 
-int Script::prepareSharedObject(char const *cacheDir,
-                                char const *cacheName,
-                                unsigned long flags) {
+int Script::prepareRelocatable(char const *cacheDir,
+                               char const *cacheName,
+                               llvm::Reloc::Model RelocModel,
+                               unsigned long flags) {
 #if USE_CACHE
-  if (cacheDir && cacheName) {
-    // Set Cache Directory and File Name
-    mCacheDir = cacheDir;
-    mCacheName = cacheName;
-
-    if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
-      mCacheDir.push_back('/'); // Ensure mCacheDir is end with '/'
-    }
-
-    // Check Cache File
-    if (internalLoadCache(true) == 0) {
-      return 0;
-    }
+  if (internalLoadCache(cacheDir, cacheName,
+                        ScriptObject::Relocatable, /* checkOnly */ true) == 0) {
+    return 0;
   }
 #endif
-  int status = internalCompile(true);
+
+  CompilerOption option;
+  option.RelocModelOpt = RelocModel;
+  option.LoadAfterCompile = false;
+  int status = internalCompile(option);
   if (status != 0) {
-    LOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+    ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
   }
   return status;
 }
 
 
+int Script::prepareSharedObject(char const *cacheDir,
+                                char const *cacheName,
+                                char const *objPath,
+                                char const *dsoPath,
+                                unsigned long flags) {
+  // TODO: Support cached shared object.
+  return 1;
+}
+
+
 int Script::prepareExecutable(char const *cacheDir,
                               char const *cacheName,
                               unsigned long flags) {
   if (mStatus != ScriptStatus::Unknown) {
     mErrorCode = BCC_INVALID_OPERATION;
-    LOGE("Invalid operation: %s\n", __func__);
+    ALOGE("Invalid operation: %s\n", __func__);
     return 1;
   }
 
   int status = -1;
 #if USE_CACHE
-  if (cacheDir && cacheName) {
-    // Set Cache Directory and File Name
-    mCacheDir = cacheDir;
-    mCacheName = cacheName;
-
-    if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
-      mCacheDir.push_back('/'); // Ensure mCacheDir is end with '/'
-    }
-
-    // Load Cache File
-    if (internalLoadCache(false) == 0) {
-      status = 0;
-    }
+  if (internalLoadCache(cacheDir, cacheName,
+                        ScriptObject::Executable, /* checkOnly */ false) == 0) {
+    status = 0;
   }
 #endif
 
-  if (status == -1) {
-    status = internalCompile(false);
-    if (status != 0) {
-      LOGE("LLVM error message: %s\n", getCompilerErrorMessage());
-    }
+  if (status != 0) {
+    CompilerOption option;
+    status = internalCompile(option);
+  }
+
+  if (status != 0) {
+    ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
   }
 
   // FIXME: Registration can be conditional on the presence of debug metadata
@@ -248,27 +246,30 @@
 }
 
 #if USE_CACHE
-int Script::internalLoadCache(bool checkOnly) {
-  if (getBooleanProp("debug.bcc.nocache")) {
-    // Android system environment property disable the cache mechanism by
-    // setting "debug.bcc.nocache".  So we will not load the cache file any
-    // way.
+int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
+                              ScriptObject::ObjectType objectType,
+                              bool checkOnly) {
+  mObjectType = objectType;
+
+  if ((cacheDir == NULL) || (cacheName == NULL)) {
     return 1;
   }
 
-  if (mCacheDir.empty() || mCacheName.empty()) {
-    // The application developer has not specify the cachePath, so
-    // we don't know where to open the cache file.
+  // Set cache file Name
+  mCacheName = cacheName;
+
+  // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
+  mCacheDir = cacheDir;
+  if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
+    mCacheDir.push_back('/');
+  }
+
+  if (!isCacheable()) {
     return 1;
   }
 
-#if USE_OLD_JIT
-  std::string objPath(mCacheDir + mCacheName + ".jit-image");
-  std::string infoPath(mCacheDir + mCacheName + ".oBCC"); // TODO: .info instead
-#elif USE_MCJIT
-  std::string objPath(mCacheDir + mCacheName + ".o");
-  std::string infoPath(mCacheDir + mCacheName + ".info");
-#endif
+  std::string objPath = getCachedObjectPath();
+  std::string infoPath = getCacheInfoPath();
 
   FileHandle objFile;
   if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
@@ -328,13 +329,13 @@
 }
 #endif
 
-int Script::internalCompile(bool compileOnly) {
+int Script::internalCompile(const CompilerOption &option) {
   // Create the ScriptCompiled object
   mCompiled = new (std::nothrow) ScriptCompiled(this);
 
   if (!mCompiled) {
     mErrorCode = BCC_OUT_OF_MEMORY;
-    LOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
+    ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
     return 1;
   }
 
@@ -346,36 +347,42 @@
                                       mpExtSymbolLookupFnContext);
   }
 
-  // Parse Bitcode File (if necessary)
-  for (size_t i = 0; i < 2; ++i) {
-    if (mSourceList[i] && mSourceList[i]->prepareModule(mCompiled) != 0) {
-      LOGE("Unable to parse bitcode for source[%lu]\n", (unsigned long)i);
+  if (!mSourceList[0]) {
+    ALOGE("Source bitcode is not set.\n");
+    return 1;
+  }
+
+  // Parse Source bitcode file (if necessary)
+  if (mSourceList[0]->prepareModule() != 0) {
+    ALOGE("Unable to setup source module\n");
+    return 1;
+  }
+
+  // Parse Library bitcode file (if necessary)
+  if (mSourceList[1]) {
+    if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
+      ALOGE("Unable to setup library module\n");
       return 1;
     }
   }
 
   // Set the main source module
-  if (!mSourceList[0] || !mSourceList[0]->getModule()) {
-    LOGE("Source bitcode is not setted.\n");
-    return 1;
-  }
-
-  if (mCompiled->readModule(mSourceList[0]->takeModule()) != 0) {
-    LOGE("Unable to read source module\n");
+  if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
+    ALOGE("Unable to read source module\n");
     return 1;
   }
 
   // Link the source module with the library module
   if (mSourceList[1]) {
-    if (mCompiled->linkModule(mSourceList[1]->takeModule()) != 0) {
-      LOGE("Unable to link library module\n");
+    if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
+      ALOGE("Unable to link library module\n");
       return 1;
     }
   }
 
   // Compile and JIT the code
-  if (mCompiled->compile(compileOnly) != 0) {
-    LOGE("Unable to compile.\n");
+  if (mCompiled->compile(option) != 0) {
+    ALOGE("Unable to compile.\n");
     return 1;
   }
 
@@ -386,22 +393,15 @@
   // Note: If the address of the context is not in the context slot, then
   // we don't have to cache it.
 
-  if (!mCacheDir.empty() &&
-      !mCacheName.empty() &&
+  if (
 #if USE_OLD_JIT
       !mIsContextSlotNotAvail &&
       ContextManager::get().isManagingContext(getContext()) &&
 #endif
-      !getBooleanProp("debug.bcc.nocache")) {
+      isCacheable()) {
 
-#if USE_OLD_JIT
-    std::string objPath(mCacheDir + mCacheName + ".jit-image");
-    std::string infoPath(mCacheDir + mCacheName + ".oBCC");
-#elif USE_MCJIT
-    std::string objPath(mCacheDir + mCacheName + ".o");
-    std::string infoPath(mCacheDir + mCacheName + ".info");
-#endif
-
+    std::string objPath = getCachedObjectPath();
+    std::string infoPath = getCacheInfoPath();
 
     // Remove the file if it already exists before writing the new file.
     // The old file may still be mapped elsewhere in memory and we do not want
@@ -450,7 +450,7 @@
         objFile.close();
 
         if (unlink(objPath.c_str()) != 0) {
-          LOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
                objPath.c_str(), strerror(errno));
         }
 
@@ -458,7 +458,7 @@
         infoFile.close();
 
         if (unlink(infoPath.c_str()) != 0) {
-          LOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
                infoPath.c_str(), strerror(errno));
         }
       }
@@ -538,6 +538,25 @@
 }
 
 
+size_t Script::getExportForEachCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportForEachCount();
+    }
+
+#if USE_CACHE
+    case ScriptStatus::Cached: {
+      return mCached->getExportForEachCount();
+    }
+#endif
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
 size_t Script::getPragmaCount() const {
   switch (mStatus) {
     case ScriptStatus::Compiled: {
@@ -660,6 +679,37 @@
   }
 }
 
+void Script::getExportForEachList(size_t funcListSize, void **funcList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                                 \
+      m##STATUS->getExportForEachList(funcListSize, funcList); \
+      break;
+
+#if USE_CACHE
+    DELEGATE(Cached);
+#endif
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportForEachNameList(forEachList);
+    }
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
 
 void Script::getPragmaList(size_t pragmaListSize,
                            char const **keyList,
@@ -757,12 +807,33 @@
 
   if (mStatus != ScriptStatus::Unknown) {
     mErrorCode = BCC_INVALID_OPERATION;
-    LOGE("Invalid operation: %s\n", __func__);
+    ALOGE("Invalid operation: %s\n", __func__);
     return 1;
   }
   return 0;
 }
 
+bool Script::isCacheable() const {
+#if USE_CACHE
+  if (getBooleanProp("debug.bcc.nocache")) {
+    // Android system environment property: Disables the cache mechanism by
+    // setting "debug.bcc.nocache".  So we will not load the cache file any
+    // way.
+    return false;
+  }
+
+  if (mCacheDir.empty() || mCacheName.empty()) {
+    // The application developer has not specified the cachePath, so
+    // we don't know where to open the cache file.
+    return false;
+  }
+
+  return true;
+#else
+  return false;
+#endif
+}
+
 #if USE_MCJIT
 size_t Script::getELFSize() const {
   switch (mStatus) {
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index ebe9f38..870d354 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
 
 #include "Compiler.h"
 
+#include <llvm/Support/CodeGen.h>
+
 #include <vector>
 #include <string>
 
@@ -36,6 +38,7 @@
   class ScriptCompiled;
   class ScriptCached;
   class SourceInfo;
+  struct CompilerOption;
 
   namespace ScriptStatus {
     enum StatusType {
@@ -47,11 +50,21 @@
     };
   }
 
+  namespace ScriptObject {
+    enum ObjectType {
+      Unknown,
+      Relocatable,
+      SharedObject,
+      Executable,
+    };
+  }
+
   class Script {
   private:
     int mErrorCode;
 
     ScriptStatus::StatusType mStatus;
+    ScriptObject::ObjectType mObjectType;
 
     union {
       ScriptCompiled *mCompiled;
@@ -63,6 +76,41 @@
 #if USE_CACHE
     std::string mCacheDir;
     std::string mCacheName;
+
+    inline std::string getCachedObjectPath() const {
+#if USE_OLD_JIT
+      return std::string(mCacheDir + mCacheName + ".jit-image");
+#elif USE_MCJIT
+      std::string objPath(mCacheDir + mCacheName);
+
+      // Append suffix depends on the object type
+      switch (mObjectType) {
+        case ScriptObject::Relocatable:
+        case ScriptObject::Executable: {
+          objPath.append(".o");
+          break;
+        }
+
+        case ScriptObject::SharedObject: {
+          objPath.append(".so");
+          break;
+        }
+
+        default: {
+          assert(false && "Unknown object type!");
+        }
+      }
+      return objPath;
+#endif
+    }
+
+    inline std::string getCacheInfoPath() const {
+#if USE_OLD_JIT
+      return getCachedObjectPath().append(".oBCC");
+#elif USE_MCJIT
+      return getCachedObjectPath().append(".info");
+#endif
+    }
 #endif
 
     bool mIsContextSlotNotAvail;
@@ -82,7 +130,7 @@
 
   public:
     Script() : mErrorCode(BCC_NO_ERROR), mStatus(ScriptStatus::Unknown),
-               mIsContextSlotNotAvail(false),
+               mObjectType(ScriptObject::Unknown), mIsContextSlotNotAvail(false),
                mpExtSymbolLookupFn(NULL), mpExtSymbolLookupFnContext(NULL) {
       Compiler::GlobalInitialization();
 
@@ -118,9 +166,31 @@
                           char const *cacheName,
                           unsigned long flags);
 
+    /*
+     * Link the given bitcodes in mSourceList to shared object (.so).
+     *
+     * Currently, it requires one to provide the relocatable object files with
+     * given bitcodes to output a shared object.
+     *
+     * The usage of this function is flexible. You can have a relocatable object
+     * compiled before and pass it in objPath to generate shared object. If the
+     * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
+     * you haven't done that yet) and then link the output relocatable object
+     * file. The latter case will have libbcc compile with USE_CACHE enabled.
+     *
+     * TODO: Currently, we only support to link the bitcodes in mSourceList[0].
+     *
+     */
     int prepareSharedObject(char const *cacheDir,
-                          char const *cacheName,
-                          unsigned long flags);
+                            char const *cacheName,
+                            char const *objPath,
+                            char const *dsoPath,
+                            unsigned long flags);
+
+    int prepareRelocatable(char const *cacheDir,
+                           char const *cacheName,
+                           llvm::Reloc::Model RelocModel,
+                           unsigned long flags);
 
     char const *getCompilerErrorMessage();
 
@@ -131,6 +201,8 @@
 
     size_t getExportFuncCount() const;
 
+    size_t getExportForEachCount() const;
+
     size_t getPragmaCount() const;
 
     size_t getFuncCount() const;
@@ -141,10 +213,14 @@
 
     void getExportFuncList(size_t size, void **list);
 
+    void getExportForEachList(size_t size, void **list);
+
     void getExportVarNameList(std::vector<std::string> &list);
 
     void getExportFuncNameList(std::vector<std::string> &list);
 
+    void getExportForEachNameList(std::vector<std::string> &list);
+
     void getPragmaList(size_t size,
                        char const **keyList,
                        char const **valueList);
@@ -163,6 +239,7 @@
     char *getContext();
 #endif
 
+    bool isCacheable() const;
 
     void setError(int error) {
       if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
@@ -178,9 +255,14 @@
 
   private:
 #if USE_CACHE
-    int internalLoadCache(bool checkOnly);
+    //
+    // It returns 0 if there's a cache hit.
+    //
+    // Side effect: it will set mCacheDir, mCacheName and mObjectType.
+    int internalLoadCache(char const *cacheDir, char const *cacheName,
+                          ScriptObject::ObjectType objectType, bool checkOnly);
 #endif
-    int internalCompile(bool compileOnly);
+    int internalCompile(const CompilerOption&);
   };
 
 } // namespace bcc
diff --git a/lib/ExecutionEngine/ScriptCached.cpp b/lib/ExecutionEngine/ScriptCached.cpp
index a7d21f7..30fc3fd 100644
--- a/lib/ExecutionEngine/ScriptCached.cpp
+++ b/lib/ExecutionEngine/ScriptCached.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
   if (mpStringPoolRaw) { free(mpStringPoolRaw); }
   if (mpExportVars) { free(mpExportVars); }
   if (mpExportFuncs) { free(mpExportFuncs); }
+  if (mpExportForEach) { free(mpExportForEach); }
   if (mpObjectSlotList) { free(mpObjectSlotList); }
 }
 
@@ -72,6 +73,21 @@
 }
 
 
+void ScriptCached::getExportForEachList(size_t forEachListSize,
+                                        void **forEachList) {
+  if (forEachList) {
+    size_t forEachCount = getExportForEachCount();
+
+    if (forEachCount > forEachListSize) {
+      forEachCount = forEachListSize;
+    }
+
+    memcpy(forEachList, mpExportForEach->cached_addr_list,
+           sizeof(void *) * forEachCount);
+  }
+}
+
+
 void ScriptCached::getPragmaList(size_t pragmaListSize,
                                  char const **keyList,
                                  char const **valueList) {
diff --git a/lib/ExecutionEngine/ScriptCached.h b/lib/ExecutionEngine/ScriptCached.h
index 2ee211a..f18cb88 100644
--- a/lib/ExecutionEngine/ScriptCached.h
+++ b/lib/ExecutionEngine/ScriptCached.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -61,6 +61,7 @@
 
     OBCC_ExportVarList *mpExportVars;
     OBCC_ExportFuncList *mpExportFuncs;
+    OBCC_ExportForEachList *mpExportForEach;
     PragmaList mPragmas;
     OBCC_ObjectSlotList *mpObjectSlotList;
 
@@ -85,6 +86,7 @@
       : mpOwner(owner),
         mpExportVars(NULL),
         mpExportFuncs(NULL),
+        mpExportForEach(NULL),
         mpObjectSlotList(NULL),
 #if USE_OLD_JIT
         mContext(NULL),
@@ -106,6 +108,10 @@
       return mpExportFuncs->count;
     }
 
+    size_t getExportForEachCount() const {
+      return mpExportForEach->count;
+    }
+
     size_t getPragmaCount() const {
       return mPragmas.size();
     }
@@ -122,6 +128,8 @@
 
     void getExportFuncList(size_t funcListSize, void **funcList);
 
+    void getExportForEachList(size_t forEachListSize, void **forEachList);
+
     void getPragmaList(size_t pragmaListSize,
                        char const **keyList,
                        char const **valueList);
diff --git a/lib/ExecutionEngine/ScriptCompiled.cpp b/lib/ExecutionEngine/ScriptCompiled.cpp
index bb3c79a..47f2bb4 100644
--- a/lib/ExecutionEngine/ScriptCompiled.cpp
+++ b/lib/ExecutionEngine/ScriptCompiled.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -67,6 +67,11 @@
 }
 
 
+void ScriptCompiled::getExportForEachNameList(std::vector<std::string> &forEachList) {
+  forEachList = mExportForEachName;
+}
+
+
 void ScriptCompiled::getExportFuncList(size_t funcListSize, void **funcList) {
   if (funcList) {
     size_t funcCount = getExportFuncCount();
@@ -84,6 +89,24 @@
 }
 
 
+void ScriptCompiled::getExportForEachList(size_t forEachListSize,
+                                          void **forEachList) {
+  if (forEachList) {
+    size_t forEachCount = getExportForEachCount();
+
+    if (forEachCount > forEachListSize) {
+      forEachCount = forEachListSize;
+    }
+
+    for (ExportForEachList::const_iterator
+         I = mExportForEach.begin(), E = mExportForEach.end();
+         I != E && forEachCount > 0; ++I, --forEachCount) {
+      *forEachList++ = *I;
+    }
+  }
+}
+
+
 void ScriptCompiled::getPragmaList(size_t pragmaListSize,
                                    char const **keyList,
                                    char const **valueList) {
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 6a1a9e8..4498f1a 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@
 }
 
 namespace bcc {
+  struct CompilerOption;
+
   class ScriptCompiled {
     friend class Compiler;
     friend class CodeEmitter;
@@ -41,6 +43,7 @@
     typedef std::list<std::pair<std::string, std::string> > PragmaList;
     typedef std::list<void*> ExportVarList;
     typedef std::list<void*> ExportFuncList;
+    typedef std::list<void*> ExportForEachList;
     typedef std::map<std::string, FuncInfo *> FuncInfoMap;
     typedef std::list<uint32_t> ObjectSlotList;
 
@@ -53,8 +56,10 @@
 
     std::vector<std::string> mExportVarsName;
     std::vector<std::string> mExportFuncsName;
+    std::vector<std::string> mExportForEachName;
 
     ExportFuncList mExportFuncs;
+    ExportForEachList mExportForEach;
     PragmaList mPragmas;
     ObjectSlotList mObjectSlots;
 
@@ -75,10 +80,6 @@
 
     ~ScriptCompiled();
 
-    llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM) {
-      return mCompiler.parseBitcodeFile(MEM);
-    }
-
     int readModule(llvm::Module *module) {
       return mCompiler.readModule(module);
     }
@@ -87,8 +88,8 @@
       return mCompiler.linkModule(module);
     }
 
-    int compile(bool compileOnly) {
-      return mCompiler.compile(compileOnly);
+    int compile(const CompilerOption &option) {
+      return mCompiler.compile(option);
     }
 
     char const *getCompilerErrorMessage() {
@@ -106,6 +107,10 @@
       return mExportFuncs.size();
     }
 
+    size_t getExportForEachCount() const {
+      return mExportForEach.size();
+    }
+
     size_t getPragmaCount() const {
       return mPragmas.size();
     }
@@ -122,10 +127,14 @@
 
     void getExportFuncList(size_t funcListSize, void **funcList);
 
+    void getExportForEachList(size_t forEachListSize, void **forEachList);
+
     void getExportVarNameList(std::vector<std::string> &varList);
 
     void getExportFuncNameList(std::vector<std::string> &funcList);
 
+    void getExportForEachNameList(std::vector<std::string> &forEachList);
+
     void getPragmaList(size_t pragmaListSize,
                        char const **keyList,
                        char const **valueList);
diff --git a/lib/ExecutionEngine/Sha1Helper.cpp b/lib/ExecutionEngine/Sha1Helper.cpp
index 1ef717a..0acd6b8 100644
--- a/lib/ExecutionEngine/Sha1Helper.cpp
+++ b/lib/ExecutionEngine/Sha1Helper.cpp
@@ -53,7 +53,7 @@
   FileHandle file;
 
   if (file.open(filename, OpenMode::Read) < 0) {
-    LOGE("Unable to calculate the sha1 checksum of %s\n", filename);
+    ALOGE("Unable to calculate the sha1 checksum of %s\n", filename);
     memset(result, '\0', 20);
     return;
   }
@@ -85,7 +85,7 @@
 void readSHA1(unsigned char *result, int result_size, char const *filename) {
   FileHandle file;
   if (file.open(filename, OpenMode::Read) < 0) {
-    LOGE("Unable to read binary sha1 file %s\n", filename);
+    ALOGE("Unable to read binary sha1 file %s\n", filename);
     memset(result, '\0', result_size);
     return;
   }
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
index 32992d8..9c49fcc 100644
--- a/lib/ExecutionEngine/SourceInfo.cpp
+++ b/lib/ExecutionEngine/SourceInfo.cpp
@@ -34,6 +34,9 @@
 #include <bcc/bcc.h>
 #include <bcc/bcc_cache.h>
 
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Module.h>
+#include <llvm/LLVMContext.h>
 #include <llvm/ADT/OwningPtr.h>
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Support/MemoryBuffer.h>
@@ -65,9 +68,9 @@
   if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
     result->flags |= BCC_SKIP_DEP_SHA1;
 
-    LOGW("It is required to give resName for sha1 dependency check.\n");
-    LOGW("Sha1sum dependency check will be skipped.\n");
-    LOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+    ALOGW("It is required to give resName for sha1 dependency check.\n");
+    ALOGW("Sha1sum dependency check will be skipped.\n");
+    ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
   }
 
   if (result->flags & BCC_SKIP_DEP_SHA1) {
@@ -114,16 +117,16 @@
   }
 
   result->type = SourceKind::Module;
-  result->module.reset(module);
+  result->module = module;
   result->flags = flags;
 
 #if USE_CACHE
   if (! (flags & BCC_SKIP_DEP_SHA1)) {
     result->flags |= BCC_SKIP_DEP_SHA1;
 
-    LOGW("Unable to calculate sha1sum for llvm::Module.\n");
-    LOGW("Sha1sum dependency check will be skipped.\n");
-    LOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+    ALOGW("Unable to calculate sha1sum for llvm::Module.\n");
+    ALOGW("Sha1sum dependency check will be skipped.\n");
+    ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
   }
 
   memset(result->sha1, '\0', 20);
@@ -133,44 +136,63 @@
 }
 
 
-int SourceInfo::prepareModule(ScriptCompiled *SC) {
+int SourceInfo::prepareModule(llvm::LLVMContext *context) {
+  if (module)
+    return 0;
+
+  llvm::OwningPtr<llvm::MemoryBuffer> mem;
+  std::string errmsg;
+
   switch (type) {
   case SourceKind::Buffer:
     {
-      llvm::OwningPtr<llvm::MemoryBuffer> MEM(
-        llvm::MemoryBuffer::getMemBuffer(
+      mem.reset(llvm::MemoryBuffer::getMemBuffer(
           llvm::StringRef(buffer.bitcode, buffer.bitcodeSize)));
 
-      if (!MEM.get()) {
-        LOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
-             buffer.bitcode, (unsigned long)buffer.bitcodeSize);
+      if (!mem.get()) {
+        ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
+              buffer.bitcode, (unsigned long)buffer.bitcodeSize);
         return 1;
       }
-
-      module.reset(SC->parseBitcodeFile(MEM.get()));
     }
     break;
 
   case SourceKind::File:
     {
-      llvm::OwningPtr<llvm::MemoryBuffer> MEM;
-
-      if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, MEM)) {
-        LOGE("Unable to MemoryBuffer::getFile(path=%s)\n", file.path);
+      if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) {
+        ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n",
+              file.path, ec.message().c_str());
         return 1;
       }
-
-      module.reset(SC->parseBitcodeFile(MEM.get()));
     }
     break;
 
   default:
+    return 0;
     break;
   }
 
-  return (module.get()) ? 0 : 1;
+  if (context)
+    shared_context = true;
+  else
+    context = new llvm::LLVMContext();
+
+  module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg);
+  if (module == NULL) {
+    ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
+    if (!shared_context)
+      delete context;
+  }
+
+  return (module == NULL);
 }
 
+SourceInfo::~SourceInfo() {
+  llvm::LLVMContext *context = &module->getContext();
+  delete module;
+  if (!shared_context)
+    delete context;
+}
 
 #if USE_CACHE
 template <typename T> void SourceInfo::introDependency(T &checker) {
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
index b6a4c54..9026f1c 100644
--- a/lib/ExecutionEngine/SourceInfo.h
+++ b/lib/ExecutionEngine/SourceInfo.h
@@ -19,14 +19,15 @@
 
 #include "Config.h"
 
-#include <llvm/ADT/OwningPtr.h>
 #include <llvm/Module.h>
 
 #include <stddef.h>
 
-namespace bcc {
-  class ScriptCompiled;
+namespace llvm {
+  class LLVMContext;
+}
 
+namespace bcc {
   namespace SourceKind {
     enum SourceType {
       File,
@@ -39,9 +40,12 @@
   private:
     SourceKind::SourceType type;
 
-    llvm::OwningPtr<llvm::Module> module;
     // Note: module should not be a part of union.  Since, we are going to
     // use module to store the pointer to parsed bitcode.
+    llvm::Module *module;
+    // If true, the LLVM context behind the module is shared with others.
+    // Therefore, don't try to destroy the context it when destroy the module.
+    bool shared_context;
 
     union {
       struct {
@@ -62,7 +66,7 @@
 #endif
 
   private:
-    SourceInfo() { }
+    SourceInfo() : module(NULL), shared_context(false) { }
 
   public:
     static SourceInfo *createFromBuffer(char const *resName,
@@ -76,19 +80,22 @@
     static SourceInfo *createFromModule(llvm::Module *module,
                                         unsigned long flags);
 
-    llvm::Module *takeModule() {
-      return module.take();
+    inline llvm::Module *getModule() const {
+      return module;
     }
 
-    llvm::Module *getModule() const {
-      return module.get();
+    inline llvm::LLVMContext *getContext() const {
+      return (module) ? &module->getContext() : NULL;
     }
 
-    int prepareModule(ScriptCompiled *);
+    // Share with the given context if it's provided.
+    int prepareModule(llvm::LLVMContext *context = NULL);
 
 #if USE_CACHE
     template <typename T> void introDependency(T &checker);
 #endif
+
+    ~SourceInfo();
   };
 
 
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index fc8b92b..6a20105 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@
 
 #include <utils/StopWatch.h>
 
+#include <llvm/Support/CodeGen.h>
+
 using namespace bcc;
 
 namespace llvm {
@@ -40,8 +42,8 @@
 
 static void bccPrintBuildStamp() {
   if (!bccBuildStampPrinted) {
-    LOGI("LIBBCC build time: %s", bccGetBuildTime());
-    LOGI("LIBBCC build revision: %s", bccGetBuildRev());
+    ALOGI("LIBBCC build time: %s", bccGetBuildTime());
+    ALOGI("LIBBCC build revision: %s", bccGetBuildRev());
     bccBuildStampPrinted = true;
   }
 }
@@ -123,11 +125,50 @@
 }
 
 
+extern "C" int bccPrepareRelocatable(BCCScriptRef script,
+                                     char const *cacheDir,
+                                     char const *cacheName,
+                                     bccRelocModelEnum RelocModel,
+                                     unsigned long flags) {
+  BCC_FUNC_LOGGER();
+  llvm::Reloc::Model RM;
+
+  switch (RelocModel) {
+    case bccRelocDefault: {
+      RM = llvm::Reloc::Default;
+      break;
+    }
+    case bccRelocStatic: {
+      RM = llvm::Reloc::Static;
+      break;
+    }
+    case bccRelocPIC: {
+      RM = llvm::Reloc::PIC_;
+      break;
+    }
+    case bccRelocDynamicNoPIC: {
+      RM = llvm::Reloc::DynamicNoPIC;
+      break;
+    }
+    default: {
+      ALOGE("Unrecognized relocation model for bccPrepareObject!");
+      return BCC_INVALID_VALUE;
+    }
+  }
+
+  return unwrap(script)->prepareRelocatable(cacheDir, cacheName, RM, flags);
+}
+
+
 extern "C" int bccPrepareSharedObject(BCCScriptRef script,
                                       char const *cacheDir,
                                       char const *cacheName,
+                                      char const *objPath,
+                                      char const *dsoPath,
                                       unsigned long flags) {
-  return unwrap(script)->prepareSharedObject(cacheDir, cacheName, flags);
+  BCC_FUNC_LOGGER();
+  return unwrap(script)->prepareSharedObject(cacheDir, cacheName,
+                                             objPath, dsoPath, flags);
 }
 
 
@@ -149,7 +190,7 @@
   void *addr = unwrap(script)->lookup(funcname);
 
 #if DEBUG_BCC_REFLECT
-  LOGD("Function Address: %s --> %p\n", funcname, addr);
+  ALOGD("Function Address: %s --> %p\n", funcname, addr);
 #endif
 
   return addr;
@@ -166,14 +207,14 @@
 
 #if DEBUG_BCC_REFLECT
     size_t count = unwrap(script)->getExportVarCount();
-    LOGD("ExportVarCount = %lu\n", (unsigned long)count);
+    ALOGD("ExportVarCount = %lu\n", (unsigned long)count);
 
     if (count > varListSize) {
       count = varListSize;
     }
 
     for (size_t i = 0; i < count; ++i) {
-      LOGD("ExportVarList[%lu] = %p\n", (unsigned long)i, varList[i]);
+      ALOGD("ExportVarList[%lu] = %p\n", (unsigned long)i, varList[i]);
     }
 #endif
   }
@@ -190,16 +231,39 @@
 
 #if DEBUG_BCC_REFLECT
     size_t count = unwrap(script)->getExportFuncCount();
-    LOGD("ExportFuncCount = %lu\n", (unsigned long)count);
+    ALOGD("ExportFuncCount = %lu\n", (unsigned long)count);
 
     if (count > funcListSize) {
       count = funcListSize;
     }
 
     for (size_t i = 0; i < count; ++i) {
-      LOGD("ExportFuncList[%lu] = %p\n", (unsigned long)i, funcList[i]);
+      ALOGD("ExportFuncList[%lu] = %p\n", (unsigned long)i, funcList[i]);
     }
 #endif
   }
 }
 
+
+extern "C" void bccGetExportForEachList(BCCScriptRef script,
+                                        size_t forEachListSize,
+                                        void **forEachList) {
+  BCC_FUNC_LOGGER();
+
+  if (forEachList) {
+    unwrap(script)->getExportForEachList(forEachListSize, forEachList);
+
+#if DEBUG_BCC_REFLECT
+    size_t count = unwrap(script)->getExportForEachCount();
+    ALOGD("ExportForEachCount = %lu\n", (unsigned long)count);
+
+    if (count > forEachListSize) {
+      count = forEachListSize;
+    }
+
+    for (size_t i = 0; i < count; ++i) {
+      ALOGD("ExportForEachList[%lu] = %p\n", (unsigned long)i, forEachList[i]);
+    }
+#endif
+  }
+}
diff --git a/lib/ScriptCRT/Android.mk b/lib/ScriptCRT/Android.mk
index 7cbcb98..8b223f0 100644
--- a/lib/ScriptCRT/Android.mk
+++ b/lib/ScriptCRT/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright (C) 2011-2012 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -21,30 +21,50 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
 
-LOCAL_SRC_FILES := \
+# C source files for the library
+clcore_c_files := \
     rs_cl.c \
     rs_core.c
 
+# Hand-written bitcode for the library
+clcore_ll_files := \
+    clamp.ll \
+    convert.ll \
+    matrix.ll \
+    pixel_packing.ll
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
 clcore_CLANG := $(HOST_OUT_EXECUTABLES)/clang$(HOST_EXECUTABLE_SUFFIX)
 clcore_LLVM_LINK := $(HOST_OUT_EXECUTABLES)/llvm-link$(HOST_EXECUTABLE_SUFFIX)
+clcore_LLVM_LD := $(HOST_OUT_EXECUTABLES)/llvm-ld$(HOST_EXECUTABLE_SUFFIX)
+clcore_LLVM_AS := $(HOST_OUT_EXECUTABLES)/llvm-as$(HOST_EXECUTABLE_SUFFIX)
+clcore_LLVM_DIS := $(HOST_OUT_EXECUTABLES)/llvm-dis$(HOST_EXECUTABLE_SUFFIX)
 
-clcore_bc_files := $(patsubst %.c,%.bc, \
-    $(addprefix $(intermediates)/, $(LOCAL_SRC_FILES)))
+clcore_c_bc_files := $(patsubst %.c,%.bc, \
+    $(addprefix $(intermediates)/, $(clcore_c_files)))
 
-$(clcore_bc_files): PRIVATE_INCLUDES := \
+clcore_ll_bc_files := $(patsubst %.ll,%.bc, \
+    $(addprefix $(intermediates)/, $(clcore_ll_files)))
+
+$(clcore_c_bc_files): PRIVATE_INCLUDES := \
     frameworks/base/libs/rs/scriptc \
     external/clang/lib/Headers
 
-$(clcore_bc_files): $(intermediates)/%.bc: $(LOCAL_PATH)/%.c  $(clcore_CLANG)
+$(clcore_c_bc_files): $(intermediates)/%.bc: $(LOCAL_PATH)/%.c  $(clcore_CLANG)
 	@mkdir -p $(dir $@)
-	$(hide) $(clcore_CLANG) $(addprefix -I, $(PRIVATE_INCLUDES)) -MD -std=c99 -c -O3 -fno-builtin -emit-llvm -ccc-host-triple armv7-none-linux-gnueabi $< -o $@
+	$(hide) $(clcore_CLANG) $(addprefix -I, $(PRIVATE_INCLUDES)) -MD -std=c99 -c -O3 -fno-builtin -emit-llvm -ccc-host-triple armv7-none-linux-gnueabi -fsigned-char $< -o $@
 
--include $(clcore_bc_files:%.bc=%.d)
+$(clcore_ll_bc_files): $(intermediates)/%.bc: $(LOCAL_PATH)/%.ll $(clcore_LLVM_AS)
+	@mkdir -p $(dir $@)
+	$(hide) $(clcore_LLVM_AS) $< -o $@
 
-$(LOCAL_BUILT_MODULE): PRIVATE_BC_FILES := $(clcore_bc_files)
-$(LOCAL_BUILT_MODULE) : $(clcore_bc_files) $(clcore_LLVM_LINK)
+-include $(clcore_c_bc_files:%.bc=%.d)
+-include $(clcore_ll_bc_files:%.bc=%.d)
+
+$(LOCAL_BUILT_MODULE): PRIVATE_BC_FILES := $(clcore_c_bc_files) $(clcore_ll_bc_files)
+$(LOCAL_BUILT_MODULE): $(clcore_c_bc_files) $(clcore_ll_bc_files)
+$(LOCAL_BUILT_MODULE): $(clcore_LLVM_LINK) $(clcore_LLVM_LD)
+$(LOCAL_BUILT_MODULE): $(clcore_LLVM_AS) $(clcore_LLVM_DIS)
 	@mkdir -p $(dir $@)
 	$(hide) $(clcore_LLVM_LINK) $(PRIVATE_BC_FILES) -o $@
diff --git a/lib/ScriptCRT/clamp.ll b/lib/ScriptCRT/clamp.ll
new file mode 100644
index 0000000..f4d58ec
--- /dev/null
+++ b/lib/ScriptCRT/clamp.ll
@@ -0,0 +1,16 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+define i32 @_Z7rsClampjjj(i32 %amount, i32 %low, i32 %high) nounwind readnone alwaysinline {
+  %1 = icmp ult i32 %amount, %low
+  br i1 %1, label %5, label %2
+
+; <label>:2                                       ; preds = %0
+  %3 = icmp ugt i32 %amount, %high
+  %4 = select i1 %3, i32 %high, i32 %amount
+  br label %5
+
+; <label>:5                                       ; preds = %2, %0
+  %6 = phi i32 [ %4, %2 ], [ %low, %0 ]
+  ret i32 %6
+}
diff --git a/lib/ScriptCRT/convert.ll b/lib/ScriptCRT/convert.ll
new file mode 100644
index 0000000..e590ad1
--- /dev/null
+++ b/lib/ScriptCRT/convert.ll
@@ -0,0 +1,256 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+define <2 x float> @_Z14convert_float2Dv2_h(<2 x i8> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <2 x i8> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_h(<3 x i8> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <3 x i8> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_h(<4 x i8> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <4 x i8> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_c(<2 x i8> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <2 x i8> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_c(<3 x i8> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <3 x i8> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_c(<4 x i8> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <4 x i8> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_t(<2 x i16> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <2 x i16> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_t(<3 x i16> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <3 x i16> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_t(<4 x i16> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <4 x i16> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_s(<2 x i16> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <2 x i16> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_s(<3 x i16> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <3 x i16> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_s(<4 x i16> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <4 x i16> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_j(<2 x i32> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <2 x i32> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_j(<3 x i32> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <3 x i32> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_j(<4 x i32> %in) nounwind readnone alwaysinline {
+  %1 = uitofp <4 x i32> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_i(<2 x i32> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <2 x i32> %in to <2 x float>
+  ret <2 x float> %1
+}
+
+define <3 x float> @_Z14convert_float3Dv3_i(<3 x i32> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <3 x i32> %in to <3 x float>
+  ret <3 x float> %1
+}
+
+define <4 x float> @_Z14convert_float4Dv4_i(<4 x i32> %in) nounwind readnone alwaysinline {
+  %1 = sitofp <4 x i32> %in to <4 x float>
+  ret <4 x float> %1
+}
+
+define <2 x float> @_Z14convert_float2Dv2_f(<2 x float> %in) nounwind readnone alwaysinline {
+  ret <2 x float> %in
+}
+
+define <3 x float> @_Z14convert_float3Dv3_f(<3 x float> %in) nounwind readnone alwaysinline {
+  ret <3 x float> %in
+}
+
+define <4 x float> @_Z14convert_float4Dv4_f(<4 x float> %in) nounwind readnone alwaysinline {
+  ret <4 x float> %in
+}
+
+;---
+
+define <4 x i8> @_Z14convert_uchar4Dv4_f(<4 x float> %in) nounwind readnone alwaysinline {
+  %1 = fptoui <4 x float> %in to <4 x i32>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i8> %5
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_f(<3 x float> %in) nounwind readnone alwaysinline {
+  %in2 = shufflevector <3 x float> %in, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %1 = fptoui <4 x float> %in2 to <4 x i32>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x i8> %5
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_f(<2 x float> %in) nounwind readnone alwaysinline {
+  %in2 = shufflevector <2 x float> %in, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %1 = fptoui <4 x float> %in2 to <4 x i32>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i8> %5
+}
+
+define <4 x i8> @_Z14convert_uchar4Dv4_h(<4 x i8> %in) nounwind readnone alwaysinline {
+  ret <4 x i8> %in
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_h(<3 x i8> %in) nounwind readnone alwaysinline {
+  ret <3 x i8> %in
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_h(<2 x i8> %in) nounwind readnone alwaysinline {
+  ret <2 x i8> %in
+}
+
+define <4 x i8> @_Z14convert_uchar4Dv4_c(<4 x i8> %in) nounwind readnone alwaysinline {
+  ret <4 x i8> %in
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_c(<3 x i8> %in) nounwind readnone alwaysinline {
+  ret <3 x i8> %in
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_c(<2 x i8> %in) nounwind readnone alwaysinline {
+  ret <2 x i8> %in
+}
+
+
+define <4 x i8> @_Z14convert_uchar4Dv4_t(<4 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <4 x i16> %in, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i8> %3
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_t(<3 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <3 x i16> %in, <3 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 5, i32 5>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x i8> %3
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_t(<2 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <2 x i16> %in, <2 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i8> %3
+}
+
+define <4 x i8> @_Z14convert_uchar4Dv4_s(<4 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <4 x i16> %in, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i8> %3
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_s(<3 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <3 x i16> %in, <3 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 5, i32 5>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x i8> %3
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_s(<2 x i16> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <2 x i16> %in, <2 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
+  %2 = trunc <8 x i16> %1 to <8 x i8>
+  %3 = shufflevector <8 x i8> %2, <8 x i8> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i8> %3
+}
+
+
+define <4 x i8> @_Z14convert_uchar4Dv4_j(<4 x i32> %in) nounwind readnone alwaysinline {
+  %1 = trunc <4 x i32> %in to <4 x i16>
+  %2 = shufflevector <4 x i16> %1, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %3 = trunc <8 x i16> %2 to <8 x i8>
+  %4 = shufflevector <8 x i8> %3, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i8> %4
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_j(<3 x i32> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <3 x i32> %in, <3 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x i8> %5
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_j(<2 x i32> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <2 x i32> %in, <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i8> %5
+}
+
+define <4 x i8> @_Z14convert_uchar4Dv4_i(<4 x i32> %in) nounwind readnone alwaysinline {
+  %1 = trunc <4 x i32> %in to <4 x i16>
+  %2 = shufflevector <4 x i16> %1, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %3 = trunc <8 x i16> %2 to <8 x i8>
+  %4 = shufflevector <8 x i8> %3, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i8> %4
+}
+
+define <3 x i8> @_Z14convert_uchar3Dv3_i(<3 x i32> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <3 x i32> %in, <3 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x i8> %5
+}
+
+define <2 x i8> @_Z14convert_uchar2Dv2_i(<2 x i32> %in) nounwind readnone alwaysinline {
+  %1 = shufflevector <2 x i32> %in, <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = trunc <4 x i32> %1 to <4 x i16>
+  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %4 = trunc <8 x i16> %3 to <8 x i8>
+  %5 = shufflevector <8 x i8> %4, <8 x i8> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i8> %5
+}
+
diff --git a/lib/ScriptCRT/matrix.ll b/lib/ScriptCRT/matrix.ll
new file mode 100644
index 0000000..e559d99
--- /dev/null
+++ b/lib/ScriptCRT/matrix.ll
@@ -0,0 +1,176 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+
+%struct.rs_matrix4x4 = type { [16 x float] }
+%struct.rs_matrix3x3 = type { [9 x float] }
+%struct.rs_matrix2x2 = type { [4 x float] }
+
+define internal <4 x float> @smear_f(float %in) nounwind readnone alwaysinline {
+  %1 = insertelement <4 x float> undef, float %in, i32 0
+  %2 = insertelement <4 x float> %1, float %in, i32 1
+  %3 = insertelement <4 x float> %2, float %in, i32 2
+  %4 = insertelement <4 x float> %3, float %in, i32 3
+  ret <4 x float> %4
+}
+
+
+define <3 x float> @_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv3_f(%struct.rs_matrix3x3* nocapture %m, <3 x float> %in) nounwind readonly {
+  %x0 = extractelement <3 x float> %in, i32 0
+  %x = tail call <4 x float> @smear_f(float %x0) nounwind readnone
+  %y0 = extractelement <3 x float> %in, i32 1
+  %y = tail call <4 x float> @smear_f(float %y0) nounwind readnone
+  %z0 = extractelement <3 x float> %in, i32 2
+  %z = tail call <4 x float> @smear_f(float %z0) nounwind readnone
+
+  %px = getelementptr inbounds %struct.rs_matrix3x3* %m, i32 0, i32 0, i32 0
+  %px2 = bitcast float* %px to <4 x float>*
+  %xm = load <4 x float>* %px2
+  %py = getelementptr inbounds %struct.rs_matrix3x3* %m, i32 0, i32 0, i32 3
+  %py2 = bitcast float* %py to <4 x float>*
+  %ym = load <4 x float>* %py2
+  %pz = getelementptr inbounds %struct.rs_matrix3x3* %m, i32 0, i32 0, i32 6
+  %pz2 = bitcast float* %pz to <3 x float>*
+  %zm2 = load <3 x float>* %pz2
+  %zm = shufflevector <3 x float> %zm2, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+
+  %a1 = fmul <4 x float> %x, %xm
+  %a2 = fmul <4 x float> %y, %ym
+  %a3 = fadd <4 x float> %a1, %a2
+  %a4 = fmul <4 x float> %z, %zm
+  %a5 = fadd <4 x float> %a4, %a3
+  %a6 = shufflevector <4 x float> %a5, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %a6
+}
+
+define <3 x float> @_Z16rsMatrixMultiplyP12rs_matrix3x3Dv3_f(%struct.rs_matrix3x3* nocapture %m, <3 x float> %in) nounwind readonly {
+  %r = tail call <3 x float> @_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv3_f(%struct.rs_matrix3x3* nocapture %m, <3 x float> %in) nounwind
+  ret <3 x float> %r
+}
+
+define <3 x float> @_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv2_f(%struct.rs_matrix3x3* nocapture %m, <2 x float> %in) nounwind readonly {
+  %x0 = extractelement <2 x float> %in, i32 0
+  %x = tail call <4 x float> @smear_f(float %x0) nounwind readnone
+  %y0 = extractelement <2 x float> %in, i32 1
+  %y = tail call <4 x float> @smear_f(float %y0) nounwind readnone
+
+  %px = getelementptr inbounds %struct.rs_matrix3x3* %m, i32 0, i32 0, i32 0
+  %px2 = bitcast float* %px to <4 x float>*
+  %xm = load <4 x float>* %px2
+  %py = getelementptr inbounds %struct.rs_matrix3x3* %m, i32 0, i32 0, i32 3
+  %py2 = bitcast float* %py to <4 x float>*
+  %ym = load <4 x float>* %py2
+
+  %a1 = fmul <4 x float> %x, %xm
+  %a2 = fmul <4 x float> %y, %ym
+  %a3 = fadd <4 x float> %a1, %a2
+  %a4 = shufflevector <4 x float> %a3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %a4
+}
+
+define <3 x float> @_Z16rsMatrixMultiplyP12rs_matrix3x3Dv2_f(%struct.rs_matrix3x3* nocapture %m, <2 x float> %in) nounwind readonly {
+  %r = tail call <3 x float> @_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv2_f(%struct.rs_matrix3x3* nocapture %m, <2 x float> %in) nounwind
+  ret <3 x float> %r
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv4_f(%struct.rs_matrix4x4* nocapture %m, <4 x float> %in) nounwind readonly {
+  %x0 = extractelement <4 x float> %in, i32 0
+  %x = tail call <4 x float> @smear_f(float %x0) nounwind readnone
+  %y0 = extractelement <4 x float> %in, i32 1
+  %y = tail call <4 x float> @smear_f(float %y0) nounwind readnone
+  %z0 = extractelement <4 x float> %in, i32 2
+  %z = tail call <4 x float> @smear_f(float %z0) nounwind readnone
+  %w0 = extractelement <4 x float> %in, i32 3
+  %w = tail call <4 x float> @smear_f(float %w0) nounwind readnone
+
+  %px = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 0
+  %px2 = bitcast float* %px to <4 x float>*
+  %xm = load <4 x float>* %px2
+  %py = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 4
+  %py2 = bitcast float* %py to <4 x float>*
+  %ym = load <4 x float>* %py2
+  %pz = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 8
+  %pz2 = bitcast float* %pz to <4 x float>*
+  %zm = load <4 x float>* %pz2
+  %pw = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 12
+  %pw2 = bitcast float* %pw to <4 x float>*
+  %wm = load <4 x float>* %pw2
+
+  %a1 = fmul <4 x float> %x, %xm
+  %a2 = fmul <4 x float> %y, %ym
+  %a3 = fadd <4 x float> %a1, %a2
+  %a4 = fmul <4 x float> %z, %zm
+  %a5 = fadd <4 x float> %a3, %a4
+  %a6 = fmul <4 x float> %w, %wm
+  %a7 = fadd <4 x float> %a5, %a6
+  ret <4 x float> %a7
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyP12rs_matrix4x4Dv4_f(%struct.rs_matrix4x4* nocapture %m, <4 x float> %in) nounwind readonly {
+  %r = tail call <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv4_f(%struct.rs_matrix4x4* nocapture %m, <4 x float> %in) nounwind
+  ret <4 x float> %r
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv3_f(%struct.rs_matrix4x4* nocapture %m, <3 x float> %in) nounwind readonly {
+  %x0 = extractelement <3 x float> %in, i32 0
+  %x = tail call <4 x float> @smear_f(float %x0) nounwind readnone
+  %y0 = extractelement <3 x float> %in, i32 1
+  %y = tail call <4 x float> @smear_f(float %y0) nounwind readnone
+  %z0 = extractelement <3 x float> %in, i32 2
+  %z = tail call <4 x float> @smear_f(float %z0) nounwind readnone
+
+  %px = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 0
+  %px2 = bitcast float* %px to <4 x float>*
+  %xm = load <4 x float>* %px2
+  %py = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 4
+  %py2 = bitcast float* %py to <4 x float>*
+  %ym = load <4 x float>* %py2
+  %pz = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 8
+  %pz2 = bitcast float* %pz to <4 x float>*
+  %zm = load <4 x float>* %pz2
+  %pw = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 12
+  %pw2 = bitcast float* %pw to <4 x float>*
+  %wm = load <4 x float>* %pw2
+
+  %a1 = fmul <4 x float> %x, %xm
+  %a2 = fadd <4 x float> %wm, %a1
+  %a3 = fmul <4 x float> %y, %ym
+  %a4 = fadd <4 x float> %a2, %a3
+  %a5 = fmul <4 x float> %z, %zm
+  %a6 = fadd <4 x float> %a4, %a5
+  ret <4 x float> %a6
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyP12rs_matrix4x4Dv3_f(%struct.rs_matrix4x4* nocapture %m, <3 x float> %in) nounwind readonly {
+  %r = tail call <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv3_f(%struct.rs_matrix4x4* nocapture %m, <3 x float> %in) nounwind
+  ret <4 x float> %r
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv2_f(%struct.rs_matrix4x4* nocapture %m, <2 x float> %in) nounwind readonly {
+  %x0 = extractelement <2 x float> %in, i32 0
+  %x = tail call <4 x float> @smear_f(float %x0) nounwind readnone
+  %y0 = extractelement <2 x float> %in, i32 1
+  %y = tail call <4 x float> @smear_f(float %y0) nounwind readnone
+
+  %px = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 0
+  %px2 = bitcast float* %px to <4 x float>*
+  %xm = load <4 x float>* %px2
+  %py = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 4
+  %py2 = bitcast float* %py to <4 x float>*
+  %ym = load <4 x float>* %py2
+  %pw = getelementptr inbounds %struct.rs_matrix4x4* %m, i32 0, i32 0, i32 12
+  %pw2 = bitcast float* %pw to <4 x float>*
+  %wm = load <4 x float>* %pw2
+
+  %a1 = fmul <4 x float> %x, %xm
+  %a2 = fadd <4 x float> %wm, %a1
+  %a3 = fmul <4 x float> %y, %ym
+  %a4 = fadd <4 x float> %a2, %a3
+  ret <4 x float> %a4
+}
+
+define <4 x float> @_Z16rsMatrixMultiplyP12rs_matrix4x4Dv2_f(%struct.rs_matrix4x4* nocapture %m, <2 x float> %in) nounwind readonly {
+  %r = tail call <4 x float> @_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv2_f(%struct.rs_matrix4x4* nocapture %m, <2 x float> %in) nounwind
+  ret <4 x float> %r
+}
+
diff --git a/lib/ScriptCRT/pixel_packing.ll b/lib/ScriptCRT/pixel_packing.ll
new file mode 100644
index 0000000..65a49a5
--- /dev/null
+++ b/lib/ScriptCRT/pixel_packing.ll
@@ -0,0 +1,47 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+@fc_255.0 = internal constant <4 x float> <float 255.0, float 255.0, float 255.0, float 255.0>, align 16
+@fc_0.5 = internal constant <4 x float> <float 0.5, float 0.5, float 0.5, float 0.5>, align 16
+
+declare <4 x i8> @_Z14convert_uchar4Dv4_f(<4 x float> %in) nounwind readnone
+declare <4 x float> @_Z14convert_float4Dv4_h(<4 x i8> %in) nounwind readnone
+
+; uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color)
+define <4 x i8> @_Z17rsPackColorTo8888Dv4_f(<4 x float> %color) nounwind readnone {
+    %f255 = load <4 x float>* @fc_255.0, align 16
+    %f05 = load <4 x float>* @fc_0.5, align 16
+    %v1 = fmul <4 x float> %f255, %color
+    %v2 = fadd <4 x float> %f05, %v1
+    %v3 = tail call <4 x i8> @_Z14convert_uchar4Dv4_f(<4 x float> %v2) nounwind readnone
+    ret <4 x i8> %v3
+}
+
+; uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color)
+define <4 x i8> @_Z17rsPackColorTo8888Dv3_f(<3 x float> %color) nounwind readnone {
+    %1 = shufflevector <3 x float> %color, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+    %2 = insertelement <4 x float> %1, float 1.0, i32 3
+    %3 = tail call <4 x i8> @_Z17rsPackColorTo8888Dv4_f(<4 x float> %2) nounwind readnone
+    ret <4 x i8> %3
+}
+
+; uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
+define <4 x i8> @_Z17rsPackColorTo8888fff(float %r, float %g, float %b) nounwind readnone {
+    %1 = insertelement <4 x float> undef, float %r, i32 0
+    %2 = insertelement <4 x float> %1, float %g, i32 1
+    %3 = insertelement <4 x float> %1, float %b, i32 2
+    %4 = insertelement <4 x float> %1, float 1.0, i32 3
+    %5 = tail call <4 x i8> @_Z17rsPackColorTo8888Dv4_f(<4 x float> %4) nounwind readnone
+    ret <4 x i8> %5
+}
+
+; uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a)
+define <4 x i8> @_Z17rsPackColorTo8888ffff(float %r, float %g, float %b, float %a) nounwind readnone {
+    %1 = insertelement <4 x float> undef, float %r, i32 0
+    %2 = insertelement <4 x float> %1, float %g, i32 1
+    %3 = insertelement <4 x float> %1, float %b, i32 2
+    %4 = insertelement <4 x float> %1, float %a, i32 3
+    %5 = tail call <4 x i8> @_Z17rsPackColorTo8888Dv4_f(<4 x float> %4) nounwind readnone
+    ret <4 x i8> %5
+}
+
diff --git a/lib/ScriptCRT/rs_cl.c b/lib/ScriptCRT/rs_cl.c
index f0390ac..9d1f402 100644
--- a/lib/ScriptCRT/rs_cl.c
+++ b/lib/ScriptCRT/rs_cl.c
@@ -28,12 +28,12 @@
                         CVT_FUNC_2(type, float)
 
 CVT_FUNC(char)
-CVT_FUNC(uchar)
+//CVT_FUNC(uchar)
 CVT_FUNC(short)
 CVT_FUNC(ushort)
 CVT_FUNC(int)
 CVT_FUNC(uint)
-CVT_FUNC(float)
+//CVT_FUNC(float)
 
 // Float ops, 6.11.2
 
diff --git a/lib/ScriptCRT/rs_core.c b/lib/ScriptCRT/rs_core.c
index 7f323a5..5d3f993 100644
--- a/lib/ScriptCRT/rs_core.c
+++ b/lib/ScriptCRT/rs_core.c
@@ -17,10 +17,20 @@
  * allocations.
  *
  *****************************************************************************/
+typedef enum {
+    RS_ALLOCATION_MIPMAP_NONE = 0,
+    RS_ALLOCATION_MIPMAP_FULL = 1,
+    RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2
+} rs_allocation_mipmap_control;
+
 typedef struct Allocation {
-    char __pad[44];
+    char __pad[28];
     struct {
+        void * drv;
         struct {
+            const void *type;
+            uint32_t usageFlags;
+            rs_allocation_mipmap_control mipmapControl;
             uint32_t dimensionX;
             uint32_t dimensionY;
             uint32_t dimensionZ;
@@ -28,6 +38,9 @@
             bool hasMipmaps;
             bool hasFaces;
             bool hasReferences;
+            void * usrPtr;
+            int32_t surfaceTextureID;
+            void * wndSurface;
         } state;
 
         struct DrvState {
@@ -36,6 +49,203 @@
     } mHal;
 } Allocation_t;
 
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class ProgramStore owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsProgramStore.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsgProgramStoreGetDepthFunc(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * program store.
+ *
+ *****************************************************************************/
+typedef struct ProgramStore {
+    char __pad[36];
+    struct {
+        struct {
+            bool ditherEnable;
+            bool colorRWriteEnable;
+            bool colorGWriteEnable;
+            bool colorBWriteEnable;
+            bool colorAWriteEnable;
+            rs_blend_src_func blendSrc;
+            rs_blend_dst_func blendDst;
+            bool depthWriteEnable;
+            rs_depth_func depthFunc;
+        } state;
+    } mHal;
+} ProgramStore_t;
+
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class ProgramRaster owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsProgramRaster.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsgProgramRasterGetCullMode(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * program raster.
+ *
+ *****************************************************************************/
+typedef struct ProgramRaster {
+    char __pad[36];
+    struct {
+        struct {
+            bool pointSprite;
+            rs_cull_mode cull;
+        } state;
+    } mHal;
+} ProgramRaster_t;
+
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class Sampler owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsSampler.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsgProgramRasterGetMagFilter(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * samplers.
+ *
+ *****************************************************************************/
+typedef struct Sampler {
+    char __pad[32];
+    struct {
+        struct {
+            rs_sampler_value magFilter;
+            rs_sampler_value minFilter;
+            rs_sampler_value wrapS;
+            rs_sampler_value wrapT;
+            rs_sampler_value wrapR;
+            float aniso;
+        } state;
+    } mHal;
+} Sampler_t;
+
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class Element owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsElement.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsElementGetSubElementCount(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * elements.
+ *
+ *****************************************************************************/
+typedef struct Element {
+    char __pad[28];
+    struct {
+        void *drv;
+        struct {
+            rs_data_type dataType;
+            rs_data_kind dataKind;
+            uint32_t vectorSize;
+            uint32_t elementSizeBytes;
+
+            // Subelements
+            const void **fields;
+            uint32_t *fieldArraySizes;
+            const char **fieldNames;
+            uint32_t *fieldNameLengths;
+            uint32_t *fieldOffsetBytes;
+            uint32_t fieldsCount;
+        } state;
+    } mHal;
+} Element_t;
+
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class Type owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsType.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsAllocationGetElement(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * types.
+ *
+ *****************************************************************************/
+typedef struct Type {
+    char __pad[28];
+    struct {
+        void *drv;
+        struct {
+            const void * element;
+            uint32_t dimX;
+            uint32_t dimY;
+            uint32_t dimZ;
+            bool dimLOD;
+            bool faces;
+        } state;
+    } mHal;
+} Type_t;
+
+/*****************************************************************************
+ * CAUTION
+ *
+ * The following structure layout provides a more efficient way to access
+ * internal members of the C++ class Mesh owned by librs. Unfortunately,
+ * since this class has virtual members, we can't simply use offsetof() or any
+ * other compiler trickery to dynamically get the appropriate values at
+ * build-time. This layout may need to be updated whenever
+ * frameworks/base/libs/rs/rsMesh.h is modified.
+ *
+ * Having the layout information available in this file allows us to
+ * accelerate functionality like rsMeshGetVertexAllocationCount(). Without this
+ * information, we would not be able to inline the bitcode, thus resulting in
+ * potential runtime performance penalties for tight loops operating on
+ * meshes.
+ *
+ *****************************************************************************/
+typedef struct Mesh {
+    char __pad[28];
+    struct {
+        void *drv;
+        struct {
+            void **vertexBuffers;
+            uint32_t vertexBuffersCount;
+
+            // indexBuffers[i] could be NULL, in which case only primitives[i] is used
+            void **indexBuffers;
+            uint32_t indexBuffersCount;
+            rs_primitive *primitives;
+            uint32_t primitivesCount;
+        } state;
+    } mHal;
+} Mesh_t;
+
+
 /* Declaration of 4 basic functions in libRS */
 extern void __attribute__((overloadable))
     rsDebug(const char *, float, float);
@@ -59,6 +269,7 @@
     rsDebug(s, v.x, v.y, v.z, v.w);
 }
 
+/*
 extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
 {
     uchar4 c;
@@ -94,6 +305,7 @@
     uchar4 c = {color.x, color.y, color.z, color.w};
     return c;
 }
+*/
 
 extern float4 rsUnpackColor8888(uchar4 c)
 {
@@ -136,7 +348,7 @@
     return m->m[row * 2 + col];
 }
 
-
+/*
 extern float4 __attribute__((overloadable))
 rsMatrixMultiply(const rs_matrix4x4 *m, float4 in) {
     float4 ret;
@@ -192,7 +404,6 @@
     return rsMatrixMultiply((const rs_matrix3x3 *)m, in);
 }
 
-
 extern float3 __attribute__((overloadable))
 rsMatrixMultiply(const rs_matrix3x3 *m, float2 in) {
     float3 ret;
@@ -205,6 +416,7 @@
 rsMatrixMultiply(rs_matrix3x3 *m, float2 in) {
     return rsMatrixMultiply((const rs_matrix3x3 *)m, in);
 }
+*/
 
 extern float2 __attribute__((overloadable))
 rsMatrixMultiply(const rs_matrix2x2 *m, float2 in) {
@@ -222,9 +434,9 @@
 // int ops
 /////////////////////////////////////////////////////
 
-extern uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high) {
+/*extern uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high) {
     return amount < low ? low : (amount > high ? high : amount);
-}
+}*/
 extern int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high) {
     return amount < low ? low : (amount > high ? high : amount);
 }
@@ -298,3 +510,328 @@
     const uint32_t dimY = alloc->mHal.state.dimensionY;
     return &p[eSize * (x + y * dimX + z * dimX * dimY)];
 }
+
+extern rs_element __attribute__((overloadable))
+        rsAllocationGetElement(rs_allocation a) {
+    Allocation_t *alloc = (Allocation_t *)a.p;
+    if (alloc == NULL) {
+        rs_element nullElem = {0};
+        return nullElem;
+    }
+    Type_t *type = (Type_t *)alloc->mHal.state.type;
+    rs_element returnElem = {type->mHal.state.element};
+    return returnElem;
+}
+
+/**
+* Program Store
+*/
+extern rs_depth_func __attribute__((overloadable))
+        rsgProgramStoreGetDepthFunc(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return RS_DEPTH_FUNC_INVALID;
+    }
+    return prog->mHal.state.depthFunc;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetDepthMask(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.depthWriteEnable;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetColorMaskR(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.colorRWriteEnable;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetColorMaskG(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.colorGWriteEnable;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetColorMaskB(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.colorBWriteEnable;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetColorMaskA(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.colorAWriteEnable;
+}
+
+extern rs_blend_src_func __attribute__((overloadable))
+        rsgProgramStoreGetBlendSrcFunc(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return RS_BLEND_SRC_INVALID;
+    }
+    return prog->mHal.state.blendSrc;
+}
+
+extern rs_blend_dst_func __attribute__((overloadable))
+        rsgProgramStoreGetBlendDstFunc(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return RS_BLEND_DST_INVALID;
+    }
+    return prog->mHal.state.blendDst;
+}
+
+extern bool __attribute__((overloadable))
+        rsgProgramStoreGetDitherEnabled(rs_program_store ps) {
+    ProgramStore_t *prog = (ProgramStore_t *)ps.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.ditherEnable;
+}
+
+/**
+* Program Raster
+*/
+extern bool __attribute__((overloadable))
+        rsgProgramRasterGetPointSpriteEnabled(rs_program_raster pr) {
+    ProgramRaster_t *prog = (ProgramRaster_t *)pr.p;
+    if (prog == NULL) {
+        return false;
+    }
+    return prog->mHal.state.pointSprite;
+}
+
+extern rs_cull_mode __attribute__((overloadable))
+        rsgProgramRasterGetCullMode(rs_program_raster pr) {
+    ProgramRaster_t *prog = (ProgramRaster_t *)pr.p;
+    if (prog == NULL) {
+        return RS_CULL_INVALID;
+    }
+    return prog->mHal.state.cull;
+}
+
+/**
+* Sampler
+*/
+extern rs_sampler_value __attribute__((overloadable))
+        rsgSamplerGetMinification(rs_sampler s) {
+    Sampler_t *prog = (Sampler_t *)s.p;
+    if (prog == NULL) {
+        return RS_SAMPLER_INVALID;
+    }
+    return prog->mHal.state.minFilter;
+}
+
+extern rs_sampler_value __attribute__((overloadable))
+        rsgSamplerGetMagnification(rs_sampler s) {
+    Sampler_t *prog = (Sampler_t *)s.p;
+    if (prog == NULL) {
+        return RS_SAMPLER_INVALID;
+    }
+    return prog->mHal.state.magFilter;
+}
+
+extern rs_sampler_value __attribute__((overloadable))
+        rsgSamplerGetWrapS(rs_sampler s) {
+    Sampler_t *prog = (Sampler_t *)s.p;
+    if (prog == NULL) {
+        return RS_SAMPLER_INVALID;
+    }
+    return prog->mHal.state.wrapS;
+}
+
+extern rs_sampler_value __attribute__((overloadable))
+        rsgSamplerGetWrapT(rs_sampler s) {
+    Sampler_t *prog = (Sampler_t *)s.p;
+    if (prog == NULL) {
+        return RS_SAMPLER_INVALID;
+    }
+    return prog->mHal.state.wrapT;
+}
+
+extern float __attribute__((overloadable))
+        rsgSamplerGetAnisotropy(rs_sampler s) {
+    Sampler_t *prog = (Sampler_t *)s.p;
+    if (prog == NULL) {
+        return 0.0f;
+    }
+    return prog->mHal.state.aniso;
+}
+
+/**
+* Mesh
+*/
+extern uint32_t __attribute__((overloadable))
+        rsMeshGetVertexAllocationCount(rs_mesh m) {
+    Mesh_t *mesh = (Mesh_t *)m.p;
+    if (mesh == NULL) {
+        return 0;
+    }
+    return mesh->mHal.state.vertexBuffersCount;
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsMeshGetPrimitiveCount(rs_mesh m) {
+    Mesh_t *mesh = (Mesh_t *)m.p;
+    if (mesh == NULL) {
+        return 0;
+    }
+    return mesh->mHal.state.primitivesCount;
+}
+
+extern rs_allocation __attribute__((overloadable))
+        rsMeshGetVertexAllocation(rs_mesh m, uint32_t index) {
+    Mesh_t *mesh = (Mesh_t *)m.p;
+    if (mesh == NULL || index >= mesh->mHal.state.vertexBuffersCount) {
+        rs_allocation nullAlloc = {0};
+        return nullAlloc;
+    }
+    rs_allocation returnAlloc = {mesh->mHal.state.vertexBuffers[index]};
+    return returnAlloc;
+}
+
+extern rs_allocation __attribute__((overloadable))
+        rsMeshGetIndexAllocation(rs_mesh m, uint32_t index) {
+    Mesh_t *mesh = (Mesh_t *)m.p;
+    if (mesh == NULL || index >= mesh->mHal.state.primitivesCount) {
+        rs_allocation nullAlloc = {0};
+        return nullAlloc;
+    }
+    rs_allocation returnAlloc = {mesh->mHal.state.indexBuffers[index]};
+    return returnAlloc;
+}
+
+extern rs_primitive __attribute__((overloadable))
+        rsMeshGetPrimitive(rs_mesh m, uint32_t index) {
+    Mesh_t *mesh = (Mesh_t *)m.p;
+    if (mesh == NULL || index >= mesh->mHal.state.primitivesCount) {
+        return RS_PRIMITIVE_INVALID;
+    }
+    return mesh->mHal.state.primitives[index];
+}
+
+/**
+* Element
+*/
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSubElementCount(rs_element e) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL) {
+        return 0;
+    }
+    return element->mHal.state.fieldsCount;
+}
+
+extern rs_element __attribute__((overloadable))
+        rsElementGetSubElement(rs_element e, uint32_t index) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL || index >= element->mHal.state.fieldsCount) {
+        rs_element nullElem = {0};
+        return nullElem;
+    }
+    rs_element returnElem = {element->mHal.state.fields[index]};
+    return returnElem;
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSubElementNameLength(rs_element e, uint32_t index) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL || index >= element->mHal.state.fieldsCount) {
+        return 0;
+    }
+    return element->mHal.state.fieldNameLengths[index];
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSubElementName(rs_element e, uint32_t index, char *name, uint32_t nameLength) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL || index >= element->mHal.state.fieldsCount ||
+        nameLength == 0 || name == 0) {
+        return 0;
+    }
+
+    uint32_t numToCopy = element->mHal.state.fieldNameLengths[index];
+    if (nameLength < numToCopy) {
+        numToCopy = nameLength;
+    }
+    // Place the null terminator manually, in case of partial string
+    numToCopy --;
+    name[numToCopy] = '\0';
+    const char *nameSource = element->mHal.state.fieldNames[index];
+    for (uint32_t i = 0; i < numToCopy; i ++) {
+        name[i] = nameSource[i];
+    }
+    return numToCopy;
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSubElementArraySize(rs_element e, uint32_t index) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL || index >= element->mHal.state.fieldsCount) {
+        return 0;
+    }
+    return element->mHal.state.fieldArraySizes[index];
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSubElementOffsetBytes(rs_element e, uint32_t index) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL || index >= element->mHal.state.fieldsCount) {
+        return 0;
+    }
+    return element->mHal.state.fieldOffsetBytes[index];
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetSizeBytes(rs_element e) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL) {
+        return 0;
+    }
+    return element->mHal.state.elementSizeBytes;
+}
+
+extern rs_data_type __attribute__((overloadable))
+        rsElementGetDataType(rs_element e) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL) {
+        return RS_TYPE_INVALID;
+    }
+    return element->mHal.state.dataType;
+}
+
+extern rs_data_kind __attribute__((overloadable))
+        rsElementGetDataKind(rs_element e) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL) {
+        return RS_KIND_INVALID;
+    }
+    return element->mHal.state.dataKind;
+}
+
+extern uint32_t __attribute__((overloadable))
+        rsElementGetVectorSize(rs_element e) {
+    Element_t *element = (Element_t *)e.p;
+    if (element == NULL) {
+        return 0;
+    }
+    return element->mHal.state.vectorSize;
+}
diff --git a/lib/Transforms/Android.mk b/lib/Transforms/Android.mk
new file mode 100644
index 0000000..c30dd29
--- /dev/null
+++ b/lib/Transforms/Android.mk
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../../libbcc-config.mk
+
+#=====================================================================
+# Common: libbccTransforms
+#=====================================================================
+
+libbcc_transforms_SRC_FILES := \
+  ForEachExpand.cpp
+
+#=====================================================================
+# Device Static Library: libbccTransforms
+#=====================================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccTransforms
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -DTARGET_BUILD
+
+LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
+LOCAL_SRC_FILES := $(libbcc_transforms_SRC_FILES)
+
+include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
+include $(LIBBCC_ROOT_PATH)/libbcc-build-rules.mk
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(BUILD_STATIC_LIBRARY)
+
+
+#=====================================================================
+# Host Static Library: libbccTransforms
+#=====================================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccTransforms
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_CFLAGS += $(libbcc_CFLAGS)
+LOCAL_CFLAGS += -D__HOST__
+LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
+
+LOCAL_SRC_FILES := $(libbcc_transforms_SRC_FILES)
+
+include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
+include $(LIBBCC_ROOT_PATH)/libbcc-build-rules.mk
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/lib/Transforms/BCCTransforms.h b/lib/Transforms/BCCTransforms.h
new file mode 100644
index 0000000..1ac8174
--- /dev/null
+++ b/lib/Transforms/BCCTransforms.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llvm/Pass.h"
+
+namespace bcc {
+
+llvm::ModulePass *createForEachExpandPass(std::vector<std::string>& Names,
+                                          std::vector<uint32_t>& Signatures);
+
+}  // namespace bcc
diff --git a/lib/Transforms/ForEachExpand.cpp b/lib/Transforms/ForEachExpand.cpp
new file mode 100644
index 0000000..53d6bdc
--- /dev/null
+++ b/lib/Transforms/ForEachExpand.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Config.h"
+#include "bcc/bcc_assert.h"
+
+#include "DebugHelper.h"
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Type.h"
+#include "llvm/Support/IRBuilder.h"
+
+namespace {
+  /* ForEachExpandPass - This pass operates on functions that are able to be
+   * called via rsForEach() or "foreach_<NAME>". We create an inner loop for
+   * the ForEach-able function to be invoked over the appropriate data cells
+   * of the input/output allocations (adjusting other relevant parameters as
+   * we go). We support doing this for any ForEach-able compute kernels.
+   * The new function name is the original function name followed by
+   * ".expand". Note that we still generate code for the original function.
+   */
+  class ForEachExpandPass : public llvm::ModulePass {
+  private:
+  static char ID;
+
+  llvm::Module *M;
+  llvm::LLVMContext *C;
+
+  std::vector<std::string>& mNames;
+  std::vector<uint32_t>& mSignatures;
+
+  uint32_t getRootSignature(llvm::Function *F) {
+    const llvm::NamedMDNode *ExportForEachMetadata =
+        M->getNamedMetadata("#rs_export_foreach");
+
+    if (!ExportForEachMetadata) {
+      llvm::SmallVector<llvm::Type*, 8> RootArgTys;
+      for (llvm::Function::arg_iterator B = F->arg_begin(),
+                                        E = F->arg_end();
+           B != E;
+           ++B) {
+        RootArgTys.push_back(B->getType());
+      }
+
+      // For pre-ICS bitcode, we may not have signature information. In that
+      // case, we use the size of the RootArgTys to select the number of
+      // arguments.
+      return (1 << RootArgTys.size()) - 1;
+    }
+
+    bccAssert(ExportForEachMetadata->getNumOperands() > 0);
+
+    // We only handle the case for legacy root() functions here, so this is
+    // hard-coded to look at only the first such function.
+    llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0);
+    if (SigNode != NULL && SigNode->getNumOperands() == 1) {
+      llvm::Value *SigVal = SigNode->getOperand(0);
+      if (SigVal->getValueID() == llvm::Value::MDStringVal) {
+        llvm::StringRef SigString =
+            static_cast<llvm::MDString*>(SigVal)->getString();
+        uint32_t Signature = 0;
+        if (SigString.getAsInteger(10, Signature)) {
+          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
+          return 0;
+        }
+        return Signature;
+      }
+    }
+
+    return 0;
+  }
+
+  static bool hasIn(uint32_t Signature) {
+    return Signature & 1;
+  }
+
+  static bool hasOut(uint32_t Signature) {
+    return Signature & 2;
+  }
+
+  static bool hasUsrData(uint32_t Signature) {
+    return Signature & 4;
+  }
+
+  static bool hasX(uint32_t Signature) {
+    return Signature & 8;
+  }
+
+  static bool hasY(uint32_t Signature) {
+    return Signature & 16;
+  }
+
+  public:
+  ForEachExpandPass(std::vector<std::string>& Names,
+                    std::vector<uint32_t>& Signatures)
+      : ModulePass(ID), M(NULL), C(NULL), mNames(Names),
+        mSignatures(Signatures) {
+  }
+
+  /* Performs the actual optimization on a selected function. On success, the
+   * Module will contain a new function of the name "<NAME>.expand" that
+   * invokes <NAME>() in a loop with the appropriate parameters.
+   */
+  bool ExpandFunction(llvm::Function *F, uint32_t Signature) {
+    ALOGV("Expanding ForEach-able Function %s", F->getName().str().c_str());
+
+    if (!Signature) {
+      Signature = getRootSignature(F);
+      if (!Signature) {
+        // We couldn't determine how to expand this function based on its
+        // function signature.
+        return false;
+      }
+    }
+
+    llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*C);
+    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C);
+    llvm::Type *SizeTy = Int32Ty;
+
+    /* Defined in frameworks/base/libs/rs/rs_hal.h:
+     *
+     * struct RsForEachStubParamStruct {
+     *   const void *in;
+     *   void *out;
+     *   const void *usr;
+     *   size_t usr_len;
+     *   uint32_t x;
+     *   uint32_t y;
+     *   uint32_t z;
+     *   uint32_t lod;
+     *   enum RsAllocationCubemapFace face;
+     *   uint32_t ar[16];
+     * };
+     */
+    llvm::SmallVector<llvm::Type*, 9> StructTys;
+    StructTys.push_back(VoidPtrTy);  // const void *in
+    StructTys.push_back(VoidPtrTy);  // void *out
+    StructTys.push_back(VoidPtrTy);  // const void *usr
+    StructTys.push_back(SizeTy);     // size_t usr_len
+    StructTys.push_back(Int32Ty);    // uint32_t x
+    StructTys.push_back(Int32Ty);    // uint32_t y
+    StructTys.push_back(Int32Ty);    // uint32_t z
+    StructTys.push_back(Int32Ty);    // uint32_t lod
+    StructTys.push_back(Int32Ty);    // enum RsAllocationCubemapFace
+    StructTys.push_back(llvm::ArrayType::get(Int32Ty, 16));  // uint32_t ar[16]
+
+    llvm::Type *ForEachStubPtrTy = llvm::StructType::create(
+        StructTys, "RsForEachStubParamStruct")->getPointerTo();
+
+    /* Create the function signature for our expanded function.
+     * void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2,
+     *       uint32_t instep, uint32_t outstep)
+     */
+    llvm::SmallVector<llvm::Type*, 8> ParamTys;
+    ParamTys.push_back(ForEachStubPtrTy);  // const RsForEachStubParamStruct *p
+    ParamTys.push_back(Int32Ty);           // uint32_t x1
+    ParamTys.push_back(Int32Ty);           // uint32_t x2
+    ParamTys.push_back(Int32Ty);           // uint32_t instep
+    ParamTys.push_back(Int32Ty);           // uint32_t outstep
+
+    llvm::FunctionType *FT =
+        llvm::FunctionType::get(llvm::Type::getVoidTy(*C), ParamTys, false);
+    llvm::Function *ExpandedFunc =
+        llvm::Function::Create(FT,
+                               llvm::GlobalValue::ExternalLinkage,
+                               F->getName() + ".expand", M);
+
+    // Create and name the actual arguments to this expanded function.
+    llvm::SmallVector<llvm::Argument*, 8> ArgVec;
+    for (llvm::Function::arg_iterator B = ExpandedFunc->arg_begin(),
+                                      E = ExpandedFunc->arg_end();
+         B != E;
+         ++B) {
+      ArgVec.push_back(B);
+    }
+
+    if (ArgVec.size() != 5) {
+      ALOGE("Incorrect number of arguments to function: %zu",
+            ArgVec.size());
+      return false;
+    }
+    llvm::Value *Arg_p = ArgVec[0];
+    llvm::Value *Arg_x1 = ArgVec[1];
+    llvm::Value *Arg_x2 = ArgVec[2];
+    llvm::Value *Arg_instep = ArgVec[3];
+    llvm::Value *Arg_outstep = ArgVec[4];
+
+    Arg_p->setName("p");
+    Arg_x1->setName("x1");
+    Arg_x2->setName("x2");
+    Arg_instep->setName("instep");
+    Arg_outstep->setName("outstep");
+
+    // Construct the actual function body.
+    llvm::BasicBlock *Begin =
+        llvm::BasicBlock::Create(*C, "Begin", ExpandedFunc);
+    llvm::IRBuilder<> Builder(Begin);
+
+    // uint32_t X = x1;
+    llvm::AllocaInst *AX = Builder.CreateAlloca(Int32Ty, 0, "AX");
+    Builder.CreateStore(Arg_x1, AX);
+
+    // Collect and construct the arguments for the kernel().
+    // Note that we load any loop-invariant arguments before entering the Loop.
+    llvm::Function::arg_iterator Args = F->arg_begin();
+
+    llvm::Type *InTy = NULL;
+    llvm::AllocaInst *AIn = NULL;
+    if (hasIn(Signature)) {
+      InTy = Args->getType();
+      AIn = Builder.CreateAlloca(InTy, 0, "AIn");
+      Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad(
+          Builder.CreateStructGEP(Arg_p, 0)), InTy), AIn);
+      Args++;
+    }
+
+    llvm::Type *OutTy = NULL;
+    llvm::AllocaInst *AOut = NULL;
+    if (hasOut(Signature)) {
+      OutTy = Args->getType();
+      AOut = Builder.CreateAlloca(OutTy, 0, "AOut");
+      Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad(
+          Builder.CreateStructGEP(Arg_p, 1)), OutTy), AOut);
+      Args++;
+    }
+
+    llvm::Value *UsrData = NULL;
+    if (hasUsrData(Signature)) {
+      llvm::Type *UsrDataTy = Args->getType();
+      UsrData = Builder.CreatePointerCast(Builder.CreateLoad(
+          Builder.CreateStructGEP(Arg_p, 2)), UsrDataTy);
+      UsrData->setName("UsrData");
+      Args++;
+    }
+
+    if (hasX(Signature)) {
+      Args++;
+    }
+
+    llvm::Value *Y = NULL;
+    if (hasY(Signature)) {
+      Y = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 5), "Y");
+      Args++;
+    }
+
+    bccAssert(Args == F->arg_end());
+
+    llvm::BasicBlock *Loop = llvm::BasicBlock::Create(*C, "Loop", ExpandedFunc);
+    llvm::BasicBlock *Exit = llvm::BasicBlock::Create(*C, "Exit", ExpandedFunc);
+
+    // if (x1 < x2) goto Loop; else goto Exit;
+    llvm::Value *Cond = Builder.CreateICmpSLT(Arg_x1, Arg_x2);
+    Builder.CreateCondBr(Cond, Loop, Exit);
+
+    // Loop:
+    Builder.SetInsertPoint(Loop);
+
+    // Populate the actual call to kernel().
+    llvm::SmallVector<llvm::Value*, 8> RootArgs;
+
+    llvm::Value *In = NULL;
+    llvm::Value *Out = NULL;
+
+    if (AIn) {
+      In = Builder.CreateLoad(AIn, "In");
+      RootArgs.push_back(In);
+    }
+
+    if (AOut) {
+      Out = Builder.CreateLoad(AOut, "Out");
+      RootArgs.push_back(Out);
+    }
+
+    if (UsrData) {
+      RootArgs.push_back(UsrData);
+    }
+
+    // We always have to load X, since it is used to iterate through the loop.
+    llvm::Value *X = Builder.CreateLoad(AX, "X");
+    if (hasX(Signature)) {
+      RootArgs.push_back(X);
+    }
+
+    if (Y) {
+      RootArgs.push_back(Y);
+    }
+
+    Builder.CreateCall(F, RootArgs);
+
+    if (In) {
+      // In += instep
+      llvm::Value *NewIn = Builder.CreateIntToPtr(Builder.CreateNUWAdd(
+          Builder.CreatePtrToInt(In, Int32Ty), Arg_instep), InTy);
+      Builder.CreateStore(NewIn, AIn);
+    }
+
+    if (Out) {
+      // Out += outstep
+      llvm::Value *NewOut = Builder.CreateIntToPtr(Builder.CreateNUWAdd(
+          Builder.CreatePtrToInt(Out, Int32Ty), Arg_outstep), OutTy);
+      Builder.CreateStore(NewOut, AOut);
+    }
+
+    // X++;
+    llvm::Value *XPlusOne =
+        Builder.CreateNUWAdd(X, llvm::ConstantInt::get(Int32Ty, 1));
+    Builder.CreateStore(XPlusOne, AX);
+
+    // If (X < x2) goto Loop; else goto Exit;
+    Cond = Builder.CreateICmpSLT(XPlusOne, Arg_x2);
+    Builder.CreateCondBr(Cond, Loop, Exit);
+
+    // Exit:
+    Builder.SetInsertPoint(Exit);
+    Builder.CreateRetVoid();
+
+    return true;
+  }
+
+  virtual bool runOnModule(llvm::Module &M) {
+    bool Changed = false;
+    this->M = &M;
+    C = &M.getContext();
+
+    bccAssert(mNames.size() == mSignatures.size());
+    for (int i = 0, e = mNames.size(); i != e; i++) {
+      llvm::Function *kernel = M.getFunction(mNames[i]);
+      if (kernel && kernel->getReturnType()->isVoidTy()) {
+        Changed |= ExpandFunction(kernel, mSignatures[i]);
+      }
+    }
+
+    return Changed;
+  }
+
+  virtual const char *getPassName() const {
+    return "ForEach-able Function Expansion";
+  }
+
+  };
+}  // end anonymous namespace
+
+char ForEachExpandPass::ID = 0;
+
+namespace bcc {
+
+  llvm::ModulePass *createForEachExpandPass(std::vector<std::string>& Names,
+                                            std::vector<uint32_t>& Signatures) {
+    return new ForEachExpandPass(Names, Signatures);
+  }
+
+}  // namespace bcc
diff --git a/libbcc-build-rules.mk b/libbcc-build-rules.mk
index 898002c..a065ed6 100644
--- a/libbcc-build-rules.mk
+++ b/libbcc-build-rules.mk
@@ -37,10 +37,14 @@
       LOCAL_CFLAGS += -DARCH_ARM_HAVE_NEON
     endif
   else
-    ifeq ($(TARGET_ARCH),x86)
-      LOCAL_CFLAGS += -DFORCE_X86_CODEGEN
+    ifeq ($(TARGET_ARCH),mips)
+      LOCAL_CFLAGS += -DFORCE_MIPS_CODEGEN
     else
-      $(error Unsupported architecture $(TARGET_ARCH))
+      ifeq ($(TARGET_ARCH),x86)
+        LOCAL_CFLAGS += -DFORCE_X86_CODEGEN
+      else
+        $(error Unsupported architecture $(TARGET_ARCH))
+      endif
     endif
   endif
 
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 39e662a..c2051ec 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -22,6 +22,8 @@
 # Device Static Library: libbccCompilerRT
 #=====================================================================
 
+ifneq ($(TARGET_ARCH),mips)
+
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libbccCompilerRT
@@ -88,3 +90,5 @@
 
 include $(LIBBCC_ROOT_PATH)/libbcc-build-rules.mk
 include $(BUILD_STATIC_LIBRARY)
+
+endif # ifneq($(TARGET_ARCH),mips)
diff --git a/tests/Android.mk b/tests/Android.mk
index 752e5ca..7362ef3 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -35,6 +35,8 @@
 
 LOCAL_LDLIBS = -ldl
 
+LOCAL_CFLAGS += -D__HOST__
+
 include $(BUILD_HOST_EXECUTABLE)
 
 # Executable for target
diff --git a/tests/main.cpp b/tests/main.cpp
index 8749a0b..4947535 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -29,6 +29,20 @@
 
 #include <unistd.h>
 
+#if defined(__HOST__)
+  #if defined(__cplusplus)
+    extern "C" {
+  #endif
+      extern char *TARGET_TRIPLE_STRING;
+  #if defined(__cplusplus)
+    };
+  #endif
+#define GETOPT_OPTIONS  "C:RST"
+#else
+#define GETOPT_OPTIONS  "RST"
+#endif
+
+
 #if defined(__arm__)
 #define PROVIDE_ARM_DISASSEMBLY
 #endif
@@ -124,10 +138,16 @@
 static int parseOption(int argc, char** argv)
 {
   int c;
-  while ((c = getopt (argc, argv, "RST")) != -1) {
+  while ((c = getopt (argc, argv, GETOPT_OPTIONS)) != -1) {
     opterr = 0;
 
     switch(c) {
+    #if defined(__HOST__)
+      case 'C':
+        TARGET_TRIPLE_STRING = optarg;
+        break;
+    #endif
+
       case 'R':
         runResults = true;
         break;