// Copyright (c) 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef LIBSPIRV_OPT_INSTRUCTION_LIST_H_ #define LIBSPIRV_OPT_INSTRUCTION_LIST_H_ #include #include #include #include #include "instruction.h" #include "operand.h" #include "util/ilist.h" #include "latest_version_spirv_header.h" #include "spirv-tools/libspirv.h" namespace spvtools { namespace ir { // This class is intended to be the container for Instructions. This container // owns the instructions that are in it. When removing an Instruction from the // list, the caller is assuming responsibility for deleting the storage. // // TODO: Because there are a number of other data structures that will want // pointers to instruction, ownership should probably be moved to the module. // Because of that I have not made the ownership passing in this class fully // explicit. For example, RemoveFromList takes ownership from the list, but // does not return an std::unique_ptr to signal that. When we fully decide on // ownership, this will have to be fixed up one way or the other. class InstructionList : public utils::IntrusiveList { public: InstructionList() = default; InstructionList(InstructionList&& that) : utils::IntrusiveList(std::move(that)) {} InstructionList& operator=(InstructionList&& that) { auto p = static_cast*>(this); *p = std::move(that); return *this; } // Destroy this list and any instructions in the list. inline virtual ~InstructionList(); class iterator : public utils::IntrusiveList::iterator { public: iterator(const utils::IntrusiveList::iterator& i) : utils::IntrusiveList::iterator(i) {} iterator(Instruction* i) : utils::IntrusiveList::iterator(i) {} // DEPRECATED: Please use MoveBefore with an InstructionList instead. // // Moves the nodes in |list| to the list that |this| points to. The // positions of the nodes will be immediately before the element pointed to // by the iterator. The return value will be an iterator pointing to the // first of the newly inserted elements. Ownership of the elements in // |list| is now passed on to |*this|. iterator InsertBefore(std::vector>&& list); // The node |i| will be inserted immediately before |this|. The return value // will be an iterator pointing to the newly inserted node. The owner of // |*i| becomes |*this| iterator InsertBefore(std::unique_ptr&& i); // Removes the node from the list, and deletes the storage. Returns a valid // iterator to the next node. iterator Erase() { iterator_template next_node = *this; ++next_node; node_->RemoveFromList(); delete node_; return next_node; } }; iterator begin() { return utils::IntrusiveList::begin(); } iterator end() { return utils::IntrusiveList::end(); } const_iterator begin() const { return utils::IntrusiveList::begin(); } const_iterator end() const { return utils::IntrusiveList::end(); } void push_back(std::unique_ptr&& inst) { utils::IntrusiveList::push_back(inst.release()); } // Same as in the base class, except it will delete the data as well. inline void clear(); // Runs the given function |f| on the instructions in the list and optionally // on the preceding debug line instructions. inline void ForEachInst(const std::function& f, bool run_on_debug_line_insts) { auto next = begin(); for (auto i = next; i != end(); i = next) { ++next; i->ForEachInst(f, run_on_debug_line_insts); } } }; InstructionList::~InstructionList() { clear(); } void InstructionList::clear() { while (!empty()) { Instruction* inst = &front(); inst->RemoveFromList(); delete inst; } } } // namespace ir } // namespace spvtools #endif // LIBSPIRV_OPT_INSTRUCTION_LIST_H_