summaryrefslogtreecommitdiff
path: root/include/llvm/OperandTraits.h
blob: 3811927e57b9787aca23e539801fd57cca672c4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//===-- llvm/OperandTraits.h - OperandTraits class definition ---------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the traits classes that are handy for enforcing the correct
// layout of various User subclasses. It also provides the means for accessing
// the operands in the most efficient manner.
//

#ifndef LLVM_OPERAND_TRAITS_H
#define LLVM_OPERAND_TRAITS_H

#include "llvm/User.h"

namespace llvm {

//===----------------------------------------------------------------------===//
//                          FixedNumOperands Trait Class
//===----------------------------------------------------------------------===//

template <unsigned ARITY>
struct FixedNumOperandTraits {
  static Use *op_begin(User* U) {
    return reinterpret_cast<Use*>(U) - ARITY;
  }
  static Use *op_end(User* U) {
    return reinterpret_cast<Use*>(U);
  }
  static unsigned operands(const User*) {
    return ARITY;
  }
  struct prefix {
    Use Ops[ARITY];
    prefix(); // DO NOT IMPLEMENT
  };
  template <class U>
  struct Layout {
    struct overlay : prefix, U {
      overlay(); // DO NOT IMPLEMENT
    };
  };
  static inline void *allocate(unsigned); // FIXME
};

//===----------------------------------------------------------------------===//
//                          OptionalOperands Trait Class
//===----------------------------------------------------------------------===//

template <unsigned ARITY = 1>
struct OptionalOperandTraits : FixedNumOperandTraits<ARITY> {
  static unsigned operands(const User *U) {
    return U->getNumOperands();
  }
};

//===----------------------------------------------------------------------===//
//                          VariadicOperand Trait Class
//===----------------------------------------------------------------------===//

template <unsigned MINARITY = 0>
struct VariadicOperandTraits {
  static Use *op_begin(User* U) {
    return reinterpret_cast<Use*>(U) - U->getNumOperands();
  }
  static Use *op_end(User* U) {
    return reinterpret_cast<Use*>(U);
  }
  static unsigned operands(const User *U) {
    return U->getNumOperands();
  }
  static inline void *allocate(unsigned); // FIXME
};

//===----------------------------------------------------------------------===//
//                          HungoffOperand Trait Class
//===----------------------------------------------------------------------===//

template <unsigned MINARITY = 1>
struct HungoffOperandTraits {
  static Use *op_begin(User* U) {
    return U->OperandList;
  }
  static Use *op_end(User* U) {
    return U->OperandList + U->getNumOperands();
  }
  static unsigned operands(const User *U) {
    return U->getNumOperands();
  }
  static inline void *allocate(unsigned); // FIXME
};

/// Macro for generating in-class operand accessor declarations.
/// It should only be called in the public section of the interface.
///
#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
  public: \
  inline VALUECLASS *getOperand(unsigned) const; \
  inline void setOperand(unsigned, VALUECLASS*); \
  protected: \
  template <unsigned> inline Use &Op(); \
  template <unsigned> inline const Use &Op() const; \
  public: \
  inline unsigned getNumOperands() const

/// Macro for generating out-of-class operand accessor definitions
#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
         && "getOperand() out of range!"); \
  return static_cast<VALUECLASS*>( \
    OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
} \
void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
         && "setOperand() out of range!"); \
  OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
} \
unsigned CLASS::getNumOperands() const { \
  return OperandTraits<CLASS>::operands(this);  \
} \
template <unsigned Idx_nocapture> Use &CLASS::Op() { \
  return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \
} \
template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \
  return OperandTraits<CLASS>::op_begin( \
    const_cast<CLASS*>(this))[Idx_nocapture]; \
}


/// Macro for generating out-of-class operand accessor
/// definitions with casted result
#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
         && "getOperand() out of range!"); \
  return cast<VALUECLASS>( \
    OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
} \
void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
         && "setOperand() out of range!"); \
  OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
} \
unsigned CLASS::getNumOperands() const { \
  return OperandTraits<CLASS>::operands(this); \
} \
template <unsigned Idx_nocapture> Use &CLASS::Op() { \
  return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \
} \
template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \
  return OperandTraits<CLASS>::op_begin( \
    const_cast<CLASS*>(this))[Idx_nocapture]; \
}


} // End llvm namespace

#endif