1 //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Defines a registry template for discovering pluggable modules. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_REGISTRY_H 15 #define LLVM_SUPPORT_REGISTRY_H 16 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/Support/Compiler.h" 19 #include <memory> 20 21 namespace llvm { 22 /// A simple registry entry which provides only a name, description, and 23 /// no-argument constructor. 24 template <typename T> 25 class SimpleRegistryEntry { 26 const char *Name, *Desc; 27 std::unique_ptr<T> (*Ctor)(); 28 29 public: SimpleRegistryEntry(const char * N,const char * D,std::unique_ptr<T> (* C)())30 SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)()) 31 : Name(N), Desc(D), Ctor(C) 32 {} 33 getName()34 const char *getName() const { return Name; } getDesc()35 const char *getDesc() const { return Desc; } instantiate()36 std::unique_ptr<T> instantiate() const { return Ctor(); } 37 }; 38 39 40 /// Traits for registry entries. If using other than SimpleRegistryEntry, it 41 /// is necessary to define an alternate traits class. 42 template <typename T> 43 class RegistryTraits { 44 RegistryTraits() LLVM_DELETED_FUNCTION; 45 46 public: 47 typedef SimpleRegistryEntry<T> entry; 48 49 /// nameof/descof - Accessors for name and description of entries. These are 50 // used to generate help for command-line options. nameof(const entry & Entry)51 static const char *nameof(const entry &Entry) { return Entry.getName(); } descof(const entry & Entry)52 static const char *descof(const entry &Entry) { return Entry.getDesc(); } 53 }; 54 55 56 /// A global registry used in conjunction with static constructors to make 57 /// pluggable components (like targets or garbage collectors) "just work" when 58 /// linked with an executable. 59 template <typename T, typename U = RegistryTraits<T> > 60 class Registry { 61 public: 62 typedef U traits; 63 typedef typename U::entry entry; 64 65 class node; 66 class listener; 67 class iterator; 68 69 private: 70 Registry() LLVM_DELETED_FUNCTION; 71 Announce(const entry & E)72 static void Announce(const entry &E) { 73 for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) 74 Cur->registered(E); 75 } 76 77 friend class node; 78 static node *Head, *Tail; 79 80 friend class listener; 81 static listener *ListenerHead, *ListenerTail; 82 83 public: 84 /// Node in linked list of entries. 85 /// 86 class node { 87 friend class iterator; 88 89 node *Next; 90 const entry& Val; 91 92 public: node(const entry & V)93 node(const entry& V) : Next(nullptr), Val(V) { 94 if (Tail) 95 Tail->Next = this; 96 else 97 Head = this; 98 Tail = this; 99 100 Announce(V); 101 } 102 }; 103 104 105 /// Iterators for registry entries. 106 /// 107 class iterator { 108 const node *Cur; 109 110 public: iterator(const node * N)111 explicit iterator(const node *N) : Cur(N) {} 112 113 bool operator==(const iterator &That) const { return Cur == That.Cur; } 114 bool operator!=(const iterator &That) const { return Cur != That.Cur; } 115 iterator &operator++() { Cur = Cur->Next; return *this; } 116 const entry &operator*() const { return Cur->Val; } 117 const entry *operator->() const { return &Cur->Val; } 118 }; 119 begin()120 static iterator begin() { return iterator(Head); } end()121 static iterator end() { return iterator(nullptr); } 122 123 124 /// Abstract base class for registry listeners, which are informed when new 125 /// entries are added to the registry. Simply subclass and instantiate: 126 /// 127 /// \code 128 /// class CollectorPrinter : public Registry<Collector>::listener { 129 /// protected: 130 /// void registered(const Registry<Collector>::entry &e) { 131 /// cerr << "collector now available: " << e->getName() << "\n"; 132 /// } 133 /// 134 /// public: 135 /// CollectorPrinter() { init(); } // Print those already registered. 136 /// }; 137 /// 138 /// CollectorPrinter Printer; 139 /// \endcode 140 class listener { 141 listener *Prev, *Next; 142 143 friend void Registry::Announce(const entry &E); 144 145 protected: 146 /// Called when an entry is added to the registry. 147 /// 148 virtual void registered(const entry &) = 0; 149 150 /// Calls 'registered' for each pre-existing entry. 151 /// init()152 void init() { 153 for (iterator I = begin(), E = end(); I != E; ++I) 154 registered(*I); 155 } 156 157 public: listener()158 listener() : Prev(ListenerTail), Next(0) { 159 if (Prev) 160 Prev->Next = this; 161 else 162 ListenerHead = this; 163 ListenerTail = this; 164 } 165 ~listener()166 virtual ~listener() { 167 if (Next) 168 Next->Prev = Prev; 169 else 170 ListenerTail = Prev; 171 if (Prev) 172 Prev->Next = Next; 173 else 174 ListenerHead = Next; 175 } 176 }; 177 178 179 /// A static registration template. Use like such: 180 /// 181 /// Registry<Collector>::Add<FancyGC> 182 /// X("fancy-gc", "Newfangled garbage collector."); 183 /// 184 /// Use of this template requires that: 185 /// 186 /// 1. The registered subclass has a default constructor. 187 // 188 /// 2. The registry entry type has a constructor compatible with this 189 /// signature: 190 /// 191 /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); 192 /// 193 /// If you have more elaborate requirements, then copy and modify. 194 /// 195 template <typename V> 196 class Add { 197 entry Entry; 198 node Node; 199 CtorFn()200 static std::unique_ptr<T> CtorFn() { return make_unique<V>(); } 201 202 public: Add(const char * Name,const char * Desc)203 Add(const char *Name, const char *Desc) 204 : Entry(Name, Desc, CtorFn), Node(Entry) {} 205 }; 206 207 /// Registry::Parser now lives in llvm/Support/RegistryParser.h. 208 209 }; 210 211 // Since these are defined in a header file, plugins must be sure to export 212 // these symbols. 213 214 template <typename T, typename U> 215 typename Registry<T,U>::node *Registry<T,U>::Head; 216 217 template <typename T, typename U> 218 typename Registry<T,U>::node *Registry<T,U>::Tail; 219 220 template <typename T, typename U> 221 typename Registry<T,U>::listener *Registry<T,U>::ListenerHead; 222 223 template <typename T, typename U> 224 typename Registry<T,U>::listener *Registry<T,U>::ListenerTail; 225 226 } 227 228 #endif 229