LLVM 23.0.0git
Registry.h
Go to the documentation of this file.
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"
18#include "llvm/ADT/StringRef.h"
22#include <memory>
23
24namespace llvm {
25/// A simple registry entry which provides only a name, description, and
26/// an `CtorParamTypes&&` variadic parameterized constructor.
27template <typename T, typename... CtorParamTypes> class SimpleRegistryEntry {
28 using FactoryFnRef = function_ref<std::unique_ptr<T>(CtorParamTypes &&...)>;
29 StringRef Name, Desc;
30 FactoryFnRef Ctor;
31
32public:
34 : Name(N), Desc(D), Ctor(C) {}
35
36 StringRef getName() const { return Name; }
37 StringRef getDesc() const { return Desc; }
38 std::unique_ptr<T> instantiate(CtorParamTypes &&...Params) const {
39 return Ctor(std::forward<CtorParamTypes>(Params)...);
40 }
41};
42
43template <typename T, typename... CtorParamTypes> class Registry;
44namespace detail {
45template <typename R> struct IsRegistryType : std::false_type {};
46template <typename T, typename... CtorParamTypes>
47struct IsRegistryType<Registry<T, CtorParamTypes...>> : std::true_type {};
48} // namespace detail
49
50/// A global registry used in conjunction with static constructors to make
51/// pluggable components (like targets or garbage collectors) "just work" when
52/// linked with an executable.
53template <typename T, typename... CtorParamTypes> class Registry {
54 static_assert(
56 "Trying to instantiate a wrong specialization 'Registry<Registry<...>>'");
57
58public:
59 using type = T;
60 using entry = SimpleRegistryEntry<T, CtorParamTypes...>;
61 static constexpr bool HasCtorParamTypes = sizeof...(CtorParamTypes) != 0;
62
63 class node;
64 class iterator;
65
66private:
67 Registry() = delete;
68
69 friend class node;
70 // These must be must two separate declarations to workaround a 20 year
71 // old MSVC bug with dllexport and multiple static fields in the same
72 // declaration causing error C2487 "member of dll interface class may not
73 // be declared with dll interface".
74 // https://developercommunity.visualstudio.com/t/c2487-in-dllexport-class-with-static-members/69878
75 static inline node *Head = nullptr;
76 static inline node *Tail = nullptr;
77
78public:
79 /// Node in linked list of entries.
80 ///
81 class node {
82 friend class iterator;
83 friend Registry<T, CtorParamTypes...>;
84
85 node *Next;
86 const entry &Val;
87
88 public:
89 node(const entry &V) : Next(nullptr), Val(V) {}
90 };
91
92 /// Add a node to the Registry: this is the interface between the plugin and
93 /// the executable.
94 ///
95 /// This function is exported by the executable and called by the plugin to
96 /// add a node to the executable's registry. Therefore it's not defined here
97 /// to avoid it being instantiated in the plugin and is instead defined in
98 /// the executable (see LLVM_INSTANTIATE_REGISTRY below).
99 static void add_node(node *N) {
100 if (Tail)
101 Tail->Next = N;
102 else
103 Head = N;
104 Tail = N;
105 }
106
107 /// Iterators for registry entries.
108 ///
110 : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
111 const entry> {
112 const node *Cur;
113
114 public:
115 explicit iterator(const node *N) : Cur(N) {}
116
117 bool operator==(const iterator &That) const { return Cur == That.Cur; }
119 Cur = Cur->Next;
120 return *this;
121 }
122 const entry &operator*() const { return Cur->Val; }
123 };
124
125 // begin is not defined here in order to avoid usage of an undefined static
126 // data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
127 static iterator begin() { return iterator(Head); }
128 static iterator end() { return iterator(nullptr); }
129
131 return make_range(begin(), end());
132 }
133
134 /// A static registration template. Use like such:
135 ///
136 /// Registry<Collector>::Add<FancyGC>
137 /// X("fancy-gc", "Newfangled garbage collector.");
138 ///
139 template <typename V> class Add {
140 entry Entry;
141 node Node;
142
143 static std::unique_ptr<T> CtorFn(CtorParamTypes &&...Params) {
144 return std::make_unique<V>(std::forward<CtorParamTypes>(Params)...);
145 }
146
147 public:
149 : Entry(Name, Desc, CtorFn), Node(Entry) {
150 add_node(&Node);
151 }
152 };
153};
154
155} // end namespace llvm
156
157#ifdef _WIN32
158/// Instantiate a registry class.
159#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
160 namespace llvm { \
161 template class LLVM_ABI_EXPORT Registry<REGISTRY_CLASS::type>; \
162 static_assert(!REGISTRY_CLASS::HasCtorParamTypes, \
163 "LLVM_INSTANTIATE_REGISTRY can't be used with extra " \
164 "constructor parameter types"); \
165 }
166#else
167#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
168 namespace llvm { \
169 template class Registry<REGISTRY_CLASS::type>; \
170 static_assert(!REGISTRY_CLASS::HasCtorParamTypes, \
171 "LLVM_INSTANTIATE_REGISTRY can't be used with extra " \
172 "constructor parameter types"); \
173 }
174#endif
175
176#endif // LLVM_SUPPORT_REGISTRY_H
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define T
This file contains some templates that are useful if you are working with the STL at all.
Add(StringRef Name, StringRef Desc)
Definition Registry.h:148
const entry & operator*() const
Definition Registry.h:122
iterator(const node *N)
Definition Registry.h:115
iterator & operator++()
Definition Registry.h:118
bool operator==(const iterator &That) const
Definition Registry.h:117
Node in linked list of entries.
Definition Registry.h:81
friend class iterator
Definition Registry.h:82
node(const entry &V)
Definition Registry.h:89
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition Registry.h:53
SimpleRegistryEntry< GCMetadataPrinter, CtorParamTypes... > entry
Definition Registry.h:60
static iterator begin()
Definition Registry.h:127
static constexpr bool HasCtorParamTypes
Definition Registry.h:61
static iterator_range< iterator > entries()
Definition Registry.h:130
static void add_node(node *N)
Add a node to the Registry: this is the interface between the plugin and the executable.
Definition Registry.h:99
static iterator end()
Definition Registry.h:128
A simple registry entry which provides only a name, description, and an CtorParamTypes&& variadic par...
Definition Registry.h:27
StringRef getName() const
Definition Registry.h:36
std::unique_ptr< T > instantiate(CtorParamTypes &&...Params) const
Definition Registry.h:38
StringRef getDesc() const
Definition Registry.h:37
SimpleRegistryEntry(StringRef N, StringRef D, FactoryFnRef C)
Definition Registry.h:33
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
An efficient, type-erasing, non-owning reference to a callable.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Definition iterator.h:80
A range adaptor for a pair of iterators.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Op::Description Desc
MachinePassRegistry< typename RegisterRegAllocBase< T >::FunctionPassCtor > RegisterRegAllocBase< T >::Registry
RegisterRegAlloc's global Registry tracks allocator registration.
#define N