1 //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Defines a registry template for discovering pluggable modules. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_SUPPORT_REGISTRY_H 14 #define LLVM_SUPPORT_REGISTRY_H 15 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringRef.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 StringRef Name, Desc; 29 std::unique_ptr<T> (*Ctor)(); 30 31 public: SimpleRegistryEntry(StringRef N,StringRef D,std::unique_ptr<T> (* C)())32 SimpleRegistryEntry(StringRef N, StringRef D, std::unique_ptr<T> (*C)()) 33 : Name(N), Desc(D), Ctor(C) {} 34 getName()35 StringRef getName() const { return Name; } getDesc()36 StringRef getDesc() const { return Desc; } instantiate()37 std::unique_ptr<T> instantiate() const { return Ctor(); } 38 }; 39 40 /// A global registry used in conjunction with static constructors to make 41 /// pluggable components (like targets or garbage collectors) "just work" when 42 /// linked with an executable. 43 template <typename T> 44 class Registry { 45 public: 46 typedef T type; 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 72 /// Add a node to the Registry: this is the interface between the plugin and 73 /// the executable. 74 /// 75 /// This function is exported by the executable and called by the plugin to 76 /// add a node to the executable's registry. Therefore it's not defined here 77 /// to avoid it being instantiated in the plugin and is instead defined in 78 /// the executable (see LLVM_INSTANTIATE_REGISTRY below). 79 static void add_node(node *N); 80 81 /// Iterators for registry entries. 82 /// 83 class iterator 84 : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag, 85 const entry> { 86 const node *Cur; 87 88 public: iterator(const node * N)89 explicit iterator(const node *N) : Cur(N) {} 90 91 bool operator==(const iterator &That) const { return Cur == That.Cur; } 92 iterator &operator++() { Cur = Cur->Next; return *this; } 93 const entry &operator*() const { return Cur->Val; } 94 }; 95 96 // begin is not defined here in order to avoid usage of an undefined static 97 // data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY. 98 static iterator begin(); end()99 static iterator end() { return iterator(nullptr); } 100 entries()101 static iterator_range<iterator> entries() { 102 return make_range(begin(), end()); 103 } 104 105 /// A static registration template. Use like such: 106 /// 107 /// Registry<Collector>::Add<FancyGC> 108 /// X("fancy-gc", "Newfangled garbage collector."); 109 /// 110 /// Use of this template requires that: 111 /// 112 /// 1. The registered subclass has a default constructor. 113 template <typename V> 114 class Add { 115 entry Entry; 116 node Node; 117 CtorFn()118 static std::unique_ptr<T> CtorFn() { return std::make_unique<V>(); } 119 120 public: Add(StringRef Name,StringRef Desc)121 Add(StringRef Name, StringRef Desc) 122 : Entry(Name, Desc, CtorFn), Node(Entry) { 123 add_node(&Node); 124 } 125 }; 126 }; 127 } // end namespace llvm 128 129 /// Instantiate a registry class. 130 /// 131 /// This provides template definitions of add_node, begin, and the Head and Tail 132 /// pointers, then explicitly instantiates them. We could explicitly specialize 133 /// them, instead of the two-step process of define then instantiate, but 134 /// strictly speaking that's not allowed by the C++ standard (we would need to 135 /// have explicit specialization declarations in all translation units where the 136 /// specialization is used) so we don't. 137 #define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \ 138 namespace llvm { \ 139 template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\ 140 template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\ 141 template<typename T> \ 142 void Registry<T>::add_node(typename Registry<T>::node *N) { \ 143 if (Tail) \ 144 Tail->Next = N; \ 145 else \ 146 Head = N; \ 147 Tail = N; \ 148 } \ 149 template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \ 150 return iterator(Head); \ 151 } \ 152 template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \ 153 template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \ 154 template \ 155 void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \ 156 template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \ 157 } 158 159 #endif // LLVM_SUPPORT_REGISTRY_H 160