| //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Defines a registry template for discovering pluggable modules. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_SUPPORT_REGISTRY_H | |
| #define LLVM_SUPPORT_REGISTRY_H | |
| namespace llvm { | |
| /// A simple registry entry which provides only a name, description, and | |
| /// no-argument constructor. | |
| template <typename T> | |
| class SimpleRegistryEntry { | |
| const char *Name, *Desc; | |
| T *(*Ctor)(); | |
| public: | |
| SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) | |
| : Name(N), Desc(D), Ctor(C) | |
| {} | |
| const char *getName() const { return Name; } | |
| const char *getDesc() const { return Desc; } | |
| T *instantiate() const { return Ctor(); } | |
| }; | |
| /// Traits for registry entries. If using other than SimpleRegistryEntry, it | |
| /// is necessary to define an alternate traits class. | |
| template <typename T> | |
| class RegistryTraits { | |
| RegistryTraits(); // Do not implement. | |
| public: | |
| typedef SimpleRegistryEntry<T> entry; | |
| /// nameof/descof - Accessors for name and description of entries. These are | |
| // used to generate help for command-line options. | |
| static const char *nameof(const entry &Entry) { return Entry.getName(); } | |
| static const char *descof(const entry &Entry) { return Entry.getDesc(); } | |
| }; | |
| /// A global registry used in conjunction with static constructors to make | |
| /// pluggable components (like targets or garbage collectors) "just work" when | |
| /// linked with an executable. | |
| template <typename T, typename U = RegistryTraits<T> > | |
| class Registry { | |
| public: | |
| typedef U traits; | |
| typedef typename U::entry entry; | |
| class node; | |
| class listener; | |
| class iterator; | |
| private: | |
| Registry(); // Do not implement. | |
| static void Announce(const entry &E) { | |
| for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) | |
| Cur->registered(E); | |
| } | |
| friend class node; | |
| static node *Head, *Tail; | |
| friend class listener; | |
| static listener *ListenerHead, *ListenerTail; | |
| public: | |
| /// Node in linked list of entries. | |
| /// | |
| class node { | |
| friend class iterator; | |
| node *Next; | |
| const entry& Val; | |
| public: | |
| node(const entry& V) : Next(0), Val(V) { | |
| if (Tail) | |
| Tail->Next = this; | |
| else | |
| Head = this; | |
| Tail = this; | |
| Announce(V); | |
| } | |
| }; | |
| /// Iterators for registry entries. | |
| /// | |
| class iterator { | |
| const node *Cur; | |
| public: | |
| explicit iterator(const node *N) : Cur(N) {} | |
| bool operator==(const iterator &That) const { return Cur == That.Cur; } | |
| bool operator!=(const iterator &That) const { return Cur != That.Cur; } | |
| iterator &operator++() { Cur = Cur->Next; return *this; } | |
| const entry &operator*() const { return Cur->Val; } | |
| const entry *operator->() const { return &Cur->Val; } | |
| }; | |
| static iterator begin() { return iterator(Head); } | |
| static iterator end() { return iterator(0); } | |
| /// Abstract base class for registry listeners, which are informed when new | |
| /// entries are added to the registry. Simply subclass and instantiate: | |
| /// | |
| /// class CollectorPrinter : public Registry<Collector>::listener { | |
| /// protected: | |
| /// void registered(const Registry<Collector>::entry &e) { | |
| /// cerr << "collector now available: " << e->getName() << "\n"; | |
| /// } | |
| /// | |
| /// public: | |
| /// CollectorPrinter() { init(); } // Print those already registered. | |
| /// }; | |
| /// | |
| /// CollectorPrinter Printer; | |
| /// | |
| class listener { | |
| listener *Prev, *Next; | |
| friend void Registry::Announce(const entry &E); | |
| protected: | |
| /// Called when an entry is added to the registry. | |
| /// | |
| virtual void registered(const entry &) = 0; | |
| /// Calls 'registered' for each pre-existing entry. | |
| /// | |
| void init() { | |
| for (iterator I = begin(), E = end(); I != E; ++I) | |
| registered(*I); | |
| } | |
| public: | |
| listener() : Prev(ListenerTail), Next(0) { | |
| if (Prev) | |
| Prev->Next = this; | |
| else | |
| ListenerHead = this; | |
| ListenerTail = this; | |
| } | |
| virtual ~listener() { | |
| if (Next) | |
| Next->Prev = Prev; | |
| else | |
| ListenerTail = Prev; | |
| if (Prev) | |
| Prev->Next = Next; | |
| else | |
| ListenerHead = Next; | |
| } | |
| }; | |
| /// A static registration template. Use like such: | |
| /// | |
| /// Registry<Collector>::Add<FancyGC> | |
| /// X("fancy-gc", "Newfangled garbage collector."); | |
| /// | |
| /// Use of this template requires that: | |
| /// | |
| /// 1. The registered subclass has a default constructor. | |
| // | |
| /// 2. The registry entry type has a constructor compatible with this | |
| /// signature: | |
| /// | |
| /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); | |
| /// | |
| /// If you have more elaborate requirements, then copy and modify. | |
| /// | |
| template <typename V> | |
| class Add { | |
| entry Entry; | |
| node Node; | |
| static T *CtorFn() { return new V(); } | |
| public: | |
| Add(const char *Name, const char *Desc) | |
| : Entry(Name, Desc, CtorFn), Node(Entry) {} | |
| }; | |
| /// Registry::Parser now lives in llvm/Support/RegistryParser.h. | |
| }; | |
| // Since these are defined in a header file, plugins must be sure to export | |
| // these symbols. | |
| template <typename T, typename U> | |
| typename Registry<T,U>::node *Registry<T,U>::Head; | |
| template <typename T, typename U> | |
| typename Registry<T,U>::node *Registry<T,U>::Tail; | |
| template <typename T, typename U> | |
| typename Registry<T,U>::listener *Registry<T,U>::ListenerHead; | |
| template <typename T, typename U> | |
| typename Registry<T,U>::listener *Registry<T,U>::ListenerTail; | |
| } | |
| #endif |