Home | History | Annotate | Line # | Download | only in IR
      1 //===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file defines the traits classes that are handy for enforcing the correct
     10 // layout of various User subclasses. It also provides the means for accessing
     11 // the operands in the most efficient manner.
     12 //
     13 
     14 #ifndef LLVM_IR_OPERANDTRAITS_H
     15 #define LLVM_IR_OPERANDTRAITS_H
     16 
     17 #include "llvm/IR/User.h"
     18 
     19 namespace llvm {
     20 
     21 //===----------------------------------------------------------------------===//
     22 //                          FixedNumOperand Trait Class
     23 //===----------------------------------------------------------------------===//
     24 
     25 /// FixedNumOperandTraits - determine the allocation regime of the Use array
     26 /// when it is a prefix to the User object, and the number of Use objects is
     27 /// known at compile time.
     28 
     29 template <typename SubClass, unsigned ARITY>
     30 struct FixedNumOperandTraits {
     31   static Use *op_begin(SubClass* U) {
     32     static_assert(
     33         !std::is_polymorphic<SubClass>::value,
     34         "adding virtual methods to subclasses of User breaks use lists");
     35     return reinterpret_cast<Use*>(U) - ARITY;
     36   }
     37   static Use *op_end(SubClass* U) {
     38     return reinterpret_cast<Use*>(U);
     39   }
     40   static unsigned operands(const User*) {
     41     return ARITY;
     42   }
     43 };
     44 
     45 //===----------------------------------------------------------------------===//
     46 //                          OptionalOperand Trait Class
     47 //===----------------------------------------------------------------------===//
     48 
     49 /// OptionalOperandTraits - when the number of operands may change at runtime.
     50 /// Naturally it may only decrease, because the allocations may not change.
     51 
     52 template <typename SubClass, unsigned ARITY = 1>
     53 struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
     54   static unsigned operands(const User *U) {
     55     return U->getNumOperands();
     56   }
     57 };
     58 
     59 //===----------------------------------------------------------------------===//
     60 //                          VariadicOperand Trait Class
     61 //===----------------------------------------------------------------------===//
     62 
     63 /// VariadicOperandTraits - determine the allocation regime of the Use array
     64 /// when it is a prefix to the User object, and the number of Use objects is
     65 /// only known at allocation time.
     66 
     67 template <typename SubClass, unsigned MINARITY = 0>
     68 struct VariadicOperandTraits {
     69   static Use *op_begin(SubClass* U) {
     70     static_assert(
     71         !std::is_polymorphic<SubClass>::value,
     72         "adding virtual methods to subclasses of User breaks use lists");
     73     return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
     74   }
     75   static Use *op_end(SubClass* U) {
     76     return reinterpret_cast<Use*>(U);
     77   }
     78   static unsigned operands(const User *U) {
     79     return U->getNumOperands();
     80   }
     81 };
     82 
     83 //===----------------------------------------------------------------------===//
     84 //                          HungoffOperand Trait Class
     85 //===----------------------------------------------------------------------===//
     86 
     87 /// HungoffOperandTraits - determine the allocation regime of the Use array
     88 /// when it is not a prefix to the User object, but allocated at an unrelated
     89 /// heap address.
     90 ///
     91 /// This is the traits class that is needed when the Use array must be
     92 /// resizable.
     93 
     94 template <unsigned MINARITY = 1>
     95 struct HungoffOperandTraits {
     96   static Use *op_begin(User* U) {
     97     return U->getOperandList();
     98   }
     99   static Use *op_end(User* U) {
    100     return U->getOperandList() + U->getNumOperands();
    101   }
    102   static unsigned operands(const User *U) {
    103     return U->getNumOperands();
    104   }
    105 };
    106 
    107 /// Macro for generating in-class operand accessor declarations.
    108 /// It should only be called in the public section of the interface.
    109 ///
    110 #define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
    111   public: \
    112   inline VALUECLASS *getOperand(unsigned) const; \
    113   inline void setOperand(unsigned, VALUECLASS*); \
    114   inline op_iterator op_begin(); \
    115   inline const_op_iterator op_begin() const; \
    116   inline op_iterator op_end(); \
    117   inline const_op_iterator op_end() const; \
    118   protected: \
    119   template <int> inline Use &Op(); \
    120   template <int> inline const Use &Op() const; \
    121   public: \
    122   inline unsigned getNumOperands() const
    123 
    124 /// Macro for generating out-of-class operand accessor definitions
    125 #define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
    126 CLASS::op_iterator CLASS::op_begin() { \
    127   return OperandTraits<CLASS>::op_begin(this); \
    128 } \
    129 CLASS::const_op_iterator CLASS::op_begin() const { \
    130   return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
    131 } \
    132 CLASS::op_iterator CLASS::op_end() { \
    133   return OperandTraits<CLASS>::op_end(this); \
    134 } \
    135 CLASS::const_op_iterator CLASS::op_end() const { \
    136   return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
    137 } \
    138 VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
    139   assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
    140          && "getOperand() out of range!"); \
    141   return cast_or_null<VALUECLASS>( \
    142     OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
    143 } \
    144 void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
    145   assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
    146          && "setOperand() out of range!"); \
    147   OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
    148 } \
    149 unsigned CLASS::getNumOperands() const { \
    150   return OperandTraits<CLASS>::operands(this); \
    151 } \
    152 template <int Idx_nocapture> Use &CLASS::Op() { \
    153   return this->OpFrom<Idx_nocapture>(this); \
    154 } \
    155 template <int Idx_nocapture> const Use &CLASS::Op() const { \
    156   return this->OpFrom<Idx_nocapture>(this); \
    157 }
    158 
    159 
    160 } // End llvm namespace
    161 
    162 #endif
    163