1 //===- llvm/CodeGen/MachinePassRegistry.h -----------------------*- 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 // This file contains the mechanics for machine function pass registries.  A
10 // function pass registry (MachinePassRegistry) is auto filled by the static
11 // constructors of MachinePassRegistryNode.  Further there is a command line
12 // parser (RegisterPassParser) which listens to each registry for additions
13 // and deletions, so that the appropriate command option is updated.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H
18 #define LLVM_CODEGEN_MACHINEPASSREGISTRY_H
19 
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/CodeGen/Passes.h"
22 #include "llvm/Support/CommandLine.h"
23 
24 namespace llvm {
25 
26 //===----------------------------------------------------------------------===//
27 ///
28 /// MachinePassRegistryListener - Listener to adds and removals of nodes in
29 /// registration list.
30 ///
31 //===----------------------------------------------------------------------===//
32 template <class PassCtorTy> class MachinePassRegistryListener {
33   virtual void anchor() {}
34 
35 public:
36   MachinePassRegistryListener() = default;
37   virtual ~MachinePassRegistryListener() = default;
38 
39   virtual void NotifyAdd(StringRef N, PassCtorTy C, StringRef D) = 0;
40   virtual void NotifyRemove(StringRef N) = 0;
41 };
42 
43 //===----------------------------------------------------------------------===//
44 ///
45 /// MachinePassRegistryNode - Machine pass node stored in registration list.
46 ///
47 //===----------------------------------------------------------------------===//
48 template <typename PassCtorTy> class MachinePassRegistryNode {
49 private:
50   MachinePassRegistryNode *Next = nullptr; // Next function pass in list.
51   StringRef Name;                       // Name of function pass.
52   StringRef Description;                // Description string.
53   PassCtorTy Ctor;                      // Pass creator.
54 
55 public:
56   MachinePassRegistryNode(const char *N, const char *D, PassCtorTy C)
57       : Name(N), Description(D), Ctor(C) {}
58 
59   // Accessors
60   MachinePassRegistryNode *getNext()      const { return Next; }
61   MachinePassRegistryNode **getNextAddress()    { return &Next; }
62   StringRef getName()                   const { return Name; }
63   StringRef getDescription()            const { return Description; }
64   PassCtorTy getCtor() const { return Ctor; }
65   void setNext(MachinePassRegistryNode *N)      { Next = N; }
66 };
67 
68 //===----------------------------------------------------------------------===//
69 ///
70 /// MachinePassRegistry - Track the registration of machine passes.
71 ///
72 //===----------------------------------------------------------------------===//
73 template <typename PassCtorTy> class MachinePassRegistry {
74 private:
75   MachinePassRegistryNode<PassCtorTy> *List; // List of registry nodes.
76   PassCtorTy Default;                        // Default function pass creator.
77   MachinePassRegistryListener<PassCtorTy>
78       *Listener; // Listener for list adds are removes.
79 
80 public:
81   // NO CONSTRUCTOR - we don't want static constructor ordering to mess
82   // with the registry.
83 
84   // Accessors.
85   //
86   MachinePassRegistryNode<PassCtorTy> *getList() { return List; }
87   PassCtorTy getDefault() { return Default; }
88   void setDefault(PassCtorTy C) { Default = C; }
89   /// setDefault - Set the default constructor by name.
90   void setDefault(StringRef Name) {
91     PassCtorTy Ctor = nullptr;
92     for (MachinePassRegistryNode<PassCtorTy> *R = getList(); R;
93          R = R->getNext()) {
94       if (R->getName() == Name) {
95         Ctor = R->getCtor();
96         break;
97       }
98     }
99     assert(Ctor && "Unregistered pass name");
100     setDefault(Ctor);
101   }
102   void setListener(MachinePassRegistryListener<PassCtorTy> *L) { Listener = L; }
103 
104   /// Add - Adds a function pass to the registration list.
105   ///
106   void Add(MachinePassRegistryNode<PassCtorTy> *Node) {
107     Node->setNext(List);
108     List = Node;
109     if (Listener)
110       Listener->NotifyAdd(Node->getName(), Node->getCtor(),
111                           Node->getDescription());
112   }
113 
114   /// Remove - Removes a function pass from the registration list.
115   ///
116   void Remove(MachinePassRegistryNode<PassCtorTy> *Node) {
117     for (MachinePassRegistryNode<PassCtorTy> **I = &List; *I;
118          I = (*I)->getNextAddress()) {
119       if (*I == Node) {
120         if (Listener)
121           Listener->NotifyRemove(Node->getName());
122         *I = (*I)->getNext();
123         break;
124       }
125     }
126   }
127 };
128 
129 //===----------------------------------------------------------------------===//
130 ///
131 /// RegisterPassParser class - Handle the addition of new machine passes.
132 ///
133 //===----------------------------------------------------------------------===//
134 template <class RegistryClass>
135 class RegisterPassParser
136     : public MachinePassRegistryListener<
137           typename RegistryClass::FunctionPassCtor>,
138       public cl::parser<typename RegistryClass::FunctionPassCtor> {
139 public:
140   RegisterPassParser(cl::Option &O)
141       : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {}
142   ~RegisterPassParser() override { RegistryClass::setListener(nullptr); }
143 
144   void initialize() {
145     cl::parser<typename RegistryClass::FunctionPassCtor>::initialize();
146 
147     // Add existing passes to option.
148     for (RegistryClass *Node = RegistryClass::getList();
149          Node; Node = Node->getNext()) {
150       this->addLiteralOption(Node->getName(),
151                       (typename RegistryClass::FunctionPassCtor)Node->getCtor(),
152                              Node->getDescription());
153     }
154 
155     // Make sure we listen for list changes.
156     RegistryClass::setListener(this);
157   }
158 
159   // Implement the MachinePassRegistryListener callbacks.
160   void NotifyAdd(StringRef N, typename RegistryClass::FunctionPassCtor C,
161                  StringRef D) override {
162     this->addLiteralOption(N, C, D);
163   }
164   void NotifyRemove(StringRef N) override {
165     this->removeLiteralOption(N);
166   }
167 };
168 
169 } // end namespace llvm
170 
171 #endif // LLVM_CODEGEN_MACHINEPASSREGISTRY_H
172