am ca1904d4: am 1957e34d: Merge "Add missed compiler support function for "/" and "%""

* commit 'ca1904d414062a381350f9081089f32ff12b7006':
  Add missed compiler support function for "/" and "%"
diff --git a/Config.h b/Config.h
index b1ea833..c1f4133 100644
--- a/Config.h
+++ b/Config.h
@@ -1,7 +1,9 @@
 #ifndef BCC_CONFIG_H
 #define BCC_CONFIG_H
 
+#ifdef HAVE_BCC_CONFIG_MK_H
 #include "ConfigFromMk.h"
+#endif
 
 //---------------------------------------------------------------------------
 // Configuration for Disassembler
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index 3be7e35..e4a2573 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -20,6 +20,7 @@
 
 #define LOG_TAG "bcinfo"
 #include <cutils/log.h>
+#include <cutils/properties.h>
 
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Bitcode/ReaderWriter.h"
@@ -221,6 +222,7 @@
   // Check to see if we have any FP precision-related pragmas.
   std::string Relaxed("rs_fp_relaxed");
   std::string Imprecise("rs_fp_imprecise");
+  std::string Full("rs_fp_full");
   bool RelaxedPragmaSeen = false;
   bool ImprecisePragmaSeen = false;
 
@@ -246,6 +248,26 @@
     mRSFloatPrecision = RS_FP_Relaxed;
   }
 
+  // Provide an override for precsion via adb shell setprop
+  // adb shell setprop debug.rs.precision rs_fp_full
+  // adb shell setprop debug.rs.precision rs_fp_relaxed
+  // adb shell setprop debug.rs.precision rs_fp_imprecise
+  char PrecisionPropBuf[PROPERTY_VALUE_MAX];
+  const std::string PrecisionPropName("debug.rs.precision");
+  property_get("debug.rs.precision", PrecisionPropBuf, "");
+  if (PrecisionPropBuf[0]) {
+    if (!Relaxed.compare(PrecisionPropBuf)) {
+      ALOGE("Switching to RS FP relaxed mode via setprop");
+      mRSFloatPrecision = RS_FP_Relaxed;
+    } else if (!Imprecise.compare(PrecisionPropBuf)) {
+      ALOGE("Switching to RS FP imprecise mode via setprop");
+      mRSFloatPrecision = RS_FP_Imprecise;
+    } else if (!Full.compare(PrecisionPropBuf)) {
+      ALOGE("Switching to RS FP full mode via setprop");
+      mRSFloatPrecision = RS_FP_Full;
+    }
+  }
+
   return;
 }
 
diff --git a/bcinfo/tools/Android.mk b/bcinfo/tools/Android.mk
index 0d99f71..f7cf34b 100644
--- a/bcinfo/tools/Android.mk
+++ b/bcinfo/tools/Android.mk
@@ -16,6 +16,8 @@
 
 LOCAL_PATH := $(call my-dir)
 
+LLVM_ROOT_PATH := external/llvm
+
 # Executable for host
 # ========================================================
 include $(CLEAR_VARS)
@@ -28,6 +30,12 @@
 LOCAL_SHARED_LIBRARIES := \
   libbcinfo
 
+LOCAL_STATIC_LIBRARIES := \
+  libLLVMBitReader \
+  libLLVMBitWriter \
+  libLLVMCore \
+  libLLVMSupport
+
 LOCAL_CFLAGS += -D__HOST__
 
 LOCAL_C_INCLUDES := \
@@ -37,5 +45,6 @@
 
 LOCAL_LDLIBS = -ldl
 
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
 include $(BUILD_HOST_EXECUTABLE)
 
diff --git a/bcinfo/tools/main.cpp b/bcinfo/tools/main.cpp
index 1360c68..2d1e449 100644
--- a/bcinfo/tools/main.cpp
+++ b/bcinfo/tools/main.cpp
@@ -18,6 +18,16 @@
 #include <bcinfo/BitcodeWrapper.h>
 #include <bcinfo/MetadataExtractor.h>
 
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Assembly/AssemblyAnnotationWriter.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/ToolOutputFile.h>
+
 #include <ctype.h>
 #include <dlfcn.h>
 #include <stdarg.h>
@@ -33,12 +43,14 @@
 
 #include <unistd.h>
 
+#include <string>
 #include <vector>
 
 // This file corresponds to the standalone bcinfo tool. It prints a variety of
 // information about a supplied bitcode input file.
 
-const char* inFile = NULL;
+std::string inFile;
+std::string outFile;
 
 extern int opterr;
 extern int optind;
@@ -72,6 +84,13 @@
   }
 
   inFile = argv[optind];
+
+  int l = inFile.length();
+  if (l > 3 && inFile[l-3] == '.' && inFile[l-2] == 'b' && inFile[l-1] == 'c') {
+    outFile = std::string(inFile.begin(), inFile.end() - 3) + ".ll";
+  } else {
+    outFile = inFile + ".ll";
+  }
   return 1;
 }
 
@@ -141,26 +160,26 @@
 
 
 static size_t readBitcode(const char **bitcode) {
-  if (!inFile) {
+  if (!inFile.length()) {
     fprintf(stderr, "input file required\n");
-    return NULL;
+    return 0;
   }
 
   struct stat statInFile;
-  if (stat(inFile, &statInFile) < 0) {
+  if (stat(inFile.c_str(), &statInFile) < 0) {
     fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
-    return NULL;
+    return 0;
   }
 
   if (!S_ISREG(statInFile.st_mode)) {
     fprintf(stderr, "Input file should be a regular file.\n");
-    return NULL;
+    return 0;
   }
 
-  FILE *in = fopen(inFile, "r");
+  FILE *in = fopen(inFile.c_str(), "r");
   if (!in) {
-    fprintf(stderr, "Could not open input file %s\n", inFile);
-    return NULL;
+    fprintf(stderr, "Could not open input file %s\n", inFile.c_str());
+    return 0;
   }
 
   size_t bitcodeSize = statInFile.st_size;
@@ -169,7 +188,7 @@
   size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in);
 
   if (nread != bitcodeSize)
-      fprintf(stderr, "Could not read all of file %s\n", inFile);
+      fprintf(stderr, "Could not read all of file %s\n", inFile.c_str());
 
   fclose(in);
   return nread;
@@ -192,7 +211,6 @@
   }
 
   const char *bitcode = NULL;
-  const char *translatedBitcode = NULL;
   size_t bitcodeSize = readBitcode(&bitcode);
 
   unsigned int version = 0;
@@ -209,25 +227,58 @@
   printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion());
   printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel());
 
-  bcinfo::BitcodeTranslator *BT =
-      new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version);
+  llvm::OwningPtr<bcinfo::BitcodeTranslator> BT;
+  BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version));
   if (!BT->translate()) {
     fprintf(stderr, "failed to translate bitcode\n");
     return 3;
   }
 
-  bcinfo::MetadataExtractor *ME =
-      new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
-                                    BT->getTranslatedBitcodeSize());
+  llvm::OwningPtr<bcinfo::MetadataExtractor> ME;
+  ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
+                                         BT->getTranslatedBitcodeSize()));
   if (!ME->extract()) {
     fprintf(stderr, "failed to get metadata\n");
     return 4;
   }
 
-  dumpMetadata(ME);
+  dumpMetadata(ME.get());
 
-  delete ME;
-  delete BT;
+  const char *translatedBitcode = BT->getTranslatedBitcode();
+  size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize();
+
+  llvm::LLVMContext &ctx = llvm::getGlobalContext();
+  llvm::llvm_shutdown_obj called_on_exit;
+
+  llvm::OwningPtr<llvm::MemoryBuffer> mem;
+
+  mem.reset(llvm::MemoryBuffer::getMemBuffer(
+      llvm::StringRef(translatedBitcode, translatedBitcodeSize),
+      inFile.c_str(), false));
+
+  llvm::OwningPtr<llvm::Module> module;
+  std::string errmsg;
+  module.reset(llvm::ParseBitcodeFile(mem.get(), ctx, &errmsg));
+  if (module.get() != 0 && module->MaterializeAllPermanently(&errmsg)) {
+    module.reset();
+  }
+
+  if (module.get() == 0) {
+    if (errmsg.size()) {
+      fprintf(stderr, "error: %s\n", errmsg.c_str());
+    } else {
+      fprintf(stderr, "error: failed to parse bitcode file\n");
+    }
+    return 5;
+  }
+
+  llvm::OwningPtr<llvm::tool_output_file> tof(
+      new llvm::tool_output_file(outFile.c_str(), errmsg,
+                                 llvm::raw_fd_ostream::F_Binary));
+  llvm::OwningPtr<llvm::AssemblyAnnotationWriter> ann;
+  module->print(tof->os(), ann.get());
+
+  tof->keep();
 
   releaseBitcode(&bitcode);
 
diff --git a/helper/Android.mk b/helper/Android.mk
index ecba95f..54b408b 100644
--- a/helper/Android.mk
+++ b/helper/Android.mk
@@ -57,7 +57,6 @@
 LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
 
 LOCAL_SRC_FILES := \
-  DebugHelper.c \
   sha1.c
 
 include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
