1249259Sdim//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file defines the traits classes that are handy for enforcing the correct 11249259Sdim// layout of various User subclasses. It also provides the means for accessing 12249259Sdim// the operands in the most efficient manner. 13249259Sdim// 14249259Sdim 15249259Sdim#ifndef LLVM_IR_OPERANDTRAITS_H 16249259Sdim#define LLVM_IR_OPERANDTRAITS_H 17249259Sdim 18249259Sdim#include "llvm/IR/User.h" 19249259Sdim 20249259Sdimnamespace llvm { 21249259Sdim 22249259Sdim//===----------------------------------------------------------------------===// 23249259Sdim// FixedNumOperand Trait Class 24249259Sdim//===----------------------------------------------------------------------===// 25249259Sdim 26249259Sdim/// FixedNumOperandTraits - determine the allocation regime of the Use array 27249259Sdim/// when it is a prefix to the User object, and the number of Use objects is 28249259Sdim/// known at compile time. 29249259Sdim 30249259Sdimtemplate <typename SubClass, unsigned ARITY> 31249259Sdimstruct FixedNumOperandTraits { 32249259Sdim static Use *op_begin(SubClass* U) { 33249259Sdim return reinterpret_cast<Use*>(U) - ARITY; 34249259Sdim } 35249259Sdim static Use *op_end(SubClass* U) { 36249259Sdim return reinterpret_cast<Use*>(U); 37249259Sdim } 38249259Sdim static unsigned operands(const User*) { 39249259Sdim return ARITY; 40249259Sdim } 41249259Sdim}; 42249259Sdim 43249259Sdim//===----------------------------------------------------------------------===// 44249259Sdim// OptionalOperand Trait Class 45249259Sdim//===----------------------------------------------------------------------===// 46249259Sdim 47249259Sdim/// OptionalOperandTraits - when the number of operands may change at runtime. 48249259Sdim/// Naturally it may only decrease, because the allocations may not change. 49249259Sdim 50249259Sdimtemplate <typename SubClass, unsigned ARITY = 1> 51249259Sdimstruct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { 52249259Sdim static unsigned operands(const User *U) { 53249259Sdim return U->getNumOperands(); 54249259Sdim } 55249259Sdim}; 56249259Sdim 57249259Sdim//===----------------------------------------------------------------------===// 58249259Sdim// VariadicOperand Trait Class 59249259Sdim//===----------------------------------------------------------------------===// 60249259Sdim 61249259Sdim/// VariadicOperandTraits - determine the allocation regime of the Use array 62249259Sdim/// when it is a prefix to the User object, and the number of Use objects is 63249259Sdim/// only known at allocation time. 64249259Sdim 65249259Sdimtemplate <typename SubClass, unsigned MINARITY = 0> 66249259Sdimstruct VariadicOperandTraits { 67249259Sdim static Use *op_begin(SubClass* U) { 68249259Sdim return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); 69249259Sdim } 70249259Sdim static Use *op_end(SubClass* U) { 71249259Sdim return reinterpret_cast<Use*>(U); 72249259Sdim } 73249259Sdim static unsigned operands(const User *U) { 74249259Sdim return U->getNumOperands(); 75249259Sdim } 76249259Sdim}; 77249259Sdim 78249259Sdim//===----------------------------------------------------------------------===// 79249259Sdim// HungoffOperand Trait Class 80249259Sdim//===----------------------------------------------------------------------===// 81249259Sdim 82249259Sdim/// HungoffOperandTraits - determine the allocation regime of the Use array 83249259Sdim/// when it is not a prefix to the User object, but allocated at an unrelated 84249259Sdim/// heap address. 85249259Sdim/// Assumes that the User subclass that is determined by this traits class 86249259Sdim/// has an OperandList member of type User::op_iterator. [Note: this is now 87249259Sdim/// trivially satisfied, because User has that member for historic reasons.] 88249259Sdim/// 89249259Sdim/// This is the traits class that is needed when the Use array must be 90249259Sdim/// resizable. 91249259Sdim 92249259Sdimtemplate <unsigned MINARITY = 1> 93249259Sdimstruct HungoffOperandTraits { 94249259Sdim static Use *op_begin(User* U) { 95249259Sdim return U->OperandList; 96249259Sdim } 97249259Sdim static Use *op_end(User* U) { 98249259Sdim return U->OperandList + U->getNumOperands(); 99249259Sdim } 100249259Sdim static unsigned operands(const User *U) { 101249259Sdim return U->getNumOperands(); 102249259Sdim } 103249259Sdim}; 104249259Sdim 105249259Sdim/// Macro for generating in-class operand accessor declarations. 106249259Sdim/// It should only be called in the public section of the interface. 107249259Sdim/// 108249259Sdim#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ 109249259Sdim public: \ 110249259Sdim inline VALUECLASS *getOperand(unsigned) const; \ 111249259Sdim inline void setOperand(unsigned, VALUECLASS*); \ 112249259Sdim inline op_iterator op_begin(); \ 113249259Sdim inline const_op_iterator op_begin() const; \ 114249259Sdim inline op_iterator op_end(); \ 115249259Sdim inline const_op_iterator op_end() const; \ 116249259Sdim protected: \ 117249259Sdim template <int> inline Use &Op(); \ 118249259Sdim template <int> inline const Use &Op() const; \ 119249259Sdim public: \ 120249259Sdim inline unsigned getNumOperands() const 121249259Sdim 122249259Sdim/// Macro for generating out-of-class operand accessor definitions 123249259Sdim#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ 124249259SdimCLASS::op_iterator CLASS::op_begin() { \ 125249259Sdim return OperandTraits<CLASS>::op_begin(this); \ 126249259Sdim} \ 127249259SdimCLASS::const_op_iterator CLASS::op_begin() const { \ 128249259Sdim return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ 129249259Sdim} \ 130249259SdimCLASS::op_iterator CLASS::op_end() { \ 131249259Sdim return OperandTraits<CLASS>::op_end(this); \ 132249259Sdim} \ 133249259SdimCLASS::const_op_iterator CLASS::op_end() const { \ 134249259Sdim return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ 135249259Sdim} \ 136249259SdimVALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ 137249259Sdim assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 138249259Sdim && "getOperand() out of range!"); \ 139249259Sdim return cast_or_null<VALUECLASS>( \ 140249259Sdim OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ 141249259Sdim} \ 142249259Sdimvoid CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ 143249259Sdim assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ 144249259Sdim && "setOperand() out of range!"); \ 145249259Sdim OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ 146249259Sdim} \ 147249259Sdimunsigned CLASS::getNumOperands() const { \ 148249259Sdim return OperandTraits<CLASS>::operands(this); \ 149249259Sdim} \ 150249259Sdimtemplate <int Idx_nocapture> Use &CLASS::Op() { \ 151249259Sdim return this->OpFrom<Idx_nocapture>(this); \ 152249259Sdim} \ 153249259Sdimtemplate <int Idx_nocapture> const Use &CLASS::Op() const { \ 154249259Sdim return this->OpFrom<Idx_nocapture>(this); \ 155249259Sdim} 156249259Sdim 157249259Sdim 158249259Sdim} // End llvm namespace 159249259Sdim 160249259Sdim#endif 161