X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FType.cpp;h=b15304cc9593b290ddcf0d95832d6908bc334805;hb=b34d837397053da8e9bff90dd714e24f2a3b98b3;hp=610036ef0d57a2b49b506a71b9c99cf804156af1;hpb=9eb5c93d34b7de9bd4387481c5048d3b13085712;p=oota-llvm.git diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 610036ef0d5..b15304cc959 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -17,6 +17,7 @@ #include "llvm/Assembly/Writer.h" #include "llvm/LLVMContext.h" #include "llvm/Metadata.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SCCIterator.h" @@ -27,9 +28,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Mutex.h" -#include "llvm/System/RWMutex.h" -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include #include using namespace llvm; @@ -42,40 +41,33 @@ using namespace llvm; AbstractTypeUser::~AbstractTypeUser() {} +void AbstractTypeUser::setType(Value *V, const Type *NewTy) { + V->VTy = NewTy; +} //===----------------------------------------------------------------------===// // Type Class Implementation //===----------------------------------------------------------------------===// -// Lock used for guarding access to the type maps. -static ManagedStatic > TypeMapLock; - -// Recursive lock used for guarding access to AbstractTypeUsers. -// NOTE: The true template parameter means this will no-op when we're not in -// multithreaded mode. -static ManagedStatic > AbstractTypeUsersLock; - -// Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions -// for types as they are needed. Because resolution of types must invalidate -// all of the abstract type descriptions, we keep them in a seperate map to make -// this easy. -static ManagedStatic ConcreteTypeDescriptions; -static ManagedStatic AbstractTypeDescriptions; - /// 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 +/// 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 (isa(this) || isa(this)) { + 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) @@ -83,16 +75,21 @@ void Type::destroy() const { // Now call the destructor for the subclass directly because we're going // to delete this as an array of char. - if (isa(this)) + if (this->isFunctionTy()) static_cast(this)->FunctionType::~FunctionType(); - else + else { + assert(isStructTy()); static_cast(this)->StructType::~StructType(); + } // Finally, remove the memory as an array deallocation of the chars it was // constructed from. operator delete(const_cast(this)); return; + } else if (const OpaqueType *opaque_this = dyn_cast(this)) { + LLVMContextImpl *pImpl = this->getContext().pImpl; + pImpl->OpaqueTypes.erase(opaque_this); } // For all the other type subclasses, there is either no contained types or @@ -103,26 +100,27 @@ void Type::destroy() const { delete this; } -const Type *Type::getPrimitiveType(TypeID IDNumber) { +const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { switch (IDNumber) { - case VoidTyID : return VoidTy; - case FloatTyID : return FloatTy; - case DoubleTyID : return DoubleTy; - case X86_FP80TyID : return X86_FP80Ty; - case FP128TyID : return FP128Ty; - case PPC_FP128TyID : return PPC_FP128Ty; - case LabelTyID : return LabelTy; - case MetadataTyID : return MetadataTy; + case VoidTyID : return getVoidTy(C); + case FloatTyID : return getFloatTy(C); + case DoubleTyID : return getDoubleTy(C); + case X86_FP80TyID : return getX86_FP80Ty(C); + case FP128TyID : return getFP128Ty(C); + case PPC_FP128TyID : return getPPC_FP128Ty(C); + case LabelTyID : return getLabelTy(C); + case MetadataTyID : return getMetadataTy(C); + case X86_MMXTyID : return getX86_MMXTy(C); default: return 0; } } -const Type *Type::getVAArgsPromotedType() const { +const Type *Type::getVAArgsPromotedType(LLVMContext &C) const { if (ID == IntegerTyID && getSubclassData() < 32) - return Type::Int32Ty; + return Type::getInt32Ty(C); else if (ID == FloatTyID) - return Type::DoubleTy; + return Type::getDoubleTy(C); else return this; } @@ -135,27 +133,32 @@ const Type *Type::getScalarType() const { return this; } -/// isIntOrIntVector - Return true if this is an integer type or a vector of +/// isIntegerTy - Return true if this is an IntegerType of the specified width. +bool Type::isIntegerTy(unsigned Bitwidth) const { + return isIntegerTy() && cast(this)->getBitWidth() == Bitwidth; +} + +/// isIntOrIntVectorTy - Return true if this is an integer type or a vector of /// integer types. /// -bool Type::isIntOrIntVector() const { - if (isInteger()) +bool Type::isIntOrIntVectorTy() const { + if (isIntegerTy()) return true; if (ID != Type::VectorTyID) return false; - return cast(this)->getElementType()->isInteger(); + return cast(this)->getElementType()->isIntegerTy(); } -/// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. +/// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP types. /// -bool Type::isFPOrFPVector() const { +bool Type::isFPOrFPVectorTy() const { if (ID == Type::FloatTyID || ID == Type::DoubleTyID || ID == Type::FP128TyID || ID == Type::X86_FP80TyID || ID == Type::PPC_FP128TyID) return true; if (ID != Type::VectorTyID) return false; - return cast(this)->getElementType()->isFloatingPoint(); + return cast(this)->getElementType()->isFloatingPointTy(); } // canLosslesslyBitCastTo - Return true if this type can be converted to @@ -171,16 +174,26 @@ bool Type::canLosslesslyBitCastTo(const Type *Ty) const { return false; // Vector -> Vector conversions are always lossless if the two vector types - // have the same size, otherwise not. - if (const VectorType *thisPTy = dyn_cast(this)) + // have the same size, otherwise not. Also, 64-bit vector types can be + // converted to x86mmx. + if (const VectorType *thisPTy = dyn_cast(this)) { if (const VectorType *thatPTy = dyn_cast(Ty)) return thisPTy->getBitWidth() == thatPTy->getBitWidth(); + if (Ty->getTypeID() == Type::X86_MMXTyID && + thisPTy->getBitWidth() == 64) + return true; + } + + if (this->getTypeID() == Type::X86_MMXTyID) + if (const VectorType *thatPTy = dyn_cast(Ty)) + if (thatPTy->getBitWidth() == 64) + return true; // At this point we have only various mismatches of the first class types // remaining and ptr->ptr. Just select the lossless conversions. Everything // else is not lossless. - if (isa(this)) - return isa(Ty); + if (this->isPointerTy()) + return Ty->isPointerTy(); return false; // Other types have no identity values } @@ -191,6 +204,7 @@ unsigned Type::getPrimitiveSizeInBits() const { case Type::X86_FP80TyID: return 80; case Type::FP128TyID: return 128; case Type::PPC_FP128TyID: return 128; + case Type::X86_MMXTyID: return 64; case Type::IntegerTyID: return cast(this)->getBitWidth(); case Type::VectorTyID: return cast(this)->getBitWidth(); default: return 0; @@ -210,7 +224,7 @@ unsigned Type::getScalarSizeInBits() const { int Type::getFPMantissaWidth() const { if (const VectorType *VTy = dyn_cast(this)) return VTy->getElementType()->getFPMantissaWidth(); - assert(isFloatingPoint() && "Not a floating point type!"); + assert(isFloatingPointTy() && "Not a floating point type!"); if (ID == FloatTyID) return 24; if (ID == DoubleTyID) return 53; if (ID == X86_FP80TyID) return 64; @@ -223,7 +237,7 @@ int Type::getFPMantissaWidth() const { /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. bool Type::isSizedDerivedType() const { - if (isa(this)) + if (this->isIntegerTy()) return true; if (const ArrayType *ATy = dyn_cast(this)) @@ -232,7 +246,7 @@ bool Type::isSizedDerivedType() const { if (const VectorType *PTy = dyn_cast(this)) return PTy->getElementType()->isSized(); - if (!isa(this)) + if (!this->isStructTy()) return false; // Okay, our struct is sized if all of the elements are... @@ -257,10 +271,12 @@ const Type *Type::getForwardedTypeInternal() const { // Yes, it is forwarded again. First thing, add the reference to the new // forward type. if (RealForwardedType->isAbstract()) - cast(RealForwardedType)->addRef(); + RealForwardedType->addRef(); // Now drop the old reference. This could cause ForwardType to get deleted. - cast(ForwardType)->dropRef(); + // ForwardType must be abstract because only abstract types can have their own + // ForwardTypes. + ForwardType->dropRef(); // Return the updated type. ForwardType = RealForwardedType; @@ -276,8 +292,11 @@ void Type::typeBecameConcrete(const DerivedType *AbsTy) { std::string Type::getDescription() const { + LLVMContextImpl *pImpl = getContext().pImpl; TypePrinting &Map = - isAbstract() ? *AbstractTypeDescriptions : *ConcreteTypeDescriptions; + isAbstract() ? + pImpl->AbstractTypeDescriptions : + pImpl->ConcreteTypeDescriptions; std::string DescStr; raw_string_ostream DescOS(DescStr); @@ -288,7 +307,7 @@ std::string Type::getDescription() const { bool StructType::indexValid(const Value *V) const { // Structure indexes require 32-bit integer constants. - if (V->getType() == Type::Int32Ty) + if (V->getType()->isIntegerTy(32)) if (const ConstantInt *CU = dyn_cast(V)) return indexValid(CU->getZExtValue()); return false; @@ -311,29 +330,118 @@ const Type *StructType::getTypeAtIndex(unsigned Idx) const { return ContainedTys[Idx]; } + //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// -const Type *Type::VoidTy = new Type(Type::VoidTyID); -const Type *Type::FloatTy = new Type(Type::FloatTyID); -const Type *Type::DoubleTy = new Type(Type::DoubleTyID); -const Type *Type::X86_FP80Ty = new Type(Type::X86_FP80TyID); -const Type *Type::FP128Ty = new Type(Type::FP128TyID); -const Type *Type::PPC_FP128Ty = new Type(Type::PPC_FP128TyID); -const Type *Type::LabelTy = new Type(Type::LabelTyID); -const Type *Type::MetadataTy = new Type(Type::MetadataTyID); +const Type *Type::getVoidTy(LLVMContext &C) { + return &C.pImpl->VoidTy; +} -namespace { - struct BuiltinIntegerType : public IntegerType { - explicit BuiltinIntegerType(unsigned W) : IntegerType(W) {} - }; +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) { + 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) { + return getFloatTy(C)->getPointerTo(AS); +} + +const PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) { + return getDoubleTy(C)->getPointerTo(AS); +} + +const PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) { + return getX86_FP80Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) { + return getFP128Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) { + return getPPC_FP128Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getX86_MMXPtrTy(LLVMContext &C, unsigned AS) { + return getX86_MMXTy(C)->getPointerTo(AS); +} + +const PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) { + return getIntNTy(C, N)->getPointerTo(AS); +} + +const PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) { + return getInt1Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) { + return getInt8Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) { + return getInt16Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) { + return getInt32Ty(C)->getPointerTo(AS); +} + +const PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) { + return getInt64Ty(C)->getPointerTo(AS); } -const IntegerType *Type::Int1Ty = new BuiltinIntegerType(1); -const IntegerType *Type::Int8Ty = new BuiltinIntegerType(8); -const IntegerType *Type::Int16Ty = new BuiltinIntegerType(16); -const IntegerType *Type::Int32Ty = new BuiltinIntegerType(32); -const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64); //===----------------------------------------------------------------------===// // Derived Type Constructors @@ -342,42 +450,20 @@ const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64); /// isValidReturnType - Return true if the specified type is valid as a return /// type. bool FunctionType::isValidReturnType(const Type *RetTy) { - if (RetTy->isFirstClassType()) { - if (const PointerType *PTy = dyn_cast(RetTy)) - return PTy->getElementType() != Type::MetadataTy; - return true; - } - if (RetTy == Type::VoidTy || RetTy == Type::MetadataTy || - isa(RetTy)) - return true; - - // If this is a multiple return case, verify that each return is a first class - // value and that there is at least one value. - const StructType *SRetTy = dyn_cast(RetTy); - if (SRetTy == 0 || SRetTy->getNumElements() == 0) - return false; - - for (unsigned i = 0, e = SRetTy->getNumElements(); i != e; ++i) - if (!SRetTy->getElementType(i)->isFirstClassType()) - return false; - return true; + return !RetTy->isFunctionTy() && !RetTy->isLabelTy() && + !RetTy->isMetadataTy(); } /// isValidArgumentType - Return true if the specified type is valid as an /// argument type. bool FunctionType::isValidArgumentType(const Type *ArgTy) { - if ((!ArgTy->isFirstClassType() && !isa(ArgTy)) || - (isa(ArgTy) && - cast(ArgTy)->getElementType() == Type::MetadataTy)) - return false; - - return true; + return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy(); } FunctionType::FunctionType(const Type *Result, - const std::vector &Params, + ArrayRef Params, bool IsVarArgs) - : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) { + : DerivedType(Result->getContext(), FunctionTyID), isVarArgs(IsVarArgs) { ContainedTys = reinterpret_cast(this+1); NumContainedTys = Params.size() + 1; // + 1 for result type assert(isValidReturnType(Result) && "invalid return type for function"); @@ -397,8 +483,9 @@ FunctionType::FunctionType(const Type *Result, setAbstract(isAbstract); } -StructType::StructType(const std::vector &Types, bool isPacked) - : CompositeType(StructTyID) { +StructType::StructType(LLVMContext &C, + ArrayRef Types, bool isPacked) + : CompositeType(C, StructTyID) { ContainedTys = reinterpret_cast(this + 1); NumContainedTys = Types.size(); setSubclassData(isPacked); @@ -441,10 +528,10 @@ PointerType::PointerType(const Type *E, unsigned AddrSpace) setAbstract(E->isAbstract()); } -OpaqueType::OpaqueType() : DerivedType(OpaqueTyID) { +OpaqueType::OpaqueType(LLVMContext &C) : DerivedType(C, OpaqueTyID) { setAbstract(true); #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *this << "\n"; + DEBUG(dbgs() << "Derived new type: " << *this << "\n"); #endif } @@ -459,36 +546,15 @@ 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. - static Type *AlwaysOpaqueTy = 0; - static PATypeHolder* Holder = 0; - Type *tmp = AlwaysOpaqueTy; - if (llvm_is_multithreaded()) { - sys::MemoryFence(); - if (!tmp) { - llvm_acquire_global_lock(); - tmp = AlwaysOpaqueTy; - if (!tmp) { - tmp = OpaqueType::get(); - PATypeHolder* tmp2 = new PATypeHolder(AlwaysOpaqueTy); - sys::MemoryFence(); - AlwaysOpaqueTy = tmp; - Holder = tmp2; - } - - llvm_release_global_lock(); - } - } else { - AlwaysOpaqueTy = OpaqueType::get(); - Holder = new PATypeHolder(AlwaysOpaqueTy); - } - - ContainedTys[0] = AlwaysOpaqueTy; + 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 AbstracTypeUser lists and stuff. + // 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] = Type::Int32Ty; + ContainedTys[i] = ConcreteTy; } } @@ -515,8 +581,8 @@ namespace llvm { static inline ChildIteratorType child_begin(NodeType *N) { if (N->isAbstract()) return N->subtype_begin(); - else // No need to process children of concrete types. - return N->subtype_end(); + // No need to process children of concrete types. + return N->subtype_end(); } static inline ChildIteratorType child_end(NodeType *N) { return N->subtype_end(); @@ -539,35 +605,35 @@ void Type::PromoteAbstractToConcrete() { // 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()) { - if (isa(SCC[0])) - 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(SCC[i])->notifyUsesThatTypeBecameConcrete(); - } + 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(SCC[i])->notifyUsesThatTypeBecameConcrete(); } } } @@ -587,7 +653,7 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, std::map &EqTypes) { if (Ty == Ty2) return true; if (Ty->getTypeID() != Ty2->getTypeID()) return false; - if (isa(Ty)) + if (Ty->isOpaqueTy()) return false; // Two unequal opaque types are never equal std::map::iterator It = EqTypes.find(Ty); @@ -605,11 +671,15 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, if (const IntegerType *ITy = dyn_cast(Ty)) { const IntegerType *ITy2 = cast(Ty2); return ITy->getBitWidth() == ITy2->getBitWidth(); - } else if (const PointerType *PTy = dyn_cast(Ty)) { + } + + if (const PointerType *PTy = dyn_cast(Ty)) { const PointerType *PTy2 = cast(Ty2); return PTy->getAddressSpace() == PTy2->getAddressSpace() && TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); - } else if (const StructType *STy = dyn_cast(Ty)) { + } + + if (const StructType *STy = dyn_cast(Ty)) { const StructType *STy2 = cast(Ty2); if (STy->getNumElements() != STy2->getNumElements()) return false; if (STy->isPacked() != STy2->isPacked()) return false; @@ -617,15 +687,21 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes)) return false; return true; - } else if (const ArrayType *ATy = dyn_cast(Ty)) { + } + + if (const ArrayType *ATy = dyn_cast(Ty)) { const ArrayType *ATy2 = cast(Ty2); return ATy->getNumElements() == ATy2->getNumElements() && TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes); - } else if (const VectorType *PTy = dyn_cast(Ty)) { + } + + if (const VectorType *PTy = dyn_cast(Ty)) { const VectorType *PTy2 = cast(Ty2); return PTy->getNumElements() == PTy2->getNumElements() && TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); - } else if (const FunctionType *FTy = dyn_cast(Ty)) { + } + + if (const FunctionType *FTy = dyn_cast(Ty)) { const FunctionType *FTy2 = cast(Ty2); if (FTy->isVarArg() != FTy2->isVarArg() || FTy->getNumParams() != FTy2->getNumParams() || @@ -636,15 +712,17 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, return false; } return true; - } else { - llvm_unreachable("Unknown derived type!"); - return false; } + + 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 EqTypes; - return TypesEqual(Ty, Ty2, EqTypes); + return ::TypesEqual(Ty, Ty2, EqTypes); +} } // AbstractTypeHasCycleThrough - Return true there is a path from CurTy to @@ -680,8 +758,10 @@ static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, return false; } -/// TypeHasCycleThroughItself - Return true if the specified type has a cycle -/// back to itself. +/// 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 VisitedTypes; @@ -698,43 +778,42 @@ static bool TypeHasCycleThroughItself(const Type *Ty) { } return false; } +} //===----------------------------------------------------------------------===// // Function Type Factory and Value Class... // - -static ManagedStatic > IntegerTypes; - -const IntegerType *IntegerType::get(unsigned NumBits) { +const 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(Type::Int1Ty); - case 8: return cast(Type::Int8Ty); - case 16: return cast(Type::Int16Ty); - case 32: return cast(Type::Int32Ty); - case 64: return cast(Type::Int64Ty); - default: - break; + case 1: return cast(Type::getInt1Ty(C)); + case 8: return cast(Type::getInt8Ty(C)); + case 16: return cast(Type::getInt16Ty(C)); + case 32: return cast(Type::getInt32Ty(C)); + case 64: return cast(Type::getInt64Ty(C)); + default: + break; } + + LLVMContextImpl *pImpl = C.pImpl; IntegerValType IVT(NumBits); IntegerType *ITy = 0; // First, see if the type is already in the table, for which // a reader lock suffices. - sys::SmartScopedLock L(*TypeMapLock); - ITy = IntegerTypes->get(IVT); + ITy = pImpl->IntegerTypes.get(IVT); if (!ITy) { // Value not found. Derive a new type! - ITy = new IntegerType(NumBits); - IntegerTypes->add(IVT, ITy); + ITy = new IntegerType(C, NumBits); + pImpl->IntegerTypes.add(IVT, ITy); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *ITy << "\n"; + DEBUG(dbgs() << "Derived new type: " << *ITy << "\n"); #endif return ITy; } @@ -748,9 +827,6 @@ APInt IntegerType::getMask() const { return APInt::getAllOnesValue(getBitWidth()); } -// Define the actual map itself now... -static ManagedStatic > FunctionTypes; - FunctionValType FunctionValType::get(const FunctionType *FT) { // Build up a FunctionValType std::vector ParamTypes; @@ -763,23 +839,24 @@ FunctionValType FunctionValType::get(const FunctionType *FT) { // FunctionType::get - The factory function for the FunctionType class... FunctionType *FunctionType::get(const Type *ReturnType, - const std::vector &Params, + ArrayRef Params, bool isVarArg) { FunctionValType VT(ReturnType, Params, isVarArg); FunctionType *FT = 0; - sys::SmartScopedLock L(*TypeMapLock); - FT = FunctionTypes->get(VT); + 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); - FunctionTypes->add(VT, FT); + pImpl->FunctionTypes.add(VT, FT); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << FT << "\n"; + DEBUG(dbgs() << "Derived new type: " << FT << "\n"); #endif return FT; } @@ -793,7 +870,6 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - sys::SmartScopedLock L(*TypeMapLock); AT = pImpl->ArrayTypes.get(AVT); if (!AT) { @@ -801,21 +877,14 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { pImpl->ArrayTypes.add(AVT, AT = new ArrayType(ElementType, NumElements)); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *AT << "\n"; + DEBUG(dbgs() << "Derived new type: " << *AT << "\n"); #endif return AT; } bool ArrayType::isValidElementType(const Type *ElemTy) { - if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || - ElemTy == Type::MetadataTy) - return false; - - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::MetadataTy) - return false; - - return true; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { @@ -826,54 +895,50 @@ VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - sys::SmartScopedLock L(*TypeMapLock); PT = pImpl->VectorTypes.get(PVT); if (!PT) { pImpl->VectorTypes.add(PVT, PT = new VectorType(ElementType, NumElements)); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *PT << "\n"; + DEBUG(dbgs() << "Derived new type: " << *PT << "\n"); #endif return PT; } bool VectorType::isValidElementType(const Type *ElemTy) { - if (ElemTy->isInteger() || ElemTy->isFloatingPoint() || - isa(ElemTy)) - return true; - - return false; + return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() || + ElemTy->isOpaqueTy(); } //===----------------------------------------------------------------------===// // Struct Type Factory... // -static ManagedStatic > StructTypes; - -StructType *StructType::get(const std::vector &ETypes, +StructType *StructType::get(LLVMContext &Context, + ArrayRef ETypes, bool isPacked) { StructValType STV(ETypes, isPacked); StructType *ST = 0; - sys::SmartScopedLock L(*TypeMapLock); - ST = StructTypes->get(STV); + LLVMContextImpl *pImpl = Context.pImpl; + + 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(ETypes, isPacked); - StructTypes->add(STV, ST); + new (ST) StructType(Context, ETypes, isPacked); + pImpl->StructTypes.add(STV, ST); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *ST << "\n"; + DEBUG(dbgs() << "Derived new type: " << *ST << "\n"); #endif return ST; } -StructType *StructType::get(const Type *type, ...) { +StructType *StructType::get(LLVMContext &Context, const Type *type, ...) { va_list ap; std::vector StructFields; va_start(ap, type); @@ -881,19 +946,12 @@ StructType *StructType::get(const Type *type, ...) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::get(StructFields); + return llvm::StructType::get(Context, StructFields); } bool StructType::isValidElementType(const Type *ElemTy) { - if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || - ElemTy == Type::MetadataTy) - return false; - - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::MetadataTy) - return false; - - return true; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } @@ -901,46 +959,52 @@ bool StructType::isValidElementType(const Type *ElemTy) { // Pointer Type Factory... // -static ManagedStatic > PointerTypes; - PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { assert(ValueType && "Can't get a pointer to type!"); - assert(ValueType != Type::VoidTy && + 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; - sys::SmartScopedLock L(*TypeMapLock); - PT = PointerTypes->get(PVT); + LLVMContextImpl *pImpl = ValueType->getContext().pImpl; + + PT = pImpl->PointerTypes.get(PVT); if (!PT) { // Value not found. Derive a new type! - PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace)); + pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace)); } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *PT << "\n"; + DEBUG(dbgs() << "Derived new type: " << *PT << "\n"); #endif return PT; } -PointerType *Type::getPointerTo(unsigned addrs) const { +const PointerType *Type::getPointerTo(unsigned addrs) const { return PointerType::get(this, addrs); } bool PointerType::isValidElementType(const Type *ElemTy) { - if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy) - return false; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy(); +} - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::MetadataTy) - return false; - return true; +//===----------------------------------------------------------------------===// +// Opaque Type Factory... +// + +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; } + //===----------------------------------------------------------------------===// // Derived Type Refinement Functions //===----------------------------------------------------------------------===// @@ -949,9 +1013,7 @@ bool PointerType::isValidElementType(const Type *ElemTy) { // it. This function is called primarily by the PATypeHandle class. void Type::addAbstractTypeUser(AbstractTypeUser *U) const { assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!"); - AbstractTypeUsersLock->acquire(); AbstractTypeUsers.push_back(U); - AbstractTypeUsersLock->release(); } @@ -961,7 +1023,6 @@ void Type::addAbstractTypeUser(AbstractTypeUser *U) const { // is annihilated, because there is no way to get a reference to it ever again. // void Type::removeAbstractTypeUser(AbstractTypeUser *U) const { - AbstractTypeUsersLock->acquire(); // 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 @@ -977,52 +1038,51 @@ void Type::removeAbstractTypeUser(AbstractTypeUser *U) const { AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i); #ifdef DEBUG_MERGE_TYPES - DOUT << " remAbstractTypeUser[" << (void*)this << ", " - << *this << "][" << i << "] User = " << U << "\n"; + DEBUG(dbgs() << " remAbstractTypeUser[" << (void*)this << ", " + << *this << "][" << i << "] User = " << U << "\n"); #endif if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) { #ifdef DEBUG_MERGE_TYPES - DOUT << "DELETEing unused abstract type: <" << *this - << ">[" << (void*)this << "]" << "\n"; + DEBUG(dbgs() << "DELETEing unused abstract type: <" << *this + << ">[" << (void*)this << "]" << "\n"); #endif - this->destroy(); + this->destroy(); } - - AbstractTypeUsersLock->release(); } -// unlockedRefineAbstractTypeTo - This function is used when it is discovered +// 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::unlockedRefineAbstractTypeTo(const Type *NewType) { +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!"); + LLVMContextImpl *pImpl = getContext().pImpl; + // The descriptions may be out of date. Conservatively clear them all! - if (AbstractTypeDescriptions.isConstructed()) - AbstractTypeDescriptions->clear(); + pImpl->AbstractTypeDescriptions.clear(); #ifdef DEBUG_MERGE_TYPES - DOUT << "REFINING abstract type [" << (void*)this << " " - << *this << "] to [" << (void*)NewType << " " - << *NewType << "]!\n"; + 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 o + // Any PATypeHolders referring to this type will now automatically forward to // the type we are resolved to. ForwardType = NewType; - if (NewType->isAbstract()) - cast(NewType)->addRef(); + 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. @@ -1041,23 +1101,21 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { // will not cause users to drop off of the use list. If we resolve to ourself // we succeed! // - AbstractTypeUsersLock->acquire(); while (!AbstractTypeUsers.empty() && NewTy != this) { AbstractTypeUser *User = AbstractTypeUsers.back(); - unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; + unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize; #ifdef DEBUG_MERGE_TYPES - DOUT << " REFINING user " << OldSize-1 << "[" << (void*)User - << "] of abstract type [" << (void*)this << " " - << *this << "] to [" << (void*)NewTy.get() << " " - << *NewTy << "]!\n"; + 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!"); } - AbstractTypeUsersLock->release(); // 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. @@ -1065,26 +1123,15 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { // destroyed. } -// refineAbstractTypeTo - This function is used by external callers to notify -// us that this abstract type is equivalent to another type. -// -void DerivedType::refineAbstractTypeTo(const Type *NewType) { - // All recursive calls will go through unlockedRefineAbstractTypeTo, - // to avoid deadlock problems. - sys::SmartScopedLock L(*TypeMapLock); - unlockedRefineAbstractTypeTo(NewType); -} - // 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 - DOUT << "typeIsREFINED type: " << (void*)this << " " << *this << "\n"; + DEBUG(dbgs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n"); #endif - AbstractTypeUsersLock->acquire(); - unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; + unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize; while (!AbstractTypeUsers.empty()) { AbstractTypeUser *ATU = AbstractTypeUsers.back(); ATU->typeBecameConcrete(this); @@ -1092,7 +1139,6 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() { assert(AbstractTypeUsers.size() < OldSize-- && "AbstractTypeUser did not remove itself from the use list!"); } - AbstractTypeUsersLock->release(); } // refineAbstractType - Called when a contained type is found to be more @@ -1101,11 +1147,13 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() { // void FunctionType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - FunctionTypes->RefineAbstractType(this, OldType, NewType); + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->FunctionTypes.RefineAbstractType(this, OldType, NewType); } void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) { - FunctionTypes->TypeBecameConcrete(this, AbsTy); + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->FunctionTypes.TypeBecameConcrete(this, AbsTy); } @@ -1145,11 +1193,13 @@ void VectorType::typeBecameConcrete(const DerivedType *AbsTy) { // void StructType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - StructTypes->RefineAbstractType(this, OldType, NewType); + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->StructTypes.RefineAbstractType(this, OldType, NewType); } void StructType::typeBecameConcrete(const DerivedType *AbsTy) { - StructTypes->TypeBecameConcrete(this, AbsTy); + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->StructTypes.TypeBecameConcrete(this, AbsTy); } // refineAbstractType - Called when a contained type is found to be more @@ -1158,33 +1208,22 @@ void StructType::typeBecameConcrete(const DerivedType *AbsTy) { // void PointerType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - PointerTypes->RefineAbstractType(this, OldType, NewType); + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->PointerTypes.RefineAbstractType(this, OldType, NewType); } void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { - PointerTypes->TypeBecameConcrete(this, AbsTy); + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->PointerTypes.TypeBecameConcrete(this, AbsTy); } bool SequentialType::indexValid(const Value *V) const { - if (isa(V->getType())) + if (V->getType()->isIntegerTy()) return true; return false; } namespace llvm { -std::ostream &operator<<(std::ostream &OS, const Type *T) { - if (T == 0) - OS << " value!\n"; - else - T->print(OS); - return OS; -} - -std::ostream &operator<<(std::ostream &OS, const Type &T) { - T.print(OS); - return OS; -} - raw_ostream &operator<<(raw_ostream &OS, const Type &T) { T.print(OS); return OS;