1249259Sdim//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file defines the traits classes that are handy for enforcing the correct
11249259Sdim// layout of various User subclasses. It also provides the means for accessing
12249259Sdim// the operands in the most efficient manner.
13249259Sdim//
14249259Sdim
15249259Sdim#ifndef LLVM_IR_OPERANDTRAITS_H
16249259Sdim#define LLVM_IR_OPERANDTRAITS_H
17249259Sdim
18249259Sdim#include "llvm/IR/User.h"
19249259Sdim
20249259Sdimnamespace llvm {
21249259Sdim
22249259Sdim//===----------------------------------------------------------------------===//
23249259Sdim//                          FixedNumOperand Trait Class
24249259Sdim//===----------------------------------------------------------------------===//
25249259Sdim
26249259Sdim/// FixedNumOperandTraits - determine the allocation regime of the Use array
27249259Sdim/// when it is a prefix to the User object, and the number of Use objects is
28249259Sdim/// known at compile time.
29249259Sdim
30249259Sdimtemplate <typename SubClass, unsigned ARITY>
31249259Sdimstruct FixedNumOperandTraits {
32249259Sdim  static Use *op_begin(SubClass* U) {
33249259Sdim    return reinterpret_cast<Use*>(U) - ARITY;
34249259Sdim  }
35249259Sdim  static Use *op_end(SubClass* U) {
36249259Sdim    return reinterpret_cast<Use*>(U);
37249259Sdim  }
38249259Sdim  static unsigned operands(const User*) {
39249259Sdim    return ARITY;
40249259Sdim  }
41249259Sdim};
42249259Sdim
43249259Sdim//===----------------------------------------------------------------------===//
44249259Sdim//                          OptionalOperand Trait Class
45249259Sdim//===----------------------------------------------------------------------===//
46249259Sdim
47249259Sdim/// OptionalOperandTraits - when the number of operands may change at runtime.
48249259Sdim/// Naturally it may only decrease, because the allocations may not change.
49249259Sdim
50249259Sdimtemplate <typename SubClass, unsigned ARITY = 1>
51249259Sdimstruct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
52249259Sdim  static unsigned operands(const User *U) {
53249259Sdim    return U->getNumOperands();
54249259Sdim  }
55249259Sdim};
56249259Sdim
57249259Sdim//===----------------------------------------------------------------------===//
58249259Sdim//                          VariadicOperand Trait Class
59249259Sdim//===----------------------------------------------------------------------===//
60249259Sdim
61249259Sdim/// VariadicOperandTraits - determine the allocation regime of the Use array
62249259Sdim/// when it is a prefix to the User object, and the number of Use objects is
63249259Sdim/// only known at allocation time.
64249259Sdim
65249259Sdimtemplate <typename SubClass, unsigned MINARITY = 0>
66249259Sdimstruct VariadicOperandTraits {
67249259Sdim  static Use *op_begin(SubClass* U) {
68249259Sdim    return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
69249259Sdim  }
70249259Sdim  static Use *op_end(SubClass* U) {
71249259Sdim    return reinterpret_cast<Use*>(U);
72249259Sdim  }
73249259Sdim  static unsigned operands(const User *U) {
74249259Sdim    return U->getNumOperands();
75249259Sdim  }
76249259Sdim};
77249259Sdim
78249259Sdim//===----------------------------------------------------------------------===//
79249259Sdim//                          HungoffOperand Trait Class
80249259Sdim//===----------------------------------------------------------------------===//
81249259Sdim
82249259Sdim/// HungoffOperandTraits - determine the allocation regime of the Use array
83249259Sdim/// when it is not a prefix to the User object, but allocated at an unrelated
84249259Sdim/// heap address.
85249259Sdim/// Assumes that the User subclass that is determined by this traits class
86249259Sdim/// has an OperandList member of type User::op_iterator. [Note: this is now
87249259Sdim/// trivially satisfied, because User has that member for historic reasons.]
88249259Sdim///
89249259Sdim/// This is the traits class that is needed when the Use array must be
90249259Sdim/// resizable.
91249259Sdim
92249259Sdimtemplate <unsigned MINARITY = 1>
93249259Sdimstruct HungoffOperandTraits {
94249259Sdim  static Use *op_begin(User* U) {
95249259Sdim    return U->OperandList;
96249259Sdim  }
97249259Sdim  static Use *op_end(User* U) {
98249259Sdim    return U->OperandList + U->getNumOperands();
99249259Sdim  }
100249259Sdim  static unsigned operands(const User *U) {
101249259Sdim    return U->getNumOperands();
102249259Sdim  }
103249259Sdim};
104249259Sdim
105249259Sdim/// Macro for generating in-class operand accessor declarations.
106249259Sdim/// It should only be called in the public section of the interface.
107249259Sdim///
108249259Sdim#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
109249259Sdim  public: \
110249259Sdim  inline VALUECLASS *getOperand(unsigned) const; \
111249259Sdim  inline void setOperand(unsigned, VALUECLASS*); \
112249259Sdim  inline op_iterator op_begin(); \
113249259Sdim  inline const_op_iterator op_begin() const; \
114249259Sdim  inline op_iterator op_end(); \
115249259Sdim  inline const_op_iterator op_end() const; \
116249259Sdim  protected: \
117249259Sdim  template <int> inline Use &Op(); \
118249259Sdim  template <int> inline const Use &Op() const; \
119249259Sdim  public: \
120249259Sdim  inline unsigned getNumOperands() const
121249259Sdim
122249259Sdim/// Macro for generating out-of-class operand accessor definitions
123249259Sdim#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
124249259SdimCLASS::op_iterator CLASS::op_begin() { \
125249259Sdim  return OperandTraits<CLASS>::op_begin(this); \
126249259Sdim} \
127249259SdimCLASS::const_op_iterator CLASS::op_begin() const { \
128249259Sdim  return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
129249259Sdim} \
130249259SdimCLASS::op_iterator CLASS::op_end() { \
131249259Sdim  return OperandTraits<CLASS>::op_end(this); \
132249259Sdim} \
133249259SdimCLASS::const_op_iterator CLASS::op_end() const { \
134249259Sdim  return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
135249259Sdim} \
136249259SdimVALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
137249259Sdim  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
138249259Sdim         && "getOperand() out of range!"); \
139249259Sdim  return cast_or_null<VALUECLASS>( \
140249259Sdim    OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
141249259Sdim} \
142249259Sdimvoid CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
143249259Sdim  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
144249259Sdim         && "setOperand() out of range!"); \
145249259Sdim  OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
146249259Sdim} \
147249259Sdimunsigned CLASS::getNumOperands() const { \
148249259Sdim  return OperandTraits<CLASS>::operands(this); \
149249259Sdim} \
150249259Sdimtemplate <int Idx_nocapture> Use &CLASS::Op() { \
151249259Sdim  return this->OpFrom<Idx_nocapture>(this); \
152249259Sdim} \
153249259Sdimtemplate <int Idx_nocapture> const Use &CLASS::Op() const { \
154249259Sdim  return this->OpFrom<Idx_nocapture>(this); \
155249259Sdim}
156249259Sdim
157249259Sdim
158249259Sdim} // End llvm namespace
159249259Sdim
160249259Sdim#endif
161