//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the Type class.  For more "Type" type
// stuff, look in DerivedTypes.h.
//
// Note that instances of the Type class are immutable: once they are created,
// they are never changed.  Also note that only one instance of a particular 
// type is ever created.  Thus seeing if two types are equal is a matter of 
// doing a trivial pointer comparison.
//
// Types, once allocated, are never free'd.
//
// Opaque types are simple derived types with no state.  There may be many
// different Opaque type objects floating around, but two are only considered
// identical if they are pointer equals of each other.  This allows us to have 
// two opaque types that end up resolving to different concrete types later.
//
// Opaque types are also kinda wierd and scary and different because they have
// to keep a list of uses of the type.  When, through linking, parsing, or
// bytecode reading, they become resolved, they need to find and update all
// users of the unknown type, causing them to reference a new, more concrete
// type.  Opaque types are deleted when their use list dwindles to zero users.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TYPE_H
#define LLVM_TYPE_H

#include "llvm/Value.h"
#include "Support/GraphTraits.h"
#include "Support/iterator"

class DerivedType;
class FunctionType;
class ArrayType;
class PointerType;
class StructType;
class OpaqueType;

struct Type : public Value {
  ///===-------------------------------------------------------------------===//
  /// Definitions of all of the base types for the Type system.  Based on this
  /// value, you can cast to a "DerivedType" subclass (see DerivedTypes.h)
  /// Note: If you add an element to this, you need to add an element to the 
  /// Type::getPrimitiveType function, or else things will break!
  ///
  enum PrimitiveID {
    VoidTyID = 0  , BoolTyID,           //  0, 1: Basics...
    UByteTyID     , SByteTyID,          //  2, 3: 8 bit types...
    UShortTyID    , ShortTyID,          //  4, 5: 16 bit types...
    UIntTyID      , IntTyID,            //  6, 7: 32 bit types...
    ULongTyID     , LongTyID,           //  8, 9: 64 bit types...

    FloatTyID     , DoubleTyID,         // 10,11: Floating point types...

    TypeTyID,                           // 12   : Type definitions
    LabelTyID     ,                     // 13   : Labels... 

    // Derived types... see DerivedTypes.h file...
    // Make sure FirstDerivedTyID stays up to date!!!
    FunctionTyID  , StructTyID,         // Functions... Structs...
    ArrayTyID     , PointerTyID,        // Array... pointer...
    OpaqueTyID,                         // Opaque type instances...
    //PackedTyID  ,                     // SIMD 'packed' format... TODO
    //...

    NumPrimitiveIDs,                    // Must remain as last defined ID
    FirstDerivedTyID = FunctionTyID,
  };

private:
  PrimitiveID ID;        // The current base type of this type...
  unsigned    UID;       // The unique ID number for this class
  bool        Abstract;  // True if type contains an OpaqueType

  const Type *getForwardedTypeInternal() const;
protected:
  /// ctor is protected, so only subclasses can create Type objects...
  Type(const std::string &Name, PrimitiveID id);
  virtual ~Type() {}

  /// setName - Associate the name with this type in the symbol table, but don't
  /// set the local name to be equal specified name.
  ///
  virtual void setName(const std::string &Name, SymbolTable *ST = 0);

  /// Types can become nonabstract later, if they are refined.
  ///
  inline void setAbstract(bool Val) { Abstract = Val; }

  /// isTypeAbstract - This method is used to calculate the Abstract bit.
  ///
  bool isTypeAbstract();

  /// ForwardType - This field is used to implement the union find scheme for
  /// abstract types.  When types are refined to other types, this field is set
  /// to the more refined type.  Only abstract types can be forwarded.
  mutable const Type *ForwardType;

public:
  virtual void print(std::ostream &O) const;

  //===--------------------------------------------------------------------===//
  // Property accessors for dealing with types... Some of these virtual methods
  // are defined in private classes defined in Type.cpp for primitive types.
  //

  /// getPrimitiveID - Return the base type of the type.  This will return one
  /// of the PrimitiveID enum elements defined above.
  ///
  inline PrimitiveID getPrimitiveID() const { return ID; }

  /// getUniqueID - Returns the UID of the type.  This can be thought of as a
  /// small integer version of the pointer to the type class.  Two types that
  /// are structurally different have different UIDs.  This can be used for
  /// indexing types into an array.
  ///
  inline unsigned getUniqueID() const { return UID; }

  /// getDescription - Return the string representation of the type...
  const std::string &getDescription() const;

  /// isSigned - Return whether an integral numeric type is signed.  This is
  /// true for SByteTy, ShortTy, IntTy, LongTy.  Note that this is not true for
  /// Float and Double.
  //
  virtual bool isSigned() const { return 0; }
  
  /// isUnsigned - Return whether a numeric type is unsigned.  This is not quite
  /// the complement of isSigned... nonnumeric types return false as they do
  /// with isSigned.  This returns true for UByteTy, UShortTy, UIntTy, and
  /// ULongTy
  /// 
  virtual bool isUnsigned() const { return 0; }

  /// isInteger - Equilivent to isSigned() || isUnsigned(), but with only a
  /// single virtual function invocation.
  ///
  virtual bool isInteger() const { return 0; }

  /// isIntegral - Returns true if this is an integral type, which is either
  /// BoolTy or one of the Integer types.
  ///
  bool isIntegral() const { return isInteger() || this == BoolTy; }

  /// isFloatingPoint - Return true if this is one of the two floating point
  /// types
  bool isFloatingPoint() const { return ID == FloatTyID || ID == DoubleTyID; }

  /// isAbstract - True if the type is either an Opaque type, or is a derived
  /// type that includes an opaque type somewhere in it.  
  ///
  inline bool isAbstract() const { return Abstract; }

