+
+// 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 ValType, class TypeClass>
+class ValTypeBase : public AbstractTypeUser {
+ TypeMap<ValType, TypeClass> &MyTable;
+protected:
+ inline ValTypeBase(TypeMap<ValType, TypeClass> &tab) : MyTable(tab) {}
+
+ // Subclass should override this... to update self as usual
+ virtual void doRefinement(const DerivedType *OldTy, const Type *NewTy) = 0;
+
+ virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
+ if (OldTy == NewTy) return;
+ TypeMap<ValType, TypeClass> &Table = MyTable; // Copy MyTable reference
+ ValType Tmp(*(ValType*)this); // Copy this.
+ PATypeHandle<TypeClass> OldType(Table.get(*(ValType*)this), this);
+ Table.remove(*(ValType*)this); // Destroy's this!
+
+ // Refine temporary to new state...
+ Tmp.doRefinement(OldTy, NewTy);
+
+ Table.add((ValType&)Tmp, (TypeClass*)OldType.get());
+ }
+};
+
+
+
+//===----------------------------------------------------------------------===//
+// Method Type Factory and Value Class...
+//
+
+// MethodValType - Define a class to hold the key that goes into the TypeMap
+//
+class MethodValType : public ValTypeBase<MethodValType, MethodType> {
+ PATypeHandle<Type> RetTy;
+ vector<PATypeHandle<Type> > ArgTypes;
+ bool isVarArg;
+public:
+ MethodValType(const Type *ret, const vector<const Type*> &args,
+ bool IVA, TypeMap<MethodValType, MethodType> &Tab)
+ : ValTypeBase<MethodValType, MethodType>(Tab), RetTy(ret, this),
+ isVarArg(IVA) {
+ for (unsigned i = 0; i < args.size(); ++i)
+ ArgTypes.push_back(PATypeHandle<Type>(args[i], this));
+ }
+
+ // We *MUST* have an explicit copy ctor so that the TypeHandles think that
+ // this MethodValType owns them, not the old one!
+ //
+ MethodValType(const MethodValType &MVT)
+ : ValTypeBase<MethodValType, MethodType>(MVT), RetTy(MVT.RetTy, this),
+ isVarArg(MVT.isVarArg) {
+ ArgTypes.reserve(MVT.ArgTypes.size());
+ for (unsigned i = 0; i < MVT.ArgTypes.size(); ++i)
+ ArgTypes.push_back(PATypeHandle<Type>(MVT.ArgTypes[i], this));
+ }
+
+ // Subclass should override this... to update self as usual
+ virtual void doRefinement(const DerivedType *OldType, const Type *NewType) {
+ if (RetTy == OldType) RetTy = NewType;
+ for (unsigned i = 0; i < ArgTypes.size(); ++i)
+ if (ArgTypes[i] == OldType) ArgTypes[i] = NewType;
+ }
+
+ inline bool operator<(const MethodValType &MTV) const {
+ if (RetTy.get() < MTV.RetTy.get()) return true;
+ if (RetTy.get() > MTV.RetTy.get()) return false;
+
+ if (ArgTypes < MTV.ArgTypes) return true;
+ return (ArgTypes == MTV.ArgTypes) && isVarArg < MTV.isVarArg;
+ }
+};
+
+// Define the actual map itself now...
+static TypeMap<MethodValType, MethodType> MethodTypes;
+
+// MethodType::get - The factory function for the MethodType class...
+MethodType *MethodType::get(const Type *ReturnType,
+ const vector<const Type*> &Params,
+ bool isVarArg) {
+ MethodValType VT(ReturnType, Params, isVarArg, MethodTypes);
+ MethodType *MT = MethodTypes.get(VT);
+ if (MT) return MT;
+
+ MethodTypes.add(VT, MT = new MethodType(ReturnType, Params, isVarArg));
+
+#ifdef DEBUG_MERGE_TYPES
+ cerr << "Derived new type: " << MT << endl;
+#endif
+ return MT;