mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
163 lines
5.8 KiB
C++
163 lines
5.8 KiB
C++
//===-- 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
|