generating x86 code works
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 1 Aug 2017 22:54:53 +0000 (15:54 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 1 Aug 2017 22:54:53 +0000 (15:54 -0700)
src/demo/demo.cpp
src/llvm_wrapper/CMakeLists.txt
src/llvm_wrapper/llvm_wrapper.cpp
src/llvm_wrapper/llvm_wrapper.h
src/spirv_to_llvm/spirv_to_llvm.cpp
src/spirv_to_llvm/spirv_to_llvm.h

index 2c7ee72b9f05ac2b0893e7164e9e5c502fd6b34a..0e50f9526c9f1097819fa660b2677a5b6755460c 100644 (file)
@@ -258,6 +258,23 @@ int test_main(int argc, char **argv)
             ::LLVMVerifyModule(converted_module.module.get(), ::LLVMPrintMessageAction, nullptr);
         if(failed)
             return 1;
+        auto orc_jit_stack = llvm_wrapper::Orc_jit_stack::create(std::move(llvm_target_machine));
+        orc_jit_stack.add_eagerly_compiled_ir(
+            std::move(converted_module.module),
+            [](const char *symbol_name, [[gnu::unused]] void *user_data) noexcept->std::uint64_t
+            {
+                std::cerr << "resolving symbol: " << symbol_name << std::endl;
+                void *symbol = nullptr;
+                return reinterpret_cast<std::uintptr_t>(symbol);
+            },
+            nullptr);
+        for(auto &entry_point : converted_module.entry_points)
+        {
+            auto function = reinterpret_cast<void *>(
+                orc_jit_stack.get_symbol_address(entry_point.entry_function_name.c_str()));
+            std::cerr << "entry point \"" << entry_point.name << "\": &"
+                      << entry_point.entry_function_name << " == " << function << std::endl;
+        }
     }
     else
     {
index a5ea6421404cfcfd10edd70ce2513158f9403d68..6889b4147b1ced3346f1ee7b2940702d3889e783 100644 (file)
@@ -23,7 +23,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
 set(sources llvm_wrapper.cpp)
 add_library(llvm_wrapper STATIC ${sources})
 if(1)
-llvm_map_components_to_libnames(llvm_libraries core mcjit native analysis)
+llvm_map_components_to_libnames(llvm_libraries core native analysis orcjit mcjit nativecodegen)
 else()
 set(llvm_libraries LLVM)
 endif()
index 881b5bdc9b3e0d84cb2a3ee3ac1c10bc8429de0f..d30fb513b6e8e5f4dcab0da9f53b9a786adbfa23 100644 (file)
@@ -23,7 +23,7 @@
 #include "llvm_wrapper.h"
 #include <llvm/Support/Host.h>
 #include <llvm/ExecutionEngine/SectionMemoryManager.h>
-#include <stdexcept>
+#include <llvm-c/ExecutionEngine.h>
 #include <iostream>
 #include <cstdlib>
 #include <algorithm>
@@ -36,9 +36,14 @@ void Context::init_helper()
 {
     if(!::LLVMIsMultithreaded())
         throw std::runtime_error("LLVM is not multithreaded");
-    ::LLVMLinkInMCJIT();
     if(::LLVMInitializeNativeTarget() != 0)
         throw std::runtime_error("LLVMInitializeNativeTarget failed");
+    if(::LLVMInitializeNativeAsmParser() != 0)
+        throw std::runtime_error("LLVMInitializeNativeAsmParser failed");
+    if(::LLVMInitializeNativeAsmPrinter() != 0)
+        throw std::runtime_error("LLVMInitializeNativeAsmPrinter failed");
+    if(::LLVMInitializeNativeDisassembler() != 0)
+        throw std::runtime_error("LLVMInitializeNativeDisassembler failed");
 }
 
 LLVM_string Target::get_process_target_triple()
@@ -108,55 +113,5 @@ void Module::set_function_target_machine(::LLVMValueRef function,
     ::LLVMAddTargetDependentFunctionAttr(
         function, "target-features", Target_machine::get_feature_string(target_machine).get());
 }
-
-Shared_memory_manager Shared_memory_manager::create()
-{
-    Context::init();
-    auto memory_manager = std::make_shared<llvm::SectionMemoryManager>();
-    std::unique_ptr<std::shared_ptr<llvm::SectionMemoryManager>> memory_manager_wrapper;
-    memory_manager_wrapper.reset(new std::shared_ptr<llvm::SectionMemoryManager>(memory_manager));
-    MCJIT_memory_manager mcjit_memory_manager(::LLVMCreateSimpleMCJITMemoryManager(
-        static_cast<void *>(memory_manager_wrapper.get()),
-        [](void *user_data,
-           std::uintptr_t size,
-           unsigned alignment,
-           unsigned section_id,
-           const char *section_name) -> std::uint8_t *
-        {
-            auto &memory_manager =
-                *static_cast<std::shared_ptr<llvm::SectionMemoryManager> *>(user_data);
-            return memory_manager->allocateCodeSection(size, alignment, section_id, section_name);
-        },
-        [](void *user_data,
-           std::uintptr_t size,
-           unsigned alignment,
-           unsigned section_id,
-           const char *section_name,
-           LLVMBool is_read_only) -> std::uint8_t *
-        {
-            auto &memory_manager =
-                *static_cast<std::shared_ptr<llvm::SectionMemoryManager> *>(user_data);
-            return memory_manager->allocateDataSection(
-                size, alignment, section_id, section_name, is_read_only);
-        },
-        [](void *user_data, char **error_message_out) -> LLVMBool
-        {
-            auto &memory_manager =
-                *static_cast<std::shared_ptr<llvm::SectionMemoryManager> *>(user_data);
-            if(!error_message_out)
-                return memory_manager->finalizeMemory(nullptr);
-            std::string error_message;
-            bool failed = memory_manager->finalizeMemory(&error_message);
-            if(failed)
-                *error_message_out = LLVM_string::from(error_message).release();
-            return failed;
-        },
-        [](void *user_data) noexcept
-        {
-            delete static_cast<std::shared_ptr<llvm::SectionMemoryManager> *>(user_data);
-        }));
-    memory_manager_wrapper.release();
-    return Shared_memory_manager(std::move(mcjit_memory_manager), std::move(memory_manager));
-}
 }
 }
