Add DEBUG_MCJIT_REFLECT and DEBUG_MCJIT_DISASSEMBLE.

Add disassembler support for MCJTI. Courtesy of outstanding intern
logan: To use disassembler for MCJIT, you have to change
USE_DISASSEMBLER to 1, and touch /data/local/tmp/mcjit-dis.s.

The disassembled assembly will be printed to
/data/local/tmp/mcjit-dis.s.

Change-Id: I488fc60ae399e7298f1360ac7219af46a980b577
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index 1a22ad5..bf4f164 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -47,10 +47,20 @@
 #include "llvm/Target/TargetRegistry.h"
 #include "llvm/Target/TargetSelect.h"
 
+#if USE_DISASSEMBLER
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/LLVMContext.h"
+#endif
+
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/MemoryBuffer.h"
 
+#include "llvm/Type.h"
 #include "llvm/GlobalValue.h"
 #include "llvm/Linker.h"
 #include "llvm/LLVMContext.h"
@@ -70,7 +80,35 @@
 #include <string>
 #include <vector>
 
-#define DEBUG_BCC_REFLECT_TO_LIBRS 0
+namespace {
+
+#if USE_DISASSEMBLER
+class BufferMemoryObject : public llvm::MemoryObject {
+private:
+  const uint8_t *mBytes;
+  uint64_t mLength;
+
+public:
+  BufferMemoryObject(const uint8_t *Bytes, uint64_t Length)
+    : mBytes(Bytes), mLength(Length) {
+  }
+
+  virtual uint64_t getBase() const { return 0; }
+  virtual uint64_t getExtent() const { return mLength; }
+
+  virtual int readByte(uint64_t Addr, uint8_t *Byte) const {
+    if (Addr > getExtent())
+      return -1;
+    *Byte = mBytes[Addr];
+    return 0;
+  }
+};
+#endif
+
+}; // namespace anonymous
+
+#define DEBUG_MCJIT REFLECT 0
+#define DEBUG_MCJIT_DISASSEMBLE 1
 
 namespace bcc {
 
@@ -374,6 +412,22 @@
                    ExportVarMetadata, ExportFuncMetadata) != 0) {
     goto on_bcc_compile_error;
   }
+#if USE_DISASSEMBLER && DEBUG_MCJIT_DISASSEMBLE
+  {
+    llvm::LLVMContext Ctx;
+    LOGD("@ long long alignment: %d\n", TD->getABITypeAlignment((llvm::Type const *)llvm::Type::getInt64Ty(Ctx)));
+    char const *func_list[] = { "root", ".helper_lookAt" };
+    size_t func_list_size = sizeof(func_list) / sizeof(char const *);
+
+    for (size_t i = 0; i < func_list_size; ++i) {
+      void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]);
+      if (func) {
+        size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]);
+        Disassemble(Target, TM, func_list[i], (unsigned char const *)func, size);
+      }
+    }
+  }
+#endif
 #endif
 
   // Read pragma information from the metadata node of the module.
@@ -399,7 +453,7 @@
                                        PragmaName.size()),
                            std::string(PragmaValue.data(),
                                        PragmaValue.size())));
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
           LOGD("compile(): Pragma: %s -> %s\n", pragmaList.back().first.c_str(),
                                            pragmaList.back().second.c_str());
 #endif
@@ -425,7 +479,7 @@
             goto on_bcc_compile_error;
           }
           objectSlotList.push_back(USlot);
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
           LOGD("compile(): RefCount Slot: %s @ %u\n", Slot.str().c_str(), USlot);
 #endif
         }
