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