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