@@ -525,7 +579,7 @@
               continue;
             if (ExportVarName == I->first->getName()) {
               varList.push_back(I->second);
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
               LOGD("runCodeGen(): Exported VAR: %s @ %p\n", ExportVarName.str().c_str(), I->second);
 #endif
               break;
@@ -534,7 +588,7 @@
           if (I != mCodeEmitter->global_address_end())
             continue;  // found
 
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
           LOGD("runCodeGen(): Exported VAR: %s @ %p\n",
                ExportVarName.str().c_str(), (void *)0);
 #endif
@@ -560,7 +614,7 @@
           llvm::StringRef ExportFuncName =
             static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
           funcList.push_back(mpResult->lookup(ExportFuncName.str().c_str()));
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
           LOGD("runCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
                funcList.back());
 #endif
@@ -634,7 +688,7 @@
           varList.push_back(
             rsloaderGetSymbolAddress(mRSExecutable,
                                      ExportVarName.str().c_str()));
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_REFLECT
           LOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(),
                varList.back());
 #endif
@@ -660,7 +714,7 @@
           funcList.push_back(
             rsloaderGetSymbolAddress(mRSExecutable,
                                      ExportFuncName.str().c_str()));
-#if DEBUG_BCC_REFLECT_TO_LIBRS
+#if DEBUG_MCJIT_RELECT
           LOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
                funcList.back());
 #endif
@@ -872,4 +926,77 @@
   // llvm::llvm_shutdown();
 }
 
+#if USE_MCJIT && USE_DISASSEMBLER
+void Compiler::Disassemble(llvm::Target const *Target,
+                           llvm::TargetMachine *TM,
+                           std::string const &Name,
+                           unsigned char const *Func,
+                           size_t FuncSize) {
+  llvm::raw_ostream *OS;
+
+#if USE_DISASSEMBLER_FILE
+  std::string ErrorInfo;
+  OS = new llvm::raw_fd_ostream("/data/local/tmp/mcjit-dis.s", ErrorInfo,
+                                llvm::raw_fd_ostream::F_Append);
+
+  if (!ErrorInfo.empty()) {    // some errors occurred
+    // LOGE("Error in creating disassembly file");
+    delete OS;
+    return;
+  }
+#else
+  OS = &llvm::outs();
+#endif
+
+  *OS << "MC/ Disassembled code: " << Name << "\n";
+
+  const llvm::MCAsmInfo *AsmInfo;
+  const llvm::MCDisassembler *Disassmbler;
+  llvm::MCInstPrinter *IP;
+
+  AsmInfo = Target->createAsmInfo(Compiler::Triple);
+  Disassmbler = Target->createMCDisassembler();
+  IP = Target->createMCInstPrinter(*TM,
+                                   AsmInfo->getAssemblerDialect(),
+                                   *AsmInfo);
+
+  const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize);
+
+  uint64_t Size;
+  uint64_t Index;
+
+  for (Index = 0; Index < FuncSize; Index += Size) {
+    llvm::MCInst Inst;
+
+    if (Disassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
+                                    /* REMOVED */ llvm::nulls())) {
+      OS->indent(4);
+      OS->write("0x", 2);
+      OS->write_hex((uint32_t)Func + Index);
+      OS->write(": 0x", 4);
+      OS->write_hex(*(uint32_t *)(Func + Index));
+      IP->printInst(&Inst, *OS);
+      *OS << "\n";
+    } else {
+      if (Size == 0)
+        Size = 1;  // skip illegible bytes
+    }
+  }
+
+  *OS << "\n";
+  delete BufferMObj;
+
+  delete AsmInfo;
+  delete Disassmbler;
+  delete IP;
+
+#if USE_DISASSEMBLER_FILE
+  // If you want the disassemble results write to file, uncomment this.
+  ((llvm::raw_fd_ostream*)OS)->close();
+  delete OS;
+#endif
+}
+#endif
+
+
 }  // namespace bcc
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index dd2a50c..ecd7235 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -104,6 +104,14 @@
 
     // Loaded and relocated executable
     RSExecRef mRSExecutable;
+
+#if USE_DISASSEMBLER
+    void Disassemble(llvm::Target const *Target,
+                     llvm::TargetMachine *TM,
+                     std::string const &name,
+                     unsigned char const *code,
+                     size_t size);
+#endif
 #endif
 
     BCCSymbolLookupFn mpSymbolLookupFn;