OperandTraits.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. #ifndef LLVM_IR_OPERANDTRAITS_H
  14. #define LLVM_IR_OPERANDTRAITS_H
  15. #include "llvm/IR/User.h"
  16. namespace llvm {
  17. //===----------------------------------------------------------------------===//
  18. // FixedNumOperand Trait Class
  19. //===----------------------------------------------------------------------===//
  20. /// FixedNumOperandTraits - determine the allocation regime of the Use array
  21. /// when it is a prefix to the User object, and the number of Use objects is
  22. /// known at compile time.
  23. template <typename SubClass, unsigned ARITY>
  24. struct FixedNumOperandTraits {
  25. static Use *op_begin(SubClass* U) {
  26. static_assert(
  27. !std::is_polymorphic<SubClass>::value,
  28. "adding virtual methods to subclasses of User breaks use lists");
  29. return reinterpret_cast<Use*>(U) - ARITY;
  30. }
  31. static Use *op_end(SubClass* U) {
  32. return reinterpret_cast<Use*>(U);
  33. }
  34. static unsigned operands(const User*) {
  35. return ARITY;
  36. }
  37. };
  38. //===----------------------------------------------------------------------===//
  39. // OptionalOperand Trait Class
  40. //===----------------------------------------------------------------------===//
  41. /// OptionalOperandTraits - when the number of operands may change at runtime.
  42. /// Naturally it may only decrease, because the allocations may not change.
  43. template <typename SubClass, unsigned ARITY = 1>
  44. struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
  45. static unsigned operands(const User *U) {
  46. return U->getNumOperands();
  47. }
  48. };
  49. //===----------------------------------------------------------------------===//
  50. // VariadicOperand Trait Class
  51. //===----------------------------------------------------------------------===//
  52. /// VariadicOperandTraits - determine the allocation regime of the Use array
  53. /// when it is a prefix to the User object, and the number of Use objects is
  54. /// only known at allocation time.
  55. template <typename SubClass, unsigned MINARITY = 0>
  56. struct VariadicOperandTraits {
  57. static Use *op_begin(SubClass* U) {
  58. static_assert(
  59. !std::is_polymorphic<SubClass>::value,
  60. "adding virtual methods to subclasses of User breaks use lists");
  61. return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
  62. }
  63. static Use *op_end(SubClass* U) {
  64. return reinterpret_cast<Use*>(U);
  65. }
  66. static unsigned operands(const User *U) {
  67. return U->getNumOperands();
  68. }
  69. };
  70. //===----------------------------------------------------------------------===//
  71. // HungoffOperand Trait Class
  72. //===----------------------------------------------------------------------===//
  73. /// HungoffOperandTraits - determine the allocation regime of the Use array
  74. /// when it is not a prefix to the User object, but allocated at an unrelated
  75. /// heap address.
  76. ///
  77. /// This is the traits class that is needed when the Use array must be
  78. /// resizable.
  79. template <unsigned MINARITY = 1>
  80. struct HungoffOperandTraits {
  81. static Use *op_begin(User* U) {
  82. return U->getOperandList();
  83. }
  84. static Use *op_end(User* U) {
  85. return U->getOperandList() + U->getNumOperands();
  86. }
  87. static unsigned operands(const User *U) {
  88. return U->getNumOperands();
  89. }
  90. };
  91. /// Macro for generating in-class operand accessor declarations.
  92. /// It should only be called in the public section of the interface.
  93. ///
  94. #define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
  95. public: \
  96. inline VALUECLASS *getOperand(unsigned) const; \
  97. inline void setOperand(unsigned, VALUECLASS*); \
  98. inline op_iterator op_begin(); \
  99. inline const_op_iterator op_begin() const; \
  100. inline op_iterator op_end(); \
  101. inline const_op_iterator op_end() const; \
  102. protected: \
  103. template <int> inline Use &Op(); \
  104. template <int> inline const Use &Op() const; \
  105. public: \
  106. inline unsigned getNumOperands() const
  107. /// Macro for generating out-of-class operand accessor definitions
  108. #define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
  109. CLASS::op_iterator CLASS::op_begin() { \
  110. return OperandTraits<CLASS>::op_begin(this); \
  111. } \
  112. CLASS::const_op_iterator CLASS::op_begin() const { \
  113. return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
  114. } \
  115. CLASS::op_iterator CLASS::op_end() { \
  116. return OperandTraits<CLASS>::op_end(this); \
  117. } \
  118. CLASS::const_op_iterator CLASS::op_end() const { \
  119. return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
  120. } \
  121. VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
  122. assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
  123. && "getOperand() out of range!"); \
  124. return cast_or_null<VALUECLASS>( \
  125. OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
  126. } \
  127. void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
  128. assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
  129. && "setOperand() out of range!"); \
  130. OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
  131. } \
  132. unsigned CLASS::getNumOperands() const { \
  133. return OperandTraits<CLASS>::operands(this); \
  134. } \
  135. template <int Idx_nocapture> Use &CLASS::Op() { \
  136. return this->OpFrom<Idx_nocapture>(this); \
  137. } \
  138. template <int Idx_nocapture> const Use &CLASS::Op() const { \
  139. return this->OpFrom<Idx_nocapture>(this); \
  140. }
  141. } // End llvm namespace
  142. #endif