Change the interface to PromoteMemToReg to also take a DominatorTree
[oota-llvm.git] / include / llvm / AbstractTypeUser.h
1 //===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===//
2 //
3 // The AbstractTypeUser class is an interface to be implemented by classes who
4 // could possible use an abstract type.  Abstract types are denoted by the
5 // isAbstract flag set to true in the Type class.  These are classes that
6 // contain an Opaque type in their structure somehow.
7 //
8 // Classes must implement this interface so that they may be notified when an
9 // abstract type is resolved.  Abstract types may be resolved into more concrete
10 // types through: linking, parsing, and bytecode reading.  When this happens,
11 // all of the users of the type must be updated to reference the new, more
12 // concrete type.  They are notified through the AbstractTypeUser interface.
13 //
14 // In addition to this, AbstractTypeUsers must keep the use list of the
15 // potentially abstract type that they reference up-to-date.  To do this in a
16 // nice, transparent way, the PATypeHandle class is used to hold "Potentially
17 // Abstract Types", and keep the use list of the abstract types up-to-date.
18 //
19 //===----------------------------------------------------------------------===//
20
21 #ifndef LLVM_ABSTRACT_TYPE_USER_H
22 #define LLVM_ABSTRACT_TYPE_USER_H
23
24 // This is the "master" include for <cassert> Whether this file needs it or not,
25 // it must always include <cassert> for the files which include
26 // llvm/AbstractTypeUser.h
27 //
28 // In this way, most every LLVM source file will have access to the assert()
29 // macro without having to #include <cassert> directly.
30 //
31 #include <cassert>
32
33 class Type;
34 class DerivedType;
35
36 class AbstractTypeUser {
37 protected:
38   virtual ~AbstractTypeUser() {}                        // Derive from me
39 public:
40
41   /// refineAbstractType - The callback method invoked when an abstract type is
42   /// resolved to another type.  An object must override this method to update
43   /// its internal state to reference NewType instead of OldType.
44   ///
45   virtual void refineAbstractType(const DerivedType *OldTy,
46                                   const Type *NewTy) = 0;
47
48   /// The other case which AbstractTypeUsers must be aware of is when a type
49   /// makes the transition from being abstract (where it has clients on it's
50   /// AbstractTypeUsers list) to concrete (where it does not).  This method
51   /// notifies ATU's when this occurs for a type.
52   ///
53   virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0;
54
55   // for debugging...
56   virtual void dump() const = 0;
57 };
58
59
60 /// PATypeHandle - Handle to a Type subclass.  This class is used to keep the
61 /// use list of abstract types up-to-date.
62 ///
63 class PATypeHandle {
64   const Type *Ty;
65   AbstractTypeUser * const User;
66
67   // These functions are defined at the bottom of Type.h.  See the comment there
68   // for justification.
69   void addUser();
70   void removeUser();
71 public:
72   // ctor - Add use to type if abstract.  Note that Ty must not be null
73   inline PATypeHandle(const Type *ty, AbstractTypeUser *user) 
74     : Ty(ty), User(user) {
75     addUser();
76   }
77
78   // ctor - Add use to type if abstract.
79   inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) {
80     addUser();
81   }
82
83   // dtor - Remove reference to type...
84   inline ~PATypeHandle() { removeUser(); }
85
86   // Automatic casting operator so that the handle may be used naturally
87   inline operator const Type *() const { return Ty; }
88   inline const Type *get() const { return Ty; }
89
90   // operator= - Allow assignment to handle
91   inline const Type *operator=(const Type *ty) {
92     if (Ty != ty) {   // Ensure we don't accidentally drop last ref to Ty
93       removeUser();
94       Ty = ty;
95       addUser();
96     }
97     return Ty;
98   }
99
100   // operator= - Allow assignment to handle
101   inline const Type *operator=(const PATypeHandle &T) {
102     return operator=(T.Ty);
103   }
104
105   inline bool operator==(const Type *ty) {
106     return Ty == ty;
107   }
108
109   // operator-> - Allow user to dereference handle naturally...
110   inline const Type *operator->() const { return Ty; }
111
112   // removeUserFromConcrete - This function should be called when the User is
113   // notified that our type is refined... and the type is being refined to
114   // itself, which is now a concrete type.  When a type becomes concrete like
115   // this, we MUST remove ourself from the AbstractTypeUser list, even though
116   // the type is apparently concrete.
117   //
118   void removeUserFromConcrete();
119 };
120
121
122 /// PATypeHolder - Holder class for a potentially abstract type.  This uses
123 /// efficient union-find techniques to handle dynamic type resolution.  Unless
124 /// you need to do custom processing when types are resolved, you should always
125 /// use PATypeHolders in preference to PATypeHandles.
126 ///
127 class PATypeHolder {
128   mutable const Type *Ty;
129 public:
130   PATypeHolder(const Type *ty) : Ty(ty) {
131     addRef();
132   }
133   PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) {
134     addRef();
135   }
136
137   operator const Type *() const { return get(); }
138   const Type *get() const;
139
140   // operator-> - Allow user to dereference handle naturally...
141   const Type *operator->() const { return get(); }
142
143   // operator= - Allow assignment to handle
144   const Type *operator=(const Type *ty) {
145     if (Ty != ty) {   // Don't accidentally drop last ref to Ty.
146       dropRef();
147       Ty = ty;
148       addRef();
149     }
150     return get();
151   }
152   const Type *operator=(const PATypeHolder &H) {
153     return operator=(H.Ty);
154   }
155
156 private:
157   void addRef();
158   void dropRef();
159 };
160
161 #endif