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/ADT/iterator_range.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/DynamicLibrary.h" 21 #include <memory> 22 23 namespace llvm { 24 /// A simple registry entry which provides only a name, description, and 25 /// no-argument constructor. 26 template <typename T> 27 class SimpleRegistryEntry { 28 const char *Name, *Desc; 29 std::unique_ptr<T> (*Ctor)(); 30 31 public: SimpleRegistryEntry(const char * N,const char * D,std::unique_ptr<T> (* C)())32 SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)()) 33 : Name(N), Desc(D), Ctor(C) 34 {} 35 getName()36 const char *getName() const { return Name; } getDesc()37 const char *getDesc() const { return Desc; } instantiate()38 std::unique_ptr<T> instantiate() const { return Ctor(); } 39 }; 40 41 /// A global registry used in conjunction with static constructors to make 42 /// pluggable components (like targets or garbage collectors) "just work" when 43 /// linked with an executable. 44 template <typename T> 45 class Registry { 46 public: 47 typedef SimpleRegistryEntry<T> entry; 48 49 class node; 50 class iterator; 51 52 private: 53 Registry() = delete; 54 55 friend class node; 56 static node *Head, *Tail; 57 58 public: 59 /// Node in linked list of entries. 60 /// 61 class node { 62 friend class iterator; 63 friend Registry<T>; 64 65 node *Next; 66 const entry& Val; 67 68 public: node(const entry & V)69 node(const entry &V) : Next(nullptr), Val(V) {} 70 }; 71 add_node(node * N)72 static void add_node(node *N) { 73 if (Tail) 74 Tail->Next = N; 75 else 76 Head = N; 77 Tail = N; 78 } 79 80 /// Iterators for registry entries. 81 /// 82 class iterator { 83 const node *Cur; 84 85 public: iterator(const node * N)86 explicit iterator(const node *N) : Cur(N) {} 87 88 bool operator==(const iterator &That) const { return Cur == That.Cur; } 89 bool operator!=(const iterator &That) const { return Cur != That.Cur; } 90 iterator &operator++() { Cur = Cur->Next; return *this; } 91 const entry &operator*() const { return Cur->Val; } 92 const entry *operator->() const { return &Cur->Val; } 93 }; 94 begin()95 static iterator begin() { return iterator(Head); } end()96 static iterator end() { return iterator(nullptr); } 97 entries()98 static iterator_range<iterator> entries() { 99 return make_range(begin(), end()); 100 } 101 102 /// A static registration template. Use like such: 103 /// 104 /// Registry<Collector>::Add<FancyGC> 105 /// X("fancy-gc", "Newfangled garbage collector."); 106 /// 107 /// Use of this template requires that: 108 /// 109 /// 1. The registered subclass has a default constructor. 110 template <typename V> 111 class Add { 112 entry Entry; 113 node Node; 114 CtorFn()115 static std::unique_ptr<T> CtorFn() { return make_unique<V>(); } 116 117 public: Add(const char * Name,const char * Desc)118 Add(const char *Name, const char *Desc) 119 : Entry(Name, Desc, CtorFn), Node(Entry) { 120 add_node(&Node); 121 } 122 }; 123 124 /// A dynamic import facility. This is used on Windows to 125 /// import the entries added in the plugin. import(sys::DynamicLibrary & DL,const char * RegistryName)126 static void import(sys::DynamicLibrary &DL, const char *RegistryName) { 127 typedef void *(*GetRegistry)(); 128 std::string Name("LLVMGetRegistry_"); 129 Name.append(RegistryName); 130 GetRegistry Getter = 131 (GetRegistry)(intptr_t)DL.getAddressOfSymbol(Name.c_str()); 132 if (Getter) { 133 // Call the getter function in order to get the full copy of the 134 // registry defined in the plugin DLL, and copy them over to the 135 // current Registry. 136 typedef std::pair<const node *, const node *> Info; 137 Info *I = static_cast<Info *>(Getter()); 138 iterator begin(I->first); 139 iterator end(I->second); 140 for (++end; begin != end; ++begin) { 141 // This Node object needs to remain alive for the 142 // duration of the program. 143 add_node(new node(*begin)); 144 } 145 } 146 } 147 148 /// Retrieve the data to be passed across DLL boundaries when 149 /// importing registries from another DLL on Windows. exportRegistry()150 static void *exportRegistry() { 151 static std::pair<const node *, const node *> Info(Head, Tail); 152 return &Info; 153 } 154 }; 155 156 157 // Since these are defined in a header file, plugins must be sure to export 158 // these symbols. 159 template <typename T> 160 typename Registry<T>::node *Registry<T>::Head; 161 162 template <typename T> 163 typename Registry<T>::node *Registry<T>::Tail; 164 } // end namespace llvm 165 166 #ifdef LLVM_ON_WIN32 167 #define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) \ 168 extern "C" { \ 169 __declspec(dllexport) void *__cdecl LLVMGetRegistry_##REGISTRY_CLASS() { \ 170 return REGISTRY_CLASS::exportRegistry(); \ 171 } \ 172 } 173 #define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) \ 174 REGISTRY_CLASS::import(DL, #REGISTRY_CLASS) 175 #else 176 #define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) 177 #define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) 178 #endif 179 180 #endif // LLVM_SUPPORT_REGISTRY_H 181