| //===- InstIterator.h - Classes for inst iteration --------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains definitions of two iterators for iterating over the |
| // instructions in a function. This is effectively a wrapper around a two level |
| // iterator that can probably be genericized later. |
| // |
| // Note that this iterator gets invalidated any time that basic blocks or |
| // instructions are moved around. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_IR_INSTITERATOR_H |
| #define LLVM_IR_INSTITERATOR_H |
| |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/IR/BasicBlock.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/SymbolTableListTraits.h" |
| #include <iterator> |
| |
| namespace llvm { |
| |
| // This class implements inst_begin() & inst_end() for |
| // inst_iterator and const_inst_iterator's. |
| // |
| template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator { |
| using BBty = BB_t; |
| using BBIty = BB_i_t; |
| using BIty = BI_t; |
| using IIty = II_t; |
| BB_t *BBs; // BasicBlocksType |
| BB_i_t BB; // BasicBlocksType::iterator |
| BI_t BI; // BasicBlock::iterator |
| |
| public: |
| using iterator_category = std::bidirectional_iterator_tag; |
| using value_type = IIty; |
| using difference_type = signed; |
| using pointer = IIty *; |
| using reference = IIty &; |
| |
| // Default constructor |
| InstIterator() = default; |
| |
| // Copy constructor... |
| template<typename A, typename B, typename C, typename D> |
| InstIterator(const InstIterator<A,B,C,D> &II) |
| : BBs(II.BBs), BB(II.BB), BI(II.BI) {} |
| |
| template<typename A, typename B, typename C, typename D> |
| InstIterator(InstIterator<A,B,C,D> &II) |
| : BBs(II.BBs), BB(II.BB), BI(II.BI) {} |
| |
| template<class M> InstIterator(M &m) |
| : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor |
| if (BB != BBs->end()) { |
| BI = BB->begin(); |
| advanceToNextBB(); |
| } |
| } |
| |
| template<class M> InstIterator(M &m, bool) |
| : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor |
| } |
| |
| // Accessors to get at the underlying iterators... |
| inline BBIty &getBasicBlockIterator() { return BB; } |
| inline BIty &getInstructionIterator() { return BI; } |
| |
| inline reference operator*() const { return *BI; } |
| inline pointer operator->() const { return &operator*(); } |
| |
| inline bool operator==(const InstIterator &y) const { |
| return BB == y.BB && (BB == BBs->end() || BI == y.BI); |
| } |
| inline bool operator!=(const InstIterator& y) const { |
| return !operator==(y); |
| } |
| |
| InstIterator& operator++() { |
| ++BI; |
| advanceToNextBB(); |
| return *this; |
| } |
| inline InstIterator operator++(int) { |
| InstIterator tmp = *this; ++*this; return tmp; |
| } |
| |
| InstIterator& operator--() { |
| while (BB == BBs->end() || BI == BB->begin()) { |
| --BB; |
| BI = BB->end(); |
| } |
| --BI; |
| return *this; |
| } |
| inline InstIterator operator--(int) { |
| InstIterator tmp = *this; --*this; return tmp; |
| } |
| |
| inline bool atEnd() const { return BB == BBs->end(); } |
| |
| private: |
| inline void advanceToNextBB() { |
| // The only way that the II could be broken is if it is now pointing to |
| // the end() of the current BasicBlock and there are successor BBs. |
| while (BI == BB->end()) { |
| ++BB; |
| if (BB == BBs->end()) break; |
| BI = BB->begin(); |
| } |
| } |
| }; |
| |
| using inst_iterator = |
| InstIterator<SymbolTableList<BasicBlock>, Function::iterator, |
| BasicBlock::iterator, Instruction>; |
| using const_inst_iterator = |
| InstIterator<const SymbolTableList<BasicBlock>, |
| Function::const_iterator, BasicBlock::const_iterator, |
| const Instruction>; |
| using inst_range = iterator_range<inst_iterator>; |
| using const_inst_range = iterator_range<const_inst_iterator>; |
| |
| inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } |
| inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } |
| inline inst_range instructions(Function *F) { |
| return inst_range(inst_begin(F), inst_end(F)); |
| } |
| inline const_inst_iterator inst_begin(const Function *F) { |
| return const_inst_iterator(*F); |
| } |
| inline const_inst_iterator inst_end(const Function *F) { |
| return const_inst_iterator(*F, true); |
| } |
| inline const_inst_range instructions(const Function *F) { |
| return const_inst_range(inst_begin(F), inst_end(F)); |
| } |
| inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } |
| inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } |
| inline inst_range instructions(Function &F) { |
| return inst_range(inst_begin(F), inst_end(F)); |
| } |
| inline const_inst_iterator inst_begin(const Function &F) { |
| return const_inst_iterator(F); |
| } |
| inline const_inst_iterator inst_end(const Function &F) { |
| return const_inst_iterator(F, true); |
| } |
| inline const_inst_range instructions(const Function &F) { |
| return const_inst_range(inst_begin(F), inst_end(F)); |
| } |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_IR_INSTITERATOR_H |