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