diff options
Diffstat (limited to 'lib/VMCore/Type.cpp')
-rw-r--r-- | lib/VMCore/Type.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp new file mode 100644 index 0000000000..cf16309ccb --- /dev/null +++ b/lib/VMCore/Type.cpp @@ -0,0 +1,308 @@ +//===-- Type.cpp - Implement the Type class ----------------------*- C++ -*--=// +// +// This file implements the Type class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/Tools/StringExtras.h" + +//===----------------------------------------------------------------------===// +// Type Class Implementation +//===----------------------------------------------------------------------===// + +static unsigned CurUID = 0; +static vector<const Type *> UIDMappings; + +Type::Type(const string &name, PrimitiveID id) + : Value(Type::TypeTy, Value::TypeVal, name) { + ID = id; + ConstRulesImpl = 0; + + UID = CurUID++; // Assign types UID's as they are created + UIDMappings.push_back(this); +} + +const Type *Type::getUniqueIDType(unsigned UID) { + assert(UID < UIDMappings.size() && + "Type::getPrimitiveType: UID out of range!"); + return UIDMappings[UID]; +} + +const Type *Type::getPrimitiveType(PrimitiveID IDNumber) { + switch (IDNumber) { + case VoidTyID : return VoidTy; + case BoolTyID : return BoolTy; + case UByteTyID : return UByteTy; + case SByteTyID : return SByteTy; + case UShortTyID: return UShortTy; + case ShortTyID : return ShortTy; + case UIntTyID : return UIntTy; + case IntTyID : return IntTy; + case ULongTyID : return ULongTy; + case LongTyID : return LongTy; + case FloatTyID : return FloatTy; + case DoubleTyID: return DoubleTy; + case TypeTyID : return TypeTy; + case LabelTyID : return LabelTy; + case LockTyID : return LockTy; + case FillerTyID: return new Type("XXX FILLER XXX", FillerTyID); // TODO:KILLME + default: + return 0; + } +} + + + +//===----------------------------------------------------------------------===// +// Auxilliary classes +//===----------------------------------------------------------------------===// +// +// These classes are used to implement specialized behavior for each different +// type. +// +class SignedIntType : public Type { + int Size; +public: + SignedIntType(const string &Name, PrimitiveID id, int size) : Type(Name, id) { + Size = size; + } + + // isSigned - Return whether a numeric type is signed. + virtual bool isSigned() const { return 1; } +}; + +class UnsignedIntType : public Type { + uint64_t Size; +public: + UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) { + Size = size; + } + + // isUnsigned - Return whether a numeric type is signed. + virtual bool isUnsigned() const { return 1; } +}; + +static struct TypeType : public Type { + TypeType() : Type("type", TypeTyID) {} +} TheTypeType; // Implement the type that is global. + + +//===----------------------------------------------------------------------===// +// Static 'Type' data +//===----------------------------------------------------------------------===// + +const Type *Type::VoidTy = new Type("void" , VoidTyID), + *Type::BoolTy = new Type("bool" , BoolTyID), + *Type::SByteTy = new SignedIntType("sbyte" , SByteTyID, 1), + *Type::UByteTy = new UnsignedIntType("ubyte" , UByteTyID, 1), + *Type::ShortTy = new SignedIntType("short" , ShortTyID, 2), + *Type::UShortTy = new UnsignedIntType("ushort", UShortTyID, 2), + *Type::IntTy = new SignedIntType("int" , IntTyID, 4), + *Type::UIntTy = new UnsignedIntType("uint" , UIntTyID, 4), + *Type::LongTy = new SignedIntType("long" , LongTyID, 8), + *Type::ULongTy = new UnsignedIntType("ulong" , ULongTyID, 8), + *Type::FloatTy = new Type("float" , FloatTyID), + *Type::DoubleTy = new Type("double", DoubleTyID), + *Type::TypeTy = &TheTypeType, + *Type::LabelTy = new Type("label" , LabelTyID), + *Type::LockTy = new Type("lock" , LockTyID); + + +//===----------------------------------------------------------------------===// +// Derived Type Implementations +//===----------------------------------------------------------------------===// + +// Make sure that only one instance of a particular type may be created on any +// given run of the compiler... +// +// TODO: This list should be kept in sorted order so that we can do a binary +// TODO: search instead of linear search! +// +// TODO: This should be templatized so that every derived type can use the same +// TODO: code! +// +#define TEST_MERGE_TYPES 0 + +#if TEST_MERGE_TYPES +#include "llvm/Assembly/Writer.h" +#endif + +//===----------------------------------------------------------------------===// +// Derived Type Constructors +//===----------------------------------------------------------------------===// + +MethodType::MethodType(const Type *Result, const vector<const Type*> &Params, + const string &Name) + : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) { +} + +ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name) + : Type(Name, ArrayTyID), ElementType(ElType) { + NumElements = NumEl; +} + +StructType::StructType(const vector<const Type*> &Types, const string &Name) + : Type(Name, StructTyID), ETypes(Types) { +} + +PointerType::PointerType(const Type *E) + : Type(E->getName() + " *", PointerTyID), ValueType(E) { +} + +//===----------------------------------------------------------------------===// +// Derived Type Creator Functions +//===----------------------------------------------------------------------===// + +const MethodType *MethodType::getMethodType(const Type *ReturnType, + const vector<const Type*> &Params) { + static vector<const MethodType*> ExistingMethodTypesCache; + for (unsigned i = 0; i < ExistingMethodTypesCache.size(); i++) { + const MethodType *T = ExistingMethodTypesCache[i]; + if (T->getReturnType() == ReturnType) { + const ParamTypes &EParams = T->getParamTypes(); + ParamTypes::const_iterator I = Params.begin(); + ParamTypes::const_iterator J = EParams.begin(); + for (; I != Params.end() && J != EParams.end(); I++, J++) + if (*I != *J) break; // These types aren't equal! + + if (I == Params.end() && J == EParams.end()) { +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Type: \""; + copy(Params.begin(), Params.end(), out); + cerr << "\"\nEquals: \""; + copy(EParams.begin(), EParams.end(), out); + cerr << "\"" << endl; +#endif + return T; + } + } + } +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Input Types: "; + copy(Params.begin(), Params.end(), out); + cerr << endl; +#endif + + // Calculate the string name for the new type... + string Name = ReturnType->getName() + " ("; + for (ParamTypes::const_iterator I = Params.begin(); + I != Params.end(); I++) { + if (I != Params.begin()) + Name += ", "; + Name += (*I)->getName(); + } + Name += ")"; + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Name << endl; +#endif + + MethodType *Result = new MethodType(ReturnType, Params, Name); + ExistingMethodTypesCache.push_back(Result); + return Result; +} + + +const ArrayType *ArrayType::getArrayType(const Type *ElementType, + int NumElements = -1) { + static vector<const ArrayType*> ExistingTypesCache; + + // Search cache for value... + for (unsigned i = 0; i < ExistingTypesCache.size(); i++) { + const ArrayType *T = ExistingTypesCache[i]; + + if (T->getElementType() == ElementType && + T->getNumElements() == NumElements) + return T; + } + + // Value not found. Derive a new type! + string Name = "["; + if (NumElements != -1) Name += itostr(NumElements) + " x "; + + Name += ElementType->getName(); + + ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]"); + ExistingTypesCache.push_back(Result); + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Result->getName() << endl; +#endif + return Result; +} + +const StructType *StructType::getStructType(const ElementTypes &ETypes) { + static vector<const StructType*> ExistingStructTypesCache; + + for (unsigned i = 0; i < ExistingStructTypesCache.size(); i++) { + const StructType *T = ExistingStructTypesCache[i]; + + const ElementTypes &Elements = T->getElementTypes(); + ElementTypes::const_iterator I = ETypes.begin(); + ElementTypes::const_iterator J = Elements.begin(); + for (; I != ETypes.end() && J != Elements.end(); I++, J++) + if (*I != *J) break; // These types aren't equal! + + if (I == ETypes.end() && J == Elements.end()) { +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Type: \""; + copy(ETypes.begin(), ETypes.end(), out); + cerr << "\"\nEquals: \""; + copy(Elements.begin(), Elements.end(), out); + cerr << "\"" << endl; +#endif + return T; + } + } + +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Input Types: "; + copy(ETypes.begin(), ETypes.end(), out); + cerr << endl; +#endif + + // Calculate the string name for the new type... + string Name = "{ "; + for (ElementTypes::const_iterator I = ETypes.begin(); + I != ETypes.end(); I++) { + if (I != ETypes.begin()) + Name += ", "; + Name += (*I)->getName(); + } + Name += " }"; + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Name << endl; +#endif + + StructType *Result = new StructType(ETypes, Name); + ExistingStructTypesCache.push_back(Result); + return Result; +} + + +const PointerType *PointerType::getPointerType(const Type *ValueType) { + static vector<const PointerType*> ExistingTypesCache; + + // Search cache for value... + for (unsigned i = 0; i < ExistingTypesCache.size(); i++) { + const PointerType *T = ExistingTypesCache[i]; + + if (T->getValueType() == ValueType) + return T; + } + + PointerType *Result = new PointerType(ValueType); + ExistingTypesCache.push_back(Result); + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Result->getName() << endl; +#endif + return Result; +} + |