Home | History | Annotate | Download | only in IR
      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 {
     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 
     53 template <typename SubClass, unsigned ARITY = 1>
     54 struct 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 
     68 template <typename SubClass, unsigned MINARITY = 0>
     69 struct 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 
     95 template <unsigned MINARITY = 1>
     96 struct 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) \
    127 CLASS::op_iterator CLASS::op_begin() { \
    128   return OperandTraits<CLASS>::op_begin(this); \
    129 } \
    130 CLASS::const_op_iterator CLASS::op_begin() const { \
    131   return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
    132 } \
    133 CLASS::op_iterator CLASS::op_end() { \
    134   return OperandTraits<CLASS>::op_end(this); \
    135 } \
    136 CLASS::const_op_iterator CLASS::op_end() const { \
    137   return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
    138 } \
    139 VALUECLASS *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 } \
    145 void 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 } \
    150 unsigned CLASS::getNumOperands() const { \
    151   return OperandTraits<CLASS>::operands(this); \
    152 } \
    153 template <int Idx_nocapture> Use &CLASS::Op() { \
    154   return this->OpFrom<Idx_nocapture>(this); \
    155 } \
    156 template <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