//===-- llvm/DerivedTypes.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 declarations of classes that represent "derived 
// types".  These are things like "arrays of x" or "structure of x, y, z" or
// "method returning x taking (y,z) as parameters", etc...
//
// The implementations of these classes live in the Type.cpp file.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DERIVED_TYPES_H
#define LLVM_DERIVED_TYPES_H

#include "llvm/Type.h"
#include <vector>

template<class ValType, class TypeClass> class TypeMap;
class FunctionValType;
class ArrayValType;
class StructValType;
class PointerValType;

class DerivedType : public Type, public AbstractTypeUser {
  /// RefCount - This counts the number of PATypeHolders that are pointing to
  /// this type.  When this number falls to zero, if the type is abstract and
  /// has no AbstractTypeUsers, the type is deleted.
  ///
  mutable unsigned RefCount;
  
  // AbstractTypeUsers - Implement a list of the users that need to be notified
  // if I am a type, and I get resolved into a more concrete type.
  //
  ///// FIXME: kill mutable nonsense when Type's are not const
  mutable std::vector<AbstractTypeUser *> AbstractTypeUsers;

protected:
  DerivedType(PrimitiveID id) : Type("", id), RefCount(0) {
  }
  ~DerivedType() {
    assert(AbstractTypeUsers.empty());
  }

  /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type
  /// that the current type has transitioned from being abstract to being
  /// concrete.
  ///
  void notifyUsesThatTypeBecameConcrete();

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses() = 0;
  
public:

  //===--------------------------------------------------------------------===//
  // Abstract Type handling methods - These types have special lifetimes, which
  // are managed by (add|remove)AbstractTypeUser. See comments in
  // AbstractTypeUser.h for more information.

  // addAbstractTypeUser - Notify an abstract type that there is a new user of
  // it.  This function is called primarily by the PATypeHandle class.
  //
  void addAbstractTypeUser(AbstractTypeUser *U) const {
    assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
    AbstractTypeUsers.push_back(U);
  }

  // removeAbstractTypeUser - Notify an abstract type that a user of the class
  // no longer has a handle to the type.  This function is called primarily by
  // the PATypeHandle class.  When there are no users of the abstract type, it
  // is annihilated, because there is no way to get a reference to it ever
  // again.
  //
  void removeAbstractTypeUser(AbstractTypeUser *U) const;

  // refineAbstractTypeTo - This function is used to when it is discovered that
  // the 'this' abstract type is actually equivalent to the NewType specified.
  // This causes all users of 'this' to switch to reference the more concrete
  // type NewType and for 'this' to be deleted.
  //
  void refineAbstractTypeTo(const Type *NewType);

  void addRef() const {
    assert(isAbstract() && "Cannot add a reference to a non-abstract type!");
    ++RefCount;
  }

  void dropRef() const {
    assert(isAbstract() && "Cannot drop a refernce to a non-abstract type!");
    assert(RefCount && "No objects are currently referencing this object!");

    // If this is the last PATypeHolder using this object, and there are no
    // PATypeHandles using it, the type is dead, delete it now.
    if (--RefCount == 0 && AbstractTypeUsers.empty())
      delete this;
  }


  void dump() const { Value::dump(); }

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




struct FunctionType : public DerivedType {
  typedef std::vector<PATypeHandle> ParamTypes;
  friend class TypeMap<FunctionValType, FunctionType>;
private:
  PATypeHandle ResultType;
  ParamTypes ParamTys;
  bool isVarArgs;

  FunctionType(const FunctionType &);                   // Do not implement
  const FunctionType &operator=(const FunctionType &);  // Do not implement
protected:
  // This should really be private, but it squelches a bogus warning
  // from GCC to make them protected:  warning: `class FunctionType' only 
  // defines private constructors and has no friends

  // Private ctor - Only can be created by a static member...
  FunctionType(const Type *Result, const std::vector<const Type*> &Params, 
               bool IsVarArgs);

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses();

public:
  /// FunctionType::get - This static method is the primary way of constructing
  /// a FunctionType
  static FunctionType *get(const Type *Result,
                           const std::vector<const Type*> &Params,
                           bool isVarArg);

  inline bool isVarArg() const { return isVarArgs; }
  inline const Type *getReturnType() const { return ResultType; }
  inline const ParamTypes &getParamTypes() const { return ParamTys; }

  // Parameter type accessors...
  const Type *getParamType(unsigned i) const { return ParamTys[i]; }

  // getNumParams - Return the number of fixed parameters this function type
  // requires.  This does not consider varargs.
  //
  unsigned getNumParams() const { return ParamTys.size(); }


  virtual const Type *getContainedType(unsigned i) const {
    return i == 0 ? ResultType.get() : ParamTys[i-1].get();
  }
  virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; }

