Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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:
  32.     SimpleRegistryEntry(StringRef N, StringRef D, std::unique_ptr<T> (*C)())
  33.         : Name(N), Desc(D), Ctor(C) {}
  34.  
  35.     StringRef getName() const { return Name; }
  36.     StringRef getDesc() const { return Desc; }
  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:
  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:
  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();
  99.     static iterator end()   { return iterator(nullptr); }
  100.  
  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.  
  118.       static std::unique_ptr<T> CtorFn() { return std::make_unique<V>(); }
  119.  
  120.     public:
  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.