| //===-- Support/Annotation.h - Annotation classes ---------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file was developed by the LLVM research group and is distributed under |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the declarations for two classes: Annotation & Annotable. |
| // Using these two simple classes, anything that derives from Annotable can have |
| // Annotation subclasses attached to them, ready for easy retrieval. |
| // |
| // Annotations are designed to be easily attachable to various classes. |
| // |
| // The AnnotationManager class is essential for using these classes. It is |
| // responsible for turning Annotation name strings into tokens [unique id #'s] |
| // that may be used to search for and create annotations. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SUPPORT_ANNOTATION_H |
| #define SUPPORT_ANNOTATION_H |
| |
| #include <string> |
| #include <cassert> |
| |
| namespace llvm { |
| |
| class AnnotationID; |
| class Annotation; |
| class Annotable; |
| class AnnotationManager; |
| |
| //===----------------------------------------------------------------------===// |
| // |
| // AnnotationID - This class is a thin wrapper around an unsigned integer that |
| // is used to hopefully prevent errors using AnnotationID's. They may be copied |
| // freely around and passed byvalue with little or no overhead. |
| // |
| class AnnotationID { |
| friend class AnnotationManager; |
| unsigned ID; |
| |
| AnnotationID(); // Default ctor is disabled |
| inline AnnotationID(unsigned i) : ID(i) {} // Only creatable from AnnMgr |
| public: |
| inline AnnotationID(const AnnotationID &A) : ID(A.ID) {} |
| |
| inline bool operator==(const AnnotationID &A) const { |
| return A.ID == ID; |
| } |
| inline bool operator<(const AnnotationID &A) const { |
| return ID < A.ID; |
| } |
| }; |
| |
| |
| //===----------------------------------------------------------------------===// |
| // |
| // Annotation Class - This class serves as a base class for any specific |
| // annotations that you might need. Simply subclass this to add extra |
| // information to the annotations. |
| // |
| class Annotation { |
| friend class Annotable; // Annotable manipulates Next list |
| AnnotationID ID; // ID number, as obtained from AnnotationManager |
| Annotation *Next; // The next annotation in the linked list |
| public: |
| inline Annotation(AnnotationID id) : ID(id), Next(0) {} |
| virtual ~Annotation() {} // Designed to be subclassed |
| |
| // getID - Return the unique ID# of this annotation |
| inline AnnotationID getID() const { return ID; } |
| |
| // getNext - Return the next annotation in the list... |
| inline Annotation *getNext() const { return Next; } |
| }; |
| |
| |
| //===----------------------------------------------------------------------===// |
| // |
| // Annotable - This class is used as a base class for all objects that would |
| // like to have annotation capability. One notable subclass is Value, which |
| // means annotations can be attached to almost everything in LLVM. |
| // |
| // Annotable objects keep their annotation list sorted as annotations are |
| // inserted and deleted. This is used to ensure that annotations with identical |
| // ID#'s are stored sequentially. |
| // |
| class Annotable { |
| mutable Annotation *AnnotationList; |
| |
| Annotable(const Annotable &); // Do not implement |
| void operator=(const Annotable &); // Do not implement |
| public: |
| Annotable() : AnnotationList(0) {} |
| virtual ~Annotable() { // Virtual because it's designed to be subclassed... |
| Annotation *A = AnnotationList; |
| while (A) { |
| Annotation *Next = A->getNext(); |
| delete A; |
| A = Next; |
| } |
| } |
| |
| // getAnnotation - Search the list for annotations of the specified ID. The |
| // pointer returned is either null (if no annotations of the specified ID |
| // exist), or it points to the first element of a potentially list of elements |
| // with identical ID #'s. |
| // |
| Annotation *getAnnotation(AnnotationID ID) const { |
| for (Annotation *A = AnnotationList; A; A = A->getNext()) |
| if (A->getID() == ID) return A; |
| return 0; |
| } |
| |
| // getOrCreateAnnotation - Search through the annotation list, if there is |
| // no annotation with the specified ID, then use the AnnotationManager to |
| // create one. |
| // |
| inline Annotation *getOrCreateAnnotation(AnnotationID ID) const; |
| |
| // addAnnotation - Insert the annotation into the list in a sorted location. |
| // |
| void addAnnotation(Annotation *A) const { |
| assert(A->Next == 0 && "Annotation already in list?!?"); |
| |
| Annotation **AL = &AnnotationList; |
| while (*AL && (*AL)->ID < A->getID()) // Find where to insert annotation |
| AL = &((*AL)->Next); |
| A->Next = *AL; // Link the annotation in |
| *AL = A; |
| } |
| |
| // unlinkAnnotation - Remove the first annotation of the specified ID... and |
| // then return the unlinked annotation. The annotation object is not deleted. |
| // |
| inline Annotation *unlinkAnnotation(AnnotationID ID) const { |
| for (Annotation **A = &AnnotationList; *A; A = &((*A)->Next)) |
| if ((*A)->getID() == ID) { |
| Annotation *Ret = *A; |
| *A = Ret->Next; |
| Ret->Next = 0; |
| return Ret; |
| } |
| return 0; |
| } |
| |
| // deleteAnnotation - Delete the first annotation of the specified ID in the |
| // list. Unlink unlinkAnnotation, this actually deletes the annotation object |
| // |
| bool deleteAnnotation(AnnotationID ID) const { |
| Annotation *A = unlinkAnnotation(ID); |
| delete A; |
| return A != 0; |
| } |
| }; |
| |
| |
| //===----------------------------------------------------------------------===// |
| // |
| // AnnotationManager - This class is primarily responsible for maintaining a |
| // one-to-one mapping between string Annotation names and Annotation ID numbers. |
| // |
| // Compared to the rest of the Annotation system, these mapping methods are |
| // relatively slow, so they should be avoided by locally caching Annotation |
| // ID #'s. These methods are safe to call at any time, even by static ctors, so |
| // they should be used by static ctors most of the time. |
| // |
| // This class also provides support for annotations that are created on demand |
| // by the Annotable::getOrCreateAnnotation method. To get this to work, simply |
| // register an annotation handler |
| // |
| struct AnnotationManager { |
| typedef Annotation *(*Factory)(AnnotationID, const Annotable *, void*); |
| |
| //===--------------------------------------------------------------------===// |
| // Basic ID <-> Name map functionality |
| |
| static AnnotationID getID(const std::string &Name); // Name -> ID |
| static const std::string &getName(AnnotationID ID); // ID -> Name |
| |
| // getID - Name -> ID + registration of a factory function for demand driven |
| // annotation support. |
| static AnnotationID getID(const std::string &Name, Factory Fact, |
| void *Data = 0); |
| |
| //===--------------------------------------------------------------------===// |
| // Annotation creation on demand support... |
| |
| // registerAnnotationFactory - This method is used to register a callback |
| // function used to create an annotation on demand if it is needed by the |
| // Annotable::getOrCreateAnnotation method. |
| // |
| static void registerAnnotationFactory(AnnotationID ID, Factory Func, |
| void *ExtraData = 0); |
| |
| // createAnnotation - Create an annotation of the specified ID for the |
| // specified object, using a register annotation creation function. |
| // |
| static Annotation *createAnnotation(AnnotationID ID, const Annotable *Obj); |
| }; |
| |
| |
| |
| // getOrCreateAnnotation - Search through the annotation list, if there is |
| // no annotation with the specified ID, then use the AnnotationManager to |
| // create one. |
| // |
| inline Annotation *Annotable::getOrCreateAnnotation(AnnotationID ID) const { |
| Annotation *A = getAnnotation(ID); // Fast path, check for preexisting ann |
| if (A) return A; |
| |
| // No annotation found, ask the annotation manager to create an annotation... |
| A = AnnotationManager::createAnnotation(ID, this); |
| assert(A && "AnnotationManager could not create annotation!"); |
| addAnnotation(A); |
| return A; |
| } |
| |
| } // End namespace llvm |
| |
| #endif |