diff --git a/helper/DebugHelper.c b/helper/DebugHelper.c
deleted file mode 100644
index 5c01b1b..0000000
--- a/helper/DebugHelper.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "DebugHelper.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define LOG_BUF_SIZE 1024
-
-#if USE_LOGGER && !defined(__arm__)
-int __android_log_print(int prio, const char *tag, const char *fmt, ...) {
-  va_list ap;
-  char buf[LOG_BUF_SIZE];
-
-  va_start(ap, fmt);
-  vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
-  va_end(ap);
-
-  return __android_log_write(prio, tag, buf);
-}
-
-int __android_log_write(int prio, const char *tag, const char *msg) {
-  if (!tag) {
-    tag = "";
-  }
-
-  return fprintf(stderr, "[%s] %s\n", tag, msg);
-}
-#endif // USE_LOGGER && !defined(__arm__)
diff --git a/helper/DebugHelper.h b/helper/DebugHelper.h
index ae68e3a..ae1d4af 100644
--- a/helper/DebugHelper.h
+++ b/helper/DebugHelper.h
@@ -19,30 +19,9 @@
 
 #include "Config.h"
 
-#if USE_LOGGER
-
 #define LOG_TAG "bcc"
 #include <cutils/log.h>
 
-#else // !USE_LOGGER
-
-#undef ALOGV
-#undef ALOGI
-#undef ALOGD
-#undef ALOGW
-#undef ALOGE
-#undef LOGA
-
-#define ALOGV(...)
-#define ALOGI(...)
-#define ALOGD(...)
-#define ALOGW(...)
-#define ALOGE(...)
-#define LOGA(...)
-
-#endif
-
-
 #if !USE_FUNC_LOGGER
 
 #define BCC_FUNC_LOGGER()
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index c015bcc..855d055 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/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.
@@ -23,6 +23,8 @@
 #=====================================================================
 
 libbcc_executionengine_SRC_FILES := \
+  BCCContext.cpp \
+  BCCContextImpl.cpp \
   Compiler.cpp \
   FileHandle.cpp \
   GDBJIT.cpp \
@@ -35,7 +37,7 @@
   ScriptCached.cpp \
   ScriptCompiled.cpp \
   Sha1Helper.cpp \
-  SourceInfo.cpp
+  Source.cpp
 
 
 #=====================================================================
diff --git a/lib/ExecutionEngine/BCCContext.cpp b/lib/ExecutionEngine/BCCContext.cpp
new file mode 100644
index 0000000..63df268
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContext.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "BCCContext.h"
+
+#include <new>
+
+#include "BCCContextImpl.h"
+#include "Compiler.h"
+#include "DebugHelper.h"
+#include "Source.h"
+
+using namespace bcc;
+
+static BCCContext *GlobalContext = NULL;
+
+BCCContext *BCCContext::GetOrCreateGlobalContext() {
+  if (GlobalContext == NULL) {
+    GlobalContext = new (std::nothrow) BCCContext();
+    if (GlobalContext == NULL) {
+      ALOGE("Out of memory when allocating global BCCContext!");
+    }
+  }
+  return GlobalContext;
+}
+
+void BCCContext::DestroyGlobalContext() {
+  delete GlobalContext;
+  GlobalContext = NULL;
+}
+
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) {
+  // Initialize the LLVM compiler infrastructure.
+  Compiler::GlobalInitialization();
+}
+
+BCCContext::~BCCContext() {
+  delete mImpl;
+  if (this == GlobalContext) {
+    // We're deleting the context returned from GetOrCreateGlobalContext().
+    // Reset the GlobalContext.
+    GlobalContext = NULL;
+  }
+}
+
+void BCCContext::addSource(Source &pSource)
+{ mImpl->mOwnSources.insert(&pSource); }
+
+void BCCContext::removeSource(Source &pSource)
+{ mImpl->mOwnSources.erase(&pSource); }
+
+llvm::LLVMContext &BCCContext::getLLVMContext()
+{ return mImpl->mLLVMContext; }
+
+const llvm::LLVMContext &BCCContext::getLLVMContext() const
+{ return mImpl->mLLVMContext; }
diff --git a/lib/ExecutionEngine/BCCContext.h b/lib/ExecutionEngine/BCCContext.h
new file mode 100644
index 0000000..56962fe
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContext.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_CONTEXT_H
+#define BCC_EXECUTION_ENGINE_CONTEXT_H
+
+namespace llvm {
+  class LLVMContext;
+}
+
+namespace bcc {
+
+class BCCContextImpl;
+class Source;
+
+/*
+ * class BCCContext manages the global data across the libbcc infrastructure.
+ */
+class BCCContext {
+public:
+  BCCContextImpl *const mImpl;
+
+  BCCContext();
+  ~BCCContext();
+
+  llvm::LLVMContext &getLLVMContext();
+  const llvm::LLVMContext &getLLVMContext() const;
+
+  void addSource(Source &pSource);
+  void removeSource(Source &pSource);
+
+  // Global BCCContext
+  static BCCContext *GetOrCreateGlobalContext();
+  static void DestroyGlobalContext();
+};
+
+} // namespace bcc
+
+#endif  // BCC_EXECUTION_ENGINE_CONTEXT_H
diff --git a/lib/ExecutionEngine/BCCContextImpl.cpp b/lib/ExecutionEngine/BCCContextImpl.cpp
new file mode 100644
index 0000000..5558e17
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContextImpl.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 "BCCContextImpl.h"
+
+#include <vector>
+
+#include <llvm/ADT/STLExtras.h>
+
+#include "Source.h"
+
+using namespace bcc;
+
+BCCContextImpl::~BCCContextImpl() {
+  // Another temporary container is needed to store the Source objects that we
+  // are going to destroy. Since the destruction of Source object will call
+  // removeSource() and change the content of OwnSources.
+  std::vector<Source *> Sources(mOwnSources.begin(), mOwnSources.end());
+  llvm::DeleteContainerPointers(Sources);
+}
diff --git a/lib/ExecutionEngine/BCCContextImpl.h b/lib/ExecutionEngine/BCCContextImpl.h
new file mode 100644
index 0000000..e60997a
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContextImpl.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
+#define BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
+
+#include <llvm/ADT/SmallPtrSet.h>
+#include <llvm/LLVMContext.h>
+
+namespace bcc {
+
+class BCCContext;
+class Source;
+
+/*
+ * class BCCContextImpl contains the implementation of BCCContext.
+ */
+class BCCContextImpl {
+public:
+  llvm::LLVMContext mLLVMContext;
+
+  // The set of sources that initialized in this context. They will be destroyed
+  // automatically when this context is gone.
+  llvm::SmallPtrSet<Source *, 2> mOwnSources;
+
+  BCCContextImpl(BCCContext &pContext) { }
+  ~BCCContextImpl();
+};
+
+} // namespace bcc
+
+#endif  // BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index cf18ef6..5397d1d 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -220,27 +220,27 @@
     mRSExecutable(NULL),
     mpSymbolLookupFn(NULL),
     mpSymbolLookupContext(NULL),
