// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include #include #include "common/bit_cast.h" #include "common/common_types.h" #include "shader_recompiler/frontend/ir/condition.h" #include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/object_pool.h" namespace Shader::IR { class Block { public: using InstructionList = boost::intrusive::list; using size_type = InstructionList::size_type; using iterator = InstructionList::iterator; using const_iterator = InstructionList::const_iterator; using reverse_iterator = InstructionList::reverse_iterator; using const_reverse_iterator = InstructionList::const_reverse_iterator; explicit Block(ObjectPool& inst_pool_); ~Block(); Block(const Block&) = delete; Block& operator=(const Block&) = delete; Block(Block&&) = default; Block& operator=(Block&&) = default; /// Appends a new instruction to the end of this basic block. void AppendNewInst(Opcode op, std::initializer_list args); /// Prepends a copy of an instruction to this basic block before the insertion point. iterator PrependNewInst(iterator insertion_point, const Inst& base_inst); /// Prepends a new instruction to this basic block before the insertion point. iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list args = {}, u32 flags = 0); /// Adds a new branch to this basic block. void AddBranch(Block* block); /// Gets a mutable reference to the instruction list for this basic block. [[nodiscard]] InstructionList& Instructions() noexcept { return instructions; } /// Gets an immutable reference to the instruction list for this basic block. [[nodiscard]] const InstructionList& Instructions() const noexcept { return instructions; } /// Gets an immutable span to the immediate predecessors. [[nodiscard]] std::span ImmPredecessors() const noexcept { return imm_predecessors; } /// Gets an immutable span to the immediate successors. [[nodiscard]] std::span ImmSuccessors() const noexcept { return imm_successors; } /// Intrusively store the host definition of this instruction. template void SetDefinition(DefinitionType def) { definition = Common::BitCast(def); } /// Return the intrusively stored host definition of this instruction. template [[nodiscard]] DefinitionType Definition() const noexcept { return Common::BitCast(definition); } void SetSsaRegValue(IR::Reg reg, const Value& value) noexcept { ssa_reg_values[RegIndex(reg)] = value; } const Value& SsaRegValue(IR::Reg reg) const noexcept { return ssa_reg_values[RegIndex(reg)]; } void SsaSeal() noexcept { is_ssa_sealed = true; } [[nodiscard]] bool IsSsaSealed() const noexcept { return is_ssa_sealed; } [[nodiscard]] bool empty() const { return instructions.empty(); } [[nodiscard]] size_type size() const { return instructions.size(); } [[nodiscard]] Inst& front() { return instructions.front(); } [[nodiscard]] const Inst& front() const { return instructions.front(); } [[nodiscard]] Inst& back() { return instructions.back(); } [[nodiscard]] const Inst& back() const { return instructions.back(); } [[nodiscard]] iterator begin() { return instructions.begin(); } [[nodiscard]] const_iterator begin() const { return instructions.begin(); } [[nodiscard]] iterator end() { return instructions.end(); } [[nodiscard]] const_iterator end() const { return instructions.end(); } [[nodiscard]] reverse_iterator rbegin() { return instructions.rbegin(); } [[nodiscard]] const_reverse_iterator rbegin() const { return instructions.rbegin(); } [[nodiscard]] reverse_iterator rend() { return instructions.rend(); } [[nodiscard]] const_reverse_iterator rend() const { return instructions.rend(); } [[nodiscard]] const_iterator cbegin() const { return instructions.cbegin(); } [[nodiscard]] const_iterator cend() const { return instructions.cend(); } [[nodiscard]] const_reverse_iterator crbegin() const { return instructions.crbegin(); } [[nodiscard]] const_reverse_iterator crend() const { return instructions.crend(); } // Set the order of the block, it can be set pre order, the user decides void SetOrder(u32 new_order) { order = new_order; } // Get the order of the block. // The higher, the closer is the block to the end. [[nodiscard]] u32 GetOrder() const { return order; } private: /// Memory pool for instruction list ObjectPool* inst_pool; /// List of instructions in this block InstructionList instructions; /// Block immediate predecessors std::vector imm_predecessors; /// Block immediate successors std::vector imm_successors; /// Intrusively store the value of a register in the block. std::array ssa_reg_values; /// Intrusively store if the block is sealed in the SSA pass. bool is_ssa_sealed{false}; /// Intrusively stored host definition of this block. u32 definition{}; /// Order of the block. u32 order{}; }; using BlockList = std::vector; [[nodiscard]] std::string DumpBlock(const Block& block); [[nodiscard]] std::string DumpBlock(const Block& block, const std::map& block_to_index, std::map& inst_to_index, size_t& inst_index); } // namespace Shader::IR