//===-- 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 struct FixedNumOperandTraits { static Use *op_begin(User* U) { return reinterpret_cast(U) - ARITY; } static Use *op_end(User* U) { return reinterpret_cast(U); } static unsigned operands(const User*) { return ARITY; } struct prefix { Use Ops[ARITY]; prefix(); // DO NOT IMPLEMENT }; template struct Layout { struct overlay : prefix, U { overlay(); // DO NOT IMPLEMENT }; }; static inline void *allocate(unsigned); // FIXME }; //===----------------------------------------------------------------------===// // OptionalOperands Trait Class //===----------------------------------------------------------------------===// template struct OptionalOperandTraits : FixedNumOperandTraits { static unsigned operands(const User *U) { return U->getNumOperands(); } }; //===----------------------------------------------------------------------===// // VariadicOperand Trait Class //===----------------------------------------------------------------------===// template struct VariadicOperandTraits { static Use *op_begin(User* U) { return reinterpret_cast(U) - U->getNumOperands(); } static Use *op_end(User* U) { return reinterpret_cast(U); } static unsigned operands(const User *U) { return U->getNumOperands(); } static inline void *allocate(unsigned); // FIXME }; //===----------------------------------------------------------------------===// // HungoffOperand Trait Class //===----------------------------------------------------------------------===// template 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 #define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ inline VALUECLASS *getOperand(unsigned) const; \ inline void setOperand(unsigned, VALUECLASS*); \ inline unsigned getNumOperands() const; \ template inline Use &Op(); \ template inline const Use &Op() 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::operands(this) && "getOperand() out of range!"); \ return static_cast(OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ } \ void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ assert(i_nocapture < OperandTraits::operands(this) && "setOperand() out of range!"); \ OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ } \ unsigned CLASS::getNumOperands() const { return OperandTraits::operands(this); } \ template Use &CLASS::Op() { \ return OperandTraits::op_begin(this)[Idx_nocapture]; \ } \ template const Use &CLASS::Op() const { \ return OperandTraits::op_begin(const_cast(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::operands(this) && "getOperand() out of range!"); \ return cast(OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ } \ void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ assert(i_nocapture < OperandTraits::operands(this) && "setOperand() out of range!"); \ OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ } \ unsigned CLASS::getNumOperands() const { return OperandTraits::operands(this); } \ template Use &CLASS::Op() { \ return OperandTraits::op_begin(this)[Idx_nocapture]; \ } \ template const Use &CLASS::Op() const { \ return OperandTraits::op_begin(const_cast(this))[Idx_nocapture]; \ } } // End llvm namespace #endif