blob: 8e07fc3f192029d5dafecf8593451681beea52ed [file] [log] [blame]
//===- PassRegistry.h - Pass Registration Utilities -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains utilities for registering information about compiler
// passes.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_PASS_PASSREGISTRY_H_
#define MLIR_PASS_PASSREGISTRY_H_
#include "mlir/Pass/PassOptions.h"
#include "mlir/Support/TypeID.h"
#include <functional>
namespace mlir {
class OpPassManager;
class Pass;
namespace detail {
class PassOptions;
} // end namespace detail
/// A registry function that adds passes to the given pass manager. This should
/// also parse options and return success() if parsing succeeded.
/// `errorHandler` is a functor used to emit errors during parsing.
/// parameter corresponds to the raw location within the pipeline string. This
/// should always return failure.
using PassRegistryFunction = std::function<LogicalResult(
OpPassManager &, StringRef options,
function_ref<LogicalResult(const Twine &)> errorHandler)>;
using PassAllocatorFunction = std::function<std::unique_ptr<Pass>()>;
//===----------------------------------------------------------------------===//
// PassRegistry
//===----------------------------------------------------------------------===//
/// Structure to group information about a passes and pass pipelines (argument
/// to invoke via mlir-opt, description, pass pipeline builder).
class PassRegistryEntry {
public:
/// Adds this pass registry entry to the given pass manager. `options` is
/// an opaque string that will be parsed by the builder. The success of
/// parsing will be returned.
LogicalResult
addToPipeline(OpPassManager &pm, StringRef options,
function_ref<LogicalResult(const Twine &)> errorHandler) const {
assert(builder &&
"cannot call addToPipeline on PassRegistryEntry without builder");
return builder(pm, options, errorHandler);
}
/// Returns the command line option that may be passed to 'mlir-opt' that will
/// cause this pass to run or null if there is no such argument.
StringRef getPassArgument() const { return arg; }
/// Returns a description for the pass, this never returns null.
StringRef getPassDescription() const { return description; }
/// Print the help information for this pass. This includes the argument,
/// description, and any pass options. `descIndent` is the indent that the
/// descriptions should be aligned.
void printHelpStr(size_t indent, size_t descIndent) const;
/// Return the maximum width required when printing the options of this entry.
size_t getOptionWidth() const;
protected:
PassRegistryEntry(
StringRef arg, StringRef description, const PassRegistryFunction &builder,
std::function<void(function_ref<void(const detail::PassOptions &)>)>
optHandler)
: arg(arg), description(description), builder(builder),
optHandler(optHandler) {}
private:
/// The argument with which to invoke the pass via mlir-opt.
StringRef arg;
/// Description of the pass.
StringRef description;
/// Function to register this entry to a pass manager pipeline.
PassRegistryFunction builder;
/// Function to invoke a handler for a pass options instance.
std::function<void(function_ref<void(const detail::PassOptions &)>)>
optHandler;
};
/// A structure to represent the information of a registered pass pipeline.
class PassPipelineInfo : public PassRegistryEntry {
public:
PassPipelineInfo(
StringRef arg, StringRef description, const PassRegistryFunction &builder,
std::function<void(function_ref<void(const detail::PassOptions &)>)>
optHandler)
: PassRegistryEntry(arg, description, builder, optHandler) {}
};
/// A structure to represent the information for a derived pass class.
class PassInfo : public PassRegistryEntry {
public:
/// PassInfo constructor should not be invoked directly, instead use
/// PassRegistration or registerPass.
PassInfo(StringRef arg, StringRef description,
const PassAllocatorFunction &allocator);
};
//===----------------------------------------------------------------------===//
// PassRegistration
//===----------------------------------------------------------------------===//
/// Register a specific dialect pipeline registry function with the system,
/// typically used through the PassPipelineRegistration template.
void registerPassPipeline(
StringRef arg, StringRef description, const PassRegistryFunction &function,
std::function<void(function_ref<void(const detail::PassOptions &)>)>
optHandler);
/// Register a specific dialect pass allocator function with the system,
/// typically used through the PassRegistration template.
void registerPass(const PassAllocatorFunction &function);
/// PassRegistration provides a global initializer that registers a Pass
/// allocation routine for a concrete pass instance. The argument is
/// optional and provides a callback to construct a pass that does not have
/// a default constructor.
///
/// Usage:
///
/// /// At namespace scope.
/// static PassRegistration<MyPass> reg;
///
template <typename ConcretePass> struct PassRegistration {
PassRegistration(const PassAllocatorFunction &constructor) {
registerPass(constructor);
}
PassRegistration()
: PassRegistration([] { return std::make_unique<ConcretePass>(); }) {}
};
/// PassPipelineRegistration provides a global initializer that registers a Pass
/// pipeline builder routine.
///
/// Usage:
///
/// // At namespace scope.
/// void pipelineBuilder(OpPassManager &pm) {
/// pm.addPass(new MyPass());
/// pm.addPass(new MyOtherPass());
/// }
///
/// static PassPipelineRegistration Unused("unused", "Unused pass",
/// pipelineBuilder);
template <typename Options = EmptyPipelineOptions>
struct PassPipelineRegistration {
PassPipelineRegistration(
StringRef arg, StringRef description,
std::function<void(OpPassManager &, const Options &options)> builder) {
registerPassPipeline(
arg, description,
[builder](OpPassManager &pm, StringRef optionsStr,
function_ref<LogicalResult(const Twine &)> errorHandler) {
Options options;
if (failed(options.parseFromString(optionsStr)))
return failure();
builder(pm, options);
return success();
},
[](function_ref<void(const detail::PassOptions &)> optHandler) {
optHandler(Options());
});
}
};
/// Convenience specialization of PassPipelineRegistration for EmptyPassOptions
/// that does not pass an empty options struct to the pass builder function.
template <> struct PassPipelineRegistration<EmptyPipelineOptions> {
PassPipelineRegistration(StringRef arg, StringRef description,
std::function<void(OpPassManager &)> builder) {
registerPassPipeline(
arg, description,
[builder](OpPassManager &pm, StringRef optionsStr,
function_ref<LogicalResult(const Twine &)> errorHandler) {
if (!optionsStr.empty())
return failure();
builder(pm);
return success();
},
[](function_ref<void(const detail::PassOptions &)>) {});
}
};
/// This function parses the textual representation of a pass pipeline, and adds
/// the result to 'pm' on success. This function returns failure if the given
/// pipeline was invalid. 'errorStream' is the output stream used to emit errors
/// found during parsing.
LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm,
raw_ostream &errorStream = llvm::errs());
//===----------------------------------------------------------------------===//
// PassPipelineCLParser
//===----------------------------------------------------------------------===//
namespace detail {
struct PassPipelineCLParserImpl;
} // end namespace detail
/// This class implements a command-line parser for MLIR passes. It registers a
/// cl option with a given argument and description. This parser will register
/// options for each of the passes and pipelines that have been registered with
/// the pass registry; Meaning that `-cse` will refer to the CSE pass in MLIR.
/// It also registers an argument, `pass-pipeline`, that supports parsing a
/// textual description of a pipeline.
class PassPipelineCLParser {
public:
/// Construct a pass pipeline parser with the given command line description.
PassPipelineCLParser(StringRef arg, StringRef description);
~PassPipelineCLParser();
/// Returns true if this parser contains any valid options to add.
bool hasAnyOccurrences() const;
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool contains(const PassRegistryEntry *entry) const;
/// Adds the passes defined by this parser entry to the given pass manager.
/// Returns failure() if the pass could not be properly constructed due
/// to options parsing.
LogicalResult
addToPipeline(OpPassManager &pm,
function_ref<LogicalResult(const Twine &)> errorHandler) const;
private:
std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
};
/// This class implements a command-line parser specifically for MLIR pass
/// names. It registers a cl option with a given argument and description that
/// accepts a comma delimited list of pass names.
class PassNameCLParser {
public:
/// Construct a parser with the given command line description.
PassNameCLParser(StringRef arg, StringRef description);
~PassNameCLParser();
/// Returns true if this parser contains any valid options to add.
bool hasAnyOccurrences() const;
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool contains(const PassRegistryEntry *entry) const;
private:
std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
};
} // end namespace mlir
#endif // MLIR_PASS_PASSREGISTRY_H_