-    mModule(NULL),
-    mHasLinked(false) /* Turn off linker */ {
+    mModule(NULL) {
   llvm::remove_fatal_error_handler();
   llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
   return;
 }
 
-
-int Compiler::linkModule(llvm::Module *moduleWith) {
-  if (llvm::Linker::LinkModules(mModule, moduleWith,
-                                llvm::Linker::PreserveSource,
-                                &mError) != 0) {
-    return hasError();
+int Compiler::readModule(llvm::Module &pModule) {
+  mModule = &pModule;
+  if (pModule.getMaterializer() != NULL) {
+    // A module with non-null materializer means that it is a lazy-load module.
+    // Materialize it now via invoking MaterializeAllPermanently(). This
+    // function returns false when the materialization is successful.
+    if (pModule.MaterializeAllPermanently(&mError)) {
+      setError("Failed to materialize the module `" +
+               pModule.getModuleIdentifier() + "'! (" + mError + ")");
+      mModule = NULL;
+    }
   }
-
-  // Everything for linking should be settled down here with no error occurs
-  mHasLinked = true;
   return hasError();
 }
 
-
 int Compiler::compile(const CompilerOption &option) {
   llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
@@ -391,7 +391,7 @@
   runInternalPasses(ForEachNameList, ForEachSigList);
 
   // Perform link-time optimization if we have multiple modules
-  if (mHasLinked) {
+  if (option.RunLTO) {
     runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel);
   }
 
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 863cda6..8fee17c 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -93,8 +93,6 @@
 
     llvm::Module *mModule;
 
-    bool mHasLinked;
-
   public:
     Compiler(ScriptCompiled *result);
 
@@ -119,12 +117,7 @@
       return mEmittedELFExecutable;
     }
 
-    int readModule(llvm::Module *module) {
-      mModule = module;
-      return hasError();
-    }
-
-    int linkModule(llvm::Module *module);
+    int readModule(llvm::Module &pModule);
 
     int compile(const CompilerOption &option);
 
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
index 75278c7..f7c1e50 100644
--- a/lib/ExecutionEngine/CompilerOption.h
+++ b/lib/ExecutionEngine/CompilerOption.h
@@ -82,6 +82,9 @@
     CodeModelOpt = llvm::CodeModel::Small;
 #endif
 
+    //-- Run LTO passes --//
+    RunLTO = true;
+
     //-- Load the result object after successful compilation  --//
     LoadAfterCompile = true;
   }
@@ -89,6 +92,7 @@
   llvm::TargetOptions TargetOpt;
   llvm::CodeModel::Model CodeModelOpt;
   llvm::Reloc::Model RelocModelOpt;
+  bool RunLTO;
   bool LoadAfterCompile;
 
 };
diff --git a/lib/ExecutionEngine/FileHandle.cpp b/lib/ExecutionEngine/FileHandle.cpp
index c0a344c..c659fb5 100644
--- a/lib/ExecutionEngine/FileHandle.cpp
+++ b/lib/ExecutionEngine/FileHandle.cpp
@@ -37,9 +37,7 @@
 
   static int const lock_flags[2] = { LOCK_SH, LOCK_EX };
 
-#if USE_LOGGER
   static char const *const open_mode_str[2] = { "read", "write" };
-#endif
 
   static size_t const RETRY_MAX = 4;
 
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 11ef0e1..dfa3f25 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -16,30 +16,33 @@
 
 #include "Script.h"
 
-#include "Config.h"
-#include "bcinfo/BitcodeWrapper.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "GDBJITRegistrar.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "SourceInfo.h"
-
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <new>
-#include <string.h>
+#include <cstring>
+
+#include <llvm/ADT/STLExtras.h>
+
 #include <cutils/properties.h>
 
+#include "Config.h"
+
+#include "MCCacheReader.h"
+#include "MCCacheWriter.h"
+#include "CompilerOption.h"
+
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+#include "FileHandle.h"
+#include "GDBJITRegistrar.h"
+#include "ScriptCompiled.h"
+#include "ScriptCached.h"
+#include "Sha1Helper.h"
+#include "Source.h"
+
 namespace {
 
 bool getBooleanProp(const char *str) {
@@ -48,10 +51,24 @@
   return strcmp(buf, "0") != 0;
 }
 
+bool isSetProp(const char *str) {
+  char buf[PROPERTY_VALUE_MAX];
+  property_get(str, buf, "");
+  return buf[0] != '\0';
+}
+
 } // namespace anonymous
 
 namespace bcc {
 
+Script::Script(Source &pSource)
+  : mSource(&pSource),
+    mpExtSymbolLookupFn(NULL),
+    mpExtSymbolLookupFnContext(NULL) {
+  resetState();
+  return;
+}
+
 Script::~Script() {
   switch (mStatus) {
   case ScriptStatus::Compiled:
@@ -65,111 +82,62 @@
   default:
     break;
   }
+  llvm::DeleteContainerPointers(mDependencyInfos);
+}
 
-  for (size_t i = 0; i < 2; ++i) {
-    delete mSourceList[i];
-  }
+void Script::resetState() {
+  mErrorCode = BCC_NO_ERROR;
+  mStatus = ScriptStatus::Unknown;
+  mObjectType = ScriptObject::Unknown;
+  mIsContextSlotNotAvail = false;
+  // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be
+  // assigned to NULL during state resetting.
+  //mpExtSymbolLookupFn = NULL;
+  //mpExtSymbolLookupFnContext = NULL;
+  llvm::DeleteContainerPointers(mDependencyInfos);
+  return;
 }
 
 
-int Script::addSourceBC(size_t idx,
-                        char const *resName,
-                        const char *bitcode,
-                        size_t bitcodeSize,
-                        unsigned long flags) {
-
-  if (!resName) {
-    mErrorCode = BCC_INVALID_VALUE;
-    ALOGE("Invalid argument: resName = NULL\n");
-    return 1;
-  }
-
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
-    return 1;
-  }
-
-  if (!bitcode) {
-    mErrorCode = BCC_INVALID_VALUE;
-    ALOGE("Invalid argument: bitcode = NULL\n");
-    return 1;
-  }
-
-  bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
-
-  mSourceList[idx] = SourceInfo::createFromBuffer(resName,
-                                                  bitcode, bitcodeSize,
-                                                  flags);
-
-  if (!mSourceList[idx]) {
-    mErrorCode = BCC_OUT_OF_MEMORY;
-    ALOGE("Out of memory while adding source bitcode\n");
-    return 1;
-  }
-
-  return 0;
+Script::DependencyInfo::DependencyInfo(MCO_ResourceType pSourceType,
+                                       const std::string &pSourceName,
+                                       const uint8_t *pSHA1)
+  : mSourceType(pSourceType), mSourceName(pSourceName) {
+  ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
+  return;
 }
 
-
-int Script::addSourceModule(size_t idx,
-                            llvm::Module *module,
-                            unsigned long flags) {
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
-    return 1;
+bool Script::reset(Source &pSource, bool pPreserveCurrent) {
+  if (mSource == &pSource) {
+    return false;
   }
 
-  if (!module) {
-    mErrorCode = BCC_INVALID_VALUE;
-    ALOGE("Invalid argument: module = NULL\n");
-    return 1;
+  if (!pPreserveCurrent) {
+    delete mSource;
   }
-
-  mSourceList[idx] = SourceInfo::createFromModule(module, flags);
-
-  if (!mSourceList[idx]) {
-    mErrorCode = BCC_OUT_OF_MEMORY;
-    ALOGE("Out of memory when add source module\n");
-    return 1;
-  }
-
-  return 0;
+  resetState();
+  mSource = &pSource;
+  return true;
 }
 
+bool Script::mergeSource(Source &pSource, bool pPreserveSource) {
+  return mSource->merge(pSource, pPreserveSource);
+}
 
-int Script::addSourceFile(size_t idx,
-                          char const *path,
-                          unsigned long flags) {
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
-    return 1;
+bool Script::addSourceDependencyInfo(MCO_ResourceType pSourceType,
+                                     const std::string &pSourceName,
+                                     const uint8_t *pSHA1) {
+  DependencyInfo *dep_info = new (std::nothrow) DependencyInfo(pSourceType,
+                                                               pSourceName,
+                                                               pSHA1);
+  if (dep_info == NULL) {
+    ALOGE("Out of memory when record dependency information of `%s'!",
+          pSourceName.c_str());
+    return false;
   }
 
-  if (!path) {
-    mErrorCode = BCC_INVALID_VALUE;
-    ALOGE("Invalid argument: path = NULL\n");
-    return 1;
-  }
-
-  struct stat sb;
-  if (stat(path, &sb) != 0) {
-    mErrorCode = BCC_INVALID_VALUE;
-    ALOGE("File not found: %s\n", path);
-    return 1;
-  }
-
-  mSourceList[idx] = SourceInfo::createFromFile(path, flags);
-
-  if (!mSourceList[idx]) {
-    mErrorCode = BCC_OUT_OF_MEMORY;
-    ALOGE("Out of memory while adding source file\n");
-    return 1;
-  }
-
-  return 0;
+  mDependencyInfos.push_back(dep_info);
+  return true;
 }
 
 int Script::prepareRelocatable(char const *objPath,
@@ -177,6 +145,7 @@
                                unsigned long flags) {
   CompilerOption option;
   option.RelocModelOpt = RelocModel;
+  option.RunLTO = false;
   option.LoadAfterCompile = false;
 
   int status = internalCompile(option);
@@ -294,10 +263,11 @@
   reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
   reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
 
-  for (size_t i = 0; i < 2; ++i) {
-    if (mSourceList[i]) {
-      mSourceList[i]->introDependency(reader);
-    }
+  for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+    const DependencyInfo *dep_info = mDependencyInfos[i];
+    reader.addDependency(dep_info->getSourceType(),
+                         dep_info->getSourceName(),
+                         dep_info->getSHA1Checksum());
   }
 
   if (checkOnly)
@@ -341,39 +311,12 @@
                                       mpExtSymbolLookupFnContext);
   }
 
-  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 (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
+  if (mCompiled->readModule(mSource->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]->getModule()) != 0) {
-      ALOGE("Unable to link library module\n");
-      return 1;
-    }
-  }
-
   // Compile and JIT the code
   if (mCompiled->compile(option) != 0) {
     ALOGE("Unable to compile.\n");
@@ -421,12 +364,14 @@
       writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
 #endif
 
-      for (size_t i = 0; i < 2; ++i) {
-        if (mSourceList[i]) {
-          mSourceList[i]->introDependency(writer);
-        }
+      for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+        const DependencyInfo *dep_info = mDependencyInfos[i];
+        writer.addDependency(dep_info->getSourceType(),
+                             dep_info->getSourceName(),
+                             dep_info->getSHA1Checksum());
       }
 
+
       // libRS is threadable dirty hack
       // TODO: This should be removed in the future
       uint32_t libRS_threadable = 0;
@@ -762,6 +707,11 @@
     return false;
   }
 
+  if (isSetProp("debug.rs.precision")) {
+    // If we have a floating point precision override, don't use the cache.
+    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.
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index e95cf8a..b654797 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -17,18 +17,20 @@
 #ifndef BCC_SCRIPT_H
 #define BCC_SCRIPT_H
 
-#include <bcc/bcc.h>
-#include "bcc_internal.h"
-
-#include "Compiler.h"
-
-#include <llvm/Support/CodeGen.h>
-
 #include <vector>
 #include <string>
 
+#include <stdint.h>
 #include <stddef.h>
 
+#include <llvm/ADT/SmallVector.h>
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "Compiler.h"
+
 namespace llvm {
   class Module;
   class GDBJITRegistrar;
@@ -37,7 +39,7 @@
 namespace bcc {
   class ScriptCompiled;
   class ScriptCached;
-  class SourceInfo;
+  class Source;
   struct CompilerOption;
 
   namespace ScriptStatus {
@@ -85,11 +87,31 @@
 
     bool mIsContextSlotNotAvail;
 
-    // Source List
-    SourceInfo *mSourceList[2];
-    // Note: mSourceList[0] (main source)
-    // Note: mSourceList[1] (library source)
-    // TODO(logan): Generalize this, use vector or SmallVector instead!
+    // This is the source associated with this object and is going to be
+    // compiled.
+    Source *mSource;
+
+    class DependencyInfo {
+    private:
+      MCO_ResourceType mSourceType;
+      std::string mSourceName;
+      uint8_t mSHA1[20];
+
+    public:
+      DependencyInfo(MCO_ResourceType pSourceType,
+                     const std::string &pSourceName,
+                     const uint8_t *pSHA1);
+
+      inline MCO_ResourceType getSourceType() const
+      { return mSourceType; }
+
+      inline const std::string getSourceName() const
+      { return mSourceName; }
+
+      inline const uint8_t *getSHA1Checksum() const
+      { return mSHA1; }
+    };
+    llvm::SmallVector<DependencyInfo *, 2> mDependencyInfos;
 
     // External Function List
     std::vector<char const *> mUserDefinedExternalSymbols;
@@ -98,32 +120,31 @@
     BCCSymbolLookupFn mpExtSymbolLookupFn;
     void *mpExtSymbolLookupFnContext;
 
-  public:
-    Script() : mErrorCode(BCC_NO_ERROR), mStatus(ScriptStatus::Unknown),
-               mObjectType(ScriptObject::Unknown),
-               mIsContextSlotNotAvail(false),
-               mpExtSymbolLookupFn(NULL), mpExtSymbolLookupFnContext(NULL) {
-      Compiler::GlobalInitialization();
+    // Reset the state of this script object
+    void resetState();
 
-      mSourceList[0] = NULL;
-      mSourceList[1] = NULL;
-    }
+  public:
+    Script(Source &pSource);
 
     ~Script();
 
-    int addSourceBC(size_t idx,
-                    char const *resName,
-                    const char *bitcode,
-                    size_t bitcodeSize,
-                    unsigned long flags);
+    // Reset this object with the new source supplied. Return false if this
+    // object remains unchanged after the call (e.g., the supplied source is
+    // the same with the one contain in this object.) If pPreserveCurrent is
+    // false, the current containing source will be destroyed after successfully
+    // reset.
+    bool reset(Source &pSource, bool pPreserveCurrent = false);
 
-    int addSourceModule(size_t idx,
-                        llvm::Module *module,
-                        unsigned long flags);
+    // Merge (or link) another source into the current source associated with
+    // this Script object. Return false on error.
+    bool mergeSource(Source &pSource, bool pPreserveSource = false);
 
-    int addSourceFile(size_t idx,
-                      char const *path,
-                      unsigned long flags);
+    // Add dependency information for this script given the source named
+    // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
+    // false on error.
+    bool addSourceDependencyInfo(MCO_ResourceType pSourceType,
+                                 const std::string &pSourceName,
+                                 const uint8_t *pSHA1);
 
     void markExternalSymbol(char const *name) {
       mUserDefinedExternalSymbols.push_back(name);
@@ -139,7 +160,7 @@
     int writeCache();
 
     /*
-     * Link the given bitcodes in mSourceList to shared object (.so).
+     * Link the given bitcodes in mSource to shared object (.so).
      *
      * Currently, it requires one to provide the relocatable object files with
      * given bitcodes to output a shared object.
@@ -150,7 +171,7 @@
      * you haven't done that yet) and then link the output relocatable object
      * file to .so in dsoPath.
      *
-     * TODO: Currently, we only support to link the bitcodes in mSourceList[0].
+     * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
      *
      */
     int prepareSharedObject(char const *objPath,
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 7b7b62a..8752aa3 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -17,17 +17,17 @@
 #ifndef BCC_SCRIPTCOMPILED_H
 #define BCC_SCRIPTCOMPILED_H
 
-#include "Compiler.h"
-#include "Script.h"
-
-#include <bcc/bcc.h>
-
 #include <list>
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
+#include <bcc/bcc.h>
+
+#include "Compiler.h"
+#include "Script.h"
+
 namespace llvm {
   class Module;
 }
@@ -73,12 +73,8 @@
 
     ~ScriptCompiled();
 
-    int readModule(llvm::Module *module) {
-      return mCompiler.readModule(module);
-    }
-
-    int linkModule(llvm::Module *module) {
-      return mCompiler.linkModule(module);
+    int readModule(llvm::Module &pModule) {
+      return mCompiler.readModule(pModule);
     }
 
     int compile(const CompilerOption &option) {
diff --git a/lib/ExecutionEngine/Source.cpp b/lib/ExecutionEngine/Source.cpp
new file mode 100644
index 0000000..754f3e5
--- /dev/null
+++ b/lib/ExecutionEngine/Source.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "Source.h"
+
+#include <new>
+
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Linker.h>
+#include <llvm/Module.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/system_error.h>
+
+#include "BCCContext.h"
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+
+namespace {
+
+// Helper function to load the bitcode. This uses "bitcode lazy load" feature to
+// reduce the startup time. On success, return the LLVM module object created
+// and take the ownership of input memory buffer (i.e., pInput). On error,
+// return NULL and will NOT take the ownership of pInput.
+static inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext,
+                                                llvm::MemoryBuffer *pInput) {
+  std::string error;
+  llvm::Module *module = llvm::getLazyBitcodeModule(pInput, pContext, &error);
+
+  if (module == NULL) {
+    ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
+          pInput->getBufferIdentifier(), error.c_str());
+  }
+
+  return module;
+}
+
+} // end anonymous namespace
+
+namespace bcc {
+
+Source *Source::CreateFromBuffer(BCCContext &pContext,
+                                 const char *pName,
+                                 const char *pBitcode,
+                                 size_t pBitcodeSize) {
+  llvm::StringRef input_data(pBitcode, pBitcodeSize);
+  llvm::MemoryBuffer *input_memory =
+      llvm::MemoryBuffer::getMemBuffer(input_data, pName);
+
+  if (input_memory == NULL) {
+    ALOGE("Unable to load bitcode `%s' from buffer!", pName);
+    return NULL;
+  }
+
+  llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+                                             input_memory);
+  if (module == NULL) {
+    delete input_memory;
+    return NULL;
+  }
+
+  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+  if (result == NULL) {
+    delete module;
+  }
+
+  return result;
+}
+
+
+Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
+  llvm::OwningPtr<llvm::MemoryBuffer> input_data;
+
+  llvm::error_code ec = llvm::MemoryBuffer::getFile(pPath, input_data);
+  if (ec != llvm::error_code::success()) {
+    ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
+                                                       ec.message().c_str());
+    return NULL;
+  }
+
+  llvm::MemoryBuffer *input_memory = input_data.take();
+  llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+                                             input_memory);
+  if (module == NULL) {
+    delete input_memory;
+    return NULL;
+  }
+
+  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+  if (result == NULL) {
+    delete module;
+  }
+
+  return result;
+}
+
+
+Source *Source::CreateFromModule(BCCContext &pContext, llvm::Module &pModule,
+                                 bool pNoDelete) {
+  Source *result = new (std::nothrow) Source(pContext, pModule, pNoDelete);
+  if (result == NULL) {
+    ALOGE("Out of memory during Source object allocation for `%s'!",
+          pModule.getModuleIdentifier().c_str());
+  }
+  return result;
+}
+
+Source::Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete)
+  : mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) {
+    pContext.addSource(*this);
+}
+
+Source::~Source() {
+  mContext.removeSource(*this);
+  if (!mNoDelete)
+    delete mModule;
+}
+
+bool Source::merge(Source &pSource, bool pPreserveSource) {
+  std::string error;
+  llvm::Linker::LinkerMode mode =
+      ((pPreserveSource) ? llvm::Linker::PreserveSource :
+                           llvm::Linker::DestroySource);
+
+  if (llvm::Linker::LinkModules(mModule, &pSource.getModule(),
+                                mode, &error) != 0) {
+    ALOGE("Failed to link source `%s' with `%s' (%s)!",
+          getIdentifier().c_str(),
+          pSource.getIdentifier().c_str(),
+          error.c_str());
+    return false;
+  }
+
+  if (!pPreserveSource) {
+    pSource.mNoDelete = true;
+    delete &pSource;
+  }
+
+  return true;
+}
+
+Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) {
+  // Create an empty module
+  llvm::Module *module =
+      new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext);
+
+  if (module == NULL) {
+    ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str());
+    return NULL;
+  }
+
+  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+  if (result == NULL) {
+    delete module;
+  }
+
+  return result;
+}
+
+const std::string &Source::getIdentifier() const {
+  return mModule->getModuleIdentifier();
+}
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/Source.h b/lib/ExecutionEngine/Source.h
new file mode 100644
index 0000000..577865f
--- /dev/null
+++ b/lib/ExecutionEngine/Source.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010-2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_SOURCE_H
+#define BCC_EXECUTION_ENGINE_SOURCE_H
+
+#include <string>
+
+namespace llvm {
+  class Module;
+}
+
+namespace bcc {
+
+class BCCContext;
+
+class Source {
+private:
+  BCCContext &mContext;
+  llvm::Module *mModule;
+
+  // If true, destructor won't destroy the mModule.
+  bool mNoDelete;
+
+private:
+  Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete = false);
+
+public:
+  static Source *CreateFromBuffer(BCCContext &pContext,
+                                  const char *pName,
+                                  const char *pBitcode,
+                                  size_t pBitcodeSize);
+
+  static Source *CreateFromFile(BCCContext &pContext,
+                                const std::string &pPath);
+
+  // Create a Source object from an existing module. If pNoDelete
+  // is true, destructor won't call delete on the given module.
+  static Source *CreateFromModule(BCCContext &pContext,
+                                  llvm::Module &pModule,
+                                  bool pNoDelete = false);
+
+  static Source *CreateEmpty(BCCContext &pContext, const std::string &pName);
+
+  // Merge the current source with pSource. If pPreserveSource is false, pSource
+  // will be destroyed after successfully merged. Return false on error.
+  bool merge(Source &pSource, bool pPreserveSource = false);
+
+  inline BCCContext &getContext()
+  { return mContext; }
+  inline const BCCContext &getContext() const
+  { return mContext; }
+
+  inline llvm::Module &getModule()
+  { return *mModule;  }
+  inline const llvm::Module &getModule() const
+  { return *mModule;  }
+
+  // Get the "identifier" of the bitcode. This will return the value of pName
+  // when it's created using CreateFromBuffer and pPath if CreateFromFile().
+  const std::string &getIdentifier() const;
+
+  ~Source();
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_SOURCE_H
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
deleted file mode 100644
index 1d0a950..0000000
--- a/lib/ExecutionEngine/SourceInfo.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SourceInfo.h"
-
-#include "MCCacheWriter.h"
-#include "MCCacheReader.h"
-
-#include "DebugHelper.h"
-#include "ScriptCompiled.h"
-#include "Sha1Helper.h"
-
-#include <bcc/bcc.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>
-#include <llvm/Support/system_error.h>
-
-#include <stddef.h>
-#include <string.h>
-
-namespace bcc {
-
-
-SourceInfo *SourceInfo::createFromBuffer(char const *resName,
-                                         char const *bitcode,
-                                         size_t bitcodeSize,
-                                         unsigned long flags) {
-  SourceInfo *result = new SourceInfo();
-
-  if (!result) {
-    return NULL;
-  }
-
-  result->type = SourceKind::Buffer;
-  result->buffer.resName = resName;
-  result->buffer.bitcode = bitcode;
-  result->buffer.bitcodeSize = bitcodeSize;
-  result->flags = flags;
-
-  if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
-    result->flags |= BCC_SKIP_DEP_SHA1;
-
-    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) {
-    memset(result->sha1, '\0', 20);
-  } else {
-    calcSHA1(result->sha1, bitcode, bitcodeSize);
-  }
-
-  return result;
-}
-
-
-SourceInfo *SourceInfo::createFromFile(char const *path,
-                                       unsigned long flags) {
-  SourceInfo *result = new SourceInfo();
-
-  if (!result) {
-    return NULL;
-  }
-
-  result->type = SourceKind::File;
-  result->file.path = path;
-  result->flags = flags;
-
-  memset(result->sha1, '\0', 20);
-
-  if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
-    calcFileSHA1(result->sha1, path);
-  }
-
-  return result;
-}
-
-
-SourceInfo *SourceInfo::createFromModule(llvm::Module *module,
-                                         unsigned long flags) {
-  SourceInfo *result = new SourceInfo();
-
-  if (!result) {
-    return NULL;
-  }
-
-  result->type = SourceKind::Module;
-  result->module = module;
-  result->flags = flags;
-
-  if (! (flags & BCC_SKIP_DEP_SHA1)) {
-    result->flags |= BCC_SKIP_DEP_SHA1;
-
-    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);
-
-  return result;
-}
-
-
-int SourceInfo::prepareModule(llvm::LLVMContext *context) {
-  if (module)
-    return 0;
-
-  llvm::OwningPtr<llvm::MemoryBuffer> mem;
-  std::string errmsg;
-
-  switch (type) {
-  case SourceKind::Buffer:
-    {
-      mem.reset(llvm::MemoryBuffer::getMemBuffer(
-          llvm::StringRef(buffer.bitcode, buffer.bitcodeSize), "", false));
-
-      if (!mem.get()) {
-        ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
-              buffer.bitcode, (unsigned long)buffer.bitcodeSize);
-        return 1;
-      }
-    }
-    break;
-
-  case SourceKind::File:
-    {
-      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;
-      }
-    }
-    break;
-
-  default:
-    return 0;
-    break;
-  }
-
-  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() {
-  if (module != NULL) {
-    llvm::LLVMContext *context = &module->getContext();
-    delete module;
-    if (!shared_context)
-      delete context;
-  }
-}
-
-template <typename T> void SourceInfo::introDependency(T &checker) {
-  if (flags & BCC_SKIP_DEP_SHA1) {
-    return;
-  }
-
-  switch (type) {
-  case SourceKind::Buffer:
-    checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1);
-    break;
-
-  case SourceKind::File:
-    checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1);
-    break;
-
-  default:
-    break;
-  }
-}
-
-template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
-template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
deleted file mode 100644
index 080d3b4..0000000
--- a/lib/ExecutionEngine/SourceInfo.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_SOURCEINFO_H
-#define BCC_SOURCEINFO_H
-
-#include "Config.h"
-
-#include <llvm/Module.h>
-
-#include <stddef.h>
-
-namespace llvm {
-  class LLVMContext;
-}
-
-namespace bcc {
-  namespace SourceKind {
-    enum SourceType {
-      File,
-      Buffer,
-      Module,
-    };
-  }
-
-  class SourceInfo {
-  private:
-    SourceKind::SourceType type;
-
-    // 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 {
-        char const *resName;
-        char const *bitcode;
-        size_t bitcodeSize;
-      } buffer;
-
-      struct {
-        char const *path;
-      } file;
-    };
-
-    unsigned long flags;
-
-    unsigned char sha1[20];
-
-  private:
-    SourceInfo() : module(NULL), shared_context(false) { }
-
-  public:
-    static SourceInfo *createFromBuffer(char const *resName,
-                                        char const *bitcode,
-                                        size_t bitcodeSize,
-                                        unsigned long flags);
-
-    static SourceInfo *createFromFile(char const *path,
-                                      unsigned long flags);
-
-    static SourceInfo *createFromModule(llvm::Module *module,
-                                        unsigned long flags);
-
-    inline llvm::Module *getModule() const {
-      return module;
-    }
-
-    inline llvm::LLVMContext *getContext() const {
-      return (module) ? &module->getContext() : NULL;
-    }
-
-    // Share with the given context if it's provided.
-    int prepareModule(llvm::LLVMContext *context = NULL);
-
-    template <typename T> void introDependency(T &checker);
-
-    ~SourceInfo();
-  };
-
-
-} // namespace bcc
-
-#endif // BCC_SOURCEINFO_H
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 01ef32f..e1894b7 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -18,19 +18,22 @@
 //    This is an eager-compilation JIT running on Android.
 
 #include <bcc/bcc.h>
