Line data Source code
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 20498 : 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 20498 : 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 60997 : static Use *op_end(SubClass* U) {
76 60997 : 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->getHungOffOperands();
98 : }
99 : static Use *op_end(User* U) {
100 : return U->getHungOffOperands() + 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
|