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