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