LLVM API Documentation
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