1 //===-- Type.cpp - Implement the Type class ----------------------*- C++ -*--=//
3 // This file implements the Type class for the VMCore library.
5 //===----------------------------------------------------------------------===//
7 #include "llvm/DerivedTypes.h"
8 #include "llvm/Tools/StringExtras.h"
10 //===----------------------------------------------------------------------===//
11 // Type Class Implementation
12 //===----------------------------------------------------------------------===//
14 static unsigned CurUID = 0;
15 static vector<const Type *> UIDMappings;
17 Type::Type(const string &name, PrimitiveID id)
18 : Value(Type::TypeTy, Value::TypeVal, name) {
22 UID = CurUID++; // Assign types UID's as they are created
23 UIDMappings.push_back(this);
26 const Type *Type::getUniqueIDType(unsigned UID) {
27 assert(UID < UIDMappings.size() &&
28 "Type::getPrimitiveType: UID out of range!");
29 return UIDMappings[UID];
32 const Type *Type::getPrimitiveType(PrimitiveID 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
57 //===----------------------------------------------------------------------===//
59 //===----------------------------------------------------------------------===//
61 // These classes are used to implement specialized behavior for each different
64 class SignedIntType : public Type {
67 SignedIntType(const string &Name, PrimitiveID id, int size) : Type(Name, id) {
71 // isSigned - Return whether a numeric type is signed.
72 virtual bool isSigned() const { return 1; }
74 // isIntegral - Return whether this is one of the integer types
75 virtual bool isIntegral() const { return 1; }
78 class UnsignedIntType : public Type {
81 UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) {
85 // isUnsigned - Return whether a numeric type is signed.
86 virtual bool isUnsigned() const { return 1; }
88 // isIntegral - Return whether this is one of the integer types
89 virtual bool isIntegral() const { return 1; }
92 static struct TypeType : public Type {
93 TypeType() : Type("type", TypeTyID) {}
94 } TheTypeType; // Implement the type that is global.
97 //===----------------------------------------------------------------------===//
99 //===----------------------------------------------------------------------===//
101 const Type *Type::VoidTy = new Type("void" , VoidTyID),
102 *Type::BoolTy = new Type("bool" , BoolTyID),
103 *Type::SByteTy = new SignedIntType("sbyte" , SByteTyID, 1),
104 *Type::UByteTy = new UnsignedIntType("ubyte" , UByteTyID, 1),
105 *Type::ShortTy = new SignedIntType("short" , ShortTyID, 2),
106 *Type::UShortTy = new UnsignedIntType("ushort", UShortTyID, 2),
107 *Type::IntTy = new SignedIntType("int" , IntTyID, 4),
108 *Type::UIntTy = new UnsignedIntType("uint" , UIntTyID, 4),
109 *Type::LongTy = new SignedIntType("long" , LongTyID, 8),
110 *Type::ULongTy = new UnsignedIntType("ulong" , ULongTyID, 8),
111 *Type::FloatTy = new Type("float" , FloatTyID),
112 *Type::DoubleTy = new Type("double", DoubleTyID),
113 *Type::TypeTy = &TheTypeType,
114 *Type::LabelTy = new Type("label" , LabelTyID),
115 *Type::LockTy = new Type("lock" , LockTyID);
118 //===----------------------------------------------------------------------===//
119 // Derived Type Implementations
120 //===----------------------------------------------------------------------===//
122 // Make sure that only one instance of a particular type may be created on any
123 // given run of the compiler...
125 // TODO: This list should be kept in sorted order so that we can do a binary
126 // TODO: search instead of linear search!
128 // TODO: This should be templatized so that every derived type can use the same
131 #define TEST_MERGE_TYPES 0
134 #include "llvm/Assembly/Writer.h"
137 //===----------------------------------------------------------------------===//
138 // Derived Type Constructors
139 //===----------------------------------------------------------------------===//
141 MethodType::MethodType(const Type *Result, const vector<const Type*> &Params,
143 : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) {
146 ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name)
147 : Type(Name, ArrayTyID), ElementType(ElType) {
151 StructType::StructType(const vector<const Type*> &Types, const string &Name)
152 : Type(Name, StructTyID),
154 layoutCache(new StructSizeAndOffsetInfo)
159 PointerType::PointerType(const Type *E)
160 : Type(E->getName() + " *", PointerTyID), ValueType(E) {
163 //===----------------------------------------------------------------------===//
164 // Derived Type Creator Functions
165 //===----------------------------------------------------------------------===//
167 const MethodType *MethodType::getMethodType(const Type *ReturnType,
168 const vector<const Type*> &Params) {
169 static vector<const MethodType*> ExistingMethodTypesCache;
170 for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
171 const MethodType *T = ExistingMethodTypesCache[i];
172 if (T->getReturnType() == ReturnType) {
173 const ParamTypes &EParams = T->getParamTypes();
174 ParamTypes::const_iterator I = Params.begin();
175 ParamTypes::const_iterator J = EParams.begin();
176 for (; I != Params.end() && J != EParams.end(); ++I, ++J)
177 if (*I != *J) break; // These types aren't equal!
179 if (I == Params.end() && J == EParams.end()) {
180 #if TEST_MERGE_TYPES == 2
181 ostream_iterator<const Type*> out(cerr, ", ");
183 copy(Params.begin(), Params.end(), out);
184 cerr << "\"\nEquals: \"";
185 copy(EParams.begin(), EParams.end(), out);
186 cerr << "\"" << endl;
192 #if TEST_MERGE_TYPES == 2
193 ostream_iterator<const Type*> out(cerr, ", ");
194 cerr << "Input Types: ";
195 copy(Params.begin(), Params.end(), out);
199 // Calculate the string name for the new type...
200 string Name = ReturnType->getName() + " (";
201 for (ParamTypes::const_iterator I = Params.begin();
202 I != Params.end(); ++I) {
203 if (I != Params.begin())
205 Name += (*I)->getName();
210 cerr << "Derived new type: " << Name << endl;
213 MethodType *Result = new MethodType(ReturnType, Params, Name);
214 ExistingMethodTypesCache.push_back(Result);
219 const ArrayType *ArrayType::getArrayType(const Type *ElementType,
220 int NumElements = -1) {
221 assert(ElementType && "Can't get array of null types!");
222 static vector<const ArrayType*> ExistingTypesCache;
224 // Search cache for value...
225 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
226 const ArrayType *T = ExistingTypesCache[i];
228 if (T->getElementType() == ElementType &&
229 T->getNumElements() == NumElements)
233 // Value not found. Derive a new type!
235 if (NumElements != -1) Name += itostr(NumElements) + " x ";
237 Name += ElementType->getName();
239 ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
240 ExistingTypesCache.push_back(Result);
243 cerr << "Derived new type: " << Result->getName() << endl;
248 const StructType *StructType::getStructType(const ElementTypes &ETypes) {
249 static vector<const StructType*> ExistingStructTypesCache;
251 for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
252 const StructType *T = ExistingStructTypesCache[i];
254 const ElementTypes &Elements = T->getElementTypes();
255 ElementTypes::const_iterator I = ETypes.begin();
256 ElementTypes::const_iterator J = Elements.begin();
257 for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
258 if (*I != *J) break; // These types aren't equal!
260 if (I == ETypes.end() && J == Elements.end()) {
261 #if TEST_MERGE_TYPES == 2
262 ostream_iterator<const Type*> out(cerr, ", ");
264 copy(ETypes.begin(), ETypes.end(), out);
265 cerr << "\"\nEquals: \"";
266 copy(Elements.begin(), Elements.end(), out);
267 cerr << "\"" << endl;
273 #if TEST_MERGE_TYPES == 2
274 ostream_iterator<const Type*> out(cerr, ", ");
275 cerr << "Input Types: ";
276 copy(ETypes.begin(), ETypes.end(), out);
280 // Calculate the string name for the new type...
282 for (ElementTypes::const_iterator I = ETypes.begin();
283 I != ETypes.end(); ++I) {
284 if (I != ETypes.begin())
286 Name += (*I)->getName();
291 cerr << "Derived new type: " << Name << endl;
294 StructType *Result = new StructType(ETypes, Name);
295 ExistingStructTypesCache.push_back(Result);
300 const PointerType *PointerType::getPointerType(const Type *ValueType) {
301 assert(ValueType && "Can't get a pointer to <null> type!");
302 static vector<const PointerType*> ExistingTypesCache;
304 // Search cache for value...
305 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
306 const PointerType *T = ExistingTypesCache[i];
308 if (T->getValueType() == ValueType)
312 PointerType *Result = new PointerType(ValueType);
313 ExistingTypesCache.push_back(Result);
316 cerr << "Derived new type: " << Result->getName() << endl;