X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FType.cpp;h=739c463d91b4f43023c6a7faf9e65cf0115f6260;hb=c4775e4b973aaf6695dc00a3403b8b64f5257568;hp=34bedbb00a319cb362c425999243d79f23f0162e;hpb=e463fc809872959d33b5da9549dbe96416dded30;p=oota-llvm.git diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 34bedbb00a3..739c463d91b 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -11,18 +11,25 @@ // //===----------------------------------------------------------------------===// -#include "llvm/AbstractTypeUser.h" +#include "LLVMContextImpl.h" #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Threading.h" #include +#include using namespace llvm; // DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are @@ -33,73 +40,112 @@ using namespace llvm; AbstractTypeUser::~AbstractTypeUser() {} - -//===----------------------------------------------------------------------===// -// Type PATypeHolder Implementation -//===----------------------------------------------------------------------===// - -/// get - This implements the forwarding part of the union-find algorithm for -/// abstract types. Before every access to the Type*, we check to see if the -/// type we are pointing to is forwarding to a new type. If so, we drop our -/// reference to the type. -/// -Type* PATypeHolder::get() const { - const Type *NewTy = Ty->getForwardedType(); - if (!NewTy) return const_cast(Ty); - return *const_cast(this) = NewTy; +void AbstractTypeUser::setType(Value *V, const Type *NewTy) { + V->VTy = NewTy; } //===----------------------------------------------------------------------===// // Type Class Implementation //===----------------------------------------------------------------------===// -// 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 +/// 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 { + + // 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)) { + // 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 (isa(this)) + static_cast(this)->FunctionType::~FunctionType(); + else + 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)); -Type::Type(const char *Name, TypeID id) - : ID(id), Abstract(false), SubclassData(0), RefCount(0), ForwardType(0) { - assert(Name && Name[0] && "Should use other ctor if no name!"); - (*ConcreteTypeDescriptions)[this] = Name; -} + return; + } + // 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(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 LabelTyID : return LabelTy; + 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); 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; } +/// getScalarType - If this is a vector type, return the element type, +/// otherwise return this. +const Type *Type::getScalarType() const { + if (const VectorType *VTy = dyn_cast(this)) + return VTy->getElementType(); + return this; +} + +/// isIntOrIntVector - Return true if this is an integer type or a vector of +/// integer types. +/// +bool Type::isIntOrIntVector() const { + if (isInteger()) + return true; + if (ID != Type::VectorTyID) return false; + + return cast(this)->getElementType()->isInteger(); +} + /// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. /// bool Type::isFPOrFPVector() const { - if (ID == Type::FloatTyID || ID == Type::DoubleTyID) return true; - if (ID != Type::PackedTyID) return false; + 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()->isFloatingPoint(); } -// canLosslesllyBitCastTo - Return true if this type can be converted to -// 'Ty' without any reinterpretation of bits. For example, uint to int. +// canLosslesslyBitCastTo - Return true if this type can be converted to +// 'Ty' without any reinterpretation of bits. For example, i8* to i32*. // bool Type::canLosslesslyBitCastTo(const Type *Ty) const { // Identity cast means no change so return true @@ -110,10 +156,10 @@ bool Type::canLosslesslyBitCastTo(const Type *Ty) const { if (!this->isFirstClassType() || !Ty->isFirstClassType()) return false; - // Packed -> Packed conversions are always lossless if the two packed types + // Vector -> Vector conversions are always lossless if the two vector types // have the same size, otherwise not. - if (const PackedType *thisPTy = dyn_cast(this)) - if (const PackedType *thatPTy = dyn_cast(Ty)) + if (const VectorType *thisPTy = dyn_cast(this)) + if (const VectorType *thatPTy = dyn_cast(Ty)) return thisPTy->getBitWidth() == thatPTy->getBitWidth(); // At this point we have only various mismatches of the first class types @@ -128,12 +174,37 @@ unsigned Type::getPrimitiveSizeInBits() const { switch (getTypeID()) { case Type::FloatTyID: return 32; case Type::DoubleTyID: return 64; + case Type::X86_FP80TyID: return 80; + case Type::FP128TyID: return 128; + case Type::PPC_FP128TyID: return 128; case Type::IntegerTyID: return cast(this)->getBitWidth(); - case Type::PackedTyID: return cast(this)->getBitWidth(); + case Type::VectorTyID: return cast(this)->getBitWidth(); default: return 0; } } +/// getScalarSizeInBits - If this is a vector type, return the +/// getPrimitiveSizeInBits value for the element type. Otherwise return the +/// getPrimitiveSizeInBits value for this type. +unsigned Type::getScalarSizeInBits() const { + return getScalarType()->getPrimitiveSizeInBits(); +} + +/// getFPMantissaWidth - Return the width of the mantissa of this type. This +/// is only valid on floating point types. If the FP type does not +/// have a stable mantissa (e.g. ppc long double), this method returns -1. +int Type::getFPMantissaWidth() const { + if (const VectorType *VTy = dyn_cast(this)) + return VTy->getElementType()->getFPMantissaWidth(); + assert(isFloatingPoint() && "Not a floating point type!"); + if (ID == FloatTyID) return 24; + if (ID == DoubleTyID) return 53; + if (ID == X86_FP80TyID) return 64; + if (ID == FP128TyID) return 113; + assert(ID == PPC_FP128TyID && "unknown fp type"); + return -1; +} + /// isSizedDerivedType - Derived types like structures and arrays are sized /// 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. @@ -144,7 +215,7 @@ bool Type::isSizedDerivedType() const { if (const ArrayType *ATy = dyn_cast(this)) return ATy->getElementType()->isSized(); - if (const PackedType *PTy = dyn_cast(this)) + if (const VectorType *PTy = dyn_cast(this)) return PTy->getElementType()->isSized(); if (!isa(this)) @@ -183,229 +254,200 @@ const Type *Type::getForwardedTypeInternal() const { } void Type::refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - abort(); + llvm_unreachable("Attempting to refine a derived type!"); } void Type::typeBecameConcrete(const DerivedType *AbsTy) { - abort(); + llvm_unreachable("DerivedType is already a concrete type!"); +} + + +std::string Type::getDescription() const { + LLVMContextImpl *pImpl = getContext().pImpl; + TypePrinting &Map = + isAbstract() ? + pImpl->AbstractTypeDescriptions : + pImpl->ConcreteTypeDescriptions; + + std::string DescStr; + raw_string_ostream DescOS(DescStr); + Map.print(this, DescOS); + return DescOS.str(); } -// getTypeDescription - This is a recursive function that walks a type hierarchy -// calculating the description for a type. +bool StructType::indexValid(const Value *V) const { + // Structure indexes require 32-bit integer constants. + if (V->getType() == Type::getInt32Ty(V->getContext())) + if (const ConstantInt *CU = dyn_cast(V)) + return indexValid(CU->getZExtValue()); + return false; +} + +bool StructType::indexValid(unsigned V) const { + return V < NumContainedTys; +} + +// getTypeAtIndex - Given an index value into the type, return the type of the +// element. For a structure type, this must be a constant value... // -static std::string getTypeDescription(const Type *Ty, - std::vector &TypeStack) { - if (isa(Ty)) { // Base case for the recursion - std::map::iterator I = - AbstractTypeDescriptions->lower_bound(Ty); - if (I != AbstractTypeDescriptions->end() && I->first == Ty) - return I->second; - std::string Desc = "opaque"; - AbstractTypeDescriptions->insert(std::make_pair(Ty, Desc)); - return Desc; - } +const Type *StructType::getTypeAtIndex(const Value *V) const { + unsigned Idx = (unsigned)cast(V)->getZExtValue(); + return getTypeAtIndex(Idx); +} - if (!Ty->isAbstract()) { // Base case for the recursion - std::map::iterator I = - ConcreteTypeDescriptions->find(Ty); - if (I != ConcreteTypeDescriptions->end()) return I->second; - } +const Type *StructType::getTypeAtIndex(unsigned Idx) const { + assert(indexValid(Idx) && "Invalid structure index!"); + return ContainedTys[Idx]; +} - // Check to see if the Type is already on the stack... - unsigned Slot = 0, CurSize = TypeStack.size(); - while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type +//===----------------------------------------------------------------------===// +// Primitive 'Type' data +//===----------------------------------------------------------------------===// - // This is another base case for the recursion. In this case, we know - // that we have looped back to a type that we have previously visited. - // Generate the appropriate upreference to handle this. - // - if (Slot < CurSize) - return "\\" + utostr(CurSize-Slot); // Here's the upreference - - // Recursive case: derived types... - std::string Result; - TypeStack.push_back(Ty); // Add us to the stack.. - - switch (Ty->getTypeID()) { - case Type::IntegerTyID: { - const IntegerType *ITy = cast(Ty); - Result = "i" + utostr(ITy->getBitWidth()); - break; - } - case Type::FunctionTyID: { - const FunctionType *FTy = cast(Ty); - if (!Result.empty()) - Result += " "; - Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " ("; - unsigned Idx = 1; - for (FunctionType::param_iterator I = FTy->param_begin(), - E = FTy->param_end(); I != E; ++I) { - if (I != FTy->param_begin()) - Result += ", "; - Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx)); - Idx++; - Result += getTypeDescription(*I, TypeStack); - } - if (FTy->isVarArg()) { - if (FTy->getNumParams()) Result += ", "; - Result += "..."; - } - Result += ")"; - if (FTy->getParamAttrs(0)) { - Result += " " + FunctionType::getParamAttrsText(FTy->getParamAttrs(0)); - } - break; - } - case Type::PackedStructTyID: - case Type::StructTyID: { - const StructType *STy = cast(Ty); - if (STy->isPacked()) - Result = "<{ "; - else - Result = "{ "; - for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); I != E; ++I) { - if (I != STy->element_begin()) - Result += ", "; - Result += getTypeDescription(*I, TypeStack); - } - Result += " }"; - if (STy->isPacked()) - Result += ">"; - break; - } - case Type::PointerTyID: { - const PointerType *PTy = cast(Ty); - Result = getTypeDescription(PTy->getElementType(), TypeStack) + " *"; - break; - } - case Type::ArrayTyID: { - const ArrayType *ATy = cast(Ty); - unsigned NumElements = ATy->getNumElements(); - Result = "["; - Result += utostr(NumElements) + " x "; - Result += getTypeDescription(ATy->getElementType(), TypeStack) + "]"; - break; - } - case Type::PackedTyID: { - const PackedType *PTy = cast(Ty); - unsigned NumElements = PTy->getNumElements(); - Result = "<"; - Result += utostr(NumElements) + " x "; - Result += getTypeDescription(PTy->getElementType(), TypeStack) + ">"; - break; - } - default: - Result = ""; - assert(0 && "Unhandled type in getTypeDescription!"); - } +const Type *Type::getVoidTy(LLVMContext &C) { + return &C.pImpl->VoidTy; +} - TypeStack.pop_back(); // Remove self from stack... +const Type *Type::getLabelTy(LLVMContext &C) { + return &C.pImpl->LabelTy; +} - return Result; +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; +} -static const std::string &getOrCreateDesc(std::map&Map, - const Type *Ty) { - std::map::iterator I = Map.find(Ty); - if (I != Map.end()) return I->second; +const Type *Type::getX86_FP80Ty(LLVMContext &C) { + return &C.pImpl->X86_FP80Ty; +} - std::vector TypeStack; - std::string Result = getTypeDescription(Ty, TypeStack); - return Map[Ty] = Result; +const Type *Type::getFP128Ty(LLVMContext &C) { + return &C.pImpl->FP128Ty; } +const Type *Type::getPPC_FP128Ty(LLVMContext &C) { + return &C.pImpl->PPC_FP128Ty; +} -const std::string &Type::getDescription() const { - if (isAbstract()) - return getOrCreateDesc(*AbstractTypeDescriptions, this); - else - return getOrCreateDesc(*ConcreteTypeDescriptions, this); +const IntegerType *Type::getInt1Ty(LLVMContext &C) { + return &C.pImpl->Int1Ty; } +const IntegerType *Type::getInt8Ty(LLVMContext &C) { + return &C.pImpl->Int8Ty; +} -bool StructType::indexValid(const Value *V) const { - // Structure indexes require 32-bit integer constants. - if (V->getType() == Type::Int32Ty) - if (const ConstantInt *CU = dyn_cast(V)) - return CU->getZExtValue() < ContainedTys.size(); - return false; +const IntegerType *Type::getInt16Ty(LLVMContext &C) { + return &C.pImpl->Int16Ty; } -// getTypeAtIndex - Given an index value into the type, return the type of the -// element. For a structure type, this must be a constant value... -// -const Type *StructType::getTypeAtIndex(const Value *V) const { - assert(indexValid(V) && "Invalid structure index!"); - unsigned Idx = (unsigned)cast(V)->getZExtValue(); - return ContainedTys[Idx]; +const IntegerType *Type::getInt32Ty(LLVMContext &C) { + return &C.pImpl->Int32Ty; } -//===----------------------------------------------------------------------===// -// Primitive 'Type' data -//===----------------------------------------------------------------------===// +const IntegerType *Type::getInt64Ty(LLVMContext &C) { + return &C.pImpl->Int64Ty; +} -const Type *Type::VoidTy = new Type("void", Type::VoidTyID); -const Type *Type::FloatTy = new Type("float", Type::FloatTyID); -const Type *Type::DoubleTy = new Type("double", Type::DoubleTyID); -const Type *Type::LabelTy = new Type("label", Type::LabelTyID); +const PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) { + return getFloatTy(C)->getPointerTo(AS); +} -namespace { - struct BuiltinIntegerType : public IntegerType { - BuiltinIntegerType(unsigned W) : IntegerType(W) {} - }; +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::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 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); +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 //===----------------------------------------------------------------------===// +/// isValidReturnType - Return true if the specified type is valid as a return +/// type. +bool FunctionType::isValidReturnType(const Type *RetTy) { + return RetTy->getTypeID() != LabelTyID && + RetTy->getTypeID() != MetadataTyID; +} + +/// isValidArgumentType - Return true if the specified type is valid as an +/// argument type. +bool FunctionType::isValidArgumentType(const Type *ArgTy) { + return ArgTy->isFirstClassType() || isa(ArgTy); +} + FunctionType::FunctionType(const Type *Result, const std::vector &Params, - bool IsVarArgs, const ParamAttrsList &Attrs) - : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) { - assert((Result->isFirstClassType() || Result == Type::VoidTy || - isa(Result)) && - "LLVM functions cannot return aggregates"); + bool 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"); + + bool isAbstract = Result->isAbstract(); - ContainedTys.reserve(Params.size()+1); - ContainedTys.push_back(PATypeHandle(Result, this)); + new (&ContainedTys[0]) PATypeHandle(Result, this); for (unsigned i = 0; i != Params.size(); ++i) { - assert((Params[i]->isFirstClassType() || isa(Params[i])) && - "Function arguments must be value types!"); - - ContainedTys.push_back(PATypeHandle(Params[i], this)); + assert(isValidArgumentType(Params[i]) && + "Not a valid type for function argument!"); + new (&ContainedTys[i+1]) PATypeHandle(Params[i], this); isAbstract |= Params[i]->isAbstract(); } - // Set the ParameterAttributes - if (!Attrs.empty()) - ParamAttrs = new ParamAttrsList(Attrs); - else - ParamAttrs = 0; - // Calculate whether or not this type is abstract setAbstract(isAbstract); - } -StructType::StructType(const std::vector &Types, bool isPacked) - : CompositeType(StructTyID) { +StructType::StructType(LLVMContext &C, + const std::vector &Types, bool isPacked) + : CompositeType(C, StructTyID) { + ContainedTys = reinterpret_cast(this + 1); + NumContainedTys = Types.size(); setSubclassData(isPacked); - ContainedTys.reserve(Types.size()); bool isAbstract = false; for (unsigned i = 0; i < Types.size(); ++i) { - assert(Types[i] != Type::VoidTy && "Void type for structure field!!"); - ContainedTys.push_back(PATypeHandle(Types[i], this)); + assert(Types[i] && " type for structure field!"); + assert(isValidElementType(Types[i]) && + "Invalid type for structure element!"); + new (&ContainedTys[i]) PATypeHandle(Types[i], this); isAbstract |= Types[i]->isAbstract(); } @@ -421,46 +463,79 @@ ArrayType::ArrayType(const Type *ElType, uint64_t NumEl) setAbstract(ElType->isAbstract()); } -PackedType::PackedType(const Type *ElType, unsigned NumEl) - : SequentialType(PackedTyID, ElType) { +VectorType::VectorType(const Type *ElType, unsigned NumEl) + : SequentialType(VectorTyID, ElType) { NumElements = NumEl; setAbstract(ElType->isAbstract()); - assert(NumEl > 0 && "NumEl of a PackedType must be greater than 0"); + assert(NumEl > 0 && "NumEl of a VectorType must be greater than 0"); + assert(isValidElementType(ElType) && + "Elements of a VectorType must be a primitive type"); + } -PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) { +PointerType::PointerType(const Type *E, unsigned AddrSpace) + : SequentialType(PointerTyID, E) { + AddressSpace = AddrSpace; // Calculate whether or not this type is abstract 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(errs() << "Derived new type: " << *this << "\n"); #endif } +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 (!ContainedTys.empty()) { + 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 = OpaqueType::get(); - static PATypeHolder Holder(AlwaysOpaqueTy); + 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; - // Change the rest of the types to be intty's. It doesn't matter what we + // 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. - for (unsigned i = 1, e = ContainedTys.size(); i != e; ++i) - ContainedTys[i] = Type::Int32Ty; + // 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; } } +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 @@ -471,6 +546,8 @@ struct TypePromotionGraph { TypePromotionGraph(Type *T) : Ty(T) {} }; +} + namespace llvm { template <> struct GraphTraits { typedef Type NodeType; @@ -555,8 +632,8 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, if (isa(Ty)) return false; // Two unequal opaque types are never equal - std::map::iterator It = EqTypes.lower_bound(Ty); - if (It != EqTypes.end() && It->first == Ty) + std::map::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 @@ -571,8 +648,9 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, const IntegerType *ITy2 = cast(Ty2); return ITy->getBitWidth() == ITy2->getBitWidth(); } else if (const PointerType *PTy = dyn_cast(Ty)) { - return TypesEqual(PTy->getElementType(), - cast(Ty2)->getElementType(), EqTypes); + const PointerType *PTy2 = cast(Ty2); + return PTy->getAddressSpace() == PTy2->getAddressSpace() && + TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); } else if (const StructType *STy = dyn_cast(Ty)) { const StructType *STy2 = cast(Ty2); if (STy->getNumElements() != STy2->getNumElements()) return false; @@ -585,27 +663,23 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, const ArrayType *ATy2 = cast(Ty2); return ATy->getNumElements() == ATy2->getNumElements() && TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes); - } else if (const PackedType *PTy = dyn_cast(Ty)) { - const PackedType *PTy2 = cast(Ty2); + } else 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)) { const FunctionType *FTy2 = cast(Ty2); if (FTy->isVarArg() != FTy2->isVarArg() || FTy->getNumParams() != FTy2->getNumParams() || - FTy->getNumAttrs() != FTy2->getNumAttrs() || - FTy->getParamAttrs(0) != FTy2->getParamAttrs(0) || !TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes)) return false; for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i) { - if (FTy->getParamAttrs(i+1) != FTy->getParamAttrs(i+1)) - return false; if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes)) return false; } return true; } else { - assert(0 && "Unknown derived type!"); + llvm_unreachable("Unknown derived type!"); return false; } } @@ -620,11 +694,11 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2) { // 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, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; if (!CurTy->isAbstract()) return false; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -635,10 +709,10 @@ static bool AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, } static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -651,7 +725,7 @@ static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, /// TypeHasCycleThroughItself - Return true if the specified type has a cycle /// back to itself. static bool TypeHasCycleThroughItself(const Type *Ty) { - std::set VisitedTypes; + SmallPtrSet VisitedTypes; if (Ty->isAbstract()) { // Optimized case for abstract types. for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); @@ -667,306 +741,40 @@ static bool TypeHasCycleThroughItself(const Type *Ty) { return false; } -/// getSubElementHash - Generate a hash value for all of the SubType's of this -/// type. The hash value is guaranteed to be zero if any of the subtypes are -/// an opaque type. Otherwise we try to mix them in as well as possible, but do -/// not look at the subtype's subtype's. -static unsigned getSubElementHash(const Type *Ty) { - unsigned HashVal = 0; - for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); - I != E; ++I) { - HashVal *= 32; - const Type *SubTy = I->get(); - HashVal += SubTy->getTypeID(); - switch (SubTy->getTypeID()) { - default: break; - case Type::OpaqueTyID: return 0; // Opaque -> hash = 0 no matter what. - case Type::IntegerTyID: - HashVal ^= (cast(SubTy)->getBitWidth() << 3); - break; - case Type::FunctionTyID: - HashVal ^= cast(SubTy)->getNumParams()*2 + - cast(SubTy)->isVarArg(); - break; - case Type::ArrayTyID: - HashVal ^= cast(SubTy)->getNumElements(); - break; - case Type::PackedTyID: - HashVal ^= cast(SubTy)->getNumElements(); - break; - case Type::StructTyID: - HashVal ^= cast(SubTy)->getNumElements(); - break; - } - } - return HashVal ? HashVal : 1; // Do not return zero unless opaque subty. -} - -//===----------------------------------------------------------------------===// -// Derived Type Factory Functions -//===----------------------------------------------------------------------===// - -namespace llvm { -class TypeMapBase { -protected: - /// TypesByHash - Keep track of types by their structure hash value. Note - /// that we only keep track of types that have cycles through themselves in - /// this map. - /// - std::multimap TypesByHash; - -public: - void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) { - std::multimap::iterator I = - TypesByHash.lower_bound(Hash); - for (; I != TypesByHash.end() && I->first == Hash; ++I) { - if (I->second == Ty) { - TypesByHash.erase(I); - return; - } - } - - // This must be do to an opaque type that was resolved. Switch down to hash - // code of zero. - assert(Hash && "Didn't find type entry!"); - RemoveFromTypesByHash(0, Ty); - } - - /// TypeBecameConcrete - When Ty gets a notification that TheType just became - /// concrete, drop uses and make Ty non-abstract if we should. - void TypeBecameConcrete(DerivedType *Ty, const DerivedType *TheType) { - // If the element just became concrete, remove 'ty' from the abstract - // type user list for the type. Do this for as many times as Ty uses - // OldType. - for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); - I != E; ++I) - if (I->get() == TheType) - TheType->removeAbstractTypeUser(Ty); - - // If the type is currently thought to be abstract, rescan all of our - // subtypes to see if the type has just become concrete! Note that this - // may send out notifications to AbstractTypeUsers that types become - // concrete. - if (Ty->isAbstract()) - Ty->PromoteAbstractToConcrete(); - } -}; -} - - -// TypeMap - Make sure that only one instance of a particular type may be -// created on any given run of the compiler... note that this involves updating -// our map if an abstract type gets refined somehow. -// -namespace llvm { -template -class TypeMap : public TypeMapBase { - std::map Map; -public: - typedef typename std::map::iterator iterator; - ~TypeMap() { print("ON EXIT"); } - - inline TypeClass *get(const ValType &V) { - iterator I = Map.find(V); - return I != Map.end() ? cast((Type*)I->second.get()) : 0; - } - - inline void add(const ValType &V, TypeClass *Ty) { - Map.insert(std::make_pair(V, Ty)); - - // If this type has a cycle, remember it. - TypesByHash.insert(std::make_pair(ValType::hashTypeStructure(Ty), Ty)); - print("add"); - } - - void clear(std::vector &DerivedTypes) { - for (typename std::map::iterator I = Map.begin(), - E = Map.end(); I != E; ++I) - DerivedTypes.push_back(I->second.get()); - TypesByHash.clear(); - Map.clear(); - } - - /// RefineAbstractType - This method is called after we have merged a type - /// with another one. We must now either merge the type away with - /// some other type or reinstall it in the map with it's new configuration. - void RefineAbstractType(TypeClass *Ty, const DerivedType *OldType, - const Type *NewType) { -#ifdef DEBUG_MERGE_TYPES - DOUT << "RefineAbstractType(" << (void*)OldType << "[" << *OldType - << "], " << (void*)NewType << " [" << *NewType << "])\n"; -#endif - - // Otherwise, we are changing one subelement type into another. Clearly the - // OldType must have been abstract, making us abstract. - assert(Ty->isAbstract() && "Refining a non-abstract type!"); - assert(OldType != NewType); - - // Make a temporary type holder for the type so that it doesn't disappear on - // us when we erase the entry from the map. - PATypeHolder TyHolder = Ty; - - // The old record is now out-of-date, because one of the children has been - // updated. Remove the obsolete entry from the map. - unsigned NumErased = Map.erase(ValType::get(Ty)); - assert(NumErased && "Element not found!"); - - // Remember the structural hash for the type before we start hacking on it, - // in case we need it later. - unsigned OldTypeHash = ValType::hashTypeStructure(Ty); - - // Find the type element we are refining... and change it now! - for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i) - if (Ty->ContainedTys[i] == OldType) - Ty->ContainedTys[i] = NewType; - unsigned NewTypeHash = ValType::hashTypeStructure(Ty); - - // If there are no cycles going through this node, we can do a simple, - // efficient lookup in the map, instead of an inefficient nasty linear - // lookup. - if (!TypeHasCycleThroughItself(Ty)) { - typename std::map::iterator I; - bool Inserted; - - tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty)); - if (!Inserted) { - // Refined to a different type altogether? - RemoveFromTypesByHash(OldTypeHash, Ty); - - // We already have this type in the table. Get rid of the newly refined - // type. - TypeClass *NewTy = cast((Type*)I->second.get()); - Ty->refineAbstractTypeTo(NewTy); - return; - } - } else { - // Now we check to see if there is an existing entry in the table which is - // structurally identical to the newly refined type. If so, this type - // gets refined to the pre-existing type. - // - std::multimap::iterator I, E, Entry; - tie(I, E) = TypesByHash.equal_range(NewTypeHash); - Entry = E; - for (; I != E; ++I) { - if (I->second == Ty) { - // Remember the position of the old type if we see it in our scan. - Entry = I; - } else { - if (TypesEqual(Ty, I->second)) { - TypeClass *NewTy = cast((Type*)I->second.get()); - - // Remove the old entry form TypesByHash. If the hash values differ - // now, remove it from the old place. Otherwise, continue scanning - // withing this hashcode to reduce work. - if (NewTypeHash != OldTypeHash) { - RemoveFromTypesByHash(OldTypeHash, Ty); - } else { - if (Entry == E) { - // Find the location of Ty in the TypesByHash structure if we - // haven't seen it already. - while (I->second != Ty) { - ++I; - assert(I != E && "Structure doesn't contain type??"); - } - Entry = I; - } - TypesByHash.erase(Entry); - } - Ty->refineAbstractTypeTo(NewTy); - return; - } - } - } - - // If there is no existing type of the same structure, we reinsert an - // updated record into the map. - Map.insert(std::make_pair(ValType::get(Ty), Ty)); - } - - // If the hash codes differ, update TypesByHash - if (NewTypeHash != OldTypeHash) { - RemoveFromTypesByHash(OldTypeHash, Ty); - TypesByHash.insert(std::make_pair(NewTypeHash, Ty)); - } - - // If the type is currently thought to be abstract, rescan all of our - // subtypes to see if the type has just become concrete! Note that this - // may send out notifications to AbstractTypeUsers that types become - // concrete. - if (Ty->isAbstract()) - Ty->PromoteAbstractToConcrete(); - } - - void print(const char *Arg) const { -#ifdef DEBUG_MERGE_TYPES - DOUT << "TypeMap<>::" << Arg << " table contents:\n"; - unsigned i = 0; - for (typename std::map::const_iterator I - = Map.begin(), E = Map.end(); I != E; ++I) - DOUT << " " << (++i) << ". " << (void*)I->second.get() << " " - << *I->second.get() << "\n"; -#endif - } - - void dump() const { print("dump output"); } -}; -} - - //===----------------------------------------------------------------------===// // Function Type Factory and Value Class... // - -//===----------------------------------------------------------------------===// -// Integer Type Factory... -// -namespace llvm { -class IntegerValType { - uint32_t bits; -public: - IntegerValType(uint16_t numbits) : bits(numbits) {} - - static IntegerValType get(const IntegerType *Ty) { - return IntegerValType(Ty->getBitWidth()); - } - - static unsigned hashTypeStructure(const IntegerType *Ty) { - return (unsigned)Ty->getBitWidth(); - } - - inline bool operator<(const IntegerValType &IVT) const { - return bits < IVT.bits; - } -}; -} - -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); + 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 = IntegerTypes->get(IVT); - if (ITy) return ITy; // Found a match, return it! - - // Value not found. Derive a new type! - ITy = new IntegerType(NumBits); - IntegerTypes->add(IVT, ITy); - + IntegerType *ITy = 0; + + // 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); + } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *ITy << "\n"; + DEBUG(errs() << "Derived new type: " << *ITy << "\n"); #endif return ITy; } @@ -976,309 +784,195 @@ bool IntegerType::isPowerOf2ByteWidth() const { return (BitWidth > 7) && isPowerOf2_32(BitWidth); } -// FunctionValType - Define a class to hold the key that goes into the TypeMap -// -namespace llvm { -class FunctionValType { - const Type *RetTy; - std::vector ArgTypes; - std::vector ParamAttrs; - bool isVarArg; -public: - FunctionValType(const Type *ret, const std::vector &args, - bool IVA, const FunctionType::ParamAttrsList &attrs) - : RetTy(ret), isVarArg(IVA) { - for (unsigned i = 0; i < args.size(); ++i) - ArgTypes.push_back(args[i]); - for (unsigned i = 0; i < attrs.size(); ++i) - ParamAttrs.push_back(attrs[i]); - } - - static FunctionValType get(const FunctionType *FT); - - static unsigned hashTypeStructure(const FunctionType *FT) { - return FT->getNumParams()*64+FT->getNumAttrs()*2+FT->isVarArg(); - } - - inline bool operator<(const FunctionValType &MTV) const { - if (RetTy < MTV.RetTy) return true; - if (RetTy > MTV.RetTy) return false; - if (isVarArg < MTV.isVarArg) return true; - if (isVarArg > MTV.isVarArg) return false; - if (ArgTypes < MTV.ArgTypes) return true; - return ArgTypes == MTV.ArgTypes && ParamAttrs < MTV.ParamAttrs; - } -}; +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; - std::vector ParamAttrs; ParamTypes.reserve(FT->getNumParams()); for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) ParamTypes.push_back(FT->getParamType(i)); - for (unsigned i = 0, e = FT->getNumAttrs(); i != e; ++i) - ParamAttrs.push_back(FT->getParamAttrs(i)); - return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg(), - ParamAttrs); + return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg()); } // FunctionType::get - The factory function for the FunctionType class... FunctionType *FunctionType::get(const Type *ReturnType, const std::vector &Params, - bool isVarArg, - const std::vector &Attrs) { - bool noAttrs = true; - for (unsigned i = 0, e = Attrs.size(); i < e; ++i) - if (Attrs[i] != FunctionType::NoAttributeSet) { - noAttrs = false; - break; - } - const std::vector NullAttrs; - const std::vector *TheAttrs = &Attrs; - if (noAttrs) - TheAttrs = &NullAttrs; - FunctionValType VT(ReturnType, Params, isVarArg, *TheAttrs); - FunctionType *MT = FunctionTypes->get(VT); - if (MT) return MT; - - MT = new FunctionType(ReturnType, Params, isVarArg, *TheAttrs); - FunctionTypes->add(VT, MT); + 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); + } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << MT << "\n"; + DEBUG(errs() << "Derived new type: " << FT << "\n"); #endif - return MT; -} - -FunctionType::ParameterAttributes -FunctionType::getParamAttrs(unsigned Idx) const { - if (!ParamAttrs) - return NoAttributeSet; - if (Idx >= ParamAttrs->size()) - return NoAttributeSet; - return (*ParamAttrs)[Idx]; + return FT; } -std::string FunctionType::getParamAttrsText(ParameterAttributes Attr) { - std::string Result; - if (Attr & ZExtAttribute) - Result += "zext "; - if (Attr & SExtAttribute) - Result += "sext "; - if (Attr & NoReturnAttribute) - Result += "noreturn "; - if (Attr & InRegAttribute) - Result += "inreg "; - if (Attr & StructRetAttribute) - Result += "sret "; - return Result; -} - -//===----------------------------------------------------------------------===// -// Array Type Factory... -// -namespace llvm { -class ArrayValType { - const Type *ValTy; - uint64_t Size; -public: - ArrayValType(const Type *val, uint64_t sz) : ValTy(val), Size(sz) {} - - static ArrayValType get(const ArrayType *AT) { - return ArrayValType(AT->getElementType(), AT->getNumElements()); - } - - static unsigned hashTypeStructure(const ArrayType *AT) { - return (unsigned)AT->getNumElements(); - } - - inline bool operator<(const ArrayValType &MTV) const { - if (Size < MTV.Size) return true; - return Size == MTV.Size && ValTy < MTV.ValTy; - } -}; -} -static ManagedStatic > ArrayTypes; - - ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { - assert(ElementType && "Can't get array of null types!"); + assert(ElementType && "Can't get array of types!"); + assert(isValidElementType(ElementType) && "Invalid type for array element!"); ArrayValType AVT(ElementType, NumElements); - ArrayType *AT = ArrayTypes->get(AVT); - if (AT) return AT; // Found a match, return it! - - // Value not found. Derive a new type! - ArrayTypes->add(AVT, AT = new ArrayType(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 - DOUT << "Derived new type: " << *AT << "\n"; + DEBUG(errs() << "Derived new type: " << *AT << "\n"); #endif return AT; } - -//===----------------------------------------------------------------------===// -// Packed Type Factory... -// -namespace llvm { -class PackedValType { - const Type *ValTy; - unsigned Size; -public: - PackedValType(const Type *val, int sz) : ValTy(val), Size(sz) {} - - static PackedValType get(const PackedType *PT) { - return PackedValType(PT->getElementType(), PT->getNumElements()); - } - - static unsigned hashTypeStructure(const PackedType *PT) { - return PT->getNumElements(); - } - - inline bool operator<(const PackedValType &MTV) const { - if (Size < MTV.Size) return true; - return Size == MTV.Size && ValTy < MTV.ValTy; - } -}; +bool ArrayType::isValidElementType(const Type *ElemTy) { + return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID && + ElemTy->getTypeID() != MetadataTyID && !isa(ElemTy); } -static ManagedStatic > PackedTypes; - - -PackedType *PackedType::get(const Type *ElementType, unsigned NumElements) { - assert(ElementType && "Can't get packed of null types!"); - assert(isPowerOf2_32(NumElements) && "Vector length should be a power of 2!"); - - PackedValType PVT(ElementType, NumElements); - PackedType *PT = PackedTypes->get(PVT); - if (PT) return PT; // Found a match, return it! - // Value not found. Derive a new type! - PackedTypes->add(PVT, PT = new PackedType(ElementType, NumElements)); +VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { + assert(ElementType && "Can't get vector of 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)); + } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *PT << "\n"; + DEBUG(errs() << "Derived new type: " << *PT << "\n"); #endif return PT; } +bool VectorType::isValidElementType(const Type *ElemTy) { + return ElemTy->isInteger() || ElemTy->isFloatingPoint() || + isa(ElemTy); +} + //===----------------------------------------------------------------------===// // Struct Type Factory... // -namespace llvm { -// StructValType - Define a class to hold the key that goes into the TypeMap -// -class StructValType { - std::vector ElTypes; - bool packed; -public: - StructValType(const std::vector &args, bool isPacked) - : ElTypes(args), packed(isPacked) {} - - static StructValType get(const StructType *ST) { - std::vector ElTypes; - ElTypes.reserve(ST->getNumElements()); - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) - ElTypes.push_back(ST->getElementType(i)); - - return StructValType(ElTypes, ST->isPacked()); - } - - static unsigned hashTypeStructure(const StructType *ST) { - return ST->getNumElements(); - } - - inline bool operator<(const StructValType &STV) const { - if (ElTypes < STV.ElTypes) return true; - else if (ElTypes > STV.ElTypes) return false; - else return (int)packed < (int)STV.packed; - } -}; -} - -static ManagedStatic > StructTypes; - -StructType *StructType::get(const std::vector &ETypes, +StructType *StructType::get(LLVMContext &Context, + const std::vector &ETypes, bool isPacked) { StructValType STV(ETypes, isPacked); - StructType *ST = StructTypes->get(STV); - if (ST) return ST; - - // Value not found. Derive a new type! - StructTypes->add(STV, ST = new StructType(ETypes, isPacked)); - + StructType *ST = 0; + + 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(Context, ETypes, isPacked); + pImpl->StructTypes.add(STV, ST); + } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *ST << "\n"; + DEBUG(errs() << "Derived new type: " << *ST << "\n"); #endif return ST; } +StructType *StructType::get(LLVMContext &Context, const Type *type, ...) { + va_list ap; + std::vector StructFields; + va_start(ap, type); + while (type) { + StructFields.push_back(type); + type = va_arg(ap, llvm::Type*); + } + return llvm::StructType::get(Context, StructFields); +} + +bool StructType::isValidElementType(const Type *ElemTy) { + return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID && + ElemTy->getTypeID() != MetadataTyID && !isa(ElemTy); +} //===----------------------------------------------------------------------===// // Pointer Type Factory... // -// PointerValType - Define a class to hold the key that goes into the TypeMap -// -namespace llvm { -class PointerValType { - const Type *ValTy; -public: - PointerValType(const Type *val) : ValTy(val) {} - - static PointerValType get(const PointerType *PT) { - return PointerValType(PT->getElementType()); - } - - static unsigned hashTypeStructure(const PointerType *PT) { - return getSubElementHash(PT); - } - - bool operator<(const PointerValType &MTV) const { - return ValTy < MTV.ValTy; - } -}; -} - -static ManagedStatic > PointerTypes; - -PointerType *PointerType::get(const Type *ValueType) { +PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { assert(ValueType && "Can't get a pointer to type!"); - assert(ValueType != Type::VoidTy && - "Pointer to void is not valid, use sbyte* instead!"); - assert(ValueType != Type::LabelTy && "Pointer to label is not valid!"); - PointerValType PVT(ValueType); - - PointerType *PT = PointerTypes->get(PVT); - if (PT) return PT; - - // Value not found. Derive a new type! - PointerTypes->add(PVT, PT = new PointerType(ValueType)); + 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; + + PT = pImpl->PointerTypes.get(PVT); + + if (!PT) { + // Value not found. Derive a new type! + pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace)); + } #ifdef DEBUG_MERGE_TYPES - DOUT << "Derived new type: " << *PT << "\n"; + DEBUG(errs() << "Derived new type: " << *PT << "\n"); #endif return PT; } +const PointerType *Type::getPointerTo(unsigned addrs) const { + return PointerType::get(this, addrs); +} + +bool PointerType::isValidElementType(const Type *ElemTy) { + return ElemTy->getTypeID() != VoidTyID && + ElemTy->getTypeID() != LabelTyID && + ElemTy->getTypeID() != MetadataTyID; +} + + //===----------------------------------------------------------------------===// // Derived Type Refinement Functions //===----------------------------------------------------------------------===// +// 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); +} + + // 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. @@ -1293,44 +987,47 @@ 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(errs() << " 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(errs() << "DELETEing unused abstract type: <" << *this + << ">[" << (void*)this << "]" << "\n"); #endif - delete this; // No users of this abstract type! + + this->destroy(); } + } - -// 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. +// unlockedRefineAbstractTypeTo - 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) { +void DerivedType::unlockedRefineAbstractTypeTo(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! - AbstractTypeDescriptions->clear(); + pImpl->AbstractTypeDescriptions.clear(); #ifdef DEBUG_MERGE_TYPES - DOUT << "REFINING abstract type [" << (void*)this << " " - << *this << "] to [" << (void*)NewType << " " - << *NewType << "]!\n"; + DEBUG(errs() << "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; @@ -1357,12 +1054,12 @@ void DerivedType::refineAbstractTypeTo(const Type *NewType) { while (!AbstractTypeUsers.empty() && NewTy != this) { AbstractTypeUser *User = AbstractTypeUsers.back(); - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=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(errs() << " REFINING user " << OldSize-1 << "[" << (void*)User + << "] of abstract type [" << (void*)this << " " + << *this << "] to [" << (void*)NewTy.get() << " " + << *NewTy << "]!\n"); #endif User->refineAbstractType(this, NewTy); @@ -1376,15 +1073,24 @@ void DerivedType::refineAbstractTypeTo(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. + 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(errs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n"); #endif - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; while (!AbstractTypeUsers.empty()) { AbstractTypeUser *ATU = AbstractTypeUsers.back(); ATU->typeBecameConcrete(this); @@ -1400,11 +1106,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); } @@ -1414,24 +1122,28 @@ void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) { // void ArrayType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - ArrayTypes->RefineAbstractType(this, OldType, NewType); + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->ArrayTypes.RefineAbstractType(this, OldType, NewType); } void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) { - ArrayTypes->TypeBecameConcrete(this, AbsTy); + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->ArrayTypes.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 PackedType::refineAbstractType(const DerivedType *OldType, +void VectorType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - PackedTypes->RefineAbstractType(this, OldType, NewType); + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->VectorTypes.RefineAbstractType(this, OldType, NewType); } -void PackedType::typeBecameConcrete(const DerivedType *AbsTy) { - PackedTypes->TypeBecameConcrete(this, AbsTy); +void VectorType::typeBecameConcrete(const DerivedType *AbsTy) { + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->VectorTypes.TypeBecameConcrete(this, AbsTy); } // refineAbstractType - Called when a contained type is found to be more @@ -1440,11 +1152,13 @@ void PackedType::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 @@ -1453,29 +1167,23 @@ 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 (const IntegerType *IT = dyn_cast(V->getType())) - return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; + if (isa(V->getType())) + 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) { +raw_ostream &operator<<(raw_ostream &OS, const Type &T) { T.print(OS); return OS; }