Add a 'normalize' method to the Triple class, which takes a mucked up
[oota-llvm.git] / include / llvm / AbstractTypeUser.h
index 7c6f429dc607a66d74853b564c24b4e09a4665db..81f5c5c7680d87ef4b6f8b0fe76cc3963923287d 100644 (file)
@@ -1,26 +1,25 @@
-//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface -----*- C++ -*--=//
+//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===//
 //
-// The AbstractTypeUser class is an interface to be implemented by classes who
-// could possible use an abstract type.  Abstract types are denoted by the
-// isAbstract flag set to true in the Type class.  These are classes that
-// contain an Opaque type in their structure somehow.
+//                     The LLVM Compiler Infrastructure
 //
-// Classes must implement this interface so that they may be notified when an
-// abstract type is resolved.  Abstract types may be resolved into more concrete
-// types through: linking, parsing, and bytecode reading.  When this happens,
-// all of the users of the type must be updated to reference the new, more
-// concrete type.  They are notified through the AbstractTypeUser interface.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
-// In addition to this, AbstractTypeUsers must keep the use list of the
-// potentially abstract type that they reference up-to-date.  To do this in a
-// nice, transparent way, the PATypeHandle class is used to hold "Potentially
-// Abstract Types", and keep the use list of the abstract types up-to-date.
+//===----------------------------------------------------------------------===//
+//
+// This file declares the AbstractTypeUser class.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_ABSTRACT_TYPE_USER_H
 #define LLVM_ABSTRACT_TYPE_USER_H
 
+#if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H)
+#error Do not include this file directly.  Include Type.h instead.
+#error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method
+#error PATypeHolder::dropRef() correctly otherwise.
+#endif
+
 // This is the "master" include for <cassert> Whether this file needs it or not,
 // it must always include <cassert> for the files which include
 // llvm/AbstractTypeUser.h
 //
 #include <cassert>
 
+namespace llvm {
+
+class Value;
 class Type;
 class DerivedType;
-
+template<typename T> struct simplify_type;
+
+/// The AbstractTypeUser class is an interface to be implemented by classes who
+/// could possibly use an abstract type.  Abstract types are denoted by the
+/// isAbstract flag set to true in the Type class.  These are classes that
+/// contain an Opaque type in their structure somewhere.
+///
+/// Classes must implement this interface so that they may be notified when an
+/// abstract type is resolved.  Abstract types may be resolved into more 
+/// concrete types through: linking, parsing, and bitcode reading.  When this 
+/// happens, all of the users of the type must be updated to reference the new,
+/// more concrete type.  They are notified through the AbstractTypeUser 
+/// interface.
+///
+/// In addition to this, AbstractTypeUsers must keep the use list of the
+/// potentially abstract type that they reference up-to-date.  To do this in a
+/// nice, transparent way, the PATypeHandle class is used to hold "Potentially
+/// Abstract Types", and keep the use list of the abstract types up-to-date.
+/// @brief LLVM Abstract Type User Representation
 class AbstractTypeUser {
 protected:
-  virtual ~AbstractTypeUser() {}                        // Derive from me
+  virtual ~AbstractTypeUser();                        // Derive from me
+
+  /// setType - It's normally not possible to change a Value's type in place,
+  /// but an AbstractTypeUser subclass that knows what its doing can be
+  /// permitted to do so with care.
+  void setType(Value *V, const Type *NewTy);
+
 public:
 
-  // refineAbstractType - The callback method invoked when an abstract type
-  // has been found to be more concrete.  A class must override this method to
-  // update its internal state to reference NewType instead of OldType.  Soon
-  // after this method is invoked, OldType shall be deleted, so referencing it
-  // is quite unwise.
-  //
-  // Another case that is important to consider is when a type is refined, but
-  // stays in the same place in memory.  In this case OldTy will equal NewTy.
-  // This callback just notifies ATU's that the underlying structure of the type
-  // has changed... but any previously used properties are still valid.
-  //
-  // Note that it is possible to refine a type with parameters OldTy==NewTy, and
-  // OldTy is no longer abstract.  In this case, abstract type users should
-  // release their hold on a type, because it went from being abstract to
-  // concrete.
-  //
+  /// refineAbstractType - The callback method invoked when an abstract type is
+  /// resolved to another type.  An object must override this method to update
+  /// its internal state to reference NewType instead of OldType.
+  ///
   virtual void refineAbstractType(const DerivedType *OldTy,
-                                 const Type *NewTy) = 0;
+                                  const Type *NewTy) = 0;
+
+  /// The other case which AbstractTypeUsers must be aware of is when a type
+  /// makes the transition from being abstract (where it has clients on its
+  /// AbstractTypeUsers list) to concrete (where it does not).  This method
+  /// notifies ATU's when this occurs for a type.
+  ///
+  virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0;
+
   // for debugging...
   virtual void dump() const = 0;
 };
 
 
