Line data Source code
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 55046199 : return reinterpret_cast<Use*>(U) - ARITY;
37 : }
38 : static Use *op_end(SubClass* U) {
39 : return reinterpret_cast<Use*>(U);
40 : }
41 0 : static unsigned operands(const User*) {
42 0 : return ARITY;
43 : }
44 0 : };
45 0 :
46 : //===----------------------------------------------------------------------===//
47 0 : // OptionalOperand Trait Class
48 0 : //===----------------------------------------------------------------------===//
49 :
50 0 : /// OptionalOperandTraits - when the number of operands may change at runtime.
51 0 : /// Naturally it may only decrease, because the allocations may not change.
52 :
53 0 : template <typename SubClass, unsigned ARITY = 1>
54 0 : struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
55 : static unsigned operands(const User *U) {
56 0 : return U->getNumOperands();
57 0 : }
58 : };
59 0 :
60 0 : //===----------------------------------------------------------------------===//
61 : // VariadicOperand Trait Class
62 0 : //===----------------------------------------------------------------------===//
63 0 :
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 177754227 : 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 27481172 : 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 19568 : 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 361269 : 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
|