aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/IR/Value.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/Value.h')
-rw-r--r--include/llvm/IR/Value.h138
1 files changed, 128 insertions, 10 deletions
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index e1361fe..d5b9f11 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -14,11 +14,12 @@
#ifndef LLVM_IR_VALUE_H
#define LLVM_IR_VALUE_H
+#include "llvm-c/Core.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Use.h"
-#include "llvm/Support/Casting.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
-#include "llvm-c/Core.h"
namespace llvm {
@@ -36,6 +37,7 @@ class InlineAsm;
class Instruction;
class LLVMContext;
class MDNode;
+class Module;
class StringRef;
class Twine;
class Type;
@@ -60,7 +62,7 @@ typedef StringMapEntry<Value*> ValueName;
/// Every value has a "use list" that keeps track of which other Values are
/// using this Value. A Value can also have an arbitrary number of ValueHandle
/// objects that watch it and listen to RAUW and Destroy events. See
-/// llvm/Support/ValueHandle.h for details.
+/// llvm/IR/ValueHandle.h for details.
///
/// @brief LLVM Value Representation
class Value {
@@ -74,6 +76,96 @@ protected:
unsigned char SubclassOptionalData : 7;
private:
+ template <typename UseT> // UseT == 'Use' or 'const Use'
+ class use_iterator_impl
+ : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
+ typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super;
+
+ UseT *U;
+ explicit use_iterator_impl(UseT *u) : U(u) {}
+ friend class Value;
+
+ public:
+ typedef typename super::reference reference;
+ typedef typename super::pointer pointer;
+
+ use_iterator_impl() : U() {}
+
+ bool operator==(const use_iterator_impl &x) const { return U == x.U; }
+ bool operator!=(const use_iterator_impl &x) const { return !operator==(x); }
+
+ use_iterator_impl &operator++() { // Preincrement
+ assert(U && "Cannot increment end iterator!");
+ U = U->getNext();
+ return *this;
+ }
+ use_iterator_impl operator++(int) { // Postincrement
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ UseT &operator*() const {
+ assert(U && "Cannot dereference end iterator!");
+ return *U;
+ }
+
+ UseT *operator->() const { return &operator*(); }
+
+ operator use_iterator_impl<const UseT>() const {
+ return use_iterator_impl<const UseT>(U);
+ }
+ };
+
+ template <typename UserTy> // UserTy == 'User' or 'const User'
+ class user_iterator_impl
+ : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> {
+ typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super;
+
+ use_iterator_impl<Use> UI;
+ explicit user_iterator_impl(Use *U) : UI(U) {}
+ friend class Value;
+
+ public:
+ typedef typename super::reference reference;
+ typedef typename super::pointer pointer;
+
+ user_iterator_impl() {}
+
+ bool operator==(const user_iterator_impl &x) const { return UI == x.UI; }
+ bool operator!=(const user_iterator_impl &x) const { return !operator==(x); }
+
+ /// \brief Returns true if this iterator is equal to user_end() on the value.
+ bool atEnd() const { return *this == user_iterator_impl(); }
+
+ user_iterator_impl &operator++() { // Preincrement
+ ++UI;
+ return *this;
+ }
+ user_iterator_impl operator++(int) { // Postincrement
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ // Retrieve a pointer to the current User.
+ UserTy *operator*() const {
+ return UI->getUser();
+ }
+
+ UserTy *operator->() const { return operator*(); }
+
+ operator user_iterator_impl<const UserTy>() const {
+ return user_iterator_impl<const UserTy>(*UI);
+ }
+
+ Use &getUse() const { return *UI; }
+
+ /// \brief Return the operand # of this use in its User.
+ /// FIXME: Replace all callers with a direct call to Use::getOperandNo.
+ unsigned getOperandNo() const { return UI->getOperandNo(); }
+ };
+
/// SubclassData - This member is defined by this class, but is not used for
/// anything. Subclasses can use it to hold whatever state they find useful.
/// This field is initialized to zero by the ctor.
@@ -106,6 +198,13 @@ public:
///
void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) const;
+ /// \brief Print the name of this Value out to the specified raw_ostream.
+ /// This is useful when you just want to print 'int %reg126', not the
+ /// instruction that generated it. If you specify a Module for context, then
+ /// even constanst get pretty-printed; for example, the type of a null
+ /// pointer is printed symbolically.
+ void printAsOperand(raw_ostream &O, bool PrintType = true, const Module *M = 0) const;
+
/// All values are typed, get the type of this value.
///
Type *getType() const { return VTy; }
@@ -143,16 +242,35 @@ public:
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
- typedef value_use_iterator<User> use_iterator;
- typedef value_use_iterator<const User> const_use_iterator;
-
bool use_empty() const { return UseList == 0; }
+
+ typedef use_iterator_impl<Use> use_iterator;
+ typedef use_iterator_impl<const Use> const_use_iterator;
use_iterator use_begin() { return use_iterator(UseList); }
const_use_iterator use_begin() const { return const_use_iterator(UseList); }
- use_iterator use_end() { return use_iterator(0); }
- const_use_iterator use_end() const { return const_use_iterator(0); }
- User *use_back() { return *use_begin(); }
- const User *use_back() const { return *use_begin(); }
+ use_iterator use_end() { return use_iterator(); }
+ const_use_iterator use_end() const { return const_use_iterator(); }
+ iterator_range<use_iterator> uses() {
+ return iterator_range<use_iterator>(use_begin(), use_end());
+ }
+ iterator_range<const_use_iterator> uses() const {
+ return iterator_range<const_use_iterator>(use_begin(), use_end());
+ }
+
+ typedef user_iterator_impl<User> user_iterator;
+ typedef user_iterator_impl<const User> const_user_iterator;
+ user_iterator user_begin() { return user_iterator(UseList); }
+ const_user_iterator user_begin() const { return const_user_iterator(UseList); }
+ user_iterator user_end() { return user_iterator(); }
+ const_user_iterator user_end() const { return const_user_iterator(); }
+ User *user_back() { return *user_begin(); }
+ const User *user_back() const { return *user_begin(); }
+ iterator_range<user_iterator> users() {
+ return iterator_range<user_iterator>(user_begin(), user_end());
+ }
+ iterator_range<const_user_iterator> users() const {
+ return iterator_range<const_user_iterator>(user_begin(), user_end());
+ }
/// hasOneUse - Return true if there is exactly one user of this value. This
/// is specialized because it is a common request and does not require