From a14252bd1d78f080b60aa9fb7f8ba7464e17c733 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Fri, 12 Jun 2026 14:45:26 +0200 Subject: [PATCH] refactor(furlang/ir): improve instruction interface Refs: #2 --- furc/src/front/ssa.cpp | 26 ++---- furlang/include/furlang/ir/instruction.hpp | 98 ++++++++++++++++++++-- furlang/include/furlang/ir/operand.hpp | 13 +++ 3 files changed, 112 insertions(+), 25 deletions(-) diff --git a/furc/src/front/ssa.cpp b/furc/src/front/ssa.cpp index 47c70d3..ea25e53 100644 --- a/furc/src/front/ssa.cpp +++ b/furc/src/front/ssa.cpp @@ -31,25 +31,15 @@ void ssa::optimize(const std::unique_ptr& func) { const auto& block = func->blocks()[i]; for (const auto& instr : block->instructions()) { - switch (instr->type()) { - case furlang::ir::instruction_t::Assign: { - const auto& assign = dynamic_cast(*instr); - regSites[assign.destination().reg()].insert(i); - if (assign.source().type() == furlang::ir::operand_t::Register) { - regUses[i].insert(assign.source().reg()); + if (instr->has_destination()) { + if (instr->destination().type() == furlang::ir::operand_t::Register) { + regSites[instr->destination().reg()].insert(i); } - } break; - case furlang::ir::instruction_t::BinaryOp: { - const auto& binOp = dynamic_cast(*instr); - regSites[binOp.dst().reg()].insert(i); - if (binOp.lhs().type() == furlang::ir::operand_t::Register) { - regUses[i].insert(binOp.lhs().reg()); - } - if (binOp.rhs().type() == furlang::ir::operand_t::Register) { - regUses[i].insert(binOp.rhs().reg()); - } - } break; - default: break; + } + + for (const furlang::ir::operand* src : instr->sources()) { + if (src->type() != furlang::ir::operand_t::Register) continue; + regUses[i].insert(src->reg()); } } diff --git a/furlang/include/furlang/ir/instruction.hpp b/furlang/include/furlang/ir/instruction.hpp index bc84926..4bc6779 100644 --- a/furlang/include/furlang/ir/instruction.hpp +++ b/furlang/include/furlang/ir/instruction.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,41 @@ public: * @return The type. */ virtual instruction_t type() const = 0; + + /** + * @brief Returns whether this instruction has a destination operand. + * + * @return true if this instruction has the destination operand. + */ + virtual bool has_destination() const { return false; } + + /** + * @brief Returns destination operand of this instruction. + * + * @return The destination operand. + */ + virtual operand& destination() { throw std::runtime_error("instruction type mismatch"); } + + /** + * @brief Returns destination operand of this instruction. + * + * @return The destination operand. + */ + virtual const operand& destination() const { throw std::runtime_error("instruction type mismatch"); } + + /** + * @brief Returns a list of source operands of this instruction. + * + * @return The list of source operands. + */ + virtual std::vector sources() { return {}; } + + /** + * @brief Returns a list of source operands of this instruction. + * + * @return The list of source operands. + */ + virtual std::vector sources() const { return {}; } public: /** * @brief Prints an instruction to an output stream. @@ -161,18 +197,39 @@ public: instruction_t type() const override { return instruction_t::Assign; } /** - * @brief Returns this instruction's source. + * @brief Returns whether this instruction has a destination operand. * - * @return The source. + * @return true */ - const operand& source() const { return m_source; } + bool has_destination() const override { return true; } /** * @brief Returns this instruction's destination. * * @return The destination. */ - const operand& destination() const { return m_destination; } + operand& destination() override { return m_destination; } + + /** + * @brief Returns this instruction's destination. + * + * @return The destination. + */ + const operand& destination() const override { return m_destination; } + + /** + * @brief Returns a list of this instruction's source operands. + * + * @return The list of source operands. + */ + std::vector sources() override { return { &m_source }; } + + /** + * @brief Returns a list of this instruction's source operands. + * + * @return The list of source operands. + */ + std::vector sources() const override { return { &m_source }; } private: operand m_source; operand m_destination; @@ -256,6 +313,16 @@ public: */ instruction_t type() const override { return instruction_t::BinaryOp; } + bool has_destination() const override { return true; } + + operand& destination() override { return m_dst; } + + const operand& destination() const override { return m_dst; } + + std::vector sources() override { return { &m_lhs, &m_rhs }; } + + std::vector sources() const override { return { &m_lhs, &m_rhs }; } + /** * @brief Returns this instruction's operation type. * @@ -445,6 +512,16 @@ public: */ instruction_t type() const override { return instruction_t::Return; } + std::vector sources() override { + if (m_value.has_value()) return { &*m_value }; + return {}; + } + + std::vector sources() const override { + if (m_value.has_value()) return { &*m_value }; + return {}; + } + /** * @brief Returns this instruction's return value operand. * @@ -469,7 +546,7 @@ protected: class phi_instruction final : public instruction { public: phi_instruction(register_operand dst) - : m_dst(dst) {} + : m_dst(operand::new_reg(dst)) {} ~phi_instruction() override = default; @@ -499,7 +576,14 @@ public: * * @return The register. */ - register_operand destination() const { return m_dst; } + operand& destination() override { return m_dst; } + + /** + * @brief Returns this instruction's destination register. + * + * @return The register. + */ + const operand& destination() const override { return m_dst; } /** * @brief Returns this instruction's labels. @@ -515,7 +599,7 @@ public: */ const std::vector>& labels() const { return m_labels; } private: - register_operand m_dst; + operand m_dst; std::vector> m_labels; protected: std::ostream& print(std::ostream& os) const override { diff --git a/furlang/include/furlang/ir/operand.hpp b/furlang/include/furlang/ir/operand.hpp index e866123..145aa92 100644 --- a/furlang/include/furlang/ir/operand.hpp +++ b/furlang/include/furlang/ir/operand.hpp @@ -137,6 +137,19 @@ public: return operand; } + /** + * @brief Construct a new register operand. + * + * @param value Value of the new register operand. + * @return The register operand. + */ + static operand new_reg(register_operand value) { + operand operand; + operand.m_type = operand_t::Register; + operand.m_value.reg = value; + return operand; + } + /** * @brief Construct a new variable operand. *