-#include "bcc_internal.h"
-
-#include "Config.h"
-
-#include "Compiler.h"
-#include "DebugHelper.h"
-#include "Script.h"
 
 #include <string>
 
 #include <utils/StopWatch.h>
 
-#include <llvm/Support/CodeGen.h>
+#include "Config.h"
+
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "BCCContext.h"
+#include "Compiler.h"
+#include "DebugHelper.h"
+#include "Script.h"
+#include "Sha1Helper.h"
+#include "Source.h"
 
 using namespace bcc;
 
@@ -51,7 +54,15 @@
 extern "C" BCCScriptRef bccCreateScript() {
   BCC_FUNC_LOGGER();
   bccPrintBuildStamp();
-  return wrap(new bcc::Script());
+  // FIXME: This is a workaround for this API: use global BCC context and
+  //        create an empty source to create a Script object.
+  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+  if (context == NULL) {
+    return NULL;
+  }
+
+  Source *source = Source::CreateEmpty(*context, "empty");
+  return wrap(new Script(*source));
 }
 
 
@@ -74,13 +85,102 @@
   return unwrap(script)->getError();
 }
 
+static bool helper_add_source(Script *pScript,
+                              char const *pName,
+                              char const *pBitcode,
+                              size_t pBitcodeSize,
+                              unsigned long pFlags,
+                              bool pIsLink) {
+  bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
+  if (!pName && need_dependency_check) {
+    pFlags |= BCC_SKIP_DEP_SHA1;
+
+    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 suppress this warning.\n");
+  }
+
+  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+  if (context == NULL) {
+    return false;
+  }
+
+  Source *source = Source::CreateFromBuffer(*context, pName,
+                                            pBitcode, pBitcodeSize);
+  if (source == NULL) {
+    return false;
+  }
+
+  if (need_dependency_check) {
+    uint8_t sha1[20];
+    calcSHA1(sha1, pBitcode, pBitcodeSize);
+    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pName, sha1)) {
+      return false;
+    }
+  }
+
+  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
+static bool helper_add_source(Script *pScript,
+                              llvm::Module *pModule,
+                              bool pIsLink) {
+  if (pModule == NULL)
+    return false;
+
+  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+  if (context == NULL) {
+    return false;
+  }
+
+  if (pModule == NULL) {
+    ALOGE("Cannot add null module to script!");
+    return false;
+  }
+
+  Source *source = Source::CreateFromModule(*context, *pModule, true);
+  if (source == NULL) {
+    return false;
+  }
+
+  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
+static bool helper_add_source(Script *pScript,
+                              char const *pPath,
+                              unsigned long pFlags,
+                              bool pIsLink) {
+  bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
+  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+  if (context == NULL) {
+    return false;
+  }
+
+  Source *source = Source::CreateFromFile(*context, pPath);
+  if (source == NULL) {
+    return false;
+  }
+
+  if (need_dependency_check) {
+    uint8_t sha1[20];
+    calcFileSHA1(sha1, pPath);
+    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pPath, sha1)) {
+      return false;
+    }
+  }
+
+  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
 extern "C" int bccReadBC(BCCScriptRef script,
                          char const *resName,
                          char const *bitcode,
                          size_t bitcodeSize,
                          unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->addSourceBC(0, resName, bitcode, bitcodeSize, flags);
+  return (helper_add_source(unwrap(script), resName,
+                            bitcode, bitcodeSize,
+                            flags, /* pIsLink */false) == false);
 }
 
 
