1 //===- InstIterator.h - Classes for inst iteration --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains definitions of two iterators for iterating over the 10 // instructions in a function. This is effectively a wrapper around a two level 11 // iterator that can probably be genericized later. 12 // 13 // Note that this iterator gets invalidated any time that basic blocks or 14 // instructions are moved around. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_IR_INSTITERATOR_H 19 #define LLVM_IR_INSTITERATOR_H 20 21 #include "llvm/ADT/iterator_range.h" 22 #include "llvm/IR/BasicBlock.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/IR/SymbolTableListTraits.h" 25 #include <iterator> 26 27 namespace llvm { 28 29 // This class implements inst_begin() & inst_end() for 30 // inst_iterator and const_inst_iterator's. 31 // 32 template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator { 33 using BBty = BB_t; 34 using BBIty = BB_i_t; 35 using BIty = BI_t; 36 using IIty = II_t; 37 BB_t *BBs; // BasicBlocksType 38 BB_i_t BB; // BasicBlocksType::iterator 39 BI_t BI; // BasicBlock::iterator 40 41 public: 42 using iterator_category = std::bidirectional_iterator_tag; 43 using value_type = IIty; 44 using difference_type = signed; 45 using pointer = IIty *; 46 using reference = IIty &; 47 48 // Default constructor 49 InstIterator() = default; 50 51 // Copy constructor... 52 template<typename A, typename B, typename C, typename D> 53 InstIterator(const InstIterator<A,B,C,D> &II) 54 : BBs(II.BBs), BB(II.BB), BI(II.BI) {} 55 56 template<typename A, typename B, typename C, typename D> 57 InstIterator(InstIterator<A,B,C,D> &II) 58 : BBs(II.BBs), BB(II.BB), BI(II.BI) {} 59 60 template<class M> InstIterator(M &m) 61 : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor 62 if (BB != BBs->end()) { 63 BI = BB->begin(); 64 advanceToNextBB(); 65 } 66 } 67 68 template<class M> InstIterator(M &m, bool) 69 : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor 70 } 71 72 // Accessors to get at the underlying iterators... 73 inline BBIty &getBasicBlockIterator() { return BB; } 74 inline BIty &getInstructionIterator() { return BI; } 75 76 inline reference operator*() const { return *BI; } 77 inline pointer operator->() const { return &operator*(); } 78 79 inline bool operator==(const InstIterator &y) const { 80 return BB == y.BB && (BB == BBs->end() || BI == y.BI); 81 } 82 inline bool operator!=(const InstIterator& y) const { 83 return !operator==(y); 84 } 85 86 InstIterator& operator++() { 87 ++BI; 88 advanceToNextBB(); 89 return *this; 90 } 91 inline InstIterator operator++(int) { 92 InstIterator tmp = *this; ++*this; return tmp; 93 } 94 95 InstIterator& operator--() { 96 while (BB == BBs->end() || BI == BB->begin()) { 97 --BB; 98 BI = BB->end(); 99 } 100 --BI; 101 return *this; 102 } 103 inline InstIterator operator--(int) { 104 InstIterator tmp = *this; --*this; return tmp; 105 } 106 107 inline bool atEnd() const { return BB == BBs->end(); } 108 109 private: 110 inline void advanceToNextBB() { 111 // The only way that the II could be broken is if it is now pointing to 112 // the end() of the current BasicBlock and there are successor BBs. 113 while (BI == BB->end()) { 114 ++BB; 115 if (BB == BBs->end()) break; 116 BI = BB->begin(); 117 } 118 } 119 }; 120 121 using inst_iterator = 122 InstIterator<SymbolTableList<BasicBlock>, Function::iterator, 123 BasicBlock::iterator, Instruction>; 124 using const_inst_iterator = 125 InstIterator<const SymbolTableList<BasicBlock>, 126 Function::const_iterator, BasicBlock::const_iterator, 127 const Instruction>; 128 using inst_range = iterator_range<inst_iterator>; 129 using const_inst_range = iterator_range<const_inst_iterator>; 130 131 inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } 132 inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } 133 inline inst_range instructions(Function *F) { 134 return inst_range(inst_begin(F), inst_end(F)); 135 } 136 inline const_inst_iterator inst_begin(const Function *F) { 137 return const_inst_iterator(*F); 138 } 139 inline const_inst_iterator inst_end(const Function *F) { 140 return const_inst_iterator(*F, true); 141 } 142 inline const_inst_range instructions(const Function *F) { 143 return const_inst_range(inst_begin(F), inst_end(F)); 144 } 145 inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } 146 inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } 147 inline inst_range instructions(Function &F) { 148 return inst_range(inst_begin(F), inst_end(F)); 149 } 150 inline const_inst_iterator inst_begin(const Function &F) { 151 return const_inst_iterator(F); 152 } 153 inline const_inst_iterator inst_end(const Function &F) { 154 return const_inst_iterator(F, true); 155 } 156 inline const_inst_range instructions(const Function &F) { 157 return const_inst_range(inst_begin(F), inst_end(F)); 158 } 159 160 } // end namespace llvm 161 162 #endif // LLVM_IR_INSTITERATOR_H 163