index 745f1c39c1e7cb512b3dfd8d1e663508aafdfd7f..f1fcb6cc4dc0670fed84a7f2b99c1adb2336e5db 100644 (file)
 #include <llvm-c/Core.h>
 #include <llvm-c/Target.h>
 #include <llvm-c/TargetMachine.h>
-#include <llvm-c/ExecutionEngine.h>
+#include <llvm-c/OrcBindings.h>
 #include <llvm-c/Analysis.h>
 #include <memory>
 #include <type_traits>
 #include <utility>
 #include <string>
 #include <cassert>
+#include <stdexcept>
 #include "util/string_view.h"
 #include "util/variant.h"
 
@@ -357,47 +358,107 @@ inline ::LLVMTypeRef get_scalar_or_vector_element_type(::LLVMTypeRef type)
     return type;
 }
 
-struct MCJIT_memory_manager_deleter
+// TODO: add CMake tests to determine which Orc version we need
+#if 0
+// added error code return from LLVMOrcAddEagerlyCompiledIR
+#define LLVM_WRAPPER_ORC_REVISION_NUMBER 307350
+#elif 0
+// added shared modules
+#define LLVM_WRAPPER_ORC_REVISION_NUMBER 306182
+#else
+// initial revision
+#define LLVM_WRAPPER_ORC_REVISION_NUMBER 251482
+#endif
+
+#if LLVM_WRAPPER_ORC_REVISION_NUMBER >= 306166
+struct Orc_shared_module_ref_deleter
 {
-    void operator()(::LLVMMCJITMemoryManagerRef v) noexcept
+    void operator()(::LLVMSharedModuleRef v) noexcept
     {
-        ::LLVMDisposeMCJITMemoryManager(v);
+        ::LLVMOrcDisposeSharedModuleRef(v);
     }
 };
 
