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/Support/StringExtras.h"
9 #include "llvm/CodeGen/TargetMachine.h"
11 //===----------------------------------------------------------------------===//
12 // Type Class Implementation
13 //===----------------------------------------------------------------------===//
15 static unsigned CurUID = 0;
16 static vector<const Type *> UIDMappings;
18 Type::Type(const string &name, PrimitiveID id)
19 : Value(Type::TypeTy, Value::TypeVal, name) {
23 UID = CurUID++; // Assign types UID's as they are created
24 UIDMappings.push_back(this);
27 const Type *Type::getUniqueIDType(unsigned UID) {
28 assert(UID < UIDMappings.size() &&
29 "Type::getPrimitiveType: UID out of range!");
30 return UIDMappings[UID];
33 const Type *Type::getPrimitiveType(PrimitiveID 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
58 //===----------------------------------------------------------------------===//
60 //===----------------------------------------------------------------------===//
62 // These classes are used to implement specialized behavior for each different
65 class SignedIntType : public Type {
68 SignedIntType(const string &Name, PrimitiveID id, int size) : Type(Name, id) {
72 // isSigned - Return whether a numeric type is signed.
73 virtual bool isSigned() const { return 1; }
75 // isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
76 // virtual function invocation.
78 virtual bool isIntegral() const { return 1; }
81 class UnsignedIntType : public Type {
84 UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) {
88 // isUnsigned - Return whether a numeric type is signed.
89 virtual bool isUnsigned() const { return 1; }
91 // isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
92 // virtual function invocation.
94 virtual bool isIntegral() const { return 1; }
97 static struct TypeType : public Type {
98 TypeType() : Type("type", TypeTyID) {}
99 } TheTypeType; // Implement the type that is global.
102 //===----------------------------------------------------------------------===//
103 // Static 'Type' data
104 //===----------------------------------------------------------------------===//
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);
123 //===----------------------------------------------------------------------===//
124 // Derived Type Implementations
125 //===----------------------------------------------------------------------===//
127 // Make sure that only one instance of a particular type may be created on any
128 // given run of the compiler...
130 // TODO: This list should be kept in sorted order so that we can do a binary
131 // TODO: search instead of linear search!
133 // TODO: This should be templatized so that every derived type can use the same
136 #define TEST_MERGE_TYPES 0
139 #include "llvm/Assembly/Writer.h"
142 #undef RESURRECT_OLD_LAYOUT_CODE
143 #ifdef RESURRECT_OLD_LAYOUT_CODE
146 StructType::getStorageSize(const TargetMachine& tmi) const
148 if (layoutCache->targetInfo && layoutCache->targetInfo != &tmi)
149 {// target machine has changed (hey it could happen). discard cached info.
151 layoutCache->targetInfo = &tmi;
154 if (layoutCache->storageSize < 0) {
155 layoutCache->storageSize = tmi.findOptimalStorageSize(this);
156 assert(layoutCache->storageSize >= 0);
159 return layoutCache->storageSize;
163 StructType::getElementOffset(int i, const TargetMachine& tmi) const
165 // target machine has changed (hey it could happen). discard cached info.
166 if (layoutCache->targetInfo && layoutCache->targetInfo != &tmi)
169 if (layoutCache->memberOffsets[i] < 0) {
170 layoutCache->targetInfo = &tmi; // remember which target was used
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);
180 return layoutCache->memberOffsets[i];
185 //===----------------------------------------------------------------------===//
186 // Derived Type Constructors
187 //===----------------------------------------------------------------------===//
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) {
196 ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name)
197 : Type(Name, ArrayTyID), ElementType(ElType) {
201 StructType::StructType(const vector<const Type*> &Types, const string &Name)
202 : Type(Name, StructTyID), ETypes(Types) {
205 PointerType::PointerType(const Type *E)
206 : Type(E->getName() + " *", PointerTyID), ValueType(E) {
209 //===----------------------------------------------------------------------===//
210 // Derived Type Creator Functions
211 //===----------------------------------------------------------------------===//
213 const MethodType *MethodType::getMethodType(const Type *ReturnType,
214 const vector<const Type*> &Params) {
215 static vector<const MethodType*> ExistingMethodTypesCache;
217 bool IsVarArg = Params.size() && (Params[Params.size()-1] == Type::VoidTy);
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!
228 if (I == EI && J == EParams.end()) {
229 #if TEST_MERGE_TYPES == 2
230 ostream_iterator<const Type*> out(cerr, ", ");
232 copy(Params.begin(), EI, out);
233 cerr << "\"\nEquals: \"";
234 copy(EParams.begin(), EParams.end(), out);
235 cerr << "\"" << endl;
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);
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())
254 Name += (*I)->getName();
257 if (Params.size() > 1) Name += ", ";
263 cerr << "Derived new type: " << Name << endl;
266 MethodType *Result = new MethodType(ReturnType, Params, IsVarArg, Name);
267 ExistingMethodTypesCache.push_back(Result);
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;
277 // Search cache for value...
278 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
279 const ArrayType *T = ExistingTypesCache[i];
281 if (T->getElementType() == ElementType &&
282 T->getNumElements() == NumElements)
286 // Value not found. Derive a new type!
288 if (NumElements != -1) Name += itostr(NumElements) + " x ";
290 Name += ElementType->getName();
292 ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]");
293 ExistingTypesCache.push_back(Result);
296 cerr << "Derived new type: " << Result->getName() << endl;
301 const StructType *StructType::getStructType(const ElementTypes &ETypes) {
302 static vector<const StructType*> ExistingStructTypesCache;
304 for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
305 const StructType *T = ExistingStructTypesCache[i];
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!
313 if (I == ETypes.end() && J == Elements.end()) {
314 #if TEST_MERGE_TYPES == 2
315 ostream_iterator<const Type*> out(cerr, ", ");
317 copy(ETypes.begin(), ETypes.end(), out);
318 cerr << "\"\nEquals: \"";
319 copy(Elements.begin(), Elements.end(), out);
320 cerr << "\"" << endl;
326 #if TEST_MERGE_TYPES == 2
327 ostream_iterator<const Type*> out(cerr, ", ");
328 cerr << "Input Types: ";
329 copy(ETypes.begin(), ETypes.end(), out);
333 // Calculate the string name for the new type...
335 for (ElementTypes::const_iterator I = ETypes.begin();
336 I != ETypes.end(); ++I) {
337 if (I != ETypes.begin())
339 Name += (*I)->getName();
344 cerr << "Derived new type: " << Name << endl;
347 StructType *Result = new StructType(ETypes, Name);
348 ExistingStructTypesCache.push_back(Result);
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;
357 // Search cache for value...
358 for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
359 const PointerType *T = ExistingTypesCache[i];
361 if (T->getValueType() == ValueType)
365 PointerType *Result = new PointerType(ValueType);
366 ExistingTypesCache.push_back(Result);
369 cerr << "Derived new type: " << Result->getName() << endl;