1 //===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the traits classes that are handy for enforcing the correct 11 // layout of various User subclasses. It also provides the means for accessing 12 // the operands in the most efficient manner. 13 // 14 15 #ifndef LLVM_IR_OPERANDTRAITS_H 16 #define LLVM_IR_OPERANDTRAITS_H 17 18 #include "llvm/IR/User.h" 19 20 namespace llvm { 21 22 //===----------------------------------------------------------------------===// 23 // FixedNumOperand Trait Class 24 //===----------------------------------------------------------------------===// 25 26 /// FixedNumOperandTraits - determine the allocation regime of the Use array 27 /// when it is a prefix to the User object, and the number of Use objects is 28 /// known at compile time. 29 30 template <typename SubClass, unsigned ARITY> 31 struct FixedNumOperandTraits { op_beginFixedNumOperandTraits32 static Use *op_begin(SubClass* U) { 33 return reinterpret_cast<Use*>(U) - ARITY; 34 } op_endFixedNumOperandTraits35 static Use *op_end(SubClass* U) { 36 return reinterpret_cast<Use*>(U); 37 } operandsFixedNumOperandTraits38 static unsigned operands(const User*) { 39 return ARITY; 40 } 41 }; 42 43 //===----------------------------------------------------------------------===// 44 // OptionalOperand Trait Class 45 //===----------------------------------------------------------------------===// 46 47 /// OptionalOperandTraits - when the number of operands may change at runtime. 48 /// Naturally it may only decrease, because the allocations may not change. 49 50 template <typename SubClass, unsigned ARITY = 1> 51 struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { operandsOptionalOperandTraits52 static unsigned operands(const User *U) { 53 return U->getNumOperands(); 54 } 55 }; 56 57 //===----------------------------------------------------------------------===// 58 // VariadicOperand Trait Class 59 //===----------------------------------------------------------------------===// 60 61 /// VariadicOperandTraits - determine the allocation regime of the Use array 62 /// when it is a prefix to the User object, and the number of Use objects is 63 /// only known at allocation time. 64 65 template <typename SubClass, unsigned MINARITY = 0> 66 struct VariadicOperandTraits { op_beginVariadicOperandTraits67 static Use *op_begin(SubClass* U) { 68 return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); 69 } op_endVariadicOperandTraits70 static Use *op_end(SubClass* U) { 71 return reinterpret_cast<Use*>(U); 72 } operandsVariadicOperandTraits73 static unsigned operands(const User *U) { 74 return U->getNumOperands(); 75 } 76 }; 77 78 //===----------------------------------------------------------------------===// 79 // HungoffOperand Trait Class 80 //===----------------------------------------------------------------------===// 81 82 /// HungoffOperandTraits - determine the allocation regime of the Use array 83 /// when it is not a prefix to the User object, but allocated at an unrelated 84 /// heap address. 85 /// Assumes that the User subclass that is determined by this traits class 86 /// has an OperandList member of type User::op_iterator. [Note: this is now 87 /// trivially satisfied, because User has that member for historic reasons.] 88 /// 89 /// This is the traits class that is needed when the Use array must be 90 /// resizable. 91 92 template <unsigned MINARITY = 1> 93 struct HungoffOperandTraits { op_beginHungoffOperandTraits94 static Use *op_begin(User* U) { 95 return U->getOperandList(); 96 } op_endHungoffOperandTraits97 static Use *op_end(User* U) { 98 return U->getOperandList() + U->getNumOperands(); 99 } operandsHungoffOperandTraits100 static unsigned operands(const User *U) { 101 return U->getNumOperands(); 102 } 103 }; 104 105 /// Macro for generating in-class operand accessor declarations. 106 /// It should only be called in the public section of the interface. 107 /// 108 #define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ 109 public: \ 110 inline VALUECLASS *getOperand(unsigned) const; \ 111 inline void setOperand(unsigned, VALUECLASS*); \ 112 inline op_iterator op_begin(); \ 113 inline const_op_iterator op_begin() const; \ 114 inline op_iterator op_end(); \ 115 inline const_op_iterator op_end() const; \ 116 protected: \ 117 template <int> inline Use &Op(); \ 118 template <int> inline const Use &Op() const; \ 119 public: \ 120 inline unsigned getNumOperands() const 121 122 /// Macro for generating out-of-class operand accessor definitions 123 #define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ 124 CLASS::op_iterator CLASS::op_begin() { \ 125 return OperandTraits<CLASS>::op_begin(this); \ 126 } \ 127 CLASS::const_op_iterator CLASS::op_begin() const { \ 128 return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ 129 } \ 130 CLASS::op_iterator CLASS::op_end() { \ 131 return OperandTraits<CLASS>::op_end(this); \ 132 } \ 133 CLASS::const_op_iterator CLASS::op_end() const { \ 134 return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ 135 } \ 136 VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ 137 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 138 && "getOperand() out of range!"); \ 139 return cast_or_null<VALUECLASS>( \ 140 OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ 141 } \ 142 void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ 143 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 144 && "setOperand() out of range!"); \ 145 OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ 146 } \ 147 unsigned CLASS::getNumOperands() const { \ 148 return OperandTraits<CLASS>::operands(this); \ 149 } \ 150 template <int Idx_nocapture> Use &CLASS::Op() { \ 151 return this->OpFrom<Idx_nocapture>(this); \ 152 } \ 153 template <int Idx_nocapture> const Use &CLASS::Op() const { \ 154 return this->OpFrom<Idx_nocapture>(this); \ 155 } 156 157 158 } // End llvm namespace 159 160 #endif 161