Home | History | Annotate | Download | only in llvm
      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 
     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 {
     32   static Use *op_begin(SubClass* U) {
     33     return reinterpret_cast<Use*>(U) - ARITY;
     34   }
     35   static Use *op_end(SubClass* U) {
     36     return reinterpret_cast<Use*>(U);
     37   }
     38   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> {
     52   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 {
     67   static Use *op_begin(SubClass* U) {
     68     return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
     69   }
     70   static Use *op_end(SubClass* U) {
     71     return reinterpret_cast<Use*>(U);
     72   }
     73   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 {
     94   static Use *op_begin(User* U) {
     95     return U->OperandList;
     96   }
     97   static Use *op_end(User* U) {
     98     return U->OperandList + U->getNumOperands();
     99   }
    100   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 static_cast<VALUECLASS*>( \
    140     OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
    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 /// Macro for generating out-of-class operand accessor
    159 /// definitions with casted result
    160 #define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
    161 CLASS::op_iterator CLASS::op_begin() { \
    162   return OperandTraits<CLASS>::op_begin(this); \
    163 } \
    164 CLASS::const_op_iterator CLASS::op_begin() const { \
    165   return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
    166 } \
    167 CLASS::op_iterator CLASS::op_end() { \
    168   return OperandTraits<CLASS>::op_end(this); \
    169 } \
    170 CLASS::const_op_iterator CLASS::op_end() const { \
    171   return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
    172 } \
    173 VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
    174   assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
    175          && "getOperand() out of range!"); \
    176   return cast<VALUECLASS>( \
    177     OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
    178 } \
    179 void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
    180   assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
    181          && "setOperand() out of range!"); \
    182   OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
    183 } \
    184 unsigned CLASS::getNumOperands() const { \
    185   return OperandTraits<CLASS>::operands(this); \
    186 } \
    187 template <int Idx_nocapture> Use &CLASS::Op() { \
    188   return this->OpFrom<Idx_nocapture>(this); \
    189 } \
    190 template <int Idx_nocapture> const Use &CLASS::Op() const { \
    191   return this->OpFrom<Idx_nocapture>(this); \
    192 }
    193 
    194 
    195 } // End llvm namespace
    196 
    197 #endif
    198