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 00037 /// The AbstractTypeUser class is an interface to be implemented by classes who 00038 /// could possibly use an abstract type. Abstract types are denoted by the 00039 /// isAbstract flag set to true in the Type class. These are classes that 00040 /// contain an Opaque type in their structure somewhere. 00041 /// 00042 /// Classes must implement this interface so that they may be notified when an 00043 /// abstract type is resolved. Abstract types may be resolved into more 00044 /// concrete types through: linking, parsing, and bitcode reading. When this 00045 /// happens, all of the users of the type must be updated to reference the new, 00046 /// more concrete type. They are notified through the AbstractTypeUser 00047 /// interface. 00048 /// 00049 /// In addition to this, AbstractTypeUsers must keep the use list of the 00050 /// potentially abstract type that they reference up-to-date. To do this in a 00051 /// nice, transparent way, the PATypeHandle class is used to hold "Potentially 00052 /// Abstract Types", and keep the use list of the abstract types up-to-date. 00053 /// @brief LLVM Abstract Type User Representation 00054 class AbstractTypeUser { 00055 protected: 00056 virtual ~AbstractTypeUser(); // Derive from me 00057 public: 00058 00059 /// refineAbstractType - The callback method invoked when an abstract type is 00060 /// resolved to another type. An object must override this method to update 00061 /// its internal state to reference NewType instead of OldType. 00062 /// 00063 virtual void refineAbstractType(const DerivedType *OldTy, 00064 const Type *NewTy) = 0; 00065 00066 /// The other case which AbstractTypeUsers must be aware of is when a type 00067 /// makes the transition from being abstract (where it has clients on it's 00068 /// AbstractTypeUsers list) to concrete (where it does not). This method 00069 /// notifies ATU's when this occurs for a type. 00070 /// 00071 virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0; 00072 00073 // for debugging... 00074 virtual void dump() const = 0; 00075 }; 00076 00077 00078 /// PATypeHandle - Handle to a Type subclass. This class is used to keep the 00079 /// use list of abstract types up-to-date. 00080 /// 00081 class PATypeHandle { 00082 const Type *Ty; 00083 AbstractTypeUser * const User; 00084 00085 // These functions are defined at the bottom of Type.h. See the comment there 00086 // for justification. 00087 void addUser(); 00088 void removeUser(); 00089 public: 00090 // ctor - Add use to type if abstract. Note that Ty must not be null 00091 inline PATypeHandle(const Type *ty, AbstractTypeUser *user) 00092 : Ty(ty), User(user) { 00093 addUser(); 00094 } 00095 00096 // ctor - Add use to type if abstract. 00097 inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) { 00098 addUser(); 00099 } 00100 00101 // dtor - Remove reference to type... 00102 inline ~PATypeHandle() { removeUser(); } 00103 00104 // Automatic casting operator so that the handle may be used naturally 00105 inline operator Type *() const { return const_cast<Type*>(Ty); } 00106 inline Type *get() const { return const_cast<Type*>(Ty); } 00107 00108 // operator= - Allow assignment to handle 00109 inline Type *operator=(const Type *ty) { 00110 if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty 00111 removeUser(); 00112 Ty = ty; 00113 addUser(); 00114 } 00115 return get(); 00116 } 00117 00118 // operator= - Allow assignment to handle 00119 inline const Type *operator=(const PATypeHandle &T) { 00120 return operator=(T.Ty); 00121 } 00122 00123 inline bool operator==(const Type *ty) { 00124 return Ty == ty; 00125 } 00126 00127 // operator-> - Allow user to dereference handle naturally... 00128 inline const Type *operator->() const { return Ty; } 00129 }; 00130 00131 00132 /// PATypeHolder - Holder class for a potentially abstract type. This uses 00133 /// efficient union-find techniques to handle dynamic type resolution. Unless 00134 /// you need to do custom processing when types are resolved, you should always 00135 /// use PATypeHolders in preference to PATypeHandles. 00136 /// 00137 class PATypeHolder { 00138 mutable const Type *Ty; 00139 public: 00140 PATypeHolder(const Type *ty) : Ty(ty) { 00141 addRef(); 00142 } 00143 PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) { 00144 addRef(); 00145 } 00146 00147 ~PATypeHolder() { dropRef(); } 00148 00149 operator Type *() const { return get(); } 00150 Type *get() const; 00151 00152 // operator-> - Allow user to dereference handle naturally... 00153 Type *operator->() const { return get(); } 00154 00155 // operator= - Allow assignment to handle 00156 Type *operator=(const Type *ty) { 00157 if (Ty != ty) { // Don't accidentally drop last ref to Ty. 00158 dropRef(); 00159 Ty = ty; 00160 addRef(); 00161 } 00162 return get(); 00163 } 00164 Type *operator=(const PATypeHolder &H) { 00165 return operator=(H.Ty); 00166 } 00167 00168 /// getRawType - This should only be used to implement the vmcore library. 00169 /// 00170 const Type *getRawType() const { return Ty; } 00171 00172 private: 00173 void addRef(); 00174 void dropRef(); 00175 }; 00176 00177 } // End llvm namespace 00178 00179 #endif