From 04890ad7fb448098249eb5caa28be870b9757a9b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 7 Sep 2001 23:00:03 +0000 Subject: [PATCH] New file for supporting abstract types git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@502 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/AbstractTypeUser.h | 134 ++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 include/llvm/AbstractTypeUser.h diff --git a/include/llvm/AbstractTypeUser.h b/include/llvm/AbstractTypeUser.h new file mode 100644 index 00000000000..24c061a3bb5 --- /dev/null +++ b/include/llvm/AbstractTypeUser.h @@ -0,0 +1,134 @@ +//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface -----*- C++ -*--=// +// +// The AbstractTypeUser class is an interface to be implemented by classes who +// could possible use an abstract type. Abstract types are denoted by the +// isAbstract flag set to true in the Type class. These are classes that +// contain an Opaque type in their structure somehow. +// +// Classes must implement this interface so that they may be notified when an +// abstract type is resolved. Abstract types may be resolved into more concrete +// types through: linking, parsing, and bytecode reading. When this happens, +// all of the users of the type must be updated to reference the new, more +// concrete type. They are notified through the AbstractTypeUser interface. +// +// In addition to this, AbstractTypeUsers must keep the use list of the +// potentially abstract type that they reference up-to-date. To do this in a +// nice, transparent way, the PATypeHandle class is used to hold "Potentially +// Abstract Types", and keep the use list of the abstract types up-to-date. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ABSTRACT_TYPE_USER_H +#define LLVM_ABSTRACT_TYPE_USER_H + +class Type; +class DerivedType; + +class AbstractTypeUser { +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. + // + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) = 0; +}; + + +// PATypeHandle - Handle to a Type subclass. This class is parameterized so +// that users can have handles to MethodType's that are still specialized, for +// example. This class is a simple class used to keep the use list of abstract +// types up-to-date. +// +template +class PATypeHandle { + const TypeSubClass *Ty; + AbstractTypeUser * const User; + + // These functions are defined at the bottom of Type.h. See the comment there + // for justification. + inline void addUser(); + inline void removeUser(); +public: + // ctor - Add use to type if abstract. Note that Ty must not be null + inline PATypeHandle(const TypeSubClass *ty, AbstractTypeUser *user) + : Ty(ty), User(user) { + addUser(); + } + + // ctor - Add use to type if abstract. + inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) { + addUser(); + } + + // dtor - Remove reference to type... + inline ~PATypeHandle() { removeUser(); } + + // Automatic casting operator so that the handle may be used naturally + inline operator const TypeSubClass *() const { return Ty; } + inline const TypeSubClass *get() const { return Ty; } + + // operator= - Allow assignment to handle + inline const TypeSubClass *operator=(const TypeSubClass *ty) { + if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty + removeUser(); + Ty = ty; + addUser(); + } + return Ty; + } + + // operator= - Allow assignment to handle + inline const TypeSubClass *operator=(const PATypeHandle &T) { + return operator=(T.Ty); + } + + inline bool operator==(const TypeSubClass *ty) { + return Ty == ty; + } + + // operator-> - Allow user to dereference handle naturally... + inline const TypeSubClass *operator->() const { return Ty; } +}; + + +// PATypeHolder - Holder class for a potentially abstract type. This functions +// as both a handle (as above) and an AbstractTypeUser. It uses the callback to +// keep its pointer member updated to the current version of the type. +// +template +class PATypeHolder : public AbstractTypeUser, public PATypeHandle { +public: + inline PATypeHolder(const TypeSC *ty) : PATypeHandle(ty, this) {} + inline PATypeHolder(const PATypeHolder &T) + : AbstractTypeUser(T), PATypeHandle(T, this) {} + + // refineAbstractType - All we do is update our PATypeHandle member to point + // to the new type. + // + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { + assert(get() == OldTy && "Can't refine to unknown value!"); + PATypeHandle::operator=((const TypeSC*)NewTy); + } + + // operator= - Allow assignment to handle + inline const TypeSC *operator=(const TypeSC *ty) { + return PATypeHandle::operator=(ty); + } + + // operator= - Allow assignment to handle + inline const TypeSC *operator=(const PATypeHandle &T) { + return PATypeHandle::operator=(T); + } + inline const TypeSC *operator=(const PATypeHolder &H) { + return PATypeHandle::operator=(H); + } +}; + + +#endif