llvm.org GIT mirror llvm / master include / llvm / IR / OperandTraits.h
master

Tree @master (Download .tar.gz)

OperandTraits.h @master

315b333
efe6536
6b54768
 
 
efe6536
 
 
 
 
 
 
 
674be02
 
efe6536
0b8c9a8
efe6536
 
 
 
138acfe
efe6536
 
07252fd
 
 
 
67c619b
efe6536
67c619b
816047d
 
 
efe6536
 
67c619b
efe6536
 
 
 
 
 
 
 
138acfe
efe6536
 
138acfe
 
 
67c619b
 
efe6536
 
 
 
 
 
 
 
 
07252fd
 
 
 
67c619b
efe6536
67c619b
816047d
 
 
67c619b
efe6536
67c619b
efe6536
 
 
 
 
 
 
 
 
 
 
07252fd
 
 
 
 
 
 
efe6536
 
 
cff40fc
efe6536
 
cff40fc
efe6536
 
 
 
 
 
 
 
 
 
 
 
 
6cd093b
 
 
 
efe6536
20cb462
 
efe6536
 
 
 
 
6cd093b
 
 
 
 
 
 
 
 
 
 
 
efe6536
 
 
ff7782b
 
efe6536
 
 
 
 
 
 
 
 
20cb462
 
efe6536
20cb462
 
efe6536
 
 
cd52a7a
efe6536
 
//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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_IR_OPERANDTRAITS_H
#define LLVM_IR_OPERANDTRAITS_H

#include "llvm/IR/User.h"

namespace llvm {

//===----------------------------------------------------------------------===//
//                          FixedNumOperand Trait Class
//===----------------------------------------------------------------------===//

/// FixedNumOperandTraits - determine the allocation regime of the Use array
/// when it is a prefix to the User object, and the number of Use objects is
/// known at compile time.

template <typename SubClass, unsigned ARITY>
struct FixedNumOperandTraits {
  static Use *op_begin(SubClass* U) {
    static_assert(
        !std::is_polymorphic<SubClass>::value,
        "adding virtual methods to subclasses of User breaks use lists");
    return reinterpret_cast<Use*>(U) - ARITY;
  }
  static Use *op_end(SubClass* U) {
    return reinterpret_cast<Use*>(U);
  }
  static unsigned operands(const User*) {
    return ARITY;
  }
};

//===----------------------------------------------------------------------===//
//                          OptionalOperand Trait Class
//===----------------------------------------------------------------------===//

/// OptionalOperandTraits - when the number of operands may change at runtime.
/// Naturally it may only decrease, because the allocations may not change.

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

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

/// VariadicOperandTraits - determine the allocation regime of the Use array
/// when it is a prefix to the User object, and the number of Use objects is
/// only known at allocation time.

template <typename SubClass, unsigned MINARITY = 0>
struct VariadicOperandTraits {
  static Use *op_begin(SubClass* U) {
    static_assert(
        !std::is_polymorphic<SubClass>::value,
        "adding virtual methods to subclasses of User breaks use lists");
    return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
  }
  static Use *op_end(SubClass* U) {
    return reinterpret_cast<Use*>(U);
  }
  static unsigned operands(const User *U) {
    return U->getNumOperands();
  }
};

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

/// HungoffOperandTraits - determine the allocation regime of the Use array
/// when it is not a prefix to the User object, but allocated at an unrelated
/// heap address.
///
/// This is the traits class that is needed when the Use array must be
/// resizable.

template <unsigned MINARITY = 1>
struct HungoffOperandTraits {
  static Use *op_begin(User* U) {
    return U->getOperandList();
  }
  static Use *op_end(User* U) {
    return U->getOperandList() + U->getNumOperands();
  }
  static unsigned operands(const User *U) {
    return U->getNumOperands();
  }
};

/// 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*); \
  inline op_iterator op_begin(); \
  inline const_op_iterator op_begin() const; \
  inline op_iterator op_end(); \
  inline const_op_iterator op_end() const; \
  protected: \
  template <int> inline Use &Op(); \
  template <int> 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) \
CLASS::op_iterator CLASS::op_begin() { \
  return OperandTraits<CLASS>::op_begin(this); \
} \
CLASS::const_op_iterator CLASS::op_begin() const { \
  return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
} \
CLASS::op_iterator CLASS::op_end() { \
  return OperandTraits<CLASS>::op_end(this); \
} \
CLASS::const_op_iterator CLASS::op_end() const { \
  return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
} \
VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
  assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
         && "getOperand() out of range!"); \
  return cast_or_null<VALUECLASS>( \
    OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
} \
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 <int Idx_nocapture> Use &CLASS::Op() { \
  return this->OpFrom<Idx_nocapture>(this); \
} \
template <int Idx_nocapture> const Use &CLASS::Op() const { \
  return this->OpFrom<Idx_nocapture>(this); \
}


} // End llvm namespace

#endif