  /// isLosslesslyConvertibleTo - Return true if this type can be converted to
  /// 'Ty' without any reinterpretation of bits.  For example, uint to int.
  ///
  bool isLosslesslyConvertibleTo(const Type *Ty) const;


  /// Here are some useful little methods to query what type derived types are
  /// Note that all other types can just compare to see if this == Type::xxxTy;
  ///
  inline bool isPrimitiveType() const { return ID < FirstDerivedTyID;  }
  inline bool isDerivedType()   const { return ID >= FirstDerivedTyID; }

  /// isFirstClassType - Return true if the value is holdable in a register.
  inline bool isFirstClassType() const {
    return isPrimitiveType() || ID == PointerTyID;
  }

  /// isSized - Return true if it makes sense to take the size of this type.  To
  /// get the actual size for a particular target, it is reasonable to use the
  /// TargetData subsystem to do this.
  ///
  bool isSized() const {
    return ID != VoidTyID && ID != TypeTyID &&
           ID != FunctionTyID && ID != LabelTyID && ID != OpaqueTyID;
  }

  /// getPrimitiveSize - Return the basic size of this type if it is a primative
  /// type.  These are fixed by LLVM and are not target dependent.  This will
  /// return zero if the type does not have a size or is not a primitive type.
  ///
  unsigned getPrimitiveSize() const;

  /// getForwaredType - Return the type that this type has been resolved to if
  /// it has been resolved to anything.  This is used to implement the
  /// union-find algorithm for type resolution.
  const Type *getForwardedType() const {
    if (!ForwardType) return 0;
    return getForwardedTypeInternal();
  }

  //===--------------------------------------------------------------------===//
  // Type Iteration support
  //
  class TypeIterator;
  typedef TypeIterator subtype_iterator;
  inline subtype_iterator subtype_begin() const;   // DEFINED BELOW
  inline subtype_iterator subtype_end() const;     // DEFINED BELOW

  /// getContainedType - This method is used to implement the type iterator
  /// (defined a the end of the file).  For derived types, this returns the
  /// types 'contained' in the derived type.
  ///
  virtual const Type *getContainedType(unsigned i) const {
    assert(0 && "No contained types!");
    return 0;
  }

  /// getNumContainedTypes - Return the number of types in the derived type
  virtual unsigned getNumContainedTypes() const { return 0; }

  //===--------------------------------------------------------------------===//
  // Static members exported by the Type class itself.  Useful for getting
  // instances of Type.
  //

  /// getPrimitiveType/getUniqueIDType - Return a type based on an identifier.
  static const Type *getPrimitiveType(PrimitiveID IDNumber);
  static const Type *getUniqueIDType(unsigned UID);

  //===--------------------------------------------------------------------===//
  // These are the builtin types that are always available...
  //
  static Type *VoidTy , *BoolTy;
  static Type *SByteTy, *UByteTy,
              *ShortTy, *UShortTy,
              *IntTy  , *UIntTy, 
              *LongTy , *ULongTy;
  static Type *FloatTy, *DoubleTy;

  static Type *TypeTy , *LabelTy;

  /// Methods for support type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const Type *T) { return true; }
  static inline bool classof(const Value *V) {
    return V->getValueType() == Value::TypeVal;
  }

#include "llvm/Type.def"

private:
  class TypeIterator : public bidirectional_iterator<const Type, ptrdiff_t> {
    const Type * const Ty;
    unsigned Idx;

    typedef TypeIterator _Self;
  public:
    TypeIterator(const Type *ty, unsigned idx) : Ty(ty), Idx(idx) {}
    ~TypeIterator() {}

    const _Self &operator=(const _Self &RHS) {
      assert(Ty == RHS.Ty && "Cannot assign from different types!");
      Idx = RHS.Idx;
      return *this;
    }
    
    bool operator==(const _Self& x) const { return Idx == x.Idx; }
    bool operator!=(const _Self& x) const { return !operator==(x); }
    
    pointer operator*() const { return Ty->getContainedType(Idx); }
    pointer operator->() const { return operator*(); }
    
    _Self& operator++() { ++Idx; return *this; } // Preincrement
    _Self operator++(int) { // Postincrement
      _Self tmp = *this; ++*this; return tmp; 
    }
    
    _Self& operator--() { --Idx; return *this; }  // Predecrement
    _Self operator--(int) { // Postdecrement
      _Self tmp = *this; --*this; return tmp;
    }
  };
};

inline Type::TypeIterator Type::subtype_begin() const {
  return TypeIterator(this, 0);
}

inline Type::TypeIterator Type::subtype_end() const {
  return TypeIterator(this, getNumContainedTypes());
}


// Provide specializations of GraphTraits to be able to treat a type as a 
// graph of sub types...

template <> struct GraphTraits<Type*> {
  typedef Type NodeType;
  typedef Type::subtype_iterator ChildIteratorType;

  static inline NodeType *getEntryNode(Type *T) { return T; }
  static inline ChildIteratorType child_begin(NodeType *N) { 
    return N->subtype_begin(); 
  }
  static inline ChildIteratorType child_end(NodeType *N) { 
    return N->subtype_end();
  }
};

template <> struct GraphTraits<const Type*> {
  typedef const Type NodeType;
  typedef Type::subtype_iterator ChildIteratorType;

  static inline NodeType *getEntryNode(const Type *T) { return T; }
  static inline ChildIteratorType child_begin(NodeType *N) { 
    return N->subtype_begin(); 
  }
  static inline ChildIteratorType child_end(NodeType *N) { 
    return N->subtype_end();
  }
};

template <> inline bool isa_impl<PointerType, Type>(const Type &Ty) { 
  return Ty.getPrimitiveID() == Type::PointerTyID;
}

#endif
