From 578bb3b45bd3b9f6a714facdfb0ac289b3657f82 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 28 Dec 2023 15:11:12 +0100 Subject: [PATCH] better representation (inspired by fleroviux's Lunatic) --- src/backend/core/JIT/IR/Opcode.hpp | 42 ++++++++++++ src/backend/core/JIT/IR/Register.hpp | 11 ++++ src/backend/core/JIT/IR/Value.hpp | 98 ++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/backend/core/JIT/IR/Opcode.hpp create mode 100644 src/backend/core/JIT/IR/Register.hpp create mode 100644 src/backend/core/JIT/IR/Value.hpp diff --git a/src/backend/core/JIT/IR/Opcode.hpp b/src/backend/core/JIT/IR/Opcode.hpp new file mode 100644 index 00000000..12ffd354 --- /dev/null +++ b/src/backend/core/JIT/IR/Opcode.hpp @@ -0,0 +1,42 @@ +#pragma once +#include + +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 +struct IROpcodeBase : IROpcode { + auto GetClass() const -> IROpcodeClass override { return _class; } +}; + +struct IRNoOp final : IROpcodeBase { + 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"; + } +}; +} \ No newline at end of file diff --git a/src/backend/core/JIT/IR/Register.hpp b/src/backend/core/JIT/IR/Register.hpp new file mode 100644 index 00000000..e42adccb --- /dev/null +++ b/src/backend/core/JIT/IR/Register.hpp @@ -0,0 +1,11 @@ +#pragma once +#include + +namespace n64 { +struct IRGuestReg { + IRGuestReg(u8 reg) : reg(reg) {} + + /// The ARM general purpose register + const u8 reg; +}; +} \ No newline at end of file diff --git a/src/backend/core/JIT/IR/Value.hpp b/src/backend/core/JIT/IR/Value.hpp new file mode 100644 index 00000000..94b853bd --- /dev/null +++ b/src/backend/core/JIT/IR/Value.hpp @@ -0,0 +1,98 @@ +#pragma once +#include + +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; +}; +} \ No newline at end of file