better representation (inspired by fleroviux's Lunatic)
This commit is contained in:
42
src/backend/core/JIT/IR/Opcode.hpp
Normal file
42
src/backend/core/JIT/IR/Opcode.hpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <log.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
enum class IROpcodeClass {
|
||||||
|
Normal, Special, Regimm, COP0, COP1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IROpcode {
|
||||||
|
virtual ~IROpcode() = default;
|
||||||
|
virtual auto GetClass() const -> IROpcodeClass = 0;
|
||||||
|
virtual auto Reads (IRVariable const& var) -> bool = 0;
|
||||||
|
virtual auto Writes(IRVariable const& var) -> bool = 0;
|
||||||
|
virtual void Repoint(IRVariable const& var_old, IRVariable const& var_new) = 0;
|
||||||
|
virtual void PropagateConstant(IRVariable const& var, IRConstant const& constant) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<IROpcodeClass _class>
|
||||||
|
struct IROpcodeBase : IROpcode {
|
||||||
|
auto GetClass() const -> IROpcodeClass override { return _class; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IRNoOp final : IROpcodeBase<IROpcodeClass::NOP> {
|
||||||
|
auto Reads(IRVariable const& var) -> bool override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Writes(IRVariable const& var) -> bool override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repoint(
|
||||||
|
IRVariable const& var_old,
|
||||||
|
IRVariable const& var_new
|
||||||
|
) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ToString() -> std::string override {
|
||||||
|
return "nop";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
11
src/backend/core/JIT/IR/Register.hpp
Normal file
11
src/backend/core/JIT/IR/Register.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <log.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
struct IRGuestReg {
|
||||||
|
IRGuestReg(u8 reg) : reg(reg) {}
|
||||||
|
|
||||||
|
/// The ARM general purpose register
|
||||||
|
const u8 reg;
|
||||||
|
};
|
||||||
|
}
|
||||||
98
src/backend/core/JIT/IR/Value.hpp
Normal file
98
src/backend/core/JIT/IR/Value.hpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <log.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
enum IRPrimitive {
|
||||||
|
Uint32, Sint32, Uint64, Sint32, Uint128, Sint128
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IRVariable {
|
||||||
|
IRVariable(IRPrimitive type, const u32 id, char const* const label) : type(type), id(id), label(label) {}
|
||||||
|
private:
|
||||||
|
IRPrimitive type;
|
||||||
|
const u32 id;
|
||||||
|
char const* const label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IRConstant {
|
||||||
|
IRConstant() {}
|
||||||
|
IRConstant(IRPrimitive type, u128 value) : type(type), value(value) {}
|
||||||
|
private:
|
||||||
|
IRPrimitive type = Uint128;
|
||||||
|
u128 value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IRAnyRef {
|
||||||
|
IRAnyRef() {}
|
||||||
|
IRAnyRef(IRVariable const& variable) : type(Type::Variable), var(&variable) {}
|
||||||
|
IRAnyRef(IRConstant const& constant) : type(Type::Constant), constant(constant) {}
|
||||||
|
|
||||||
|
auto operator=(IRAnyRef const& other) -> IRAnyRef& {
|
||||||
|
type = other.type;
|
||||||
|
if (IsConstant()) {
|
||||||
|
constant = other.constant;
|
||||||
|
} else {
|
||||||
|
var = other.var;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNull() const { return type == Type::Null; }
|
||||||
|
bool IsVariable() const { return type == Type::Variable; }
|
||||||
|
bool IsConstant() const { return type == Type::Constant; }
|
||||||
|
|
||||||
|
auto GetVar() const -> IRVariable const& {
|
||||||
|
if (!IsVariable()) {
|
||||||
|
Util::panic("called GetVar() but value is a constant or null");
|
||||||
|
}
|
||||||
|
return *var;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetConst() const -> IRConstant const& {
|
||||||
|
if (!IsConstant()) {
|
||||||
|
Util::panic("called GetConst() but value is a variable or null");
|
||||||
|
}
|
||||||
|
return constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repoint(IRVariable const& var_old, IRVariable const& var_new) {
|
||||||
|
if (IsVariable() && (&GetVar() == &var_old)) {
|
||||||
|
var = &var_new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropagateConstant(IRVariable const& var, IRConstant const& constant) {
|
||||||
|
if (IsVariable() && (&GetVar() == &var)) {
|
||||||
|
type = Type::Constant;
|
||||||
|
this->constant = constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
enum Type {
|
||||||
|
Null, Variable, Constant
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
IRVariable const* var;
|
||||||
|
IRConstant constant;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IRVarRef {
|
||||||
|
IRVarRef(IRVariable const& var) : p_var(&var) {}
|
||||||
|
|
||||||
|
auto Get() const -> IRVariable const& {
|
||||||
|
return *p_var;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repoint(IRVariable const& var_old, IRVariable const& var_new) {
|
||||||
|
if (&var_old == p_var) {
|
||||||
|
p_var = &var_new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
IRVariable const* p_var;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user