2016-06-22 13:37:51 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-11-29 23:11:28 +00:00
|
|
|
// Include asmjit with warnings ignored
|
2018-06-12 18:03:53 +00:00
|
|
|
#define ASMJIT_EMBED
|
2018-05-14 20:06:17 +00:00
|
|
|
#define ASMJIT_DEBUG
|
|
|
|
|
2019-11-29 23:11:28 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push, 0)
|
|
|
|
#include <asmjit/asmjit.h>
|
|
|
|
#pragma warning(pop)
|
|
|
|
#else
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wall"
|
|
|
|
#pragma GCC diagnostic ignored "-Wextra"
|
|
|
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
2018-06-12 18:03:53 +00:00
|
|
|
#include <asmjit/asmjit.h>
|
2019-11-29 23:11:28 +00:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
|
|
|
|
2018-05-16 23:38:14 +00:00
|
|
|
#include <array>
|
2018-05-14 20:06:17 +00:00
|
|
|
#include <functional>
|
|
|
|
|
2019-01-28 17:23:26 +00:00
|
|
|
enum class jit_class
|
|
|
|
{
|
|
|
|
ppu_code,
|
|
|
|
ppu_data,
|
|
|
|
spu_code,
|
|
|
|
spu_data,
|
|
|
|
};
|
|
|
|
|
2019-01-26 20:15:45 +00:00
|
|
|
// ASMJIT runtime for emitting code in a single 2G region
|
|
|
|
struct jit_runtime final : asmjit::HostRuntime
|
|
|
|
{
|
|
|
|
jit_runtime();
|
|
|
|
~jit_runtime() override;
|
|
|
|
|
|
|
|
// Allocate executable memory
|
|
|
|
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override;
|
|
|
|
|
|
|
|
// Do nothing (deallocation is delayed)
|
|
|
|
asmjit::Error _release(void* p) noexcept override;
|
|
|
|
|
|
|
|
// Allocate memory
|
|
|
|
static u8* alloc(std::size_t size, uint align, bool exec = true) noexcept;
|
|
|
|
|
|
|
|
// Should be called at least once after global initialization
|
|
|
|
static void initialize();
|
|
|
|
|
|
|
|
// Deallocate all memory
|
|
|
|
static void finalize() noexcept;
|
|
|
|
};
|
|
|
|
|
2018-05-14 20:06:17 +00:00
|
|
|
namespace asmjit
|
|
|
|
{
|
|
|
|
// Should only be used to build global functions
|
2019-03-18 20:01:16 +00:00
|
|
|
asmjit::JitRuntime& get_global_runtime();
|
2018-05-14 20:06:17 +00:00
|
|
|
|
2018-05-18 15:51:48 +00:00
|
|
|
// Emit xbegin and adjacent loop, return label at xbegin
|
2019-06-06 18:32:35 +00:00
|
|
|
void build_transaction_enter(X86Assembler& c, Label fallback, const X86Gp& ctr, uint less_than);
|
2018-05-14 20:06:17 +00:00
|
|
|
|
2018-05-14 20:07:36 +00:00
|
|
|
// Emit xabort
|
2018-05-14 20:06:17 +00:00
|
|
|
void build_transaction_abort(X86Assembler& c, unsigned char code);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build runtime function with asmjit::X86Assembler
|
|
|
|
template <typename FT, typename F>
|
|
|
|
FT build_function_asm(F&& builder)
|
|
|
|
{
|
|
|
|
using namespace asmjit;
|
|
|
|
|
|
|
|
auto& rt = get_global_runtime();
|
|
|
|
|
|
|
|
CodeHolder code;
|
|
|
|
code.init(rt.getCodeInfo());
|
|
|
|
code._globalHints = asmjit::CodeEmitter::kHintOptimizedAlign;
|
|
|
|
|
|
|
|
std::array<X86Gp, 4> args;
|
|
|
|
#ifdef _WIN32
|
|
|
|
args[0] = x86::rcx;
|
|
|
|
args[1] = x86::rdx;
|
|
|
|
args[2] = x86::r8;
|
|
|
|
args[3] = x86::r9;
|
|
|
|
#else
|
|
|
|
args[0] = x86::rdi;
|
|
|
|
args[1] = x86::rsi;
|
|
|
|
args[2] = x86::rdx;
|
|
|
|
args[3] = x86::rcx;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
X86Assembler compiler(&code);
|
|
|
|
builder(std::ref(compiler), args);
|
|
|
|
|
|
|
|
FT result;
|
|
|
|
|
|
|
|
if (rt.add(&result, &code))
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-06-22 13:37:51 +00:00
|
|
|
#ifdef LLVM_AVAILABLE
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
2019-01-21 18:04:32 +00:00
|
|
|
#include <string_view>
|
2016-06-22 13:37:51 +00:00
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include "types.h"
|
2017-06-24 15:36:49 +00:00
|
|
|
#include "mutex.h"
|
2016-06-22 13:37:51 +00:00
|
|
|
|
2017-01-28 12:32:45 +00:00
|
|
|
#include "restore_new.h"
|
2016-06-22 13:37:51 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push, 0)
|
2019-11-29 23:11:28 +00:00
|
|
|
#else
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wall"
|
|
|
|
#pragma GCC diagnostic ignored "-Wextra"
|
|
|
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
2016-06-22 13:37:51 +00:00
|
|
|
#endif
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(pop)
|
2019-11-29 23:11:28 +00:00
|
|
|
#else
|
|
|
|
#pragma GCC diagnostic pop
|
2016-06-22 13:37:51 +00:00
|
|
|
#endif
|
2017-01-28 12:32:45 +00:00
|
|
|
#include "define_new_memleakdetect.h"
|
2016-06-22 13:37:51 +00:00
|
|
|
|
|
|
|
// Temporary compiler interface
|
|
|
|
class jit_compiler final
|
|
|
|
{
|
2017-06-24 15:36:49 +00:00
|
|
|
// Local LLVM context
|
|
|
|
llvm::LLVMContext m_context;
|
|
|
|
|
|
|
|
// JIT Event Listener
|
|
|
|
std::unique_ptr<struct EventListener> m_jit_el;
|
|
|
|
|
2016-06-22 13:37:51 +00:00
|
|
|
// Execution instance
|
|
|
|
std::unique_ptr<llvm::ExecutionEngine> m_engine;
|
|
|
|
|
2017-06-24 15:36:49 +00:00
|
|
|
// Link table
|
2017-06-22 21:52:09 +00:00
|
|
|
std::unordered_map<std::string, u64> m_link;
|
|
|
|
|
2017-02-26 15:56:31 +00:00
|
|
|
// Arch
|
|
|
|
std::string m_cpu;
|
|
|
|
|
2016-06-22 13:37:51 +00:00
|
|
|
public:
|
2019-03-18 16:24:55 +00:00
|
|
|
jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags = 0);
|
2016-06-22 13:37:51 +00:00
|
|
|
~jit_compiler();
|
|
|
|
|
2017-06-24 15:36:49 +00:00
|
|
|
// Get LLVM context
|
|
|
|
auto& get_context()
|
|
|
|
{
|
|
|
|
return m_context;
|
|
|
|
}
|
|
|
|
|
2018-05-01 10:20:36 +00:00
|
|
|
auto& get_engine() const
|
|
|
|
{
|
|
|
|
return *m_engine;
|
|
|
|
}
|
|
|
|
|
2017-07-15 09:20:40 +00:00
|
|
|
// Add module (path to obj cache dir)
|
2020-05-06 15:18:30 +00:00
|
|
|
void add(std::unique_ptr<llvm::Module> _module, const std::string& path);
|
2017-06-22 21:52:09 +00:00
|
|
|
|
2018-05-01 10:20:36 +00:00
|
|
|
// Add module (not cached)
|
2020-05-06 15:18:30 +00:00
|
|
|
void add(std::unique_ptr<llvm::Module> _module);
|
2018-05-01 10:20:36 +00:00
|
|
|
|
2017-07-15 09:20:40 +00:00
|
|
|
// Add object (path to obj file)
|
|
|
|
void add(const std::string& path);
|
|
|
|
|
2020-04-07 13:09:47 +00:00
|
|
|
// Check object file
|
|
|
|
static bool check(const std::string& path);
|
|
|
|
|
2017-06-22 21:52:09 +00:00
|
|
|
// Finalize
|
2017-06-24 15:36:49 +00:00
|
|
|
void fin();
|
2017-02-26 15:56:31 +00:00
|
|
|
|
2016-06-22 13:37:51 +00:00
|
|
|
// Get compiled function address
|
2017-06-24 15:36:49 +00:00
|
|
|
u64 get(const std::string& name);
|
|
|
|
|
2017-02-26 15:56:31 +00:00
|
|
|
// Get CPU info
|
2018-03-17 17:41:35 +00:00
|
|
|
static std::string cpu(const std::string& _cpu);
|
2017-06-29 14:25:39 +00:00
|
|
|
|
|
|
|
// Check JIT purpose
|
|
|
|
bool is_primary() const
|
|
|
|
{
|
|
|
|
return !m_link.empty();
|
|
|
|
}
|
2016-06-22 13:37:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|