@@ -89,7 +189,8 @@
                              LLVMModuleRef module,
                              unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->addSourceModule(0, unwrap(module), flags);
+  return (helper_add_source(unwrap(script), unwrap(module),
+                            /* pIsLink */false) == false);
 }
 
 
@@ -97,7 +198,8 @@
                            char const *path,
                            unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->addSourceFile(0, path, flags);
+  return (helper_add_source(unwrap(script), path,
+                            flags, /* pIsLink */false) == false);
 }
 
 
@@ -107,7 +209,9 @@
                          size_t bitcodeSize,
                          unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->addSourceBC(1, resName, bitcode, bitcodeSize, flags);
+  return (helper_add_source(unwrap(script), resName,
+                            bitcode, bitcodeSize,
+                            flags, /* pIsLink */true) == false);
 }
 
 
@@ -115,7 +219,8 @@
                            char const *path,
                            unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return unwrap(script)->addSourceFile(1, path, flags);
+  return (helper_add_source(unwrap(script), path,
+                            flags, /* pIsLink */true) == false);
 }
 
 
diff --git a/lib/ScriptCRT/Android.mk b/lib/ScriptCRT/Android.mk
index f8b6d80..85b0f33 100644
--- a/lib/ScriptCRT/Android.mk
+++ b/lib/ScriptCRT/Android.mk
@@ -32,11 +32,11 @@
 
 clcore_files := \
     $(clcore_base_files) \
