blob: 5ae2cf9761c88842118c7eaeb251a63f23de0df7 [file] [log] [blame]
Chris Lattner00950542001-06-06 20:29:01 +00001//===-- 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
14static unsigned CurUID = 0;
15static vector<const Type *> UIDMappings;
16
17Type::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
26const Type *Type::getUniqueIDType(unsigned UID) {
27 assert(UID < UIDMappings.size() &&
28 "Type::getPrimitiveType: UID out of range!");
29 return UIDMappings[UID];
30}
31
32const 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//
64class SignedIntType : public Type {
65 int Size;
66public:
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
75class UnsignedIntType : public Type {
76 uint64_t Size;
77public:
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
86static 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
95const 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
135MethodType::MethodType(const Type *Result, const vector<const Type*> &Params,
136 const string &Name)
137 : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) {
138}
139
140ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name)
141 : Type(Name, ArrayTyID), ElementType(ElType) {
142 NumElements = NumEl;
143}
144
145StructType::StructType(const vector<const Type*> &Types, const string &Name)
146 : Type(Name, StructTyID), ETypes(Types) {
147}
148
149PointerType::PointerType(const Type *E)
150 : Type(E->getName() + " *", PointerTyID), ValueType(E) {
151}
152
153//===----------------------------------------------------------------------===//
154// Derived Type Creator Functions
155//===----------------------------------------------------------------------===//
156
157const MethodType *MethodType::getMethodType(const Type *ReturnType,
158 const vector<const Type*> &Params) {
159 static vector<const MethodType*> ExistingMethodTypesCache;
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000160 for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000161 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();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000166 for (; I != Params.end() && J != EParams.end(); ++I, ++J)
Chris Lattner00950542001-06-06 20:29:01 +0000167 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();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000192 I != Params.end(); ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000193 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
209const ArrayType *ArrayType::getArrayType(const Type *ElementType,
210 int NumElements = -1) {
211 static vector<const ArrayType*> ExistingTypesCache;
212
213 // Search cache for value...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000214 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000215 const ArrayType *T = ExistingTypesCache[i];
216
217 if (T->getElementType() == ElementType &&
218 T->getNumElements() == NumElements)
219 return T;
220 }
221
222 // Value not found. Derive a new type!
223 string Name = "[";
224 if (NumElements != -1) Name += itostr(NumElements) + " x ";
225
226 Name += ElementType->getName();
227
228 ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
229 ExistingTypesCache.push_back(Result);
230
231#if TEST_MERGE_TYPES
232 cerr << "Derived new type: " << Result->getName() << endl;
233#endif
234 return Result;
235}
236
237const StructType *StructType::getStructType(const ElementTypes &ETypes) {
238 static vector<const StructType*> ExistingStructTypesCache;
239
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000240 for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000241 const StructType *T = ExistingStructTypesCache[i];
242
243 const ElementTypes &Elements = T->getElementTypes();
244 ElementTypes::const_iterator I = ETypes.begin();
245 ElementTypes::const_iterator J = Elements.begin();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000246 for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
Chris Lattner00950542001-06-06 20:29:01 +0000247 if (*I != *J) break; // These types aren't equal!
248
249 if (I == ETypes.end() && J == Elements.end()) {
250#if TEST_MERGE_TYPES == 2
251 ostream_iterator<const Type*> out(cerr, ", ");
252 cerr << "Type: \"";
253 copy(ETypes.begin(), ETypes.end(), out);
254 cerr << "\"\nEquals: \"";
255 copy(Elements.begin(), Elements.end(), out);
256 cerr << "\"" << endl;
257#endif
258 return T;
259 }
260 }
261
262#if TEST_MERGE_TYPES == 2
263 ostream_iterator<const Type*> out(cerr, ", ");
264 cerr << "Input Types: ";
265 copy(ETypes.begin(), ETypes.end(), out);
266 cerr << endl;
267#endif
268
269 // Calculate the string name for the new type...
270 string Name = "{ ";
271 for (ElementTypes::const_iterator I = ETypes.begin();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000272 I != ETypes.end(); ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000273 if (I != ETypes.begin())
274 Name += ", ";
275 Name += (*I)->getName();
276 }
277 Name += " }";
278
279#if TEST_MERGE_TYPES
280 cerr << "Derived new type: " << Name << endl;
281#endif
282
283 StructType *Result = new StructType(ETypes, Name);
284 ExistingStructTypesCache.push_back(Result);
285 return Result;
286}
287
288
289const PointerType *PointerType::getPointerType(const Type *ValueType) {
290 static vector<const PointerType*> ExistingTypesCache;
291
292 // Search cache for value...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000293 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000294 const PointerType *T = ExistingTypesCache[i];
295
296 if (T->getValueType() == ValueType)
297 return T;
298 }
299
300 PointerType *Result = new PointerType(ValueType);
301 ExistingTypesCache.push_back(Result);
302
303#if TEST_MERGE_TYPES
304 cerr << "Derived new type: " << Result->getName() << endl;
305#endif
306 return Result;
307}
308