3f93459b23268c31b572237ec808cf396c067a07
[oota-llvm.git] / include / llvm / DerivedTypes.h
1 //===-- llvm/DerivedTypes.h - Classes for handling data types ----*- C++ -*--=//
2 //
3 // This file contains the declarations of classes that represent "derived 
4 // types".  These are things like "arrays of x" or "structure of x, y, z" or
5 // "method returning x taking (y,z) as parameters", etc...
6 //
7 // The implementations of these classes live in the Type.cpp file.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #ifndef LLVM_DERIVED_TYPES_H
12 #define LLVM_DERIVED_TYPES_H
13
14 #include "llvm/Type.h"
15
16 class DerivedType : public Type {
17   // AbstractTypeUsers - Implement a list of the users that need to be notified
18   // if I am a type, and I get resolved into a more concrete type.
19   //
20   ///// FIXME: kill mutable nonsense when Type's are not const
21   mutable vector<AbstractTypeUser *> AbstractTypeUsers;
22
23   char isRefining;                                   // Used for recursive types
24
25 protected:
26   inline DerivedType(const string &Name, PrimitiveID id) : Type(Name, id) {
27     isRefining = false;
28   }
29
30   // typeIsRefined - Notify AbstractTypeUsers of this type that the current type
31   // has been refined a bit.  The pointer is still valid and still should be
32   // used, but the subtypes have changed.
33   //
34   void typeIsRefined();
35   
36   // setDerivedTypeProperties - Based on the subtypes, set the name of this
37   // type so that it is printed nicely by the type printer.  Also calculate
38   // whether this type is abstract or not.  Used by the constructor and when
39   // the type is refined.
40   //
41   void setDerivedTypeProperties();
42
43 public:
44
45   //===--------------------------------------------------------------------===//
46   // Abstract Type handling methods - These types have special lifetimes, which
47   // are managed by (add|remove)AbstractTypeUser. See comments in
48   // AbstractTypeUser.h for more information.
49
50   // addAbstractTypeUser - Notify an abstract type that there is a new user of
51   // it.  This function is called primarily by the PATypeHandle class.
52   //
53   void addAbstractTypeUser(AbstractTypeUser *U) const {
54     assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
55 #if 0
56     cerr << "  addAbstractTypeUser[" << (void*)this << ", " << getDescription() 
57          << "][" << AbstractTypeUsers.size() << "] User = " << U << endl;
58 #endif
59     AbstractTypeUsers.push_back(U);
60   }
61
62   // removeAbstractTypeUser - Notify an abstract type that a user of the class
63   // no longer has a handle to the type.  This function is called primarily by
64   // the PATypeHandle class.  When there are no users of the abstract type, it
65   // is anihilated, because there is no way to get a reference to it ever again.
66   //
67   void removeAbstractTypeUser(AbstractTypeUser *U) const;
68
69   // getNumAbstractTypeUsers - Return the number of users registered to the type
70   inline unsigned getNumAbstractTypeUsers() const {
71     assert(isAbstract() && "getNumAbstractTypeUsers: Type not abstract!");
72     return AbstractTypeUsers.size(); 
73   }
74
75   // refineAbstractTypeTo - This function is used to when it is discovered that
76   // the 'this' abstract type is actually equivalent to the NewType specified.
77   // This causes all users of 'this' to switch to reference the more concrete
78   // type NewType and for 'this' to be deleted.
79   //
80   void refineAbstractTypeTo(const Type *NewType);
81 };
82
83
84
85
86 class MethodType : public DerivedType {
87 public:
88   typedef vector<PATypeHandle<Type> > ParamTypes;
89 private:
90   PATypeHandle<Type> ResultType;
91   ParamTypes ParamTys;
92   bool isVarArgs;
93
94   MethodType(const MethodType &);                   // Do not implement
95   const MethodType &operator=(const MethodType &);  // Do not implement
96 protected:
97   // This should really be private, but it squelches a bogus warning
98   // from GCC to make them protected:  warning: `class MethodType' only 
99   // defines private constructors and has no friends
100
101   // Private ctor - Only can be created by a static member...
102   MethodType(const Type *Result, const vector<const Type*> &Params, 
103              bool IsVarArgs);
104
105 public:
106
107   inline bool isVarArg() const { return isVarArgs; }
108   inline const Type *getReturnType() const { return ResultType; }
109   inline const ParamTypes &getParamTypes() const { return ParamTys; }
110
111
112   virtual const Type *getContainedType(unsigned i) const {
113     return i == 0 ? ResultType : (i <= ParamTys.size() ? ParamTys[i-1] : 0);
114   }
115   virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; }
116
117   // refineAbstractType - Called when a contained type is found to be more
118   // concrete - this could potentially change us from an abstract type to a
119   // concrete type.
120   //
121   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
122
123   static MethodType *get(const Type *Result, const vector<const Type*> &Params);
124 };
125
126
127 class ArrayType : public DerivedType {
128 private:
129   PATypeHandle<Type> ElementType;
130   int NumElements;       // >= 0 for sized array, -1 for unbounded/unknown array
131
132   ArrayType(const ArrayType &);                   // Do not implement
133   const ArrayType &operator=(const ArrayType &);  // Do not implement
134 protected:
135   // This should really be private, but it squelches a bogus warning
136   // from GCC to make them protected:  warning: `class ArrayType' only 
137   // defines private constructors and has no friends
138
139
140   // Private ctor - Only can be created by a static member...
141   ArrayType(const Type *ElType, int NumEl);
142
143 public:
144
145   inline const Type *getElementType() const { return ElementType; }
146   inline int         getNumElements() const { return NumElements; }
147
148   inline bool isSized()   const { return NumElements >= 0; }
149   inline bool isUnsized() const { return NumElements == -1; }
150
151   virtual const Type *getContainedType(unsigned i) const { 
152     return i == 0 ? ElementType : 0;
153   }
154   virtual unsigned getNumContainedTypes() const { return 1; }
155
156   // refineAbstractType - Called when a contained type is found to be more
157   // concrete - this could potentially change us from an abstract type to a
158   // concrete type.
159   //
160   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
161
162   static ArrayType *get(const Type *ElementType, int NumElements = -1);
163 };
164
165
166 class StructType : public DerivedType {
167 public:
168   typedef vector<PATypeHandle<Type> > ElementTypes;
169
170 private:
171   ElementTypes ETypes;                              // Element types of struct
172
173   StructType(const StructType &);                   // Do not implement
174   const StructType &operator=(const StructType &);  // Do not implement
175
176 protected:
177   // This should really be private, but it squelches a bogus warning
178   // from GCC to make them protected:  warning: `class StructType' only 
179   // defines private constructors and has no friends
180
181   // Private ctor - Only can be created by a static member...
182   StructType(const vector<const Type*> &Types);
183   
184 public:
185   inline const ElementTypes &getElementTypes() const { return ETypes; }
186
187   virtual const Type *getContainedType(unsigned i) const { 
188     return i < ETypes.size() ? ETypes[i] : 0;
189   }
190   virtual unsigned getNumContainedTypes() const { return ETypes.size(); }
191
192   // refineAbstractType - Called when a contained type is found to be more
193   // concrete - this could potentially change us from an abstract type to a
194   // concrete type.
195   //
196   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
197
198   static StructType *get(const vector<const Type*> &Params);
199 };
200
201
202 class PointerType : public DerivedType {
203 private:
204   PATypeHandle<Type> ValueType;
205
206   PointerType(const PointerType &);                   // Do not implement
207   const PointerType &operator=(const PointerType &);  // Do not implement
208 protected:
209   // This should really be private, but it squelches a bogus warning
210   // from GCC to make them protected:  warning: `class PointerType' only 
211   // defines private constructors and has no friends
212
213
214   // Private ctor - Only can be created by a static member...
215   PointerType(const Type *ElType);
216
217 public:
218
219   inline const Type *getValueType() const { return ValueType; }
220
221   virtual const Type *getContainedType(unsigned i) const { 
222     return i == 0 ? ValueType : 0;
223   }
224   virtual unsigned getNumContainedTypes() const { return 1; }
225
226   static PointerType *get(const Type *ElementType);
227
228   // refineAbstractType - Called when a contained type is found to be more
229   // concrete - this could potentially change us from an abstract type to a
230   // concrete type.
231   //
232   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
233 };
234
235
236 class OpaqueType : public DerivedType {
237 private:
238   OpaqueType(const OpaqueType &);                   // Do not implement
239   const OpaqueType &operator=(const OpaqueType &);  // Do not implement
240 protected:
241   // This should really be private, but it squelches a bogus warning
242   // from GCC to make them protected:  warning: `class OpaqueType' only 
243   // defines private constructors and has no friends
244
245   // Private ctor - Only can be created by a static member...
246   OpaqueType();
247
248 public:
249
250   // get - Static factory method for the OpaqueType class...
251   static OpaqueType *get() {
252     return new OpaqueType();           // All opaque types are distinct
253   }
254 };
255
256
257 // Define some inline methods for the AbstractTypeUser.h:PATypeHandle class.
258 // These are defined here because they MUST be inlined, yet are dependant on 
259 // the definition of the Type class.  Of course Type derives from Value, which
260 // contains an AbstractTypeUser instance, so there is no good way to factor out
261 // the code.  Hence this bit of uglyness.
262 //
263 template <class TypeSubClass> void PATypeHandle<TypeSubClass>::addUser() {
264   if (Ty->isAbstract())
265     Ty->castDerivedTypeAsserting()->addAbstractTypeUser(User);
266 }
267 template <class TypeSubClass> void PATypeHandle<TypeSubClass>::removeUser() {
268   if (Ty->isAbstract())
269     Ty->castDerivedTypeAsserting()->removeAbstractTypeUser(User);
270 }
271
272 #endif