-struct MCJIT_memory_manager
-    : public Wrapper<::LLVMMCJITMemoryManagerRef, MCJIT_memory_manager_deleter>
+struct Orc_shared_module_ref : public Wrapper<::LLVMSharedModuleRef, Orc_shared_module_ref_deleter>
 {
     using Wrapper::Wrapper;
-};
-
-struct Shared_memory_manager
-{
-    MCJIT_memory_manager mcjit_memory_manager;
-    std::shared_ptr<void> shared_memory_manager;
-    explicit Shared_memory_manager(MCJIT_memory_manager mcjit_memory_manager,
-                                   std::shared_ptr<void> shared_memory_manager) noexcept
-        : mcjit_memory_manager(std::move(mcjit_memory_manager)),
-          shared_memory_manager(std::move(shared_memory_manager))
+    static Orc_shared_module_ref make(Module module)
     {
+        return Orc_shared_module_ref(::LLVMOrcMakeSharedModule(module.release()));
     }
-    Shared_memory_manager() noexcept
-    {
-    }
-    static Shared_memory_manager create();
 };
+#endif
 
-struct Execution_engine_deleter
+struct Orc_jit_stack_deleter
 {
-    void operator()(::LLVMExecutionEngineRef v) noexcept
+    void operator()(::LLVMOrcJITStackRef v) noexcept
     {
-        ::LLVMDisposeExecutionEngine(v);
+        ::LLVMOrcDisposeInstance(v);
     }
 };
 
-struct Execution_engine : public Wrapper<::LLVMExecutionEngineRef, Execution_engine_deleter>
+struct Orc_jit_stack : public Wrapper<::LLVMOrcJITStackRef, Orc_jit_stack_deleter>
 {
     using Wrapper::Wrapper;
+    static Orc_jit_stack create(Target_machine target_machine)
+    {
+        return Orc_jit_stack(::LLVMOrcCreateInstance(target_machine.release()));
+    }
+    static ::LLVMOrcModuleHandle add_eagerly_compiled_ir(
+        ::LLVMOrcJITStackRef orc_jit_stack,
+        Module module,
+        ::LLVMOrcSymbolResolverFn symbol_resolver_callback,
+        void *symbol_resolver_user_data)
+    {
+        ::LLVMOrcModuleHandle retval{};
+#if LLVM_WRAPPER_ORC_REVISION_NUMBER >= 307350
+        if(::LLVMOrcErrorSuccess
+           != ::LLVMOrcAddEagerlyCompiledIR(orc_jit_stack,
+                                            &retval,
+                                            Orc_shared_module_ref::make(std::move(module)).get(),
+                                            symbol_resolver_callback,
+                                            symbol_resolver_user_data))
+            throw std::runtime_error(std::string("LLVM Orc Error: ")
+                                     + ::LLVMOrcGetErrorMsg(orc_jit_stack));
+#elif LLVM_WRAPPER_ORC_REVISION_NUMBER >= 306182
+        retval = ::LLVMOrcAddEagerlyCompiledIR(orc_jit_stack,
+                                               Orc_shared_module_ref::make(std::move(module)).get(),
+                                               symbol_resolver_callback,
+                                               symbol_resolver_user_data);
+#elif LLVM_WRAPPER_ORC_REVISION_NUMBER >= 251482
+        retval = ::LLVMOrcAddEagerlyCompiledIR(
+            orc_jit_stack, module.release(), symbol_resolver_callback, symbol_resolver_user_data);
+#else
+#error unsupported LLVM_WRAPPER_ORC_REVISION_NUMBER
+#endif
+        return retval;
+    }
+    ::LLVMOrcModuleHandle add_eagerly_compiled_ir(
+        Module module,
+        ::LLVMOrcSymbolResolverFn symbol_resolver_callback,
+        void *symbol_resolver_user_data)
+    {
+        return add_eagerly_compiled_ir(
+            get(), std::move(module), symbol_resolver_callback, symbol_resolver_user_data);
+    }
+    static std::uintptr_t get_symbol_address(::LLVMOrcJITStackRef orc_jit_stack, const char *symbol_name)
+    {
+        return ::LLVMOrcGetSymbolAddress(orc_jit_stack, symbol_name);
+    }
+    template <typename T>
+    static T *get_symbol(::LLVMOrcJITStackRef orc_jit_stack, const char *symbol_name)
+    {
+        return reinterpret_cast<T *>(get_symbol_address(orc_jit_stack, symbol_name));
+    }
+    std::uintptr_t get_symbol_address(const char *symbol_name)
+    {
+        return get_symbol_address(get(), symbol_name);
+    }
+    template <typename T>
+    T *get_symbol(const char *symbol_name)
+    {
+        return get_symbol<T>(get(), symbol_name);
+    }
 };
 }
 }
