Dump disassembly in RS after the compilation. BUG=6841435.

Change libbcc_DEBUG_MC_DISASSEMBLER in libbcc-config.mk to enable
this feature.

Change-Id: Iaac106dfa9cda1b1830ea4255807ab08b2f0e2bb
diff --git a/lib/RenderScript/RSCompilerDriver.cpp b/lib/RenderScript/RSCompilerDriver.cpp
index 60a6d9d..21d3bca 100644
--- a/lib/RenderScript/RSCompilerDriver.cpp
+++ b/lib/RenderScript/RSCompilerDriver.cpp
@@ -287,6 +287,20 @@
   }
 
   //===--------------------------------------------------------------------===//
+  // Dump the disassembly for debug when possible.
+  //===--------------------------------------------------------------------===//
+#if DEBUG_MC_DISASSEMBLER
+  OutputFile *disassembly_output =
+      new (std::nothrow) OutputFile(DEBUG_MC_DISASSEMBLER_FILE,
+                                    FileBase::kAppend);
+
+  if (disassembly_output != NULL) {
+    result->dumpDisassembly(*disassembly_output);
+    delete disassembly_output;
+  }
+#endif
+
+  //===--------------------------------------------------------------------===//
   // Write out the RS info file.
   //===--------------------------------------------------------------------===//
   // Note that write failure only results in a warning since the source is
diff --git a/lib/RenderScript/RSExecutable.cpp b/lib/RenderScript/RSExecutable.cpp
index e18167a..aa6d411 100644
--- a/lib/RenderScript/RSExecutable.cpp
+++ b/lib/RenderScript/RSExecutable.cpp
@@ -16,6 +16,8 @@
 
 #include "bcc/RenderScript/RSExecutable.h"
 
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Disassembler.h"
 #include "bcc/Support/FileBase.h"
 #include "bcc/Support/Log.h"
 #include "bcc/Support/OutputFile.h"
@@ -157,6 +159,48 @@
   return true;
 }
 
+void RSExecutable::dumpDisassembly(OutputFile &pOutput) const {
+#if DEBUG_MC_DISASSEMBLER
+  if (pOutput.hasError()) {
+    return;
+  }
+
+  // Get MC codegen emitted function name list.
+  android::Vector<const char *> func_list;
+
+  if (!mLoader->getSymbolNameList(func_list, ObjectLoader::kFunctionType)) {
+    ALOGW("Failed to get the list of function name in %s for disassembly!",
+          mObjFile->getName().c_str());
+  } else {
+    // Disassemble each function
+    for (size_t i = 0, e = func_list.size(); i != e; i++) {
+      const char* func_name = func_list[i];
+      void *func = mLoader->getSymbolAddress(func_name);
+      size_t func_size = mLoader->getSymbolSize(func_name);
+
+      if (func == NULL) {
+        continue;
+      }
+      DisassembleResult result =
+          Disassemble(pOutput, DEFAULT_TARGET_TRIPLE_STRING, func_name,
+                      reinterpret_cast<const uint8_t *>(func), func_size);
+
+      if (result != kDisassembleSuccess) {
+        ALOGW("Failed to disassemble the function %s in %s (error code=%zu)!",
+              func_name, mObjFile->getName().c_str(), result);
+
+        if (result != kDisassembleInvalidInstruction) {
+          ALOGW("And the error occured in disassembler is fatal. Abort "
+                "disassembler on remaining functions!");
+          break;
+        }
+      }
+    }
+  }
+#endif
+  return;
+}
+
 RSExecutable::~RSExecutable() {
   syncInfo();
   delete mInfo;