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