#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 <algorithm>
#include <cstdarg>
AbstractTypeUser::~AbstractTypeUser() {}
+void AbstractTypeUser::setType(Value *V, const Type *NewTy) {
+ V->VTy = NewTy;
+}
//===----------------------------------------------------------------------===//
// Type Class Implementation
//===----------------------------------------------------------------------===//
-// Lock used for guarding access to the type maps.
-static ManagedStatic<sys::SmartMutex<true> > TypeMapLock;
-
-// Recursive lock used for guarding access to AbstractTypeUsers.
-// NOTE: The true template parameter means this will no-op when we're not in
-// multithreaded mode.
-static ManagedStatic<sys::SmartMutex<true> > AbstractTypeUsersLock;
-
-// Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions
-// for types as they are needed. Because resolution of types must invalidate
-// all of the abstract type descriptions, we keep them in a seperate map to make
-// this easy.
-static ManagedStatic<TypePrinting> ConcreteTypeDescriptions;
-static ManagedStatic<TypePrinting> AbstractTypeDescriptions;
-
/// Because of the way Type subclasses are allocated, this function is necessary
/// to use the correct kind of "delete" operator to deallocate the Type object.
-/// Some type objects (FunctionTy, StructTy) allocate additional space after
-/// the space for their derived type to hold the contained types array of
+/// Some type objects (FunctionTy, StructTy, UnionTy) 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<FunctionType>(this) || isa<StructType>(this)) {
+ if (this->isFunctionTy() || this->isStructTy() ||
+ this->isUnionTy()) {
// First, make sure we destruct any PATypeHandles allocated by these
// subclasses. They must be manually destructed.
for (unsigned i = 0; i < NumContainedTys; ++i)
// Now call the destructor for the subclass directly because we're going
// to delete this as an array of char.
- if (isa<FunctionType>(this))
+ if (this->isFunctionTy())
static_cast<const FunctionType*>(this)->FunctionType::~FunctionType();
- else
+ else if (this->isStructTy())
static_cast<const StructType*>(this)->StructType::~StructType();
+ else
+ static_cast<const UnionType*>(this)->UnionType::~UnionType();
// Finally, remove the memory as an array deallocation of the chars it was
// constructed from.
operator delete(const_cast<Type *>(this));
return;
+ } else if (const OpaqueType *opaque_this = dyn_cast<OpaqueType>(this)) {
+ LLVMContextImpl *pImpl = this->getContext().pImpl;
+ pImpl->OpaqueTypes.erase(opaque_this);
}
// For all the other type subclasses, there is either no contained types or
delete this;
}
-const Type *Type::getPrimitiveType(TypeID IDNumber) {
+const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
switch (IDNumber) {
- case VoidTyID : return VoidTy;
- case FloatTyID : return FloatTy;
- case DoubleTyID : return DoubleTy;
- case X86_FP80TyID : return X86_FP80Ty;
- case FP128TyID : return FP128Ty;
- case PPC_FP128TyID : return PPC_FP128Ty;
- case LabelTyID : return LabelTy;
- case MetadataTyID : return MetadataTy;
+ case VoidTyID : return getVoidTy(C);
+ case FloatTyID : return getFloatTy(C);
+ case DoubleTyID : return getDoubleTy(C);
+ case X86_FP80TyID : return getX86_FP80Ty(C);
+ case FP128TyID : return getFP128Ty(C);
+ case PPC_FP128TyID : return getPPC_FP128Ty(C);
+ case LabelTyID : return getLabelTy(C);
+ case MetadataTyID : return getMetadataTy(C);
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;
}
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<IntegerType>(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<VectorType>(this)->getElementType()->isInteger();
+ return cast<VectorType>(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<VectorType>(this)->getElementType()->isFloatingPoint();
+ return cast<VectorType>(this)->getElementType()->isFloatingPointTy();
}
// canLosslesslyBitCastTo - Return true if this type can be converted to
// 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<PointerType>(this))
- return isa<PointerType>(Ty);
+ if (this->isPointerTy())
+ return Ty->isPointerTy();
return false; // Other types have no identity values
}
int Type::getFPMantissaWidth() const {
if (const VectorType *VTy = dyn_cast<VectorType>(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;
/// 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<IntegerType>(this))
+ if (this->isIntegerTy())
return true;
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
if (const VectorType *PTy = dyn_cast<VectorType>(this))
return PTy->getElementType()->isSized();
- if (!isa<StructType>(this))
+ if (!this->isStructTy() && !this->isUnionTy())
return false;
// Okay, our struct is sized if all of the elements are...
// Yes, it is forwarded again. First thing, add the reference to the new
// forward type.
if (RealForwardedType->isAbstract())
- cast<DerivedType>(RealForwardedType)->addRef();
+ RealForwardedType->addRef();
// Now drop the old reference. This could cause ForwardType to get deleted.
- cast<DerivedType>(ForwardType)->dropRef();
+ // ForwardType must be abstract because only abstract types can have their own
+ // ForwardTypes.
+ ForwardType->dropRef();
// Return the updated type.
ForwardType = RealForwardedType;
std::string Type::getDescription() const {
+ LLVMContextImpl *pImpl = getContext().pImpl;
TypePrinting &Map =
- isAbstract() ? *AbstractTypeDescriptions : *ConcreteTypeDescriptions;
+ isAbstract() ?
+ pImpl->AbstractTypeDescriptions :
+ pImpl->ConcreteTypeDescriptions;
std::string DescStr;
raw_string_ostream DescOS(DescStr);
bool StructType::indexValid(const Value *V) const {
// Structure indexes require 32-bit integer constants.
- if (V->getType() == Type::Int32Ty)
+ if (V->getType()->isIntegerTy(32))
if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
return indexValid(CU->getZExtValue());
return false;
return ContainedTys[Idx];
}
+
+bool UnionType::indexValid(const Value *V) const {
+ // Union indexes require 32-bit integer constants.
+ if (V->getType()->isIntegerTy(32))
+ if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
+ return indexValid(CU->getZExtValue());
+ return false;
+}
+
+bool UnionType::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...
+//
+const Type *UnionType::getTypeAtIndex(const Value *V) const {
+ unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
+ return getTypeAtIndex(Idx);
+}
+
+const Type *UnionType::getTypeAtIndex(unsigned Idx) const {
+ assert(indexValid(Idx) && "Invalid structure index!");
+ return ContainedTys[Idx];
+}
+
//===----------------------------------------------------------------------===//
// Primitive 'Type' data
//===----------------------------------------------------------------------===//
-const Type *Type::VoidTy = new Type(Type::VoidTyID);
-const Type *Type::FloatTy = new Type(Type::FloatTyID);
-const Type *Type::DoubleTy = new Type(Type::DoubleTyID);
-const Type *Type::X86_FP80Ty = new Type(Type::X86_FP80TyID);
-const Type *Type::FP128Ty = new Type(Type::FP128TyID);
-const Type *Type::PPC_FP128Ty = new Type(Type::PPC_FP128TyID);
-const Type *Type::LabelTy = new Type(Type::LabelTyID);
-const Type *Type::MetadataTy = new Type(Type::MetadataTyID);
+const Type *Type::getVoidTy(LLVMContext &C) {
+ return &C.pImpl->VoidTy;
+}
-namespace {
- struct BuiltinIntegerType : public IntegerType {
- explicit BuiltinIntegerType(unsigned W) : IntegerType(W) {}
- };
+const Type *Type::getLabelTy(LLVMContext &C) {
+ return &C.pImpl->LabelTy;
+}
+
+const Type *Type::getFloatTy(LLVMContext &C) {
+ return &C.pImpl->FloatTy;
+}
+
+const Type *Type::getDoubleTy(LLVMContext &C) {
+ return &C.pImpl->DoubleTy;
+}
+
+const Type *Type::getMetadataTy(LLVMContext &C) {
+ return &C.pImpl->MetadataTy;
+}
+
+const Type *Type::getX86_FP80Ty(LLVMContext &C) {
+ return &C.pImpl->X86_FP80Ty;
+}
+
+const Type *Type::getFP128Ty(LLVMContext &C) {
+ return &C.pImpl->FP128Ty;
+}
+
+const Type *Type::getPPC_FP128Ty(LLVMContext &C) {
+ return &C.pImpl->PPC_FP128Ty;
+}
+
+const IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
+ return IntegerType::get(C, N);
+}
+
+const IntegerType *Type::getInt1Ty(LLVMContext &C) {
+ return &C.pImpl->Int1Ty;
+}
+
+const IntegerType *Type::getInt8Ty(LLVMContext &C) {
+ return &C.pImpl->Int8Ty;
+}
+
+const IntegerType *Type::getInt16Ty(LLVMContext &C) {
+ return &C.pImpl->Int16Ty;
+}
+
+const IntegerType *Type::getInt32Ty(LLVMContext &C) {
+ return &C.pImpl->Int32Ty;
+}
+
+const IntegerType *Type::getInt64Ty(LLVMContext &C) {
+ return &C.pImpl->Int64Ty;
+}
+
+const PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) {
+ return getFloatTy(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) {
+ return getDoubleTy(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) {
+ return getX86_FP80Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) {
+ return getFP128Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) {
+ return getPPC_FP128Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) {
+ return getIntNTy(C, N)->getPointerTo(AS);
+}
+
+const PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) {
+ return getInt1Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) {
+ return getInt8Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) {
+ return getInt16Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) {
+ return getInt32Ty(C)->getPointerTo(AS);
+}
+
+const PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) {
+ return getInt64Ty(C)->getPointerTo(AS);
}
-const IntegerType *Type::Int1Ty = new BuiltinIntegerType(1);
-const IntegerType *Type::Int8Ty = new BuiltinIntegerType(8);
-const IntegerType *Type::Int16Ty = new BuiltinIntegerType(16);
-const IntegerType *Type::Int32Ty = new BuiltinIntegerType(32);
-const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
//===----------------------------------------------------------------------===//
// Derived Type Constructors
/// 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<PointerType>(RetTy))
- return PTy->getElementType() != Type::MetadataTy;
- return true;
- }
- if (RetTy == Type::VoidTy || RetTy == Type::MetadataTy ||
- isa<OpaqueType>(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<StructType>(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->getTypeID() != LabelTyID &&
+ RetTy->getTypeID() != MetadataTyID;
}
/// isValidArgumentType - Return true if the specified type is valid as an
/// argument type.
bool FunctionType::isValidArgumentType(const Type *ArgTy) {
- if ((!ArgTy->isFirstClassType() && !isa<OpaqueType>(ArgTy)) ||
- (isa<PointerType>(ArgTy) &&
- cast<PointerType>(ArgTy)->getElementType() == Type::MetadataTy))
- return false;
-
- return true;
+ return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy();
}
FunctionType::FunctionType(const Type *Result,
const std::vector<const Type*> &Params,
bool IsVarArgs)
- : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) {
+ : DerivedType(Result->getContext(), FunctionTyID), isVarArgs(IsVarArgs) {
ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
NumContainedTys = Params.size() + 1; // + 1 for result type
assert(isValidReturnType(Result) && "invalid return type for function");
setAbstract(isAbstract);
}
-StructType::StructType(const std::vector<const Type*> &Types, bool isPacked)
- : CompositeType(StructTyID) {
+StructType::StructType(LLVMContext &C,
+ const std::vector<const Type*> &Types, bool isPacked)
+ : CompositeType(C, StructTyID) {
ContainedTys = reinterpret_cast<PATypeHandle*>(this + 1);
NumContainedTys = Types.size();
setSubclassData(isPacked);
setAbstract(isAbstract);
}
+UnionType::UnionType(LLVMContext &C,const Type* const* Types, unsigned NumTypes)
+ : CompositeType(C, UnionTyID) {
+ ContainedTys = reinterpret_cast<PATypeHandle*>(this + 1);
+ NumContainedTys = NumTypes;
+ bool isAbstract = false;
+ for (unsigned i = 0; i < NumTypes; ++i) {
+ assert(Types[i] && "<null> type for union field!");
+ assert(isValidElementType(Types[i]) &&
+ "Invalid type for union element!");
+ new (&ContainedTys[i]) PATypeHandle(Types[i], this);
+ isAbstract |= Types[i]->isAbstract();
+ }
+
+ // Calculate whether or not this type is abstract
+ setAbstract(isAbstract);
+}
+
ArrayType::ArrayType(const Type *ElType, uint64_t NumEl)
: SequentialType(ArrayTyID, ElType) {
NumElements = NumEl;
setAbstract(E->isAbstract());
}
-OpaqueType::OpaqueType() : DerivedType(OpaqueTyID) {
+OpaqueType::OpaqueType(LLVMContext &C) : DerivedType(C, OpaqueTyID) {
setAbstract(true);
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *this << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *this << "\n");
#endif
}
if (NumContainedTys != 0) {
// The type must stay abstract. To do this, we insert a pointer to a type
// that will never get resolved, thus will always be abstract.
- static Type *AlwaysOpaqueTy = 0;
- static PATypeHolder* Holder = 0;
- Type *tmp = AlwaysOpaqueTy;
- if (llvm_is_multithreaded()) {
- sys::MemoryFence();
- if (!tmp) {
- llvm_acquire_global_lock();
- tmp = AlwaysOpaqueTy;
- if (!tmp) {
- tmp = OpaqueType::get();
- PATypeHolder* tmp2 = new PATypeHolder(AlwaysOpaqueTy);
- sys::MemoryFence();
- AlwaysOpaqueTy = tmp;
- Holder = tmp2;
- }
-
- llvm_release_global_lock();
- }
- } else {
- AlwaysOpaqueTy = OpaqueType::get();
- Holder = new PATypeHolder(AlwaysOpaqueTy);
- }
-
- ContainedTys[0] = AlwaysOpaqueTy;
+ ContainedTys[0] = getContext().pImpl->AlwaysOpaqueTy;
// Change the rest of the types to be Int32Ty's. It doesn't matter what we
// pick so long as it doesn't point back to this type. We choose something
- // concrete to avoid overhead for adding to AbstracTypeUser lists and stuff.
+ // concrete to avoid overhead for adding to AbstractTypeUser lists and
+ // stuff.
+ const Type *ConcreteTy = Type::getInt32Ty(getContext());
for (unsigned i = 1, e = NumContainedTys; i != e; ++i)
- ContainedTys[i] = Type::Int32Ty;
+ ContainedTys[i] = ConcreteTy;
}
}
// 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<OpaqueType>(SCC[0]))
+ 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,
std::map<const Type *, const Type *> &EqTypes) {
if (Ty == Ty2) return true;
if (Ty->getTypeID() != Ty2->getTypeID()) return false;
- if (isa<OpaqueType>(Ty))
+ if (Ty->isOpaqueTy())
return false; // Two unequal opaque types are never equal
std::map<const Type*, const Type*>::iterator It = EqTypes.find(Ty);
if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes))
return false;
return true;
+ } else if (const UnionType *UTy = dyn_cast<UnionType>(Ty)) {
+ const UnionType *UTy2 = cast<UnionType>(Ty2);
+ if (UTy->getNumElements() != UTy2->getNumElements()) return false;
+ for (unsigned i = 0, e = UTy2->getNumElements(); i != e; ++i)
+ if (!TypesEqual(UTy->getElementType(i), UTy2->getElementType(i), EqTypes))
+ return false;
+ return true;
} else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
const ArrayType *ATy2 = cast<ArrayType>(Ty2);
return ATy->getNumElements() == ATy2->getNumElements() &&
}
}
+namespace llvm { // in namespace llvm so findable by ADL
static bool TypesEqual(const Type *Ty, const Type *Ty2) {
std::map<const Type *, const Type *> EqTypes;
- return TypesEqual(Ty, Ty2, EqTypes);
+ return ::TypesEqual(Ty, Ty2, EqTypes);
+}
}
// AbstractTypeHasCycleThrough - Return true there is a path from CurTy to
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<const Type*, 128> VisitedTypes;
}
return false;
}
+}
//===----------------------------------------------------------------------===//
// Function Type Factory and Value Class...
//
-
-static ManagedStatic<TypeMap<IntegerValType, IntegerType> > 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<IntegerType>(Type::Int1Ty);
- case 8: return cast<IntegerType>(Type::Int8Ty);
- case 16: return cast<IntegerType>(Type::Int16Ty);
- case 32: return cast<IntegerType>(Type::Int32Ty);
- case 64: return cast<IntegerType>(Type::Int64Ty);
+ case 1: return cast<IntegerType>(Type::getInt1Ty(C));
+ case 8: return cast<IntegerType>(Type::getInt8Ty(C));
+ case 16: return cast<IntegerType>(Type::getInt16Ty(C));
+ case 32: return cast<IntegerType>(Type::getInt32Ty(C));
+ case 64: return cast<IntegerType>(Type::getInt64Ty(C));
default:
break;
}
+
+ LLVMContextImpl *pImpl = C.pImpl;
IntegerValType IVT(NumBits);
IntegerType *ITy = 0;
// First, see if the type is already in the table, for which
// a reader lock suffices.
- sys::SmartScopedLock<true> L(*TypeMapLock);
- ITy = IntegerTypes->get(IVT);
+ ITy = pImpl->IntegerTypes.get(IVT);
if (!ITy) {
// Value not found. Derive a new type!
- ITy = new IntegerType(NumBits);
- IntegerTypes->add(IVT, ITy);
+ ITy = new IntegerType(C, NumBits);
+ pImpl->IntegerTypes.add(IVT, ITy);
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *ITy << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *ITy << "\n");
#endif
return ITy;
}
LLVMContextImpl *pImpl = ReturnType->getContext().pImpl;
- sys::SmartScopedLock<true> L(*TypeMapLock);
FT = pImpl->FunctionTypes.get(VT);
if (!FT) {
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << FT << "\n";
+ DEBUG(dbgs() << "Derived new type: " << FT << "\n");
#endif
return FT;
}
LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
- sys::SmartScopedLock<true> L(*TypeMapLock);
AT = pImpl->ArrayTypes.get(AVT);
if (!AT) {
pImpl->ArrayTypes.add(AVT, AT = new ArrayType(ElementType, NumElements));
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *AT << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *AT << "\n");
#endif
return AT;
}
bool ArrayType::isValidElementType(const Type *ElemTy) {
- if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy ||
- ElemTy == Type::MetadataTy)
- return false;
-
- if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy))
- if (PTy->getElementType() == Type::MetadataTy)
- return false;
-
- return true;
+ return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID &&
+ ElemTy->getTypeID() != MetadataTyID && !ElemTy->isFunctionTy();
}
VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) {
LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
- sys::SmartScopedLock<true> L(*TypeMapLock);
PT = pImpl->VectorTypes.get(PVT);
if (!PT) {
pImpl->VectorTypes.add(PVT, PT = new VectorType(ElementType, NumElements));
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *PT << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *PT << "\n");
#endif
return PT;
}
bool VectorType::isValidElementType(const Type *ElemTy) {
- if (ElemTy->isInteger() || ElemTy->isFloatingPoint() ||
- isa<OpaqueType>(ElemTy))
- return true;
-
- return false;
+ return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() ||
+ ElemTy->isOpaqueTy();
}
//===----------------------------------------------------------------------===//
LLVMContextImpl *pImpl = Context.pImpl;
- sys::SmartScopedLock<true> L(*TypeMapLock);
ST = pImpl->StructTypes.get(STV);
if (!ST) {
// Value not found. Derive a new type!
ST = (StructType*) operator new(sizeof(StructType) +
sizeof(PATypeHandle) * ETypes.size());
- new (ST) StructType(ETypes, isPacked);
+ new (ST) StructType(Context, ETypes, isPacked);
pImpl->StructTypes.add(STV, ST);
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *ST << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *ST << "\n");
#endif
return ST;
}
}
bool StructType::isValidElementType(const Type *ElemTy) {
- if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy ||
- ElemTy == Type::MetadataTy)
- return false;
+ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
+ !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
+}
- if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy))
- if (PTy->getElementType() == Type::MetadataTy)
- return false;
- return true;
+//===----------------------------------------------------------------------===//
+// Union Type Factory...
+//
+
+UnionType *UnionType::get(const Type* const* Types, unsigned NumTypes) {
+ assert(NumTypes > 0 && "union must have at least one member type!");
+ UnionValType UTV(Types, NumTypes);
+ UnionType *UT = 0;
+
+ LLVMContextImpl *pImpl = Types[0]->getContext().pImpl;
+
+ UT = pImpl->UnionTypes.get(UTV);
+
+ if (!UT) {
+ // Value not found. Derive a new type!
+ UT = (UnionType*) operator new(sizeof(UnionType) +
+ sizeof(PATypeHandle) * NumTypes);
+ new (UT) UnionType(Types[0]->getContext(), Types, NumTypes);
+ pImpl->UnionTypes.add(UTV, UT);
+ }
+#ifdef DEBUG_MERGE_TYPES
+ DEBUG(dbgs() << "Derived new type: " << *UT << "\n");
+#endif
+ return UT;
}
+UnionType *UnionType::get(const Type *type, ...) {
+ va_list ap;
+ SmallVector<const llvm::Type*, 8> UnionFields;
+ va_start(ap, type);
+ while (type) {
+ UnionFields.push_back(type);
+ type = va_arg(ap, llvm::Type*);
+ }
+ unsigned NumTypes = UnionFields.size();
+ assert(NumTypes > 0 && "union must have at least one member type!");
+ return llvm::UnionType::get(&UnionFields[0], NumTypes);
+}
+
+bool UnionType::isValidElementType(const Type *ElemTy) {
+ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
+ !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
+}
+
+int UnionType::getElementTypeIndex(const Type *ElemTy) const {
+ int index = 0;
+ for (UnionType::element_iterator I = element_begin(), E = element_end();
+ I != E; ++I, ++index) {
+ if (ElemTy == *I) return index;
+ }
+
+ return -1;
+}
//===----------------------------------------------------------------------===//
// Pointer Type Factory...
PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) {
assert(ValueType && "Can't get a pointer to <null> type!");
- assert(ValueType != Type::VoidTy &&
+ assert(ValueType->getTypeID() != VoidTyID &&
"Pointer to void is not valid, use i8* instead!");
assert(isValidElementType(ValueType) && "Invalid type for pointer element!");
PointerValType PVT(ValueType, AddressSpace);
LLVMContextImpl *pImpl = ValueType->getContext().pImpl;
- sys::SmartScopedLock<true> L(*TypeMapLock);
PT = pImpl->PointerTypes.get(PVT);
if (!PT) {
pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace));
}
#ifdef DEBUG_MERGE_TYPES
- DOUT << "Derived new type: " << *PT << "\n";
+ DEBUG(dbgs() << "Derived new type: " << *PT << "\n");
#endif
return PT;
}
-PointerType *Type::getPointerTo(unsigned addrs) const {
+const PointerType *Type::getPointerTo(unsigned addrs) const {
return PointerType::get(this, addrs);
}
bool PointerType::isValidElementType(const Type *ElemTy) {
- if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy)
- return false;
+ return ElemTy->getTypeID() != VoidTyID &&
+ ElemTy->getTypeID() != LabelTyID &&
+ ElemTy->getTypeID() != MetadataTyID;
+}
- if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy))
- if (PTy->getElementType() == Type::MetadataTy)
- return false;
- return true;
+//===----------------------------------------------------------------------===//
+// Opaque Type Factory...
+//
+
+OpaqueType *OpaqueType::get(LLVMContext &C) {
+ OpaqueType *OT = new OpaqueType(C); // All opaque types are distinct
+
+ LLVMContextImpl *pImpl = C.pImpl;
+ pImpl->OpaqueTypes.insert(OT);
+ return OT;
}
+
//===----------------------------------------------------------------------===//
// Derived Type Refinement Functions
//===----------------------------------------------------------------------===//
// it. This function is called primarily by the PATypeHandle class.
void Type::addAbstractTypeUser(AbstractTypeUser *U) const {
assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
- AbstractTypeUsersLock->acquire();
AbstractTypeUsers.push_back(U);
- AbstractTypeUsersLock->release();
}
// is annihilated, because there is no way to get a reference to it ever again.
//
void Type::removeAbstractTypeUser(AbstractTypeUser *U) const {
- AbstractTypeUsersLock->acquire();
// Search from back to front because we will notify users from back to
// front. Also, it is likely that there will be a stack like behavior to
AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i);
#ifdef DEBUG_MERGE_TYPES
- DOUT << " remAbstractTypeUser[" << (void*)this << ", "
- << *this << "][" << i << "] User = " << U << "\n";
+ DEBUG(dbgs() << " remAbstractTypeUser[" << (void*)this << ", "
+ << *this << "][" << i << "] User = " << U << "\n");
#endif
if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) {
#ifdef DEBUG_MERGE_TYPES
- DOUT << "DELETEing unused abstract type: <" << *this
- << ">[" << (void*)this << "]" << "\n";
+ DEBUG(dbgs() << "DELETEing unused abstract type: <" << *this
+ << ">[" << (void*)this << "]" << "\n");
#endif
this->destroy();
}
- AbstractTypeUsersLock->release();
}
// unlockedRefineAbstractTypeTo - This function is used when it is discovered
assert(this != NewType && "Can't refine to myself!");
assert(ForwardType == 0 && "This type has already been refined!");
+ LLVMContextImpl *pImpl = getContext().pImpl;
+
// The descriptions may be out of date. Conservatively clear them all!
- if (AbstractTypeDescriptions.isConstructed())
- AbstractTypeDescriptions->clear();
+ pImpl->AbstractTypeDescriptions.clear();
#ifdef DEBUG_MERGE_TYPES
- DOUT << "REFINING abstract type [" << (void*)this << " "
- << *this << "] to [" << (void*)NewType << " "
- << *NewType << "]!\n";
+ DEBUG(dbgs() << "REFINING abstract type [" << (void*)this << " "
+ << *this << "] to [" << (void*)NewType << " "
+ << *NewType << "]!\n");
#endif
// Make sure to put the type to be refined to into a holder so that if IT gets
// refined, that we will not continue using a dead reference...
//
PATypeHolder NewTy(NewType);
- // Any PATypeHolders referring to this type will now automatically forward o
+ // Any PATypeHolders referring to this type will now automatically forward to
// the type we are resolved to.
ForwardType = NewType;
- if (NewType->isAbstract())
- cast<DerivedType>(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.
// will not cause users to drop off of the use list. If we resolve to ourself
// we succeed!
//
- AbstractTypeUsersLock->acquire();
while (!AbstractTypeUsers.empty() && NewTy != this) {
AbstractTypeUser *User = AbstractTypeUsers.back();
unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize;
#ifdef DEBUG_MERGE_TYPES
- DOUT << " REFINING user " << OldSize-1 << "[" << (void*)User
- << "] of abstract type [" << (void*)this << " "
- << *this << "] to [" << (void*)NewTy.get() << " "
- << *NewTy << "]!\n";
+ DEBUG(dbgs() << " REFINING user " << OldSize-1 << "[" << (void*)User
+ << "] of abstract type [" << (void*)this << " "
+ << *this << "] to [" << (void*)NewTy.get() << " "
+ << *NewTy << "]!\n");
#endif
User->refineAbstractType(this, NewTy);
assert(AbstractTypeUsers.size() != OldSize &&
"AbsTyUser did not remove self from user list!");
}
- AbstractTypeUsersLock->release();
// If we were successful removing all users from the type, 'this' will be
// deleted when the last PATypeHolder is destroyed or updated from this type.
void DerivedType::refineAbstractTypeTo(const Type *NewType) {
// All recursive calls will go through unlockedRefineAbstractTypeTo,
// to avoid deadlock problems.
- sys::SmartScopedLock<true> L(*TypeMapLock);
unlockedRefineAbstractTypeTo(NewType);
}
//
void DerivedType::notifyUsesThatTypeBecameConcrete() {
#ifdef DEBUG_MERGE_TYPES
- DOUT << "typeIsREFINED type: " << (void*)this << " " << *this << "\n";
+ DEBUG(dbgs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n");
#endif
- AbstractTypeUsersLock->acquire();
unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize;
while (!AbstractTypeUsers.empty()) {
AbstractTypeUser *ATU = AbstractTypeUsers.back();
assert(AbstractTypeUsers.size() < OldSize-- &&
"AbstractTypeUser did not remove itself from the use list!");
}
- AbstractTypeUsersLock->release();
}
// refineAbstractType - Called when a contained type is found to be more
pImpl->StructTypes.TypeBecameConcrete(this, AbsTy);
}
+// refineAbstractType - Called when a contained type is found to be more
+// concrete - this could potentially change us from an abstract type to a
+// concrete type.
+//
+void UnionType::refineAbstractType(const DerivedType *OldType,
+ const Type *NewType) {
+ LLVMContextImpl *pImpl = OldType->getContext().pImpl;
+ pImpl->UnionTypes.RefineAbstractType(this, OldType, NewType);
+}
+
+void UnionType::typeBecameConcrete(const DerivedType *AbsTy) {
+ LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
+ pImpl->UnionTypes.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.
}
bool SequentialType::indexValid(const Value *V) const {
- if (isa<IntegerType>(V->getType()))
+ if (V->getType()->isIntegerTy())
return true;
return false;
}
namespace llvm {
-std::ostream &operator<<(std::ostream &OS, const Type *T) {
- if (T == 0)
- OS << "<null> value!\n";
- else
- T->print(OS);
- return OS;
-}
-
-std::ostream &operator<<(std::ostream &OS, const Type &T) {
- T.print(OS);
- return OS;
-}
-
raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
T.print(OS);
return OS;