LLVM API Documentation

AbstractTypeUser.h

Go to the documentation of this file.
00001 //===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file declares the AbstractTypeUser class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ABSTRACT_TYPE_USER_H
00015 #define LLVM_ABSTRACT_TYPE_USER_H
00016 
00017 #if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H)
00018 #error Do not include this file directly.  Include Type.h instead.
00019 #error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method
00020 #error PATypeHolder::dropRef() correctly otherwise.
00021 #endif
00022 
00023 // This is the "master" include for <cassert> Whether this file needs it or not,
00024 // it must always include <cassert> for the files which include
00025 // llvm/AbstractTypeUser.h
00026 //
00027 // In this way, most every LLVM source file will have access to the assert()
00028 // macro without having to #include <cassert> directly.
00029 //
00030 #include <cassert>
00031 
00032 namespace llvm {
00033 
00034 class Type;
00035 class DerivedType;
00036 template<typename T> struct simplify_type;
00037 
00038 /// The AbstractTypeUser class is an interface to be implemented by classes who
00039 /// could possibly use an abstract type.  Abstract types are denoted by the
00040 /// isAbstract flag set to true in the Type class.  These are classes that
00041 /// contain an Opaque type in their structure somewhere.
00042 ///
00043 /// Classes must implement this interface so that they may be notified when an
00044 /// abstract type is resolved.  Abstract types may be resolved into more 
00045 /// concrete types through: linking, parsing, and bitcode reading.  When this 
00046 /// happens, all of the users of the type must be updated to reference the new,
00047 /// more concrete type.  They are notified through the AbstractTypeUser 
00048 /// interface.
00049 ///
00050 /// In addition to this, AbstractTypeUsers must keep the use list of the
00051 /// potentially abstract type that they reference up-to-date.  To do this in a
00052 /// nice, transparent way, the PATypeHandle class is used to hold "Potentially
00053 /// Abstract Types", and keep the use list of the abstract types up-to-date.
00054 /// @brief LLVM Abstract Type User Representation
00055 class AbstractTypeUser {
00056 protected:
00057   virtual ~AbstractTypeUser();                        // Derive from me
00058 public:
00059 
00060   /// refineAbstractType - The callback method invoked when an abstract type is
00061   /// resolved to another type.  An object must override this method to update
00062   /// its internal state to reference NewType instead of OldType.
00063   ///
00064   virtual void refineAbstractType(const DerivedType *OldTy,
00065                                   const Type *NewTy) = 0;
00066 
00067   /// The other case which AbstractTypeUsers must be aware of is when a type
00068   /// makes the transition from being abstract (where it has clients on it's
00069   /// AbstractTypeUsers list) to concrete (where it does not).  This method
00070   /// notifies ATU's when this occurs for a type.
00071   ///
00072   virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0;
00073 
00074   // for debugging...
00075   virtual void dump() const = 0;
00076 };
00077 
00078 
00079 /// PATypeHandle - Handle to a Type subclass.  This class is used to keep the
00080 /// use list of abstract types up-to-date.
00081 ///
00082 class PATypeHandle {
00083   const Type *Ty;
00084   AbstractTypeUser * const User;
00085 
00086   // These functions are defined at the bottom of Type.h.  See the comment there
00087   // for justification.
00088   void addUser();
00089   void removeUser();
00090 public:
00091   // ctor - Add use to type if abstract.  Note that Ty must not be null
00092   inline PATypeHandle(const Type *ty, AbstractTypeUser *user)
00093     : Ty(ty), User(user) {
00094     addUser();
00095   }
00096 
00097   // ctor - Add use to type if abstract.
00098   inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) {
00099     addUser();
00100   }
00101 
00102   // dtor - Remove reference to type...
00103   inline ~PATypeHandle() { removeUser(); }
00104 
00105   // Automatic casting operator so that the handle may be used naturally
00106   inline operator Type *() const { return const_cast<Type*>(Ty); }
00107   inline Type *get() const { return const_cast<Type*>(Ty); }
00108 
00109   // operator= - Allow assignment to handle
00110   inline Type *operator=(const Type *ty) {
00111     if (Ty != ty) {   // Ensure we don't accidentally drop last ref to Ty
00112       removeUser();
00113       Ty = ty;
00114       addUser();
00115     }
00116     return get();
00117   }
00118 
00119   // operator= - Allow assignment to handle
00120   inline const Type *operator=(const PATypeHandle &T) {
00121     return operator=(T.Ty);
00122   }
00123 
00124   inline bool operator==(const Type *ty) {
00125     return Ty == ty;
00126   }
00127 
00128   // operator-> - Allow user to dereference handle naturally...
00129   inline const Type *operator->() const { return Ty; }
00130 };
00131 
00132 
00133 /// PATypeHolder - Holder class for a potentially abstract type.  This uses
00134 /// efficient union-find techniques to handle dynamic type resolution.  Unless
00135 /// you need to do custom processing when types are resolved, you should always
00136 /// use PATypeHolders in preference to PATypeHandles.
00137 ///
00138 class PATypeHolder {
00139   mutable const Type *Ty;
00140 public:
00141   PATypeHolder(const Type *ty) : Ty(ty) {
00142     addRef();
00143   }
00144   PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) {
00145     addRef();
00146   }
00147 
00148   ~PATypeHolder() { dropRef(); }
00149 
00150   operator Type *() const { return get(); }
00151   Type *get() const;
00152 
00153   // operator-> - Allow user to dereference handle naturally...
00154   Type *operator->() const { return get(); }
00155 
00156   // operator= - Allow assignment to handle
00157   Type *operator=(const Type *ty) {
00158     if (Ty != ty) {   // Don't accidentally drop last ref to Ty.
00159       dropRef();
00160       Ty = ty;
00161       addRef();
00162     }
00163     return get();
00164   }
00165   Type *operator=(const PATypeHolder &H) {
00166     return operator=(H.Ty);
00167   }
00168 
00169   /// getRawType - This should only be used to implement the vmcore library.
00170   ///
00171   const Type *getRawType() const { return Ty; }
00172 
00173 private:
00174   void addRef();
00175   void dropRef();
00176 };
00177 
00178 // simplify_type - Allow clients to treat uses just like values when using
00179 // casting operators.
00180 template<> struct simplify_type<PATypeHolder> {
00181   typedef const Type* SimpleType;
00182   static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
00183     return static_cast<SimpleType>(Val.get());
00184   }
00185 };
00186 template<> struct simplify_type<const PATypeHolder> {
00187   typedef const Type* SimpleType;
00188   static SimpleType getSimplifiedValue(const PATypeHolder &Val) {
00189     return static_cast<SimpleType>(Val.get());
00190   }
00191 };
00192   
00193 } // End llvm namespace
00194 
00195 #endif