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 20namespace 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 30template <typename SubClass, unsigned ARITY> 31struct FixedNumOperandTraits { 32 static Use *op_begin(SubClass* U) { 33 static_assert( 34 !std::is_polymorphic<SubClass>::value, 35 "adding virtual methods to subclasses of User breaks use lists"); 36 return reinterpret_cast<Use*>(U) - ARITY; 37 } 38 static Use *op_end(SubClass* U) { 39 return reinterpret_cast<Use*>(U); 40 } 41 static unsigned operands(const User*) { 42 return ARITY; 43 } 44}; 45 46//===----------------------------------------------------------------------===// 47// OptionalOperand Trait Class 48//===----------------------------------------------------------------------===// 49 50/// OptionalOperandTraits - when the number of operands may change at runtime. 51/// Naturally it may only decrease, because the allocations may not change. 52 53template <typename SubClass, unsigned ARITY = 1> 54struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { 55 static unsigned operands(const User *U) { 56 return U->getNumOperands(); 57 } 58}; 59 60//===----------------------------------------------------------------------===// 61// VariadicOperand Trait Class 62//===----------------------------------------------------------------------===// 63 64/// VariadicOperandTraits - determine the allocation regime of the Use array 65/// when it is a prefix to the User object, and the number of Use objects is 66/// only known at allocation time. 67 68template <typename SubClass, unsigned MINARITY = 0> 69struct VariadicOperandTraits { 70 static Use *op_begin(SubClass* U) { 71 static_assert( 72 !std::is_polymorphic<SubClass>::value, 73 "adding virtual methods to subclasses of User breaks use lists"); 74 return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); 75 } 76 static Use *op_end(SubClass* U) { 77 return reinterpret_cast<Use*>(U); 78 } 79 static unsigned operands(const User *U) { 80 return U->getNumOperands(); 81 } 82}; 83 84//===----------------------------------------------------------------------===// 85// HungoffOperand Trait Class 86//===----------------------------------------------------------------------===// 87 88/// HungoffOperandTraits - determine the allocation regime of the Use array 89/// when it is not a prefix to the User object, but allocated at an unrelated 90/// heap address. 91/// 92/// This is the traits class that is needed when the Use array must be 93/// resizable. 94 95template <unsigned MINARITY = 1> 96struct HungoffOperandTraits { 97 static Use *op_begin(User* U) { 98 return U->getOperandList(); 99 } 100 static Use *op_end(User* U) { 101 return U->getOperandList() + U->getNumOperands(); 102 } 103 static unsigned operands(const User *U) { 104 return U->getNumOperands(); 105 } 106}; 107 108/// Macro for generating in-class operand accessor declarations. 109/// It should only be called in the public section of the interface. 110/// 111#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ 112 public: \ 113 inline VALUECLASS *getOperand(unsigned) const; \ 114 inline void setOperand(unsigned, VALUECLASS*); \ 115 inline op_iterator op_begin(); \ 116 inline const_op_iterator op_begin() const; \ 117 inline op_iterator op_end(); \ 118 inline const_op_iterator op_end() const; \ 119 protected: \ 120 template <int> inline Use &Op(); \ 121 template <int> inline const Use &Op() const; \ 122 public: \ 123 inline unsigned getNumOperands() const 124 125/// Macro for generating out-of-class operand accessor definitions 126#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ 127CLASS::op_iterator CLASS::op_begin() { \ 128 return OperandTraits<CLASS>::op_begin(this); \ 129} \ 130CLASS::const_op_iterator CLASS::op_begin() const { \ 131 return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ 132} \ 133CLASS::op_iterator CLASS::op_end() { \ 134 return OperandTraits<CLASS>::op_end(this); \ 135} \ 136CLASS::const_op_iterator CLASS::op_end() const { \ 137 return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ 138} \ 139VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ 140 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 141 && "getOperand() out of range!"); \ 142 return cast_or_null<VALUECLASS>( \ 143 OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ 144} \ 145void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ 146 assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 147 && "setOperand() out of range!"); \ 148 OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ 149} \ 150unsigned CLASS::getNumOperands() const { \ 151 return OperandTraits<CLASS>::operands(this); \ 152} \ 153template <int Idx_nocapture> Use &CLASS::Op() { \ 154 return this->OpFrom<Idx_nocapture>(this); \ 155} \ 156template <int Idx_nocapture> const Use &CLASS::Op() const { \ 157 return this->OpFrom<Idx_nocapture>(this); \ 158} 159 160 161} // End llvm namespace 162 163#endif 164