2001-06-06 20:29:01 +00:00
|
|
|
//===-- Type.cpp - Implement the Type class ----------------------*- C++ -*--=//
|
|
|
|
//
|
|
|
|
// This file implements the Type class for the VMCore library.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/DerivedTypes.h"
|
2001-07-23 17:46:59 +00:00
|
|
|
#include "llvm/Support/StringExtras.h"
|
2001-06-06 20:29:01 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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; }
|
2001-07-21 19:15:26 +00:00
|
|
|
|
|
|
|
// isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
|
|
|
|
// virtual function invocation.
|
|
|
|
//
|
2001-07-21 12:32:48 +00:00
|
|
|
virtual bool isIntegral() const { return 1; }
|
2001-06-06 20:29:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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; }
|
2001-07-21 19:15:26 +00:00
|
|
|
|
|
|
|
// isIntegral - Equivalent to isSigned() || isUnsigned, but with only a single
|
|
|
|
// virtual function invocation.
|
|
|
|
//
|
2001-07-21 12:32:48 +00:00
|
|
|
virtual bool isIntegral() const { return 1; }
|
2001-06-06 20:29:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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,
|
2001-07-25 22:47:55 +00:00
|
|
|
bool IsVarArgs, const string &Name)
|
|
|
|
: Type(Name, MethodTyID), ResultType(Result),
|
|
|
|
ParamTys(Params.begin(), Params.end()-IsVarArgs),
|
|
|
|
isVarArgs(IsVarArgs) {
|
2001-06-06 20:29:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2001-08-27 15:52:13 +00:00
|
|
|
: Type(Name, StructTyID), ETypes(Types) {
|
2001-06-06 20:29:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2001-07-25 22:47:55 +00:00
|
|
|
|
|
|
|
bool IsVarArg = Params.size() && (Params[Params.size()-1] == Type::VoidTy);
|
|
|
|
|
2001-06-27 23:41:11 +00:00
|
|
|
for (unsigned i = 0; i < ExistingMethodTypesCache.size(); ++i) {
|
2001-06-06 20:29:01 +00:00
|
|
|
const MethodType *T = ExistingMethodTypesCache[i];
|
2001-07-25 22:47:55 +00:00
|
|
|
if (T->getReturnType() == ReturnType && T->isVarArg() == IsVarArg) {
|
2001-06-06 20:29:01 +00:00
|
|
|
const ParamTypes &EParams = T->getParamTypes();
|
2001-07-25 22:47:55 +00:00
|
|
|
ParamTypes::const_iterator I = Params.begin(), EI = Params.end()-IsVarArg;
|
2001-06-06 20:29:01 +00:00
|
|
|
ParamTypes::const_iterator J = EParams.begin();
|
2001-07-25 22:47:55 +00:00
|
|
|
for (; I != EI && J != EParams.end(); ++I, ++J)
|
2001-06-06 20:29:01 +00:00
|
|
|
if (*I != *J) break; // These types aren't equal!
|
|
|
|
|
2001-07-25 22:47:55 +00:00
|
|
|
if (I == EI && J == EParams.end()) {
|
2001-06-06 20:29:01 +00:00
|
|
|
#if TEST_MERGE_TYPES == 2
|
|
|
|
ostream_iterator<const Type*> out(cerr, ", ");
|
|
|
|
cerr << "Type: \"";
|
2001-07-25 22:47:55 +00:00
|
|
|
copy(Params.begin(), EI, out);
|
2001-06-06 20:29:01 +00:00
|
|
|
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: ";
|
2001-07-25 22:47:55 +00:00
|
|
|
copy(Params.begin(), Params.end()-IsVarArg, out);
|
2001-06-06 20:29:01 +00:00
|
|
|
cerr << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Calculate the string name for the new type...
|
|
|
|
string Name = ReturnType->getName() + " (";
|
|
|
|
for (ParamTypes::const_iterator I = Params.begin();
|
2001-07-25 22:47:55 +00:00
|
|
|
I != (Params.end()-IsVarArg); ++I) {
|
2001-06-06 20:29:01 +00:00
|
|
|
if (I != Params.begin())
|
|
|
|
Name += ", ";
|
|
|
|
Name += (*I)->getName();
|
|
|
|
}
|
2001-07-28 17:52:35 +00:00
|
|
|
if (IsVarArg) {
|
|
|
|
if (Params.size() > 1) Name += ", ";
|
|
|
|
Name += "...";
|
|
|
|
}
|
2001-06-06 20:29:01 +00:00
|
|
|
Name += ")";
|
|
|
|
|
|
|
|
#if TEST_MERGE_TYPES
|
|
|
|
cerr << "Derived new type: " << Name << endl;
|
|
|
|
#endif
|
|
|
|
|
2001-07-25 22:47:55 +00:00
|
|
|
MethodType *Result = new MethodType(ReturnType, Params, IsVarArg, Name);
|
2001-06-06 20:29:01 +00:00
|
|
|
ExistingMethodTypesCache.push_back(Result);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const ArrayType *ArrayType::getArrayType(const Type *ElementType,
|
|
|
|
int NumElements = -1) {
|
2001-07-08 23:22:50 +00:00
|
|
|
assert(ElementType && "Can't get array of null types!");
|
2001-06-06 20:29:01 +00:00
|
|
|
static vector<const ArrayType*> ExistingTypesCache;
|
|
|
|
|
|
|
|
// Search cache for value...
|
2001-06-27 23:41:11 +00:00
|
|
|
for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
|
2001-06-06 20:29:01 +00:00
|
|
|
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;
|
|
|
|
|
2001-06-27 23:41:11 +00:00
|
|
|
for (unsigned i = 0; i < ExistingStructTypesCache.size(); ++i) {
|
2001-06-06 20:29:01 +00:00
|
|
|
const StructType *T = ExistingStructTypesCache[i];
|
|
|
|
|
|
|
|
const ElementTypes &Elements = T->getElementTypes();
|
|
|
|
ElementTypes::const_iterator I = ETypes.begin();
|
|
|
|
ElementTypes::const_iterator J = Elements.begin();
|
2001-06-27 23:41:11 +00:00
|
|
|
for (; I != ETypes.end() && J != Elements.end(); ++I, ++J)
|
2001-06-06 20:29:01 +00:00
|
|
|
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();
|
2001-06-27 23:41:11 +00:00
|
|
|
I != ETypes.end(); ++I) {
|
2001-06-06 20:29:01 +00:00
|
|
|
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) {
|
2001-07-08 23:22:50 +00:00
|
|
|
assert(ValueType && "Can't get a pointer to <null> type!");
|
2001-06-06 20:29:01 +00:00
|
|
|
static vector<const PointerType*> ExistingTypesCache;
|
|
|
|
|
|
|
|
// Search cache for value...
|
2001-06-27 23:41:11 +00:00
|
|
|
for (unsigned i = 0; i < ExistingTypesCache.size(); ++i) {
|
2001-06-06 20:29:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|