am 6ab612bb: Merge "Add HAS_HW_DIV to control the compilation of __udivsi3."

* commit '6ab612bb58a13c27c9217eb076297594fdf7b0b8':
  Add HAS_HW_DIV to control the compilation of __udivsi3.
diff --git a/Android.mk b/Android.mk
index f9aa1ff..99fcb78 100644
--- a/Android.mk
+++ b/Android.mk
@@ -34,6 +34,9 @@
   libmcldTarget \
   libmcldLDVariant \
   libmcldMC \
+  libmcldObject \
+  libmcldFragment \
+  libmcldCore \
   libmcldSupport \
   libmcldADT \
   libmcldLD
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 319c5f4..a7ef88d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -56,6 +56,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore_neon.bc_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore*.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbcinfo_intermediates)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/include/bcc/AndroidBitcode/ABCCompiler.h b/include/bcc/AndroidBitcode/ABCCompiler.h
index 91b8009..7164149 100644
--- a/include/bcc/AndroidBitcode/ABCCompiler.h
+++ b/include/bcc/AndroidBitcode/ABCCompiler.h
@@ -28,7 +28,10 @@
   const ABCCompilerDriver &mDriver;
 
 public:
-  ABCCompiler(const ABCCompilerDriver &pDriver) : mDriver(pDriver) { }
+  ABCCompiler(const ABCCompilerDriver &pDriver) : mDriver(pDriver) {
+    // Disable LTO
+    enableLTO(false);
+  }
 
   virtual ~ABCCompiler() { }
 
diff --git a/include/bcc/AndroidBitcode/ABCCompilerDriver.h b/include/bcc/AndroidBitcode/ABCCompilerDriver.h
index 5f5ad7f..a740330 100644
--- a/include/bcc/AndroidBitcode/ABCCompilerDriver.h
+++ b/include/bcc/AndroidBitcode/ABCCompilerDriver.h
@@ -39,7 +39,6 @@
   CompilerConfig *mCompilerConfig;
   LinkerConfig *mLinkerConfig;
 
-  std::string mTriple;
   std::string mAndroidSysroot;
 
 private:
@@ -52,6 +51,10 @@
   bool link(const Script &pScript, const std::string &input_relocatable,
             int pOutputFd);
 
+private:
+  virtual CompilerConfig *createCompilerConfig() const = 0;
+  virtual LinkerConfig *createLinkerConfig() const = 0;
+
 protected:
   virtual const char **getNonPortableList() const {
     return NULL;
@@ -61,7 +64,7 @@
   virtual ABCExpandVAArgPass *createExpandVAArgPass() const = 0;
 
 protected:
-  ABCCompilerDriver(const std::string &pTriple);
+  ABCCompilerDriver();
 
 public:
   static ABCCompilerDriver *Create(const std::string &pTriple);
@@ -76,10 +79,6 @@
     mAndroidSysroot = pAndroidSysroot;
   }
 
-  inline const std::string &getTriple() const {
-    return mTriple;
-  }
-
   // Compile the bitcode and link the shared object
   bool build(int pInputFd, int pOutputFd);
 };
diff --git a/include/bcc/Linker.h b/include/bcc/Linker.h
index 6a3d7d1..43a8839 100644
--- a/include/bcc/Linker.h
+++ b/include/bcc/Linker.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2012, The Android Open Source Project
+ * 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.
@@ -21,12 +21,12 @@
 
 namespace mcld {
 
-class TargetLDBackend;
-class MCLDDriver;
-class MemoryFactory;
-class MCLDInfo;
-class TreeIteratorBase;
+class Module;
+class IRBuilder;
+class LinkerConfig;
+class Linker;
 class Input;
+class MemoryArea;
 
 namespace sys { namespace fs {
 
@@ -38,7 +38,6 @@
 
 namespace bcc {
 
-class MemoryFactory;
 class LinkerConfig;
 
 class Linker {
@@ -46,30 +45,29 @@
   enum ErrorCode {
     kSuccess,
     kDoubleConfig,
-    kCreateBackend,
     kDelegateLDInfo,
     kFindNameSpec,
-    kOpenNameSpec,
     kOpenObjectFile,
+    kOpenMemory,
     kNotConfig,
     kNotSetUpOutput,
     kOpenOutput,
     kReadSections,
     kReadSymbols,
     kAddAdditionalSymbols,
-    kMaxErrorCode,
+    kMaxErrorCode
   };
 
   static const char *GetErrorString(enum ErrorCode pErrCode);
 
 private:
-  mcld::TargetLDBackend *mBackend;
-  mcld::MCLDDriver *mDriver;
-  MemoryFactory *mMemAreaFactory;
-  mcld::MCLDInfo *mLDInfo;
-  mcld::TreeIteratorBase *mRoot;
-  bool mShared;
+  const mcld::LinkerConfig *mLDConfig;
+  mcld::Module *mModule;
+  mcld::Linker *mLinker;
+  mcld::IRBuilder *mBuilder;
   std::string mSOName;
+  std::string mOutputPath;
+  int mOutputHandler;
 
 public:
   Linker();
@@ -96,12 +94,6 @@
 
 private:
   enum ErrorCode extractFiles(const LinkerConfig& pConfig);
-
-  enum ErrorCode openFile(const mcld::sys::fs::Path& pPath,
-                          enum ErrorCode pCode,
-                          mcld::Input& pInput);
-
-  void advanceRoot();
 };
 
 } // end namespace bcc
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index 66a60e4..e42ee73 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -49,7 +49,9 @@
   RSExecutable *compileScript(RSScript &pScript,
                               const char* pScriptName,
                               const char *pOutputPath,
-                              const RSInfo::DependencyTableTy &pDeps);
+                              const char *pRuntimePath,
+                              const RSInfo::DependencyTableTy &pDeps,
+                              bool pSkipLoad);
 
 public:
   RSCompilerDriver();
@@ -61,12 +63,23 @@
   inline void setRSRuntimeLookupContext(void *pContext)
   { mRSRuntime.setContext(pContext); }
 
+  RSCompiler *getCompiler() {
+    return &mCompiler;
+  }
+
+  void setConfig(CompilerConfig *config) {
+    mConfig = config;
+  }
+
   // FIXME: This method accompany with loadScriptCache and compileScript should
   //        all be const-methods. They're not now because the getAddress() in
   //        SymbolResolverInterface is not a const-method.
   RSExecutable *build(BCCContext &pContext,
                       const char *pCacheDir, const char *pResName,
-                      const char *pBitcode, size_t pBitcodeSize);
+                      const char *pBitcode, size_t pBitcodeSize,
+                      const char *pRuntimePath);
+  RSExecutable *build(RSScript &pScript, const char *pOut,
+                      const char *pRuntimePath);
 };
 
 } // end namespace bcc
diff --git a/include/bcc/Renderscript/RSInfo.h b/include/bcc/Renderscript/RSInfo.h
index 91f4d7b..71be3c8 100644
--- a/include/bcc/Renderscript/RSInfo.h
+++ b/include/bcc/Renderscript/RSInfo.h
@@ -153,7 +153,7 @@
 
 public:
   // Calculate or load the SHA-1 information of the built-in dependencies.
-  static void LoadBuiltInSHA1Information();
+  static bool LoadBuiltInSHA1Information();
 
   // Return the path of the RS info file corresponded to the given output
   // executable file.
diff --git a/include/bcc/Renderscript/RSScript.h b/include/bcc/Renderscript/RSScript.h
index 4522ada..7a6e07d 100644
--- a/include/bcc/Renderscript/RSScript.h
+++ b/include/bcc/Renderscript/RSScript.h
@@ -44,33 +44,49 @@
 
   OptimizationLevel mOptimizationLevel;
 
+  bool mEmbedInfo;
+
 private:
   // This will be invoked when the containing source has been reset.
   virtual bool doReset();
 
 public:
-  static bool LinkRuntime(RSScript &pScript);
+  static bool LinkRuntime(RSScript &pScript, const char *rt_path = NULL);
 
   RSScript(Source &pSource);
 
   // Set the associated RSInfo of the script.
-  void setInfo(const RSInfo *pInfo)
-  { mInfo = pInfo; }
+  void setInfo(const RSInfo *pInfo) {
+    mInfo = pInfo;
+  }
 
-  const RSInfo *getInfo() const
-  { return mInfo; }
+  const RSInfo *getInfo() const {
+    return mInfo;
+  }
 
-  void setCompilerVersion(unsigned pCompilerVersion)
-  {  mCompilerVersion = pCompilerVersion; }
+  void setCompilerVersion(unsigned pCompilerVersion) {
+    mCompilerVersion = pCompilerVersion;
+  }
 
-  unsigned getCompilerVersion() const
-  {  return mCompilerVersion; }
+  unsigned getCompilerVersion() const {
+    return mCompilerVersion;
+  }
 
-  void setOptimizationLevel(OptimizationLevel pOptimizationLevel)
-  {  mOptimizationLevel = pOptimizationLevel; }
+  void setOptimizationLevel(OptimizationLevel pOptimizationLevel) {
+    mOptimizationLevel = pOptimizationLevel;
+  }
 
-  OptimizationLevel getOptimizationLevel() const
-  {  return mOptimizationLevel; }
+  OptimizationLevel getOptimizationLevel() const {
+    return mOptimizationLevel;
+  }
+
+  void setEmbedInfo(bool pEnable) {
+    mEmbedInfo = pEnable;
+  }
+
+  bool getEmbedInfo() const {
+    return mEmbedInfo;
+  }
 };
 
 } // end namespace bcc
diff --git a/include/bcc/Renderscript/RSTransforms.h b/include/bcc/Renderscript/RSTransforms.h
index 79b7bd7..3094ba9 100644
--- a/include/bcc/Renderscript/RSTransforms.h
+++ b/include/bcc/Renderscript/RSTransforms.h
@@ -29,6 +29,8 @@
 createRSForEachExpandPass(const RSInfo::ExportForeachFuncListTy &pForeachFuncs,
                           bool pEnableStepOpt);
 
+llvm::ModulePass * createRSEmbedInfoPass(const RSInfo *info);
+
 } // end namespace bcc
 
 #endif // BCC_RS_TRANSFORMS_H
