Add new CompositeType shared baseclass of ArrayType and StructType
[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   // Methods for support type inquiry through isa, cast, and dyn_cast:
83   static inline bool classof(const DerivedType *T) { return true; }
84   static inline bool classof(const Type *T) {
85     return T->isDerivedType();
86   }
87   static inline bool classof(const Value *V) {
88     return isa<Type>(V) && classof(cast<const Type>(V));
89   }
90 };
91
92
93
94
95 class MethodType : public DerivedType {
96 public:
97   typedef vector<PATypeHandle<Type> > ParamTypes;
98 private:
99   PATypeHandle<Type> ResultType;
100   ParamTypes ParamTys;
101   bool isVarArgs;
102
103   MethodType(const MethodType &);                   // Do not implement
104   const MethodType &operator=(const MethodType &);  // Do not implement
105 protected:
106   // This should really be private, but it squelches a bogus warning
107   // from GCC to make them protected:  warning: `class MethodType' only 
108   // defines private constructors and has no friends
109
110   // Private ctor - Only can be created by a static member...
111   MethodType(const Type *Result, const vector<const Type*> &Params, 
112              bool IsVarArgs);
113
114 public:
115
116   inline bool isVarArg() const { return isVarArgs; }
117   inline const Type *getReturnType() const { return ResultType; }
118   inline const ParamTypes &getParamTypes() const { return ParamTys; }
119
120
121   virtual const Type *getContainedType(unsigned i) const {
122     return i == 0 ? ResultType : 
123                     (i <= ParamTys.size() ? ParamTys[i-1].get() : 0);
124   }
125   virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; }
126
127   // refineAbstractType - Called when a contained type is found to be more
128   // concrete - this could potentially change us from an abstract type to a
129   // concrete type.
130   //
131   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
132
133   static MethodType *get(const Type *Result, const vector<const Type*> &Params,
134                          bool isVarArg);
135
136
137   // Methods for support type inquiry through isa, cast, and dyn_cast:
138   static inline bool classof(const MethodType *T) { return true; }
139   static inline bool classof(const Type *T) {
140     return T->getPrimitiveID() == MethodTyID;
141   }
142   static inline bool classof(const Value *V) {
143     return isa<Type>(V) && classof(cast<const Type>(V));
144   }
145 };
146
147
148 // CompositeType - Common super class of ArrayType and StructType...
149 //
150 class CompositeType : public DerivedType {
151 protected:
152   inline CompositeType(const string &Name, PrimitiveID id)
153     : DerivedType(Name, id) { }
154
155 public:
156
157   // getTypeAtIndex - Given an index value into the type, return the type of the
158   // element.
159   //
160   virtual const Type *getTypeAtIndex(const Value *V) const = 0;
161   virtual bool indexValid(const Value *V) const = 0;
162
163   // getIndexType - Return the type required of indices for this composite.
164   // For structures, this is ubyte, for arrays, this is uint
165   //
166   virtual const Type *getIndexType() const = 0;
167
168
169   // Methods for support type inquiry through isa, cast, and dyn_cast:
170   static inline bool classof(const CompositeType *T) { return true; }
171   static inline bool classof(const Type *T) {
172     return T->getPrimitiveID() == ArrayTyID || 
173            T->getPrimitiveID() == StructTyID;
174   }
175   static inline bool classof(const Value *V) {
176     return isa<Type>(V) && classof(cast<const Type>(V));
177   }
178 };
179
180
181 class ArrayType : public CompositeType {
182 private:
183   PATypeHandle<Type> ElementType;
184   int NumElements;       // >= 0 for sized array, -1 for unbounded/unknown array
185
186   ArrayType(const ArrayType &);                   // Do not implement
187   const ArrayType &operator=(const ArrayType &);  // Do not implement
188 protected:
189   // This should really be private, but it squelches a bogus warning
190   // from GCC to make them protected:  warning: `class ArrayType' only 
191   // defines private constructors and has no friends
192
193
194   // Private ctor - Only can be created by a static member...
195   ArrayType(const Type *ElType, int NumEl);
196 public:
197
198   inline const Type *getElementType() const { return ElementType; }
199   inline int         getNumElements() const { return NumElements; }
200
201   inline bool isSized()   const { return NumElements >= 0; }
202   inline bool isUnsized() const { return NumElements == -1; }
203
204   virtual const Type *getContainedType(unsigned i) const { 
205     return i == 0 ? ElementType.get() : 0;
206   }
207   virtual unsigned getNumContainedTypes() const { return 1; }
208
209   // getTypeAtIndex - Given an index value into the type, return the type of the
210   // element.  For an arraytype, there is only one subtype...
211   //
212   virtual const Type *getTypeAtIndex(const Value *V) const {
213     return ElementType.get();
214   }
215   virtual bool indexValid(const Value *V) const {
216     return V->getType() == Type::UIntTy;   // Must be an unsigned int index
217   }
218
219   // getIndexType - Return the type required of indices for this composite.
220   // For structures, this is ubyte, for arrays, this is uint
221   //
222   virtual const Type *getIndexType() const { return Type::UIntTy; }
223
224   // refineAbstractType - Called when a contained type is found to be more
225   // concrete - this could potentially change us from an abstract type to a
226   // concrete type.
227   //
228   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
229
230   static ArrayType *get(const Type *ElementType, int NumElements = -1);
231
232   // Methods for support type inquiry through isa, cast, and dyn_cast:
233   static inline bool classof(const ArrayType *T) { return true; }
234   static inline bool classof(const Type *T) {
235     return T->getPrimitiveID() == ArrayTyID;
236   }
237   static inline bool classof(const Value *V) {
238     return isa<Type>(V) && classof(cast<const Type>(V));
239   }
240 };
241
242
243 class StructType : public CompositeType {
244 public:
245   typedef vector<PATypeHandle<Type> > ElementTypes;
246
247 private:
248   ElementTypes ETypes;                              // Element types of struct
249
250   StructType(const StructType &);                   // Do not implement
251   const StructType &operator=(const StructType &);  // Do not implement
252
253 protected:
254   // This should really be private, but it squelches a bogus warning
255   // from GCC to make them protected:  warning: `class StructType' only 
256   // defines private constructors and has no friends
257
258   // Private ctor - Only can be created by a static member...
259   StructType(const vector<const Type*> &Types);
260   
261 public:
262   inline const ElementTypes &getElementTypes() const { return ETypes; }
263
264   virtual const Type *getContainedType(unsigned i) const { 
265     return i < ETypes.size() ? ETypes[i].get() : 0;
266   }
267   virtual unsigned getNumContainedTypes() const { return ETypes.size(); }
268
269   // getTypeAtIndex - Given an index value into the type, return the type of the
270   // element.  For a structure type, this must be a constant value...
271   //
272   virtual const Type *getTypeAtIndex(const Value *V) const ;
273   virtual bool indexValid(const Value *V) const;
274
275   // getIndexType - Return the type required of indices for this composite.
276   // For structures, this is ubyte, for arrays, this is uint
277   //
278   virtual const Type *getIndexType() const { return Type::UByteTy; }
279
280   // refineAbstractType - Called when a contained type is found to be more
281   // concrete - this could potentially change us from an abstract type to a
282   // concrete type.
283   //
284   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
285
286   static StructType *get(const vector<const Type*> &Params);
287
288   // Methods for support type inquiry through isa, cast, and dyn_cast:
289   static inline bool classof(const StructType *T) { return true; }
290   static inline bool classof(const Type *T) {
291     return T->getPrimitiveID() == StructTyID;
292   }
293   static inline bool classof(const Value *V) {
294     return isa<Type>(V) && classof(cast<const Type>(V));
295   }
296 };
297
298
299 class PointerType : public DerivedType {
300 private:
301   PATypeHandle<Type> ValueType;
302
303   PointerType(const PointerType &);                   // Do not implement
304   const PointerType &operator=(const PointerType &);  // Do not implement
305 protected:
306   // This should really be private, but it squelches a bogus warning
307   // from GCC to make them protected:  warning: `class PointerType' only 
308   // defines private constructors and has no friends
309
310
311   // Private ctor - Only can be created by a static member...
312   PointerType(const Type *ElType);
313 public:
314
315   inline const Type *getValueType() const { return ValueType; }
316
317   virtual const Type *getContainedType(unsigned i) const { 
318     return i == 0 ? ValueType.get() : 0;
319   }
320   virtual unsigned getNumContainedTypes() const { return 1; }
321
322   static PointerType *get(const Type *ElementType);
323
324   // refineAbstractType - Called when a contained type is found to be more
325   // concrete - this could potentially change us from an abstract type to a
326   // concrete type.
327   //
328   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
329
330   // Methods for support type inquiry through isa, cast, and dyn_cast:
331   static inline bool classof(const PointerType *T) { return true; }
332   static inline bool classof(const Type *T) {
333     return T->getPrimitiveID() == PointerTyID;
334   }
335   static inline bool classof(const Value *V) {
336     return isa<Type>(V) && classof(cast<const Type>(V));
337   }
338 };
339
340
341 class OpaqueType : public DerivedType {
342 private:
343   OpaqueType(const OpaqueType &);                   // Do not implement
344   const OpaqueType &operator=(const OpaqueType &);  // Do not implement
345 protected:
346   // This should really be private, but it squelches a bogus warning
347   // from GCC to make them protected:  warning: `class OpaqueType' only 
348   // defines private constructors and has no friends
349
350   // Private ctor - Only can be created by a static member...
351   OpaqueType();
352
353 public:
354
355   // get - Static factory method for the OpaqueType class...
356   static OpaqueType *get() {
357     return new OpaqueType();           // All opaque types are distinct
358   }
359
360   // Methods for support type inquiry through isa, cast, and dyn_cast:
361   static inline bool classof(const OpaqueType *T) { return true; }
362   static inline bool classof(const Type *T) {
363     return T->getPrimitiveID() == OpaqueTyID;
364   }
365   static inline bool classof(const Value *V) {
366     return isa<Type>(V) && classof(cast<const Type>(V));
367   }
368 };
369
370
371 // Define some inline methods for the AbstractTypeUser.h:PATypeHandle class.
372 // These are defined here because they MUST be inlined, yet are dependant on 
373 // the definition of the Type class.  Of course Type derives from Value, which
374 // contains an AbstractTypeUser instance, so there is no good way to factor out
375 // the code.  Hence this bit of uglyness.
376 //
377 template <class TypeSubClass> void PATypeHandle<TypeSubClass>::addUser() {
378   if (Ty->isAbstract())
379     cast<DerivedType>(Ty)->addAbstractTypeUser(User);
380 }
381 template <class TypeSubClass> void PATypeHandle<TypeSubClass>::removeUser() {
382   if (Ty->isAbstract())
383     cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
384 }
385
386 template <class TypeSubClass>
387 void PATypeHandle<TypeSubClass>::removeUserFromConcrete() {
388   if (!Ty->isAbstract())
389     cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
390 }
391
392 #endif