  // Implement the AbstractTypeUser interface.
  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
  virtual void typeBecameConcrete(const DerivedType *AbsTy);
  
  // Methods for support type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const FunctionType *T) { return true; }
  static inline bool classof(const Type *T) {
    return T->getPrimitiveID() == FunctionTyID;
  }
  static inline bool classof(const Value *V) {
    return isa<Type>(V) && classof(cast<Type>(V));
  }
};


// CompositeType - Common super class of ArrayType, StructType, and PointerType
//
class CompositeType : public DerivedType {
protected:
  inline CompositeType(PrimitiveID id) : DerivedType(id) { }
public:

  // getTypeAtIndex - Given an index value into the type, return the type of the
  // element.
  //
  virtual const Type *getTypeAtIndex(const Value *V) const = 0;
  virtual bool indexValid(const Value *V) const = 0;

  // getIndexType - Return the type required of indices for this composite.
  // For structures, this is ubyte, for arrays, this is uint
  //
  virtual const Type *getIndexType() const = 0;


  // Methods for support type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const CompositeType *T) { return true; }
  static inline bool classof(const Type *T) {
    return T->getPrimitiveID() == ArrayTyID || 
           T->getPrimitiveID() == StructTyID ||
           T->getPrimitiveID() == PointerTyID;
  }
  static inline bool classof(const Value *V) {
    return isa<Type>(V) && classof(cast<Type>(V));
  }
};


struct StructType : public CompositeType {
  friend class TypeMap<StructValType, StructType>;
  typedef std::vector<PATypeHandle> ElementTypes;

private:
  ElementTypes ETypes;                              // Element types of struct

  StructType(const StructType &);                   // Do not implement
  const StructType &operator=(const StructType &);  // Do not implement

protected:
  // This should really be private, but it squelches a bogus warning
  // from GCC to make them protected:  warning: `class StructType' only 
  // defines private constructors and has no friends

  // Private ctor - Only can be created by a static member...
  StructType(const std::vector<const Type*> &Types);

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses();
  
public:
  /// StructType::get - This static method is the primary way to create a
  /// StructType.
  static StructType *get(const std::vector<const Type*> &Params);

  inline const ElementTypes &getElementTypes() const { return ETypes; }

  virtual const Type *getContainedType(unsigned i) const { 
    return ETypes[i].get();
  }
  virtual unsigned getNumContainedTypes() const { return ETypes.size(); }

  // getTypeAtIndex - Given an index value into the type, return the type of the
  // element.  For a structure type, this must be a constant value...
  //
  virtual const Type *getTypeAtIndex(const Value *V) const ;
  virtual bool indexValid(const Value *V) const;

  // getIndexType - Return the type required of indices for this composite.
  // For structures, this is ubyte, for arrays, this is uint
  //
  virtual const Type *getIndexType() const { return Type::UByteTy; }

  // Implement the AbstractTypeUser interface.
  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
  virtual void typeBecameConcrete(const DerivedType *AbsTy);

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


// SequentialType - This is the superclass of the array and pointer type
// classes.  Both of these represent "arrays" in memory.  The array type
// represents a specifically sized array, pointer types are unsized/unknown size
// arrays.  SequentialType holds the common features of both, which stem from
// the fact that both lay their components out in memory identically.
//
class SequentialType : public CompositeType {
  SequentialType(const SequentialType &);                  // Do not implement!
  const SequentialType &operator=(const SequentialType &); // Do not implement!
protected:
  PATypeHandle ElementType;

  SequentialType(PrimitiveID TID, const Type *ElType)
    : CompositeType(TID), ElementType(PATypeHandle(ElType, this)) {
  }

public:
  inline const Type *getElementType() const { return ElementType; }

  virtual const Type *getContainedType(unsigned i) const { 
    return ElementType.get();
  }
  virtual unsigned getNumContainedTypes() const { return 1; }

  // getTypeAtIndex - Given an index value into the type, return the type of the
  // element.  For sequential types, there is only one subtype...
  //
  virtual const Type *getTypeAtIndex(const Value *V) const {
    return ElementType.get();
  }
  virtual bool indexValid(const Value *V) const {
    return V->getType() == Type::LongTy;   // Must be a 'long' index
  }

  // getIndexType() - Return the type required of indices for this composite.
  // For structures, this is ubyte, for arrays, this is uint
  //
  virtual const Type *getIndexType() const { return Type::LongTy; }

  // Methods for support type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const SequentialType *T) { return true; }
  static inline bool classof(const Type *T) {
    return T->getPrimitiveID() == ArrayTyID ||
           T->getPrimitiveID() == PointerTyID;
  }
  static inline bool classof(const Value *V) {
    return isa<Type>(V) && classof(cast<Type>(V));
  }
};


class ArrayType : public SequentialType {
  friend class TypeMap<ArrayValType, ArrayType>;
  unsigned NumElements;

