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> struct VariadicOperandTraits { 68 static Use *op_begin(SubClass* U) { 69 static_assert( 70 !std::is_polymorphic<SubClass>::value, 71 "adding virtual methods to subclasses of User breaks use lists"); 72 return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); 73 } 74 static Use *op_end(SubClass* U) { 75 return reinterpret_cast<Use*>(U); 76 } 77 static unsigned operands(const User *U) { 78 return U->getNumOperands(); 79 } 80 }; 81 82 //===----------------------------------------------------------------------===// 83 // HungoffOperand Trait Class 84 //===----------------------------------------------------------------------===// 85 86 /// HungoffOperandTraits - determine the allocation regime of the Use array 87 /// when it is not a prefix to the User object, but allocated at an unrelated 88 /// heap address. 89 /// 90 /// This is the traits class that is needed when the Use array must be 91 /// resizable. 92 93 struct HungoffOperandTraits { 94 static Use *op_begin(User* U) { 95 return U->getHungOffOperands(); 96 } 97 static Use *op_end(User* U) { 98 return U->getHungOffOperands() + 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 cast_or_null<VALUECLASS>( \ 140 OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ 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 } // End llvm namespace 159 160 #endif 161