Add bccPrepareSharedObject

Unlike bccPrepareExecuteable, bccPrepareSharedObject does not
resolve external symbols; therefore it only generate cache file
not execuable.

Change-Id: I3ef093015a4f54011fbf298123cac2464230b408
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index c1c9267..09c0890 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -308,7 +308,7 @@
 }
 
 
-int Compiler::compile() {
+int Compiler::compile(bool compileOnly) {
   llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
   llvm::TargetMachine *TM = NULL;
@@ -370,11 +370,77 @@
 #endif
 
 #if USE_MCJIT
-  if (runMCCodeGen(new llvm::TargetData(*TD), TM,
-                   ExportVarMetadata, ExportFuncMetadata) != 0) {
+  if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) {
     goto on_bcc_compile_error;
   }
 
+  if (compileOnly)
+    return 0;
+
+  // Load the ELF Object
+  mRSExecutable =
+    rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
+                       mEmittedELFExecutable.size(),
+                       &resolveSymbolAdapter, this);
+
+  if (!mRSExecutable) {
+    setError("Fail to load emitted ELF relocatable file");
+    goto on_bcc_compile_error;
+  }
+
+  if (ExportVarMetadata) {
+    ScriptCompiled::ExportVarList &varList = mpResult->mExportVars;
+    std::vector<std::string> &varNameList = mpResult->mExportVarsName;
+
+    for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
+      if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
+        llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
+        if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef ExportVarName =
+            static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
+
+          varList.push_back(
+            rsloaderGetSymbolAddress(mRSExecutable,
+                                     ExportVarName.str().c_str()));
+          varNameList.push_back(ExportVarName.str());
+#if DEBUG_MCJIT_REFLECT
+          LOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(),
+               varList.back());
+#endif
+          continue;
+        }
+      }
+
+      varList.push_back(NULL);
+    }
+  }
+
+  if (ExportFuncMetadata) {
+    ScriptCompiled::ExportFuncList &funcList = mpResult->mExportFuncs;
+    std::vector<std::string> &funcNameList = mpResult->mExportFuncsName;
+
+    for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
+      if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
+        llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
+        if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef ExportFuncName =
+            static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
+
+          funcList.push_back(
+            rsloaderGetSymbolAddress(mRSExecutable,
+                                     ExportFuncName.str().c_str()));
+          funcNameList.push_back(ExportFuncName.str());
+#if DEBUG_MCJIT_RELECT
+          LOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
+               funcList.back());
+#endif
+        }
+      }
+    }
+  }
+
 #if DEBUG_MCJIT_DISASSEMBLER
   {
     // Get MC codegen emitted function name list
@@ -599,9 +665,7 @@
 
 
 #if USE_MCJIT
-int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
-                           llvm::NamedMDNode const *ExportVarMetadata,
-                           llvm::NamedMDNode const *ExportFuncMetadata) {
+int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) {
   // Decorate mEmittedELFExecutable with formatted ostream
   llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable);
 
@@ -624,75 +688,6 @@
 
   MCCodeGenPasses.run(*mModule);
   OutSVOS.flush();
-
-  // Load the ELF Object
-  mRSExecutable =
-    rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
-                       mEmittedELFExecutable.size(),
-                       &resolveSymbolAdapter, this);
-
-  if (!mRSExecutable) {
-    setError("Fail to load emitted ELF relocatable file");
-    return 1;
-  }
-
-#if !USE_OLD_JIT
-  // Note: If old JIT is compiled then we prefer the old version instead of the
-  // new version.
-
-  if (ExportVarMetadata) {
-    ScriptCompiled::ExportVarList &varList = mpResult->mExportVars;
-    std::vector<std::string> &varNameList = mpResult->mExportVarsName;
-
-    for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
-      llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
-      if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
-        llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
-        if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
-          llvm::StringRef ExportVarName =
-            static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
-
-          varList.push_back(
-            rsloaderGetSymbolAddress(mRSExecutable,
-                                     ExportVarName.str().c_str()));
-          varNameList.push_back(ExportVarName.str());
-#if DEBUG_MCJIT_REFLECT
-          LOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(),
-               varList.back());
-#endif
-          continue;
-        }
-      }
-
-      varList.push_back(NULL);
-    }
-  }
-
-  if (ExportFuncMetadata) {
-    ScriptCompiled::ExportFuncList &funcList = mpResult->mExportFuncs;
-    std::vector<std::string> &funcNameList = mpResult->mExportFuncsName;
-
-    for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
-      llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
-      if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
-        llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
-        if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
-          llvm::StringRef ExportFuncName =
-            static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
-
-          funcList.push_back(
-            rsloaderGetSymbolAddress(mRSExecutable,
-                                     ExportFuncName.str().c_str()));
-          funcNameList.push_back(ExportFuncName.str());
-#if DEBUG_MCJIT_RELECT
-          LOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
-               funcList.back());
-#endif
-        }
-      }
-    }
-  }
-#endif // !USE_OLD_JIT
   return 0;
 }
 #endif // USE_MCJIT
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 82e0be2..c6938a6 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -153,7 +153,7 @@
 
     int linkModule(llvm::Module *module);
 
-    int compile();
+    int compile(bool compileOnly);
 
     char const *getErrorMessage() {
       return mError.c_str();
@@ -171,9 +171,7 @@
                    llvm::NamedMDNode const *ExportVarMetadata,
                    llvm::NamedMDNode const *ExportFuncMetadata);
 
