Configure standalone bcc compiler to work with plugin libraries.

Bug: 7342767

This change adds support (hidden behind the EXTERNAL_BCC_COMPILER ifdef)
for loading plugin libraries via the external bcc toolchain. The external
bcc compiler loads the named library and will then invoke a customized
rsCompilerDriverInit() from that library.

Change-Id: I07c2ea68be54c2255d36926fd37e395db790ef8f
diff --git a/cpu_ref/Android.mk b/cpu_ref/Android.mk
index c7565da..82c1ca9 100644
--- a/cpu_ref/Android.mk
+++ b/cpu_ref/Android.mk
@@ -85,6 +85,8 @@
 LOCAL_C_INCLUDES += frameworks/rs
 LOCAL_C_INCLUDES += system/core/include
 
+include external/libcxx/libcxx.mk
+
 LOCAL_CFLAGS += $(rs_base_CFLAGS)
 
 LOCAL_LDLIBS := -lpthread -ldl
diff --git a/cpu_ref/rsCpuCore.cpp b/cpu_ref/rsCpuCore.cpp
index f2ce358..0a3a872 100644
--- a/cpu_ref/rsCpuCore.cpp
+++ b/cpu_ref/rsCpuCore.cpp
@@ -66,7 +66,8 @@
         uint32_t version_minor, sym_lookup_t lfn, script_lookup_t slfn
 #ifndef RS_COMPATIBILITY_LIB
         , bcc::RSLinkRuntimeCallback pLinkRuntimeCallback,
