0b272f0bb57e48370a6b140fee6e2f291caa194c
[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
75 class UnsignedIntType : public Type {
76   uint64_t Size;
77 public:
78   UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) {
79     Size = size;
80   }
81
82   // isUnsigned - Return whether a numeric type is signed.
83   virtual bool isUnsigned() const { return 1; }
84 };
85
86 static struct TypeType : public Type {
87   TypeType() : Type("type", TypeTyID) {}
88 } TheTypeType;   // Implement the type that is global.
89
90
91 //===----------------------------------------------------------------------===//
92 //                           Static 'Type' data
93 //===----------------------------------------------------------------------===//
94
95 const Type *Type::VoidTy   = new            Type("void"  , VoidTyID),
96            *Type::BoolTy   = new            Type("bool"  , BoolTyID),
97            *Type::SByteTy  = new   SignedIntType("sbyte" , SByteTyID, 1),
98            *Type::UByteTy  = new UnsignedIntType("ubyte" , UByteTyID, 1),
99            *Type::ShortTy  = new   SignedIntType("short" ,  ShortTyID, 2),
100            *Type::UShortTy = new UnsignedIntType("ushort", UShortTyID, 2),
101            *Type::IntTy    = new   SignedIntType("int"   ,  IntTyID, 4), 
102            *Type::UIntTy   = new UnsignedIntType("uint"  , UIntTyID, 4),
103            *Type::LongTy   = new   SignedIntType("long"  ,  LongTyID, 8),
104            *Type::ULongTy  = new UnsignedIntType("ulong" , ULongTyID, 8),
105            *Type::FloatTy  = new            Type("float" , FloatTyID),
106            *Type::DoubleTy = new            Type("double", DoubleTyID),
107            *Type::TypeTy   =        &TheTypeType,
108            *Type::LabelTy  = new            Type("label" , LabelTyID),
109            *Type::LockTy   = new            Type("lock"  , LockTyID);
110
111
112 //===----------------------------------------------------------------------===//
113 //                      Derived Type Implementations
114 //===----------------------------------------------------------------------===//
115
116 // Make sure that only one instance of a particular type may be created on any
117 // given run of the compiler...
118 //
119 // TODO: This list should be kept in sorted order so that we can do a binary
120 // TODO: search instead of linear search!
121 //
122 // TODO: This should be templatized so that every derived type can use the same
123 // TODO: code!
124 //
125 #define TEST_MERGE_TYPES 0
126
127 #if TEST_MERGE_TYPES
128 #include "llvm/Assembly/Writer.h"
129 #endif
130
131 //===----------------------------------------------------------------------===//
132 //                          Derived Type Constructors
133 //===----------------------------------------------------------------------===//
134
135 MethodType::MethodType(const Type *Result, const vector<const Type*> &Params, 
136                        const string &Name) 
137   : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) {
138 }
139
140 ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name) 
141   : Type(Name, ArrayTyID), ElementType(ElType) {
142   NumElements = NumEl;
143 }
144
145 StructType::StructType(const vector<const Type*> &Types, const string &Name) 
146   : Type(Name, StructTyID), ETypes(Types) {
147 }
148
149 PointerType::PointerType(const Type *E) 
150   : Type(E->getName() + " *", PointerTyID), ValueType(E) {
151 }
152
153 //===----------------------------------------------------------------------===//
154 //                         Derived Type Creator Functions
155 //===----------------------------------------------------------------------===//
156
157 const MethodType *MethodType::getMethodType(const Type *ReturnType, 
158                                             const vector<const Type*> &Params) {
159   static vector<const MethodType*> ExistingMethodTypesCache;
160   for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
161     const MethodType *T = ExistingMethodTypesCache[i];
162     if (T->getReturnType() == ReturnType) {
163       const ParamTypes &EParams = T->getParamTypes();
164       ParamTypes::const_iterator I = Params.begin(); 
165       ParamTypes::const_iterator J = EParams.begin(); 
166       for (; I != Params.end() && J != EParams.end(); ++I, ++J)
167         if (*I != *J) break;  // These types aren't equal!
168
169       if (I == Params.end() && J == EParams.end()) {
170 #if TEST_MERGE_TYPES == 2
171         ostream_iterator<const Type*> out(cerr, ", ");
172         cerr << "Type: \"";
173         copy(Params.begin(), Params.end(), out);
174         cerr << "\"\nEquals: \"";
175         copy(EParams.begin(), EParams.end(), out);
176         cerr << "\"" << endl;
177 #endif
178         return T;
179       }
180     }
181   }  
182 #if TEST_MERGE_TYPES == 2
183   ostream_iterator<const Type*> out(cerr, ", ");
184   cerr << "Input Types: ";
185   copy(Params.begin(), Params.end(), out);
186   cerr << endl;
187 #endif
188
189   // Calculate the string name for the new type...
190   string Name = ReturnType->getName() + " (";
191   for (ParamTypes::const_iterator I = Params.begin();  
192        I != Params.end(); ++I) {
193     if (I != Params.begin())
194       Name += ", ";
195     Name += (*I)->getName();
196   }
197   Name += ")";
198
199 #if TEST_MERGE_TYPES
200   cerr << "Derived new type: " << Name << endl;
201 #endif
202
203   MethodType *Result = new MethodType(ReturnType, Params, Name);
204   ExistingMethodTypesCache.push_back(Result);
205   return Result;
206 }
207
208
209 const ArrayType *ArrayType::getArrayType(const Type *ElementType, 
210                                          int NumElements = -1) {
211   assert(ElementType && "Can't get array of null types!");
212   static vector<const ArrayType*> ExistingTypesCache;
213
214   // Search cache for value...
215   for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
216     const ArrayType *T = ExistingTypesCache[i];
217
218     if (T->getElementType() == ElementType && 
219         T->getNumElements() == NumElements)
220       return T;
221   }
222
223   // Value not found.  Derive a new type!
224   string Name = "[";
225   if (NumElements != -1) Name += itostr(NumElements) + " x ";
226
227   Name += ElementType->getName();
228   
229   ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
230   ExistingTypesCache.push_back(Result);
231
232 #if TEST_MERGE_TYPES
233   cerr << "Derived new type: " << Result->getName() << endl;
234 #endif
235   return Result;
236 }
237
238 const StructType *StructType::getStructType(const ElementTypes &ETypes) {
239   static vector<const StructType*> ExistingStructTypesCache;
240
241   for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
242     const StructType *T = ExistingStructTypesCache[i];
243
244     const ElementTypes &Elements = T->getElementTypes();
245     ElementTypes::const_iterator I = ETypes.begin(); 
246     ElementTypes::const_iterator J = Elements.begin(); 
247     for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
248       if (*I != *J) break;  // These types aren't equal!
249     
250     if (I == ETypes.end() && J == Elements.end()) {
251 #if TEST_MERGE_TYPES == 2
252       ostream_iterator<const Type*> out(cerr, ", ");
253       cerr << "Type: \"";
254       copy(ETypes.begin(), ETypes.end(), out);
255       cerr << "\"\nEquals: \"";
256       copy(Elements.begin(), Elements.end(), out);
257       cerr << "\"" << endl;
258 #endif
259       return T;
260     }
261   }
262
263 #if TEST_MERGE_TYPES == 2
264   ostream_iterator<const Type*> out(cerr, ", ");
265   cerr << "Input Types: ";
266   copy(ETypes.begin(), ETypes.end(), out);
267   cerr << endl;
268 #endif
269
270   // Calculate the string name for the new type...
271   string Name = "{ ";
272   for (ElementTypes::const_iterator I = ETypes.begin();  
273        I != ETypes.end(); ++I) {
274     if (I != ETypes.begin())
275       Name += ", ";
276     Name += (*I)->getName();
277   }
278   Name += " }";
279
280 #if TEST_MERGE_TYPES
281   cerr << "Derived new type: " << Name << endl;
282 #endif
283
284   StructType *Result = new StructType(ETypes, Name);
285   ExistingStructTypesCache.push_back(Result);
286   return Result;
287 }
288
289
290 const PointerType *PointerType::getPointerType(const Type *ValueType) {
291   assert(ValueType && "Can't get a pointer to <null> type!");
292   static vector<const PointerType*> ExistingTypesCache;
293
294   // Search cache for value...
295   for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
296     const PointerType *T = ExistingTypesCache[i];
297
298     if (T->getValueType() == ValueType)
299       return T;
300   }
301
302   PointerType *Result = new PointerType(ValueType);
303   ExistingTypesCache.push_back(Result);
304
305 #if TEST_MERGE_TYPES
306   cerr << "Derived new type: " << Result->getName() << endl;
307 #endif
308   return Result;
309 }
310