diff options
| author | Ralf Luther <luther.ralf@gmail.com> | 2019-03-27 20:23:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@aicp-server-3> | 2019-03-27 20:23:17 +0000 |
| commit | 1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch) | |
| tree | 391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/llvm/Support/Registry.h | |
| parent | d1d48b140bafaa8a50107292f5fce95562575765 (diff) | |
| parent | 4f56932d3416ac03f646bc1a611b3135fec2fe08 (diff) | |
Merge "Update prebuilt Clang to r353983." into p9.0HEADp9.0-backupp9.0
Diffstat (limited to 'clang-r353983/include/llvm/Support/Registry.h')
| -rw-r--r-- | clang-r353983/include/llvm/Support/Registry.h | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/Support/Registry.h b/clang-r353983/include/llvm/Support/Registry.h new file mode 100644 index 00000000..4d8aa5f1 --- /dev/null +++ b/clang-r353983/include/llvm/Support/Registry.h @@ -0,0 +1,159 @@ +//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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 + : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag, + const entry> { + const node *Cur; + + public: + explicit iterator(const node *N) : Cur(N) {} + + bool operator==(const iterator &That) const { return Cur == That.Cur; } + iterator &operator++() { Cur = Cur->Next; return *this; } + 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 |