-    clamp.c
+    arch/generic.c
 
 clcore_neon_files := \
     $(clcore_base_files) \
-    neon/clamp.ll
+    arch/neon.ll
 
 ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"
   RS_VERSION := $(PLATFORM_SDK_VERSION)
diff --git a/lib/ScriptCRT/arch/generic.c b/lib/ScriptCRT/arch/generic.c
new file mode 100644
index 0000000..801ab28
--- /dev/null
+++ b/lib/ScriptCRT/arch/generic.c
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+
+#include "rs_types.rsh"
+
+extern short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high);
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high);
+extern uchar4 __attribute__((overloadable)) convert_uchar4(short4);
+
+
+/*
+ * CLAMP
+ */
+
+extern float __attribute__((overloadable)) clamp(float amount, float low, float high) {
+    return amount < low ? low : (amount > high ? high : amount);
+}
+
+extern float2 __attribute__((overloadable)) clamp(float2 amount, float2 low, float2 high) {
+    float2 r;
+    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) clamp(float3 amount, float3 low, float3 high) {
+    float3 r;
+    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+    r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high) {
+    float4 r;
+    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+    r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
+    r.w = amount.w < low.w ? low.w : (amount.w > high.w ? high.w : amount.w);
+    return r;
+}
+
+extern float2 __attribute__((overloadable)) clamp(float2 amount, float low, float high) {
+    float2 r;
+    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) clamp(float3 amount, float low, float high) {
+    float3 r;
+    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+    r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float low, float high) {
+    float4 r;
+    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+    r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
+    r.w = amount.w < low ? low : (amount.w > high ? high : amount.w);
+    return r;
+}
+
+
+/*
+ * FMAX
+ */
+
+extern float __attribute__((overloadable)) fmax(float v1, float v2) {
+    return v1 > v2 ? v1 : v2;
+}
+
+extern float2 __attribute__((overloadable)) fmax(float2 v1, float2 v2) {
+    float2 r;
+    r.x = v1.x > v2.x ? v1.x : v2.x;
+    r.y = v1.y > v2.y ? v1.y : v2.y;
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) fmax(float3 v1, float3 v2) {
+    float3 r;
+    r.x = v1.x > v2.x ? v1.x : v2.x;
+    r.y = v1.y > v2.y ? v1.y : v2.y;
+    r.z = v1.z > v2.z ? v1.z : v2.z;
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) fmax(float4 v1, float4 v2) {
+    float4 r;
+    r.x = v1.x > v2.x ? v1.x : v2.x;
+    r.y = v1.y > v2.y ? v1.y : v2.y;
+    r.z = v1.z > v2.z ? v1.z : v2.z;
+    r.w = v1.w > v2.w ? v1.w : v2.w;
+    return r;
+}
+
+extern float2 __attribute__((overloadable)) fmax(float2 v1, float v2) {
+    float2 r;
+    r.x = v1.x > v2 ? v1.x : v2;
+    r.y = v1.y > v2 ? v1.y : v2;
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) fmax(float3 v1, float v2) {
+    float3 r;
+    r.x = v1.x > v2 ? v1.x : v2;
+    r.y = v1.y > v2 ? v1.y : v2;
+    r.z = v1.z > v2 ? v1.z : v2;
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) fmax(float4 v1, float v2) {
+    float4 r;
+    r.x = v1.x > v2 ? v1.x : v2;
+    r.y = v1.y > v2 ? v1.y : v2;
+    r.z = v1.z > v2 ? v1.z : v2;
+    r.w = v1.w > v2 ? v1.w : v2;
+    return r;
+}
+
+extern float __attribute__((overloadable)) fmin(float v1, float v2) {
+    return v1 < v2 ? v1 : v2;
+}
+
+
+/*
+ * FMIN
+ */
+extern float2 __attribute__((overloadable)) fmin(float2 v1, float2 v2) {
+    float2 r;
+    r.x = v1.x < v2.x ? v1.x : v2.x;
+    r.y = v1.y < v2.y ? v1.y : v2.y;
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) fmin(float3 v1, float3 v2) {
+    float3 r;
+    r.x = v1.x < v2.x ? v1.x : v2.x;
+    r.y = v1.y < v2.y ? v1.y : v2.y;
+    r.z = v1.z < v2.z ? v1.z : v2.z;
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) fmin(float4 v1, float4 v2) {
+    float4 r;
+    r.x = v1.x < v2.x ? v1.x : v2.x;
+    r.y = v1.y < v2.y ? v1.y : v2.y;
+    r.z = v1.z < v2.z ? v1.z : v2.z;
+    r.w = v1.w < v2.w ? v1.w : v2.w;
+    return r;
+}
+
+extern float2 __attribute__((overloadable)) fmin(float2 v1, float v2) {
+    float2 r;
+    r.x = v1.x < v2 ? v1.x : v2;
+    r.y = v1.y < v2 ? v1.y : v2;
+    return r;
+}
+
+extern float3 __attribute__((overloadable)) fmin(float3 v1, float v2) {
+    float3 r;
+    r.x = v1.x < v2 ? v1.x : v2;
+    r.y = v1.y < v2 ? v1.y : v2;
+    r.z = v1.z < v2 ? v1.z : v2;
+    return r;
+}
+
+extern float4 __attribute__((overloadable)) fmin(float4 v1, float v2) {
+    float4 r;
+    r.x = v1.x < v2 ? v1.x : v2;
+    r.y = v1.y < v2 ? v1.y : v2;
+    r.z = v1.z < v2 ? v1.z : v2;
+    r.w = v1.w < v2 ? v1.w : v2;
+    return r;
+}
+
+/*
+ * YUV
+ */
+extern uchar4 __attribute__((overloadable)) rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
+    short Y = ((short)y) - 16;
+    short U = ((short)u) - 128;
+    short V = ((short)v) - 128;
+
+    short4 p;
+    p.r = (Y * 298 + V * 409 + 128) >> 8;
+    p.g = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
+    p.b = (Y * 298 + U * 516 + 128) >> 8;
+    p.a = 255;
+    p.r = rsClamp(p.r, (short)0, (short)255);
+    p.g = rsClamp(p.g, (short)0, (short)255);
+    p.b = rsClamp(p.b, (short)0, (short)255);
+
+    return convert_uchar4(p);
+}
+
+static float4 yuv_U_values = {0.f, -0.392f * 0.003921569f, +2.02 * 0.003921569f, 0.f};
+static float4 yuv_V_values = {1.603f * 0.003921569f, -0.815f * 0.003921569f, 0.f, 0.f};
+
+extern float4 __attribute__((overloadable)) rsYuvToRGBA_float4(uchar y, uchar u, uchar v) {
+    float4 color = (float)y * 0.003921569f;
+    float4 fU = ((float)u) - 128.f;
+    float4 fV = ((float)v) - 128.f;
+
+    color += fU * yuv_U_values;
+    color += fV * yuv_V_values;
+    color = clamp(color, 0.f, 1.f);
+    return color;
+}
+
diff --git a/lib/ScriptCRT/arch/neon.ll b/lib/ScriptCRT/arch/neon.ll
new file mode 100644
index 0000000..958f2e8
--- /dev/null
+++ b/lib/ScriptCRT/arch/neon.ll
@@ -0,0 +1,264 @@
+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"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;               INTRINSICS               ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float>, <2 x float>) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float>, <4 x float>) nounwind readnone
+declare <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float>, <2 x float>) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float>, <4 x float>) nounwind readnone
+
+declare <8 x i8>  @llvm.arm.neon.vqshiftns.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftns.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftns.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <8 x i8>  @llvm.arm.neon.vqshiftnu.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftnu.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftnu.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <8 x i8>  @llvm.arm.neon.vqshiftnsu.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftnsu.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftnsu.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32>, <4 x i32>) nounwind readnone
+declare <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32>, <4 x i32>) nounwind readnone
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;                HELPERS                 ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define internal <4 x float> @smear_4f(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 internal <2 x float> @smear_2f(float %in) nounwind readnone alwaysinline {
+  %1 = insertelement <2 x float> undef, float %in, i32 0
+  %2 = insertelement <2 x float> %1, float %in, i32 1
+  ret <2 x float> %2
+}
+
+define internal <4 x i32> @smear_4i32(i32 %in) nounwind readnone alwaysinline {
+  %1 = insertelement <4 x i32> undef, i32 %in, i32 0
+  %2 = insertelement <4 x i32> %1, i32 %in, i32 1
+  %3 = insertelement <4 x i32> %2, i32 %in, i32 2
+  %4 = insertelement <4 x i32> %3, i32 %in, i32 3
+  ret <4 x i32> %4
+}
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;                 CLAMP                  ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %low, <4 x float> %high) nounwind readonly {
+  %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %value, <4 x float> %high) nounwind readnone
+  %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %low) nounwind readnone
+  ret <4 x float> %2
+}
+
+define <4 x float> @_Z5clampDv4_fff(<4 x float> %value, float %low, float %high) nounwind readonly {
+  %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
+  %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
+  %out = tail call <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %_low, <4 x float> %_high) nounwind readonly
+  ret <4 x float> %out
+}
+
+define <3 x float> @_Z5clampDv3_fS_S_(<3 x float> %value, <3 x float> %low, <3 x float> %high) nounwind readonly {
+  %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %_low = shufflevector <3 x float> %low, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %_high = shufflevector <3 x float> %high, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
+  %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
+  %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %c
+}
+
+define <3 x float> @_Z5clampDv3_fff(<3 x float> %value, float %low, float %high) nounwind readonly {
+  %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
+  %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
+  %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
+  %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
+  %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %c
+}
+
+define <2 x float> @_Z5clampDv2_fS_S_(<2 x float> %value, <2 x float> %low, <2 x float> %high) nounwind readonly {
+  %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %high) nounwind readnone
+  %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %low) nounwind readnone
+  ret <2 x float> %2
+}
+
+define <2 x float> @_Z5clampDv2_fff(<2 x float> %value, float %low, float %high) nounwind readonly {
+  %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
+  %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
+  %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %_high) nounwind readnone
+  %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
+  ret <2 x float> %b
+}
+
+
+define float @_Z5clampfff(float %value, float %low, float %high) nounwind readonly {
+  %_value = tail call <2 x float> @smear_2f(float %value) nounwind readnone
+  %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
+  %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
+  %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %_value, <2 x float> %_high) nounwind readnone
+  %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
+  %c = extractelement <2 x float> %b, i32 0
+  ret float %c
+}
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;                  FMAX                  ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z4fmaxDv4_fS_(<4 x float> %v1, <4 x float> %v2) nounwind readonly {
+  %1 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %v1, <4 x float> %v2) nounwind readnone
+  ret <4 x float> %1
+}
+
+define <4 x float> @_Z4fmaxDv4_ff(<4 x float> %v1, float %v2) nounwind readonly {
+  %1 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+  %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %v1, <4 x float> %1) nounwind readnone
+  ret <4 x float> %2
+}
+
+define <3 x float> @_Z4fmaxDv3_fS_(<3 x float> %v1, <3 x float> %v2) nounwind readonly {
+  %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = shufflevector <3 x float> %v2, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %3 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+  %4 = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %4
+}
+
+define <3 x float> @_Z4fmaxDv3_ff(<3 x float> %v1, float %v2) nounwind readonly {
+  %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+  %3 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+  %c = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %c
+}
+
+define <2 x float> @_Z4fmaxDv2_fS_(<2 x float> %v1, <2 x float> %v2) nounwind readonly {
+  %1 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %v1, <2 x float> %v2) nounwind readnone
+  ret <2 x float> %1
+}
+
+define <2 x float> @_Z4fmaxDv2_ff(<2 x float> %v1, float %v2) nounwind readonly {
+  %1 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+  %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %v1, <2 x float> %1) nounwind readnone
+  ret <2 x float> %2
+}
+
+define float @_Z4fmaxff(float %v1, float %v2) nounwind readonly {
+  %1 = tail call <2 x float> @smear_2f(float %v1) nounwind readnone
+  %2 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+  %3 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %2) nounwind readnone
+  %4 = extractelement <2 x float> %3, i32 0
+  ret float %4
+}
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;                  FMIN                  ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z4fminDv4_fS_(<4 x float> %v1, <4 x float> %v2) nounwind readonly {
+  %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %v1, <4 x float> %v2) nounwind readnone
+  ret <4 x float> %1
+}
+
+define <4 x float> @_Z4fminDv4_ff(<4 x float> %v1, float %v2) nounwind readonly {
+  %1 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+  %2 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %v1, <4 x float> %1) nounwind readnone
+  ret <4 x float> %2
+}
+
+define <3 x float> @_Z4fminDv3_fS_(<3 x float> %v1, <3 x float> %v2) nounwind readonly {
+  %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = shufflevector <3 x float> %v2, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %3 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+  %4 = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %4
+}
+
+define <3 x float> @_Z4fminDv3_ff(<3 x float> %v1, float %v2) nounwind readonly {
+  %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %2 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+  %3 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+  %c = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  ret <3 x float> %c
+}
+
+define <2 x float> @_Z4fminDv2_fS_(<2 x float> %v1, <2 x float> %v2) nounwind readonly {
+  %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %v1, <2 x float> %v2) nounwind readnone
+  ret <2 x float> %1
+}
+
+define <2 x float> @_Z4fminDv2_ff(<2 x float> %v1, float %v2) nounwind readonly {
+  %1 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+  %2 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %v1, <2 x float> %1) nounwind readnone
+  ret <2 x float> %2
+}
+
+define float @_Z4fminff(float %v1, float %v2) nounwind readonly {
+  %1 = tail call <2 x float> @smear_2f(float %v1) nounwind readnone
+  %2 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+  %3 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %1, <2 x float> %2) nounwind readnone
+  %4 = extractelement <2 x float> %3, i32 0
+  ret float %4
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;                  YUV                   ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+@yuv_U = internal constant <4 x i32> <i32 0, i32 -100, i32 516, i32 0>, align 16
+@yuv_V = internal constant <4 x i32> <i32 409, i32 -208, i32 0, i32 0>, align 16
+@yuv_0 = internal constant <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 16
+@yuv_255 = internal constant <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>, align 16
+
+
+define <4 x i8> @_Z18rsYuvToRGBA_uchar4hhh(i8 %pY, i8 %pU, i8 %pV) nounwind readnone alwaysinline {
+  %_sy = zext i8 %pY to i32
+  %_su = zext i8 %pU to i32
+  %_sv = zext i8 %pV to i32
+
+  %_sy2 = add i32 -16, %_sy
+  %_sy3 = mul i32 298, %_sy2
+  %_su2 = add i32 -128, %_su
+  %_sv2 = add i32 -128, %_sv
+  %_y = tail call <4 x i32> @smear_4i32(i32 %_sy3) nounwind readnone
+  %_u = tail call <4 x i32> @smear_4i32(i32 %_su2) nounwind readnone
+  %_v = tail call <4 x i32> @smear_4i32(i32 %_sv2) nounwind readnone
+
+  %mu = load <4 x i32>* @yuv_U, align 8
+  %mv = load <4 x i32>* @yuv_V, align 8
+  %_u2 = mul <4 x i32> %_u, %mu
+  %_v2 = mul <4 x i32> %_v, %mv
+  %_y2 = add <4 x i32> %_y, %_u2
+  %_y3 = add <4 x i32> %_y2, %_v2
+
+ ; %r1 = tail call <4 x i16> @llvm.arm.neon.vqshiftnsu.v4i16(<4 x i32> %_y3, <4 x i32> <i32 8, i32 8, i32 8, i32 8>) nounwind readnone
+;  %r2 = trunc <4 x i16> %r1 to <4 x i8>
+;  ret <4 x i8> %r2
+
+  %c0 = load <4 x i32>* @yuv_0, align 8
+  %c255 = load <4 x i32>* @yuv_255, align 8
+  %r1 = tail call <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32> %_y3, <4 x i32> %c0) nounwind readnone
+  %r2 = tail call <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32> %r1, <4 x i32> %c255) nounwind readnone
+  %r3 = lshr <4 x i32> %r2, <i32 8, i32 8, i32 8, i32 8>
+  %r4 = trunc <4 x i32> %r3 to <4 x i8>
+  ret <4 x i8> %r4
+}
+
diff --git a/lib/ScriptCRT/clamp.c b/lib/ScriptCRT/clamp.c
deleted file mode 100644
index c7e2c39..0000000
--- a/lib/ScriptCRT/clamp.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-
-#include "rs_types.rsh"
-
-extern float __attribute__((overloadable)) clamp(float amount, float low, float high) {
-    return amount < low ? low : (amount > high ? high : amount);
-}
-
-extern float2 __attribute__((overloadable)) clamp(float2 amount, float2 low, float2 high) {
-    float2 r;
-    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
-    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
-    return r;
-}
-
-extern float3 __attribute__((overloadable)) clamp(float3 amount, float3 low, float3 high) {
-    float3 r;
-    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
-    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
-    r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
-    return r;
-}
-
-extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high) {
-    float4 r;
-    r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
-    r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
-    r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
-    r.w = amount.w < low.w ? low.w : (amount.w > high.w ? high.w : amount.w);
-    return r;
-}
-
-extern float2 __attribute__((overloadable)) clamp(float2 amount, float low, float high) {
-    float2 r;
-    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
-    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
-    return r;
-}
-
-extern float3 __attribute__((overloadable)) clamp(float3 amount, float low, float high) {
-    float3 r;
-    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
-    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
-    r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
-    return r;
-}
-
-extern float4 __attribute__((overloadable)) clamp(float4 amount, float low, float high) {
-    float4 r;
-    r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
-    r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
-    r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
-    r.w = amount.w < low ? low : (amount.w > high ? high : amount.w);
-    return r;
-}
-
-
diff --git a/lib/ScriptCRT/neon/clamp.ll b/lib/ScriptCRT/neon/clamp.ll
deleted file mode 100644
index 4bcbdaa..0000000
--- a/lib/ScriptCRT/neon/clamp.ll
+++ /dev/null
@@ -1,81 +0,0 @@
-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 internal <4 x float> @smear_4f(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 internal <2 x float> @smear_2f(float %in) nounwind readnone alwaysinline {
-  %1 = insertelement <2 x float> undef, float %in, i32 0
-  %2 = insertelement <2 x float> %1, float %in, i32 1
-  ret <2 x float> %2
-}
-
-declare <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float>, <2 x float>) nounwind readnone
-declare <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float>, <4 x float>) nounwind readnone
-declare <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float>, <2 x float>) nounwind readnone
-declare <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float>, <4 x float>) nounwind readnone
-
-define <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %low, <4 x float> %high) nounwind readonly {
-  %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %value, <4 x float> %high) nounwind readnone
-  %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %low) nounwind readnone
-  ret <4 x float> %2
-}
-
-define <4 x float> @_Z5clampDv4_fff(<4 x float> %value, float %low, float %high) nounwind readonly {
-  %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
-  %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
-  %out = tail call <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %_low, <4 x float> %_high) nounwind readonly
-  ret <4 x float> %out
-}
-
-define <3 x float> @_Z5clampDv3_fS_S_(<3 x float> %value, <3 x float> %low, <3 x float> %high) nounwind readonly {
-  %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
-  %_low = shufflevector <3 x float> %low, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
-  %_high = shufflevector <3 x float> %high, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
-  %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
-  %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
-  %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
-  ret <3 x float> %c
-}
-
-define <3 x float> @_Z5clampDv3_fff(<3 x float> %value, float %low, float %high) nounwind readonly {
-  %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
-  %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
-  %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
-  %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
-  %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
-  %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
-  ret <3 x float> %c
-}
-
-
-define <2 x float> @_Z5clampDv2_fS_S_(<2 x float> %value, <2 x float> %low, <2 x float> %high) nounwind readonly {
-  %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %high) nounwind readnone
-  %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %low) nounwind readnone
-  ret <2 x float> %2
-}
-
-define <2 x float> @_Z5clampDv2_fff(<2 x float> %value, float %low, float %high) nounwind readonly {
-  %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
-  %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
-  %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %_high) nounwind readnone
-  %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
-  ret <2 x float> %b
-}
-
-
-define float @_Z5clampfff(float %value, float %low, float %high) nounwind readonly {
-  %_value = tail call <2 x float> @smear_2f(float %value) nounwind readnone
-  %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
-  %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
-  %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %_value, <2 x float> %_high) nounwind readnone
-  %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
-  %c = extractelement <2 x float> %b, i32 0
-  ret float %c
-}
-
diff --git a/lib/ScriptCRT/rs_cl.c b/lib/ScriptCRT/rs_cl.c
index 8e6f8ef..f8fabc2 100644
--- a/lib/ScriptCRT/rs_cl.c
+++ b/lib/ScriptCRT/rs_cl.c
@@ -447,13 +447,7 @@
 extern float __attribute__((overloadable)) fma(float, float, float);
 FN_FUNC_FN_FN_FN(fma)
 
