13271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
23271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//
33271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//                     The LLVM Compiler Infrastructure
43271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//
584e66db653835cee524fc51185ed614f1d6ac628Chris Lattner// This file is distributed under the University of Illinois Open Source
684e66db653835cee524fc51185ed614f1d6ac628Chris Lattner// License. See LICENSE.TXT for details.
73271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//
83271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//===----------------------------------------------------------------------===//
93271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//
103271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen// Defines a registry template for discovering pluggable modules.
1126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov//
123271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen//===----------------------------------------------------------------------===//
133271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen
143271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen#ifndef LLVM_SUPPORT_REGISTRY_H
153271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen#define LLVM_SUPPORT_REGISTRY_H
163271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen
173271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksennamespace llvm {
183271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// A simple registry entry which provides only a name, description, and
193271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// no-argument constructor.
203271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  template <typename T>
213271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  class SimpleRegistryEntry {
223271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    const char *Name, *Desc;
233271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    T *(*Ctor)();
2426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
253271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  public:
263271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
273271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      : Name(N), Desc(D), Ctor(C)
283271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    {}
2926e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
303271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    const char *getName() const { return Name; }
313271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    const char *getDesc() const { return Desc; }
323271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    T *instantiate() const { return Ctor(); }
333271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  };
3426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
3526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
363271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// Traits for registry entries. If using other than SimpleRegistryEntry, it
373271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// is necessary to define an alternate traits class.
383271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  template <typename T>
393271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  class RegistryTraits {
403271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    RegistryTraits(); // Do not implement.
4126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
423271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  public:
433271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    typedef SimpleRegistryEntry<T> entry;
4426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
45f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen    /// nameof/descof - Accessors for name and description of entries. These are
46f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen    //                  used to generate help for command-line options.
473271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static const char *nameof(const entry &Entry) { return Entry.getName(); }
483271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static const char *descof(const entry &Entry) { return Entry.getDesc(); }
493271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  };
5026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
5126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
523271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// A global registry used in conjunction with static constructors to make
533271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// pluggable components (like targets or garbage collectors) "just work" when
543271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  /// linked with an executable.
553271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  template <typename T, typename U = RegistryTraits<T> >
563271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  class Registry {
573271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  public:
583271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    typedef U traits;
593271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    typedef typename U::entry entry;
6026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
613271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class node;
623271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class listener;
633271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class iterator;
6426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
653271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  private:
663271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    Registry(); // Do not implement.
6726e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
682e15f6698d461579ba92bde9d2286b72f33556b7Hartmut Kaiser    static void Announce(const entry &E) {
692e15f6698d461579ba92bde9d2286b72f33556b7Hartmut Kaiser      for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
702e15f6698d461579ba92bde9d2286b72f33556b7Hartmut Kaiser        Cur->registered(E);
712e15f6698d461579ba92bde9d2286b72f33556b7Hartmut Kaiser    }
7226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
733271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    friend class node;
743271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static node *Head, *Tail;
7526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
763271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    friend class listener;
773271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static listener *ListenerHead, *ListenerTail;
7826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
793271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  public:
803271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// Node in linked list of entries.
8126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
823271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class node {
833271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      friend class iterator;
8426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
853271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      node *Next;
863271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      const entry& Val;
8726e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
883271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    public:
893271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      node(const entry& V) : Next(0), Val(V) {
903271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        if (Tail)
913271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          Tail->Next = this;
923271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        else
933271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          Head = this;
943271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        Tail = this;
9526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
963271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        Announce(V);
973271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      }
983271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    };
9926e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
10026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1013271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// Iterators for registry entries.
10226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1033271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class iterator {
1043271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      const node *Cur;
10526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1063271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    public:
1073271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      explicit iterator(const node *N) : Cur(N) {}
10826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1093271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      bool operator==(const iterator &That) const { return Cur == That.Cur; }
1103271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      bool operator!=(const iterator &That) const { return Cur != That.Cur; }
1113271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      iterator &operator++() { Cur = Cur->Next; return *this; }
1123271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      const entry &operator*() const { return Cur->Val; }
1133271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      const entry *operator->() const { return &Cur->Val; }
1143271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    };
11526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1163271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static iterator begin() { return iterator(Head); }
1173271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    static iterator end()   { return iterator(0); }
11826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
11926e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1203271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// Abstract base class for registry listeners, which are informed when new
1213271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// entries are added to the registry. Simply subclass and instantiate:
12226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1233271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   class CollectorPrinter : public Registry<Collector>::listener {
1243271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   protected:
1253271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///     void registered(const Registry<Collector>::entry &e) {
1263271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///       cerr << "collector now available: " << e->getName() << "\n";
1273271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///     }
12826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1293271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   public:
1303271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///     CollectorPrinter() { init(); }  // Print those already registered.
1313271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   };
13226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1333271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   CollectorPrinter Printer;
13426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1353271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class listener {
1363271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      listener *Prev, *Next;
13726e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1383271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      friend void Registry::Announce(const entry &E);
13926e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1403271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    protected:
1413271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      /// Called when an entry is added to the registry.
14226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov      ///
1433271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      virtual void registered(const entry &) = 0;
14426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1453271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      /// Calls 'registered' for each pre-existing entry.
14626e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov      ///
1473271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      void init() {
1483271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        for (iterator I = begin(), E = end(); I != E; ++I)
1493271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          registered(*I);
1503271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      }
15126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1523271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    public:
1533271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      listener() : Prev(ListenerTail), Next(0) {
1543271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        if (Prev)
1553271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          Prev->Next = this;
1563271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        else
1573271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          ListenerHead = this;
1583271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        ListenerTail = this;
1593271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      }
16026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1613271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      virtual ~listener() {
1623271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        if (Next)
1633271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          Next->Prev = Prev;
1643271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        else
1653271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          ListenerTail = Prev;
1663271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        if (Prev)
1673271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          Prev->Next = Next;
1683271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        else
1693271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen          ListenerHead = Next;
1703271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      }
1713271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    };
17226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
17326e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1743271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// A static registration template. Use like such:
17526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1763271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   Registry<Collector>::Add<FancyGC>
1773271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///   X("fancy-gc", "Newfangled garbage collector.");
17826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1793271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// Use of this template requires that:
18026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1813271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///  1. The registered subclass has a default constructor.
18226e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    //
1833271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///  2. The registry entry type has a constructor compatible with this
1843271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///     signature:
18526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1863271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
18726e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1883271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    /// If you have more elaborate requirements, then copy and modify.
18926e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov    ///
1903271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    template <typename V>
1913271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    class Add {
1923271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      entry Entry;
1933271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      node Node;
19426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1953271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      static T *CtorFn() { return new V(); }
19626e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
1973271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    public:
1983271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen      Add(const char *Name, const char *Desc)
1993271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen        : Entry(Name, Desc, CtorFn), Node(Entry) {}
2003271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen    };
20126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
20261fc6c80cf9d50c19fe46decedc592251918d78dMikhail Glushenkov    /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
20326e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
2043271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen  };
20526e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
20604a4ec2f27c060cce3f285cf8f3e80f2fede5d80Dan Gohman  // Since these are defined in a header file, plugins must be sure to export
20704a4ec2f27c060cce3f285cf8f3e80f2fede5d80Dan Gohman  // these symbols.
20826e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
209f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  template <typename T, typename U>
210f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  typename Registry<T,U>::node *Registry<T,U>::Head;
21126e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
212f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  template <typename T, typename U>
213f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  typename Registry<T,U>::node *Registry<T,U>::Tail;
21426e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
215f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  template <typename T, typename U>
216f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
21726e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
218f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  template <typename T, typename U>
219f1bbd1f3e1067c0494af9527f06dc3da265930aeGordon Henriksen  typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
22026e9aed70cc520d39e32813513217163ff254e72Mikhail Glushenkov
2213271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen}
2223271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen
2233271e5aea340b1beb0953ce04cfc90791fc26dbfGordon Henriksen#endif
224