This commit is contained in:
SimoneN64
2024-01-02 23:57:58 +01:00
parent 463b53f0e4
commit d1b4da3de2
3 changed files with 122 additions and 12 deletions

View File

@@ -2,6 +2,7 @@
#include <common.hpp>
#include <vector>
#include <optional>
#include <IR/Opcode.hpp>
namespace n64 {
struct Entry {

View File

@@ -1,9 +1,11 @@
#pragma once
#include <log.hpp>
#include <IR/Value.hpp>
#include <IR/Register.hpp>
namespace n64 {
enum class IROpcodeClass {
Normal, Special, Regimm, COP0, COP1
StorePC, Add, Special, Regimm, COP0, COP1
};
struct IROpcode {
@@ -13,6 +15,7 @@ struct IROpcode {
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) {}
virtual auto ToString() -> std::string = 0;
};
template<IROpcodeClass _class>
@@ -20,13 +23,59 @@ struct IROpcodeBase : IROpcode {
auto GetClass() const -> IROpcodeClass override { return _class; }
};
struct IRNoOp final : IROpcodeBase<IROpcodeClass::NOP> {
template<IROpcodeClass _class>
struct IRBinaryOpBase : IROpcodeBase<_class> {
IRBinaryOpBase(IRVariable const& result, IRVariable lhs, IRAnyRef rhs)
: result(const_cast<IRVariable &>(result)), lhs(lhs), rhs(rhs) {}
IRVariable& result;
IRVarRef lhs;
IRAnyRef rhs;
auto Reads(IRVariable const& var) -> bool override {
return &lhs.Get() == &var ||
(rhs.IsVariable() && (&rhs.GetVar() == &var));
}
auto Writes(IRVariable const& var) -> bool override {
return result.HasValue() && (&result == &var);
}
void Repoint(
IRVariable const& var_old,
IRVariable const& var_new
) override {
// TODO: make this reusable?
if (result.HasValue() && (&result == &var_old)) {
result = var_new;
}
lhs.Repoint(var_old, var_new);
rhs.Repoint(var_old, var_new);
}
void PropagateConstant(
IRVariable const& var,
IRConstant const& constant
) override {
rhs.PropagateConstant(var, constant);
}
};
struct IRStorePC final : IROpcodeBase<IROpcodeClass::StorePC> {
IRStorePC(IRAnyRef val) : val(val) {}
IRAnyRef val;
auto Reads(IRVariable const& var) -> bool override {
if(val.IsVariable()) {
return &var == &val.GetVar();
}
return false;
}
auto Writes(IRVariable const& var) -> bool override {
return false;
return true;
}
void Repoint(
@@ -36,7 +85,20 @@ struct IRNoOp final : IROpcodeBase<IROpcodeClass::NOP> {
}
auto ToString() -> std::string override {
return "nop";
return fmt::format("str_pc {}", std::to_string(val));
}
};
struct IRAdd final : IRBinaryOpBase<IROpcodeClass::Add> {
using IRBinaryOpBase::IRBinaryOpBase;
auto ToString() -> std::string override {
return fmt::format(
"add {}, {}, {}",
std::to_string(result),
std::to_string(lhs),
std::to_string(rhs)
);
}
};
}

View File

@@ -3,23 +3,27 @@
namespace n64 {
enum IRPrimitive {
Uint32, Sint32, Uint64, Sint32, Uint128, Sint128
Uint32, Sint32, Uint64, Sint64
};
struct IRVariable {
IRVariable(IRPrimitive type, const u32 id, char const* const label) : type(type), id(id), label(label) {}
private:
IRVariable(IRPrimitive type, const u32 id, char const* const label) : type(type), id(id), label(label), assigned(false) {}
IRPrimitive type;
const u32 id;
char const* const label;
u32 id;
char const* label;
bool assigned;
bool HasValue() const { return assigned; }
bool IsNull() const { return !assigned; }
};
struct IRConstant {
IRConstant() {}
IRConstant(IRPrimitive type, u128 value) : type(type), value(value) {}
IRConstant(IRPrimitive type, u64 value) : type(type), value(value) {}
u64 value = 0;
private:
IRPrimitive type = Uint128;
u128 value = 0;
IRPrimitive type = Uint64;
};
struct IRAnyRef {
@@ -96,3 +100,46 @@ private:
IRVariable const* p_var;
};
}
namespace std {
inline auto to_string(n64::IRPrimitive data_type) -> std::string {
switch (data_type) {
case n64::IRPrimitive::Uint32:
return "u32";
case n64::IRPrimitive::Sint32:
return "s32";
case n64::IRPrimitive::Uint64:
return "u64";
case n64::IRPrimitive::Sint64:
return "s64";
default:
return "???";
}
}
inline auto to_string(n64::IRVariable const &variable) -> std::string {
if (variable.label) {
return fmt::format("var{}_{}", variable.id, variable.label);
}
return fmt::format("var{}", variable.id);
}
inline auto to_string(n64::IRConstant const &constant) -> std::string {
return fmt::format("0x{:0X}", constant.value);
}
inline auto to_string(n64::IRAnyRef const &value) -> std::string {
if (value.IsNull()) {
return "(null)";
}
if (value.IsConstant()) {
return std::to_string(value.GetConst());
}
return std::to_string(value.GetVar());
}
inline auto to_string(n64::IRVarRef const &variable) -> std::string {
return std::to_string(variable.Get());
}
}