diff options
Diffstat (limited to 'lib/VMCore/Type.cpp')
-rw-r--r-- | lib/VMCore/Type.cpp | 1205 |
1 files changed, 339 insertions, 866 deletions
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 92990709202..734d43a0174 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -12,81 +12,17 @@ //===----------------------------------------------------------------------===// #include "LLVMContextImpl.h" -#include "llvm/ADT/SCCIterator.h" +#include "llvm/Module.h" #include <algorithm> #include <cstdarg> +#include "llvm/ADT/SmallString.h" using namespace llvm; -// DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are -// created and later destroyed, all in an effort to make sure that there is only -// a single canonical version of a type. -// -// #define DEBUG_MERGE_TYPES 1 - -AbstractTypeUser::~AbstractTypeUser() {} - -void AbstractTypeUser::setType(Value *V, const Type *NewTy) { - V->VTy = NewTy; -} - //===----------------------------------------------------------------------===// // Type Class Implementation //===----------------------------------------------------------------------===// -/// Because of the way Type subclasses are allocated, this function is necessary -/// to use the correct kind of "delete" operator to deallocate the Type object. -/// Some type objects (FunctionTy, StructTy) allocate additional space -/// after the space for their derived type to hold the contained types array of -/// PATypeHandles. Using this allocation scheme means all the PATypeHandles are -/// allocated with the type object, decreasing allocations and eliminating the -/// need for a std::vector to be used in the Type class itself. -/// @brief Type destruction function -void Type::destroy() const { - // Nothing calls getForwardedType from here on. - if (ForwardType && ForwardType->isAbstract()) { - ForwardType->dropRef(); - ForwardType = NULL; - } - - // Structures and Functions allocate their contained types past the end of - // the type object itself. These need to be destroyed differently than the - // other types. - if (this->isFunctionTy() || this->isStructTy()) { - // First, make sure we destruct any PATypeHandles allocated by these - // subclasses. They must be manually destructed. - for (unsigned i = 0; i < NumContainedTys; ++i) - ContainedTys[i].PATypeHandle::~PATypeHandle(); - - // Now call the destructor for the subclass directly because we're going - // to delete this as an array of char. - if (this->isFunctionTy()) - static_cast<const FunctionType*>(this)->FunctionType::~FunctionType(); - else { - assert(isStructTy()); - static_cast<const StructType*>(this)->StructType::~StructType(); - } - - // Finally, remove the memory as an array deallocation of the chars it was - // constructed from. - operator delete(const_cast<Type *>(this)); - - return; - } - - if (const OpaqueType *opaque_this = dyn_cast<OpaqueType>(this)) { - LLVMContextImpl *pImpl = this->getContext().pImpl; - pImpl->OpaqueTypes.erase(opaque_this); - } - - // For all the other type subclasses, there is either no contained types or - // just one (all Sequentials). For Sequentials, the PATypeHandle is not - // allocated past the type object, its included directly in the SequentialType - // class. This means we can safely just do "normal" delete of this object and - // all the destructors that need to run will be run. - delete this; -} - -const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { +Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { switch (IDNumber) { case VoidTyID : return getVoidTy(C); case FloatTyID : return getFloatTy(C); @@ -245,7 +181,11 @@ bool Type::isSizedDerivedType() const { if (!this->isStructTy()) return false; - // Okay, our struct is sized if all of the elements are... + // Opaque structs have no size. + if (cast<StructType>(this)->isOpaque()) + return false; + + // Okay, our struct is sized if all of the elements are. for (subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I) if (!(*I)->isSized()) return false; @@ -253,703 +193,346 @@ bool Type::isSizedDerivedType() const { return true; } -/// getForwardedTypeInternal - This method is used to implement the union-find -/// algorithm for when a type is being forwarded to another type. -const Type *Type::getForwardedTypeInternal() const { - assert(ForwardType && "This type is not being forwarded to another type!"); - - // Check to see if the forwarded type has been forwarded on. If so, collapse - // the forwarding links. - const Type *RealForwardedType = ForwardType->getForwardedType(); - if (!RealForwardedType) - return ForwardType; // No it's not forwarded again - - // Yes, it is forwarded again. First thing, add the reference to the new - // forward type. - if (RealForwardedType->isAbstract()) - RealForwardedType->addRef(); - - // Now drop the old reference. This could cause ForwardType to get deleted. - // ForwardType must be abstract because only abstract types can have their own - // ForwardTypes. - ForwardType->dropRef(); - - // Return the updated type. - ForwardType = RealForwardedType; - return ForwardType; -} - -void Type::refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - llvm_unreachable("Attempting to refine a derived type!"); -} -void Type::typeBecameConcrete(const DerivedType *AbsTy) { - llvm_unreachable("DerivedType is already a concrete type!"); -} - -const Type *CompositeType::getTypeAtIndex(const Value *V) const { - if (const StructType *STy = dyn_cast<StructType>(this)) { - unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue(); - assert(indexValid(Idx) && "Invalid structure index!"); - return STy->getElementType(Idx); - } - - return cast<SequentialType>(this)->getElementType(); -} -const Type *CompositeType::getTypeAtIndex(unsigned Idx) const { - if (const StructType *STy = dyn_cast<StructType>(this)) { - assert(indexValid(Idx) && "Invalid structure index!"); - return STy->getElementType(Idx); - } - - return cast<SequentialType>(this)->getElementType(); -} -bool CompositeType::indexValid(const Value *V) const { - if (const StructType *STy = dyn_cast<StructType>(this)) { - // Structure indexes require 32-bit integer constants. - if (V->getType()->isIntegerTy(32)) - if (const ConstantInt *CU = dyn_cast<ConstantInt>(V)) - return CU->getZExtValue() < STy->getNumElements(); - return false; - } - - // Sequential types can be indexed by any integer. - return V->getType()->isIntegerTy(); -} - -bool CompositeType::indexValid(unsigned Idx) const { - if (const StructType *STy = dyn_cast<StructType>(this)) - return Idx < STy->getNumElements(); - // Sequential types can be indexed by any integer. - return true; -} - - //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// -const Type *Type::getVoidTy(LLVMContext &C) { - return &C.pImpl->VoidTy; -} - -const Type *Type::getLabelTy(LLVMContext &C) { - return &C.pImpl->LabelTy; -} - -const Type *Type::getFloatTy(LLVMContext &C) { - return &C.pImpl->FloatTy; -} - -const Type *Type::getDoubleTy(LLVMContext &C) { - return &C.pImpl->DoubleTy; -} - -const Type *Type::getMetadataTy(LLVMContext &C) { - return &C.pImpl->MetadataTy; -} - -const Type *Type::getX86_FP80Ty(LLVMContext &C) { - return &C.pImpl->X86_FP80Ty; -} - -const Type *Type::getFP128Ty(LLVMContext &C) { - return &C.pImpl->FP128Ty; -} - -const Type *Type::getPPC_FP128Ty(LLVMContext &C) { - return &C.pImpl->PPC_FP128Ty; -} - -const Type *Type::getX86_MMXTy(LLVMContext &C) { - return &C.pImpl->X86_MMXTy; -} - -const IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) { +Type *Type::getVoidTy(LLVMContext &C) { return &C.pImpl->VoidTy; } +Type *Type::getLabelTy(LLVMContext &C) { return &C.pImpl->LabelTy; } +Type *Type::getFloatTy(LLVMContext &C) { return &C.pImpl->FloatTy; } +Type *Type::getDoubleTy(LLVMContext &C) { return &C.pImpl->DoubleTy; } +Type *Type::getMetadataTy(LLVMContext &C) { return &C.pImpl->MetadataTy; } +Type *Type::getX86_FP80Ty(LLVMContext &C) { return &C.pImpl->X86_FP80Ty; } +Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; } +Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; } +Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; } + +IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; } +IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; } +IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; } +IntegerType *Type::getInt32Ty(LLVMContext &C) { return &C.pImpl->Int32Ty; } +IntegerType *Type::getInt64Ty(LLVMContext &C) { return &C.pImpl->Int64Ty; } + +IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) { return IntegerType::get(C, N); } -const IntegerType *Type::getInt1Ty(LLVMContext &C) { - return &C.pImpl->Int1Ty; -} - -const IntegerType *Type::getInt8Ty(LLVMContext &C) { - return &C.pImpl->Int8Ty; -} - -const IntegerType *Type::getInt16Ty(LLVMContext &C) { - return &C.pImpl->Int16Ty; -} - -const IntegerType *Type::getInt32Ty(LLVMContext &C) { - return &C.pImpl->Int32Ty; -} - -const IntegerType *Type::getInt64Ty(LLVMContext &C) { - return &C.pImpl->Int64Ty; -} - -const PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) { return getFloatTy(C)->getPointerTo(AS); } -const PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) { return getDoubleTy(C)->getPointerTo(AS); } -const PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) { return getX86_FP80Ty(C)->getPointerTo(AS); } -const PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) { return getFP128Ty(C)->getPointerTo(AS); } -const PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) { return getPPC_FP128Ty(C)->getPointerTo(AS); } -const PointerType *Type::getX86_MMXPtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getX86_MMXPtrTy(LLVMContext &C, unsigned AS) { return getX86_MMXTy(C)->getPointerTo(AS); } -const PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) { +PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) { return getIntNTy(C, N)->getPointerTo(AS); } -const PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) { return getInt1Ty(C)->getPointerTo(AS); } -const PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) { return getInt8Ty(C)->getPointerTo(AS); } -const PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) { return getInt16Ty(C)->getPointerTo(AS); } -const PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) { return getInt32Ty(C)->getPointerTo(AS); } -const PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) { +PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) { return getInt64Ty(C)->getPointerTo(AS); } + //===----------------------------------------------------------------------===// -// Derived Type Constructors +// IntegerType Implementation //===----------------------------------------------------------------------===// -/// isValidReturnType - Return true if the specified type is valid as a return -/// type. -bool FunctionType::isValidReturnType(const Type *RetTy) { - return !RetTy->isFunctionTy() && !RetTy->isLabelTy() && - !RetTy->isMetadataTy(); +IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { + assert(NumBits >= MIN_INT_BITS && "bitwidth too small"); + assert(NumBits <= MAX_INT_BITS && "bitwidth too large"); + + // Check for the built-in integer types + switch (NumBits) { + case 1: return cast<IntegerType>(Type::getInt1Ty(C)); + case 8: return cast<IntegerType>(Type::getInt8Ty(C)); + case 16: return cast<IntegerType>(Type::getInt16Ty(C)); + case 32: return cast<IntegerType>(Type::getInt32Ty(C)); + case 64: return cast<IntegerType>(Type::getInt64Ty(C)); + default: + break; + } + + IntegerType *&Entry = C.pImpl->IntegerTypes[NumBits]; + + if (Entry == 0) + Entry = new IntegerType(C, NumBits); + + return Entry; } -/// isValidArgumentType - Return true if the specified type is valid as an -/// argument type. -bool FunctionType::isValidArgumentType(const Type *ArgTy) { - return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy(); +bool IntegerType::isPowerOf2ByteWidth() const { + unsigned BitWidth = getBitWidth(); + return (BitWidth > 7) && isPowerOf2_32(BitWidth); +} + +APInt IntegerType::getMask() const { + return APInt::getAllOnesValue(getBitWidth()); } -FunctionType::FunctionType(const Type *Result, - ArrayRef<const Type*> Params, +//===----------------------------------------------------------------------===// +// FunctionType Implementation +//===----------------------------------------------------------------------===// + +FunctionType::FunctionType(const Type *Result, ArrayRef<Type*> Params, bool IsVarArgs) : DerivedType(Result->getContext(), FunctionTyID) { - ContainedTys = reinterpret_cast<PATypeHandle*>(this+1); - NumContainedTys = Params.size() + 1; // + 1 for result type + Type **SubTys = reinterpret_cast<Type**>(this+1); assert(isValidReturnType(Result) && "invalid return type for function"); setSubclassData(IsVarArgs); - bool isAbstract = Result->isAbstract(); - new (&ContainedTys[0]) PATypeHandle(Result, this); + SubTys[0] = const_cast<Type*>(Result); - for (unsigned i = 0; i != Params.size(); ++i) { + for (unsigned i = 0, e = Params.size(); i != e; ++i) { assert(isValidArgumentType(Params[i]) && "Not a valid type for function argument!"); - new (&ContainedTys[i+1]) PATypeHandle(Params[i], this); - isAbstract |= Params[i]->isAbstract(); - } - - // Calculate whether or not this type is abstract - setAbstract(isAbstract); -} - -StructType::StructType(LLVMContext &C, - ArrayRef<const Type*> Types, bool isPacked) - : CompositeType(C, StructTyID) { - ContainedTys = reinterpret_cast<PATypeHandle*>(this + 1); - NumContainedTys = Types.size(); - setSubclassData(isPacked); - bool isAbstract = false; - for (unsigned i = 0; i < Types.size(); ++i) { - assert(Types[i] && "<null> type for structure field!"); - assert(isValidElementType(Types[i]) && - "Invalid type for structure element!"); - new (&ContainedTys[i]) PATypeHandle(Types[i], this); - isAbstract |= Types[i]->isAbstract(); + SubTys[i+1] = Params[i]; } - // Calculate whether or not this type is abstract - setAbstract(isAbstract); -} - -ArrayType::ArrayType(const Type *ElType, uint64_t NumEl) - : SequentialType(ArrayTyID, ElType) { - NumElements = NumEl; - - // Calculate whether or not this type is abstract - setAbstract(ElType->isAbstract()); + ContainedTys = SubTys; + NumContainedTys = Params.size() + 1; // + 1 for result type } -VectorType::VectorType(const Type *ElType, unsigned NumEl) - : SequentialType(VectorTyID, ElType) { - NumElements = NumEl; - setAbstract(ElType->isAbstract()); - assert(NumEl > 0 && "NumEl of a VectorType must be greater than 0"); - assert(isValidElementType(ElType) && - "Elements of a VectorType must be a primitive type"); - +// FIXME: Remove this version. +FunctionType *FunctionType::get(const Type *ReturnType, + ArrayRef<const Type*> Params, bool isVarArg) { + return get(ReturnType, ArrayRef<Type*>(const_cast<Type**>(Params.data()), + Params.size()), isVarArg); } +// FunctionType::get - The factory function for the FunctionType class. +FunctionType *FunctionType::get(const Type *ReturnType, + ArrayRef<Type*> Params, bool isVarArg) { + // TODO: This is brutally slow. + std::vector<Type*> Key; + Key.reserve(Params.size()+2); + Key.push_back(const_cast<Type*>(ReturnType)); + for (unsigned i = 0, e = Params.size(); i != e; ++i) + Key.push_back(const_cast<Type*>(Params[i])); + if (isVarArg) + Key.push_back(0); + + FunctionType *&FT = ReturnType->getContext().pImpl->FunctionTypes[Key]; + + if (FT == 0) { + FT = (FunctionType*) operator new(sizeof(FunctionType) + + sizeof(Type*)*(Params.size()+1)); + new (FT) FunctionType(ReturnType, Params, isVarArg); + } -PointerType::PointerType(const Type *E, unsigned AddrSpace) - : SequentialType(PointerTyID, E) { - setSubclassData(AddrSpace); - // Calculate whether or not this type is abstract - setAbstract(E->isAbstract()); -} - -OpaqueType::OpaqueType(LLVMContext &C) : DerivedType(C, OpaqueTyID) { - setAbstract(true); -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *this << "\n"); -#endif + return FT; } -void PATypeHolder::destroy() { - Ty = 0; -} -// dropAllTypeUses - When this (abstract) type is resolved to be equal to -// another (more concrete) type, we must eliminate all references to other -// types, to avoid some circular reference problems. -void DerivedType::dropAllTypeUses() { - if (NumContainedTys != 0) { - // The type must stay abstract. To do this, we insert a pointer to a type - // that will never get resolved, thus will always be abstract. - ContainedTys[0] = getContext().pImpl->AlwaysOpaqueTy; - - // Change the rest of the types to be Int32Ty's. It doesn't matter what we - // pick so long as it doesn't point back to this type. We choose something - // concrete to avoid overhead for adding to AbstractTypeUser lists and - // stuff. - const Type *ConcreteTy = Type::getInt32Ty(getContext()); - for (unsigned i = 1, e = NumContainedTys; i != e; ++i) - ContainedTys[i] = ConcreteTy; - } +FunctionType *FunctionType::get(const Type *Result, bool isVarArg) { + return get(Result, ArrayRef<const Type *>(), isVarArg); } -namespace { - -/// TypePromotionGraph and graph traits - this is designed to allow us to do -/// efficient SCC processing of type graphs. This is the exact same as -/// GraphTraits<Type*>, except that we pretend that concrete types have no -/// children to avoid processing them. -struct TypePromotionGraph { - Type *Ty; - TypePromotionGraph(Type *T) : Ty(T) {} -}; - -} - -namespace llvm { - template <> struct GraphTraits<TypePromotionGraph> { - typedef Type NodeType; - typedef Type::subtype_iterator ChildIteratorType; - - static inline NodeType *getEntryNode(TypePromotionGraph G) { return G.Ty; } - static inline ChildIteratorType child_begin(NodeType *N) { - if (N->isAbstract()) - return N->subtype_begin(); - // No need to process children of concrete types. - return N->subtype_end(); - } - static inline ChildIteratorType child_end(NodeType *N) { - return N->subtype_end(); - } - }; +/// isValidReturnType - Return true if the specified type is valid as a return +/// type. +bool FunctionType::isValidReturnType(const Type *RetTy) { + return !RetTy->isFunctionTy() && !RetTy->isLabelTy() && + !RetTy->isMetadataTy(); } - -// PromoteAbstractToConcrete - This is a recursive function that walks a type -// graph calculating whether or not a type is abstract. -// -void Type::PromoteAbstractToConcrete() { - if (!isAbstract()) return; - - scc_iterator<TypePromotionGraph> SI = scc_begin(TypePromotionGraph(this)); - scc_iterator<TypePromotionGraph> SE = scc_end (TypePromotionGraph(this)); - - for (; SI != SE; ++SI) { - std::vector<Type*> &SCC = *SI; - - // Concrete types are leaves in the tree. Since an SCC will either be all - // abstract or all concrete, we only need to check one type. - if (!SCC[0]->isAbstract()) continue; - - if (SCC[0]->isOpaqueTy()) - return; // Not going to be concrete, sorry. - - // If all of the children of all of the types in this SCC are concrete, - // then this SCC is now concrete as well. If not, neither this SCC, nor - // any parent SCCs will be concrete, so we might as well just exit. - for (unsigned i = 0, e = SCC.size(); i != e; ++i) - for (Type::subtype_iterator CI = SCC[i]->subtype_begin(), - E = SCC[i]->subtype_end(); CI != E; ++CI) - if ((*CI)->isAbstract()) - // If the child type is in our SCC, it doesn't make the entire SCC - // abstract unless there is a non-SCC abstract type. - if (std::find(SCC.begin(), SCC.end(), *CI) == SCC.end()) - return; // Not going to be concrete, sorry. - - // Okay, we just discovered this whole SCC is now concrete, mark it as - // such! - for (unsigned i = 0, e = SCC.size(); i != e; ++i) { - assert(SCC[i]->isAbstract() && "Why are we processing concrete types?"); - - SCC[i]->setAbstract(false); - } - - for (unsigned i = 0, e = SCC.size(); i != e; ++i) { - assert(!SCC[i]->isAbstract() && "Concrete type became abstract?"); - // The type just became concrete, notify all users! - cast<DerivedType>(SCC[i])->notifyUsesThatTypeBecameConcrete(); - } - } +/// isValidArgumentType - Return true if the specified type is valid as an +/// argument type. +bool FunctionType::isValidArgumentType(const Type *ArgTy) { + return ArgTy->isFirstClassType(); } - //===----------------------------------------------------------------------===// -// Type Structural Equality Testing +// StructType Implementation //===----------------------------------------------------------------------===// -// TypesEqual - Two types are considered structurally equal if they have the -// same "shape": Every level and element of the types have identical primitive -// ID's, and the graphs have the same edges/nodes in them. Nodes do not have to -// be pointer equals to be equivalent though. This uses an optimistic algorithm -// that assumes that two graphs are the same until proven otherwise. -// -static bool TypesEqual(const Type *Ty, const Type *Ty2, - std::map<const Type *, const Type *> &EqTypes) { - if (Ty == Ty2) return true; - if (Ty->getTypeID() != Ty2->getTypeID()) return false; - if (Ty->isOpaqueTy()) - return false; // Two unequal opaque types are never equal - - std::map<const Type*, const Type*>::iterator It = EqTypes.find(Ty); - if (It != EqTypes.end()) - return It->second == Ty2; // Looping back on a type, check for equality - - // Otherwise, add the mapping to the table to make sure we don't get - // recursion on the types... - EqTypes.insert(It, std::make_pair(Ty, Ty2)); - - // Two really annoying special cases that breaks an otherwise nice simple - // algorithm is the fact that arraytypes have sizes that differentiates types, - // and that function types can be varargs or not. Consider this now. - // - if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) { - const IntegerType *ITy2 = cast<IntegerType>(Ty2); - return ITy->getBitWidth() == ITy2->getBitWidth(); - } - - if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) { - const PointerType *PTy2 = cast<PointerType>(Ty2); - return PTy->getAddressSpace() == PTy2->getAddressSpace() && - TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); +// Primitive Constructors. + +StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes, + bool isPacked) { + // FIXME: std::vector is horribly inefficient for this probe. + std::vector<Type*> Key; + for (unsigned i = 0, e = ETypes.size(); i != e; ++i) { + assert(isValidElementType(ETypes[i]) && + "Invalid type for structure element!"); + Key.push_back(ETypes[i]); } + if (isPacked) + Key.push_back(0); - if (const StructType *STy = dyn_cast<StructType>(Ty)) { - const StructType *STy2 = cast<StructType>(Ty2); - if (STy->getNumElements() != STy2->getNumElements()) return false; - if (STy->isPacked() != STy2->isPacked()) return false; - for (unsigned i = 0, e = STy2->getNumElements(); i != e; ++i) - if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes)) - return false; - return true; - } + StructType *&ST = Context.pImpl->AnonStructTypes[Key]; + + if (ST) return ST; - if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { - const ArrayType *ATy2 = cast<ArrayType>(Ty2); - return ATy->getNumElements() == ATy2->getNumElements() && - TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes); - } + // Value not found. Create a new type! + ST = new StructType(Context); + ST->setSubclassData(SCDB_IsAnonymous); // Anonymous struct. + ST->setBody(ETypes, isPacked); + return ST; +} + +void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) { + assert(isOpaque() && "Struct body already set!"); - if (const VectorType *PTy = dyn_cast<VectorType>(Ty)) { - const VectorType *PTy2 = cast<VectorType>(Ty2); - return PTy->getNumElements() == PTy2->getNumElements() && - TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); - } + setSubclassData(getSubclassData() | SCDB_HasBody); + if (isPacked) + setSubclassData(getSubclassData() | SCDB_Packed); - if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { - const FunctionType *FTy2 = cast<FunctionType>(Ty2); - if (FTy->isVarArg() != FTy2->isVarArg() || - FTy->getNumParams() != FTy2->getNumParams() || - !TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes)) - return false; - for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i) { - if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes)) - return false; - } - return true; - } + Type **Elts = new Type*[Elements.size()]; + memcpy(Elts, Elements.data(), sizeof(Elements[0])*Elements.size()); - llvm_unreachable("Unknown derived type!"); - return false; -} - -namespace llvm { // in namespace llvm so findable by ADL -static bool TypesEqual(const Type *Ty, const Type *Ty2) { - std::map<const Type *, const Type *> EqTypes; - return ::TypesEqual(Ty, Ty2, EqTypes); -} -} - -// AbstractTypeHasCycleThrough - Return true there is a path from CurTy to -// TargetTy in the type graph. We know that Ty is an abstract type, so if we -// ever reach a non-abstract type, we know that we don't need to search the -// subgraph. -static bool AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - SmallPtrSet<const Type*, 128> &VisitedTypes) { - if (TargetTy == CurTy) return true; - if (!CurTy->isAbstract()) return false; - - if (!VisitedTypes.insert(CurTy)) - return false; // Already been here. - - for (Type::subtype_iterator I = CurTy->subtype_begin(), - E = CurTy->subtype_end(); I != E; ++I) - if (AbstractTypeHasCycleThrough(TargetTy, *I, VisitedTypes)) - return true; - return false; + ContainedTys = Elts; + NumContainedTys = Elements.size(); } -static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - SmallPtrSet<const Type*, 128> &VisitedTypes) { - if (TargetTy == CurTy) return true; - - if (!VisitedTypes.insert(CurTy)) - return false; // Already been here. - - for (Type::subtype_iterator I = CurTy->subtype_begin(), - E = CurTy->subtype_end(); I != E; ++I) - if (ConcreteTypeHasCycleThrough(TargetTy, *I, VisitedTypes)) - return true; - return false; -} - -/// TypeHasCycleThroughItself - Return true if the specified type has -/// a cycle back to itself. - -namespace llvm { // in namespace llvm so it's findable by ADL -static bool TypeHasCycleThroughItself(const Type *Ty) { - SmallPtrSet<const Type*, 128> VisitedTypes; - - if (Ty->isAbstract()) { // Optimized case for abstract types. - for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); - I != E; ++I) - if (AbstractTypeHasCycleThrough(Ty, *I, VisitedTypes)) - return true; - } else { - for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); - I != E; ++I) - if (ConcreteTypeHasCycleThrough(Ty, *I, VisitedTypes)) - return true; - } - return false; -} +StructType *StructType::createNamed(LLVMContext &Context, StringRef Name) { + StructType *ST = new StructType(Context); + ST->setName(Name); + return ST; } -//===----------------------------------------------------------------------===// -// Function Type Factory and Value Class... -// -const IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { - assert(NumBits >= MIN_INT_BITS && "bitwidth too small"); - assert(NumBits <= MAX_INT_BITS && "bitwidth too large"); +void StructType::setName(StringRef Name) { + if (Name == getName()) return; - // Check for the built-in integer types - switch (NumBits) { - case 1: return cast<IntegerType>(Type::getInt1Ty(C)); - case 8: return cast<IntegerType>(Type::getInt8Ty(C)); - case 16: return cast<IntegerType>(Type::getInt16Ty(C)); - case 32: return cast<IntegerType>(Type::getInt32Ty(C)); - case 64: return cast<IntegerType>(Type::getInt64Ty(C)); - default: - break; + // If this struct already had a name, remove its symbol table entry. + if (SymbolTableEntry) { + getContext().pImpl->NamedStructTypes.erase(getName()); + SymbolTableEntry = 0; } - - LLVMContextImpl *pImpl = C.pImpl; - IntegerValType IVT(NumBits); - IntegerType *ITy = 0; + // If this is just removing the name, we're done. + if (Name.empty()) + return; - // First, see if the type is already in the table, for which - // a reader lock suffices. - ITy = pImpl->IntegerTypes.get(IVT); - - if (!ITy) { - // Value not found. Derive a new type! - ITy = new IntegerType(C, NumBits); - pImpl->IntegerTypes.add(IVT, ITy); + // Look up the entry for the name. + StringMapEntry<StructType*> *Entry = + &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name); + + // While we have a name collision, try a random rename. + if (Entry->getValue()) { + SmallString<64> TempStr(Name); + TempStr.push_back('.'); + raw_svector_ostream TmpStream(TempStr); + + do { + TempStr.resize(Name.size()+1); + TmpStream.resync(); + TmpStream << getContext().pImpl->NamedStructTypesUniqueID++; + + Entry = &getContext().pImpl-> + NamedStructTypes.GetOrCreateValue(TmpStream.str()); + } while (Entry->getValue()); } -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *ITy << "\n"); -#endif - return ITy; -} -bool IntegerType::isPowerOf2ByteWidth() const { - unsigned BitWidth = getBitWidth(); - return (BitWidth > 7) && isPowerOf2_32(BitWidth); + // Okay, we found an entry that isn't used. It's us! + Entry->setValue(this); + + SymbolTableEntry = Entry; } -APInt IntegerType::getMask() const { - return APInt::getAllOnesValue(getBitWidth()); -} +//===----------------------------------------------------------------------===// +// StructType Helper functions. -FunctionValType FunctionValType::get(const FunctionType *FT) { - // Build up a FunctionValType - std::vector<const Type *> ParamTypes; - ParamTypes.reserve(FT->getNumParams()); - for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) - ParamTypes.push_back(FT->getParamType(i)); - return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg()); +// FIXME: Remove this version. +StructType *StructType::get(LLVMContext &Context, ArrayRef<const Type*>Elements, + bool isPacked) { + return get(Context, ArrayRef<Type*>(const_cast<Type**>(Elements.data()), + Elements.size()), isPacked); } -FunctionType *FunctionType::get(const Type *Result, bool isVarArg) { - return get(Result, ArrayRef<const Type *>(), isVarArg); +StructType *StructType::get(LLVMContext &Context, bool isPacked) { + return get(Context, llvm::ArrayRef<const Type*>(), isPacked); } -// FunctionType::get - The factory function for the FunctionType class... -FunctionType *FunctionType::get(const Type *ReturnType, - ArrayRef<const Type*> Params, - bool isVarArg) { - FunctionValType VT(ReturnType, Params, isVarArg); - FunctionType *FT = 0; - - LLVMContextImpl *pImpl = ReturnType->getContext().pImpl; - - FT = pImpl->FunctionTypes.get(VT); - - if (!FT) { - FT = (FunctionType*) operator new(sizeof(FunctionType) + - sizeof(PATypeHandle)*(Params.size()+1)); - new (FT) FunctionType(ReturnType, Params, isVarArg); - pImpl->FunctionTypes.add(VT, FT); +StructType *StructType::get(const Type *type, ...) { + assert(type != 0 && "Cannot create a struct type with no elements with this"); + LLVMContext &Ctx = type->getContext(); + va_list ap; + SmallVector<const llvm::Type*, 8> StructFields; + va_start(ap, type); + while (type) { + StructFields.push_back(type); + type = va_arg(ap, llvm::Type*); } - -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << FT << "\n"); -#endif - return FT; + return llvm::StructType::get(Ctx, StructFields); } -ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { - assert(ElementType && "Can't get array of <null> types!"); - assert(isValidElementType(ElementType) && "Invalid type for array element!"); - - ArrayValType AVT(ElementType, NumElements); - ArrayType *AT = 0; - - LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - - AT = pImpl->ArrayTypes.get(AVT); - - if (!AT) { - // Value not found. Derive a new type! - pImpl->ArrayTypes.add(AVT, AT = new ArrayType(ElementType, NumElements)); - } -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *AT << "\n"); -#endif - return AT; +StructType *StructType::createNamed(LLVMContext &Context, StringRef Name, + ArrayRef<Type*> Elements, bool isPacked) { + StructType *ST = createNamed(Context, Name); + ST->setBody(Elements, isPacked); + return ST; } -bool ArrayType::isValidElementType(const Type *ElemTy) { - return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); +StructType *StructType::createNamed(StringRef Name, ArrayRef<Type*> Elements, + bool isPacked) { + assert(!Elements.empty() && + "This method may not be invoked with an empty list"); + return createNamed(Elements[0]->getContext(), Name, Elements, isPacked); } -VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { - assert(ElementType && "Can't get vector of <null> types!"); - - VectorValType PVT(ElementType, NumElements); - VectorType *PT = 0; - - LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - - PT = pImpl->VectorTypes.get(PVT); - - if (!PT) { - pImpl->VectorTypes.add(PVT, PT = new VectorType(ElementType, NumElements)); +StructType *StructType::createNamed(StringRef Name, Type *type, ...) { + assert(type != 0 && "Cannot create a struct type with no elements with this"); + LLVMContext &Ctx = type->getContext(); + va_list ap; + SmallVector<llvm::Type*, 8> StructFields; + va_start(ap, type); + while (type) { + StructFields.push_back(type); + type = va_arg(ap, llvm::Type*); } -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *PT << "\n"); -#endif - return PT; -} - -bool VectorType::isValidElementType(const Type *ElemTy) { - return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() || - ElemTy->isOpaqueTy(); -} - -//===----------------------------------------------------------------------===// -// Struct Type Factory. -// - -StructType *StructType::get(LLVMContext &Context, bool isPacked) { - return get(Context, llvm::ArrayRef<const Type*>(), isPacked); + return llvm::StructType::createNamed(Ctx, Name, StructFields); } - -StructType *StructType::get(LLVMContext &Context, - ArrayRef<const Type*> ETypes, - bool isPacked) { - StructValType STV(ETypes, isPacked); - StructType *ST = 0; - - LLVMContextImpl *pImpl = Context.pImpl; +StringRef StructType::getName() const { + assert(!isAnonymous() && "Anonymous structs never have names"); + if (SymbolTableEntry == 0) return StringRef(); - ST = pImpl->StructTypes.get(STV); - - if (!ST) { - // Value not found. Derive a new type! - ST = (StructType*) operator new(sizeof(StructType) + - sizeof(PATypeHandle) * ETypes.size()); - new (ST) StructType(Context, ETypes, isPacked); - pImpl->StructTypes.add(STV, ST); - } -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *ST << "\n"); -#endif - return ST; + return ((StringMapEntry<StructType*> *)SymbolTableEntry)->getKey(); } -StructType *StructType::get(const Type *type, ...) { +void StructType::setBody(Type *type, ...) { assert(type != 0 && "Cannot create a struct type with no elements with this"); - LLVMContext &Ctx = type->getContext(); va_list ap; - SmallVector<const llvm::Type*, 8> StructFields; + SmallVector<llvm::Type*, 8> StructFields; va_start(ap, type); while (type) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::get(Ctx, StructFields); + setBody(StructFields); } bool StructType::isValidElementType(const Type *ElemTy) { @@ -957,267 +540,157 @@ bool StructType::isValidElementType(const Type *ElemTy) { !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } - -//===----------------------------------------------------------------------===// -// Pointer Type Factory... -// - -PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { - assert(ValueType && "Can't get a pointer to <null> type!"); - assert(ValueType->getTypeID() != VoidTyID && - "Pointer to void is not valid, use i8* instead!"); - assert(isValidElementType(ValueType) && "Invalid type for pointer element!"); - PointerValType PVT(ValueType, AddressSpace); - - PointerType *PT = 0; - - LLVMContextImpl *pImpl = ValueType->getContext().pImpl; +/// isLayoutIdentical - Return true if this is layout identical to the +/// specified struct. +bool StructType::isLayoutIdentical(const StructType *Other) const { + if (this == Other) return true; - PT = pImpl->PointerTypes.get(PVT); + if (isPacked() != Other->isPacked() || + getNumElements() != Other->getNumElements()) + return false; - if (!PT) { - // Value not found. Derive a new type! - pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace)); - } -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "Derived new type: " << *PT << "\n"); -#endif - return PT; + return std::equal(element_begin(), element_end(), Other->element_begin()); } -const PointerType *Type::getPointerTo(unsigned addrs) const { - return PointerType::get(this, addrs); -} -bool PointerType::isValidElementType(const Type *ElemTy) { - return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy(); +/// getTypeByName - Return the type with the specified name, or null if there +/// is none by that name. +StructType *Module::getTypeByName(StringRef Name) const { + StringMap<StructType*>::iterator I = + getContext().pImpl->NamedStructTypes.find(Name); + if (I != getContext().pImpl->NamedStructTypes.end()) + return I->second; + return 0; } //===----------------------------------------------------------------------===// -// Opaque Type Factory... -// +// CompositeType Implementation +//===----------------------------------------------------------------------===// -OpaqueType *OpaqueType::get(LLVMContext &C) { - OpaqueType *OT = new OpaqueType(C); // All opaque types are distinct. - LLVMContextImpl *pImpl = C.pImpl; - pImpl->OpaqueTypes.insert(OT); - return OT; +Type *CompositeType::getTypeAtIndex(const Value *V) const { + if (const StructType *STy = dyn_cast<StructType>(this)) { + unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue(); + assert(indexValid(Idx) && "Invalid structure index!"); + return STy->getElementType(Idx); + } + + return cast<SequentialType>(this)->getElementType(); +} +Type *CompositeType::getTypeAtIndex(unsigned Idx) const { + if (const StructType *STy = dyn_cast<StructType>(this)) { + assert(indexValid(Idx) && "Invalid structure index!"); + return STy->getElementType(Idx); + } + + return cast<SequentialType>(this)->getElementType(); +} +bool CompositeType::indexValid(const Value *V) const { + if (const StructType *STy = dyn_cast<StructType>(this)) { + // Structure indexes require 32-bit integer constants. + if (V->getType()->isIntegerTy(32)) + if (const ConstantInt *CU = dyn_cast<ConstantInt>(V)) + return CU->getZExtValue() < STy->getNumElements(); + return false; + } + + // Sequential types can be indexed by any integer. + return V->getType()->isIntegerTy(); } +bool CompositeType::indexValid(unsigned Idx) const { + if (const StructType *STy = dyn_cast<StructType>(this)) + return Idx < STy->getNumElements(); + // Sequential types can be indexed by any integer. + return true; +} //===----------------------------------------------------------------------===// -// Derived Type Refinement Functions +// ArrayType Implementation //===----------------------------------------------------------------------===// -// addAbstractTypeUser - Notify an abstract type that there is a new user of -// it. This function is called primarily by the PATypeHandle class. -void Type::addAbstractTypeUser(AbstractTypeUser *U) const { - assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!"); - AbstractTypeUsers.push_back(U); +ArrayType::ArrayType(Type *ElType, uint64_t NumEl) + : SequentialType(ArrayTyID, ElType) { + NumElements = NumEl; } -// removeAbstractTypeUser - Notify an abstract type that a user of the class -// no longer has a handle to the type. This function is called primarily by -// the PATypeHandle class. When there are no users of the abstract type, it -// is annihilated, because there is no way to get a reference to it ever again. -// -void Type::removeAbstractTypeUser(AbstractTypeUser *U) const { - - // Search from back to front because we will notify users from back to - // front. Also, it is likely that there will be a stack like behavior to - // users that register and unregister users. - // - unsigned i; - for (i = AbstractTypeUsers.size(); AbstractTypeUsers[i-1] != U; --i) - assert(i != 0 && "AbstractTypeUser not in user list!"); - - --i; // Convert to be in range 0 <= i < size() - assert(i < AbstractTypeUsers.size() && "Index out of range!"); // Wraparound? - - AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i); - -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << " remAbstractTypeUser[" << (void*)this << ", " - << *this << "][" << i << "] User = " << U << "\n"); -#endif - - if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) { -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "DELETEing unused abstract type: <" << *this - << ">[" << (void*)this << "]" << "\n"); -#endif +ArrayType *ArrayType::get(const Type *elementType, uint64_t NumElements) { + Type *ElementType = const_cast<Type*>(elementType); + assert(isValidElementType(ElementType) && "Invalid type for array element!"); + + ArrayType *&Entry = ElementType->getContext().pImpl + ->ArrayTypes[std::make_pair(ElementType, NumElements)]; - this->destroy(); - } + if (Entry == 0) + Entry = new ArrayType(ElementType, NumElements); + return Entry; } -// refineAbstractTypeTo - This function is used when it is discovered -// that the 'this' abstract type is actually equivalent to the NewType -// specified. This causes all users of 'this' to switch to reference the more -// concrete type NewType and for 'this' to be deleted. Only used for internal -// callers. -// -void DerivedType::refineAbstractTypeTo(const Type *NewType) { - assert(isAbstract() && "refineAbstractTypeTo: Current type is not abstract!"); - assert(this != NewType && "Can't refine to myself!"); - assert(ForwardType == 0 && "This type has already been refined!"); - -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "REFINING abstract type [" << (void*)this << " " - << *this << "] to [" << (void*)NewType << " " - << *NewType << "]!\n"); -#endif - - // Make sure to put the type to be refined to into a holder so that if IT gets - // refined, that we will not continue using a dead reference... - // - PATypeHolder NewTy(NewType); - // Any PATypeHolders referring to this type will now automatically forward to - // the type we are resolved to. - ForwardType = NewType; - if (ForwardType->isAbstract()) - ForwardType->addRef(); - - // Add a self use of the current type so that we don't delete ourself until - // after the function exits. - // - PATypeHolder CurrentTy(this); - - // To make the situation simpler, we ask the subclass to remove this type from - // the type map, and to replace any type uses with uses of non-abstract types. - // This dramatically limits the amount of recursive type trouble we can find - // ourselves in. - dropAllTypeUses(); - - // Iterate over all of the uses of this type, invoking callback. Each user - // should remove itself from our use list automatically. We have to check to - // make sure that NewTy doesn't _become_ 'this'. If it does, resolving types - // will not cause users to drop off of the use list. If we resolve to ourself - // we succeed! - // - while (!AbstractTypeUsers.empty() && NewTy != this) { - AbstractTypeUser *User = AbstractTypeUsers.back(); - - unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize; -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << " REFINING user " << OldSize-1 << "[" << (void*)User - << "] of abstract type [" << (void*)this << " " - << *this << "] to [" << (void*)NewTy.get() << " " - << *NewTy << "]!\n"); -#endif - User->refineAbstractType(this, NewTy); - - assert(AbstractTypeUsers.size() != OldSize && - "AbsTyUser did not remove self from user list!"); - } - - // If we were successful removing all users from the type, 'this' will be - // deleted when the last PATypeHolder is destroyed or updated from this type. - // This may occur on exit of this function, as the CurrentTy object is - // destroyed. -} - -// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type that -// the current type has transitioned from being abstract to being concrete. -// -void DerivedType::notifyUsesThatTypeBecameConcrete() { -#ifdef DEBUG_MERGE_TYPES - DEBUG(dbgs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n"); -#endif - - unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize; - while (!AbstractTypeUsers.empty()) { - AbstractTypeUser *ATU = AbstractTypeUsers.back(); - ATU->typeBecameConcrete(this); - - assert(AbstractTypeUsers.size() < OldSize-- && - "AbstractTypeUser did not remove itself from the use list!"); - } +bool ArrayType::isValidElementType(const Type *ElemTy) { + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } -// refineAbstractType - Called when a contained type is found to be more -// concrete - this could potentially change us from an abstract type to a -// concrete type. -// -void FunctionType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { - LLVMContextImpl *pImpl = OldType->getContext().pImpl; - pImpl->FunctionTypes.RefineAbstractType(this, OldType, NewType); -} +//===----------------------------------------------------------------------===// +// VectorType Implementation +//===----------------------------------------------------------------------===// -void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) { - LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; - pImpl->FunctionTypes.TypeBecameConcrete(this, AbsTy); +VectorType::VectorType(Type *ElType, unsigned NumEl) + : SequentialType(VectorTyID, ElType) { + NumElements = NumEl; } - -// refineAbstractType - Called when a contained type is found to be more -// concrete - this could potentially change us from an abstract type to a -// concrete type. -// -void ArrayType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { - LLVMContextImpl *pImpl = OldType->getContext().pImpl; - pImpl->ArrayTypes.RefineAbstractType(this, OldType, NewType); +VectorType *VectorType::get(const Type *elementType, unsigned NumElements) { + Type *ElementType = const_cast<Type*>(elementType); + assert(NumElements > 0 && "#Elements of a VectorType must be greater than 0"); + assert(isValidElementType(ElementType) && + "Elements of a VectorType must be a primitive type"); + + VectorType *&Entry = ElementType->getContext().pImpl + ->VectorTypes[std::make_pair(ElementType, NumElements)]; + + if (Entry == 0) + Entry = new VectorType(ElementType, NumElements); + return Entry; } -void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) { - LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; - pImpl->ArrayTypes.TypeBecameConcrete(this, AbsTy); +bool VectorType::isValidElementType(const Type *ElemTy) { + return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy(); } -// refineAbstractType - Called when a contained type is found to be more -// concrete - this could potentially change us from an abstract type to a -// concrete type. -// -void VectorType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { - LLVMContextImpl *pImpl = OldType->getContext().pImpl; - pImpl->VectorTypes.RefineAbstractType(this, OldType, NewType); -} +//===----------------------------------------------------------------------===// +// PointerType Implementation +//===----------------------------------------------------------------------===// -void VectorType::typeBecameConcrete(const DerivedType *AbsTy) { - LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; - pImpl->VectorTypes.TypeBecameConcrete(this, AbsTy); -} +PointerType *PointerType::get(const Type *eltTy, unsigned AddressSpace) { + Type *EltTy = const_cast<Type*>(eltTy); + assert(EltTy && "Can't get a pointer to <null> type!"); + assert(isValidElementType(EltTy) && "Invalid type for pointer element!"); + + LLVMContextImpl *CImpl = EltTy->getContext().pImpl; + + // Since AddressSpace #0 is the common case, we special case it. + PointerType *&Entry = AddressSpace == 0 ? CImpl->PointerTypes[EltTy] + : CImpl->ASPointerTypes[std::make_pair(EltTy, AddressSpace)]; -// refineAbstractType - Called when a contained type is found to be more -// concrete - this could potentially change us from an abstract type to a -// concrete type. -// -void StructType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { - LLVMContextImpl *pImpl = OldType->getContext().pImpl; - pImpl->StructTypes.RefineAbstractType(this, OldType, NewType); + if (Entry == 0) + Entry = new PointerType(EltTy, AddressSpace); + return Entry; } -void StructType::typeBecameConcrete(const DerivedType *AbsTy) { - LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; - pImpl->StructTypes.TypeBecameConcrete(this, AbsTy); -} -// refineAbstractType - Called when a contained type is found to be more -// concrete - this could potentially change us from an abstract type to a -// concrete type. -// -void PointerType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { - LLVMContextImpl *pImpl = OldType->getContext().pImpl; - pImpl->PointerTypes.RefineAbstractType(this, OldType, NewType); +PointerType::PointerType(Type *E, unsigned AddrSpace) + : SequentialType(PointerTyID, E) { + setSubclassData(AddrSpace); } -void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { - LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; - pImpl->PointerTypes.TypeBecameConcrete(this, AbsTy); +PointerType *Type::getPointerTo(unsigned addrs) const { + return PointerType::get(this, addrs); } -namespace llvm { -raw_ostream &operator<<(raw_ostream &OS, const Type &T) { - T.print(OS); - return OS; -} +bool PointerType::isValidElementType(const Type *ElemTy) { + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy(); } |