Merge "Improve standalone bcc for on-device compilation."
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index 371014c..7863ae6 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -28,8 +28,14 @@
 
 class BCCContext;
 class CompilerConfig;
+class RSCompilerDriver;
 class RSExecutable;
 
+// Type signature for dynamically loaded initialization of an RSCompilerDriver.
+typedef void (*RSCompilerDriverInit_t) (bcc::RSCompilerDriver *);
+// Name of the function that we attempt to dynamically load/execute.
+#define RS_COMPILER_DRIVER_INIT_FN rsCompilerDriverInit
+
 class RSCompilerDriver {
 private:
   CompilerConfig *mConfig;
@@ -42,6 +48,9 @@
   // Are we compiling under an RS debug context with additional checks?
   bool mDebugContext;
 
+  // Callback before linking with the runtime library.
+  RSLinkRuntimeCallback mLinkRuntimeCallback;
+
   // Do we merge global variables on ARM using LLVM's optimization pass?
   // Disabling LLVM's global merge pass allows static globals to be correctly
   // emitted to ELF. This can result in decreased performance due to increased
@@ -82,6 +91,14 @@
     mDebugContext = v;
   }
 
+  void setLinkRuntimeCallback(RSLinkRuntimeCallback c) {
+    mLinkRuntimeCallback = c;
+  }
+
+  RSLinkRuntimeCallback getLinkRuntimeCallback() const {
+    return mLinkRuntimeCallback;
+  }
+
   // This function enables/disables merging of global static variables.
   // Note that it only takes effect on ARM architectures (other architectures
   // do not offer this option).
diff --git a/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index 7da3420..346bd2f 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -46,7 +46,7 @@
 
 RSCompilerDriver::RSCompilerDriver(bool pUseCompilerRT) :
     mConfig(NULL), mCompiler(), mCompilerRuntime(NULL), mDebugContext(false),
-    mEnableGlobalMerge(true) {
+    mLinkRuntimeCallback(NULL), mEnableGlobalMerge(true) {
   init::Initialize();
   // Chain the symbol resolvers for compiler_rt and RS runtimes.
   if (pUseCompilerRT) {
@@ -390,8 +390,11 @@
     delete source;
     return false;
   }
+  if (pLinkRuntimeCallback) {
+    setLinkRuntimeCallback(pLinkRuntimeCallback);
+  }
 
-  script->setLinkRuntimeCallback(pLinkRuntimeCallback);
+  script->setLinkRuntimeCallback(getLinkRuntimeCallback());
 
   // Read information from bitcode wrapper.
   bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
diff --git a/tools/bcc/Main.cpp b/tools/bcc/Main.cpp
index 04b6942..e5b8bc0 100644
--- a/tools/bcc/Main.cpp
+++ b/tools/bcc/Main.cpp
@@ -17,6 +17,7 @@
 #include <string>
 #include <vector>
 
+#include <dlfcn.h>
 #include <stdlib.h>
 
 #include <llvm/ADT/OwningPtr.h>
@@ -26,6 +27,7 @@
 #include <llvm/Support/CommandLine.h>
 #include <llvm/Support/FileSystem.h>
 #include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/PluginLoader.h>
 #include <llvm/Support/raw_ostream.h>
 #include <llvm/Support/system_error.h>
 
@@ -48,6 +50,9 @@
 
 using namespace bcc;
 
+#define STR2(a) #a
+#define STR(a) STR2(a)
+
 //===----------------------------------------------------------------------===//
 // General Options
 //===----------------------------------------------------------------------===//
@@ -90,6 +95,10 @@
                                  llvm::cl::aliasopt(OptTargetTriple));
 #endif
 
+llvm::cl::opt<bool>
+OptRSDebugContext("rs-debug-ctx",
+    llvm::cl::desc("Enable build to work with a RenderScript debug context"));
+
 //===----------------------------------------------------------------------===//
 // Compiler Options
 //===----------------------------------------------------------------------===//
@@ -148,6 +157,10 @@
   pRSCD.setConfig(config);
   Compiler::ErrorCode result = RSC->config(*config);
 
+  if (OptRSDebugContext) {
+    pRSCD.setDebugContext(true);
+  }
+
   if (result != Compiler::kSuccess) {
     llvm::errs() << "Failed to configure the compiler! (detail: "
                  << Compiler::GetErrorString(result) << ")\n";
@@ -184,6 +197,15 @@
     ALOGE("Failed to configure compiler");
     return EXIT_FAILURE;
   }
+
+  // Attempt to dynamically initialize the compiler driver if such a function
+  // is present. It is only present if passed via "-load libFOO.so".
+  RSCompilerDriverInit_t rscdi = (RSCompilerDriverInit_t)
+      dlsym(RTLD_DEFAULT, STR(RS_COMPILER_DRIVER_INIT_FN));
+  if (rscdi != NULL) {
+    rscdi(&RSCD);
+  }
+
   bool built = RSCD.build(context, OptOutputPath.c_str(),
       OptOutputFilename.c_str(), bitcode, bitcodeSize,
       OptBCLibFilename.c_str(), NULL, OptEmitLLVM);