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