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, TypeID passID, 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(StringRef arg, StringRef description, 129 const PassAllocatorFunction &function); 130 131 /// PassRegistration provides a global initializer that registers a Pass 132 /// allocation routine for a concrete pass instance. The third argument is 133 /// optional and provides a callback to construct a pass that does not have 134 /// a default constructor. 135 /// 136 /// Usage: 137 /// 138 /// /// At namespace scope. 139 /// static PassRegistration<MyPass> reg("my-pass", "My Pass Description."); 140 /// 141 template <typename ConcretePass> struct PassRegistration { PassRegistrationPassRegistration142 PassRegistration(StringRef arg, StringRef description, 143 const PassAllocatorFunction &constructor) { 144 registerPass(arg, description, constructor); 145 } 146 PassRegistrationPassRegistration147 PassRegistration(StringRef arg, StringRef description) 148 : PassRegistration(arg, description, 149 [] { return std::make_unique<ConcretePass>(); }) {} 150 }; 151 152 /// PassPipelineRegistration provides a global initializer that registers a Pass 153 /// pipeline builder routine. 154 /// 155 /// Usage: 156 /// 157 /// // At namespace scope. 158 /// void pipelineBuilder(OpPassManager &pm) { 159 /// pm.addPass(new MyPass()); 160 /// pm.addPass(new MyOtherPass()); 161 /// } 162 /// 163 /// static PassPipelineRegistration Unused("unused", "Unused pass", 164 /// pipelineBuilder); 165 template <typename Options = EmptyPipelineOptions> 166 struct PassPipelineRegistration { PassPipelineRegistrationPassPipelineRegistration167 PassPipelineRegistration( 168 StringRef arg, StringRef description, 169 std::function<void(OpPassManager &, const Options &options)> builder) { 170 registerPassPipeline( 171 arg, description, 172 [builder](OpPassManager &pm, StringRef optionsStr, 173 function_ref<LogicalResult(const Twine &)> errorHandler) { 174 Options options; 175 if (failed(options.parseFromString(optionsStr))) 176 return failure(); 177 builder(pm, options); 178 return success(); 179 }, 180 [](function_ref<void(const detail::PassOptions &)> optHandler) { 181 optHandler(Options()); 182 }); 183 } 184 }; 185 186 /// Convenience specialization of PassPipelineRegistration for EmptyPassOptions 187 /// that does not pass an empty options struct to the pass builder function. 188 template <> struct PassPipelineRegistration<EmptyPipelineOptions> { 189 PassPipelineRegistration(StringRef arg, StringRef description, 190 std::function<void(OpPassManager &)> builder) { 191 registerPassPipeline( 192 arg, description, 193 [builder](OpPassManager &pm, StringRef optionsStr, 194 function_ref<LogicalResult(const Twine &)> errorHandler) { 195 if (!optionsStr.empty()) 196 return failure(); 197 builder(pm); 198 return success(); 199 }, 200 [](function_ref<void(const detail::PassOptions &)>) {}); 201 } 202 }; 203 204 /// This function parses the textual representation of a pass pipeline, and adds 205 /// the result to 'pm' on success. This function returns failure if the given 206 /// pipeline was invalid. 'errorStream' is the output stream used to emit errors 207 /// found during parsing. 208 LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm, 209 raw_ostream &errorStream = llvm::errs()); 210 211 //===----------------------------------------------------------------------===// 212 // PassPipelineCLParser 213 //===----------------------------------------------------------------------===// 214 215 namespace detail { 216 struct PassPipelineCLParserImpl; 217 } // end namespace detail 218 219 /// This class implements a command-line parser for MLIR passes. It registers a 220 /// cl option with a given argument and description. This parser will register 221 /// options for each of the passes and pipelines that have been registered with 222 /// the pass registry; Meaning that `-cse` will refer to the CSE pass in MLIR. 223 /// It also registers an argument, `pass-pipeline`, that supports parsing a 224 /// textual description of a pipeline. 225 class PassPipelineCLParser { 226 public: 227 /// Construct a pass pipeline parser with the given command line description. 228 PassPipelineCLParser(StringRef arg, StringRef description); 229 ~PassPipelineCLParser(); 230 231 /// Returns true if this parser contains any valid options to add. 232 bool hasAnyOccurrences() const; 233 234 /// Returns true if the given pass registry entry was registered at the 235 /// top-level of the parser, i.e. not within an explicit textual pipeline. 236 bool contains(const PassRegistryEntry *entry) const; 237 238 /// Adds the passes defined by this parser entry to the given pass manager. 239 /// Returns failure() if the pass could not be properly constructed due 240 /// to options parsing. 241 LogicalResult 242 addToPipeline(OpPassManager &pm, 243 function_ref<LogicalResult(const Twine &)> errorHandler) const; 244 245 private: 246 std::unique_ptr<detail::PassPipelineCLParserImpl> impl; 247 }; 248 249 } // end namespace mlir 250 251 #endif // MLIR_PASS_PASSREGISTRY_H_ 252