Files
llvm-mirror/include/llvm/CodeGen/MachineInstrBundleIterator.h
T
Duncan P. N. Exon Smith cd73eace2f CodeGen: Assert that bundle iterators are valid
Add an assertion to the MachineInstrBundleIterator from instr_iterator
that the underlying iterator is valid.  This is possible know that we
can check ilist_node::isSentinel (since r281168), and is consistent with
the constructors from MachineInstr* and MachineInstr&.

Avoiding the new assertion in operator== and operator!= requires four
(!!!!) new overloads each.

(As an aside, I'm strongly in favour of:
- making the conversion from instr_iterator explicit;
- making the conversion from pointer explicit;
- making the conversion from reference explicit; and
- removing all the extra overloads of operator== and operator!= except
  const_instr_iterator.

I'm not signing up for that at this point, but being clear about when
something is an MachineInstr-iterator (possibly instr_end()) vs
MachineInstr-bundle-iterator (possibly end()) vs MachineInstr* (possibly
nullptr) vs MachineInstr& (known valid) would surely make code
cleaner... and it would remove a ton of boilerplate from
MachineInstrBundleIterator operators.)

llvm-svn: 281170
2016-09-11 17:12:28 +00:00

194 lines
7.1 KiB
C++

//===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines an iterator class that bundles MachineInstr.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
#include "llvm/ADT/ilist.h"
#include <iterator>
namespace llvm {
template <class T> struct MachineInstrBundleIteratorTraits {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::iterator instr_iterator;
typedef typename list_type::iterator nonconst_instr_iterator;
typedef typename list_type::const_iterator const_instr_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<const T> {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::const_iterator instr_iterator;
typedef typename list_type::iterator nonconst_instr_iterator;
typedef typename list_type::const_iterator const_instr_iterator;
};
/// MachineBasicBlock iterator that automatically skips over MIs that are
/// inside bundles (i.e. walk top level MIs only).
template <typename Ty> class MachineInstrBundleIterator {
typedef MachineInstrBundleIteratorTraits<Ty> Traits;
typedef typename Traits::instr_iterator instr_iterator;
instr_iterator MII;
public:
typedef typename instr_iterator::value_type value_type;
typedef typename instr_iterator::difference_type difference_type;
typedef typename instr_iterator::pointer pointer;
typedef typename instr_iterator::reference reference;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename instr_iterator::const_pointer const_pointer;
typedef typename instr_iterator::const_reference const_reference;
private:
typedef typename Traits::nonconst_instr_iterator nonconst_instr_iterator;
typedef typename Traits::const_instr_iterator const_instr_iterator;
typedef MachineInstrBundleIterator<
typename nonconst_instr_iterator::value_type>
nonconst_iterator;
public:
MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {
assert((!MI.getNodePtr() || MI.isEnd() || !MI->isBundledWithPred()) &&
"It's not legal to initialize MachineInstrBundleIterator with a "
"bundled MI");
}
MachineInstrBundleIterator(reference MI) : MII(MI) {
assert(!MI.isBundledWithPred() && "It's not legal to initialize "
"MachineInstrBundleIterator with a "
"bundled MI");
}
MachineInstrBundleIterator(pointer MI) : MII(MI) {
// FIXME: This conversion should be explicit.
assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
"MachineInstrBundleIterator "
"with a bundled MI");
}
// Template allows conversion from const to nonconst.
template <class OtherTy>
MachineInstrBundleIterator(
const MachineInstrBundleIterator<OtherTy> &I,
typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
void *>::type = nullptr)
: MII(I.getInstrIterator()) {}
MachineInstrBundleIterator() : MII(nullptr) {}
reference operator*() const { return *MII; }
pointer operator->() const { return &operator*(); }
/// Check for null.
bool isValid() const { return MII.getNodePtr(); }
friend bool operator==(const MachineInstrBundleIterator &L,
const MachineInstrBundleIterator &R) {
return L.MII == R.MII;
}
friend bool operator==(const MachineInstrBundleIterator &L,
const const_instr_iterator &R) {
return L.MII == R; // Avoid assertion about validity of R.
}
friend bool operator==(const const_instr_iterator &L,
const MachineInstrBundleIterator &R) {
return L == R.MII; // Avoid assertion about validity of L.
}
friend bool operator==(const MachineInstrBundleIterator &L,
const nonconst_instr_iterator &R) {
return L.MII == R; // Avoid assertion about validity of R.
}
friend bool operator==(const nonconst_instr_iterator &L,
const MachineInstrBundleIterator &R) {
return L == R.MII; // Avoid assertion about validity of L.
}
friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) {
return L == const_instr_iterator(R); // Avoid assertion about validity of R.
}
friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) {
return const_instr_iterator(L) == R; // Avoid assertion about validity of L.
}
friend bool operator==(const MachineInstrBundleIterator &L,
const_reference R) {
return L == &R; // Avoid assertion about validity of R.
}
friend bool operator==(const_reference L,
const MachineInstrBundleIterator &R) {
return &L == R; // Avoid assertion about validity of L.
}
friend bool operator!=(const MachineInstrBundleIterator &L,
const MachineInstrBundleIterator &R) {
return !(L == R);
}
friend bool operator!=(const MachineInstrBundleIterator &L,
const const_instr_iterator &R) {
return !(L == R);
}
friend bool operator!=(const const_instr_iterator &L,
const MachineInstrBundleIterator &R) {
return !(L == R);
}
friend bool operator!=(const MachineInstrBundleIterator &L,
const nonconst_instr_iterator &R) {
return !(L == R);
}
friend bool operator!=(const nonconst_instr_iterator &L,
const MachineInstrBundleIterator &R) {
return !(L == R);
}
friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) {
return !(L == R);
}
friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) {
return !(L == R);
}
friend bool operator!=(const MachineInstrBundleIterator &L,
const_reference R) {
return !(L == R);
}
friend bool operator!=(const_reference L,
const MachineInstrBundleIterator &R) {
return !(L == R);
}
// Increment and decrement operators...
MachineInstrBundleIterator &operator--() {
do
--MII;
while (MII->isBundledWithPred());
return *this;
}
MachineInstrBundleIterator &operator++() {
while (MII->isBundledWithSucc())
++MII;
++MII;
return *this;
}
MachineInstrBundleIterator operator--(int) {
MachineInstrBundleIterator Temp = *this;
--*this;
return Temp;
}
MachineInstrBundleIterator operator++(int) {
MachineInstrBundleIterator Temp = *this;
++*this;
return Temp;
}
instr_iterator getInstrIterator() const { return MII; }
nonconst_iterator getNonConstIterator() const { return MII.getNonConst(); }
};
} // end namespace llvm
#endif