am ead5ccba: Revert "Refactor SourceInfo into Source."

* commit 'ead5ccba05af33df1a061b39847a9be137c00143':
  Revert "Refactor SourceInfo into Source."
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index 855d055..78850dd 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -24,7 +24,6 @@
 
 libbcc_executionengine_SRC_FILES := \
   BCCContext.cpp \
-  BCCContextImpl.cpp \
   Compiler.cpp \
   FileHandle.cpp \
   GDBJIT.cpp \
@@ -37,7 +36,7 @@
   ScriptCached.cpp \
   ScriptCompiled.cpp \
   Sha1Helper.cpp \
-  Source.cpp
+  SourceInfo.cpp
 
 
 #=====================================================================
diff --git a/lib/ExecutionEngine/BCCContext.cpp b/lib/ExecutionEngine/BCCContext.cpp
index 892fd5a..6d0c5b9 100644
--- a/lib/ExecutionEngine/BCCContext.cpp
+++ b/lib/ExecutionEngine/BCCContext.cpp
@@ -19,9 +19,7 @@
 #include <new>
 
 #include "BCCContextImpl.h"
-#include "Compiler.h"
 #include "DebugHelper.h"
-#include "Source.h"
 
 using namespace bcc;
 
@@ -42,10 +40,7 @@
   GlobalContext = NULL;
 }
 
-BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) {
-  // Initialize the LLVM compiler infrastructure.
-  Compiler::GlobalInitialization();
-}
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) { }
 
 BCCContext::~BCCContext() {
   delete mImpl;
@@ -54,14 +49,9 @@
     // Reset the GlobalContext.
     GlobalContext = NULL;
   }
+  return;
 }
 
-void BCCContext::addSource(Source &pSource)
-{ mImpl->mOwnSources.insert(&pSource); }
-
-void BCCContext::removeSource(Source &pSource)
-{ mImpl->mOwnSources.erase(&pSource); }
-
 llvm::LLVMContext &BCCContext::getLLVMContext()
 { return mImpl->mLLVMContext; }
 
