OperandTraits.h revision 6cd093b56e80ed54a2062e789937a096ba3afe56
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_OPERAND_TRAITS_H 16#define LLVM_OPERAND_TRAITS_H 17 18#include "llvm/User.h" 19 20namespace llvm { 21 22//===----------------------------------------------------------------------===// 23// FixedNumOperands 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 30template <unsigned ARITY> 31struct FixedNumOperandTraits { 32 static Use *op_begin(User* U) { 33 return reinterpret_cast<Use*>(U) - ARITY; 34 } 35 static Use *op_end(User* U) { 36 return reinterpret_cast<Use*>(U); 37 } 38 static unsigned operands(const User*) { 39 return ARITY; 40 } 41 struct prefix { 42 Use Ops[ARITY]; 43 prefix(); // DO NOT IMPLEMENT 44 }; 45 template <class U> 46 struct Layout { 47 struct overlay : prefix, U { 48 overlay(); // DO NOT IMPLEMENT 49 }; 50 }; 51 static inline void *allocate(unsigned); // FIXME 52}; 53 54//===----------------------------------------------------------------------===// 55// OptionalOperands Trait Class 56//===----------------------------------------------------------------------===// 57 58template <unsigned ARITY = 1> 59struct OptionalOperandTraits : FixedNumOperandTraits<ARITY> { 60 static unsigned operands(const User *U) { 61 return U->getNumOperands(); 62 } 63}; 64 65//===----------------------------------------------------------------------===// 66// VariadicOperand Trait Class 67//===----------------------------------------------------------------------===// 68 69/// VariadicOperandTraits - determine the allocation regime of the Use array 70/// when it is a prefix to the User object, and the number of Use objects is 71/// only known at allocation time. 72 73template <unsigned MINARITY = 0> 74struct VariadicOperandTraits { 75 static Use *op_begin(User* U) { 76 return reinterpret_cast<Use*>(U) - U->getNumOperands(); 77 } 78 static Use *op_end(User* U) { 79 return reinterpret_cast<Use*>(U); 80 } 81 static unsigned operands(const User *U) { 82 return U->getNumOperands(); 83 } 84 static inline void *allocate(unsigned); // FIXME 85}; 86 87//===----------------------------------------------------------------------===// 88// HungoffOperand Trait Class 89//===----------------------------------------------------------------------===// 90 91/// HungoffOperandTraits - determine the allocation regime of the Use array 92/// when it is not a prefix to the User object, but allocated at an unrelated 93/// heap address. 94/// Assumes that the User subclass that is determined by this traits class 95/// has an OperandList member of type User::op_iterator. [Note: this is now 96/// trivially satisfied, because User has that member for historic reasons.] 97/// 98/// This is the traits class that is needed when the Use array must be 99/// resizable. 100 101template <unsigned MINARITY = 1> 102struct HungoffOperandTraits { 103 static Use *op_begin(User* U) { 104 return U->OperandList; 105 } 106 static Use *op_end(User* U) { 107 return U->OperandList + U->getNumOperands(); 108 } 109 static unsigned operands(const User *U) { 110 return U->getNumOperands(); 111 } 112 static inline void *allocate(unsigned); // FIXME 113}; 114 115/// Macro for generating in-class operand accessor declarations. 116/// It should only be called in the public section of the interface. 117/// 118#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ 119 public: \ 120 inline VALUECLASS *getOperand(unsigned) const; \ 121 inline void setOperand(unsigned, VALUECLASS*); \ 122 inline op_iterator op_begin(); \ 123 inline const_op_iterator op_begin() const; \ 124 inline op_iterator op_end(); \ 125 inline const_op_iterator op_end() const; \ 126 protected: \ 127 template <unsigned> inline Use &Op(); \ 128 template <unsigned> inline const Use &Op() const; \ 129 public: \ 130 inline unsigned getNumOperands() const 131 132/// Macro for generating out-of-class operand accessor definitions 133#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ 134CLASS::op_iterator CLASS::op_begin() { \ 135 return OperandTraits<CLASS>::op_begin(this); \ 136} \ 137CLASS::const_op_iterator CLASS::op_begin() const { \ 138 return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ 139} \ 140CLASS::op_iterator CLASS::op_end() { \ 141 return OperandTraits<CLASS>::op_end(this); \ 142} \ 143CLASS::const_op_iterator CLASS::op_end() const { \ 144 return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ 145} \ 146VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ 147 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 148 && "getOperand() out of range!"); \ 149 return static_cast<VALUECLASS*>( \ 150 OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \ 151} \ 152void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ 153 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 154 && "setOperand() out of range!"); \ 155 OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ 156} \ 157unsigned CLASS::getNumOperands() const { \ 158 return OperandTraits<CLASS>::operands(this); \ 159} \ 160template <unsigned Idx_nocapture> Use &CLASS::Op() { \ 161 return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \ 162} \ 163template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \ 164 return OperandTraits<CLASS>::op_begin( \ 165 const_cast<CLASS*>(this))[Idx_nocapture]; \ 166} 167 168 169/// Macro for generating out-of-class operand accessor 170/// definitions with casted result 171#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ 172CLASS::op_iterator CLASS::op_begin() { \ 173 return OperandTraits<CLASS>::op_begin(this); \ 174} \ 175CLASS::const_op_iterator CLASS::op_begin() const { \ 176 return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ 177} \ 178CLASS::op_iterator CLASS::op_end() { \ 179 return OperandTraits<CLASS>::op_end(this); \ 180} \ 181CLASS::const_op_iterator CLASS::op_end() const { \ 182 return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ 183} \ 184VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ 185 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 186 && "getOperand() out of range!"); \ 187 return cast<VALUECLASS>( \ 188 OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \ 189} \ 190void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ 191 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 192 && "setOperand() out of range!"); \ 193 OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ 194} \ 195unsigned CLASS::getNumOperands() const { \ 196 return OperandTraits<CLASS>::operands(this); \ 197} \ 198template <unsigned Idx_nocapture> Use &CLASS::Op() { \ 199 return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \ 200} \ 201template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \ 202 return OperandTraits<CLASS>::op_begin( \ 203 const_cast<CLASS*>(this))[Idx_nocapture]; \ 204} 205 206 207} // End llvm namespace 208 209#endif 210