-extern float __attribute__((overloadable)) fmax(float, float);
-FN_FUNC_FN_FN(fmax);
-FN_FUNC_FN_F(fmax);
-
 extern float __attribute__((overloadable)) fmin(float, float);
-FN_FUNC_FN_FN(fmin);
-FN_FUNC_FN_F(fmin);
 
 extern float __attribute__((overloadable)) fmod(float, float);
 FN_FUNC_FN_FN(fmod)
@@ -751,7 +745,15 @@
 extern float __attribute__((overloadable)) degrees(float radians) {
     return radians * (180.f / M_PI);
 }
-FN_FUNC_FN(degrees)
+extern float2 __attribute__((overloadable)) degrees(float2 radians) {
+    return radians * (180.f / M_PI);
+}
+extern float3 __attribute__((overloadable)) degrees(float3 radians) {
+    return radians * (180.f / M_PI);
+}
+extern float4 __attribute__((overloadable)) degrees(float4 radians) {
+    return radians * (180.f / M_PI);
+}
 
 extern float __attribute__((overloadable)) mix(float start, float stop, float amount) {
     return start + (stop - start) * amount;
@@ -778,7 +780,15 @@
 extern float __attribute__((overloadable)) radians(float degrees) {
     return degrees * (M_PI / 180.f);
 }
-FN_FUNC_FN(radians)
+extern float2 __attribute__((overloadable)) radians(float2 degrees) {
+    return degrees * (M_PI / 180.f);
+}
+extern float3 __attribute__((overloadable)) radians(float3 degrees) {
+    return degrees * (M_PI / 180.f);
+}
+extern float4 __attribute__((overloadable)) radians(float4 degrees) {
+    return degrees * (M_PI / 180.f);
+}
 
 extern float __attribute__((overloadable)) step(float edge, float v) {
     return (v < edge) ? 0.f : 1.f;
diff --git a/lib/ScriptCRT/rs_core.c b/lib/ScriptCRT/rs_core.c
index f655c05..aaf1336 100644
--- a/lib/ScriptCRT/rs_core.c
+++ b/lib/ScriptCRT/rs_core.c
@@ -2,29 +2,11 @@
 #include "rs_graphics.rsh"
 #include "rs_structs.h"
 
-/* Declaration of 4 basic functions in libRS */
-extern void __attribute__((overloadable))
-    rsDebug(const char *, float, float);
-extern void __attribute__((overloadable))
-    rsDebug(const char *, float, float, float);
-extern void __attribute__((overloadable))
-    rsDebug(const char *, float, float, float, float);
+/* Function declarations from libRS */
 extern float4 __attribute__((overloadable)) convert_float4(uchar4 c);
 
 /* Implementation of Core Runtime */
 
-extern void __attribute__((overloadable)) rsDebug(const char *s, float2 v) {
-    rsDebug(s, v.x, v.y);
-}
-
-extern void __attribute__((overloadable)) rsDebug(const char *s, float3 v) {
-    rsDebug(s, v.x, v.y, v.z);
-}
-
-extern void __attribute__((overloadable)) rsDebug(const char *s, float4 v) {
-    rsDebug(s, v.x, v.y, v.z, v.w);
-}
-
 /*
 extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
 {
diff --git a/libbcc-config.mk b/libbcc-config.mk
index 37cc848..90e6fab 100644
--- a/libbcc-config.mk
+++ b/libbcc-config.mk
@@ -30,7 +30,6 @@
 
 libbcc_DEBUG_MC_DISASSEMBLER        := 0
 
-libbcc_USE_LOGGER                   := 1
 libbcc_USE_FUNC_LOGGER              := 0
 libbcc_DEBUG_BCC_REFLECT            := 0
 libbcc_DEBUG_MC_REFLECT             := 0
diff --git a/libbcc-gen-build-stamp.mk b/libbcc-gen-build-stamp.mk
index 22fe81d..a2d8374 100644
--- a/libbcc-gen-build-stamp.mk
+++ b/libbcc-gen-build-stamp.mk
@@ -55,3 +55,7 @@
 	$(transform-generated-source)
 
 LOCAL_GENERATED_SOURCES += $(GEN)
+
+LOCAL_CFLAGS := \
+  -DHAVE_BCC_CONFIG_MK_H \
+  $(LOCAL_CFLAGS)
diff --git a/tools/bcc/Android.mk b/tools/bcc/Android.mk
index 414b4d2..3231228 100644
--- a/tools/bcc/Android.mk
+++ b/tools/bcc/Android.mk
@@ -14,9 +14,6 @@
 # limitations under the License.
 #
 
-ifeq (darwin,$(BUILD_OS))
-else
-
 LOCAL_PATH := $(call my-dir)
 
 # Executable for host
@@ -36,6 +33,10 @@
 
 LOCAL_MODULE_TAGS := tests eng
 
+# The definition of those functions in libLLVMSupport may elude libbcc due to linker.
+# Should include libLLVMSupport since bcc references some functions within it.
+LOCAL_STATIC_LIBRARIES := libLLVMSupport
+LOCAL_SHARED_LIBRARIES := libbcc
 LOCAL_LDLIBS = -ldl
 
 LOCAL_CFLAGS += -D__HOST__ -Wall -Werror
@@ -60,5 +61,3 @@
 
 include external/stlport/libstlport.mk
 include $(BUILD_EXECUTABLE)
-
-endif