// TODO: store all of values, allocated registers, stack offsets in single allocator // to be able to find out which kind a specific temp register represent #pragma once #include #include "string.hpp" #include "ir.hpp" template class Allocator { public: virtual ~Allocator() {}; public: virtual const Slot& Allocate(const StringView& addr) = 0; virtual const Slot& Resolve(const StringView& addr) = 0; }; struct StackSlot { size_t offset; StringView addr; }; class StackAllocator : public Allocator { public: StackAllocator() = default; ~StackAllocator() override = default; public: const StackSlot& Allocate(const StringView& addr) { m_offset_counter += 4; m_slots.Push(StackSlot { m_offset_counter, addr }); return m_slots.data[m_slots.size - 1]; } const StackSlot& Resolve(const StringView& addr) { for (size_t i = 0; i < m_slots.size; ++i) { if (strcmp(m_slots.data[i].addr.c_str(), addr.c_str()) == 0) { return m_slots.data[i]; } } assert(0 && "could not resolve stack offset for specified address"); } private: size_t m_offset_counter = 0; Builder m_slots; }; // struct ConstSlot // { // long value; // StringView addr; // }; // class ConstAllocator : public Allocator // { // public: // ConstAllocator() = default; // ~ConstAllocator() override = default; // public: // const ConstSlot& Allocate(const StringView& addr) // { // m_slots.Push(ConstSlot { 0, addr }); // return m_slots.data[m_slots.size - 1]; // } // const ConstSlot& StoreValue(const StringView& addr, long value) // { // for (size_t i = 0; i < m_slots.size; ++i) // { // if (strcmp(m_slots.data[i].addr.c_str(), addr.c_str()) == 0) // { // m_slots.data[i].value = value; // return m_slots.data[i]; // } // } // assert(0 && "could not resolve const under specified address"); // } // const ConstSlot& Resolve(const StringView& addr) // { // for (size_t i = 0; i < m_slots.size; ++i) // { // if (strcmp(m_slots.data[i].addr.c_str(), addr.c_str()) == 0) // { // return m_slots.data[i]; // } // } // assert(0 && "could not resolve const under specified address"); // } // private: // Builder m_slots; // }; // struct RegisterSlot // { // const StringView& reg; // StringView addr; // }; // class RegisterAllocator : public Allocator // { // public: // RegisterAllocator() // { // m_regs.Push(std::move(StringView("eax"))); // m_regs.Push(std::move(StringView("ecx"))); // } // ~RegisterAllocator() override = default; // public: // const RegisterSlot& Allocate(const StringView& addr) // { // assert(m_slots.size < m_regs.size && "no space available for allocating to register"); // m_slots.Push(RegisterSlot { m_regs.data[m_slots.size], addr }); // return m_slots.data[m_slots.size - 1]; // } // const RegisterSlot& Resolve(const StringView& addr) // { // for (size_t i = 0; i < m_slots.size; ++i) // { // if (strcmp(m_slots.data[i].addr.c_str(), addr.c_str()) == 0) // { // return m_slots.data[i]; // } // } // assert(0 && "could not resolve register for specified address"); // } // void Clear() // { // m_slots.size = 0; // } // private: // Builder m_slots; // Builder m_regs; // }; class CodeGenerator { public: virtual ~CodeGenerator() {}; virtual void Generate(const char* filename, View ops) = 0; };