blob: 9d09e2950733685b4998c394acb48ec91981d27a [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"
Chris Lattner57dbb3a2001-07-23 17:46:59 +00008#include "llvm/Support/StringExtras.h"
Chris Lattner00950542001-06-06 20:29:01 +00009
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; }
Chris Lattner1a2cefc2001-07-21 19:15:26 +000073
74 // isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
75 // virtual function invocation.
76 //
Vikram S. Advea4e6f882001-07-21 12:32:48 +000077 virtual bool isIntegral() const { return 1; }
Chris Lattner00950542001-06-06 20:29:01 +000078};
79
80class UnsignedIntType : public Type {
81 uint64_t Size;
82public:
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; }
Chris Lattner1a2cefc2001-07-21 19:15:26 +000089
90 // isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
91 // virtual function invocation.
92 //
Vikram S. Advea4e6f882001-07-21 12:32:48 +000093 virtual bool isIntegral() const { return 1; }
Chris Lattner00950542001-06-06 20:29:01 +000094};
95
96static 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
105const 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
145MethodType::MethodType(const Type *Result, const vector<const Type*> &Params,
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000146 bool IsVarArgs, const string &Name)
147 : Type(Name, MethodTyID), ResultType(Result),
148 ParamTys(Params.begin(), Params.end()-IsVarArgs),
149 isVarArgs(IsVarArgs) {
Chris Lattner00950542001-06-06 20:29:01 +0000150}
151
152ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name)
153 : Type(Name, ArrayTyID), ElementType(ElType) {
154 NumElements = NumEl;
155}
156
157StructType::StructType(const vector<const Type*> &Types, const string &Name)
Vikram S. Adved01d99b2001-07-20 21:09:17 +0000158 : Type(Name, StructTyID),
159 ETypes(Types),
160 layoutCache(new StructSizeAndOffsetInfo)
161{
162 ResetCachedInfo();
Chris Lattner00950542001-06-06 20:29:01 +0000163}
164
165PointerType::PointerType(const Type *E)
166 : Type(E->getName() + " *", PointerTyID), ValueType(E) {
167}
168
169//===----------------------------------------------------------------------===//
170// Derived Type Creator Functions
171//===----------------------------------------------------------------------===//
172
173const MethodType *MethodType::getMethodType(const Type *ReturnType,
174 const vector<const Type*> &Params) {
175 static vector<const MethodType*> ExistingMethodTypesCache;
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000176
177 bool IsVarArg = Params.size() && (Params[Params.size()-1] == Type::VoidTy);
178
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000179 for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000180 const MethodType *T = ExistingMethodTypesCache[i];
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000181 if (T->getReturnType() == ReturnType && T->isVarArg() == IsVarArg) {
Chris Lattner00950542001-06-06 20:29:01 +0000182 const ParamTypes &EParams = T->getParamTypes();
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000183 ParamTypes::const_iterator I = Params.begin(), EI = Params.end()-IsVarArg;
Chris Lattner00950542001-06-06 20:29:01 +0000184 ParamTypes::const_iterator J = EParams.begin();
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000185 for (; I != EI && J != EParams.end(); ++I, ++J)
Chris Lattner00950542001-06-06 20:29:01 +0000186 if (*I != *J) break; // These types aren't equal!
187
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000188 if (I == EI && J == EParams.end()) {
Chris Lattner00950542001-06-06 20:29:01 +0000189#if TEST_MERGE_TYPES == 2
190 ostream_iterator<const Type*> out(cerr, ", ");
191 cerr << "Type: \"";
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000192 copy(Params.begin(), EI, out);
Chris Lattner00950542001-06-06 20:29:01 +0000193 cerr << "\"\nEquals: \"";
194 copy(EParams.begin(), EParams.end(), out);
195 cerr << "\"" << endl;
196#endif
197 return T;
198 }
199 }
200 }
201#if TEST_MERGE_TYPES == 2
202 ostream_iterator<const Type*> out(cerr, ", ");
203 cerr << "Input Types: ";
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000204 copy(Params.begin(), Params.end()-IsVarArg, out);
Chris Lattner00950542001-06-06 20:29:01 +0000205 cerr << endl;
206#endif
207
208 // Calculate the string name for the new type...
209 string Name = ReturnType->getName() + " (";
210 for (ParamTypes::const_iterator I = Params.begin();
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000211 I != (Params.end()-IsVarArg); ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000212 if (I != Params.begin())
213 Name += ", ";
214 Name += (*I)->getName();
215 }
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000216 if (IsVarArg) Name += ", ...";
Chris Lattner00950542001-06-06 20:29:01 +0000217 Name += ")";
218
219#if TEST_MERGE_TYPES
220 cerr << "Derived new type: " << Name << endl;
221#endif
222
Chris Lattnere5a57ee2001-07-25 22:47:55 +0000223 MethodType *Result = new MethodType(ReturnType, Params, IsVarArg, Name);
Chris Lattner00950542001-06-06 20:29:01 +0000224 ExistingMethodTypesCache.push_back(Result);
225 return Result;
226}
227
228
229const ArrayType *ArrayType::getArrayType(const Type *ElementType,
230 int NumElements = -1) {
Chris Lattnerab5ac6b2001-07-08 23:22:50 +0000231 assert(ElementType && "Can't get array of null types!");
Chris Lattner00950542001-06-06 20:29:01 +0000232 static vector<const ArrayType*> ExistingTypesCache;
233
234 // Search cache for value...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000235 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000236 const ArrayType *T = ExistingTypesCache[i];
237
238 if (T->getElementType() == ElementType &&
239 T->getNumElements() == NumElements)
240 return T;
241 }
242
243 // Value not found. Derive a new type!
244 string Name = "[";
245 if (NumElements != -1) Name += itostr(NumElements) + " x ";
246
247 Name += ElementType->getName();
248
249 ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
250 ExistingTypesCache.push_back(Result);
251
252#if TEST_MERGE_TYPES
253 cerr << "Derived new type: " << Result->getName() << endl;
254#endif
255 return Result;
256}
257
258const StructType *StructType::getStructType(const ElementTypes &ETypes) {
259 static vector<const StructType*> ExistingStructTypesCache;
260
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000261 for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000262 const StructType *T = ExistingStructTypesCache[i];
263
264 const ElementTypes &Elements = T->getElementTypes();
265 ElementTypes::const_iterator I = ETypes.begin();
266 ElementTypes::const_iterator J = Elements.begin();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000267 for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
Chris Lattner00950542001-06-06 20:29:01 +0000268 if (*I != *J) break; // These types aren't equal!
269
270 if (I == ETypes.end() && J == Elements.end()) {
271#if TEST_MERGE_TYPES == 2
272 ostream_iterator<const Type*> out(cerr, ", ");
273 cerr << "Type: \"";
274 copy(ETypes.begin(), ETypes.end(), out);
275 cerr << "\"\nEquals: \"";
276 copy(Elements.begin(), Elements.end(), out);
277 cerr << "\"" << endl;
278#endif
279 return T;
280 }
281 }
282
283#if TEST_MERGE_TYPES == 2
284 ostream_iterator<const Type*> out(cerr, ", ");
285 cerr << "Input Types: ";
286 copy(ETypes.begin(), ETypes.end(), out);
287 cerr << endl;
288#endif
289
290 // Calculate the string name for the new type...
291 string Name = "{ ";
292 for (ElementTypes::const_iterator I = ETypes.begin();
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000293 I != ETypes.end(); ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000294 if (I != ETypes.begin())
295 Name += ", ";
296 Name += (*I)->getName();
297 }
298 Name += " }";
299
300#if TEST_MERGE_TYPES
301 cerr << "Derived new type: " << Name << endl;
302#endif
303
304 StructType *Result = new StructType(ETypes, Name);
305 ExistingStructTypesCache.push_back(Result);
306 return Result;
307}
308
309
310const PointerType *PointerType::getPointerType(const Type *ValueType) {
Chris Lattnerab5ac6b2001-07-08 23:22:50 +0000311 assert(ValueType && "Can't get a pointer to <null> type!");
Chris Lattner00950542001-06-06 20:29:01 +0000312 static vector<const PointerType*> ExistingTypesCache;
313
314 // Search cache for value...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000315 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000316 const PointerType *T = ExistingTypesCache[i];
317
318 if (T->getValueType() == ValueType)
319 return T;
320 }
321
322 PointerType *Result = new PointerType(ValueType);
323 ExistingTypesCache.push_back(Result);
324
325#if TEST_MERGE_TYPES
326 cerr << "Derived new type: " << Result->getName() << endl;
327#endif
328 return Result;
329}
330