diff --git a/llvm/include/llvm/AbstractTypeUser.h b/llvm/include/llvm/AbstractTypeUser.h index b9e5f1c6593a..e4096787f438 100644 --- a/llvm/include/llvm/AbstractTypeUser.h +++ b/llvm/include/llvm/AbstractTypeUser.h @@ -38,24 +38,20 @@ protected: virtual ~AbstractTypeUser() {} // Derive from me public: - // refineAbstractType - The callback method invoked when an abstract type - // has been found to be more concrete. A class must override this method to - // update its internal state to reference NewType instead of OldType. Soon - // after this method is invoked, OldType shall be deleted, so referencing it - // is quite unwise. - // - // Another case that is important to consider is when a type is refined, but - // stays in the same place in memory. In this case OldTy will equal NewTy. - // This callback just notifies ATU's that the underlying structure of the type - // has changed... but any previously used properties are still valid. - // - // Note that it is possible to refine a type with parameters OldTy==NewTy, and - // OldTy is no longer abstract. In this case, abstract type users should - // release their hold on a type, because it went from being abstract to - // concrete. - // + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) = 0; + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on it's + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0; + // for debugging... virtual void dump() const = 0; }; diff --git a/llvm/include/llvm/DerivedTypes.h b/llvm/include/llvm/DerivedTypes.h index 5ed30458fb8f..74ff96dfabf4 100644 --- a/llvm/include/llvm/DerivedTypes.h +++ b/llvm/include/llvm/DerivedTypes.h @@ -26,9 +26,6 @@ class DerivedType : public Type, public AbstractTypeUser { /// mutable unsigned RefCount; - // isRefining - Used for recursive types - char isRefining; - // AbstractTypeUsers - Implement a list of the users that need to be notified // if I am a type, and I get resolved into a more concrete type. // @@ -36,17 +33,17 @@ class DerivedType : public Type, public AbstractTypeUser { mutable std::vector AbstractTypeUsers; protected: - DerivedType(PrimitiveID id) : Type("", id), RefCount(0), isRefining(0) { + DerivedType(PrimitiveID id) : Type("", id), RefCount(0) { } ~DerivedType() { assert(AbstractTypeUsers.empty()); } - // typeIsRefined - Notify AbstractTypeUsers of this type that the current type - // has been refined a bit. The pointer is still valid and still should be - // used, but the subtypes have changed. - // - void typeIsRefined(); + /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type + /// that the current type has transitioned from being abstract to being + /// concrete. + /// + void notifyUsesThatTypeBecameConcrete(); // dropAllTypeUses - When this (abstract) type is resolved to be equal to // another (more concrete) type, we must eliminate all references to other @@ -146,6 +143,11 @@ protected: virtual void dropAllTypeUses(bool inMap); public: + /// FunctionType::get - This static method is the primary way of constructing + /// a FunctionType + static FunctionType *get(const Type *Result, + const std::vector &Params, + bool isVarArg); inline bool isVarArg() const { return isVarArgs; } inline const Type *getReturnType() const { return ResultType; } @@ -166,16 +168,10 @@ public: } virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; } - // 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. - // + // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); - - static FunctionType *get(const Type *Result, - const std::vector &Params, - bool isVarArg); - + virtual void typeBecameConcrete(const DerivedType *AbsTy); + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const FunctionType *T) { return true; } static inline bool classof(const Type *T) { @@ -244,6 +240,10 @@ protected: virtual void dropAllTypeUses(bool inMap); public: + /// StructType::get - This static method is the primary way to create a + /// StructType. + static StructType *get(const std::vector &Params); + inline const ElementTypes &getElementTypes() const { return ETypes; } virtual const Type *getContainedType(unsigned i) const { @@ -262,13 +262,9 @@ public: // virtual const Type *getIndexType() const { return Type::UByteTy; } - // 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. - // + // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); - - static StructType *get(const std::vector &Params); + virtual void typeBecameConcrete(const DerivedType *AbsTy); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const StructType *T) { return true; } @@ -353,15 +349,15 @@ protected: virtual void dropAllTypeUses(bool inMap); public: + /// ArrayType::get - This static method is the primary way to construct an + /// ArrayType + static ArrayType *get(const Type *ElementType, unsigned NumElements); + inline unsigned getNumElements() const { return NumElements; } - // 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. - // + // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); - - static ArrayType *get(const Type *ElementType, unsigned NumElements); + virtual void typeBecameConcrete(const DerivedType *AbsTy); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ArrayType *T) { return true; } @@ -393,16 +389,14 @@ protected: // type from the internal tables of available types. virtual void dropAllTypeUses(bool inMap); public: - // PointerType::get - Named constructor for pointer types... + /// PointerType::get - This is the only way to construct a new pointer type. static PointerType *get(const Type *ElementType); - // 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. - // + // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); - // Methods for support type inquiry through isa, cast, and dyn_cast: + // Implement support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const PointerType *T) { return true; } static inline bool classof(const Type *T) { return T->getPrimitiveID() == PointerTyID; @@ -430,23 +424,20 @@ protected: virtual void dropAllTypeUses(bool inMap) {} // No type uses public: - - // get - Static factory method for the OpaqueType class... + // OpaqueType::get - Static factory method for the OpaqueType class... static OpaqueType *get() { return new OpaqueType(); // All opaque types are distinct } - // 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. - // + // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - // This class never uses other types! - abort(); + abort(); // FIXME: this is not really an AbstractTypeUser! + } + virtual void typeBecameConcrete(const DerivedType *AbsTy) { + abort(); // FIXME: this is not really an AbstractTypeUser! } - - // Methods for support type inquiry through isa, cast, and dyn_cast: + // Implement support for type inquiry through isa, cast, and dyn_cast: static inline bool classof(const OpaqueType *T) { return true; } static inline bool classof(const Type *T) { return T->getPrimitiveID() == OpaqueTyID; diff --git a/llvm/include/llvm/SymbolTable.h b/llvm/include/llvm/SymbolTable.h index 30dc14fb7f91..7e1340206497 100644 --- a/llvm/include/llvm/SymbolTable.h +++ b/llvm/include/llvm/SymbolTable.h @@ -118,6 +118,7 @@ private: // This function is called when one of the types in the type plane are refined virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); }; #endif diff --git a/llvm/lib/VMCore/SymbolTable.cpp b/llvm/lib/VMCore/SymbolTable.cpp index bebc26c15df3..9def6cb5122c 100644 --- a/llvm/lib/VMCore/SymbolTable.cpp +++ b/llvm/lib/VMCore/SymbolTable.cpp @@ -195,7 +195,7 @@ void SymbolTable::refineAbstractType(const DerivedType *OldType, // Search to see if we have any values of the type oldtype. If so, we need to // move them into the newtype plane... iterator TPI = find(OldType); - if (OldType != NewType && TPI != end()) { + if (TPI != end()) { // Get a handle to the new type plane... iterator NewTypeIt = find(NewType); if (NewTypeIt == super::end()) { // If no plane exists, add one @@ -281,12 +281,6 @@ void SymbolTable::refineAbstractType(const DerivedType *OldType, // Remove the plane that is no longer used erase(TPI); - } else if (TPI != end()) { - assert(OldType == NewType); -#if DEBUG_ABSTYPE - std::cerr << "Removing SELF type " << OldType->getDescription() << "\n"; -#endif - OldType->removeAbstractTypeUser(this); } TPI = find(Type::TypeTy); @@ -315,6 +309,27 @@ void SymbolTable::refineAbstractType(const DerivedType *OldType, } } +void SymbolTable::typeBecameConcrete(const DerivedType *AbsTy) { + iterator TPI = find(AbsTy); + + // If there are any values in the symbol table of this type, then the type + // plan is a use of the abstract type which must be dropped. + if (TPI != end()) + AbsTy->removeAbstractTypeUser(this); + + TPI = find(Type::TypeTy); + if (TPI != end()) { + // Loop over all of the types in the symbol table, dropping any abstract + // type user entries for AbsTy which occur because there are names for the + // type. + // + VarMap &TyPlane = TPI->second; + for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) + if (I->second == (Value*)AbsTy) // FIXME when Types aren't const. + AbsTy->removeAbstractTypeUser(this); + } +} + static void DumpVal(const std::pair &V) { std::cout << " '" << V.first << "' = "; V.second->dump(); diff --git a/llvm/lib/VMCore/Type.cpp b/llvm/lib/VMCore/Type.cpp index dfd844e9847a..12b7d76f5007 100644 --- a/llvm/lib/VMCore/Type.cpp +++ b/llvm/lib/VMCore/Type.cpp @@ -498,8 +498,8 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2) { // our map if an abstract type gets refined somehow... // template -class TypeMap : public AbstractTypeUser { - typedef std::map MapTy; +class TypeMap { + typedef std::map MapTy; MapTy Map; public: typedef typename MapTy::iterator iterator; @@ -507,11 +507,11 @@ public: inline TypeClass *get(const ValType &V) { iterator I = Map.find(V); - return I != Map.end() ? (TypeClass*)I->second.get() : 0; + return I != Map.end() ? I->second : 0; } inline void add(const ValType &V, TypeClass *T) { - Map.insert(std::make_pair(V, PATypeHandle(T, this))); + Map.insert(std::make_pair(V, T)); print("add"); } @@ -519,57 +519,48 @@ public: iterator I = Map.find(ValType::get(Ty)); if (I == Map.end()) print("ERROR!"); assert(I != Map.end() && "Didn't find type entry!"); - assert(T->second == Ty && "Type entry wrong?"); + assert(I->second == Ty && "Type entry wrong?"); return I; } - void finishRefinement(TypeClass *Ty) { - //const TypeClass *Ty = (const TypeClass*)TyIt->second.get(); + void finishRefinement(TypeClass *Ty, iterator TyIt) { + // FIXME: this could eventually just pass in the iterator! + assert(TyIt->second == Ty && "Did not specify entry for the correct type!"); + + // The old record is now out-of-date, because one of the children has been + // updated. Remove the obsolete entry from the map. + Map.erase(TyIt); + + // 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. + // for (iterator I = Map.begin(), E = Map.end(); I != E; ++I) - if (I->second.get() != Ty && TypesEqual(Ty, I->second.get())) { + if (TypesEqual(Ty, I->second)) { assert(Ty->isAbstract() && "Replacing a non-abstract type?"); - TypeClass *NewTy = (TypeClass*)I->second.get(); -#if 0 - //Map.erase(TyIt); // The old entry is now dead! -#endif + TypeClass *NewTy = I->second; + // Refined to a different type altogether? Ty->refineAbstractTypeToInternal(NewTy, false); 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 type is currently thought to be abstract, rescan all of our // subtypes to see if the type has just become concrete! - if (Ty->isAbstract()) + if (Ty->isAbstract()) { Ty->setAbstract(Ty->isTypeAbstract()); - // This method may be called with either an abstract or a concrete type. - // Concrete types might get refined if a subelement type got refined which - // was previously marked as abstract, but was realized to be concrete. This - // can happen for recursive types. - Ty->typeIsRefined(); // Same type, different contents... + // If the type just became concrete, notify all users! + if (!Ty->isAbstract()) + Ty->notifyUsesThatTypeBecameConcrete(); + } } - - // refineAbstractType - This is called when one of the contained abstract - // types gets refined... this simply removes the abstract type from our table. - // We expect that whoever refined the type will add it back to the table, - // corrected. - // - virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { -#ifdef DEBUG_MERGE_TYPES - std::cerr << "Removing Old type from Tab: " << (void*)OldTy << ", " - << *OldTy << " replacement == " << (void*)NewTy - << ", " << *NewTy << "\n"; -#endif - for (iterator I = Map.begin(), E = Map.end(); I != E; ++I) - if (I->second.get() == OldTy) { - // Check to see if the type just became concrete. If so, remove self - // from user list. - I->second.removeUserFromConcrete(); - I->second = cast(NewTy); - } - } - + void remove(const ValType &OldVal) { iterator I = Map.find(OldVal); assert(I != Map.end() && "TypeMap::remove, element not found!"); @@ -587,8 +578,8 @@ public: unsigned i = 0; for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E; ++I) - std::cerr << " " << (++i) << ". " << (void*)I->second.get() << " " - << *I->second.get() << "\n"; + std::cerr << " " << (++i) << ". " << (void*)I->second << " " + << *I->second << "\n"; #endif } @@ -596,50 +587,6 @@ public: }; -// ValTypeBase - This is the base class that is used by the various -// instantiations of TypeMap. This class is an AbstractType user that notifies -// the underlying TypeMap when it gets modified. -// -template -class ValTypeBase : public AbstractTypeUser { - TypeMap &MyTable; -protected: - inline ValTypeBase(TypeMap &tab) : MyTable(tab) {} - - // Subclass should override this... to update self as usual - virtual void doRefinement(const DerivedType *OldTy, const Type *NewTy) = 0; - - // typeBecameConcrete - This callback occurs when a contained type refines - // to itself, but becomes concrete in the process. Our subclass should remove - // itself from the ATU list of the specified type. - // - virtual void typeBecameConcrete(const DerivedType *Ty) = 0; - - virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { - assert(OldTy == NewTy || OldTy->isAbstract()); - - if (!OldTy->isAbstract()) - typeBecameConcrete(OldTy); - - TypeMap &Table = MyTable; // Copy MyTable reference - ValType Tmp(*(ValType*)this); // Copy this. - PATypeHandle OldType(Table.get(*(ValType*)this), this); - Table.remove(*(ValType*)this); // Destroy's this! - - // Refine temporary to new state... - if (OldTy != NewTy) - Tmp.doRefinement(OldTy, NewTy); - - // FIXME: when types are not const! - Table.add((ValType&)Tmp, (TypeClass*)OldType.get()); - } - - void dump() const { - std::cerr << "ValTypeBase instance!\n"; - } -}; - - //===----------------------------------------------------------------------===// // Function Type Factory and Value Class... @@ -647,52 +594,42 @@ protected: // FunctionValType - Define a class to hold the key that goes into the TypeMap // -class FunctionValType : public ValTypeBase { - PATypeHandle RetTy; - std::vector ArgTypes; +class FunctionValType { + const Type *RetTy; + std::vector ArgTypes; bool isVarArg; public: FunctionValType(const Type *ret, const std::vector &args, - bool IVA, TypeMap &Tab) - : ValTypeBase(Tab), RetTy(ret, this), - isVarArg(IVA) { + bool IVA) : RetTy(ret), isVarArg(IVA) { for (unsigned i = 0; i < args.size(); ++i) - ArgTypes.push_back(PATypeHandle(args[i], this)); + ArgTypes.push_back(args[i]); } // We *MUST* have an explicit copy ctor so that the TypeHandles think that // this FunctionValType owns them, not the old one! // - FunctionValType(const FunctionValType &MVT) - : ValTypeBase(MVT), RetTy(MVT.RetTy, this), - isVarArg(MVT.isVarArg) { + FunctionValType(const FunctionValType &MVT) + : RetTy(MVT.RetTy), isVarArg(MVT.isVarArg) { ArgTypes.reserve(MVT.ArgTypes.size()); for (unsigned i = 0; i < MVT.ArgTypes.size(); ++i) - ArgTypes.push_back(PATypeHandle(MVT.ArgTypes[i], this)); + ArgTypes.push_back(MVT.ArgTypes[i]); } static FunctionValType get(const FunctionType *FT); // Subclass should override this... to update self as usual - virtual void doRefinement(const DerivedType *OldType, const Type *NewType) { + void doRefinement(const DerivedType *OldType, const Type *NewType) { if (RetTy == OldType) RetTy = NewType; for (unsigned i = 0, e = ArgTypes.size(); i != e; ++i) if (ArgTypes[i] == OldType) ArgTypes[i] = NewType; } - virtual void typeBecameConcrete(const DerivedType *Ty) { - if (RetTy == Ty) RetTy.removeUserFromConcrete(); - - for (unsigned i = 0; i < ArgTypes.size(); ++i) - if (ArgTypes[i] == Ty) ArgTypes[i].removeUserFromConcrete(); - } - inline bool operator<(const FunctionValType &MTV) const { - if (RetTy.get() < MTV.RetTy.get()) return true; - if (RetTy.get() > MTV.RetTy.get()) return false; + if (RetTy < MTV.RetTy) return true; + if (RetTy > MTV.RetTy) return false; if (ArgTypes < MTV.ArgTypes) return true; - return (ArgTypes == MTV.ArgTypes) && isVarArg < MTV.isVarArg; + return ArgTypes == MTV.ArgTypes && isVarArg < MTV.isVarArg; } }; @@ -705,8 +642,7 @@ FunctionValType FunctionValType::get(const FunctionType *FT) { ParamTypes.reserve(FT->getParamTypes().size()); for (unsigned i = 0, e = FT->getParamTypes().size(); i != e; ++i) ParamTypes.push_back(FT->getParamType(i)); - return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg(), - FunctionTypes); + return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg()); } @@ -714,7 +650,7 @@ FunctionValType FunctionValType::get(const FunctionType *FT) { FunctionType *FunctionType::get(const Type *ReturnType, const std::vector &Params, bool isVarArg) { - FunctionValType VT(ReturnType, Params, isVarArg, FunctionTypes); + FunctionValType VT(ReturnType, Params, isVarArg); FunctionType *MT = FunctionTypes.get(VT); if (MT) return MT; @@ -739,52 +675,40 @@ void FunctionType::dropAllTypeUses(bool inMap) { //===----------------------------------------------------------------------===// // Array Type Factory... // -class ArrayValType : public ValTypeBase { - PATypeHandle ValTy; +class ArrayValType { + const Type *ValTy; unsigned Size; public: - ArrayValType(const Type *val, int sz, TypeMap &Tab) - : ValTypeBase(Tab), ValTy(val, this), Size(sz) {} + ArrayValType(const Type *val, int sz) : ValTy(val), Size(sz) {} // We *MUST* have an explicit copy ctor so that the ValTy thinks that this // ArrayValType owns it, not the old one! // - ArrayValType(const ArrayValType &AVT) - : ValTypeBase(AVT), ValTy(AVT.ValTy, this), - Size(AVT.Size) {} - - static ArrayValType get(const ArrayType *AT); + ArrayValType(const ArrayValType &AVT) : ValTy(AVT.ValTy), Size(AVT.Size) {} + static ArrayValType get(const ArrayType *AT) { + return ArrayValType(AT->getElementType(), AT->getNumElements()); + } // Subclass should override this... to update self as usual - virtual void doRefinement(const DerivedType *OldType, const Type *NewType) { + void doRefinement(const DerivedType *OldType, const Type *NewType) { assert(ValTy == OldType); ValTy = NewType; } - virtual void typeBecameConcrete(const DerivedType *Ty) { - assert(ValTy == Ty && - "Contained type became concrete but we're not using it!"); - ValTy.removeUserFromConcrete(); - } - inline bool operator<(const ArrayValType &MTV) const { if (Size < MTV.Size) return true; - return Size == MTV.Size && ValTy.get() < MTV.ValTy.get(); + return Size == MTV.Size && ValTy < MTV.ValTy; } }; static TypeMap ArrayTypes; -ArrayValType ArrayValType::get(const ArrayType *AT) { - return ArrayValType(AT->getElementType(), AT->getNumElements(), ArrayTypes); -} - ArrayType *ArrayType::get(const Type *ElementType, unsigned NumElements) { assert(ElementType && "Can't get array of null types!"); - ArrayValType AVT(ElementType, NumElements, ArrayTypes); + ArrayValType AVT(ElementType, NumElements); ArrayType *AT = ArrayTypes.get(AVT); if (AT) return AT; // Found a match, return it! @@ -813,41 +737,29 @@ void ArrayType::dropAllTypeUses(bool inMap) { // StructValType - Define a class to hold the key that goes into the TypeMap // -class StructValType : public ValTypeBase { - std::vector ElTypes; +class StructValType { + std::vector ElTypes; public: - StructValType(const std::vector &args, - TypeMap &Tab) - : ValTypeBase(Tab) { - ElTypes.reserve(args.size()); - for (unsigned i = 0, e = args.size(); i != e; ++i) - ElTypes.push_back(PATypeHandle(args[i], this)); - } + StructValType(const std::vector &args) : ElTypes(args) {} - // We *MUST* have an explicit copy ctor so that the TypeHandles think that - // this StructValType owns them, not the old one! - // - StructValType(const StructValType &SVT) - : ValTypeBase(SVT){ - ElTypes.reserve(SVT.ElTypes.size()); - for (unsigned i = 0, e = SVT.ElTypes.size(); i != e; ++i) - ElTypes.push_back(PATypeHandle(SVT.ElTypes[i], this)); - } + // Explicit copy ctor not needed + StructValType(const StructValType &SVT) : ElTypes(SVT.ElTypes) {} - static StructValType get(const StructType *ST); + static StructValType get(const StructType *ST) { + std::vector ElTypes; + ElTypes.reserve(ST->getElementTypes().size()); + for (unsigned i = 0, e = ST->getElementTypes().size(); i != e; ++i) + ElTypes.push_back(ST->getElementTypes()[i]); + + return StructValType(ElTypes); + } // Subclass should override this... to update self as usual - virtual void doRefinement(const DerivedType *OldType, const Type *NewType) { + void doRefinement(const DerivedType *OldType, const Type *NewType) { for (unsigned i = 0; i < ElTypes.size(); ++i) if (ElTypes[i] == OldType) ElTypes[i] = NewType; } - virtual void typeBecameConcrete(const DerivedType *Ty) { - for (unsigned i = 0, e = ElTypes.size(); i != e; ++i) - if (ElTypes[i] == Ty) - ElTypes[i].removeUserFromConcrete(); - } - inline bool operator<(const StructValType &STV) const { return ElTypes < STV.ElTypes; } @@ -855,19 +767,8 @@ public: static TypeMap StructTypes; -StructValType StructValType::get(const StructType *ST) { - std::vector ElTypes; - ElTypes.reserve(ST->getElementTypes().size()); - for (unsigned i = 0, e = ST->getElementTypes().size(); i != e; ++i) - ElTypes.push_back(ST->getElementTypes()[i]); - - return StructValType(ElTypes, StructTypes); -} - - - StructType *StructType::get(const std::vector &ETypes) { - StructValType STV(ETypes, StructTypes); + StructValType STV(ETypes); StructType *ST = StructTypes.get(STV); if (ST) return ST; @@ -896,47 +797,34 @@ void StructType::dropAllTypeUses(bool inMap) { // PointerValType - Define a class to hold the key that goes into the TypeMap // -class PointerValType : public ValTypeBase { - PATypeHandle ValTy; +class PointerValType { + const Type *ValTy; public: - PointerValType(const Type *val, TypeMap &Tab) - : ValTypeBase(Tab), ValTy(val, this) {} + PointerValType(const Type *val) : ValTy(val) {} - // We *MUST* have an explicit copy ctor so that the ValTy thinks that this - // PointerValType owns it, not the old one! - // - PointerValType(const PointerValType &PVT) - : ValTypeBase(PVT), ValTy(PVT.ValTy, this) {} + // FIXME: delete explicit copy ctor + PointerValType(const PointerValType &PVT) : ValTy(PVT.ValTy) {} - static PointerValType get(const PointerType *PT); + static PointerValType get(const PointerType *PT) { + return PointerValType(PT->getElementType()); + } // Subclass should override this... to update self as usual - virtual void doRefinement(const DerivedType *OldType, const Type *NewType) { + void doRefinement(const DerivedType *OldType, const Type *NewType) { assert(ValTy == OldType); ValTy = NewType; } - virtual void typeBecameConcrete(const DerivedType *Ty) { - assert(ValTy == Ty && - "Contained type became concrete but we're not using it!"); - ValTy.removeUserFromConcrete(); - } - - inline bool operator<(const PointerValType &MTV) const { - return ValTy.get() < MTV.ValTy.get(); + bool operator<(const PointerValType &MTV) const { + return ValTy < MTV.ValTy; } }; static TypeMap PointerTypes; -PointerValType PointerValType::get(const PointerType *PT) { - return PointerValType(PT->getElementType(), PointerTypes); -} - - PointerType *PointerType::get(const Type *ValueType) { assert(ValueType && "Can't get a pointer to type!"); - PointerValType PVT(ValueType, PointerTypes); + PointerValType PVT(ValueType); PointerType *PT = PointerTypes.get(PVT); if (PT) return PT; @@ -1011,7 +899,8 @@ void DerivedType::removeAbstractTypeUser(AbstractTypeUser *U) const { void DerivedType::refineAbstractTypeToInternal(const Type *NewType, bool inMap){ 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!"); + // The descriptions may be out of date. Conservatively clear them all! AbstractTypeDescriptions.clear(); @@ -1021,12 +910,13 @@ void DerivedType::refineAbstractTypeToInternal(const Type *NewType, bool inMap){ << *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 (NewType->isAbstract()) cast(NewType)->addRef(); @@ -1060,18 +950,6 @@ void DerivedType::refineAbstractTypeToInternal(const Type *NewType, bool inMap){ #endif User->refineAbstractType(this, NewTy); -#ifdef DEBUG_MERGE_TYPES - if (AbstractTypeUsers.size() == OldSize) { - User->refineAbstractType(this, NewTy); - if (AbstractTypeUsers.back() != User) - std::cerr << "User changed!\n"; - std::cerr << "Top of user list is:\n"; - AbstractTypeUsers.back()->dump(); - - std::cerr <<"\nOld User=\n"; - User->dump(); - } -#endif assert(AbstractTypeUsers.size() != OldSize && "AbsTyUser did not remove self from user list!"); } @@ -1082,69 +960,22 @@ void DerivedType::refineAbstractTypeToInternal(const Type *NewType, bool inMap){ // destroyed. } -// typeIsRefined - Notify AbstractTypeUsers of this type that the current type -// has been refined a bit. The pointer is still valid and still should be -// used, but the subtypes have changed. +// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type that +// the current type has transitioned from being abstract to being concrete. // -void DerivedType::typeIsRefined() { - assert(isRefining >= 0 && isRefining <= 2 && "isRefining out of bounds!"); - if (isRefining == 1) return; // Kill recursion here... - ++isRefining; - +void DerivedType::notifyUsesThatTypeBecameConcrete() { #ifdef DEBUG_MERGE_TYPES std::cerr << "typeIsREFINED type: " << (void*)this << " " << *this << "\n"; #endif - // In this loop we have to be very careful not to get into infinite loops and - // other problem cases. Specifically, we loop through all of the abstract - // type users in the user list, notifying them that the type has been refined. - // At their choice, they may or may not choose to remove themselves from the - // list of users. Regardless of whether they do or not, we have to be sure - // that we only notify each user exactly once. Because the refineAbstractType - // method can cause an arbitrary permutation to the user list, we cannot loop - // through it in any particular order and be guaranteed that we will be - // successful at this aim. Because of this, we keep track of all the users we - // have visited and only visit users we have not seen. Because this user list - // should be small, we use a vector instead of a full featured set to keep - // track of what users we have notified so far. - // - std::vector Refined; - while (1) { - unsigned i; - for (i = AbstractTypeUsers.size(); i != 0; --i) - if (find(Refined.begin(), Refined.end(), AbstractTypeUsers[i-1]) == - Refined.end()) - break; // Found an unrefined user? - - if (i == 0) break; // Noone to refine left, break out of here! + unsigned OldSize = AbstractTypeUsers.size(); + while (!AbstractTypeUsers.empty()) { + AbstractTypeUser *ATU = AbstractTypeUsers.back(); + ATU->typeBecameConcrete(this); - AbstractTypeUser *ATU = AbstractTypeUsers[--i]; - Refined.push_back(ATU); // Keep track of which users we have refined! - -#ifdef DEBUG_MERGE_TYPES - std::cerr << " typeIsREFINED user " << i << "[" << ATU - << "] of abstract type [" << (void*)this << " " - << *this << "]\n"; -#endif - ATU->refineAbstractType(this, this); + assert(AbstractTypeUsers.size() < OldSize-- && + "AbstractTypeUser did not remove itself from the use list!"); } - - --isRefining; - -#ifndef _NDEBUG - if (!(isAbstract() || AbstractTypeUsers.empty())) - for (unsigned i = 0; i < AbstractTypeUsers.size(); ++i) { - if (AbstractTypeUsers[i] != this) { - // Debugging hook - std::cerr << "FOUND FAILURE\nUser: "; - AbstractTypeUsers[i]->dump(); - std::cerr << "\nCatch:\n"; - AbstractTypeUsers[i]->refineAbstractType(this, this); - assert(0 && "Type became concrete," - " but it still has abstract type users hanging around!"); - } - } -#endif } @@ -1165,10 +996,8 @@ void FunctionType::refineAbstractType(const DerivedType *OldType, #endif // Look up our current type map entry.. -#if 0 TypeMap::iterator TMI = FunctionTypes.getEntryForType(this); -#endif // Find the type element we are refining... if (ResultType == OldType) { @@ -1181,7 +1010,11 @@ void FunctionType::refineAbstractType(const DerivedType *OldType, ParamTys[i] = NewType; } - FunctionTypes.finishRefinement(this); + FunctionTypes.finishRefinement(this, TMI); +} + +void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) { + refineAbstractType(AbsTy, AbsTy); } @@ -1199,17 +1032,19 @@ void ArrayType::refineAbstractType(const DerivedType *OldType, << *NewType << "])\n"; #endif -#if 0 // Look up our current type map entry.. TypeMap::iterator TMI = ArrayTypes.getEntryForType(this); -#endif assert(getElementType() == OldType); ElementType.removeUserFromConcrete(); ElementType = NewType; - ArrayTypes.finishRefinement(this); + ArrayTypes.finishRefinement(this, TMI); +} + +void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) { + refineAbstractType(AbsTy, AbsTy); } @@ -1227,11 +1062,9 @@ void StructType::refineAbstractType(const DerivedType *OldType, << *NewType << "])\n"; #endif -#if 0 // Look up our current type map entry.. TypeMap::iterator TMI = StructTypes.getEntryForType(this); -#endif for (int i = ETypes.size()-1; i >= 0; --i) if (ETypes[i] == OldType) { @@ -1241,7 +1074,11 @@ void StructType::refineAbstractType(const DerivedType *OldType, ETypes[i] = NewType; } - StructTypes.finishRefinement(this); + StructTypes.finishRefinement(this, TMI); +} + +void StructType::typeBecameConcrete(const DerivedType *AbsTy) { + refineAbstractType(AbsTy, AbsTy); } // refineAbstractType - Called when a contained type is found to be more @@ -1258,16 +1095,18 @@ void PointerType::refineAbstractType(const DerivedType *OldType, << *NewType << "])\n"; #endif -#if 0 // Look up our current type map entry.. TypeMap::iterator TMI = PointerTypes.getEntryForType(this); -#endif assert(ElementType == OldType); ElementType.removeUserFromConcrete(); ElementType = NewType; - PointerTypes.finishRefinement(this); + PointerTypes.finishRefinement(this, TMI); +} + +void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { + refineAbstractType(AbsTy, AbsTy); }