1 //===- PassRegistry.h - Pass Registration Utilities -------------*- 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 utilities for registering information about compiler
10 // passes.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_PASS_PASSREGISTRY_H_
15 #define MLIR_PASS_PASSREGISTRY_H_
16 
17 #include "mlir/Pass/PassOptions.h"
18 #include "mlir/Support/TypeID.h"
19 #include <functional>
20 
21 namespace mlir {
22 class OpPassManager;
23 class Pass;
24 
25 namespace detail {
26 class PassOptions;
27 } // end namespace detail
28 
29 /// A registry function that adds passes to the given pass manager. This should
30 /// also parse options and return success() if parsing succeeded.
31 /// `errorHandler` is a functor used to emit errors during parsing.
32 /// parameter corresponds to the raw location within the pipeline string. This
33 /// should always return failure.
34 using PassRegistryFunction = std::function<LogicalResult(
35     OpPassManager &, StringRef options,
36     function_ref<LogicalResult(const Twine &)> errorHandler)>;
37 using PassAllocatorFunction = std::function<std::unique_ptr<Pass>()>;
38 
39 //===----------------------------------------------------------------------===//
40 // PassRegistry
41 //===----------------------------------------------------------------------===//
42 
43 /// Structure to group information about a passes and pass pipelines (argument
44 /// to invoke via mlir-opt, description, pass pipeline builder).
45 class PassRegistryEntry {
46 public:
47   /// Adds this pass registry entry to the given pass manager. `options` is
48   /// an opaque string that will be parsed by the builder. The success of
49   /// parsing will be returned.
50   LogicalResult
addToPipeline(OpPassManager & pm,StringRef options,function_ref<LogicalResult (const Twine &)> errorHandler)51   addToPipeline(OpPassManager &pm, StringRef options,
52                 function_ref<LogicalResult(const Twine &)> errorHandler) const {
53     assert(builder &&
54            "cannot call addToPipeline on PassRegistryEntry without builder");
55     return builder(pm, options, errorHandler);
56   }
57 
58   /// Returns the command line option that may be passed to 'mlir-opt' that will
59   /// cause this pass to run or null if there is no such argument.
getPassArgument()60   StringRef getPassArgument() const { return arg; }
61 
62   /// Returns a description for the pass, this never returns null.
getPassDescription()63   StringRef getPassDescription() const { return description; }
64 
65   /// Print the help information for this pass. This includes the argument,
66   /// description, and any pass options. `descIndent` is the indent that the
67   /// descriptions should be aligned.
68   void printHelpStr(size_t indent, size_t descIndent) const;
69 
70   /// Return the maximum width required when printing the options of this entry.
71   size_t getOptionWidth() const;
72 
73 protected:
PassRegistryEntry(StringRef arg,StringRef description,const PassRegistryFunction & builder,std::function<void (function_ref<void (const detail::PassOptions &)>)> optHandler)74   PassRegistryEntry(
75       StringRef arg, StringRef description, const PassRegistryFunction &builder,
76       std::function<void(function_ref<void(const detail::PassOptions &)>)>
77           optHandler)
78       : arg(arg), description(description), builder(builder),
79         optHandler(optHandler) {}
80 
81 private:
82   /// The argument with which to invoke the pass via mlir-opt.
83   StringRef arg;
84 
85   /// Description of the pass.
86   StringRef description;
87 
88   /// Function to register this entry to a pass manager pipeline.
89   PassRegistryFunction builder;
90 
91   /// Function to invoke a handler for a pass options instance.
92   std::function<void(function_ref<void(const detail::PassOptions &)>)>
93       optHandler;
94 };
95 
96 /// A structure to represent the information of a registered pass pipeline.
97 class PassPipelineInfo : public PassRegistryEntry {
98 public:
PassPipelineInfo(StringRef arg,StringRef description,const PassRegistryFunction & builder,std::function<void (function_ref<void (const detail::PassOptions &)>)> optHandler)99   PassPipelineInfo(
100       StringRef arg, StringRef description, const PassRegistryFunction &builder,
101       std::function<void(function_ref<void(const detail::PassOptions &)>)>
102           optHandler)
103       : PassRegistryEntry(arg, description, builder, optHandler) {}
104 };
105 
106 /// A structure to represent the information for a derived pass class.
107 class PassInfo : public PassRegistryEntry {
108 public:
109   /// PassInfo constructor should not be invoked directly, instead use
110   /// PassRegistration or registerPass.
111   PassInfo(StringRef arg, StringRef description,
112            const PassAllocatorFunction &allocator);
113 };
114 
115 //===----------------------------------------------------------------------===//
116 // PassRegistration
117 //===----------------------------------------------------------------------===//
118 
119 /// Register a specific dialect pipeline registry function with the system,
120 /// typically used through the PassPipelineRegistration template.
121 void registerPassPipeline(
122     StringRef arg, StringRef description, const PassRegistryFunction &function,
123     std::function<void(function_ref<void(const detail::PassOptions &)>)>
124         optHandler);
125 
126 /// Register a specific dialect pass allocator function with the system,
127 /// typically used through the PassRegistration template.
128 void registerPass(const PassAllocatorFunction &function);
129 
130 /// PassRegistration provides a global initializer that registers a Pass
131 /// allocation routine for a concrete pass instance. The argument is
132 /// optional and provides a callback to construct a pass that does not have
133 /// a default constructor.
134 ///
135 /// Usage:
136 ///
137 ///   /// At namespace scope.
138 ///   static PassRegistration<MyPass> reg;
139 ///
140 template <typename ConcretePass> struct PassRegistration {
PassRegistrationPassRegistration141   PassRegistration(const PassAllocatorFunction &constructor) {
142     registerPass(constructor);
143   }
PassRegistrationPassRegistration144   PassRegistration()
145       : PassRegistration([] { return std::make_unique<ConcretePass>(); }) {}
146 };
147 
148 /// PassPipelineRegistration provides a global initializer that registers a Pass
149 /// pipeline builder routine.
150 ///
151 /// Usage:
152 ///
153 ///   // At namespace scope.
154 ///   void pipelineBuilder(OpPassManager &pm) {
155 ///      pm.addPass(new MyPass());
156 ///      pm.addPass(new MyOtherPass());
157 ///   }
158 ///
159 ///   static PassPipelineRegistration Unused("unused", "Unused pass",
160 ///                                          pipelineBuilder);
161 template <typename Options = EmptyPipelineOptions>
162 struct PassPipelineRegistration {
PassPipelineRegistrationPassPipelineRegistration163   PassPipelineRegistration(
164       StringRef arg, StringRef description,
165       std::function<void(OpPassManager &, const Options &options)> builder) {
166     registerPassPipeline(
167         arg, description,
168         [builder](OpPassManager &pm, StringRef optionsStr,
169                   function_ref<LogicalResult(const Twine &)> errorHandler) {
170           Options options;
171           if (failed(options.parseFromString(optionsStr)))
172             return failure();
173           builder(pm, options);
174           return success();
175         },
176         [](function_ref<void(const detail::PassOptions &)> optHandler) {
177           optHandler(Options());
178         });
179   }
180 };
181 
182 /// Convenience specialization of PassPipelineRegistration for EmptyPassOptions
183 /// that does not pass an empty options struct to the pass builder function.
184 template <> struct PassPipelineRegistration<EmptyPipelineOptions> {
185   PassPipelineRegistration(StringRef arg, StringRef description,
186                            std::function<void(OpPassManager &)> builder) {
187     registerPassPipeline(
188         arg, description,
189         [builder](OpPassManager &pm, StringRef optionsStr,
190                   function_ref<LogicalResult(const Twine &)> errorHandler) {
191           if (!optionsStr.empty())
192             return failure();
193           builder(pm);
194           return success();
195         },
196         [](function_ref<void(const detail::PassOptions &)>) {});
197   }
198 };
199 
200 /// This function parses the textual representation of a pass pipeline, and adds
201 /// the result to 'pm' on success. This function returns failure if the given
202 /// pipeline was invalid. 'errorStream' is the output stream used to emit errors
203 /// found during parsing.
204 LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm,
205                                 raw_ostream &errorStream = llvm::errs());
206 
207 //===----------------------------------------------------------------------===//
208 // PassPipelineCLParser
209 //===----------------------------------------------------------------------===//
210 
211 namespace detail {
212 struct PassPipelineCLParserImpl;
213 } // end namespace detail
214 
215 /// This class implements a command-line parser for MLIR passes. It registers a
216 /// cl option with a given argument and description. This parser will register
217 /// options for each of the passes and pipelines that have been registered with
218 /// the pass registry; Meaning that `-cse` will refer to the CSE pass in MLIR.
219 /// It also registers an argument, `pass-pipeline`, that supports parsing a
220 /// textual description of a pipeline.
221 class PassPipelineCLParser {
222 public:
223   /// Construct a pass pipeline parser with the given command line description.
224   PassPipelineCLParser(StringRef arg, StringRef description);
225   ~PassPipelineCLParser();
226 
227   /// Returns true if this parser contains any valid options to add.
228   bool hasAnyOccurrences() const;
229 
230   /// Returns true if the given pass registry entry was registered at the
231   /// top-level of the parser, i.e. not within an explicit textual pipeline.
232   bool contains(const PassRegistryEntry *entry) const;
233 
234   /// Adds the passes defined by this parser entry to the given pass manager.
235   /// Returns failure() if the pass could not be properly constructed due
236   /// to options parsing.
237   LogicalResult
238   addToPipeline(OpPassManager &pm,
239                 function_ref<LogicalResult(const Twine &)> errorHandler) const;
240 
241 private:
242   std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
243 };
244 
245 /// This class implements a command-line parser specifically for MLIR pass
246 /// names. It registers a cl option with a given argument and description that
247 /// accepts a comma delimited list of pass names.
248 class PassNameCLParser {
249 public:
250   /// Construct a parser with the given command line description.
251   PassNameCLParser(StringRef arg, StringRef description);
252   ~PassNameCLParser();
253 
254   /// Returns true if this parser contains any valid options to add.
255   bool hasAnyOccurrences() const;
256 
257   /// Returns true if the given pass registry entry was registered at the
258   /// top-level of the parser, i.e. not within an explicit textual pipeline.
259   bool contains(const PassRegistryEntry *entry) const;
260 
261 private:
262   std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
263 };
264 
265 } // end namespace mlir
266 
267 #endif // MLIR_PASS_PASSREGISTRY_H_
268