LCOV - code coverage report
Current view: top level - include/llvm/Support - Registry.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 6 9 66.7 %
Date: 2018-10-20 13:21:21 Functions: 35 73 47.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 :     StringRef getName() const { return Name; }
      37             :     StringRef getDesc() const { return Desc; }
      38       58633 :     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           0 :       bool operator==(const iterator &That) const { return Cur == That.Cur; }
      91           0 :       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
      92       58532 :       iterator &operator++() { Cur = Cur->Next; return *this; }
      93          85 :       const entry &operator*() const { return Cur->Val; }
      94       59025 :       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          25 :       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       58633 :       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

Generated by: LCOV version 1.13