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
24namespace llvm {
25
26//===----------------------------------------------------------------------===//
27///
28/// MachinePassRegistryListener - Listener to adds and removals of nodes in
29/// registration list.
30///
31//===----------------------------------------------------------------------===//
32template <class PassCtorTy> class MachinePassRegistryListener {
33  virtual void anchor() {}
34
35public:
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//===----------------------------------------------------------------------===//
48template <typename PassCtorTy> class MachinePassRegistryNode {
49private:
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
55public:
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//===----------------------------------------------------------------------===//
73template <typename PassCtorTy> class MachinePassRegistry {
74private:
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
80public:
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//===----------------------------------------------------------------------===//
134template <class RegistryClass>
135class RegisterPassParser
136    : public MachinePassRegistryListener<
137          typename RegistryClass::FunctionPassCtor>,
138      public cl::parser<typename RegistryClass::FunctionPassCtor> {
139public:
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