X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FType.cpp;h=b15304cc9593b290ddcf0d95832d6908bc334805;hb=b34d837397053da8e9bff90dd714e24f2a3b98b3;hp=1abeffa99ff6ec297788861ee4064fdfcd6145ee;hpb=254bb831d826e5a7295b7f271bbac77be9044d63;p=oota-llvm.git diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 1abeffa99ff..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,6 +41,9 @@ using namespace llvm; AbstractTypeUser::~AbstractTypeUser() {} +void AbstractTypeUser::setType(Value *V, const Type *NewTy) { + V->VTy = NewTy; +} //===----------------------------------------------------------------------===// // Type Class Implementation @@ -49,18 +51,23 @@ AbstractTypeUser::~AbstractTypeUser() {} /// 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) @@ -68,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 @@ -98,6 +110,7 @@ const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { 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; } @@ -120,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 @@ -156,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 } @@ -176,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; @@ -195,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; @@ -208,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)) @@ -217,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... @@ -242,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,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::getInt32Ty(V->getContext())) + if (V->getType()->isIntegerTy(32)) if (const ConstantInt *CU = dyn_cast(V)) return indexValid(CU->getZExtValue()); return false; @@ -299,6 +330,7 @@ const Type *StructType::getTypeAtIndex(unsigned Idx) const { return ContainedTys[Idx]; } + //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// @@ -335,6 +367,14 @@ 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; } @@ -355,6 +395,54 @@ 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); +} + //===----------------------------------------------------------------------===// // Derived Type Constructors //===----------------------------------------------------------------------===// @@ -362,42 +450,18 @@ const IntegerType *Type::getInt64Ty(LLVMContext &C) { /// 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::getMetadataTy(RetTy->getContext()); - return true; - } - if (RetTy == Type::getVoidTy(RetTy->getContext()) || - RetTy == Type::getMetadataTy(RetTy->getContext()) || - 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::getMetadataTy(ArgTy->getContext()))) - return false; - - return true; + return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy(); } FunctionType::FunctionType(const Type *Result, - const std::vector &Params, + ArrayRef Params, bool IsVarArgs) : DerivedType(Result->getContext(), FunctionTyID), isVarArgs(IsVarArgs) { ContainedTys = reinterpret_cast(this+1); @@ -420,7 +484,7 @@ FunctionType::FunctionType(const Type *Result, } StructType::StructType(LLVMContext &C, - const std::vector &Types, bool isPacked) + ArrayRef Types, bool isPacked) : CompositeType(C, StructTyID) { ContainedTys = reinterpret_cast(this + 1); NumContainedTys = Types.size(); @@ -467,7 +531,7 @@ PointerType::PointerType(const Type *E, unsigned AddrSpace) OpaqueType::OpaqueType(LLVMContext &C) : DerivedType(C, OpaqueTyID) { setAbstract(true); #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "Derived new type: " << *this << "\n"); + DEBUG(dbgs() << "Derived new type: " << *this << "\n"); #endif } @@ -482,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(getContext()); - PATypeHolder* tmp2 = new PATypeHolder(tmp); - sys::MemoryFence(); - AlwaysOpaqueTy = tmp; - Holder = tmp2; - } - - llvm_release_global_lock(); - } - } else if (!AlwaysOpaqueTy) { - AlwaysOpaqueTy = OpaqueType::get(getContext()); - 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::getInt32Ty(getContext()); + ContainedTys[i] = ConcreteTy; } } @@ -538,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(); @@ -562,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(); } } } @@ -610,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); @@ -628,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; @@ -640,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() || @@ -659,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 @@ -703,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; @@ -721,6 +778,7 @@ static bool TypeHasCycleThroughItself(const Type *Ty) { } return false; } +} //===----------------------------------------------------------------------===// // Function Type Factory and Value Class... @@ -731,13 +789,13 @@ const IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { // Check for the built-in integer types switch (NumBits) { - 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; + 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; @@ -747,7 +805,6 @@ const IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { // First, see if the type is already in the table, for which // a reader lock suffices. - sys::SmartScopedLock L(pImpl->TypeMapLock); ITy = pImpl->IntegerTypes.get(IVT); if (!ITy) { @@ -756,7 +813,7 @@ const IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { pImpl->IntegerTypes.add(IVT, ITy); } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "Derived new type: " << *ITy << "\n"); + DEBUG(dbgs() << "Derived new type: " << *ITy << "\n"); #endif return ITy; } @@ -782,14 +839,13 @@ 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; LLVMContextImpl *pImpl = ReturnType->getContext().pImpl; - sys::SmartScopedLock L(pImpl->TypeMapLock); FT = pImpl->FunctionTypes.get(VT); if (!FT) { @@ -800,7 +856,7 @@ FunctionType *FunctionType::get(const Type *ReturnType, } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "Derived new type: " << FT << "\n"); + DEBUG(dbgs() << "Derived new type: " << FT << "\n"); #endif return FT; } @@ -814,7 +870,6 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - sys::SmartScopedLock L(pImpl->TypeMapLock); AT = pImpl->ArrayTypes.get(AVT); if (!AT) { @@ -822,22 +877,14 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { pImpl->ArrayTypes.add(AVT, AT = new ArrayType(ElementType, NumElements)); } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "Derived new type: " << *AT << "\n"); + DEBUG(dbgs() << "Derived new type: " << *AT << "\n"); #endif return AT; } bool ArrayType::isValidElementType(const Type *ElemTy) { - if (ElemTy == Type::getVoidTy(ElemTy->getContext()) || - ElemTy == Type::getLabelTy(ElemTy->getContext()) || - ElemTy == Type::getMetadataTy(ElemTy->getContext())) - return false; - - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::getMetadataTy(ElemTy->getContext())) - return false; - - return true; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { @@ -848,24 +895,20 @@ VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { LLVMContextImpl *pImpl = ElementType->getContext().pImpl; - sys::SmartScopedLock L(pImpl->TypeMapLock); PT = pImpl->VectorTypes.get(PVT); if (!PT) { pImpl->VectorTypes.add(PVT, PT = new VectorType(ElementType, NumElements)); } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "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(); } //===----------------------------------------------------------------------===// @@ -873,14 +916,13 @@ bool VectorType::isValidElementType(const Type *ElemTy) { // StructType *StructType::get(LLVMContext &Context, - const std::vector &ETypes, + ArrayRef ETypes, bool isPacked) { StructValType STV(ETypes, isPacked); StructType *ST = 0; LLVMContextImpl *pImpl = Context.pImpl; - sys::SmartScopedLock L(pImpl->TypeMapLock); ST = pImpl->StructTypes.get(STV); if (!ST) { @@ -891,7 +933,7 @@ StructType *StructType::get(LLVMContext &Context, pImpl->StructTypes.add(STV, ST); } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "Derived new type: " << *ST << "\n"); + DEBUG(dbgs() << "Derived new type: " << *ST << "\n"); #endif return ST; } @@ -908,16 +950,8 @@ StructType *StructType::get(LLVMContext &Context, const Type *type, ...) { } bool StructType::isValidElementType(const Type *ElemTy) { - if (ElemTy == Type::getVoidTy(ElemTy->getContext()) || - ElemTy == Type::getLabelTy(ElemTy->getContext()) || - ElemTy == Type::getMetadataTy(ElemTy->getContext())) - return false; - - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::getMetadataTy(ElemTy->getContext())) - return false; - - return true; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } @@ -927,7 +961,7 @@ bool StructType::isValidElementType(const Type *ElemTy) { PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { assert(ValueType && "Can't get a pointer to type!"); - assert(ValueType != Type::getVoidTy(ValueType->getContext()) && + 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); @@ -936,7 +970,6 @@ PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { LLVMContextImpl *pImpl = ValueType->getContext().pImpl; - sys::SmartScopedLock L(pImpl->TypeMapLock); PT = pImpl->PointerTypes.get(PVT); if (!PT) { @@ -944,28 +977,34 @@ PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace)); } #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "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::getVoidTy(ElemTy->getContext()) || - ElemTy == Type::getLabelTy(ElemTy->getContext())) - return false; + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy(); +} - if (const PointerType *PTy = dyn_cast(ElemTy)) - if (PTy->getElementType() == Type::getMetadataTy(ElemTy->getContext())) - 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 //===----------------------------------------------------------------------===// @@ -974,10 +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!"); - LLVMContextImpl *pImpl = getContext().pImpl; - pImpl->AbstractTypeUsersLock.acquire(); AbstractTypeUsers.push_back(U); - pImpl->AbstractTypeUsersLock.release(); } @@ -987,8 +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 { - LLVMContextImpl *pImpl = getContext().pImpl; - pImpl->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 @@ -1004,29 +1038,27 @@ void Type::removeAbstractTypeUser(AbstractTypeUser *U) const { AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i); #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << " remAbstractTypeUser[" << (void*)this << ", " + DEBUG(dbgs() << " remAbstractTypeUser[" << (void*)this << ", " << *this << "][" << i << "] User = " << U << "\n"); #endif if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) { #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "DELETEing unused abstract type: <" << *this + DEBUG(dbgs() << "DELETEing unused abstract type: <" << *this << ">[" << (void*)this << "]" << "\n"); #endif - this->destroy(); + this->destroy(); } - - pImpl->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!"); @@ -1037,7 +1069,7 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { pImpl->AbstractTypeDescriptions.clear(); #ifdef DEBUG_MERGE_TYPES - DEBUG(errs() << "REFINING abstract type [" << (void*)this << " " + DEBUG(dbgs() << "REFINING abstract type [" << (void*)this << " " << *this << "] to [" << (void*)NewType << " " << *NewType << "]!\n"); #endif @@ -1046,11 +1078,11 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { // 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. @@ -1069,13 +1101,12 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { // will not cause users to drop off of the use list. If we resolve to ourself // we succeed! // - pImpl->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 - DEBUG(errs() << " REFINING user " << OldSize-1 << "[" << (void*)User + DEBUG(dbgs() << " REFINING user " << OldSize-1 << "[" << (void*)User << "] of abstract type [" << (void*)this << " " << *this << "] to [" << (void*)NewTy.get() << " " << *NewTy << "]!\n"); @@ -1085,7 +1116,6 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) { assert(AbstractTypeUsers.size() != OldSize && "AbsTyUser did not remove self from user list!"); } - pImpl->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. @@ -1093,28 +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(NewType->getContext().pImpl->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 - DEBUG(errs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n"); + DEBUG(dbgs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n"); #endif - LLVMContextImpl *pImpl = getContext().pImpl; - - pImpl->AbstractTypeUsersLock.acquire(); - unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; + unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize; while (!AbstractTypeUsers.empty()) { AbstractTypeUser *ATU = AbstractTypeUsers.back(); ATU->typeBecameConcrete(this); @@ -1122,7 +1139,6 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() { assert(AbstractTypeUsers.size() < OldSize-- && "AbstractTypeUser did not remove itself from the use list!"); } - pImpl->AbstractTypeUsersLock.release(); } // refineAbstractType - Called when a contained type is found to be more @@ -1202,7 +1218,7 @@ void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { } bool SequentialType::indexValid(const Value *V) const { - if (isa(V->getType())) + if (V->getType()->isIntegerTy()) return true; return false; }