//===--- SILSuccessor.h - Terminator Instruction Successor ------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_SILSUCCESSOR_H #define SWIFT_SIL_SILSUCCESSOR_H #include "swift/Basic/ProfileCounter.h" #include #include #include namespace swift { class SILBasicBlock; class TermInst; /// An edge in the control flow graph. /// /// A SILSuccessor is stored in the terminator instruction of the tail block of /// the CFG edge. Internally it has a back reference to the terminator that /// contains it (ContainingInst). It also contains the SuccessorBlock that is /// the "head" of the CFG edge. This makes it very simple to iterate over the /// successors of a specific block. /// /// SILSuccessor also enables given a "head" edge the ability to iterate over /// predecessors. This is done by using an ilist that is embedded into /// SILSuccessors. class SILSuccessor { /// The terminator instruction that contains this SILSuccessor. TermInst *ContainingInst = nullptr; /// If non-null, this is the BasicBlock that the terminator branches to. SILBasicBlock *SuccessorBlock = nullptr; /// If hasValue, this is the profiled execution count of the edge ProfileCounter Count; /// A pointer to the SILSuccessor that represents the previous SILSuccessor in the /// predecessor list for SuccessorBlock. /// /// Must be nullptr if SuccessorBlock is. SILSuccessor **Prev = nullptr; /// A pointer to the SILSuccessor that represents the next SILSuccessor in the /// predecessor list for SuccessorBlock. /// /// Must be nullptr if SuccessorBlock is. SILSuccessor *Next = nullptr; public: SILSuccessor(ProfileCounter Count = ProfileCounter()) : Count(Count) {} SILSuccessor(TermInst *CI, ProfileCounter Count = ProfileCounter()) : ContainingInst(CI), Count(Count) {} SILSuccessor(TermInst *CI, SILBasicBlock *Succ, ProfileCounter Count = ProfileCounter()) : ContainingInst(CI), Count(Count) { *this = Succ; } ~SILSuccessor() { *this = nullptr; } void operator=(SILBasicBlock *BB); operator SILBasicBlock*() const { return SuccessorBlock; } SILBasicBlock *getBB() const { return SuccessorBlock; } TermInst *getContainingInst() const { return ContainingInst; } SILSuccessor *getNext() const { return Next; } ProfileCounter getCount() const { return Count; } // Do not copy or move these. SILSuccessor(const SILSuccessor &) = delete; SILSuccessor(SILSuccessor &&) = delete; /// This is an iterator for walking the predecessor list of a SILBasicBlock. class pred_iterator { SILSuccessor *Cur; // Cache the basic block to avoid repeated pointer chasing. SILBasicBlock *Block; void cacheBasicBlock(); public: using difference_type = std::ptrdiff_t; using value_type = SILBasicBlock *; using pointer = SILBasicBlock **; using reference = SILBasicBlock *&; using iterator_category = std::forward_iterator_tag; pred_iterator(SILSuccessor *Cur = nullptr) : Cur(Cur), Block(nullptr) { cacheBasicBlock(); } bool operator==(pred_iterator I2) const { return Cur == I2.Cur; } bool operator!=(pred_iterator I2) const { return Cur != I2.Cur; } pred_iterator &operator++() { assert(Cur != nullptr); Cur = Cur->Next; cacheBasicBlock(); return *this; } pred_iterator operator++(int) { auto old = *this; ++*this; return old; } pred_iterator operator+(unsigned distance) const { auto copy = *this; if (distance == 0) return copy; do { copy.Cur = Cur->Next; } while (--distance > 0); copy.cacheBasicBlock(); return copy; } SILSuccessor *getSuccessorRef() const { return Cur; } SILBasicBlock *operator*() const { return Block; } }; }; } // end swift namespace #endif