export module ir;
import std;
import <triton/context.hpp>;
namespace ir {
static unsigned s_index{};
struct Variable {
std::string name;
std::size_t size;
Variable(std::size_t sz) : name{std::format("t{}", ++s_index)}, size{sz} {}
Variable(std::string_view n, std::size_t sz) : name{n}, size{sz} {}
};
struct Register {
triton::arch::Register reg;
Register(const triton::arch::Register& r) : reg{r} {}
};
struct Immediate {
std::uintptr_t value;
std::size_t size;
Immediate(std::uintptr_t v, std::size_t sz = 8) : value{v}, size{sz} {}
Immediate(const triton::arch::Immediate& imm) : value{imm.getValue()}, size{imm.getSize()} {}
};
using Leaf = std::variant<Variable, Register, Immediate>;
struct Memory { Leaf expr; triton::arch::Register seg; std::size_t size; };
struct Extract { Leaf expr; std::size_t hi, lo; };
struct Extend { Leaf expr; std::size_t size; };
struct Sign_extend { Leaf expr; std::size_t size; };
struct Zero_extend { Leaf expr; std::size_t size; };
struct Inc { Leaf expr; std::size_t size; };
struct Dec { Leaf expr; std::size_t size; };
struct Neg { Leaf expr; std::size_t size; };
struct Not { Leaf expr; std::size_t size; };
using Expr = std::variant<
Variable, Register, Immediate,
Memory, Extract, Extend, Sign_extend, Zero_extend,
Inc, Dec, Neg, Not
>;
struct Push { Expr expr; };
struct Assign { Expr lhs, rhs; };
using Instr = std::variant<Push, Assign>;
inline std::string to_string(const Variable& v) { return v.name; }
inline std::string to_string(const Register& r) { return r.reg.getName(); }
inline std::string to_string(const Immediate& i) { return std::format("{:#x}", i.value); }
inline std::string to_string(const Leaf& l) { return std::visit([](auto&& v){ return to_string(v); }, l); }
inline std::size_t get_size(const Variable& v) { return v.size; }
inline std::size_t get_size(const Register& r) { return r.reg.getSize(); }
inline std::size_t get_size(const Immediate& i) { return i.size; }
inline std::size_t get_size(const Leaf& l) { return std::visit([](auto&& v){ return get_size(v); }, l); }
}