11 #include <llvm/ADT/ilist.h>
12 #include <llvm/ADT/ilist_node.h>
13 #include <llvm/ADT/iterator_range.h>
14 #include <llvm/IR/CFG.h>
15 #include <llvm/Support/raw_ostream.h>
17 #include "core/inst.h"
18 #include "core/global.h"
19 #include "core/symbol_table.h"
29 class Block final :
public llvm::ilist_node_with_parent<Block, Func>,
public Global {
36 using InstListType = llvm::ilist<Inst>;
39 using iterator = InstListType::iterator;
40 using reverse_iterator = InstListType::reverse_iterator;
41 using const_iterator = InstListType::const_iterator;
42 using const_reverse_iterator = InstListType::const_reverse_iterator;
46 using iter_fwd = std::iterator<std::forward_iterator_tag, T, ptrdiff_t, T *, T *>;
49 template <
class BlockT,
class UseIterator>
56 using pointer =
typename iter_fwd<BlockT>::pointer;
57 using reference =
typename iter_fwd<BlockT>::reference;
61 inline PredIterator(UseIterator it) : use_(it) { SkipToTerminator(); }
63 inline bool operator==(
const PredIterator& x)
const {
return use_ == x.use_; }
64 inline bool operator!=(
const PredIterator& x)
const {
return !operator==(x); }
66 inline reference operator*()
const
68 return static_cast<const TerminatorInst *
>(*use_)->getParent();
71 inline pointer *operator->()
const
90 inline void SkipToTerminator()
92 while (!use_.atEnd()) {
93 if (!*use_ || !(*use_)->Is(Value::Kind::INST)) {
109 using succ_iterator = llvm::SuccIterator<TerminatorInst, Block>;
110 using const_succ_iterator = llvm::SuccIterator<const TerminatorInst, const Block>;
115 template<
typename It,
typename T>
116 using facade_fwd = llvm::iterator_facade_base<It, std::forward_iterator_tag, T>;
119 template<
typename PhiT,
typename IterT>
120 class PhiIterator :
public facade_fwd<PhiIterator<PhiT, IterT>, PhiT> {
123 template <
typename PhiU,
typename IterU>
138 auto end = phi_->getParent()->end();
139 auto it = std::next(IterT(phi_));
140 if (it != end && it->Is(Inst::Kind::PHI)) {
141 phi_ =
static_cast<PhiT *
>(&*it);
165 using phi_iterator = PhiIterator<PhiInst, iterator>;
166 using const_phi_iterator = PhiIterator<const PhiInst, const_iterator>;
176 const std::string_view name,
177 Visibility visibility = Visibility::LOCAL
206 return llvm::Align(1u);
224 void erase(iterator it);
226 void erase(iterator first, iterator last);
232 bool empty()
const {
return insts_.empty(); }
233 iterator begin() {
return insts_.begin(); }
234 iterator end() {
return insts_.end(); }
235 const_iterator begin()
const {
return insts_.begin(); }
236 const_iterator end()
const {
return insts_.end(); }
237 reverse_iterator rbegin() {
return insts_.rbegin(); }
238 reverse_iterator rend() {
return insts_.rend(); }
239 const_reverse_iterator rbegin()
const {
return insts_.rbegin(); }
240 const_reverse_iterator rend()
const {
return insts_.rend(); }
243 size_t size()
const {
return insts_.size(); }
246 succ_iterator succ_begin();
247 succ_iterator succ_end();
248 inline llvm::iterator_range<succ_iterator> successors()
250 return llvm::make_range(succ_begin(), succ_end());
253 const_succ_iterator succ_begin()
const;
254 const_succ_iterator succ_end()
const;
255 inline llvm::iterator_range<const_succ_iterator> successors()
const
257 return llvm::make_range(succ_begin(), succ_end());
260 inline unsigned succ_size()
const
262 return std::distance(succ_begin(), succ_end());
265 inline bool succ_empty()
const {
return succ_begin() == succ_end(); }
268 inline bool pred_empty()
const {
return pred_begin() == pred_end(); }
269 inline unsigned pred_size()
const
271 return std::distance(pred_begin(), pred_end());
273 pred_iterator pred_begin() {
return pred_iterator(user_begin()); }
274 pred_iterator pred_end() {
return pred_iterator(user_end()); }
275 const_pred_iterator pred_begin()
const {
return const_pred_iterator(user_begin()); }
276 const_pred_iterator pred_end()
const {
return const_pred_iterator(user_end()); }
277 inline llvm::iterator_range<pred_iterator> predecessors()
279 return llvm::make_range(pred_begin(), pred_end());
281 inline llvm::iterator_range<const_pred_iterator> predecessors()
const
283 return llvm::make_range(pred_begin(), pred_end());
287 bool phi_empty()
const {
return !begin()->Is(Inst::Kind::PHI); }
289 llvm::iterator_range<const_phi_iterator> phis()
const {
290 return const_cast<Block *
>(
this)->phis();
292 llvm::iterator_range<phi_iterator> phis();
301 void printAsOperand(llvm::raw_ostream &O,
bool PrintType =
true)
const;
307 void dump(llvm::raw_ostream &os = llvm::errs())
const;
310 friend struct llvm::ilist_traits<
Inst>;
313 void setParent(
Func *parent) { parent_ = parent; }
323 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const Block &block)