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