JIT hackery. Not quite working.

This commit is contained in:
Ben Vanik
2014-01-25 20:30:18 -08:00
parent a84ce633c9
commit 4609339c5a
16 changed files with 1585 additions and 379 deletions

View File

@@ -12,9 +12,12 @@
#include <alloy/core.h>
#include <alloy/hir/value.h>
#include <third_party/xbyak/xbyak/xbyak.h>
XEDECLARECLASS2(alloy, hir, HIRBuilder);
XEDECLARECLASS2(alloy, hir, Instr);
namespace alloy {
namespace backend {
@@ -23,6 +26,11 @@ namespace x64 {
class X64Backend;
class X64CodeCache;
enum RegisterFlags {
REG_DEST = (1 << 0),
REG_ABCD = (1 << 1),
};
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
class XbyakAllocator : public Xbyak::Allocator {
public:
@@ -39,6 +47,91 @@ public:
int Emit(hir::HIRBuilder* builder,
void*& out_code_address, size_t& out_code_size);
public:
template<typename V0>
void BeginOp(hir::Value* v0, V0& r0, uint32_t r0_flags) {
uint32_t v0_idx;
FindFreeRegs(v0, v0_idx, r0_flags);
SetupReg(v0_idx, r0);
}
template<typename V0, typename V1>
void BeginOp(hir::Value* v0, V0& r0, uint32_t r0_flags,
hir::Value* v1, V1& r1, uint32_t r1_flags) {
uint32_t v0_idx, v1_idx;
FindFreeRegs(v0, v0_idx, r0_flags,
v1, v1_idx, r1_flags);
SetupReg(v0_idx, r0);
SetupReg(v1_idx, r1);
}
template<typename V0, typename V1, typename V2>
void BeginOp(hir::Value* v0, V0& r0, uint32_t r0_flags,
hir::Value* v1, V1& r1, uint32_t r1_flags,
hir::Value* v2, V2& r2, uint32_t r2_flags) {
uint32_t v0_idx, v1_idx, v2_idx;
FindFreeRegs(v0, v0_idx, r0_flags,
v1, v1_idx, r1_flags,
v2, v2_idx, r2_flags);
SetupReg(v0_idx, r0);
SetupReg(v1_idx, r1);
SetupReg(v2_idx, r2);
}
template<typename V0, typename V1, typename V2, typename V3>
void BeginOp(hir::Value* v0, V0& r0, uint32_t r0_flags,
hir::Value* v1, V1& r1, uint32_t r1_flags,
hir::Value* v2, V2& r2, uint32_t r2_flags,
hir::Value* v3, V3& r3, uint32_t r3_flags) {
uint32_t v0_idx, v1_idx, v2_idx, v3_idx;
FindFreeRegs(v0, v0_idx, r0_flags,
v1, v1_idx, r1_flags,
v2, v2_idx, r2_flags,
v3, v3_idx, r3_flags);
SetupReg(v0_idx, r0);
SetupReg(v1_idx, r1);
SetupReg(v2_idx, r2);
SetupReg(v3_idx, r3);
}
template<typename V0>
void EndOp(V0& r0) {
reg_state_.active_regs = reg_state_.active_regs ^ GetRegBit(r0);
}
template<typename V0, typename V1>
void EndOp(V0& r0, V1& r1) {
reg_state_.active_regs = reg_state_.active_regs ^ (
GetRegBit(r0) | GetRegBit(r1));
}
template<typename V0, typename V1, typename V2>
void EndOp(V0& r0, V1& r1, V2& r2) {
reg_state_.active_regs = reg_state_.active_regs ^ (
GetRegBit(r0) | GetRegBit(r1) | GetRegBit(r2));
}
template<typename V0, typename V1, typename V2, typename V3>
void EndOp(V0& r0, V1& r1, V2& r2, V3& r3) {
reg_state_.active_regs = reg_state_.active_regs ^ (
GetRegBit(r0) | GetRegBit(r1) | GetRegBit(r2) | GetRegBit(r3));
}
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags);
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags,
hir::Value* v1, uint32_t& v1_idx, uint32_t v1_flags);
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags,
hir::Value* v1, uint32_t& v1_idx, uint32_t v1_flags,
hir::Value* v2, uint32_t& v2_idx, uint32_t v2_flags);
void FindFreeRegs(hir::Value* v0, uint32_t& v0_idx, uint32_t v0_flags,
hir::Value* v1, uint32_t& v1_idx, uint32_t v1_flags,
hir::Value* v2, uint32_t& v2_idx, uint32_t v2_flags,
hir::Value* v3, uint32_t& v3_idx, uint32_t v3_flags);
static void SetupReg(uint32_t idx, Xbyak::Reg8& r) { r = Xbyak::Reg8(idx); }
static void SetupReg(uint32_t idx, Xbyak::Reg16& r) { r = Xbyak::Reg16(idx); }
static void SetupReg(uint32_t idx, Xbyak::Reg32& r) { r = Xbyak::Reg32(idx); }
static void SetupReg(uint32_t idx, Xbyak::Reg64& r) { r = Xbyak::Reg64(idx); }
static void SetupReg(uint32_t idx, Xbyak::Xmm& r) { r = Xbyak::Xmm(idx - 16); }
static uint32_t GetRegBit(const Xbyak::Reg8& r) { return 1 << r.getIdx(); }
static uint32_t GetRegBit(const Xbyak::Reg16& r) { return 1 << r.getIdx(); }
static uint32_t GetRegBit(const Xbyak::Reg32& r) { return 1 << r.getIdx(); }
static uint32_t GetRegBit(const Xbyak::Reg64& r) { return 1 << r.getIdx(); }
static uint32_t GetRegBit(const Xbyak::Xmm& r) { return 1 << (16 + r.getIdx()); }
private:
void* Emplace(X64CodeCache* code_cache);
int Emit(hir::HIRBuilder* builder);
@@ -47,6 +140,16 @@ private:
X64Backend* backend_;
X64CodeCache* code_cache_;
XbyakAllocator* allocator_;
struct {
// Registers currently active within a begin/end op block. These
// cannot be reused.
uint32_t active_regs;
// Registers with values in them.
uint32_t live_regs;
// Current register values.
hir::Value* reg_values[32];
} reg_state_;
};