c0bdc634b950 — Leonard Ritter 2 months ago
* fixed support for `compile-flag-dump-disassembly`
4 files changed, 152 insertions(+), 130 deletions(-)

M src/execution.cpp
M src/execution.hpp
M src/gen_llvm.cpp
M testing/test_codegen.sc
M src/execution.cpp +143 -11
@@ 25,11 25,15 @@ 
 #include <llvm-c/BitWriter.h>
 #include <llvm-c/LLJIT.h>
 #include <llvm-c/OrcEE.h>
+#include <llvm-c/Disassembler.h>
 
 #include <llvm-c/Transforms/PassManagerBuilder.h>
 #include <llvm-c/Transforms/InstCombine.h>
 #include <llvm-c/Transforms/IPO.h>
 
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/Object/SymbolSize.h"
+
 #include <limits.h>
 
 #include <stdio.h>

          
@@ 40,6 44,7 @@ 
 #include <zlib.h>
 
 #define SCOPES_CACHE_KEY_BITCODE 1
+#define SCOPES_LLVM_SUPPORT_DISASSEMBLY 1
 
 #if SCOPES_MACOS
 #define SCOPES_JIT_SYMBOL_PREFIX '_'

          
@@ 51,6 56,125 @@ namespace scopes {
 
 ////////////////////////////////////////////////////////////////////////////////
 
+#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
+static void pprint(int pos, unsigned char *buf, int len, const char *disasm) {
+  int i;
+  printf("%04x:  ", pos);
+  for (i = 0; i < 8; i++) {
+    if (i < len) {
+      printf("%02x ", buf[i]);
+    } else {
+      printf("   ");
+    }
+  }
+
+  printf("   %s\n", disasm);
+}
+
+static void do_disassemble(LLVMTargetMachineRef tm, void *fptr, int siz) {
+
+    unsigned char *buf = (unsigned char *)fptr;
+
+  LLVMDisasmContextRef D = LLVMCreateDisasmCPUFeatures(
+    LLVMGetTargetMachineTriple(tm),
+    LLVMGetTargetMachineCPU(tm),
+    LLVMGetTargetMachineFeatureString(tm),
+    NULL, 0, NULL, NULL);
+    LLVMSetDisasmOptions(D,
+        LLVMDisassembler_Option_PrintImmHex);
+  char outline[1024];
+  int pos;
+
+  if (!D) {
+    printf("ERROR: Couldn't create disassembler\n");
+    return;
+  }
+
+  pos = 0;
+  while (pos < siz) {
+    size_t l = LLVMDisasmInstruction(D, buf + pos, siz - pos, 0, outline,
+                                     sizeof(outline));
+    if (!l) {
+      pprint(pos, buf + pos, 1, "\t???");
+      pos++;
+        break;
+    } else {
+      pprint(pos, buf + pos, l, outline);
+      pos += l;
+    }
+  }
+
+  LLVMDisasmDispose(D);
+}
+
+class DisassemblyListener : public llvm::JITEventListener {
+public:
+    bool enabled = false;
+
+    DisassemblyListener() {}
+
+    std::unordered_map<std::string, size_t> sizes;
+
+    void InitializeDebugData(
+        llvm::StringRef name,
+        llvm::object::SymbolRef::Type type, uint64_t sz) {
+        if(type == llvm::object::SymbolRef::ST_Function) {
+            sizes[name.data()] = sz;
+        }
+    }
+
+    virtual void notifyObjectLoaded(
+        ObjectKey K,
+        const llvm::object::ObjectFile &Obj,
+        const llvm::RuntimeDyld::LoadedObjectInfo &L) {
+        if (!enabled)
+            return;
+        #if 0
+        StyledStream ss;
+        ss << "object emitted!" << std::endl;
+        #endif
+        auto size_map = llvm::object::computeSymbolSizes(Obj);
+        for(auto & S : size_map) {
+            llvm::object::SymbolRef sym = S.first;
+            auto name = sym.getName();
+            auto type = sym.getType();
+            if(name && type)
+                InitializeDebugData(name.get(),type.get(),S.second);
+        }
+    }
+};
+#endif
+
+#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
+static DisassemblyListener *disassembly_listener = nullptr;
+#endif
+
+void enable_disassembly(bool enable) {
+#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
+    assert(disassembly_listener);
+    disassembly_listener->enabled = enable;
+#endif
+}
+
+void print_disassembly(std::string symbol, void *pfunc) {
+#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
+    assert(disassembly_listener);
+    //auto td = LLVMGetExecutionEngineTargetData(ee);
+    auto it = disassembly_listener->sizes.find(symbol);
+    if (it != disassembly_listener->sizes.end()) {
+        std::cout << "disassembly:\n";
+        auto target_machine = get_jit_target_machine();
+        do_disassemble(target_machine, pfunc, it->second);
+        return;
+    }
+    std::cout << "no disassembly available\n";
+#else
+    std::cout << "disassembly is unsupported\n";
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 void build_and_run_opt_passes(LLVMModuleRef module, int opt_level) {
     LLVMPassManagerBuilderRef passBuilder;
 

          
@@ 177,12 301,6 @@ LLVMTargetMachineRef get_object_target_m
     return object_target_machine;
 }
 
-void add_jit_event_listener(LLVMJITEventListenerRef listener) {
-    //LLVMOrcRegisterJITEventListener(orc, listener);
-    assert(object_layer);
-    LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(object_layer, listener);
-}
-
 #if 0
 uint64_t lazy_compile_callback(LLVMOrcJITStackRef orc, void *ctx) {
     printf("lazy_compile_callback ???\n");

          
@@ 215,6 333,24 @@ static LLVMErrorRef definition_generator
     return LLVMOrcJITDylibDefine(jit_dylib, mu);
 }
 
+static LLVMOrcObjectLayerRef llvm_create_object_layer(
+    void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple) {
+
+    object_layer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
+    LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(object_layer, LLVMCreateGDBRegistrationListener());
+
+#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
+    if (!disassembly_listener) {
+        disassembly_listener = new DisassemblyListener();
+        llvm::JITEventListener *le = disassembly_listener;
+        LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(object_layer,
+            llvm::wrap(le));
+    }
+#endif
+
+	return object_layer;
+}
+
 SCOPES_RESULT(void) init_execution() {
     SCOPES_RESULT_TYPE(void);
     if (orc) return {};

          
@@ 267,6 403,7 @@ SCOPES_RESULT(void) init_execution() {
     auto builder = LLVMOrcCreateLLJITBuilder();
     auto tmb = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(jtm);
     LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(builder, tmb);
+    LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(builder, llvm_create_object_layer, nullptr);
 
     auto err = LLVMOrcCreateLLJIT(&orc, builder);
     if (err) {

          
@@ 274,11 411,6 @@ SCOPES_RESULT(void) init_execution() {
     }
     assert(orc);
 
-    auto ES = LLVMOrcLLJITGetExecutionSession(orc);
-    assert(ES);
-    object_layer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
-    add_jit_event_listener(LLVMCreateGDBRegistrationListener());
-
     jit_dylib = LLVMOrcLLJITGetMainJITDylib(orc);
 
     LLVMOrcDefinitionGeneratorRef defgen = 0;

          
M src/execution.hpp +2 -1
@@ 36,9 36,10 @@ SCOPES_RESULT(uint64_t) get_address(cons
 void *local_aware_dlsym(Symbol name);
 LLVMTargetMachineRef get_jit_target_machine();
 LLVMTargetMachineRef get_object_target_machine();
-void add_jit_event_listener(LLVMJITEventListenerRef listener);
 SCOPES_RESULT(void) add_object(const char *path);
 void build_and_run_opt_passes(LLVMModuleRef module, int opt_level);
+void print_disassembly(std::string symbol, void *pfunc);
+void enable_disassembly(bool enable);
 
 void init_llvm();
 

          
M src/gen_llvm.cpp +5 -117
@@ 34,7 34,6 @@ 
 #include <llvm-c/Core.h>
 //#include <llvm-c/ExecutionEngine.h>
 #include <llvm-c/Analysis.h>
-#include <llvm-c/Disassembler.h>
 #include <llvm-c/Support.h>
 #include <llvm-c/DebugInfo.h>
 #include <llvm-c/BitWriter.h>

          
@@ 45,8 44,6 @@ 
 //#include "llvm/IR/DIBuilder.h"
 //#include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JITEventListener.h"
-#include "llvm/Object/SymbolSize.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 //#include "llvm/Support/Timer.h"
 //#include "llvm/Support/raw_os_ostream.h"

          
@@ 59,8 56,6 @@ namespace scopes {
 
 #define SCOPES_GEN_TARGET "IR"
 
-#define SCOPES_LLVM_SUPPORT_DISASSEMBLY 1
-
 #define SCOPES_LLVM_EXTENDED_DEBUG_INFO 0
 
 

          
@@ 3231,94 3226,6 @@ unsigned LLVMIRGenerator::attr_kind_byva
 // IL COMPILER
 //------------------------------------------------------------------------------
 
-#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
-static void pprint(int pos, unsigned char *buf, int len, const char *disasm) {
-  int i;
-  printf("%04x:  ", pos);
-  for (i = 0; i < 8; i++) {
-    if (i < len) {
-      printf("%02x ", buf[i]);
-    } else {
-      printf("   ");
-    }
-  }
-
-  printf("   %s\n", disasm);
-}
-
-static void do_disassemble(LLVMTargetMachineRef tm, void *fptr, int siz) {
-
-    unsigned char *buf = (unsigned char *)fptr;
-
-  LLVMDisasmContextRef D = LLVMCreateDisasmCPUFeatures(
-    LLVMGetTargetMachineTriple(tm),
-    LLVMGetTargetMachineCPU(tm),
-    LLVMGetTargetMachineFeatureString(tm),
-    NULL, 0, NULL, NULL);
-    LLVMSetDisasmOptions(D,
-        LLVMDisassembler_Option_PrintImmHex);
-  char outline[1024];
-  int pos;
-
-  if (!D) {
-    printf("ERROR: Couldn't create disassembler\n");
-    return;
-  }
-
-  pos = 0;
-  while (pos < siz) {
-    size_t l = LLVMDisasmInstruction(D, buf + pos, siz - pos, 0, outline,
-                                     sizeof(outline));
-    if (!l) {
-      pprint(pos, buf + pos, 1, "\t???");
-      pos++;
-        break;
-    } else {
-      pprint(pos, buf + pos, l, outline);
-      pos += l;
-    }
-  }
-
-  LLVMDisasmDispose(D);
-}
-
-class DisassemblyListener : public llvm::JITEventListener {
-public:
-    DisassemblyListener() {}
-
-    std::unordered_map<void *, size_t> sizes;
-
-    void InitializeDebugData(
-        llvm::StringRef name,
-        llvm::object::SymbolRef::Type type, uint64_t sz) {
-        if(type == llvm::object::SymbolRef::ST_Function) {
-            #if !defined(__arm__) && !defined(__linux__)
-            name = name.substr(1);
-            #endif
-            void * addr = (void *)get_address(name.data()).assert_ok();
-            if(addr) {
-                assert(addr);
-                sizes[addr] = sz;
-            }
-        }
-    }
-
-    virtual void NotifyObjectEmitted(
-        const llvm::object::ObjectFile &Obj,
-        const llvm::RuntimeDyld::LoadedObjectInfo &L) {
-        StyledStream ss;
-        ss << "object emitted!" << std::endl;
-        auto size_map = llvm::object::computeSymbolSizes(Obj);
-        for(auto & S : size_map) {
-            llvm::object::SymbolRef sym = S.first;
-            auto name = sym.getName();
-            auto type = sym.getType();
-            if(name && type)
-                InitializeDebugData(name.get(),type.get(),S.second);
-        }
-    }
-};
-#endif
 
 SCOPES_RESULT(void) compile_object(const String *triple,
     CompilerFileKind kind, const String *path, const Scope *scope, uint64_t flags) {

          
@@ 3396,10 3303,6 @@ SCOPES_RESULT(void) compile_object(const
     return {};
 }
 
-#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
-static DisassemblyListener *disassembly_listener = nullptr;
-#endif
-
 SCOPES_RESULT(ConstPointerRef) compile(const FunctionRef &fn, uint64_t flags) {
     SCOPES_RESULT_TYPE(ConstPointerRef);
     Timer sum_compile_time(TIMER_Compile);

          
@@ 3453,14 3356,6 @@ SCOPES_RESULT(ConstPointerRef) compile(c
 
     SCOPES_CHECK_RESULT(init_execution());
 
-#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
-    if (!disassembly_listener && (flags & CF_DumpDisassembly)) {
-        disassembly_listener = new DisassemblyListener();
-        llvm::JITEventListener *le = disassembly_listener;
-        add_jit_event_listener(reinterpret_cast<LLVMJITEventListenerRef>(le));
-    }
-#endif
-
     std::string funcname;
     {
         size_t length = 0;

          
@@ 3477,6 3372,10 @@ SCOPES_RESULT(ConstPointerRef) compile(c
     }
 #endif
 
+    if (flags & CF_DumpDisassembly) {
+        enable_disassembly(true);
+    }
+
     SCOPES_CHECK_RESULT(add_module(module, ctx.pointer_map, flags));
 
     if (flags & CF_DumpModule) {

          
@@ 3494,20 3393,9 @@ SCOPES_RESULT(ConstPointerRef) compile(c
 
     //LLVMDumpModule(module);
     void *pfunc = (void *)SCOPES_GET_RESULT(get_address(funcname.c_str()));
-#if SCOPES_LLVM_SUPPORT_DISASSEMBLY
     if (flags & CF_DumpDisassembly) {
-        assert(disassembly_listener);
-        //auto td = LLVMGetExecutionEngineTargetData(ee);
-        auto it = disassembly_listener->sizes.find(pfunc);
-        if (it != disassembly_listener->sizes.end()) {
-            std::cout << "disassembly:\n";
-            auto target_machine = get_jit_target_machine();
-            do_disassemble(target_machine, pfunc, it->second);
-        } else {
-            std::cout << "no disassembly available\n";
-        }
+        print_disassembly(funcname, pfunc);
     }
-#endif
 
     return ref(fn.anchor(), ConstPointer::from(functype, pfunc));
 }

          
M testing/test_codegen.sc +2 -1
@@ 4,6 4,7 @@ using import testing
 fn elidable (x)
     extractvalue (insertvalue x 1 0) 0
 
-compile (static-typify elidable (tuple i32 i32)) 'dump-function
+compile (static-typify elidable (tuple i32 i32)) 'dump-function 'dump-disassembly
+compile (static-typify elidable (tuple i32 i32)) 'dump-function 'dump-disassembly
 
 ;
  No newline at end of file