-    int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
-                     llvm::NamedMDNode const *ExportVarMetadata,
-                     llvm::NamedMDNode const *ExportFuncMetadata);
+    int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);
 
 #if USE_MCJIT
     static void *resolveSymbolAdapter(void *context, char const *name);
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
index 82b7cdc..39e567f 100644
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ b/lib/ExecutionEngine/MCCacheReader.cpp
@@ -54,9 +54,24 @@
 ScriptCached *MCCacheReader::readCacheFile(FileHandle *objFile,
                                            FileHandle *infoFile,
                                            Script *S) {
+  bool result = checkCacheFile(objFile, infoFile, S)
+             && readPragmaList()
+             && readObjectSlotList()
+             && readObjFile()
+             && readVarNameList()
+             && readFuncNameList()
+             //&& relocate()
+             ;
+
+  return result ? mpResult.take() : NULL;
+}
+
+bool MCCacheReader::checkCacheFile(FileHandle *objFile,
+                                            FileHandle *infoFile,
+                                            Script *S) {
   // Check file handle
   if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
-    return NULL;
+    return false;
   }
 
   mObjFile = objFile;
@@ -67,7 +82,7 @@
 
   if (!mpResult) {
     LOGE("Unable to allocate ScriptCached object.\n");
-    return NULL;
+    return false;
   }
 
   bool result = checkFileSize()
@@ -79,15 +94,9 @@
              && checkStringPool()
              && readDependencyTable()
              && checkDependency()
-             && readPragmaList()
-             && readObjectSlotList()
-             && readObjFile()
-             && readVarNameList()
-             && readFuncNameList()
-             //&& relocate()
              ;
 
-  return result ? mpResult.take() : NULL;
+  return result;
 }
 
 
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
index d9e4027..7fcbe41 100644
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ b/lib/ExecutionEngine/MCCacheReader.h
@@ -75,6 +75,7 @@
     }
 
     ScriptCached *readCacheFile(FileHandle *objFile, FileHandle *infoFile, Script *s);
+    bool checkCacheFile(FileHandle *objFile, FileHandle *infoFile, Script *S);
 
     bool isContextSlotNotAvail() const {
       return mIsContextSlotNotAvail;
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 26929fd..e67fd61 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -178,6 +178,32 @@
   return 0;
 }
 
+int Script::prepareSharedObject(char const *cacheDir,
+                                char const *cacheName,
+                                unsigned long flags) {
+#if USE_CACHE
+  if (cacheDir && cacheName) {
+    // Set Cache Directory and File Name
+    mCacheDir = cacheDir;
+    mCacheName = cacheName;
+
+    if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
+      mCacheDir.push_back('/'); // Ensure mCacheDir is end with '/'
+    }
+
+    // Check Cache File
+    if (internalLoadCache(true) == 0) {
+      return 0;
+    }
+  }
+#endif
+  int status = internalCompile(true);
+  if (status != 0) {
+    LOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+  }
+  return status;
+}
+
 
 int Script::prepareExecutable(char const *cacheDir,
                               char const *cacheName,
@@ -199,13 +225,13 @@
     }
 
     // Load Cache File
-    if (internalLoadCache() == 0) {
+    if (internalLoadCache(false) == 0) {
       return 0;
     }
   }
 #endif
 
-  int status = internalCompile();
+  int status = internalCompile(false);
   if (status != 0) {
     LOGE("LLVM error message: %s\n", getCompilerErrorMessage());
   }
@@ -214,7 +240,7 @@
 
 
 #if USE_CACHE
-int Script::internalLoadCache() {
+int Script::internalLoadCache(bool checkOnly) {
   if (getBooleanProp("debug.bcc.nocache")) {
     // Android system environment property disable the cache mechanism by
     // setting "debug.bcc.nocache".  So we will not load the cache file any
@@ -270,6 +296,9 @@
     }
   }
 
+  if (checkOnly)
+    return reader.checkCacheFile(&objFile, &infoFile, this);
+
   // Read cache file
   ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
 
@@ -291,7 +320,7 @@
 }
 #endif
 
-int Script::internalCompile() {
+int Script::internalCompile(bool compileOnly) {
   // Create the ScriptCompiled object
   mCompiled = new (std::nothrow) ScriptCompiled(this);
 
@@ -337,7 +366,7 @@
   }
 
   // Compile and JIT the code
-  if (mCompiled->compile() != 0) {
+  if (mCompiled->compile(compileOnly) != 0) {
     LOGE("Unable to compile.\n");
     return 1;
   }
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index 921af8c..46b385f 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -103,6 +103,10 @@
                           char const *cacheName,
                           unsigned long flags);
 
+    int prepareSharedObject(char const *cacheDir,
+                          char const *cacheName,
+                          unsigned long flags);
+
     char const *getCompilerErrorMessage();
 
     void *lookup(const char *name);
@@ -159,9 +163,9 @@
 
   private:
 #if USE_CACHE
-    int internalLoadCache();
+    int internalLoadCache(bool checkOnly);
 #endif
-    int internalCompile();
+    int internalCompile(bool compileOnly);
 
   };
 
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 9593be8..5972ddf 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -88,8 +88,8 @@
       return mCompiler.linkModule(module);
     }
 
-    int compile() {
-      return mCompiler.compile();
+    int compile(bool compileOnly) {
+      return mCompiler.compile(compileOnly);
     }
 
     char const *getCompilerErrorMessage() {
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 1d2bc8f..1686cb2 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -117,6 +117,14 @@
 }
 
 
+extern "C" int bccPrepareSharedObject(BCCScriptRef script,
+                                      char const *cacheDir,
+                                      char const *cacheName,
+                                      unsigned long flags) {
+  return unwrap(script)->prepareSharedObject(cacheDir, cacheName, flags);
+}
+
+
 extern "C" int bccPrepareExecutable(BCCScriptRef script,
                                     char const *cacheDir,
                                     char const *cacheName,