LLVM API Documentation
00001 //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Defines a registry template for discovering pluggable modules. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_SUPPORT_REGISTRY_H 00015 #define LLVM_SUPPORT_REGISTRY_H 00016 00017 #include "llvm/ADT/STLExtras.h" 00018 #include "llvm/Support/Compiler.h" 00019 00020 #include <memory> 00021 00022 namespace llvm { 00023 /// A simple registry entry which provides only a name, description, and 00024 /// no-argument constructor. 00025 template <typename T> 00026 class SimpleRegistryEntry { 00027 const char *Name, *Desc; 00028 std::unique_ptr<T> (*Ctor)(); 00029 00030 public: 00031 SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)()) 00032 : Name(N), Desc(D), Ctor(C) 00033 {} 00034 00035 const char *getName() const { return Name; } 00036 const char *getDesc() const { return Desc; } 00037 std::unique_ptr<T> instantiate() const { return Ctor(); } 00038 }; 00039 00040 00041 /// Traits for registry entries. If using other than SimpleRegistryEntry, it 00042 /// is necessary to define an alternate traits class. 00043 template <typename T> 00044 class RegistryTraits { 00045 RegistryTraits() LLVM_DELETED_FUNCTION; 00046 00047 public: 00048 typedef SimpleRegistryEntry<T> entry; 00049 00050 /// nameof/descof - Accessors for name and description of entries. These are 00051 // used to generate help for command-line options. 00052 static const char *nameof(const entry &Entry) { return Entry.getName(); } 00053 static const char *descof(const entry &Entry) { return Entry.getDesc(); } 00054 }; 00055 00056 00057 /// A global registry used in conjunction with static constructors to make 00058 /// pluggable components (like targets or garbage collectors) "just work" when 00059 /// linked with an executable. 00060 template <typename T, typename U = RegistryTraits<T> > 00061 class Registry { 00062 public: 00063 typedef U traits; 00064 typedef typename U::entry entry; 00065 00066 class node; 00067 class listener; 00068 class iterator; 00069 00070 private: 00071 Registry() LLVM_DELETED_FUNCTION; 00072 00073 static void Announce(const entry &E) { 00074 for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) 00075 Cur->registered(E); 00076 } 00077 00078 friend class node; 00079 static node *Head, *Tail; 00080 00081 friend class listener; 00082 static listener *ListenerHead, *ListenerTail; 00083 00084 public: 00085 /// Node in linked list of entries. 00086 /// 00087 class node { 00088 friend class iterator; 00089 00090 node *Next; 00091 const entry& Val; 00092 00093 public: 00094 node(const entry& V) : Next(nullptr), Val(V) { 00095 if (Tail) 00096 Tail->Next = this; 00097 else 00098 Head = this; 00099 Tail = this; 00100 00101 Announce(V); 00102 } 00103 }; 00104 00105 00106 /// Iterators for registry entries. 00107 /// 00108 class iterator { 00109 const node *Cur; 00110 00111 public: 00112 explicit iterator(const node *N) : Cur(N) {} 00113 00114 bool operator==(const iterator &That) const { return Cur == That.Cur; } 00115 bool operator!=(const iterator &That) const { return Cur != That.Cur; } 00116 iterator &operator++() { Cur = Cur->Next; return *this; } 00117 const entry &operator*() const { return Cur->Val; } 00118 const entry *operator->() const { return &Cur->Val; } 00119 }; 00120 00121 static iterator begin() { return iterator(Head); } 00122 static iterator end() { return iterator(nullptr); } 00123 00124 00125 /// Abstract base class for registry listeners, which are informed when new 00126 /// entries are added to the registry. Simply subclass and instantiate: 00127 /// 00128 /// \code 00129 /// class CollectorPrinter : public Registry<Collector>::listener { 00130 /// protected: 00131 /// void registered(const Registry<Collector>::entry &e) { 00132 /// cerr << "collector now available: " << e->getName() << "\n"; 00133 /// } 00134 /// 00135 /// public: 00136 /// CollectorPrinter() { init(); } // Print those already registered. 00137 /// }; 00138 /// 00139 /// CollectorPrinter Printer; 00140 /// \endcode 00141 class listener { 00142 listener *Prev, *Next; 00143 00144 friend void Registry::Announce(const entry &E); 00145 00146 protected: 00147 /// Called when an entry is added to the registry. 00148 /// 00149 virtual void registered(const entry &) = 0; 00150 00151 /// Calls 'registered' for each pre-existing entry. 00152 /// 00153 void init() { 00154 for (iterator I = begin(), E = end(); I != E; ++I) 00155 registered(*I); 00156 } 00157 00158 public: 00159 listener() : Prev(ListenerTail), Next(0) { 00160 if (Prev) 00161 Prev->Next = this; 00162 else 00163 ListenerHead = this; 00164 ListenerTail = this; 00165 } 00166 00167 virtual ~listener() { 00168 if (Next) 00169 Next->Prev = Prev; 00170 else 00171 ListenerTail = Prev; 00172 if (Prev) 00173 Prev->Next = Next; 00174 else 00175 ListenerHead = Next; 00176 } 00177 }; 00178 00179 00180 /// A static registration template. Use like such: 00181 /// 00182 /// Registry<Collector>::Add<FancyGC> 00183 /// X("fancy-gc", "Newfangled garbage collector."); 00184 /// 00185 /// Use of this template requires that: 00186 /// 00187 /// 1. The registered subclass has a default constructor. 00188 // 00189 /// 2. The registry entry type has a constructor compatible with this 00190 /// signature: 00191 /// 00192 /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); 00193 /// 00194 /// If you have more elaborate requirements, then copy and modify. 00195 /// 00196 template <typename V> 00197 class Add { 00198 entry Entry; 00199 node Node; 00200 00201 static std::unique_ptr<T> CtorFn() { return make_unique<V>(); } 00202 00203 public: 00204 Add(const char *Name, const char *Desc) 00205 : Entry(Name, Desc, CtorFn), Node(Entry) {} 00206 }; 00207 00208 /// Registry::Parser now lives in llvm/Support/RegistryParser.h. 00209 00210 }; 00211 00212 // Since these are defined in a header file, plugins must be sure to export 00213 // these symbols. 00214 00215 template <typename T, typename U> 00216 typename Registry<T,U>::node *Registry<T,U>::Head; 00217 00218 template <typename T, typename U> 00219 typename Registry<T,U>::node *Registry<T,U>::Tail; 00220 00221 template <typename T, typename U> 00222 typename Registry<T,U>::listener *Registry<T,U>::ListenerHead; 00223 00224 template <typename T, typename U> 00225 typename Registry<T,U>::listener *Registry<T,U>::ListenerTail; 00226 00227 } 00228 00229 #endif