-        RSSelectRTCallback pSelectRTCallback
+        RSSelectRTCallback pSelectRTCallback,
+        const char *pBccPluginName
 #endif
         ) {
 
@@ -82,6 +83,9 @@
 #ifndef RS_COMPATIBILITY_LIB
     cpu->setLinkRuntimeCallback(pLinkRuntimeCallback);
     cpu->setSelectRTCallback(pSelectRTCallback);
+    if (pBccPluginName) {
+        cpu->setBccPluginName(pBccPluginName);
+    }
 #endif
 
     return cpu;
@@ -504,7 +508,11 @@
                                     uint32_t flags) {
 
     RsdCpuScriptImpl *i = new RsdCpuScriptImpl(this, s);
-    if (!i->init(resName, cacheDir, bitcode, bitcodeSize, flags)) {
+    if (!i->init(resName, cacheDir, bitcode, bitcodeSize, flags
+#ifndef RS_COMPATIBILITY_LIB
+        , getBccPluginName()
+#endif
+        )) {
         delete i;
         return NULL;
     }
diff --git a/cpu_ref/rsCpuCore.h b/cpu_ref/rsCpuCore.h
index 22d0d28..31de95b 100644
--- a/cpu_ref/rsCpuCore.h
+++ b/cpu_ref/rsCpuCore.h
@@ -23,6 +23,8 @@
 #include "rsElement.h"
 #include "rsScriptC.h"
 
+#include <string>
+
 namespace bcc {
     class BCCContext;
     class RSCompilerDriver;
@@ -134,6 +136,13 @@
     virtual RSSetupCompilerCallback getSetupCompilerCallback() const {
         return mSetupCompilerCallback;
     }
+
+    virtual void setBccPluginName(const char *name) {
+        mBccPluginName.assign(name);
+    }
+    virtual const char *getBccPluginName() const {
+        return mBccPluginName.c_str();
+    }
 #endif
     virtual bool getInForEach() { return mInForEach; }
 
@@ -166,6 +175,7 @@
     bcc::RSLinkRuntimeCallback mLinkRuntimeCallback;
     RSSelectRTCallback mSelectRTCallback;
     RSSetupCompilerCallback mSetupCompilerCallback;
+    std::string mBccPluginName;
 #endif
 };
 
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index 2cf9b83..d4888e1 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -38,6 +38,9 @@
     #include <sys/types.h>
     #include <sys/wait.h>
     #include <unistd.h>
+
+    #include <string>
+    #include <vector>
 #endif
 #endif
 
@@ -221,7 +224,9 @@
                            const char *resName,
                            const char *bitcode,
                            size_t bitcodeSize,
-                           const char *core_lib) {
+                           const char *core_lib,
+                           bool useRSDebugContext,
+                           const char *bccPluginName) {
     rsAssert(cacheDir && resName && bitcode && bitcodeSize && core_lib);
 
     android::String8 bcFilename(cacheDir);
@@ -242,21 +247,46 @@
     }
 
     pid_t pid = fork();
+
     switch (pid) {
     case -1: {  // Error occurred (we attempt no recovery)
         ALOGE("Couldn't fork for bcc compiler execution");
         return false;
     }
     case 0: {  // Child process
+        std::vector<std::string> args;
+        args.push_back(BCC_EXE_PATH);
+        args.push_back("-o");
+        args.push_back(resName);
+        args.push_back("-output_path");
+        args.push_back(cacheDir);
+        args.push_back("-bclib");
+        args.push_back(core_lib);
+
         // Execute the bcc compiler.
-        execl(BCC_EXE_PATH,
-              BCC_EXE_PATH,
-              "-o", resName,
-              "-output_path", cacheDir,
-              "-bclib", core_lib,
-              bcFilename.string(),
-              (char *) NULL);
-        ALOGE("execl() failed: %s", strerror(errno));
+        if (useRSDebugContext) {
+            args.push_back("-rs-debug-ctx");
+        } else {
+            // Only load additional libraries for compiles that don't use
+            // the debug context.
+            if (bccPluginName && strlen(bccPluginName) > 0) {
+                args.push_back("-load");
+                args.push_back(bccPluginName);
+            }
+        }
+
+        args.push_back(bcFilename.string());
+
+        const char **cargs = new const char *[args.size() + 1];
+        for (uint32_t i = 0; i < args.size(); i++) {
+            cargs[i] = args[i].c_str();
+        }
+        cargs[args.size()] = NULL;
+
+        execv(BCC_EXE_PATH, (char *const *)cargs);
+
+        delete [] cargs;
+        ALOGE("execv() failed: %s", strerror(errno));
         abort();
         return false;
     }
@@ -360,7 +390,7 @@
 
 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
                             uint8_t const *bitcode, size_t bitcodeSize,
-                            uint32_t flags) {
+                            uint32_t flags, char const *bccPluginName) {
     //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
     //ALOGE("rsdScriptInit %p %p", rsc, script);
 
@@ -368,6 +398,7 @@
 #ifndef FAKE_ARM64_BUILD
 #ifndef RS_COMPATIBILITY_LIB
     bcc::RSExecutable *exec = NULL;
+    bool useRSDebugContext = false;
 
     mCompilerContext = NULL;
     mCompilerDriver = NULL;
@@ -436,6 +467,7 @@
         // Use the libclcore_debug.bc instead of the default library.
         core_lib = bcc::RSInfo::LibCLCoreDebugPath;
         mCompilerDriver->setDebugContext(true);
+        useRSDebugContext = true;
         // Skip the cache lookup
     } else if (!is_force_recompile()) {
         // Attempt to just load the script from cache first if we can.
@@ -446,7 +478,8 @@
     if (exec == NULL) {
 #ifdef EXTERNAL_BCC_COMPILER
         bool built = compileBitcode(cacheDir, resName, (const char *)bitcode,
-                                    bitcodeSize, core_lib);
+                                    bitcodeSize, core_lib, useRSDebugContext,
+                                    bccPluginName);
 #else
         bool built = mCompilerDriver->build(*mCompilerContext, cacheDir,
                                             resName, (const char *)bitcode,
diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h
index eeb38bf..4cc9d6d 100644
--- a/cpu_ref/rsCpuScript.h
+++ b/cpu_ref/rsCpuScript.h
@@ -47,7 +47,8 @@
 #endif
 
     bool init(char const *resName, char const *cacheDir,
-              uint8_t const *bitcode, size_t bitcodeSize, uint32_t flags);
+              uint8_t const *bitcode, size_t bitcodeSize, uint32_t flags,
+              char const *bccPluginName = NULL);
     virtual void populateScript(Script *);
 
     virtual void invokeFunction(uint32_t slot, const void *params, size_t paramLength);
diff --git a/cpu_ref/rsd_cpu.h b/cpu_ref/rsd_cpu.h
index d81a145..ac4cf31 100644
--- a/cpu_ref/rsd_cpu.h
+++ b/cpu_ref/rsd_cpu.h
@@ -110,7 +110,8 @@
                                     uint32_t version_minor, sym_lookup_t lfn, script_lookup_t slfn
 #ifndef RS_COMPATIBILITY_LIB
                                     , bcc::RSLinkRuntimeCallback pLinkRuntimeCallback = NULL,
-                                    RSSelectRTCallback pSelectRTCallback = NULL
+                                    RSSelectRTCallback pSelectRTCallback = NULL,
+                                    const char *pBccPluginName = NULL
 #endif
                                     );
     virtual ~RsdCpuReference();