Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:33

0001 //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Defines a registry template for discovering pluggable modules.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_SUPPORT_REGISTRY_H
0014 #define LLVM_SUPPORT_REGISTRY_H
0015 
0016 #include "llvm/ADT/STLExtras.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/ADT/iterator_range.h"
0019 #include "llvm/Support/Compiler.h"
0020 #include "llvm/Support/DynamicLibrary.h"
0021 #include <memory>
0022 
0023 namespace llvm {
0024   /// A simple registry entry which provides only a name, description, and
0025   /// no-argument constructor.
0026   template <typename T>
0027   class SimpleRegistryEntry {
0028     StringRef Name, Desc;
0029     std::unique_ptr<T> (*Ctor)();
0030 
0031   public:
0032     SimpleRegistryEntry(StringRef N, StringRef D, std::unique_ptr<T> (*C)())
0033         : Name(N), Desc(D), Ctor(C) {}
0034 
0035     StringRef getName() const { return Name; }
0036     StringRef getDesc() const { return Desc; }
0037     std::unique_ptr<T> instantiate() const { return Ctor(); }
0038   };
0039 
0040   /// A global registry used in conjunction with static constructors to make
0041   /// pluggable components (like targets or garbage collectors) "just work" when
0042   /// linked with an executable.
0043   template <typename T>
0044   class Registry {
0045   public:
0046     typedef T type;
0047     typedef SimpleRegistryEntry<T> entry;
0048 
0049     class node;
0050     class iterator;
0051 
0052   private:
0053     Registry() = delete;
0054 
0055     friend class node;
0056     // These must be must two separate declarations to workaround a 20 year
0057     // old MSVC bug with dllexport and multiple static fields in the same
0058     // declaration causing error C2487 "member of dll interface class may not
0059     // be declared with dll interface".
0060     // https://developercommunity.visualstudio.com/t/c2487-in-dllexport-class-with-static-members/69878
0061     static node *Head;
0062     static node *Tail;
0063 
0064   public:
0065     /// Node in linked list of entries.
0066     ///
0067     class node {
0068       friend class iterator;
0069       friend Registry<T>;
0070 
0071       node *Next;
0072       const entry& Val;
0073 
0074     public:
0075       node(const entry &V) : Next(nullptr), Val(V) {}
0076     };
0077 
0078     /// Add a node to the Registry: this is the interface between the plugin and
0079     /// the executable.
0080     ///
0081     /// This function is exported by the executable and called by the plugin to
0082     /// add a node to the executable's registry. Therefore it's not defined here
0083     /// to avoid it being instantiated in the plugin and is instead defined in
0084     /// the executable (see LLVM_INSTANTIATE_REGISTRY below).
0085     static void add_node(node *N) {
0086       if (Tail)
0087         Tail->Next = N;
0088       else
0089         Head = N;
0090       Tail = N;
0091     }
0092 
0093     /// Iterators for registry entries.
0094     ///
0095     class iterator
0096         : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
0097                                             const entry> {
0098       const node *Cur;
0099 
0100     public:
0101       explicit iterator(const node *N) : Cur(N) {}
0102 
0103       bool operator==(const iterator &That) const { return Cur == That.Cur; }
0104       iterator &operator++() { Cur = Cur->Next; return *this; }
0105       const entry &operator*() const { return Cur->Val; }
0106     };
0107 
0108     // begin is not defined here in order to avoid usage of an undefined static
0109     // data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
0110     static iterator begin() { return iterator(Head); }
0111     static iterator end()   { return iterator(nullptr); }
0112 
0113     static iterator_range<iterator> entries() {
0114       return make_range(begin(), end());
0115     }
0116 
0117     /// A static registration template. Use like such:
0118     ///
0119     ///   Registry<Collector>::Add<FancyGC>
0120     ///   X("fancy-gc", "Newfangled garbage collector.");
0121     ///
0122     /// Use of this template requires that:
0123     ///
0124     ///  1. The registered subclass has a default constructor.
0125     template <typename V>
0126     class Add {
0127       entry Entry;
0128       node Node;
0129 
0130       static std::unique_ptr<T> CtorFn() { return std::make_unique<V>(); }
0131 
0132     public:
0133       Add(StringRef Name, StringRef Desc)
0134           : Entry(Name, Desc, CtorFn), Node(Entry) {
0135         add_node(&Node);
0136       }
0137     };
0138   };
0139 
0140 } // end namespace llvm
0141 
0142 #ifdef _WIN32
0143 /// Instantiate a registry class.
0144 #define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS)                              \
0145   namespace llvm {                                                             \
0146   template <typename T>                                                        \
0147   typename Registry<T>::node *Registry<T>::Head = nullptr;                     \
0148   template <typename T>                                                        \
0149   typename Registry<T>::node *Registry<T>::Tail = nullptr;                     \
0150   template class LLVM_ABI_EXPORT Registry<REGISTRY_CLASS::type>;               \
0151   }
0152 #else
0153 #define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS)                              \
0154   namespace llvm {                                                             \
0155   template <typename T>                                                        \
0156   typename Registry<T>::node *Registry<T>::Head = nullptr;                     \
0157   template <typename T>                                                        \
0158   typename Registry<T>::node *Registry<T>::Tail = nullptr;                     \
0159   template class Registry<REGISTRY_CLASS::type>;                               \
0160   }
0161 #endif
0162 
0163 #endif // LLVM_SUPPORT_REGISTRY_H