index 40dedfb386da4be89e68d67e004984b4d581b537..09f567d5869e4b550caf68e712697180664f314f 100644 (file)
@@ -511,10 +511,14 @@ private:
         std::shared_ptr<Function_type_descriptor> type;
         ::LLVMValueRef function;
         util::optional<Entry_block> entry_block;
+        std::string output_function_name;
         explicit Function_state(std::shared_ptr<Function_type_descriptor> type,
-                                ::LLVMValueRef function) noexcept : type(std::move(type)),
-                                                                    function(function),
-                                                                    entry_block()
+                                ::LLVMValueRef function,
+                                std::string output_function_name) noexcept
+            : type(std::move(type)),
+              function(function),
+              entry_block(),
+              output_function_name(std::move(output_function_name))
         {
         }
     };
@@ -607,6 +611,7 @@ private:
     };
 
 private:
+    std::uint64_t next_name_index = 0;
     std::vector<Id_state> id_states;
     unsigned input_version_number_major = 0;
     unsigned input_version_number_minor = 0;
@@ -670,9 +675,28 @@ private:
     std::string get_prefixed_name(std::string name) const
     {
         if(!name.empty())
+        {
+            std::size_t first_non_underline = name.find_first_not_of('_');
+            if(first_non_underline != std::string::npos && name[first_non_underline] >= '0'
+               && name[first_non_underline] <= '9')
+            {
+                // ensure name doesn't conflict with names generated by get_or_make_prefixed_name
+                name.insert(0, "_");
+            }
             return name_prefix_string + std::move(name);
+        }
         return name;
     }
+    std::string get_or_make_prefixed_name(std::string name)
+    {
+        if(name.empty())
+        {
+            std::ostringstream ss;
+            ss << name_prefix_string << next_name_index++;
+            return ss.str();
+        }
+        return get_prefixed_name(std::move(name));
+    }
 
 public:
     explicit Spirv_to_llvm(::LLVMContextRef context,
@@ -733,8 +757,13 @@ public:
         {
             for(auto &entry_point : id_state.op_entry_points)
             {
+                if(!id_state.function)
+                    throw Parser_error(entry_point.instruction_start_index,
+                                       entry_point.instruction_start_index,
+                                       "No definition for function referenced in OpEntryPoint");
                 entry_points.push_back(
-                    Converted_module::Entry_point(std::string(entry_point.entry_point.name)));
+                    Converted_module::Entry_point(std::string(entry_point.entry_point.name),
+                                                  id_state.function->output_function_name));
             }
         }
         Converted_module retval(std::move(module),
@@ -2710,11 +2739,11 @@ void Spirv_to_llvm::handle_instruction_op_function(Op_function instruction,
                                    + std::string(get_enumerant_name(instruction.get_operation())));
         auto function_type =
             get_type<Function_type_descriptor>(instruction.function_type, instruction_start_index);
-        auto function = ::LLVMAddFunction(module.get(),
-                                          get_prefixed_name(get_name(current_function_id)).c_str(),
-                                          function_type->get_or_make_type());
+        auto function_name = get_or_make_prefixed_name(get_name(current_function_id));
+        auto function = ::LLVMAddFunction(
+            module.get(), function_name.c_str(), function_type->get_or_make_type());
         llvm_wrapper::Module::set_function_target_machine(function, target_machine);
-        state.function = Function_state(function_type, function);
+        state.function = Function_state(function_type, function, std::move(function_name));
         break;
     }
     }
index 4888d7d599426ac5ecbccf93935c1d0912a9d0f6..eda3fe2a21038a1d21a71a19852d083b27b1252a 100644 (file)
@@ -475,8 +475,11 @@ struct Converted_module
     struct Entry_point
     {
         std::string name;
+        std::string entry_function_name;
 #warning finish filling in Entry_point
-        explicit Entry_point(std::string name) noexcept : name(std::move(name))
+        explicit Entry_point(std::string name, std::string entry_function_name) noexcept
+            : name(std::move(name)),
+              entry_function_name(std::move(entry_function_name))
         {
         }
     };