  ArrayType(const ArrayType &);                   // Do not implement
  const ArrayType &operator=(const ArrayType &);  // Do not implement
protected:
  // This should really be private, but it squelches a bogus warning
  // from GCC to make them protected:  warning: `class ArrayType' only 
  // defines private constructors and has no friends

  // Private ctor - Only can be created by a static member...
  ArrayType(const Type *ElType, unsigned NumEl);

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses();

public:
  /// ArrayType::get - This static method is the primary way to construct an
  /// ArrayType
  static ArrayType *get(const Type *ElementType, unsigned NumElements);

  inline unsigned    getNumElements() const { return NumElements; }

  // Implement the AbstractTypeUser interface.
  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
  virtual void typeBecameConcrete(const DerivedType *AbsTy);

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



class PointerType : public SequentialType {
  friend class TypeMap<PointerValType, PointerType>;
  PointerType(const PointerType &);                   // Do not implement
  const PointerType &operator=(const PointerType &);  // Do not implement
protected:
  // This should really be private, but it squelches a bogus warning
  // from GCC to make them protected:  warning: `class PointerType' only 
  // defines private constructors and has no friends

  // Private ctor - Only can be created by a static member...
  PointerType(const Type *ElType);

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses();
public:
  /// PointerType::get - This is the only way to construct a new pointer type.
  static PointerType *get(const Type *ElementType);

  // Implement the AbstractTypeUser interface.
  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
  virtual void typeBecameConcrete(const DerivedType *AbsTy);

  // Implement support type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const PointerType *T) { return true; }
  static inline bool classof(const Type *T) {
    return T->getPrimitiveID() == PointerTyID;
  }
  static inline bool classof(const Value *V) {
    return isa<Type>(V) && classof(cast<Type>(V));
  }
};


class OpaqueType : public DerivedType {
  OpaqueType(const OpaqueType &);                   // DO NOT IMPLEMENT
  const OpaqueType &operator=(const OpaqueType &);  // DO NOT IMPLEMENT
protected:
  // This should really be private, but it squelches a bogus warning
  // from GCC to make them protected:  warning: `class OpaqueType' only 
  // defines private constructors and has no friends

  // Private ctor - Only can be created by a static member...
  OpaqueType();

  // dropAllTypeUses - When this (abstract) type is resolved to be equal to
  // another (more concrete) type, we must eliminate all references to other
  // types, to avoid some circular reference problems.
  virtual void dropAllTypeUses() {
    // FIXME: THIS IS NOT AN ABSTRACT TYPE USER!
  }  // No type uses

public:
  // OpaqueType::get - Static factory method for the OpaqueType class...
  static OpaqueType *get() {
    return new OpaqueType();           // All opaque types are distinct
  }

  // Implement the AbstractTypeUser interface.
  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
    abort();   // FIXME: this is not really an AbstractTypeUser!
  }
  virtual void typeBecameConcrete(const DerivedType *AbsTy) {
    abort();   // FIXME: this is not really an AbstractTypeUser!
  }

  // Implement support for type inquiry through isa, cast, and dyn_cast:
  static inline bool classof(const OpaqueType *T) { return true; }
  static inline bool classof(const Type *T) {
    return T->getPrimitiveID() == OpaqueTyID;
  }
  static inline bool classof(const Value *V) {
    return isa<Type>(V) && classof(cast<Type>(V));
  }
};


// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class.
// These are defined here because they MUST be inlined, yet are dependent on 
// the definition of the Type class.  Of course Type derives from Value, which
// contains an AbstractTypeUser instance, so there is no good way to factor out
// the code.  Hence this bit of uglyness.
//
inline void PATypeHandle::addUser() {
  assert(Ty && "Type Handle has a null type!");
  if (Ty->isAbstract())
    cast<DerivedType>(Ty)->addAbstractTypeUser(User);
}
inline void PATypeHandle::removeUser() {
  if (Ty->isAbstract())
    cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
}

inline void PATypeHandle::removeUserFromConcrete() {
  if (!Ty->isAbstract())
    cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
}

// Define inline methods for PATypeHolder...

inline void PATypeHolder::addRef() {
  if (Ty->isAbstract())
    cast<DerivedType>(Ty)->addRef();
}

inline void PATypeHolder::dropRef() {
  if (Ty->isAbstract())
    cast<DerivedType>(Ty)->dropRef();
}

/// get - This implements the forwarding part of the union-find algorithm for
/// abstract types.  Before every access to the Type*, we check to see if the
/// type we are pointing to is forwarding to a new type.  If so, we drop our
/// reference to the type.
inline const Type* PATypeHolder::get() const {
  const Type *NewTy = Ty->getForwardedType();
  if (!NewTy) return Ty;
  return *const_cast<PATypeHolder*>(this) = NewTy;
}

#endif
