1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//                     The LLVM Compiler Infrastructure
4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file is distributed under the University of Illinois Open Source
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// License. See LICENSE.TXT for details.
7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Defines a registry template for discovering pluggable modules.
11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#ifndef LLVM_SUPPORT_REGISTRY_H
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#define LLVM_SUPPORT_REGISTRY_H
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace llvm {
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// A simple registry entry which provides only a name, description, and
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// no-argument constructor.
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T>
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class SimpleRegistryEntry {
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const char *Name, *Desc;
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    T *(*Ctor)();
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  public:
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      : Name(N), Desc(D), Ctor(C)
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    {}
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const char *getName() const { return Name; }
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const char *getDesc() const { return Desc; }
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    T *instantiate() const { return Ctor(); }
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  };
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// Traits for registry entries. If using other than SimpleRegistryEntry, it
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// is necessary to define an alternate traits class.
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T>
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class RegistryTraits {
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    RegistryTraits(); // Do not implement.
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  public:
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    typedef SimpleRegistryEntry<T> entry;
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// nameof/descof - Accessors for name and description of entries. These are
46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    //                  used to generate help for command-line options.
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static const char *nameof(const entry &Entry) { return Entry.getName(); }
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static const char *descof(const entry &Entry) { return Entry.getDesc(); }
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  };
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// A global registry used in conjunction with static constructors to make
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// pluggable components (like targets or garbage collectors) "just work" when
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /// linked with an executable.
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T, typename U = RegistryTraits<T> >
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class Registry {
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  public:
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    typedef U traits;
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    typedef typename U::entry entry;
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class node;
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class listener;
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class iterator;
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  private:
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Registry(); // Do not implement.
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static void Announce(const entry &E) {
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Cur->registered(E);
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    friend class node;
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static node *Head, *Tail;
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    friend class listener;
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static listener *ListenerHead, *ListenerTail;
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  public:
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Node in linked list of entries.
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class node {
83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      friend class iterator;
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      node *Next;
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const entry& Val;
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    public:
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      node(const entry& V) : Next(0), Val(V) {
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (Tail)
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Tail->Next = this;
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        else
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Head = this;
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Tail = this;
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Announce(V);
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Iterators for registry entries.
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class iterator {
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const node *Cur;
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    public:
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      explicit iterator(const node *N) : Cur(N) {}
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      bool operator==(const iterator &That) const { return Cur == That.Cur; }
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      bool operator!=(const iterator &That) const { return Cur != That.Cur; }
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      iterator &operator++() { Cur = Cur->Next; return *this; }
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const entry &operator*() const { return Cur->Val; }
113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const entry *operator->() const { return &Cur->Val; }
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static iterator begin() { return iterator(Head); }
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static iterator end()   { return iterator(0); }
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Abstract base class for registry listeners, which are informed when new
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// entries are added to the registry. Simply subclass and instantiate:
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   class CollectorPrinter : public Registry<Collector>::listener {
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   protected:
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///     void registered(const Registry<Collector>::entry &e) {
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///       cerr << "collector now available: " << e->getName() << "\n";
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///     }
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   public:
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///     CollectorPrinter() { init(); }  // Print those already registered.
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   };
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   CollectorPrinter Printer;
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class listener {
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      listener *Prev, *Next;
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      friend void Registry::Announce(const entry &E);
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    protected:
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      /// Called when an entry is added to the registry.
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ///
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      virtual void registered(const entry &) = 0;
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      /// Calls 'registered' for each pre-existing entry.
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ///
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      void init() {
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        for (iterator I = begin(), E = end(); I != E; ++I)
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          registered(*I);
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    public:
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      listener() : Prev(ListenerTail), Next(0) {
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (Prev)
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Prev->Next = this;
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        else
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          ListenerHead = this;
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ListenerTail = this;
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      virtual ~listener() {
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (Next)
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Next->Prev = Prev;
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        else
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          ListenerTail = Prev;
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (Prev)
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Prev->Next = Next;
168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        else
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          ListenerHead = Next;
170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// A static registration template. Use like such:
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   Registry<Collector>::Add<FancyGC>
177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///   X("fancy-gc", "Newfangled garbage collector.");
178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Use of this template requires that:
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///  1. The registered subclass has a default constructor.
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    //
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///  2. The registry entry type has a constructor compatible with this
184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///     signature:
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// If you have more elaborate requirements, then copy and modify.
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ///
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    template <typename V>
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    class Add {
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      entry Entry;
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      node Node;
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      static T *CtorFn() { return new V(); }
196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    public:
198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Add(const char *Name, const char *Desc)
199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        : Entry(Name, Desc, CtorFn), Node(Entry) {}
200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  };
205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Since these are defined in a header file, plugins must be sure to export
207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // these symbols.
208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T, typename U>
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  typename Registry<T,U>::node *Registry<T,U>::Head;
211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T, typename U>
213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  typename Registry<T,U>::node *Registry<T,U>::Tail;
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T, typename U>
216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  template <typename T, typename U>
219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
224