better representation (inspired by fleroviux's Lunatic)

This commit is contained in:
Simone
2023-12-28 15:11:12 +01:00
parent 52914d9b78
commit 578bb3b45b
3 changed files with 151 additions and 0 deletions

View 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";
}
};
}

View 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;
};
}

View 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;
};
}