Turn conditions like x<Y|z==q into multiple blocks.
[oota-llvm.git] / include / llvm / Type.h
index dd2fd9b1132d8c2bd14d05c533b5d7340ad29e87..dab6c127cd1694e08888d82266048f67ec48a8cf 100644 (file)
@@ -6,38 +6,17 @@
 // 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, unless they are an abstract type
-// that is resolved to a more concrete type.
-//
-// 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 weird 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 "AbstractTypeUser.h"
+#include "llvm/AbstractTypeUser.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/iterator"
+#include <string>
 #include <vector>
 
 namespace llvm {
@@ -49,8 +28,39 @@ class OpaqueType;
 class PointerType;
 class StructType;
 class PackedType;
+class TypeMapBase;
 
-class Type {
+/// This file contains the declaration of the Type class.  For more "Type" type
+/// stuff, look in DerivedTypes.h.
+///
+/// The 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. To enforce that no two equal instances
+/// are created, Type instances can only be created via static factory methods 
+/// in class Type and in derived classes.
+/// 
+/// Once allocated, Types are never free'd, unless they are an abstract type
+/// that is resolved to a more concrete type.
+/// 
+/// Types themself don't have a name, and can be named either by:
+/// - using SymbolTable instance, typically from some Module,
+/// - using convenience methods in the Module class (which uses module's 
+///    SymbolTable too).
+///
+/// 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 weird 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.
+///
+/// @brief Root of type hierarchy
+class Type : public AbstractTypeUser {
 public:
   ///===-------------------------------------------------------------------===//
   /// Definitions of all of the base types for the Type system.  Based on this
@@ -83,7 +93,7 @@ public:
 
 private:
   TypeID   ID : 8;    // The current base type of this type.
-  bool     Abstract;  // True if type contains an OpaqueType
+  bool     Abstract : 1;  // True if type contains an OpaqueType
 
   /// 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
@@ -94,17 +104,16 @@ private:
 
   const Type *getForwardedTypeInternal() const;
 protected:
-  Type(const std::string& Name, TypeID id);
-  virtual ~Type() {}
+  Type(const char *Name, TypeID id);
+  Type(TypeID id) : ID(id), Abstract(false), RefCount(0), ForwardType(0) {}
+  virtual ~Type() {
+    assert(AbstractTypeUsers.empty());
+  }
 
   /// Types can become nonabstract later, if they are refined.
   ///
   inline void setAbstract(bool Val) { Abstract = Val; }
 
-  // PromoteAbstractToConcrete - This is an internal method used to calculate
-  // change "Abstract" from true to false when types are refined.
-  void PromoteAbstractToConcrete();
-
   unsigned getRefCount() const { return RefCount; }
 
   /// ForwardType - This field is used to implement the union find scheme for
@@ -121,6 +130,10 @@ protected:
   /// not contain any elements (most are derived).
   std::vector<PATypeHandle> ContainedTys;
 
+  /// 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.
+  ///
+  mutable std::vector<AbstractTypeUser *> AbstractTypeUsers;
 public:
   void print(std::ostream &O) const;
 
@@ -172,6 +185,10 @@ public:
   /// types
   bool isFloatingPoint() const { return ID == FloatTyID || ID == DoubleTyID; }
 
+  /// isFPOrFPVector - Return true if this is a FP type or a vector of FP types.
+  ///
+  bool isFPOrFPVector() const;
+  
   /// isAbstract - True if the type is either an Opaque type, or is a derived
   /// type that includes an opaque type somewhere in it.
   ///
@@ -227,6 +244,14 @@ public:
   /// getSignedVersion - If this is an integer type, return the signed variant
   /// of this type.  For example uint -> int.
   const Type *getSignedVersion() const;
+  
+  /// getIntegralTypeMask - Return a bitmask with ones set for all of the bits
+  /// that can be set by an unsigned version of this type.  This is 0xFF for
+  /// sbyte/ubyte, 0xFFFF for shorts, etc.
+  uint64_t getIntegralTypeMask() const {
+    assert(isIntegral() && "This only works for integral types!");
+    return ~uint64_t(0UL) >> (64-getPrimitiveSizeInBits());
+  }
 
   /// getForwaredType - Return the type that this type has been resolved to if
   /// it has been resolved to anything.  This is used to implement the
@@ -295,15 +320,6 @@ public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Type *T) { return true; }
 
-  // Virtual methods used by callbacks below.  These should only be implemented
-  // in the DerivedType class.
-  virtual void addAbstractTypeUser(AbstractTypeUser *U) const {
-    abort(); // Only on derived types!
-  }
-  virtual void removeAbstractTypeUser(AbstractTypeUser *U) const {
-    abort(); // Only on derived types!
-  }
-
   void addRef() const {
     assert(isAbstract() && "Cannot add a reference to a non-abstract type!");
     ++RefCount;
@@ -315,14 +331,25 @@ public:
 
     // 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)
-      RefCountIsZero();
+    if (--RefCount == 0 && AbstractTypeUsers.empty())
+      delete this;
   }
-
-  /// clearAllTypeMaps - This method frees all internal memory used by the
-  /// type subsystem, which can be used in environments where this memory is
-  /// otherwise reported as a leak.
-  static void clearAllTypeMaps();
+  
+  /// 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;
 
 private:
   /// isSizedDerivedType - Derived types like structures and arrays are sized
@@ -330,22 +357,20 @@ private:
   /// their size is relatively uncommon, move this operation out of line.
   bool isSizedDerivedType() const;
 
-  virtual void RefCountIsZero() const {
-    abort(); // only on derived types!
-  }
+  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
+  virtual void typeBecameConcrete(const DerivedType *AbsTy);
 
+protected:
+  // PromoteAbstractToConcrete - This is an internal method used to calculate
+  // change "Abstract" from true to false when types are refined.
+  void PromoteAbstractToConcrete();
+  friend class TypeMapBase;
 };
 
 //===----------------------------------------------------------------------===//
 // 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.
-//
-// In the long term, Type should not derive from Value, allowing
-// AbstractTypeUser.h to #include Type.h, allowing us to eliminate this
-// nastyness entirely.
+// the definition of the Type class.
 //
 inline void PATypeHandle::addUser() {
   assert(Ty && "Type Handle has a null type!");
@@ -369,18 +394,6 @@ inline void PATypeHolder::dropRef() {
     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 Type* PATypeHolder::get() const {
-  const Type *NewTy = Ty->getForwardedType();
-  if (!NewTy) return const_cast<Type*>(Ty);
-  return *const_cast<PATypeHolder*>(this) = NewTy;
-}
-
-
 
 //===----------------------------------------------------------------------===//
 // Provide specializations of GraphTraits to be able to treat a type as a