1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines a registry template for discovering pluggable modules.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_REGISTRY_H
#define LLVM_SUPPORT_REGISTRY_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DynamicLibrary.h"
#include <memory>
namespace llvm {
/// A simple registry entry which provides only a name, description, and
/// no-argument constructor.
template <typename T>
class SimpleRegistryEntry {
StringRef Name, Desc;
std::unique_ptr<T> (*Ctor)();
public:
SimpleRegistryEntry(StringRef N, StringRef D, std::unique_ptr<T> (*C)())
: Name(N), Desc(D), Ctor(C) {}
StringRef getName() const { return Name; }
StringRef getDesc() const { return Desc; }
std::unique_ptr<T> instantiate() const { return Ctor(); }
};
/// A global registry used in conjunction with static constructors to make
/// pluggable components (like targets or garbage collectors) "just work" when
/// linked with an executable.
template <typename T>
class Registry {
public:
typedef T type;
typedef SimpleRegistryEntry<T> entry;
class node;
class iterator;
private:
Registry() = delete;
friend class node;
static node *Head, *Tail;
public:
/// Node in linked list of entries.
///
class node {
friend class iterator;
friend Registry<T>;
node *Next;
const entry& Val;
public:
node(const entry &V) : Next(nullptr), Val(V) {}
};
/// Add a node to the Registry: this is the interface between the plugin and
/// the executable.
///
/// This function is exported by the executable and called by the plugin to
/// add a node to the executable's registry. Therefore it's not defined here
/// to avoid it being instantiated in the plugin and is instead defined in
/// the executable (see LLVM_INSTANTIATE_REGISTRY below).
static void add_node(node *N);
/// Iterators for registry entries.
///
class iterator {
const node *Cur;
public:
explicit iterator(const node *N) : Cur(N) {}
bool operator==(const iterator &That) const { return Cur == That.Cur; }
bool operator!=(const iterator &That) const { return Cur != That.Cur; }
iterator &operator++() { Cur = Cur->Next; return *this; }
const entry &operator*() const { return Cur->Val; }
const entry *operator->() const { return &Cur->Val; }
};
// begin is not defined here in order to avoid usage of an undefined static
// data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
static iterator begin();
static iterator end() { return iterator(nullptr); }
static iterator_range<iterator> entries() {
return make_range(begin(), end());
}
/// A static registration template. Use like such:
///
/// Registry<Collector>::Add<FancyGC>
/// X("fancy-gc", "Newfangled garbage collector.");
///
/// Use of this template requires that:
///
/// 1. The registered subclass has a default constructor.
template <typename V>
class Add {
entry Entry;
node Node;
static std::unique_ptr<T> CtorFn() { return make_unique<V>(); }
public:
Add(StringRef Name, StringRef Desc)
: Entry(Name, Desc, CtorFn), Node(Entry) {
add_node(&Node);
}
};
};
} // end namespace llvm
/// Instantiate a registry class.
///
/// This provides template definitions of add_node, begin, and the Head and Tail
/// pointers, then explicitly instantiates them. We could explicitly specialize
/// them, instead of the two-step process of define then instantiate, but
/// strictly speaking that's not allowed by the C++ standard (we would need to
/// have explicit specialization declarations in all translation units where the
/// specialization is used) so we don't.
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
namespace llvm { \
template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\
template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\
template<typename T> \
void Registry<T>::add_node(typename Registry<T>::node *N) { \
if (Tail) \
Tail->Next = N; \
else \
Head = N; \
Tail = N; \
} \
template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \
return iterator(Head); \
} \
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \
template \
void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \
template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \
}
#endif // LLVM_SUPPORT_REGISTRY_H
|