diff --git a/include/bcc/Support/FileBase.h b/include/bcc/Support/FileBase.h
index c201f97..637ced2 100644
--- a/include/bcc/Support/FileBase.h
+++ b/include/bcc/Support/FileBase.h
@@ -38,15 +38,10 @@
   };
 
   enum FlagEnum {
-    // The openning file is a binary file.
     kBinary = 1 << 0,
-
-    // The openning file will be truncated to length 0.
     kTruncate = 1 << 1,
-
-    // The openning file will put its file pointer to the end of the file before
-    // each write.
     kAppend = 1 << 2,
+    kDeleteOnClose = 1 << 3
   };
 
   enum LockModeEnum {
@@ -82,6 +77,9 @@
   // True true if we should call unlock() in destructor.
   bool mShouldUnlock;
 
+  // True if file should be deleted in destructor.
+  bool mShouldDelete;
+
   // Open mName with flag mOpenFlags (using POSIX open().)
   bool open();
 
diff --git a/include/bcc/Support/FileMutex.h b/include/bcc/Support/FileMutex.h
index 15c9f01..82f14b0 100644
--- a/include/bcc/Support/FileMutex.h
+++ b/include/bcc/Support/FileMutex.h
@@ -27,7 +27,7 @@
 class FileMutex : public FileBase {
 public:
   FileMutex(const std::string &pFileToLock)
-    : FileBase(pFileToLock + ".lock", O_RDONLY | O_CREAT, 0) { }
+    : FileBase(pFileToLock + ".lock", O_RDONLY | O_CREAT, kDeleteOnClose) { }
 
   // Provide a lock() interface filled with default configuration.
   inline bool lock(bool pNonblocking = true,
diff --git a/include/bcc/Support/LinkerConfig.h b/include/bcc/Support/LinkerConfig.h
index d1ab0b1..09a08ec 100644
--- a/include/bcc/Support/LinkerConfig.h
+++ b/include/bcc/Support/LinkerConfig.h
@@ -19,7 +19,7 @@
 
 #include <string>
 
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
 #include <mcld/LD/DiagnosticPrinter.h>
@@ -32,7 +32,6 @@
   // Available Configurations
   //===--------------------------------------------------------------------===//
   const std::string mTriple;
-  bool mShared;
   std::string mSOName;
 
 private:
@@ -42,7 +41,7 @@
   const mcld::Target *mTarget;
   bool initializeTarget();
 
-  mcld::MCLDInfo *mLDInfo;
+  mcld::LinkerConfig *mLDConfig;
   bool initializeLDInfo();
 
   mcld::DiagnosticLineInfo *mDiagLineInfo;
@@ -50,6 +49,26 @@
   bool initializeDiagnostic();
 
 public:
+  enum ZOptionEnum {
+    kCombReloc     = 1 << 0,  ///< [on] -z combreloc, [off] -z nocombreloc
+    kDefs          = 1 << 1,  ///< -z defs
+    kExecStack     = 1 << 2,  ///< [on] -z execstack, [off] -z noexecstack
+    kInitFirst     = 1 << 3,  ///< -z initfirst
+    kInterPose     = 1 << 4,  ///< -z interpose
+    kLoadFltr      = 1 << 5,  ///< -z loadfltr
+    kMulDefs       = 1 << 6,  ///< -z muldefs
+    kNoCopyReloc   = 1 << 7,  ///< -z nocopyreloc
+    kNoDefaultLib  = 1 << 8,  ///< -z nodefaultlib
+    kNoDelete      = 1 << 9,  ///< -z nodelete
+    kNoDLOpen      = 1 << 10, ///< -z nodlopen
+    kNoDump        = 1 << 11, ///< -z nodump
+    kRelro         = 1 << 12, ///< [on] -z relro, [off] -z norelro
+    kLazy          = 1 << 13, ///< [on] -z lazy, [off] -z now
+    kOrigin        = 1 << 14, ///< -z origin
+    kZOptionMask   = 0xFFFF
+  };
+
+public:
   //===--------------------------------------------------------------------===//
   // Getters
   //===--------------------------------------------------------------------===//
@@ -59,14 +78,13 @@
   inline const mcld::Target *getTarget() const
   { return mTarget; }
 
-  inline mcld::MCLDInfo* getLDInfo()
-  { return mLDInfo; }
+  inline mcld::LinkerConfig* getLDConfig()
+  { return mLDConfig; }
 
-  inline const mcld::MCLDInfo* getLDInfo() const
-  { return mLDInfo; }
+  inline const mcld::LinkerConfig* getLDConfig() const
+  { return mLDConfig; }
 
-  inline bool isShared() const
-  { return mShared; }
+  bool isShared() const;
 
   inline std::string getSOName() const
   { return mSOName; }
@@ -75,12 +93,16 @@
 
   void setBsymbolic(bool pEnable = true);
 
+  void setDefineCommon(bool pEnable = true);
+
   void setSOName(const std::string &pSOName);
 
   void setDyld(const std::string &pDyld);
 
   void setSysRoot(const std::string &pSysRoot);
 
+  void setZOption(unsigned int pOptions);
+
   void addWrap(const std::string &pWrapSymbol);
 
   void addPortable(const std::string &pPortableSymbol);
diff --git a/include/bcc/Support/TargetCompilerConfigs.h b/include/bcc/Support/TargetCompilerConfigs.h
index 181fd80..391a0eb 100644
--- a/include/bcc/Support/TargetCompilerConfigs.h
+++ b/include/bcc/Support/TargetCompilerConfigs.h
@@ -26,18 +26,39 @@
 // ARM
 //===----------------------------------------------------------------------===//
 #if defined(PROVIDE_ARM_CODEGEN)
-class ARMCompilerConfig : public CompilerConfig {
+class ARMBaseCompilerConfig : public CompilerConfig {
 private:
   bool mEnableNEON;
+  bool mInThumbMode;
+
+  static bool HasThumb2();
 
   static void GetFeatureVector(std::vector<std::string> &pAttributes,
-                               bool pEnableNEON);
+                               bool pInThumbMode, bool pEnableNEON);
+
+protected:
+  ARMBaseCompilerConfig(const std::string &pTriple, bool pInThumbMode);
 
 public:
-  ARMCompilerConfig();
-
   // Return true if config has been changed after returning from this function.
   bool enableNEON(bool pEnable = true);
+
+  bool isInThumbMode() const
+  { return mInThumbMode; }
+};
+
+class ARMCompilerConfig : public ARMBaseCompilerConfig {
+public:
+  ARMCompilerConfig()
+    : ARMBaseCompilerConfig(DEFAULT_ARM_TRIPLE_STRING,
+                            /* pInThumbMode */false) { }
+};
+
+class ThumbCompilerConfig : public ARMBaseCompilerConfig {
+public:
+  ThumbCompilerConfig()
+    : ARMBaseCompilerConfig(DEFAULT_THUMB_TRIPLE_STRING,
+                            /* pInThumbMode */true) { }
 };
 #endif // defined(PROVIDE_ARM_CODEGEN)
 
diff --git a/include/bcc/Support/TargetLinkerConfigs.h b/include/bcc/Support/TargetLinkerConfigs.h
index c0b488b..fd7b7df 100644
--- a/include/bcc/Support/TargetLinkerConfigs.h
+++ b/include/bcc/Support/TargetLinkerConfigs.h
@@ -81,6 +81,16 @@
 #endif
 { };
 
+#if !defined(TARGET_BUILD)
+//===----------------------------------------------------------------------===//
+// General target
+//===----------------------------------------------------------------------===//
+class GeneralLinkerConfig : public LinkerConfig {
+public:
+  GeneralLinkerConfig(const std::string& pTriple);
+};
+#endif // !defined(TARGET_BUILD)
+
 } // end namespace bcc
 
 #endif // BCC_SUPPORT_LINKER_CONFIG_H
diff --git a/lib/AndroidBitcode/ABCCompilerDriver.cpp b/lib/AndroidBitcode/ABCCompilerDriver.cpp
index 4eb33e6..1e5e906 100644
--- a/lib/AndroidBitcode/ABCCompilerDriver.cpp
+++ b/lib/AndroidBitcode/ABCCompilerDriver.cpp
@@ -44,10 +44,9 @@
 
 namespace bcc {
 
-ABCCompilerDriver::ABCCompilerDriver(const std::string &pTriple)
+ABCCompilerDriver::ABCCompilerDriver()
   : mContext(), mCompiler(*this), mLinker(),
-    mCompilerConfig(NULL), mLinkerConfig(NULL),
-    mTriple(pTriple), mAndroidSysroot("/") {
+    mCompilerConfig(NULL), mLinkerConfig(NULL), mAndroidSysroot("/") {
 }
 
 ABCCompilerDriver::~ABCCompilerDriver() {
@@ -60,7 +59,7 @@
     return true;
   }
 
-  mCompilerConfig = new (std::nothrow) CompilerConfig(mTriple);
+  mCompilerConfig = createCompilerConfig();
   if (mCompilerConfig == NULL) {
     ALOGE("Out of memory when create the compiler configuration!");
     return false;
@@ -88,7 +87,7 @@
     return true;
   }
 
-  mLinkerConfig = new (std::nothrow) LinkerConfig(mTriple);
+  mLinkerConfig = createLinkerConfig();
   if (mLinkerConfig == NULL) {
     ALOGE("Out of memory when create the linker configuration!");
     return false;
@@ -118,6 +117,11 @@
   // -Bsymbolic.
   mLinkerConfig->setBsymbolic(true);
 
+  // Set kRelro for -z relro
+  // Not set kExecStack for -z noexecstack
+  // Not set kLazy for -z now
+  mLinkerConfig->setZOption(LinkerConfig::kRelro);
+
   // Config the linker.
   Linker::ErrorCode result = mLinker.config(*mLinkerConfig);
   if (result != Linker::kSuccess) {
@@ -230,19 +234,21 @@
 
   switch (llvm::Triple::getArchTypeForLLVMName(target->getName())) {
 #if defined(PROVIDE_ARM_CODEGEN)
-    case llvm::Triple::arm:
+    case llvm::Triple::arm: {
+      return new ARMABCCompilerDriver(/* pInThumbMode */false);
+    }
     case llvm::Triple::thumb: {
-      return new ARMABCCompilerDriver(pTriple);
+      return new ARMABCCompilerDriver(/* pInThumbMode */true);
     }
 #endif
 #if defined(PROVIDE_MIPS_CODEGEN)
     case llvm::Triple::mipsel: {
-      return new MipsABCCompilerDriver(pTriple);
+      return new MipsABCCompilerDriver();
     }
 #endif
 #if defined(PROVIDE_X86_CODEGEN)
     case llvm::Triple::x86: {
-      return new X86ABCCompilerDriver(pTriple);
+      return new X86ABCCompilerDriver();
     }
 #endif
     default: {
diff --git a/lib/AndroidBitcode/ABCExpandVAArgPass.cpp b/lib/AndroidBitcode/ABCExpandVAArgPass.cpp
index 7b89ced..1f0debf 100644
--- a/lib/AndroidBitcode/ABCExpandVAArgPass.cpp
+++ b/lib/AndroidBitcode/ABCExpandVAArgPass.cpp
@@ -19,6 +19,7 @@
 
 #include "bcc/AndroidBitcode/ABCExpandVAArgPass.h"
 
+#include <llvm/ADT/STLExtras.h>
 #include <llvm/Instructions.h>
 #include <llvm/Support/InstIterator.h>
 
@@ -33,7 +34,8 @@
 
   // process va_arg inst
   for (llvm::inst_iterator inst = llvm::inst_begin(pFunc),
-          inst_end = llvm::inst_end(pFunc); inst != inst_end; inst++) {
+          inst_end = llvm::inst_end(pFunc), next_inst = llvm::next(inst);
+       inst != inst_end; inst = next_inst++) {
     if (inst->getOpcode() == llvm::Instruction::VAArg) {
       llvm::Value *v = expandVAArg(&*inst);
       inst->replaceAllUsesWith(v);
diff --git a/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.cpp b/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.cpp
new file mode 100644
index 0000000..f019bde
--- /dev/null
+++ b/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "ARM/ARMABCCompilerDriver.h"
+
+#include "bcc/Support/TargetCompilerConfigs.h"
+#include "bcc/Support/TargetLinkerConfigs.h"
+
+namespace bcc {
+
+CompilerConfig *ARMABCCompilerDriver::createCompilerConfig() const {
+  if (mInThumbMode) {
+    return new (std::nothrow) ThumbCompilerConfig();
+  } else {
+    return new (std::nothrow) ARMCompilerConfig();
+  }
+}
+
+LinkerConfig *ARMABCCompilerDriver::createLinkerConfig() const {
+  return new (std::nothrow) ARMLinkerConfig();
+}
+
+} // end namespace bcc
diff --git a/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.h b/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.h
index 29f4f0a..97e5f8d 100644
--- a/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.h
+++ b/lib/AndroidBitcode/ARM/ARMABCCompilerDriver.h
@@ -22,13 +22,24 @@
 namespace bcc {
 
 class ARMABCCompilerDriver : public ABCCompilerDriver {
+private:
+  bool mInThumbMode;
+
 public:
-  ARMABCCompilerDriver(const std::string &pTriple)
-      : ABCCompilerDriver(pTriple) { }
+  ARMABCCompilerDriver(bool pInThumbMode)
+    : ABCCompilerDriver(), mInThumbMode(pInThumbMode) { }
 
   virtual ~ARMABCCompilerDriver() { }
 
+public:
+  inline bool IsInThumbMode() const {
+    return mInThumbMode;
+  }
+
 private:
+  virtual CompilerConfig *createCompilerConfig() const;
+  virtual LinkerConfig *createLinkerConfig() const;
+
   virtual ABCExpandVAArgPass *createExpandVAArgPass() const;
 };
 
diff --git a/lib/AndroidBitcode/Android.mk b/lib/AndroidBitcode/Android.mk
index 806202c..0befc55 100644
--- a/lib/AndroidBitcode/Android.mk
+++ b/lib/AndroidBitcode/Android.mk
@@ -27,6 +27,7 @@
   ABCCompilerDriver.cpp
 
 libbcc_arm_androidbitcode_SRC_FILES := \
+  ARM/ARMABCCompilerDriver.cpp \
   ARM/ARMABCExpandVAArg.cpp
 
 libbcc_mips_androidbitcode_SRC_FILES := \
diff --git a/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.cpp b/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.cpp
index 54b9d61..326920a 100644
--- a/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.cpp
+++ b/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.cpp
@@ -16,6 +16,9 @@
 
 #include "Mips/MipsABCCompilerDriver.h"
 
+#include "bcc/Support/TargetCompilerConfigs.h"
+#include "bcc/Support/TargetLinkerConfigs.h"
+
 namespace {
 
 static const char *MipsNonPortableList[] = {
@@ -37,6 +40,14 @@
 
 namespace bcc {
 
+CompilerConfig *MipsABCCompilerDriver::createCompilerConfig() const {
+  return new (std::nothrow) MipsCompilerConfig();
+}
+
+LinkerConfig *MipsABCCompilerDriver::createLinkerConfig() const {
+  return new (std::nothrow) MipsLinkerConfig();
+}
+
 const char **MipsABCCompilerDriver::getNonPortableList() const {
   return MipsNonPortableList;
 }
diff --git a/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.h b/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.h
index 7cfc34f..6cdecc5 100644
--- a/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.h
+++ b/lib/AndroidBitcode/Mips/MipsABCCompilerDriver.h
@@ -23,12 +23,14 @@
 
 class MipsABCCompilerDriver : public ABCCompilerDriver {
 public:
-  MipsABCCompilerDriver(const std::string &pTriple)
-      : ABCCompilerDriver(pTriple) { }
+  MipsABCCompilerDriver() : ABCCompilerDriver() { }
 
   virtual ~MipsABCCompilerDriver() { }
 
 private:
+  virtual CompilerConfig *createCompilerConfig() const;
+  virtual LinkerConfig *createLinkerConfig() const;
+
   virtual const char **getNonPortableList() const;
 
   virtual ABCExpandVAArgPass *createExpandVAArgPass() const;
diff --git a/lib/AndroidBitcode/X86/X86ABCCompilerDriver.cpp b/lib/AndroidBitcode/X86/X86ABCCompilerDriver.cpp
index 171da7c..e8f0159 100644
--- a/lib/AndroidBitcode/X86/X86ABCCompilerDriver.cpp
+++ b/lib/AndroidBitcode/X86/X86ABCCompilerDriver.cpp
@@ -16,6 +16,9 @@
 
 #include "X86/X86ABCCompilerDriver.h"
 
+#include "bcc/Support/TargetCompilerConfigs.h"
+#include "bcc/Support/TargetLinkerConfigs.h"
+
 namespace {
 
 static const char *X86NonPortableList[] = {
@@ -36,6 +39,16 @@
 
 namespace bcc {
 
+CompilerConfig *X86ABCCompilerDriver::createCompilerConfig() const {
+  // x86-64 is currently unsupported.
+  return new (std::nothrow) X86_32CompilerConfig();
+}
+
+LinkerConfig *X86ABCCompilerDriver::createLinkerConfig() const {
+  // x86-64 is currently unsupported.
+  return new (std::nothrow) X86_32LinkerConfig();
+}
+
 const char **X86ABCCompilerDriver::getNonPortableList() const {
   return X86NonPortableList;
 }
diff --git a/lib/AndroidBitcode/X86/X86ABCCompilerDriver.h b/lib/AndroidBitcode/X86/X86ABCCompilerDriver.h
index af52866..aed2f56 100644
--- a/lib/AndroidBitcode/X86/X86ABCCompilerDriver.h
+++ b/lib/AndroidBitcode/X86/X86ABCCompilerDriver.h
@@ -23,12 +23,14 @@
 
 class X86ABCCompilerDriver : public ABCCompilerDriver {
 public:
-  X86ABCCompilerDriver(const std::string &pTriple)
-      : ABCCompilerDriver(pTriple) { }
+  X86ABCCompilerDriver() : ABCCompilerDriver() { }
 
   virtual ~X86ABCCompilerDriver() { }
 
 private:
+  virtual CompilerConfig *createCompilerConfig() const;
+  virtual LinkerConfig *createLinkerConfig() const;
+
   virtual const char **getNonPortableList() const;
 
   virtual ABCExpandVAArgPass *createExpandVAArgPass() const;
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
index e6cbc95..87bc389 100644
--- a/lib/Core/Linker.cpp
+++ b/lib/Core/Linker.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2012, The Android Open Source Project
+ * 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.
@@ -16,23 +16,17 @@
 
 #include "bcc/Linker.h"
 #include "bcc/Support/LinkerConfig.h"
-#include "bcc/Support/MemoryFactory.h"
 #include "bcc/Support/Log.h"
 
 #include <llvm/Support/ELF.h>
 
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/InputTree.h>
+#include <mcld/Module.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Linker.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDContext.h>
-#include <mcld/Target/TargetLDBackend.h>
 #include <mcld/Support/Path.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/TargetRegistry.h>
 
 using namespace bcc;
 
@@ -42,14 +36,10 @@
     "Successfully compiled.",
     /* kDoubleConfig */
     "Configure Linker twice.",
-    /* kCreateBackend */
-    "Cannot create backend.",
     /* kDelegateLDInfo */
     "Cannot get linker information",
     /* kFindNameSpec */
     "Cannot find -lnamespec",
-    /* kOpenNameSpec */
-    "Cannot open -lnamespec",
     /* kOpenObjectFile */
     "Cannot open object file",
     /* kNotConfig */
@@ -79,13 +69,13 @@
 // Linker
 //===----------------------------------------------------------------------===//
 Linker::Linker()
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
-    mRoot(NULL), mShared(false) {
+  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
+    mOutputHandler(-1) {
 }
 
 Linker::Linker(const LinkerConfig& pConfig)
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
-    mRoot(NULL), mShared(false) {
+  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
+    mOutputHandler(-1) {
 
   const std::string &triple = pConfig.getTriple();
 
@@ -99,286 +89,93 @@
 }
 
 Linker::~Linker() {
-  delete mDriver;
-  delete mBackend;
-  delete mMemAreaFactory;
-  delete mRoot;
+  delete mModule;
+  delete mLinker;
+  delete mBuilder;
 }
 
 enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
-  mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
-  if (mLDInfo == NULL) {
+  mLDConfig = pConfig.getLDConfig();
+  if (mLDConfig == NULL) {
     return kDelegateLDInfo;
   }
-
-  mRoot = new mcld::InputTree::iterator(mLDInfo->inputs().root());
-  mShared = pConfig.isShared();
-  mSOName = pConfig.getSOName();
-
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
-  if (mLDInfo != NULL) {
+  if (mLDConfig != NULL) {
     return kDoubleConfig;
   }
 
   extractFiles(pConfig);
 
-  mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
-  if (mBackend == NULL) {
-    return kCreateBackend;
-  }
+  mModule = new mcld::Module(mLDConfig->options().soname());
 
-  mMemAreaFactory = new MemoryFactory();
+  mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
 
-  mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend, *mMemAreaFactory);
+  mLinker = new mcld::Linker();
 
-  mDriver->initMCLinker();
+  mLinker->config(const_cast<mcld::LinkerConfig&>(*mLDConfig));
 
   return kSuccess;
 }
 
-void Linker::advanceRoot() {
-  if (mRoot->isRoot()) {
-    mRoot->move<mcld::TreeIteratorBase::Leftward>();
-  } else {
-    mRoot->move<mcld::TreeIteratorBase::Rightward>();
-  }
-  return;
-}
-
-enum Linker::ErrorCode Linker::openFile(const mcld::sys::fs::Path& pPath,
-                                        enum Linker::ErrorCode pCode,
-                                        mcld::Input& pInput) {
-  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pPath,
-                                                    mcld::FileHandle::ReadOnly);
-
-  if (input_memory->handler()->isGood()) {
-    pInput.setMemArea(input_memory);
-  } else {
-    return pCode;
-  }
-
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
-  pInput.setContext(input_context);
-  return kSuccess;
-}
-
 enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
-  mcld::sys::fs::Path* path = NULL;
-  // find out the real path of the namespec.
-  if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
-    // In the system with shared object support, we can find both archive
-    // and shared object.
-
-    if (mLDInfo->attrFactory().last().isStatic()) {
-      // with --static, we must search an archive.
-      path = mLDInfo->options().directories().find(pNameSpec,
-                                                   mcld::Input::Archive);
-    }
-    else {
-      // otherwise, with --Bdynamic, we can find either an archive or a
-      // shared object.
-      path = mLDInfo->options().directories().find(pNameSpec,
-                                                   mcld::Input::DynObj);
-    }
-  }
-  else {
-    // In the system without shared object support, we only look for an
-    // archive.
-    path = mLDInfo->options().directories().find(pNameSpec,
-                                                 mcld::Input::Archive);
-  }
-
-  if (NULL == path)
+  mcld::Input* input = mBuilder->ReadInput(pNameSpec);
+  if (NULL == input)
     return kFindNameSpec;
-
-  mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
-                                                       mcld::Input::Unknown);
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
-  advanceRoot();
-
-  return openFile(*path, kOpenNameSpec, *input);
+  return kSuccess;
 }
 
 /// addObject - Add a object file by the filename.
 enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
-  mcld::Input* input = mLDInfo->inputFactory().produce(pObjectPath,
-                                                       pObjectPath,
-                                                       mcld::Input::Unknown);
-
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
-  advanceRoot();
-
-  return openFile(pObjectPath, kOpenObjectFile, *input);
+  mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
+  if (NULL == input)
+    return kOpenObjectFile;
+  return kSuccess;
 }
 
 /// addObject - Add a piece of memory. The memory is of ELF format.
 enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
-
-  mcld::Input* input = mLDInfo->inputFactory().produce("memory object",
-                                                       "NAN",
-                                                       mcld::Input::Unknown);
-
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
-  advanceRoot();
-
-  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
-  input->setMemArea(input_memory);
-
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
-  input->setContext(input_context);
-
+  mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
+  if (NULL == input)
+    return kOpenMemory;
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
-  mcld::Input* input = mLDInfo->inputFactory().produce("code object",
-                                                       "NAN",
-                                                       mcld::Input::External);
-
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
-  advanceRoot();
-
-  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
-  input->setMemArea(input_memory);
-
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
-  input->setContext(input_context);
-
-  // FIXME: So far, MCLinker must set up output before add input files.
-  // set up LDContext
-  if (mDriver->hasInitLinker()) {
-    return kNotConfig;
-  }
-
-  if (!mLDInfo->output().hasContext()) {
-    return kNotSetUpOutput;
-  }
-
-  // create NULL section
-  mcld::LDSection& null =
-      mDriver->getLinker()->createSectHdr("",
-                                          mcld::LDFileFormat::Null,
-                                          llvm::ELF::SHT_NULL,
-                                          0);
-
-  null.setSize(0);
-  null.setOffset(0);
-  null.setIndex(0);
-  null.setInfo(0);
-  null.setAlign(0);
-
-  input_context->getSectionTable().push_back(&null);
-
-  // create .text section
-  mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
-                              mcld::LDFileFormat::Regular,
-                              llvm::ELF::SHT_PROGBITS,
-                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
-
-  text.setSize(pSize);
-  text.setOffset(0x0);
-  text.setIndex(1);
-  text.setInfo(0);
-  text.setAlign(1);
-
-  input_context->getSectionTable().push_back(&text);
-
+  mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
+  mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
+                                llvm::ELF::SHT_PROGBITS,
+                                llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+                                0x1);
+  mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
+  mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
+  mBuilder->AppendFragment(*frag, *data);
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
-  if (mLDInfo->output().hasContext()) {
-    return kDoubleConfig;
-  }
-
-  // -----  initialize output file  ----- //
-
-  mcld::FileHandle::Permission perm = 0755;
-
-  mcld::MemoryArea* out_area = mMemAreaFactory->produce(
-                      pPath,
-                      mcld::FileHandle::ReadWrite |
-                        mcld::FileHandle::Truncate |
-                        mcld::FileHandle::Create,
-                      perm);
-
-  if (!out_area->handler()->isGood()) {
-    return kOpenOutput;
-  }
-
-  if (mShared) {
-    mLDInfo->output().setType(mcld::Output::DynObj);
-  } else {
-    mLDInfo->output().setType(mcld::Output::Exec);
-  }
-
-  mLDInfo->output().setSOName(mSOName);
-  mLDInfo->output().setMemArea(out_area);
-  mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
-
-  // FIXME: We must initialize MCLinker before setOutput, and initialize
-  // standard sections here. This is because we have to build the section
-  // map before input files using it.
-  if (!mDriver->hasInitLinker()) {
-    return kNotConfig;
-  }
-
-  mDriver->initStdSections();
-
+  mOutputPath = pPath;
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
-  if (mLDInfo->output().hasContext()) {
-    return kDoubleConfig;
-  }
-
-  // -----  initialize output file  ----- //
-  mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
-
-  mLDInfo->output().setType(mcld::Output::DynObj);
-  mLDInfo->output().setMemArea(out_area);
-  mLDInfo->output().setContext(mLDInfo->contextFactory().produce());
-
-  // FIXME: We must initialize MCLinker before setOutput, and initialize
-  // standard sections here. This is because we have to build the section
-  // map before input files using it.
-  if (!mDriver->hasInitLinker()) {
-    return kNotConfig;
-  }
-
-  mDriver->initStdSections();
-
+  mOutputHandler = pFileHandler;
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::link() {
-  mDriver->normalize();
-
-  if (!mDriver->mergeSections()) {
-    return kReadSections;
+  mLinker->link(*mModule, *mBuilder);
+  if (!mOutputPath.empty()) {
+    mLinker->emit(mOutputPath);
+    return kSuccess;
   }
 
-  if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
-    return kAddAdditionalSymbols;
+  if (-1 != mOutputHandler) {
+    mLinker->emit(mOutputHandler);
+    return kSuccess;
   }
-
-  mDriver->readRelocations();
-  mDriver->prelayout();
-  mDriver->layout();
-  mDriver->postlayout();
-  mDriver->finalizeSymbolValue();
-  mDriver->relocation();
-  mDriver->emitOutput();
-  mDriver->postProcessing();
-
-  return kSuccess;
+  return kNotSetUpOutput;
 }
 
diff --git a/lib/Renderscript/Android.mk b/lib/Renderscript/Android.mk
index 6989d5b..bbd1e64 100644
--- a/lib/Renderscript/Android.mk
+++ b/lib/Renderscript/Android.mk
@@ -24,6 +24,7 @@
 libbcc_renderscript_SRC_FILES := \
   RSCompiler.cpp \
   RSCompilerDriver.cpp \
+  RSEmbedInfo.cpp \
   RSExecutable.cpp \
   RSForEachExpand.cpp \
   RSInfo.cpp \
diff --git a/lib/Renderscript/RSCompiler.cpp b/lib/Renderscript/RSCompiler.cpp
index 7ba1cff..ce43e8b 100644
--- a/lib/Renderscript/RSCompiler.cpp
+++ b/lib/Renderscript/RSCompiler.cpp
@@ -106,6 +106,9 @@
   // Expand ForEach on CPU path to reduce launch overhead.
   rs_passes.add(createRSForEachExpandPass(info->getExportForeachFuncs(),
                                           /* pEnableStepOpt */ true));
+  if (script.getEmbedInfo()) {
+    rs_passes.add(createRSEmbedInfoPass(info));
+  }
 
   // Execute the pass.
   rs_passes.run(module);
diff --git a/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index c854b69..1251c3c 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -184,7 +184,9 @@
 RSCompilerDriver::compileScript(RSScript &pScript,
                                 const char* pScriptName,
                                 const char *pOutputPath,
-                                const RSInfo::DependencyTableTy &pDeps) {
+                                const char *pRuntimePath,
+                                const RSInfo::DependencyTableTy &pDeps,
+                                bool pSkipLoad) {
   android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
   RSExecutable *result = NULL;
   RSInfo *info = NULL;
@@ -209,7 +211,7 @@
   //===--------------------------------------------------------------------===//
   // Link RS script with Renderscript runtime.
   //===--------------------------------------------------------------------===//
-  if (!RSScript::LinkRuntime(pScript)) {
+  if (!RSScript::LinkRuntime(pScript, pRuntimePath)) {
     ALOGE("Failed to link script '%s' with Renderscript runtime!", pScriptName);
     return NULL;
   }
@@ -276,6 +278,12 @@
     return NULL;
   }
 
+  // No need to produce an RSExecutable in this case.
+  // TODO: Error handling in this case is nonexistent.
+  if (pSkipLoad) {
+    return NULL;
+  }
+
   //===--------------------------------------------------------------------===//
   // Create the RSExecutable.
   //===--------------------------------------------------------------------===//
@@ -317,7 +325,8 @@
                                       const char *pCacheDir,
                                       const char *pResName,
                                       const char *pBitcode,
-                                      size_t pBitcodeSize) {
+                                      size_t pBitcodeSize,
+                                      const char *pRuntimePath) {
   android::StopWatch build_time("bcc: RSCompilerDriver::build time");
   //===--------------------------------------------------------------------===//
   // Check parameters.
@@ -393,7 +402,8 @@
   //===--------------------------------------------------------------------===//
   // Compile the script
   //===--------------------------------------------------------------------===//
-  result = compileScript(*script, pResName, output_path.c_str(), dep_info);
+  result = compileScript(*script, pResName, output_path.c_str(), pRuntimePath,
+                         dep_info, false);
 
   // Script is no longer used. Free it to get more memory.
   delete script;
@@ -404,3 +414,23 @@
 
   return result;
 }
+
+
+RSExecutable *RSCompilerDriver::build(RSScript &pScript, const char *pOut,
+                                      const char *pRuntimePath) {
+  RSInfo::DependencyTableTy dep_info;
+  RSInfo *info = RSInfo::ExtractFromSource(pScript.getSource(), dep_info);
+  if (info == NULL) {
+    return NULL;
+  }
+  pScript.setInfo(info);
+
+  // Embed the info string directly in the ELF, since this path is for an
+  // offline (host) compilation.
+  pScript.setEmbedInfo(true);
+
+  RSExecutable *result = compileScript(pScript, pOut, pOut, pRuntimePath,
+                                       dep_info, true);
+  return result;
+}
+
diff --git a/lib/Renderscript/RSEmbedInfo.cpp b/lib/Renderscript/RSEmbedInfo.cpp
new file mode 100644
index 0000000..faa71bf
--- /dev/null
+++ b/lib/Renderscript/RSEmbedInfo.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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 "bcc/Assert.h"
+#include "bcc/Renderscript/RSTransforms.h"
+
+#include <cstdlib>
+#include <vector>
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/IRBuilder.h>
+#include <llvm/Module.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Type.h>
+
+#include "bcc/Config/Config.h"
+#include "bcc/Renderscript/RSInfo.h"
+#include "bcc/Support/Log.h"
+
+using namespace bcc;
+
+namespace {
+
+/* RSForEachExpandPass - 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 RSEmbedInfoPass : public llvm::ModulePass {
+private:
+  static char ID;
+
+  llvm::Module *M;
+  llvm::LLVMContext *C;
+
+  const RSInfo *mInfo;
+
+public:
+  RSEmbedInfoPass(const RSInfo *info)
+      : ModulePass(ID),
+        mInfo(info) {
+  }
+
+  virtual bool runOnModule(llvm::Module &M) {
+    this->M = &M;
+    C = &M.getContext();
+
+    std::string str;
+    llvm::raw_string_ostream s(str);
+
+    // We use a simple text format here that the compatibility library can
+    // easily parse. Each section starts out with its name followed by a count.
+    // The count denotes the number of lines to parse for that particular
+    // category. Variables and Functions merely put the appropriate identifier
+    // on the line, while ForEach kernels have the encoded int signature,
+    // followed by a hyphen followed by the identifier (function to look up).
+    // Object Slots are just listed as one integer per line.
+    const RSInfo::ExportVarNameListTy &export_vars = mInfo->getExportVarNames();
+    s << "exportVarCount: " << (unsigned int) export_vars.size() << "\n";
+    for (RSInfo::ExportVarNameListTy::const_iterator
+             export_var_iter = export_vars.begin(),
+             export_var_end = export_vars.end();
+         export_var_iter != export_var_end; export_var_iter++) {
+      s << *export_var_iter << "\n";
+    }
+
+    const RSInfo::ExportFuncNameListTy &export_funcs =
+        mInfo->getExportFuncNames();
+    s << "exportFuncCount: " << (unsigned int) export_funcs.size() << "\n";
+    for (RSInfo::ExportFuncNameListTy::const_iterator
+             export_func_iter = export_funcs.begin(),
+             export_func_end = export_funcs.end();
+         export_func_iter != export_func_end; export_func_iter++) {
+      s << *export_func_iter << "\n";
+    }
+
+    const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
+        mInfo->getExportForeachFuncs();
+    s << "exportForEachCount: "
+      << (unsigned int) export_foreach_funcs.size() << "\n";
+    for (RSInfo::ExportForeachFuncListTy::const_iterator
+             foreach_func_iter = export_foreach_funcs.begin(),
+             foreach_func_end = export_foreach_funcs.end();
+         foreach_func_iter != foreach_func_end; foreach_func_iter++) {
+      std::string name(foreach_func_iter->first);
+      s << foreach_func_iter->second << " - "
+        << foreach_func_iter->first << "\n";
+    }
+
+    std::vector<unsigned int> object_slot_numbers;
+    unsigned int i = 0;
+    const RSInfo::ObjectSlotListTy &object_slots = mInfo->getObjectSlots();
+    for (RSInfo::ObjectSlotListTy::const_iterator
+             slots_iter = object_slots.begin(),
+             slots_end = object_slots.end();
+         slots_iter != slots_end; slots_iter++) {
+      if (*slots_iter) {
+        object_slot_numbers.push_back(i);
+      }
+      i++;
+    }
+    s << "objectSlotCount: " << (unsigned int) object_slot_numbers.size()
+      << "\n";
+    for (i = 0; i < object_slot_numbers.size(); i++) {
+      s << object_slot_numbers[i] << "\n";
+    }
+
+    s.flush();
+
+    // Embed this as the global variable .rs.info so that it will be
+    // accessible from the shared object later.
+    llvm::Constant *Init = llvm::ConstantDataArray::getString(*C, str);
+    llvm::GlobalVariable *InfoGV =
+        new llvm::GlobalVariable(M, Init->getType(), true,
+                                 llvm::GlobalValue::ExternalLinkage, Init,
+                                 ".rs.info");
+    (void) InfoGV;
+
+    return true;
+  }
+
+  virtual const char *getPassName() const {
+    return "Embed Renderscript Info";
+  }
+
+};  // end RSEmbedInfoPass
+
+}  // end anonymous namespace
+
+char RSEmbedInfoPass::ID = 0;
+
+namespace bcc {
+
+llvm::ModulePass *
+createRSEmbedInfoPass(const RSInfo *info) {
+  return new RSEmbedInfoPass(info);
+}
+
+}  // end namespace bcc
diff --git a/lib/Renderscript/RSExecutable.cpp b/lib/Renderscript/RSExecutable.cpp
index c73fd5e..b918835 100644
--- a/lib/Renderscript/RSExecutable.cpp
+++ b/lib/Renderscript/RSExecutable.cpp
@@ -28,11 +28,11 @@
 using namespace bcc;
 
 const char *RSExecutable::SpecialFunctionNames[] = {
-  "root",
-  "init",
-  ".rs.dtor",
-  // Must be NULL-terminated.
-  NULL
+  "root",      // Graphics drawing function or compute kernel.
+  "init",      // Initialization routine called implicitly on startup.
+  ".rs.dtor",  // Static global destructor for a script instance.
+  ".rs.info",  // Variable containing string of RS metadata info.
+  NULL         // Must be NULL-terminated.
 };
 
 RSExecutable *RSExecutable::Create(RSInfo &pInfo,
diff --git a/lib/Renderscript/RSInfo.cpp b/lib/Renderscript/RSInfo.cpp
index dbf8657..ff6a0a2 100644
--- a/lib/Renderscript/RSInfo.cpp
+++ b/lib/Renderscript/RSInfo.cpp
@@ -21,6 +21,7 @@
 
 #include <cstring>
 #include <new>
+#include <string>
 
 #include "bcc/Support/FileBase.h"
 #include "bcc/Support/Log.h"
@@ -43,17 +44,18 @@
 const uint8_t *RSInfo::LibCLCoreNEONSHA1 = NULL;
 #endif
 
-void RSInfo::LoadBuiltInSHA1Information() {
+bool RSInfo::LoadBuiltInSHA1Information() {
+#ifdef TARGET_BUILD
   if (LibBCCSHA1 != NULL) {
     // Loaded before.
-    return;
+    return true;
   }
 
   void *h = ::dlopen("/system/lib/libbcc.sha1.so", RTLD_LAZY | RTLD_NOW);
   if (h == NULL) {
     ALOGE("Failed to load SHA-1 information from shared library '"
           "/system/lib/libbcc.sha1.so'! (%s)", ::dlerror());
-    return;
+    return false;
   }
 
   LibBCCSHA1 = reinterpret_cast<const uint8_t *>(::dlsym(h, "libbcc_so_SHA1"));
@@ -65,7 +67,10 @@
       reinterpret_cast<const uint8_t *>(::dlsym(h, "libclcore_neon_bc_SHA1"));
 #endif
 
-  return;
+  return true;
+#else  // TARGET_BUILD
+  return false;
+#endif  // TARGET_BUILD
 }
 
 android::String8 RSInfo::GetPath(const FileBase &pFile) {
@@ -315,33 +320,36 @@
 
 RSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
   // Check to see if we have any FP precision-related pragmas.
-  static const char relaxed_pragma[] = "rs_fp_relaxed";
-  static const char imprecise_pragma[] = "rs_fp_imprecise";
-  static const char full_pragma[] = "rs_fp_full";
+  std::string relaxed_pragma("rs_fp_relaxed");
+  std::string imprecise_pragma("rs_fp_imprecise");
+  std::string full_pragma("rs_fp_full");
   bool relaxed_pragma_seen = false;
-  RSInfo::FloatPrecision result;
+  bool imprecise_pragma_seen = false;
+  RSInfo::FloatPrecision result = FP_Full;
 
   for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
            pragma_end = mPragmas.end(); pragma_iter != pragma_end;
        pragma_iter++) {
     const char *pragma_key = pragma_iter->first;
-    if (::strcmp(pragma_key, relaxed_pragma) == 0) {
-      relaxed_pragma_seen = true;
-    } else if (::strcmp(pragma_key, imprecise_pragma) == 0) {
-      if (relaxed_pragma_seen) {
-        ALOGW("Multiple float precision pragmas specified!");
+    if (!relaxed_pragma.compare(pragma_key)) {
+      if (relaxed_pragma_seen || imprecise_pragma_seen) {
+        ALOGE("Multiple float precision pragmas specified!");
       }
-      // Fast return when there's rs_fp_imprecise specified.
-      result = FP_Imprecise;
+      relaxed_pragma_seen = true;
+    } else if (!imprecise_pragma.compare(pragma_key)) {
+      if (relaxed_pragma_seen || imprecise_pragma_seen) {
+        ALOGE("Multiple float precision pragmas specified!");
+      }
+      imprecise_pragma_seen = true;
     }
   }
 
   // Imprecise is selected over Relaxed precision.
   // In the absence of both, we stick to the default Full precision.
-  if (relaxed_pragma_seen) {
+  if (imprecise_pragma_seen) {
+    result = FP_Imprecise;
+  } else if (relaxed_pragma_seen) {
     result = FP_Relaxed;
-  } else {
-    result = FP_Full;
   }
 
   // Provide an override for precsion via adb shell setprop
@@ -352,13 +360,13 @@
   property_get("debug.rs.precision", precision_prop_buf, "");
 
   if (precision_prop_buf[0]) {
-    if (::strcmp(precision_prop_buf, relaxed_pragma) == 0) {
+    if (!relaxed_pragma.compare(precision_prop_buf)) {
       ALOGI("Switching to RS FP relaxed mode via setprop");
       result = FP_Relaxed;
-    } else if (::strcmp(precision_prop_buf, imprecise_pragma) == 0) {
+    } else if (!imprecise_pragma.compare(precision_prop_buf)) {
       ALOGI("Switching to RS FP imprecise mode via setprop");
       result = FP_Imprecise;
-    } else if (::strcmp(precision_prop_buf, full_pragma) == 0) {
+    } else if (!full_pragma.compare(precision_prop_buf)) {
       ALOGI("Switching to RS FP full mode via setprop");
       result = FP_Full;
     }
diff --git a/lib/Renderscript/RSInfoExtractor.cpp b/lib/Renderscript/RSInfoExtractor.cpp
index 4ba5703..c0775b5 100644
--- a/lib/Renderscript/RSInfoExtractor.cpp
+++ b/lib/Renderscript/RSInfoExtractor.cpp
@@ -360,46 +360,46 @@
   }
 #undef FOR_EACH_NODE_IN
 
-  //===--------------------------------------------------------------------===//
-  // Record built-in dependency information.
-  //===--------------------------------------------------------------------===//
-  LoadBuiltInSHA1Information();
-
-  if (!writeDependency(LibBCCPath, LibBCCSHA1,
-                       result->mStringPool, &cur_string_pool_offset,
-                       result->mDependencyTable)) {
-    goto bail;
-  }
-
-  if (!writeDependency(LibRSPath, LibRSSHA1,
-                       result->mStringPool, &cur_string_pool_offset,
-                       result->mDependencyTable)) {
-    goto bail;
-  }
-
-  if (!writeDependency(LibCLCorePath, LibCLCoreSHA1,
-                       result->mStringPool, &cur_string_pool_offset,
-                       result->mDependencyTable)) {
-    goto bail;
-  }
-
-#if defined(ARCH_ARM_HAVE_NEON)
-  if (!writeDependency(LibCLCoreNEONPath, LibCLCoreNEONSHA1,
-                       result->mStringPool, &cur_string_pool_offset,
-                       result->mDependencyTable)) {
-    goto bail;
-  }
-#endif
-
-  //===--------------------------------------------------------------------===//
-  // Record dependency information.
-  //===--------------------------------------------------------------------===//
-  for (unsigned i = 0, e = pDeps.size(); i != e; i++) {
-    if (!writeDependency(/* name */pDeps[i].first, /* SHA-1 */pDeps[i].second,
+  if (LoadBuiltInSHA1Information()) {
+    //===------------------------------------------------------------------===//
+    // Record built-in dependency information.
+    //===------------------------------------------------------------------===//
+    if (!writeDependency(LibBCCPath, LibBCCSHA1,
                          result->mStringPool, &cur_string_pool_offset,
                          result->mDependencyTable)) {
       goto bail;
     }
+
+    if (!writeDependency(LibRSPath, LibRSSHA1,
+                         result->mStringPool, &cur_string_pool_offset,
+                         result->mDependencyTable)) {
+      goto bail;
+    }
+
+    if (!writeDependency(LibCLCorePath, LibCLCoreSHA1,
+                         result->mStringPool, &cur_string_pool_offset,
+                         result->mDependencyTable)) {
+      goto bail;
+    }
+
+#if defined(ARCH_ARM_HAVE_NEON)
+    if (!writeDependency(LibCLCoreNEONPath, LibCLCoreNEONSHA1,
+                         result->mStringPool, &cur_string_pool_offset,
+                         result->mDependencyTable)) {
+      goto bail;
+    }
+#endif
+
+    //===------------------------------------------------------------------===//
+    // Record dependency information.
+    //===------------------------------------------------------------------===//
+    for (unsigned i = 0, e = pDeps.size(); i != e; i++) {
+      if (!writeDependency(/* name */pDeps[i].first, /* SHA-1 */pDeps[i].second,
+                           result->mStringPool, &cur_string_pool_offset,
+                           result->mDependencyTable)) {
+        goto bail;
+      }
+    }
   }
 
   //===--------------------------------------------------------------------===//
diff --git a/lib/Renderscript/RSScript.cpp b/lib/Renderscript/RSScript.cpp
index 75cfff9..53c8946 100644
--- a/lib/Renderscript/RSScript.cpp
+++ b/lib/Renderscript/RSScript.cpp
@@ -22,7 +22,7 @@
 
 using namespace bcc;
 
-bool RSScript::LinkRuntime(RSScript &pScript) {
+bool RSScript::LinkRuntime(RSScript &pScript, const char *rt_path) {
   // Using the same context with the source in pScript.
   BCCContext &context = pScript.getSource().getContext();
   const char* core_lib = RSInfo::LibCLCorePath;
@@ -37,6 +37,10 @@
   }
 #endif
 
+  if (rt_path != NULL) {
+    core_lib = rt_path;
+  }
+
   Source *libclcore_source = Source::CreateFromFile(context, core_lib);
   if (libclcore_source == NULL) {
     ALOGE("Failed to load Renderscript library '%s' to link!", core_lib);
diff --git a/lib/Renderscript/runtime/math.ll b/lib/Renderscript/runtime/math.ll
index 4ea2b10..dd4dc4b 100644
--- a/lib/Renderscript/runtime/math.ll
+++ b/lib/Renderscript/runtime/math.ll
@@ -3,14 +3,35 @@
 
 declare float @llvm.sqrt.f32(float)
 declare float @llvm.pow.f32(float, float)
+declare float @llvm.fabs.f32(float)
+declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
+declare <3 x float> @llvm.fabs.v3f32(<3 x float>)
+declare <4 x float> @llvm.fabs.v4f32(<4 x float>)
 
-define float @_Z4sqrtf(float %v) {
+define float @_Z4sqrtf(float %v) nounwind readnone alwaysinline {
   %1 = tail call float @llvm.sqrt.f32(float %v)
   ret float %1
 }
 
-define float @_Z3powf(float %v1, float %v2) {
+define float @_Z3powf(float %v1, float %v2) nounwind readnone alwaysinline {
   %1 = tail call float @llvm.pow.f32(float  %v1, float %v2)
   ret float %1
 }
 
+define float @_Z4fabsf(float %v) nounwind readnone alwaysinline {
+  %1 = tail call float @llvm.fabs.f32(float %v)
+  ret float %1
+}
+define <2 x float> @_Z4fabsDv2_f(<2 x float> %v) nounwind readnone alwaysinline {
+  %1 = tail call <2 x float> @llvm.fabs.v2f32(<2 x float> %v)
+  ret <2 x float> %1
+}
+define <3 x float> @_Z4fabsDv3_f(<3 x float> %v) nounwind readnone alwaysinline {
+  %1 = tail call <3 x float> @llvm.fabs.v3f32(<3 x float> %v)
+  ret <3 x float> %1
+}
+define <4 x float> @_Z4fabsDv4_f(<4 x float> %v) nounwind readnone alwaysinline {
+  %1 = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> %v)
+  ret <4 x float> %1
+}
+
diff --git a/lib/Renderscript/runtime/rs_allocation.c b/lib/Renderscript/runtime/rs_allocation.c
index dbfb76e..e348d3a 100644
--- a/lib/Renderscript/runtime/rs_allocation.c
+++ b/lib/Renderscript/runtime/rs_allocation.c
@@ -6,19 +6,19 @@
 extern uint32_t __attribute__((overloadable))
     rsAllocationGetDimX(rs_allocation a) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    return alloc->mHal.state.dimensionX;
+    return alloc->mHal.drvState.lod[0].dimX;
 }
 
 extern uint32_t __attribute__((overloadable))
         rsAllocationGetDimY(rs_allocation a) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    return alloc->mHal.state.dimensionY;
+    return alloc->mHal.drvState.lod[0].dimY;
 }
 
 extern uint32_t __attribute__((overloadable))
         rsAllocationGetDimZ(rs_allocation a) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    return alloc->mHal.state.dimensionZ;
+    return alloc->mHal.drvState.lod[0].dimZ;
 }
 
 extern uint32_t __attribute__((overloadable))
@@ -36,7 +36,7 @@
 extern const void * __attribute__((overloadable))
         rsGetElementAt(rs_allocation a, uint32_t x) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
     const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
     return &p[eSize * x];
 }
@@ -44,19 +44,19 @@
 extern const void * __attribute__((overloadable))
         rsGetElementAt(rs_allocation a, uint32_t x, uint32_t y) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
     const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
-    const uint32_t stride = alloc->mHal.drvState.stride;
+    const uint32_t stride = alloc->mHal.drvState.lod[0].stride;
     return &p[(eSize * x) + (y * stride)];
 }
 
 extern const void * __attribute__((overloadable))
         rsGetElementAt(rs_allocation a, uint32_t x, uint32_t y, uint32_t z) {
     Allocation_t *alloc = (Allocation_t *)a.p;
-    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
     const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
-    const uint32_t stride = alloc->mHal.drvState.stride;
-    const uint32_t dimY = alloc->mHal.state.dimensionY;
+    const uint32_t stride = alloc->mHal.drvState.lod[0].stride;
+    const uint32_t dimY = alloc->mHal.drvState.lod[0].dimY;
     return &p[(eSize * x) + (y * stride) + (z * stride * dimY)];
 }
 
@@ -71,3 +71,88 @@
     rs_element returnElem = {type->mHal.state.element};
     return returnElem;
 }
+
+// TODO: this needs to be optimized, obviously
+static void memcpy(void* dst, void* src, size_t size) {
+    char* dst_c = (char*) dst, *src_c = (char*) src;
+    for (; size > 0; size--) {
+        *dst_c++ = *src_c++;
+    }
+}
+
+extern void __attribute__((overloadable))
+        rsSetElementAt(rs_allocation a, void* ptr, uint32_t x) {
+    Allocation_t *alloc = (Allocation_t *)a.p;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
+    const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+    memcpy((void*)&p[eSize * x], ptr, eSize);
+}
+
+extern void __attribute__((overloadable))
+        rsSetElementAt(rs_allocation a, void* ptr, uint32_t x, uint32_t y) {
+    Allocation_t *alloc = (Allocation_t *)a.p;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
+    const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+    const uint32_t stride = alloc->mHal.drvState.lod[0].stride;
+    memcpy((void*)&p[(eSize * x) + (y * stride)], ptr, eSize);
+}
+
+#define SET_ELEMENT_AT(T)                                               \
+    extern void __attribute__((overloadable))                           \
+    __rsSetElementAt_##T(rs_allocation a, T val, uint32_t x) {          \
+        Allocation_t *alloc = (Allocation_t *)a.p;                      \
+        const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr; \
+        const uint32_t eSize = sizeof(T);                               \
+        *((T*)&p[(eSize * x)]) = val;                                   \
+    }                                                                   \
+    extern void __attribute__((overloadable))                           \
+    __rsSetElementAt_##T(rs_allocation a, T val, uint32_t x, uint32_t y) { \
+        Allocation_t *alloc = (Allocation_t *)a.p;                      \
+        const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr; \
+        const uint32_t eSize = sizeof(T);                               \
+        const uint32_t stride = alloc->mHal.drvState.lod[0].stride;     \
+        *((T*)&p[(eSize * x) + (y * stride)]) = val;                    \
+    }
+
+SET_ELEMENT_AT(char)
+SET_ELEMENT_AT(char2)
+SET_ELEMENT_AT(char3)
+SET_ELEMENT_AT(char4)
+SET_ELEMENT_AT(uchar)
+SET_ELEMENT_AT(uchar2)
+SET_ELEMENT_AT(uchar3)
+SET_ELEMENT_AT(uchar4)
+SET_ELEMENT_AT(short)
+SET_ELEMENT_AT(short2)
+SET_ELEMENT_AT(short3)
+SET_ELEMENT_AT(short4)
+SET_ELEMENT_AT(ushort)
+SET_ELEMENT_AT(ushort2)
+SET_ELEMENT_AT(ushort3)
+SET_ELEMENT_AT(ushort4)
+SET_ELEMENT_AT(int)
+SET_ELEMENT_AT(int2)
+SET_ELEMENT_AT(int3)
+SET_ELEMENT_AT(int4)
+SET_ELEMENT_AT(uint)
+SET_ELEMENT_AT(uint2)
+SET_ELEMENT_AT(uint3)
+SET_ELEMENT_AT(uint4)
+SET_ELEMENT_AT(long)
+SET_ELEMENT_AT(long2)
+SET_ELEMENT_AT(long3)
+SET_ELEMENT_AT(long4)
+SET_ELEMENT_AT(ulong)
+SET_ELEMENT_AT(ulong2)
+SET_ELEMENT_AT(ulong3)
+SET_ELEMENT_AT(ulong4)
+SET_ELEMENT_AT(float)
+SET_ELEMENT_AT(float2)
+SET_ELEMENT_AT(float3)
+SET_ELEMENT_AT(float4)
+SET_ELEMENT_AT(double)
+SET_ELEMENT_AT(double2)
+SET_ELEMENT_AT(double3)
+SET_ELEMENT_AT(double4)
+
+#undef SET_ELEMENT_AT
diff --git a/lib/Renderscript/runtime/rs_cl.c b/lib/Renderscript/runtime/rs_cl.c
index b6c2b6a..32b25d5 100644
--- a/lib/Renderscript/runtime/rs_cl.c
+++ b/lib/Renderscript/runtime/rs_cl.c
@@ -404,8 +404,10 @@
 extern float __attribute__((overloadable)) expm1(float);
 FN_FUNC_FN(expm1)
 
-extern float __attribute__((overloadable)) fabs(float);
-FN_FUNC_FN(fabs)
+extern float __attribute__((overloadable)) fabs(float v);
+extern float2 __attribute__((overloadable)) fabs(float2 v);
+extern float3 __attribute__((overloadable)) fabs(float3 v);
+extern float4 __attribute__((overloadable)) fabs(float4 v);
 
 extern float __attribute__((overloadable)) fdim(float, float);
 FN_FUNC_FN_FN(fdim)
@@ -421,9 +423,17 @@
 extern float __attribute__((overloadable)) fmod(float, float);
 FN_FUNC_FN_FN(fmod)
 
+extern float __attribute__((overloadable)) fract(float v) {
+    int i = (int)floor(v);
+    return fmin(v - i, 0x1.fffffep-1f);
+}
+FN_FUNC_FN(fract)
+
 extern float __attribute__((overloadable)) fract(float v, float *iptr) {
     int i = (int)floor(v);
-    iptr[0] = i;
+    if (iptr) {
+        iptr[0] = i;
+    }
     return fmin(v - i, 0x1.fffffep-1f);
 }
 FN_FUNC_FN_PFN(fract)
diff --git a/lib/Renderscript/runtime/rs_sample.c b/lib/Renderscript/runtime/rs_sample.c
index b41e7f1..6c34368 100644
--- a/lib/Renderscript/runtime/rs_sample.c
+++ b/lib/Renderscript/runtime/rs_sample.c
@@ -9,7 +9,7 @@
         getElementAt(rs_allocation a, uint32_t x, uint32_t lod) {
     Allocation_t *alloc = (Allocation_t *)a.p;
     const Type_t *type = (const Type_t*)alloc->mHal.state.type;
-    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
 
     const uint32_t offset = type->mHal.state.lodOffset[lod];
     const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
@@ -21,13 +21,13 @@
         getElementAt(rs_allocation a, uint32_t x, uint32_t y, uint32_t lod) {
     Allocation_t *alloc = (Allocation_t *)a.p;
     const Type_t *type = (const Type_t*)alloc->mHal.state.type;
-    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
+    const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr;
 
     const uint32_t eSize = alloc->mHal.state.elementSizeBytes;
     const uint32_t offset = type->mHal.state.lodOffset[lod];
     uint32_t stride;
     if(lod == 0) {
-        stride = alloc->mHal.drvState.stride;
+        stride = alloc->mHal.drvState.lod[0].stride;
     } else {
         stride = type->mHal.state.lodDimX[lod] * eSize;
     }
diff --git a/lib/Renderscript/runtime/rs_structs.h b/lib/Renderscript/runtime/rs_structs.h
index 710dd31..a61ebea 100644
--- a/lib/Renderscript/runtime/rs_structs.h
+++ b/lib/Renderscript/runtime/rs_structs.h
@@ -32,9 +32,7 @@
             const void *type;
             uint32_t usageFlags;
             rs_allocation_mipmap_control mipmapControl;
-            uint32_t dimensionX;
-            uint32_t dimensionY;
-            uint32_t dimensionZ;
+            uint32_t yuv;
             uint32_t elementSizeBytes;
             bool hasMipmaps;
             bool hasFaces;
@@ -43,12 +41,19 @@
             int32_t surfaceTextureID;
             void * wndSurface;
             void * surfaceTexture;
-            rs_data_type eType;
         } state;
 
         struct DrvState {
-            void * mallocPtr;
-            uint32_t stride;
+            struct LodState {
+                void * mallocPtr;
+                size_t stride;
+                uint32_t dimX;
+                uint32_t dimY;
+                uint32_t dimZ;
+            } lod[16/*android::renderscript::Allocation::MAX_LOD*/];
+            size_t faceOffset;
+            uint32_t lodCount;
+            uint32_t faceCount;
         } drvState;
     } mHal;
 } Allocation_t;
diff --git a/lib/Support/FileBase.cpp b/lib/Support/FileBase.cpp
index 579d78f..5dc9944 100644
--- a/lib/Support/FileBase.cpp
+++ b/lib/Support/FileBase.cpp
@@ -16,11 +16,14 @@
 
 #include "bcc/Support/FileBase.h"
 
+#include "bcc/Support/Log.h"
+
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <cerrno>
+#include <cstring>
 #include <new>
 
 #include <utils/FileMap.h>
@@ -33,7 +36,8 @@
   : mFD(-1),
     mError(),
     mName(pFilename), mOpenFlags(pOpenFlags),
-    mShouldUnlock(false) {
+    mShouldUnlock(false),
+    mShouldDelete(false) {
   // Process pFlags
 #ifdef O_BINARY
   if (pFlags & kBinary) {
@@ -48,6 +52,10 @@
     mOpenFlags |= O_APPEND;
   }
 
+  if (pFlags & kDeleteOnClose) {
+    mShouldDelete = true;
+  }
+
   // Open the file.
   open();
 
@@ -282,5 +290,11 @@
     ::close(mFD);
     mFD = -1;
   }
+  if (mShouldDelete) {
+    int res = ::remove(mName.c_str());
+    if (res != 0) {
+      ALOGE("Failed to remove file: %s - %s", mName.c_str(), ::strerror(res));
+    }
+  }
   return;
 }
diff --git a/lib/Support/Initialization.cpp b/lib/Support/Initialization.cpp
index 6951a05..32be882 100644
--- a/lib/Support/Initialization.cpp
+++ b/lib/Support/Initialization.cpp
@@ -55,10 +55,10 @@
   LLVMInitializeARMTargetMC();
   LLVMInitializeARMTargetInfo();
   LLVMInitializeARMTarget();
-  LLVMInitializeARMLDTargetInfo();
-  LLVMInitializeARMLDTarget();
-  LLVMInitializeARMLDBackend();
-  LLVMInitializeARMDiagnosticLineInfo();
+  MCLDInitializeARMLDTargetInfo();
+  MCLDInitializeARMLDTarget();
+  MCLDInitializeARMLDBackend();
+  MCLDInitializeARMDiagnosticLineInfo();
 #endif
 
 #if defined(PROVIDE_MIPS_CODEGEN)
@@ -69,10 +69,10 @@
   LLVMInitializeMipsTargetMC();
   LLVMInitializeMipsTargetInfo();
   LLVMInitializeMipsTarget();
-  LLVMInitializeMipsLDTargetInfo();
-  LLVMInitializeMipsLDTarget();
-  LLVMInitializeMipsLDBackend();
-  LLVMInitializeMipsDiagnosticLineInfo();
+  MCLDInitializeMipsLDTargetInfo();
+  MCLDInitializeMipsLDTarget();
+  MCLDInitializeMipsLDBackend();
+  MCLDInitializeMipsDiagnosticLineInfo();
 #endif
 
 #if defined(PROVIDE_X86_CODEGEN)
@@ -83,10 +83,10 @@
   LLVMInitializeX86TargetMC();
   LLVMInitializeX86TargetInfo();
   LLVMInitializeX86Target();
-  LLVMInitializeX86LDTargetInfo();
-  LLVMInitializeX86LDTarget();
-  LLVMInitializeX86LDBackend();
-  LLVMInitializeX86DiagnosticLineInfo();
+  MCLDInitializeX86LDTargetInfo();
+  MCLDInitializeX86LDTarget();
+  MCLDInitializeX86LDBackend();
+  MCLDInitializeX86DiagnosticLineInfo();
 #endif
 
   is_initialized = true;
diff --git a/lib/Support/LinkerConfig.cpp b/lib/Support/LinkerConfig.cpp
index bdbde23..a4ede97 100644
--- a/lib/Support/LinkerConfig.cpp
+++ b/lib/Support/LinkerConfig.cpp
@@ -19,9 +19,9 @@
 
 #include <llvm/Support/Signals.h>
 
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDFile.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/MC/MCLDDirectory.h>
+#include <mcld/MC/ZOption.h>
 #include <mcld/LD/TextDiagnosticPrinter.h>
 #include <mcld/Support/Path.h>
 #include <mcld/Support/MsgHandling.h>
@@ -30,7 +30,7 @@
 using namespace bcc;
 
 LinkerConfig::LinkerConfig(const std::string &pTriple)
-  : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
+  : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
     mDiagLineInfo(NULL), mDiagPrinter(NULL) {
 
   initializeTarget();
@@ -39,7 +39,7 @@
 }
 
 LinkerConfig::~LinkerConfig() {
-  delete mLDInfo;
+  delete mLDConfig;
 
   if (mDiagPrinter->getNumErrors() != 0) {
     // If here, the program failed ungracefully. Run the interrupt handlers to
@@ -66,58 +66,224 @@
 }
 
 bool LinkerConfig::initializeLDInfo() {
-  if (NULL != mLDInfo) {
+  if (NULL != mLDConfig) {
     ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
           mTriple.c_str());
     return false;
   }
 
-  mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
+  mLDConfig = new mcld::LinkerConfig(getTriple());
+  mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
+
+  struct NameMap {
+    const char* from;
+    const char* to;
+  };
+
+  static const NameMap map[] =
+  {
+    {".text", ".text"},
+    {".rodata", ".rodata"},
+    {".data.rel.ro.local", ".data.rel.ro.local"},
+    {".data.rel.ro", ".data.rel.ro"},
+    {".data", ".data"},
+    {".bss", ".bss"},
+    {".tdata", ".tdata"},
+    {".tbss", ".tbss"},
+    {".init_array", ".init_array"},
+    {".fini_array", ".fini_array"},
+    // TODO: Support DT_INIT_ARRAY for all constructors?
+    {".ctors", ".ctors"},
+    {".dtors", ".dtors"},
+    // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
+    // sections would be handled differently.
+    {".sdata2", ".sdata"},
+    {".sbss2", ".sbss"},
+    {".sdata", ".sdata"},
+    {".sbss", ".sbss"},
+    {".lrodata", ".lrodata"},
+    {".ldata", ".ldata"},
+    {".lbss", ".lbss"},
+    {".gcc_except_table", ".gcc_except_table"},
+    {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
+    {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
+    {".gnu.linkonce.r", ".rodata"},
+    {".gnu.linkonce.d", ".data"},
+    {".gnu.linkonce.b", ".bss"},
+    {".gnu.linkonce.sb2", ".sbss"},
+    {".gnu.linkonce.sb", ".sbss"},
+    {".gnu.linkonce.s2", ".sdata"},
+    {".gnu.linkonce.s", ".sdata"},
+    {".gnu.linkonce.wi", ".debug_info"},
+    {".gnu.linkonce.td", ".tdata"},
+    {".gnu.linkonce.tb", ".tbss"},
+    {".gnu.linkonce.t", ".text"},
+    {".gnu.linkonce.lr", ".lrodata"},
+    {".gnu.linkonce.lb", ".lbss"},
+    {".gnu.linkonce.l", ".ldata"},
+  };
+
+  if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) {
+    const unsigned int map_size =  (sizeof(map) / sizeof(map[0]) );
+    for (unsigned int i = 0; i < map_size; ++i) {
+      bool exist = false;
+      mLDConfig->scripts().sectionMap().append(map[i].from,
+                                               map[i].to,
+                                               exist);
+    }
+  }
   return true;
 }
 
 bool LinkerConfig::initializeDiagnostic() {
   // Set up MsgHandler.
+  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
+
+  mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
+
   mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
 
-  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
-
-  mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
-
+  mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
   return true;
 }
 
+bool LinkerConfig::isShared() const {
+  return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
+}
+
 void LinkerConfig::setShared(bool pEnable) {
-  mShared = pEnable;
+  if (pEnable)
+    mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
+  else
+    mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
   return;
 }
 
 void LinkerConfig::setBsymbolic(bool pEnable) {
-  mLDInfo->options().setBsymbolic(pEnable);
+  mLDConfig->options().setBsymbolic(pEnable);
+  return;
+}
+
+void LinkerConfig::setDefineCommon(bool pEnable) {
+  mLDConfig->options().setDefineCommon(pEnable);
   return;
 }
 
 void LinkerConfig::setSOName(const std::string &pSOName) {
-  mSOName = pSOName;
+  mLDConfig->options().setSOName(pSOName);
   return;
 }
 
 void LinkerConfig::setDyld(const std::string &pDyld) {
-  mLDInfo->options().setDyld(pDyld);
+  mLDConfig->options().setDyld(pDyld);
   return;
 }
 
 void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
-  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+  mLDConfig->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
   return;
 }
 
+void LinkerConfig::setZOption(unsigned int pOptions) {
+  mcld::ZOption option;
+  if (pOptions & kCombReloc) {
+    option.setKind(mcld::ZOption::CombReloc);
+    mLDConfig->options().addZOption(option);
+  }
+  else {
+    option.setKind(mcld::ZOption::NoCombReloc);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kDefs) {
+    option.setKind(mcld::ZOption::Defs);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kExecStack) {
+    option.setKind(mcld::ZOption::ExecStack);
+    mLDConfig->options().addZOption(option);
+  }
+  else {
+    option.setKind(mcld::ZOption::NoExecStack);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kInitFirst) {
+    option.setKind(mcld::ZOption::InitFirst);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kInterPose) {
+    option.setKind(mcld::ZOption::InterPose);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kLoadFltr) {
+    option.setKind(mcld::ZOption::LoadFltr);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kMulDefs) {
+    option.setKind(mcld::ZOption::MulDefs);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kNoCopyReloc) {
+    option.setKind(mcld::ZOption::NoCopyReloc);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kNoDefaultLib) {
+    option.setKind(mcld::ZOption::NoDefaultLib);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kNoDelete) {
+    option.setKind(mcld::ZOption::NoDelete);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kNoDLOpen) {
+    option.setKind(mcld::ZOption::NoDLOpen);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kNoDump) {
+    option.setKind(mcld::ZOption::NoDump);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kRelro) {
+    option.setKind(mcld::ZOption::Relro);
+    mLDConfig->options().addZOption(option);
+  }
+  else {
+    option.setKind(mcld::ZOption::NoRelro);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kLazy) {
+    option.setKind(mcld::ZOption::Lazy);
+    mLDConfig->options().addZOption(option);
+  }
+  else {
+    option.setKind(mcld::ZOption::Now);
+    mLDConfig->options().addZOption(option);
+  }
+
+  if (pOptions & kOrigin) {
+    option.setKind(mcld::ZOption::Origin);
+    mLDConfig->options().addZOption(option);
+  }
+}
+
 void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
   bool exist = false;
 
   // Add wname -> __wrap_wname.
   mcld::StringEntry<llvm::StringRef>* to_wrap =
-               mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist);
+               mLDConfig->scripts().renameMap().insert(pWrapSymbol, exist);
 
   std::string to_wrap_str = "__wrap_" + pWrapSymbol;
   to_wrap->setValue(to_wrap_str);
@@ -129,7 +295,7 @@
   // Add __real_wname -> wname.
   std::string from_real_str = "__real_" + pWrapSymbol;
   mcld::StringEntry<llvm::StringRef>* from_real =
-             mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+             mLDConfig->scripts().renameMap().insert(from_real_str, exist);
   from_real->setValue(pWrapSymbol);
 
   if (exist) {
@@ -144,7 +310,7 @@
 
   // Add pname -> pname_portable.
   mcld::StringEntry<llvm::StringRef>* to_port =
-                mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
+                mLDConfig->scripts().renameMap().insert(pPortableSymbol, exist);
 
   std::string to_port_str = pPortableSymbol + "_portable";
   to_port->setValue(to_port_str);
@@ -156,7 +322,7 @@
   // Add __real_pname -> pname.
   std::string from_real_str = "__real_" + pPortableSymbol;
   mcld::StringEntry<llvm::StringRef>* from_real =
-           mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+           mLDConfig->scripts().renameMap().insert(from_real_str, exist);
 
   from_real->setValue(pPortableSymbol);
 
@@ -169,17 +335,7 @@
 
 void LinkerConfig::addSearchDir(const std::string &pDirPath) {
   // SearchDirs will remove the created MCLDDirectory.
-  mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
-
-  if (sd->isInSysroot()) {
-    sd->setSysroot(mLDInfo->options().sysroot());
+  if (!mLDConfig->options().directories().insert(pDirPath)) {
+    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
   }
-
-  if (exists(sd->path()) && is_directory(sd->path())) {
-    mLDInfo->options().directories().add(*sd);
-  } else {
-    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
-  }
-
-  return;
 }
diff --git a/lib/Support/TargetCompilerConfigs.cpp b/lib/Support/TargetCompilerConfigs.cpp
index df78637..2dcd173 100644
--- a/lib/Support/TargetCompilerConfigs.cpp
+++ b/lib/Support/TargetCompilerConfigs.cpp
@@ -16,6 +16,11 @@
 
 #include "bcc/Support/TargetCompilerConfigs.h"
 
+// Get ARM version number (i.e., __ARM_ARCH__)
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+
 using namespace bcc;
 
 //===----------------------------------------------------------------------===//
@@ -23,8 +28,28 @@
 //===----------------------------------------------------------------------===//
 #if defined(PROVIDE_ARM_CODEGEN)
 
-void ARMCompilerConfig::GetFeatureVector(std::vector<std::string> &pAttributes,
-                                         bool pEnableNEON) {
+bool ARMBaseCompilerConfig::HasThumb2() {
+#if !defined(TARGET_BUILD)
+  // Cross-compiler can always generate Thumb-2 instructions.
+  return true;
+#else // defined(TARGET_BUILD)
+#  if defined(ARCH_ARM_HAVE_THUMB_SUPPORT)
+#    if (__ARM_ARCH__ >= 7) || defined(__ARM_ARCH_6T2__)
+  return true;
+#    else
+  // ARM prior to V6T2 doesn't support Thumb-2.
+  return false;
+#    endif
+#  else // !defined(ARCH_ARM_HAVE_THUMB_SUPPORT)
+  // Target that doesn't support Thumb feature won't support Thumb-2, either.
+  return false;
+#  endif
+#endif
+}
+
+void
+ARMBaseCompilerConfig::GetFeatureVector(std::vector<std::string> &pAttributes,
+                                        bool pInThumbMode, bool pEnableNEON) {
 #if defined(ARCH_ARM_HAVE_VFP)
   pAttributes.push_back("+vfp3");
 #  if !defined(ARCH_ARM_HAVE_VFP_D32)
@@ -32,6 +57,14 @@
 #  endif
 #endif
 
+  if (pInThumbMode) {
+    if (HasThumb2()) {
+      pAttributes.push_back("+thumb2");
+    } else {
+      pAttributes.push_back("-thumb2");
+    }
+  }
+
 #if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_ARCH_ARM_HAVE_NEON)
   if (pEnableNEON) {
     pAttributes.push_back("+neon");
@@ -48,24 +81,25 @@
   return;
 }
 
-ARMCompilerConfig::ARMCompilerConfig()
-  : CompilerConfig(DEFAULT_ARM_TRIPLE_STRING) {
+ARMBaseCompilerConfig::ARMBaseCompilerConfig(const std::string &pTriple,
+                                             bool pInThumbMode)
+  : CompilerConfig(pTriple), mInThumbMode(pInThumbMode) {
 
   // Enable NEON by default.
   mEnableNEON = true;
 
   std::vector<std::string> attributes;
-  GetFeatureVector(attributes, /* pEnableNEON */mEnableNEON);
+  GetFeatureVector(attributes, mInThumbMode, mEnableNEON);
   setFeatureString(attributes);
 
   return;
 }
 
-bool ARMCompilerConfig::enableNEON(bool pEnable) {
+bool ARMBaseCompilerConfig::enableNEON(bool pEnable) {
 #if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_ARCH_ARM_HAVE_NEON)
   if (mEnableNEON != pEnable) {
     std::vector<std::string> attributes;
-    GetFeatureVector(attributes, pEnable);
+    GetFeatureVector(attributes, mInThumbMode, pEnable);
     setFeatureString(attributes);
     mEnableNEON = pEnable;
     return true;
diff --git a/lib/Support/TargetLinkerConfigs.cpp b/lib/Support/TargetLinkerConfigs.cpp
index b57e81a..d7e6163 100644
--- a/lib/Support/TargetLinkerConfigs.cpp
+++ b/lib/Support/TargetLinkerConfigs.cpp
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
+
 #include "bcc/Config/Config.h"
 #include "bcc/Support/TargetLinkerConfigs.h"
 
+#include <mcld/TargetOptions.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/Fragment/Relocation.h>
+
 using namespace bcc;
 
 #ifdef TARGET_BUILD
@@ -33,23 +38,38 @@
 #if defined(PROVIDE_ARM_CODEGEN)
 ARMLinkerConfig::ARMLinkerConfig() : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
 
+  // set up target-dependent options
+  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+  getLDConfig()->targets().setBitClass(32);
+
   // set up target-dependent constraints of attributes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
   }
+
+  // set up section map
+  if (getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+    bool exist = false;
+    getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+  }
+
+  // set up relocation factory
+  mcld::Relocation::SetUp(*getLDConfig());
 }
 #endif // defined(PROVIDE_ARM_CODEGEN)
 
@@ -60,23 +80,30 @@
 MipsLinkerConfig::MipsLinkerConfig()
   : LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
 
+  // set up target-dependent options
+  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+  getLDConfig()->targets().setBitClass(32);
+
   // set up target-dependent constraints of attibutes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
   }
+
+  // set up relocation factory
+  mcld::Relocation::SetUp(*getLDConfig());
 }
 #endif // defined(PROVIDE_MIPS_CODEGEN)
 
@@ -86,23 +113,30 @@
 #if defined(PROVIDE_X86_CODEGEN)
 X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
   : LinkerConfig(pTriple) {
+  // set up target-dependent options
+  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+  getLDConfig()->targets().setBitClass(32);
+
   // set up target-dependent constraints of attibutes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
   }
+
+  // set up relocation factory
+  mcld::Relocation::SetUp(*getLDConfig());
 }
 
 X86_32LinkerConfig::X86_32LinkerConfig()
@@ -113,3 +147,37 @@
   : X86FamilyLinkerConfigBase(DEFAULT_X86_64_TRIPLE_STRING) {
 }
 #endif // defined(PROVIDE_X86_CODEGEN)
+
+#if !defined(TARGET_BUILD)
+//===----------------------------------------------------------------------===//
+// General
+//===----------------------------------------------------------------------===//
+GeneralLinkerConfig::GeneralLinkerConfig(const std::string& pTriple)
+  : LinkerConfig(pTriple) {
+
+  // set up target-dependent options
+  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+  getLDConfig()->targets().setBitClass(32);
+
+  // set up target-dependent constraints of attributes
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
+
+  // set up section map
+  if (llvm::Triple::arm == getLDConfig()->targets().triple().getArch() &&
+      getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+    bool exist = false;
+    getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+  }
+
+  // set up relocation factory
+  mcld::Relocation::SetUp(*getLDConfig());
+}
+#endif // defined(TARGET_BUILD)
diff --git a/tools/abcc/Main.cpp b/tools/abcc/Main.cpp
index 44ceadd..d783ca9 100644
--- a/tools/abcc/Main.cpp
+++ b/tools/abcc/Main.cpp
@@ -102,7 +102,12 @@
 #endif
 
   if (triple == NULL) {
-    triple = DEFAULT_TARGET_TRIPLE_STRING;
+#ifdef DEFAULT_ARM_CODEGEN
+    // Generate Thumb instead of ARM.
+    triple = DEFAULT_THUMB_TRIPLE_STRING;
+#else
+     triple = DEFAULT_TARGET_TRIPLE_STRING;
+#endif
   }
 
   if (sysroot == NULL) {
diff --git a/tools/bcc/Android.mk b/tools/bcc/Android.mk
index 6f95eec..0799c61 100644
--- a/tools/bcc/Android.mk
+++ b/tools/bcc/Android.mk
@@ -45,7 +45,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := bcc
-LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := EXECUTABLES
 
 LOCAL_SRC_FILES := Main.cpp
diff --git a/tools/bcc_compat/Android.mk b/tools/bcc_compat/Android.mk
new file mode 100644
index 0000000..601ca7e
--- /dev/null
+++ b/tools/bcc_compat/Android.mk
@@ -0,0 +1,43 @@
+#
+# 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)
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcc_compat
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+LOCAL_CFLAGS := -DFORCE_ARM_CODEGEN
+
+LOCAL_SRC_FILES := \
+  main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+  libbcc
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/../../include
+
+LOCAL_LDLIBS = -ldl
+LOCAL_SRC_FILES := Main.cpp
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LIBBCC_GEN_CONFIG_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/bcc_compat/Main.cpp b/tools/bcc_compat/Main.cpp
new file mode 100644
index 0000000..25e7964
--- /dev/null
+++ b/tools/bcc_compat/Main.cpp
@@ -0,0 +1,275 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#include <stdlib.h>
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/ADT/SmallString.h>
+#include <llvm/Config/config.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/system_error.h>
+
+#include <bcc/BCCContext.h>
+#include <bcc/Compiler.h>
+#include <bcc/Config/BuildInfo.h>
+#include <bcc/Config/Config.h>
+#include <bcc/ExecutionEngine/BCCRuntimeSymbolResolver.h>
+#include <bcc/ExecutionEngine/ObjectLoader.h>
+#include <bcc/ExecutionEngine/SymbolResolverProxy.h>
+#include <bcc/ExecutionEngine/SymbolResolvers.h>
+#include <bcc/Renderscript/RSCompilerDriver.h>
+#include <bcc/Script.h>
+#include <bcc/Source.h>
+#include <bcc/Support/CompilerConfig.h>
+#include <bcc/Support/Initialization.h>
+#include <bcc/Support/InputFile.h>
+#include <bcc/Support/OutputFile.h>
+#include <bcc/Support/TargetCompilerConfigs.h>
+
+using namespace bcc;
+
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
+namespace {
+
+llvm::cl::list<std::string>
+OptInputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
+                  llvm::cl::desc("<input bitcode files>"));
+
+llvm::cl::opt<std::string>
+OptOutputFilename("o", llvm::cl::desc("Specify the output filename"),
+                  llvm::cl::value_desc("filename"));
+
+llvm::cl::opt<std::string>
+OptRuntimePath("rt-path", llvm::cl::desc("Specify the runtime library path"),
+               llvm::cl::value_desc("path"));
+
+#ifdef TARGET_BUILD
+const std::string OptTargetTriple(DEFAULT_TARGET_TRIPLE_STRING);
+#else
+llvm::cl::opt<std::string>
+OptTargetTriple("mtriple",
+                llvm::cl::desc("Specify the target triple (default: "
+                               DEFAULT_TARGET_TRIPLE_STRING ")"),
+                llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
+                llvm::cl::value_desc("triple"));
+
+llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
+                                 llvm::cl::desc("Alias for -mtriple"),
+                                 llvm::cl::aliasopt(OptTargetTriple));
+#endif
+
+//===----------------------------------------------------------------------===//
+// Compiler Options
+//===----------------------------------------------------------------------===//
+llvm::cl::opt<bool>
+OptPIC("fPIC", llvm::cl::desc("Generate fully relocatable, position independent"
+                              " code"));
+
+llvm::cl::opt<char>
+OptOptLevel("O", llvm::cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+                                "(default: -O2)"),
+            llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::init('2'));
+
+llvm::cl::opt<bool>
+OptC("c", llvm::cl::desc("Compile and assemble, but do not link."));
+
+//===----------------------------------------------------------------------===//
+// Linker Options
+//===----------------------------------------------------------------------===//
+// FIXME: this option will be removed in the future when MCLinker is capable
+//        of generating shared library directly from given bitcode. It only
+//        takes effect when -shared is supplied.
+llvm::cl::opt<std::string>
+OptImmObjectOutput("or", llvm::cl::desc("Specify the filename for output the "
+                                        "intermediate relocatable when linking "
+                                        "the input bitcode to the shared "
+                                        "library"), llvm::cl::ValueRequired);
+
+llvm::cl::opt<bool>
+OptShared("shared", llvm::cl::desc("Create a shared library from input bitcode "
+                                   "files"));
+
+
+// Override "bcc -version" since the LLVM version information is not correct on
+// Android build.
+void BCCVersionPrinter() {
+  llvm::raw_ostream &os = llvm::outs();
+  os << "libbcc (The Android Open Source Project, http://www.android.com/):\n"
+     << "  Build time: " << BuildInfo::GetBuildTime() << "\n"
+     << "  Build revision: " << BuildInfo::GetBuildRev() << "\n"
+     << "  Build source blob: " << BuildInfo::GetBuildSourceBlob() << "\n"
+     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n";
+
+  os << "\n";
+
+  os << "LLVM (http://llvm.org/):\n"
+     << "  Version: " << PACKAGE_VERSION << "\n";
+  return;
+}
+
+} // end anonymous namespace
+
+RSScript *PrepareRSScript(BCCContext &pContext,
+                          const llvm::cl::list<std::string> &pBitcodeFiles) {
+  RSScript *result = NULL;
+
+  for (unsigned i = 0; i < pBitcodeFiles.size(); i++) {
+    const std::string &input_bitcode = pBitcodeFiles[i];
+    Source *source = Source::CreateFromFile(pContext, input_bitcode);
+    if (source == NULL) {
+      llvm::errs() << "Failed to load llvm module from file `" << input_bitcode
+                   << "'!\n";
+      return NULL;
+    }
+
+    if (result != NULL) {
+      if (!result->mergeSource(*source, /* pPreserveSource */false)) {
+        llvm::errs() << "Failed to merge the llvm module `" << input_bitcode
+                     << "' to compile!\n";
+        delete source;
+        return NULL;
+      }
+    } else {
+      result = new (std::nothrow) RSScript(*source);
+      if (result == NULL) {
+        llvm::errs() << "Out of memory when create script for file `"
+                     << input_bitcode << "'!\n";
+        delete source;
+        return NULL;
+      }
+    }
+  }
+
+  return result;
+}
+
+static inline
+bool ConfigCompiler(RSCompilerDriver &pCompilerDriver) {
+  RSCompiler *compiler = pCompilerDriver.getCompiler();
+  CompilerConfig *config = NULL;
+
+#ifdef TARGET_BUILD
+  config = new (std::nothrow) DefaultCompilerConfig();
+#else
+  config = new (std::nothrow) CompilerConfig(OptTargetTriple);
+#endif
+  if (config == NULL) {
+    llvm::errs() << "Out of memory when create the compiler configuration!\n";
+    return false;
+  }
+
+  // Setup the config according to the value of command line option.
+  if (OptPIC) {
+    config->setRelocationModel(llvm::Reloc::PIC_);
+  }
+  switch (OptOptLevel) {
+    case '0': config->setOptimizationLevel(llvm::CodeGenOpt::None); break;
+    case '1': config->setOptimizationLevel(llvm::CodeGenOpt::Less); break;
+    case '3': config->setOptimizationLevel(llvm::CodeGenOpt::Aggressive); break;
+    case '2':
+    default: {
+      config->setOptimizationLevel(llvm::CodeGenOpt::Default);
+      break;
+    }
+  }
+
+  pCompilerDriver.setConfig(config);
+  Compiler::ErrorCode result = compiler->config(*config);
+
+  if (result != Compiler::kSuccess) {
+    llvm::errs() << "Failed to configure the compiler! (detail: "
+                 << Compiler::GetErrorString(result) << ")\n";
+    return false;
+  }
+
+  return true;
+}
+
+#define DEFAULT_OUTPUT_PATH   "/sdcard/a.out"
+static inline
+std::string DetermineOutputFilename(const std::string &pOutputPath) {
+  if (!pOutputPath.empty()) {
+    return pOutputPath;
+  }
+
+  // User doesn't specify the value to -o.
+  if (OptInputFilenames.size() > 1) {
+    llvm::errs() << "Use " DEFAULT_OUTPUT_PATH " for output file!\n";
+    return DEFAULT_OUTPUT_PATH;
+  }
+
+  // There's only one input bitcode file.
+  const std::string &input_path = OptInputFilenames[0];
+  llvm::SmallString<200> output_path(input_path);
+
+  llvm::error_code err = llvm::sys::fs::make_absolute(output_path);
+  if (err != llvm::errc::success) {
+    llvm::errs() << "Failed to determine the absolute path of `" << input_path
+                 << "'! (detail: " << err.message() << ")\n";
+    return "";
+  }
+
+  if (OptC) {
+    // -c was specified. Replace the extension to .o.
+    llvm::sys::path::replace_extension(output_path, "o");
+  } else {
+    // Use a.out under current working directory when compile executable or
+    // shared library.
+    llvm::sys::path::remove_filename(output_path);
+    llvm::sys::path::append(output_path, "a.out");
+  }
+
+  return output_path.c_str();
+}
+
+int main(int argc, char **argv) {
+  llvm::cl::SetVersionPrinter(BCCVersionPrinter);
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+  init::Initialize();
+
+  if (OptRuntimePath.empty()) {
+    fprintf(stderr, "You must set \"-rt-path </path/to/libclcore.bc>\" with "
+                    "this tool\n");
+    return EXIT_FAILURE;
+  }
+
+  BCCContext context;
+  RSCompilerDriver rscd;
+  Compiler compiler;
+
+  if (!ConfigCompiler(rscd)) {
+    return EXIT_FAILURE;
+  }
+
+  std::string OutputFilename = DetermineOutputFilename(OptOutputFilename);
+  if (OutputFilename.empty()) {
+    return EXIT_FAILURE;
+  }
+
+  RSScript *s = NULL;
+  s = PrepareRSScript(context, OptInputFilenames);
+  rscd.build(*s, OutputFilename.c_str(), OptRuntimePath.c_str());
+
+  return EXIT_SUCCESS;
+}
diff --git a/tools/mcld/Android.mk b/tools/mcld/Android.mk
index b8213d0..3e53c42 100644
--- a/tools/mcld/Android.mk
+++ b/tools/mcld/Android.mk
@@ -21,7 +21,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := mcld
-LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := EXECUTABLES
 
 LOCAL_SRC_FILES := Main.cpp
@@ -40,7 +39,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := mcld
-LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := EXECUTABLES
 
 LOCAL_SRC_FILES := Main.cpp
diff --git a/tools/mcld/Main.cpp b/tools/mcld/Main.cpp
index 8e20312..ac4772e 100644
--- a/tools/mcld/Main.cpp
+++ b/tools/mcld/Main.cpp
@@ -104,6 +104,33 @@
         llvm::cl::desc("Set the name of the dynamic linker."),
         llvm::cl::value_desc("Program"));
 
+static llvm::cl::opt<bool>
+OptRelocatable("relocatable",
+               llvm::cl::desc("Generate relocatable output"),
+               llvm::cl::init(false));
+
+static llvm::cl::alias
+OptRelocatableAlias("r",
+                    llvm::cl::desc("alias for --relocatable"),
+                    llvm::cl::aliasopt(OptRelocatable));
+
+static llvm::cl::opt<bool>
+OptDefineCommon("d",
+                llvm::cl::ZeroOrMore,
+                llvm::cl::desc("Define common symbol"),
+                llvm::cl::init(false));
+
+static llvm::cl::alias
+OptDefineCommonAlias1("dc",
+                      llvm::cl::desc("alias for -d"),
+                      llvm::cl::aliasopt(OptDefineCommon));
+
+static llvm::cl::alias
+OptDefineCommonAlias2("dp",
+                      llvm::cl::desc("alias for -d"),
+                      llvm::cl::aliasopt(OptDefineCommon));
+
+
 //===----------------------------------------------------------------------===//
 // Inputs
 //===----------------------------------------------------------------------===//
@@ -189,7 +216,7 @@
 #ifdef TARGET_BUILD
   config = new (std::nothrow) DefaultLinkerConfig();
 #else
-  config = new (std::nothrow) LinkerConfig(OptTargetTriple);
+  config = new (std::nothrow) GeneralLinkerConfig(OptTargetTriple);
 #endif
   if (config == NULL) {
     llvm::errs() << "Out of memory when create the linker configuration!\n";
@@ -243,6 +270,9 @@
   // 8. Set up -Bsymbolic.
   config->setBsymbolic(OptBsymbolic);
 
+  // 9. Set up -d (define common symbols)
+  config->setDefineCommon(OptDefineCommon);
+
   Linker::ErrorCode result = pLinker.config(*config);
   if (Linker::kSuccess != result) {
     llvm::errs() << "Failed to configure the linker! (detail: "