-// PATypeHandle - Handle to a Type subclass.  This class is parameterized so
-// that users can have handles to FunctionType's that are still specialized, for
-// example.  This class is a simple class used to keep the use list of abstract
-// types up-to-date.
-//
+/// PATypeHandle - Handle to a Type subclass.  This class is used to keep the
+/// use list of abstract types up-to-date.
+///
 class PATypeHandle {
   const Type *Ty;
   AbstractTypeUser * const User;
@@ -76,7 +96,7 @@ class PATypeHandle {
   void removeUser();
 public:
   // ctor - Add use to type if abstract.  Note that Ty must not be null
-  inline PATypeHandle(const Type *ty, AbstractTypeUser *user) 
+  inline PATypeHandle(const Type *ty, AbstractTypeUser *user)
     : Ty(ty), User(user) {
     addUser();
   }
@@ -90,17 +110,17 @@ public:
   inline ~PATypeHandle() { removeUser(); }
 
   // Automatic casting operator so that the handle may be used naturally
-  inline operator const Type *() const { return Ty; }
-  inline const Type *get() const { return Ty; }
+  inline operator Type *() const { return const_cast<Type*>(Ty); }
+  inline Type *get() const { return const_cast<Type*>(Ty); }
 
   // operator= - Allow assignment to handle
-  inline const Type *operator=(const Type *ty) {
+  inline Type *operator=(const Type *ty) {
     if (Ty != ty) {   // Ensure we don't accidentally drop last ref to Ty
       removeUser();
       Ty = ty;
       addUser();
     }
-    return Ty;
+    return get();
   }
 
   // operator= - Allow assignment to handle
@@ -114,54 +134,72 @@ public:
 
   // operator-> - Allow user to dereference handle naturally...
   inline const Type *operator->() const { return Ty; }
-
-  // removeUserFromConcrete - This function should be called when the User is
-  // notified that our type is refined... and the type is being refined to
-  // itself, which is now a concrete type.  When a type becomes concrete like
-  // this, we MUST remove ourself from the AbstractTypeUser list, even though
-  // the type is apparently concrete.
-  //
-  void removeUserFromConcrete();
 };
 
 
-// PATypeHolder - Holder class for a potentially abstract type.  This functions
-// as both a handle (as above) and an AbstractTypeUser.  It uses the callback to
-// keep its pointer member updated to the current version of the type.
-//
-struct PATypeHolder : public AbstractTypeUser, public PATypeHandle {
-  inline PATypeHolder(const Type *ty) : PATypeHandle(ty, this) {}
-  inline PATypeHolder(const PATypeHolder &T)
-    : AbstractTypeUser(T), PATypeHandle(T, this) {}
-
-  // refineAbstractType - All we do is update our PATypeHandle member to point
-  // to the new type.
-  //
-  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
-    assert(get() == (const Type*)OldTy && "Can't refine to unknown value!");
-
-    // Check to see if the type just became concrete.  If so, we have to
-    // removeUser to get off its AbstractTypeUser list
-    removeUserFromConcrete();
-
-    if ((const Type*)OldTy != NewTy)
-      PATypeHandle::operator=(NewTy);
+/// PATypeHolder - Holder class for a potentially abstract type.  This uses
+/// efficient union-find techniques to handle dynamic type resolution.  Unless
+/// you need to do custom processing when types are resolved, you should always
+/// use PATypeHolders in preference to PATypeHandles.
+///
+class PATypeHolder {
+  mutable const Type *Ty;
+  void destroy();
+public:
+  PATypeHolder() : Ty(0) {}
+  PATypeHolder(const Type *ty) : Ty(ty) {
+    addRef();
   }
-
-  // operator= - Allow assignment to handle
-  inline const Type *operator=(const Type *ty) {
-    return PATypeHandle::operator=(ty);
+  PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) {
+    addRef();
   }
 
+  ~PATypeHolder() { dropRef(); }
+
+  operator Type *() const { return get(); }
+  Type *get() const;
+
+  // operator-> - Allow user to dereference handle naturally...
+  Type *operator->() const { return get(); }
+
   // operator= - Allow assignment to handle
-  inline const Type *operator=(const PATypeHandle &T) {
-    return PATypeHandle::operator=(T);
+  Type *operator=(const Type *ty) {
+    if (Ty != ty) {   // Don't accidentally drop last ref to Ty.
+      dropRef();
+      Ty = ty;
+      addRef();
+    }
+    return get();
   }
-  inline const Type *operator=(const PATypeHolder &H) {
-    return PATypeHandle::operator=(H);
+  Type *operator=(const PATypeHolder &H) {
+    return operator=(H.Ty);
   }
 
-  void dump() const;
+  /// getRawType - This should only be used to implement the vmcore library.
+  ///
+  const Type *getRawType() const { return Ty; }
+
+private:
+  void addRef();
+  void dropRef();
+  friend class TypeMapBase;
+};
+
+// simplify_type - Allow clients to treat uses just like values when using
+// casting operators.
+template<> struct simplify_type<PATypeHolder> {
+  typedef const Type* SimpleType;
+  static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
+    return static_cast<SimpleType>(Val.get());
+  }
+};
+template<> struct simplify_type<const PATypeHolder> {
+  typedef const Type* SimpleType;
+  static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
+    return static_cast<SimpleType>(Val.get());
+  }
 };
+  
+} // End llvm namespace
 
 #endif