diff --git a/lib/ExecutionEngine/BCCContext.h b/lib/ExecutionEngine/BCCContext.h
index 56962fe..3e58acc 100644
--- a/lib/ExecutionEngine/BCCContext.h
+++ b/lib/ExecutionEngine/BCCContext.h
@@ -24,7 +24,6 @@
 namespace bcc {
 
 class BCCContextImpl;
-class Source;
 
 /*
  * class BCCContext manages the global data across the libbcc infrastructure.
@@ -39,9 +38,6 @@
   llvm::LLVMContext &getLLVMContext();
   const llvm::LLVMContext &getLLVMContext() const;
 
-  void addSource(Source &pSource);
-  void removeSource(Source &pSource);
-
   // Global BCCContext
   static BCCContext *GetOrCreateGlobalContext();
   static void DestroyGlobalContext();
diff --git a/lib/ExecutionEngine/BCCContextImpl.cpp b/lib/ExecutionEngine/BCCContextImpl.cpp
deleted file mode 100644
index ec865fa..0000000
--- a/lib/ExecutionEngine/BCCContextImpl.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BCCContextImpl.h"
-
-#include <vector>
-
-#include <llvm/ADT/STLExtras.h>
-
-#include "Source.h"
-
-using namespace bcc;
-
-BCCContextImpl::~BCCContextImpl() {
-  // Another temporary container is needed to store the Source objects that we
-  // are going to detroy. Since the destruction of Source object will call
-  // removeSource() and change the content of OwnSources.
-  std::vector<Source *> Sources(mOwnSources.begin(), mOwnSources.end());
-  llvm::DeleteContainerPointers(Sources);
-}
diff --git a/lib/ExecutionEngine/BCCContextImpl.h b/lib/ExecutionEngine/BCCContextImpl.h
index 446eb36..b23d798 100644
--- a/lib/ExecutionEngine/BCCContextImpl.h
+++ b/lib/ExecutionEngine/BCCContextImpl.h
@@ -17,13 +17,11 @@
 #ifndef BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
 #define BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
 
-#include <llvm/ADT/SmallPtrSet.h>
 #include <llvm/LLVMContext.h>
 
 namespace bcc {
 
 class BCCContext;
-class Source;
 
 /*
  * class BCCContextImpl contains the implementation of BCCCotext.
@@ -32,12 +30,8 @@
 public:
   llvm::LLVMContext mLLVMContext;
 
-  // The set of sources that initialized in this context. They will be destroyed
-  // automatically when this context is gone.
-  llvm::SmallPtrSet<Source *, 2> mOwnSources;
-
   BCCContextImpl(BCCContext &pContext) { }
-  ~BCCContextImpl();
+  ~BCCContextImpl() { }
 };
 
 } // namespace bcc
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index 100f54b..58a49c5 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -226,27 +226,27 @@
     mRSExecutable(NULL),
     mpSymbolLookupFn(NULL),
     mpSymbolLookupContext(NULL),
-    mModule(NULL) {
+    mModule(NULL),
+    mHasLinked(false) /* Turn off linker */ {
   llvm::remove_fatal_error_handler();
   llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
   return;
 }
 
-int Compiler::readModule(llvm::Module &pModule) {
-  mModule = &pModule;
-  if (pModule.getMaterializer() != NULL) {
-    // A module with non-null materializer means that it is a lazy-load module.
-    // Materialize it now via invoking MaterializeAllPermanently(). This
-    // function returns false when the materialization is successful.
-    if (pModule.MaterializeAllPermanently(&mError)) {
-      setError("Failed to materialize the module `" +
-               pModule.getModuleIdentifier() + "'! (" + mError + ")");
-      mModule = NULL;
-    }
+
+int Compiler::linkModule(llvm::Module *moduleWith) {
+  if (llvm::Linker::LinkModules(mModule, moduleWith,
+                                llvm::Linker::PreserveSource,
+                                &mError) != 0) {
+    return hasError();
   }
+
+  // Everything for linking should be settled down here with no error occurs
+  mHasLinked = true;
   return hasError();
 }
 
+
 int Compiler::compile(const CompilerOption &option) {
   llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
@@ -390,7 +390,7 @@
   runInternalPasses(ForEachNameList, ForEachSigList);
 
   // Perform link-time optimization if we have multiple modules
-  if (option.RunLTO) {
+  if (mHasLinked) {
     runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel);
   }
 
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 8fee17c..863cda6 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -93,6 +93,8 @@
 
     llvm::Module *mModule;
 
+    bool mHasLinked;
+
   public:
     Compiler(ScriptCompiled *result);
 
@@ -117,7 +119,12 @@
       return mEmittedELFExecutable;
     }
 
-    int readModule(llvm::Module &pModule);
+    int readModule(llvm::Module *module) {
+      mModule = module;
+      return hasError();
+    }
+
+    int linkModule(llvm::Module *module);
 
     int compile(const CompilerOption &option);
 
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
index f7c1e50..75278c7 100644
--- a/lib/ExecutionEngine/CompilerOption.h
+++ b/lib/ExecutionEngine/CompilerOption.h
@@ -82,9 +82,6 @@
     CodeModelOpt = llvm::CodeModel::Small;
 #endif
 
-    //-- Run LTO passes --//
-    RunLTO = true;
-
     //-- Load the result object after successful compilation  --//
     LoadAfterCompile = true;
   }
@@ -92,7 +89,6 @@
   llvm::TargetOptions TargetOpt;
   llvm::CodeModel::Model CodeModelOpt;
   llvm::Reloc::Model RelocModelOpt;
-  bool RunLTO;
   bool LoadAfterCompile;
 
 };
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 7c79254..2dbdf40 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -16,19 +16,8 @@
 
 #include "Script.h"
 
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <new>
-#include <cstring>
-
-#include <llvm/ADT/STLExtras.h>
-
-#include <cutils/properties.h>
-
 #include "Config.h"
+#include "bcinfo/BitcodeWrapper.h"
 
 #include "MCCacheReader.h"
 #include "MCCacheWriter.h"
@@ -41,7 +30,16 @@
 #include "ScriptCompiled.h"
 #include "ScriptCached.h"
 #include "Sha1Helper.h"
-#include "Source.h"
+#include "SourceInfo.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <new>
+#include <string.h>
+#include <cutils/properties.h>
 
 namespace {
 
@@ -55,14 +53,6 @@
 
 namespace bcc {
 
-Script::Script(Source &pSource)
-  : mSource(&pSource),
-    mpExtSymbolLookupFn(NULL),
-    mpExtSymbolLookupFnContext(NULL) {
-  resetState();
-  return;
-}
-
 Script::~Script() {
   switch (mStatus) {
   case ScriptStatus::Compiled:
@@ -76,62 +66,111 @@
   default:
     break;
   }
-  llvm::DeleteContainerPointers(mDependencyInfos);
-}
 
-void Script::resetState() {
-  mErrorCode = BCC_NO_ERROR;
-  mStatus = ScriptStatus::Unknown;
-  mObjectType = ScriptObject::Unknown;
-  mIsContextSlotNotAvail = false;
-  // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
-  //        to NULL during state resetting.
-  //mpExtSymbolLookupFn = NULL;
-  //mpExtSymbolLookupFnContext = NULL;
-  llvm::DeleteContainerPointers(mDependencyInfos);
-  return;
+  for (size_t i = 0; i < 2; ++i) {
+    delete mSourceList[i];
+  }
 }
 
 
-Script::DependencyInfo::DependencyInfo(MCO_ResourceType pSourceType,
-                                       const std::string &pSourceName,
-                                       const uint8_t *pSHA1)
-  : mSourceType(pSourceType), mSourceName(pSourceName) {
-  ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
-  return;
-}
+int Script::addSourceBC(size_t idx,
+                        char const *resName,
+                        const char *bitcode,
+                        size_t bitcodeSize,
+                        unsigned long flags) {
 
-bool Script::reset(Source &pSource, bool pPreserveCurrent) {
-  if (mSource == &pSource) {
-    return false;
+  if (!resName) {
+    mErrorCode = BCC_INVALID_VALUE;
+    ALOGE("Invalid argument: resName = NULL\n");
+    return 1;
   }
 
-  if (!pPreserveCurrent) {
-    delete mSource;
-  }
-  mSource = &pSource;
-  resetState();
-  return true;
-}
-
-bool Script::mergeSource(Source &pSource, bool pPreserveSource) {
-  return mSource->merge(pSource, pPreserveSource);
-}
-
-bool Script::addSourceDependencyInfo(MCO_ResourceType pSourceType,
-                                     const std::string &pSourceName,
-                                     const uint8_t *pSHA1) {
-  DependencyInfo *dep_info = new (std::nothrow) DependencyInfo(pSourceType,
-                                                               pSourceName,
-                                                               pSHA1);
-  if (dep_info == NULL) {
-    ALOGE("Out of memory when record dependency information of `%s'!",
-          pSourceName.c_str());
-    return false;
+  if (mStatus != ScriptStatus::Unknown) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    return 1;
   }
 
-  mDependencyInfos.push_back(dep_info);
-  return true;
+  if (!bitcode) {
+    mErrorCode = BCC_INVALID_VALUE;
+    ALOGE("Invalid argument: bitcode = NULL\n");
+    return 1;
+  }
+
+  bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
+
+  mSourceList[idx] = SourceInfo::createFromBuffer(resName,
+                                                  bitcode, bitcodeSize,
+                                                  flags);
+
+  if (!mSourceList[idx]) {
+    mErrorCode = BCC_OUT_OF_MEMORY;
+    ALOGE("Out of memory while adding source bitcode\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+
+int Script::addSourceModule(size_t idx,
+                            llvm::Module *module,
+                            unsigned long flags) {
+  if (mStatus != ScriptStatus::Unknown) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    return 1;
+  }
+
+  if (!module) {
+    mErrorCode = BCC_INVALID_VALUE;
+    ALOGE("Invalid argument: module = NULL\n");
+    return 1;
+  }
+
+  mSourceList[idx] = SourceInfo::createFromModule(module, flags);
+
+  if (!mSourceList[idx]) {
+    mErrorCode = BCC_OUT_OF_MEMORY;
+    ALOGE("Out of memory when add source module\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+
+int Script::addSourceFile(size_t idx,
+                          char const *path,
+                          unsigned long flags) {
+  if (mStatus != ScriptStatus::Unknown) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
+    return 1;
+  }
+
+  if (!path) {
+    mErrorCode = BCC_INVALID_VALUE;
+    ALOGE("Invalid argument: path = NULL\n");
+    return 1;
+  }
+
+  struct stat sb;
+  if (stat(path, &sb) != 0) {
+    mErrorCode = BCC_INVALID_VALUE;
+    ALOGE("File not found: %s\n", path);
+    return 1;
+  }
+
+  mSourceList[idx] = SourceInfo::createFromFile(path, flags);
+
+  if (!mSourceList[idx]) {
+    mErrorCode = BCC_OUT_OF_MEMORY;
+    ALOGE("Out of memory while adding source file\n");
+    return 1;
+  }
+
+  return 0;
 }
 
 int Script::prepareRelocatable(char const *objPath,
@@ -139,7 +178,6 @@
                                unsigned long flags) {
   CompilerOption option;
   option.RelocModelOpt = RelocModel;
-  option.RunLTO = false;
   option.LoadAfterCompile = false;
 
   int status = internalCompile(option);
@@ -257,11 +295,10 @@
   reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
   reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
 
-  for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
-    const DependencyInfo *dep_info = mDependencyInfos[i];
-    reader.addDependency(dep_info->getSourceType(),
-                         dep_info->getSourceName(),
-                         dep_info->getSHA1Checksum());
+  for (size_t i = 0; i < 2; ++i) {
+    if (mSourceList[i]) {
+      mSourceList[i]->introDependency(reader);
+    }
   }
 
   if (checkOnly)
@@ -305,12 +342,39 @@
                                       mpExtSymbolLookupFnContext);
   }
 
+  if (!mSourceList[0]) {
+    ALOGE("Source bitcode is not set.\n");
+    return 1;
+  }
+
+  // Parse Source bitcode file (if necessary)
+  if (mSourceList[0]->prepareModule(mContext.mImpl->mLLVMContext) != 0) {
+    ALOGE("Unable to setup source module\n");
+    return 1;
+  }
+
+  // Parse Library bitcode file (if necessary)
+  if (mSourceList[1]) {
+    if (mSourceList[1]->prepareModule(mContext.mImpl->mLLVMContext) != 0) {
+      ALOGE("Unable to setup library module\n");
+      return 1;
+    }
+  }
+
   // Set the main source module
-  if (mCompiled->readModule(mSource->getModule()) != 0) {
+  if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
     ALOGE("Unable to read source module\n");
     return 1;
   }
 
+  // Link the source module with the library module
+  if (mSourceList[1]) {
+    if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
+      ALOGE("Unable to link library module\n");
+      return 1;
+    }
+  }
+
   // Compile and JIT the code
   if (mCompiled->compile(option) != 0) {
     ALOGE("Unable to compile.\n");
@@ -358,14 +422,12 @@
       writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
 #endif
 
-      for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
-        const DependencyInfo *dep_info = mDependencyInfos[i];
-        writer.addDependency(dep_info->getSourceType(),
-                             dep_info->getSourceName(),
-                             dep_info->getSHA1Checksum());
+      for (size_t i = 0; i < 2; ++i) {
+        if (mSourceList[i]) {
+          mSourceList[i]->introDependency(writer);
+        }
       }
 
-
       // libRS is threadable dirty hack
       // TODO: This should be removed in the future
       uint32_t libRS_threadable = 0;
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index b654797..4534951 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -17,20 +17,19 @@
 #ifndef BCC_SCRIPT_H
 #define BCC_SCRIPT_H
 
+#include <bcc/bcc.h>
+#include "bcc_internal.h"
+
+#include "BCCContext.h"
+#include "Compiler.h"
+
+#include <llvm/Support/CodeGen.h>
+
 #include <vector>
 #include <string>
 
-#include <stdint.h>
 #include <stddef.h>
 
-#include <llvm/ADT/SmallVector.h>
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "Compiler.h"
-
 namespace llvm {
   class Module;
   class GDBJITRegistrar;
@@ -39,7 +38,7 @@
 namespace bcc {
   class ScriptCompiled;
   class ScriptCached;
-  class Source;
+  class SourceInfo;
   struct CompilerOption;
 
   namespace ScriptStatus {
@@ -61,6 +60,8 @@
 
   class Script {
   private:
+    BCCContext mContext;
+
     int mErrorCode;
 
     ScriptStatus::StatusType mStatus;
@@ -87,31 +88,11 @@
 
     bool mIsContextSlotNotAvail;
 
-    // This is the source associated with this object and is going to be
-    // compiled.
-    Source *mSource;
-
-    class DependencyInfo {
-    private:
-      MCO_ResourceType mSourceType;
-      std::string mSourceName;
-      uint8_t mSHA1[20];
-
-    public:
-      DependencyInfo(MCO_ResourceType pSourceType,
-                     const std::string &pSourceName,
-                     const uint8_t *pSHA1);
-
-      inline MCO_ResourceType getSourceType() const
-      { return mSourceType; }
-
-      inline const std::string getSourceName() const
-      { return mSourceName; }
-
-      inline const uint8_t *getSHA1Checksum() const
-      { return mSHA1; }
-    };
-    llvm::SmallVector<DependencyInfo *, 2> mDependencyInfos;
+    // Source List
+    SourceInfo *mSourceList[2];
+    // Note: mSourceList[0] (main source)
+    // Note: mSourceList[1] (library source)
+    // TODO(logan): Generalize this, use vector or SmallVector instead!
 
     // External Function List
     std::vector<char const *> mUserDefinedExternalSymbols;
@@ -120,31 +101,32 @@
     BCCSymbolLookupFn mpExtSymbolLookupFn;
     void *mpExtSymbolLookupFnContext;
 
-    // Reset the state of this script object
-    void resetState();
-
   public:
-    Script(Source &pSource);
+    Script() : mErrorCode(BCC_NO_ERROR), mStatus(ScriptStatus::Unknown),
+               mObjectType(ScriptObject::Unknown),
+               mIsContextSlotNotAvail(false),
+               mpExtSymbolLookupFn(NULL), mpExtSymbolLookupFnContext(NULL) {
+      Compiler::GlobalInitialization();
+
+      mSourceList[0] = NULL;
+      mSourceList[1] = NULL;
+    }
 
     ~Script();
 
-    // Reset this object with the new source supplied. Return false if this
-    // object remains unchanged after the call (e.g., the supplied source is
-    // the same with the one contain in this object.) If pPreserveCurrent is
-    // false, the current containing source will be destroyed after successfully
-    // reset.
-    bool reset(Source &pSource, bool pPreserveCurrent = false);
+    int addSourceBC(size_t idx,
+                    char const *resName,
+                    const char *bitcode,
+                    size_t bitcodeSize,
+                    unsigned long flags);
 
-    // Merge (or link) another source into the current source associated with
-    // this Script object. Return false on error.
-    bool mergeSource(Source &pSource, bool pPreserveSource = false);
+    int addSourceModule(size_t idx,
+                        llvm::Module *module,
+                        unsigned long flags);
 
-    // Add dependency information for this script given the source named
-    // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
-    // false on error.
-    bool addSourceDependencyInfo(MCO_ResourceType pSourceType,
-                                 const std::string &pSourceName,
-                                 const uint8_t *pSHA1);
+    int addSourceFile(size_t idx,
+                      char const *path,
+                      unsigned long flags);
 
     void markExternalSymbol(char const *name) {
       mUserDefinedExternalSymbols.push_back(name);
@@ -160,7 +142,7 @@
     int writeCache();
 
     /*
-     * Link the given bitcodes in mSource to shared object (.so).
+     * Link the given bitcodes in mSourceList to shared object (.so).
      *
      * Currently, it requires one to provide the relocatable object files with
      * given bitcodes to output a shared object.
@@ -171,7 +153,7 @@
      * you haven't done that yet) and then link the output relocatable object
      * file to .so in dsoPath.
      *
-     * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
+     * TODO: Currently, we only support to link the bitcodes in mSourceList[0].
      *
      */
     int prepareSharedObject(char const *objPath,
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 8752aa3..7b7b62a 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -17,17 +17,17 @@
 #ifndef BCC_SCRIPTCOMPILED_H
 #define BCC_SCRIPTCOMPILED_H
 
+#include "Compiler.h"
+#include "Script.h"
+
+#include <bcc/bcc.h>
+
 #include <list>
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include <bcc/bcc.h>
-
-#include "Compiler.h"
-#include "Script.h"
-
 namespace llvm {
   class Module;
 }
@@ -73,8 +73,12 @@
 
     ~ScriptCompiled();
 
-    int readModule(llvm::Module &pModule) {
-      return mCompiler.readModule(pModule);
+    int readModule(llvm::Module *module) {
+      return mCompiler.readModule(module);
+    }
+
+    int linkModule(llvm::Module *module) {
+      return mCompiler.linkModule(module);
     }
 
     int compile(const CompilerOption &option) {
diff --git a/lib/ExecutionEngine/Source.cpp b/lib/ExecutionEngine/Source.cpp
deleted file mode 100644
index 754f3e5..0000000
--- a/lib/ExecutionEngine/Source.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Source.h"
-
-#include <new>
-
-#include <llvm/Bitcode/ReaderWriter.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/Linker.h>
-#include <llvm/Module.h>
-#include <llvm/Support/MemoryBuffer.h>
-#include <llvm/Support/system_error.h>
-
-#include "BCCContext.h"
-#include "BCCContextImpl.h"
-#include "DebugHelper.h"
-
-namespace {
-
-// Helper function to load the bitcode. This uses "bitcode lazy load" feature to
-// reduce the startup time. On success, return the LLVM module object created
-// and take the ownership of input memory buffer (i.e., pInput). On error,
-// return NULL and will NOT take the ownership of pInput.
-static inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext,
-                                                llvm::MemoryBuffer *pInput) {
-  std::string error;
-  llvm::Module *module = llvm::getLazyBitcodeModule(pInput, pContext, &error);
-
-  if (module == NULL) {
-    ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
-          pInput->getBufferIdentifier(), error.c_str());
-  }
-
-  return module;
-}
-
-} // end anonymous namespace
-
-namespace bcc {
-
-Source *Source::CreateFromBuffer(BCCContext &pContext,
-                                 const char *pName,
-                                 const char *pBitcode,
-                                 size_t pBitcodeSize) {
-  llvm::StringRef input_data(pBitcode, pBitcodeSize);
-  llvm::MemoryBuffer *input_memory =
-      llvm::MemoryBuffer::getMemBuffer(input_data, pName);
-
-  if (input_memory == NULL) {
-    ALOGE("Unable to load bitcode `%s' from buffer!", pName);
-    return NULL;
-  }
-
-  llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
-                                             input_memory);
-  if (module == NULL) {
-    delete input_memory;
-    return NULL;
-  }
-
-  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
-  if (result == NULL) {
-    delete module;
-  }
-
-  return result;
-}
-
-
-Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
-  llvm::OwningPtr<llvm::MemoryBuffer> input_data;
-
-  llvm::error_code ec = llvm::MemoryBuffer::getFile(pPath, input_data);
-  if (ec != llvm::error_code::success()) {
-    ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
-                                                       ec.message().c_str());
-    return NULL;
-  }
-
-  llvm::MemoryBuffer *input_memory = input_data.take();
-  llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
-                                             input_memory);
-  if (module == NULL) {
-    delete input_memory;
-    return NULL;
-  }
-
-  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
-  if (result == NULL) {
-    delete module;
-  }
-
-  return result;
-}
-
-
-Source *Source::CreateFromModule(BCCContext &pContext, llvm::Module &pModule,
-                                 bool pNoDelete) {
-  Source *result = new (std::nothrow) Source(pContext, pModule, pNoDelete);
-  if (result == NULL) {
-    ALOGE("Out of memory during Source object allocation for `%s'!",
-          pModule.getModuleIdentifier().c_str());
-  }
-  return result;
-}
-
-Source::Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete)
-  : mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) {
-    pContext.addSource(*this);
-}
-
-Source::~Source() {
-  mContext.removeSource(*this);
-  if (!mNoDelete)
-    delete mModule;
-}
-
-bool Source::merge(Source &pSource, bool pPreserveSource) {
-  std::string error;
-  llvm::Linker::LinkerMode mode =
-      ((pPreserveSource) ? llvm::Linker::PreserveSource :
-                           llvm::Linker::DestroySource);
-
-  if (llvm::Linker::LinkModules(mModule, &pSource.getModule(),
-                                mode, &error) != 0) {
-    ALOGE("Failed to link source `%s' with `%s' (%s)!",
-          getIdentifier().c_str(),
-          pSource.getIdentifier().c_str(),
-          error.c_str());
-    return false;
-  }
-
-  if (!pPreserveSource) {
-    pSource.mNoDelete = true;
-    delete &pSource;
-  }
-
-  return true;
-}
-
-Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) {
-  // Create an empty module
-  llvm::Module *module =
-      new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext);
-
-  if (module == NULL) {
-    ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str());
-    return NULL;
-  }
-
-  Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
-  if (result == NULL) {
-    delete module;
-  }
-
-  return result;
-}
-
-const std::string &Source::getIdentifier() const {
-  return mModule->getModuleIdentifier();
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/Source.h b/lib/ExecutionEngine/Source.h
deleted file mode 100644
index b9a98e8..0000000
--- a/lib/ExecutionEngine/Source.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_SOURCE_H
-#define BCC_EXECUTION_ENGINE_SOURCE_H
-
-#include <string>
-
-namespace llvm {
-  class Module;
-}
-
-namespace bcc {
-
-class BCCContext;
-
-class Source {
-private:
-  BCCContext &mContext;
-  llvm::Module *mModule;
-
-  // If true, destructor won't destroy the mModule.
-  bool mNoDelete;
-
-private:
-  Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete = false);
-
-public:
-  static Source *CreateFromBuffer(BCCContext &pContext,
-                                  const char *pName,
-                                  const char *pBitcode,
-                                  size_t pBitcodeSize);
-
-  static Source *CreateFromFile(BCCContext &pContext,
-                                const std::string &pPath);
-
-  // Create a Source object from an existing module. If pNoDelete
-  // is true, destructor won't call delete on the given module.
-  static Source *CreateFromModule(BCCContext &pContext,
-                                  llvm::Module &pModule,
-                                  bool pNoDelete = false);
-
-  static Source *CreateEmpty(BCCContext &pContext, const std::string &pName);
-
-  // Merge the current source with pSource. If pPreserveSource is false, pSource
-  // will be destroyed after successfully merged. Return false on error.
-  bool merge(Source &pSource, bool pPreserveSource = false);
-
-  inline BCCContext &getContext()
-  { return mContext; }
-  inline const BCCContext &getContext() const
-  { return mContext; }
-
-  inline llvm::Module &getModule()
-  { return *mModule;  }
-  inline const llvm::Module &getModule() const
-  { return *mModule;  }
-
-  // Get the "identifier" of the bitcode. This will return the value of pName
-  // when it's created using CreateFromBuffer and pPath if CreateFromFile().
-  const std::string &getIdentifier() const;
-
-  ~Source();
-};
-
-} // namespace bcc
-
-#endif // BCC_EXECUTION_ENGINE_SOURCE_H
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
new file mode 100644
index 0000000..5477514
--- /dev/null
+++ b/lib/ExecutionEngine/SourceInfo.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SourceInfo.h"
+
+#include "MCCacheWriter.h"
+#include "MCCacheReader.h"
+
+#include "DebugHelper.h"
+#include "ScriptCompiled.h"
+#include "Sha1Helper.h"
+
+#include <bcc/bcc.h>
+
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Module.h>
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/system_error.h>
+
+#include <stddef.h>
+#include <string.h>
+
+namespace bcc {
+
+
+SourceInfo *SourceInfo::createFromBuffer(char const *resName,
+                                         char const *bitcode,
+                                         size_t bitcodeSize,
+                                         unsigned long flags) {
+  SourceInfo *result = new SourceInfo();
+
+  if (!result) {
+    return NULL;
+  }
+
+  result->type = SourceKind::Buffer;
+  result->buffer.resName = resName;
+  result->buffer.bitcode = bitcode;
+  result->buffer.bitcodeSize = bitcodeSize;
+  result->flags = flags;
+
+  if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
+    result->flags |= BCC_SKIP_DEP_SHA1;
+
+    ALOGW("It is required to give resName for sha1 dependency check.\n");
+    ALOGW("Sha1sum dependency check will be skipped.\n");
+    ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+  }
+
+  if (result->flags & BCC_SKIP_DEP_SHA1) {
+    memset(result->sha1, '\0', 20);
+  } else {
+    calcSHA1(result->sha1, bitcode, bitcodeSize);
+  }
+
+  return result;
+}
+
+
+SourceInfo *SourceInfo::createFromFile(char const *path,
+                                       unsigned long flags) {
+  SourceInfo *result = new SourceInfo();
+
+  if (!result) {
+    return NULL;
+  }
+
+  result->type = SourceKind::File;
+  result->file.path = path;
+  result->flags = flags;
+
+  memset(result->sha1, '\0', 20);
+
+  if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
+    calcFileSHA1(result->sha1, path);
+  }
+
+  return result;
+}
+
+
+SourceInfo *SourceInfo::createFromModule(llvm::Module *module,
+                                         unsigned long flags) {
+  SourceInfo *result = new SourceInfo();
+
+  if (!result) {
+    return NULL;
+  }
+
+  result->type = SourceKind::Module;
+  result->module = module;
+  result->flags = flags;
+
+  if (! (flags & BCC_SKIP_DEP_SHA1)) {
+    result->flags |= BCC_SKIP_DEP_SHA1;
+
+    ALOGW("Unable to calculate sha1sum for llvm::Module.\n");
+    ALOGW("Sha1sum dependency check will be skipped.\n");
+    ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+  }
+
+  memset(result->sha1, '\0', 20);
+
+  return result;
+}
+
+
+int SourceInfo::prepareModule(llvm::LLVMContext &context) {
+  if (module)
+    return 0;
+
+  llvm::OwningPtr<llvm::MemoryBuffer> mem;
+  std::string errmsg;
+
+  switch (type) {
+  case SourceKind::Buffer:
+    {
+      mem.reset(llvm::MemoryBuffer::getMemBuffer(
+          llvm::StringRef(buffer.bitcode, buffer.bitcodeSize)));
+
+      if (!mem.get()) {
+        ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
+              buffer.bitcode, (unsigned long)buffer.bitcodeSize);
+        return 1;
+      }
+    }
+    break;
+
+  case SourceKind::File:
+    {
+      if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) {
+        ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n",
+              file.path, ec.message().c_str());
+        return 1;
+      }
+    }
+    break;
+
+  default:
+    return 0;
+    break;
+  }
+
+  module = llvm::ParseBitcodeFile(mem.get(), context, &errmsg);
+  if (module == NULL) {
+    ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
+  }
+
+  return (module == NULL);
+}
+
+SourceInfo::~SourceInfo() {
+  delete module;
+}
+
+template <typename T> void SourceInfo::introDependency(T &checker) {
+  if (flags & BCC_SKIP_DEP_SHA1) {
+    return;
+  }
+
+  switch (type) {
+  case SourceKind::Buffer:
+    checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1);
+    break;
+
+  case SourceKind::File:
+    checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1);
+    break;
+
+  default:
+    break;
+  }
+}
+
+template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
+template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
+
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
new file mode 100644
index 0000000..f838f71
--- /dev/null
+++ b/lib/ExecutionEngine/SourceInfo.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_SOURCEINFO_H
+#define BCC_SOURCEINFO_H
+
+#include "Config.h"
+
+#include <llvm/Module.h>
+
+#include <stddef.h>
+
+namespace bcc {
+  namespace SourceKind {
+    enum SourceType {
+      File,
+      Buffer,
+      Module,
+    };
+  }
+
+  class SourceInfo {
+  private:
+    SourceKind::SourceType type;
+
+    // Note: module should not be a part of union.  Since, we are going to
+    // use module to store the pointer to parsed bitcode.
+    llvm::Module *module;
+
+    union {
+      struct {
+        char const *resName;
+        char const *bitcode;
+        size_t bitcodeSize;
+      } buffer;
+
+      struct {
+        char const *path;
+      } file;
+    };
+
+    unsigned long flags;
+
+    unsigned char sha1[20];
+
+  private:
+    SourceInfo() : module(NULL) { }
+
+  public:
+    static SourceInfo *createFromBuffer(char const *resName,
+                                        char const *bitcode,
+                                        size_t bitcodeSize,
+                                        unsigned long flags);
+
+    static SourceInfo *createFromFile(char const *path,
+                                      unsigned long flags);
+
+    static SourceInfo *createFromModule(llvm::Module *module,
+                                        unsigned long flags);
+
+    inline llvm::Module *getModule() const {
+      return module;
+    }
+
+    // Share with the given context if it's provided.
+    int prepareModule(llvm::LLVMContext &context);
+
+    template <typename T> void introDependency(T &checker);
+
+    ~SourceInfo();
+  };
+
+
+} // namespace bcc
+
+#endif // BCC_SOURCEINFO_H
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index ee6efaa..01ef32f 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -18,22 +18,19 @@
 //    This is an eager-compilation JIT running on Android.
 
 #include <bcc/bcc.h>
