::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
{
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()
#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>
{
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()
::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));
-}
}
}
#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"
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);
+ }
};
}
}
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))
{
}
};
};
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;
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,
{
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),
+ 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;
}
}
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))
{
}
};