From d84a130ecc2a6f764eba271151b96ff3aa174c4f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 1 Aug 2017 15:54:53 -0700 Subject: [PATCH] generating x86 code works --- src/demo/demo.cpp | 17 +++++ src/llvm_wrapper/CMakeLists.txt | 2 +- src/llvm_wrapper/llvm_wrapper.cpp | 59 ++------------- src/llvm_wrapper/llvm_wrapper.h | 109 ++++++++++++++++++++++------ src/spirv_to_llvm/spirv_to_llvm.cpp | 45 ++++++++++-- src/spirv_to_llvm/spirv_to_llvm.h | 5 +- 6 files changed, 151 insertions(+), 86 deletions(-) diff --git a/src/demo/demo.cpp b/src/demo/demo.cpp index 2c7ee72..0e50f95 100644 --- a/src/demo/demo.cpp +++ b/src/demo/demo.cpp @@ -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(symbol); + }, + nullptr); + for(auto &entry_point : converted_module.entry_points) + { + auto function = reinterpret_cast( + 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 { diff --git a/src/llvm_wrapper/CMakeLists.txt b/src/llvm_wrapper/CMakeLists.txt index a5ea642..6889b41 100644 --- a/src/llvm_wrapper/CMakeLists.txt +++ b/src/llvm_wrapper/CMakeLists.txt @@ -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() diff --git a/src/llvm_wrapper/llvm_wrapper.cpp b/src/llvm_wrapper/llvm_wrapper.cpp index 881b5bd..d30fb51 100644 --- a/src/llvm_wrapper/llvm_wrapper.cpp +++ b/src/llvm_wrapper/llvm_wrapper.cpp @@ -23,7 +23,7 @@ #include "llvm_wrapper.h" #include #include -#include +#include #include #include #include @@ -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(); - std::unique_ptr> memory_manager_wrapper; - memory_manager_wrapper.reset(new std::shared_ptr(memory_manager)); - MCJIT_memory_manager mcjit_memory_manager(::LLVMCreateSimpleMCJITMemoryManager( - static_cast(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 *>(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 *>(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 *>(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 *>(user_data); - })); - memory_manager_wrapper.release(); - return Shared_memory_manager(std::move(mcjit_memory_manager), std::move(memory_manager)); -} } } diff --git a/src/llvm_wrapper/llvm_wrapper.h b/src/llvm_wrapper/llvm_wrapper.h index 745f1c3..f1fcb6c 100644 --- a/src/llvm_wrapper/llvm_wrapper.h +++ b/src/llvm_wrapper/llvm_wrapper.h @@ -26,13 +26,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include #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 shared_memory_manager; - explicit Shared_memory_manager(MCJIT_memory_manager mcjit_memory_manager, - std::shared_ptr 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 + static T *get_symbol(::LLVMOrcJITStackRef orc_jit_stack, const char *symbol_name) + { + return reinterpret_cast(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 + T *get_symbol(const char *symbol_name) + { + return get_symbol(get(), symbol_name); + } }; } } diff --git a/src/spirv_to_llvm/spirv_to_llvm.cpp b/src/spirv_to_llvm/spirv_to_llvm.cpp index 40dedfb..09f567d 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.cpp +++ b/src/spirv_to_llvm/spirv_to_llvm.cpp @@ -511,10 +511,14 @@ private: std::shared_ptr type; ::LLVMValueRef function; util::optional entry_block; + std::string output_function_name; explicit Function_state(std::shared_ptr 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_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(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; } } diff --git a/src/spirv_to_llvm/spirv_to_llvm.h b/src/spirv_to_llvm/spirv_to_llvm.h index 4888d7d..eda3fe2 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.h +++ b/src/spirv_to_llvm/spirv_to_llvm.h @@ -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)) { } }; -- 2.30.2