+#include "bcc_internal.h"
+
+#include "Config.h"
+
+#include "Compiler.h"
+#include "DebugHelper.h"
+#include "Script.h"
 
 #include <string>
 
 #include <utils/StopWatch.h>
 
-#include "Config.h"
-
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "BCCContext.h"
-#include "Compiler.h"
-#include "DebugHelper.h"
-#include "Script.h"
-#include "Sha1Helper.h"
-#include "Source.h"
+#include <llvm/Support/CodeGen.h>
 
 using namespace bcc;
 
@@ -54,15 +51,7 @@
 extern "C" BCCScriptRef bccCreateScript() {
   BCC_FUNC_LOGGER();
   bccPrintBuildStamp();
-  // FIXME: This is a workaround for this API: use global BCC context and
-  //        create an empty source to create a Script object.
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return NULL;
-  }
-
-  Source *source = Source::CreateEmpty(*context, "empty");
-  return wrap(new Script(*source));
+  return wrap(new bcc::Script());
 }
 
 
@@ -85,102 +74,13 @@
   return unwrap(script)->getError();
 }
 
-static bool helper_add_source(Script *pScript,
-                              char const *pName,
-                              char const *pBitcode,
-                              size_t pBitcodeSize,
-                              unsigned long pFlags,
-                              bool pIsLink) {
-  bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
-  if (!pName && need_dependency_check) {
-    pFlags |= BCC_SKIP_DEP_SHA1;
-
-    ALOGW("It is required to give resName for sha1 dependency check.\n");
-    ALOGW("Sha1sum dependency check will be skipped.\n");
-    ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
-  }
-
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return false;
-  }
-
-  Source *source = Source::CreateFromBuffer(*context, pName,
-                                            pBitcode, pBitcodeSize);
-  if (source == NULL) {
-    return false;
-  }
-
-  if (need_dependency_check) {
-    uint8_t sha1[20];
-    calcSHA1(sha1, pBitcode, pBitcodeSize);
-    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pName, sha1)) {
-      return false;
-    }
-  }
-
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
-}
-
-static bool helper_add_source(Script *pScript,
-                              llvm::Module *pModule,
-                              bool pIsLink) {
-  if (pModule == NULL)
-    return false;
-
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return false;
-  }
-
-  if (pModule == NULL) {
-    ALOGE("Cannot add null module to script!");
-    return false;
-  }
-
-  Source *source = Source::CreateFromModule(*context, *pModule, true);
-  if (source == NULL) {
-    return false;
-  }
-
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
-}
-
-static bool helper_add_source(Script *pScript,
-                              char const *pPath,
-                              unsigned long pFlags,
-                              bool pIsLink) {
-  bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
-  BCCContext *context = BCCContext::GetOrCreateGlobalContext();
-  if (context == NULL) {
-    return false;
-  }
-
-  Source *source = Source::CreateFromFile(*context, pPath);
-  if (source == NULL) {
-    return false;
-  }
-
-  if (need_dependency_check) {
-    uint8_t sha1[20];
-    calcFileSHA1(sha1, pPath);
-    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pPath, sha1)) {
-      return false;
-    }
-  }
-
-  return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
-}
-
 extern "C" int bccReadBC(BCCScriptRef script,
                          char const *resName,
                          char const *bitcode,
                          size_t bitcodeSize,
                          unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return (helper_add_source(unwrap(script), resName,
-                            bitcode, bitcodeSize,
-                            flags, /* pIsLink */false) == false);
+  return unwrap(script)->addSourceBC(0, resName, bitcode, bitcodeSize, flags);
 }
 
 
@@ -189,8 +89,7 @@
                              LLVMModuleRef module,
                              unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return (helper_add_source(unwrap(script), unwrap(module),
-                            /* pIsLink */false) == false);
+  return unwrap(script)->addSourceModule(0, unwrap(module), flags);
 }
 
 
@@ -198,8 +97,7 @@
                            char const *path,
                            unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return (helper_add_source(unwrap(script), path,
-                            flags, /* pIsLink */false) == false);
+  return unwrap(script)->addSourceFile(0, path, flags);
 }
 
 
@@ -209,9 +107,7 @@
                          size_t bitcodeSize,
                          unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return (helper_add_source(unwrap(script), resName,
-                            bitcode, bitcodeSize,
-                            flags, /* pIsLink */true) == false);
+  return unwrap(script)->addSourceBC(1, resName, bitcode, bitcodeSize, flags);
 }
 
 
@@ -219,8 +115,7 @@
                            char const *path,
                            unsigned long flags) {
   BCC_FUNC_LOGGER();
-  return (helper_add_source(unwrap(script), path,
-                            flags, /* pIsLink */true) == false);
+  return unwrap(script)->addSourceFile(1, path, flags);
 }