Add support for casting operators
[oota-llvm.git] / lib / VMCore / Type.cpp
1 //===-- Type.cpp - Implement the Type class ----------------------*- C++ -*--=//
2 //
3 // This file implements the Type class for the VMCore library.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "llvm/DerivedTypes.h"
8 #include "llvm/Tools/StringExtras.h"
9
10 //===----------------------------------------------------------------------===//
11 //                         Type Class Implementation
12 //===----------------------------------------------------------------------===//
13
14 static unsigned CurUID = 0;
15 static vector<const Type *> UIDMappings;
16
17 Type::Type(const string &name, PrimitiveID id) 
18   : Value(Type::TypeTy, Value::TypeVal, name) {
19   ID = id;
20   ConstRulesImpl = 0;
21
22   UID = CurUID++;       // Assign types UID's as they are created
23   UIDMappings.push_back(this);
24 }
25
26 const Type *Type::getUniqueIDType(unsigned UID) {
27   assert(UID < UIDMappings.size() && 
28          "Type::getPrimitiveType: UID out of range!");
29   return UIDMappings[UID];
30 }
31
32 const Type *Type::getPrimitiveType(PrimitiveID IDNumber) {
33   switch (IDNumber) {
34   case VoidTyID  : return VoidTy;
35   case BoolTyID  : return BoolTy;
36   case UByteTyID : return UByteTy;
37   case SByteTyID : return SByteTy;
38   case UShortTyID: return UShortTy;
39   case ShortTyID : return ShortTy;
40   case UIntTyID  : return UIntTy;
41   case IntTyID   : return IntTy;
42   case ULongTyID : return ULongTy;
43   case LongTyID  : return LongTy;
44   case FloatTyID : return FloatTy;
45   case DoubleTyID: return DoubleTy;
46   case TypeTyID  : return TypeTy;
47   case LabelTyID : return LabelTy;
48   case LockTyID  : return LockTy;
49   case FillerTyID: return new Type("XXX FILLER XXX", FillerTyID); // TODO:KILLME
50   default:
51     return 0;
52   }
53 }
54
55
56
57 //===----------------------------------------------------------------------===//
58 //                           Auxilliary classes
59 //===----------------------------------------------------------------------===//
60 //
61 // These classes are used to implement specialized behavior for each different
62 // type.
63 //
64 class SignedIntType : public Type {
65   int Size;
66 public:
67   SignedIntType(const string &Name, PrimitiveID id, int size) : Type(Name, id) {
68     Size = size;
69   }
70
71   // isSigned - Return whether a numeric type is signed.
72   virtual bool isSigned() const { return 1; }
73   
74   // isIntegral - Return whether this is one of the integer types
75   virtual bool isIntegral() const { return 1; }
76 };
77
78 class UnsignedIntType : public Type {
79   uint64_t Size;
80 public:
81   UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) {
82     Size = size;
83   }
84
85   // isUnsigned - Return whether a numeric type is signed.
86   virtual bool isUnsigned() const { return 1; }
87   
88   // isIntegral - Return whether this is one of the integer types
89   virtual bool isIntegral() const { return 1; }
90 };
91
92 static struct TypeType : public Type {
93   TypeType() : Type("type", TypeTyID) {}
94 } TheTypeType;   // Implement the type that is global.
95
96
97 //===----------------------------------------------------------------------===//
98 //                           Static 'Type' data
99 //===----------------------------------------------------------------------===//
100
101 const Type *Type::VoidTy   = new            Type("void"  , VoidTyID),
102            *Type::BoolTy   = new            Type("bool"  , BoolTyID),
103            *Type::SByteTy  = new   SignedIntType("sbyte" , SByteTyID, 1),
104            *Type::UByteTy  = new UnsignedIntType("ubyte" , UByteTyID, 1),
105            *Type::ShortTy  = new   SignedIntType("short" ,  ShortTyID, 2),
106            *Type::UShortTy = new UnsignedIntType("ushort", UShortTyID, 2),
107            *Type::IntTy    = new   SignedIntType("int"   ,  IntTyID, 4), 
108            *Type::UIntTy   = new UnsignedIntType("uint"  , UIntTyID, 4),
109            *Type::LongTy   = new   SignedIntType("long"  ,  LongTyID, 8),
110            *Type::ULongTy  = new UnsignedIntType("ulong" , ULongTyID, 8),
111            *Type::FloatTy  = new            Type("float" , FloatTyID),
112            *Type::DoubleTy = new            Type("double", DoubleTyID),
113            *Type::TypeTy   =        &TheTypeType,
114            *Type::LabelTy  = new            Type("label" , LabelTyID),
115            *Type::LockTy   = new            Type("lock"  , LockTyID);
116
117
118 //===----------------------------------------------------------------------===//
119 //                      Derived Type Implementations
120 //===----------------------------------------------------------------------===//
121
122 // Make sure that only one instance of a particular type may be created on any
123 // given run of the compiler...
124 //
125 // TODO: This list should be kept in sorted order so that we can do a binary
126 // TODO: search instead of linear search!
127 //
128 // TODO: This should be templatized so that every derived type can use the same
129 // TODO: code!
130 //
131 #define TEST_MERGE_TYPES 0
132
133 #if TEST_MERGE_TYPES
134 #include "llvm/Assembly/Writer.h"
135 #endif
136
137 //===----------------------------------------------------------------------===//
138 //                          Derived Type Constructors
139 //===----------------------------------------------------------------------===//
140
141 MethodType::MethodType(const Type *Result, const vector<const Type*> &Params, 
142                        const string &Name) 
143   : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) {
144 }
145
146 ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name) 
147   : Type(Name, ArrayTyID), ElementType(ElType) {
148   NumElements = NumEl;
149 }
150
151 StructType::StructType(const vector<const Type*> &Types, const string &Name) 
152   : Type(Name, StructTyID),
153     ETypes(Types),
154     layoutCache(new StructSizeAndOffsetInfo) 
155 {
156   ResetCachedInfo();
157 }
158
159 PointerType::PointerType(const Type *E) 
160   : Type(E->getName() + " *", PointerTyID), ValueType(E) {
161 }
162
163 //===----------------------------------------------------------------------===//
164 //                         Derived Type Creator Functions
165 //===----------------------------------------------------------------------===//
166
167 const MethodType *MethodType::getMethodType(const Type *ReturnType, 
168                                             const vector<const Type*> &Params) {
169   static vector<const MethodType*> ExistingMethodTypesCache;
170   for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
171     const MethodType *T = ExistingMethodTypesCache[i];
172     if (T->getReturnType() == ReturnType) {
173       const ParamTypes &EParams = T->getParamTypes();
174       ParamTypes::const_iterator I = Params.begin(); 
175       ParamTypes::const_iterator J = EParams.begin(); 
176       for (; I != Params.end() && J != EParams.end(); ++I, ++J)
177         if (*I != *J) break;  // These types aren't equal!
178
179       if (I == Params.end() && J == EParams.end()) {
180 #if TEST_MERGE_TYPES == 2
181         ostream_iterator<const Type*> out(cerr, ", ");
182         cerr << "Type: \"";
183         copy(Params.begin(), Params.end(), out);
184         cerr << "\"\nEquals: \"";
185         copy(EParams.begin(), EParams.end(), out);
186         cerr << "\"" << endl;
187 #endif
188         return T;
189       }
190     }
191   }  
192 #if TEST_MERGE_TYPES == 2
193   ostream_iterator<const Type*> out(cerr, ", ");
194   cerr << "Input Types: ";
195   copy(Params.begin(), Params.end(), out);
196   cerr << endl;
197 #endif
198
199   // Calculate the string name for the new type...
200   string Name = ReturnType->getName() + " (";
201   for (ParamTypes::const_iterator I = Params.begin();  
202        I != Params.end(); ++I) {
203     if (I != Params.begin())
204       Name += ", ";
205     Name += (*I)->getName();
206   }
207   Name += ")";
208
209 #if TEST_MERGE_TYPES
210   cerr << "Derived new type: " << Name << endl;
211 #endif
212
213   MethodType *Result = new MethodType(ReturnType, Params, Name);
214   ExistingMethodTypesCache.push_back(Result);
215   return Result;
216 }
217
218
219 const ArrayType *ArrayType::getArrayType(const Type *ElementType, 
220                                          int NumElements = -1) {
221   assert(ElementType && "Can't get array of null types!");
222   static vector<const ArrayType*> ExistingTypesCache;
223
224   // Search cache for value...
225   for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
226     const ArrayType *T = ExistingTypesCache[i];
227
228     if (T->getElementType() == ElementType && 
229         T->getNumElements() == NumElements)
230       return T;
231   }
232
233   // Value not found.  Derive a new type!
234   string Name = "[";
235   if (NumElements != -1) Name += itostr(NumElements) + " x ";
236
237   Name += ElementType->getName();
238   
239   ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
240   ExistingTypesCache.push_back(Result);
241
242 #if TEST_MERGE_TYPES
243   cerr << "Derived new type: " << Result->getName() << endl;
244 #endif
245   return Result;
246 }
247
248 const StructType *StructType::getStructType(const ElementTypes &ETypes) {
249   static vector<const StructType*> ExistingStructTypesCache;
250
251   for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
252     const StructType *T = ExistingStructTypesCache[i];
253
254     const ElementTypes &Elements = T->getElementTypes();
255     ElementTypes::const_iterator I = ETypes.begin(); 
256     ElementTypes::const_iterator J = Elements.begin(); 
257     for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
258       if (*I != *J) break;  // These types aren't equal!
259     
260     if (I == ETypes.end() && J == Elements.end()) {
261 #if TEST_MERGE_TYPES == 2
262       ostream_iterator<const Type*> out(cerr, ", ");
263       cerr << "Type: \"";
264       copy(ETypes.begin(), ETypes.end(), out);
265       cerr << "\"\nEquals: \"";
266       copy(Elements.begin(), Elements.end(), out);
267       cerr << "\"" << endl;
268 #endif
269       return T;
270     }
271   }
272
273 #if TEST_MERGE_TYPES == 2
274   ostream_iterator<const Type*> out(cerr, ", ");
275   cerr << "Input Types: ";
276   copy(ETypes.begin(), ETypes.end(), out);
277   cerr << endl;
278 #endif
279
280   // Calculate the string name for the new type...
281   string Name = "{ ";
282   for (ElementTypes::const_iterator I = ETypes.begin();  
283        I != ETypes.end(); ++I) {
284     if (I != ETypes.begin())
285       Name += ", ";
286     Name += (*I)->getName();
287   }
288   Name += " }";
289
290 #if TEST_MERGE_TYPES
291   cerr << "Derived new type: " << Name << endl;
292 #endif
293
294   StructType *Result = new StructType(ETypes, Name);
295   ExistingStructTypesCache.push_back(Result);
296   return Result;
297 }
298
299
300 const PointerType *PointerType::getPointerType(const Type *ValueType) {
301   assert(ValueType && "Can't get a pointer to <null> type!");
302   static vector<const PointerType*> ExistingTypesCache;
303
304   // Search cache for value...
305   for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
306     const PointerType *T = ExistingTypesCache[i];
307
308     if (T->getValueType() == ValueType)
309       return T;
310   }
311
312   PointerType *Result = new PointerType(ValueType);
313   ExistingTypesCache.push_back(Result);
314
315 #if TEST_MERGE_TYPES
316   cerr << "Derived new type: " << Result->getName() << endl;
317 #endif
318   return Result;
319 }
320