My Project
PassOptions.h
Go to the documentation of this file.
1 //===- PassOptions.h - Pass Option Utilities --------------------*- C++ -*-===//
2 //
3 // Part of the MLIR 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 options with compiler passes and
10 // pipelines.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_PASS_PASSOPTIONS_H_
15 #define MLIR_PASS_PASSOPTIONS_H_
16 
17 #include "mlir/Support/LLVM.h"
19 #include "mlir/Support/STLExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Compiler.h"
23 #include <memory>
24 
25 namespace mlir {
26 namespace detail {
28 class PassOptions : protected llvm::cl::SubCommand {
29 private:
32  class OptionBase {
33  public:
34  virtual ~OptionBase() = default;
35 
37  virtual void anchor();
38 
40  virtual void print(raw_ostream &os) = 0;
41 
43  StringRef getArgStr() const { return getOption()->ArgStr; }
44 
45  protected:
47  virtual const llvm::cl::Option *getOption() const = 0;
48 
50  virtual void copyValueFrom(const OptionBase &other) = 0;
51 
53  friend PassOptions;
54  };
55 
59  template <typename DataType>
60  struct GenericOptionParser : public llvm::cl::parser<DataType> {
61  using llvm::cl::parser<DataType>::parser;
62 
64  Optional<StringRef> findArgStrForValue(const DataType &value) {
65  for (auto &it : this->Values)
66  if (it.V.compare(value))
67  return it.Name;
68  return llvm::None;
69  }
70  };
71 
77  template <typename DataType>
78  using OptionParser =
79  std::conditional_t<std::is_base_of<llvm::cl::generic_parser_base,
80  llvm::cl::parser<DataType>>::value,
81  GenericOptionParser<DataType>,
82  llvm::cl::parser<DataType>>;
83 
85  template <typename DataT>
86  static void printValue(raw_ostream &os, GenericOptionParser<DataT> &parser,
87  const DataT &value) {
88  if (Optional<StringRef> argStr = parser.findArgStrForValue(value))
89  os << argStr;
90  else
91  llvm_unreachable("unknown data value for option");
92  }
93  template <typename DataT, typename ParserT>
94  static void printValue(raw_ostream &os, ParserT &parser, const DataT &value) {
95  os << value;
96  }
97  template <typename ParserT>
98  static void printValue(raw_ostream &os, ParserT &parser, const bool &value) {
99  os << (value ? StringRef("true") : StringRef("false"));
100  }
101 
102 public:
104  template <typename DataType>
105  class Option : public llvm::cl::opt<DataType, /*ExternalStorage=*/false,
106  OptionParser<DataType>>,
107  public OptionBase {
108  public:
109  template <typename... Args>
110  Option(PassOptions &parent, StringRef arg, Args &&... args)
111  : llvm::cl::opt<DataType, /*ExternalStorage=*/false,
112  OptionParser<DataType>>(arg, llvm::cl::sub(parent),
113  std::forward<Args>(args)...) {
114  assert(!this->isPositional() && !this->isSink() &&
115  "sink and positional options are not supported");
116  parent.options.push_back(this);
117  }
118  using llvm::cl::opt<DataType, /*ExternalStorage=*/false,
119  OptionParser<DataType>>::operator=;
120  ~Option() override = default;
121 
122  private:
124  const llvm::cl::Option *getOption() const final { return this; }
125 
127  void print(raw_ostream &os) final {
128  os << this->ArgStr << '=';
129  printValue(os, this->getParser(), this->getValue());
130  }
131 
133  void copyValueFrom(const OptionBase &other) final {
134  this->setValue(static_cast<const Option<DataType> &>(other).getValue());
135  }
136  };
137 
140  template <typename DataType>
141  class ListOption : public llvm::cl::list<DataType, /*StorageClass=*/bool,
142  OptionParser<DataType>>,
143  public OptionBase {
144  public:
145  template <typename... Args>
146  ListOption(PassOptions &parent, StringRef arg, Args &&... args)
147  : llvm::cl::list<DataType, /*StorageClass=*/bool,
148  OptionParser<DataType>>(arg, llvm::cl::sub(parent),
149  std::forward<Args>(args)...) {
150  assert(!this->isPositional() && !this->isSink() &&
151  "sink and positional options are not supported");
152  parent.options.push_back(this);
153  }
154  ~ListOption() override = default;
155 
158  (*this)->assign(values.begin(), values.end());
159  return *this;
160  }
161 
162  std::vector<DataType> *operator->() { return &*this; }
163 
164  private:
166  const llvm::cl::Option *getOption() const final { return this; }
167 
169  void print(raw_ostream &os) final {
170  os << this->ArgStr << '=';
171  auto printElementFn = [&](const DataType &value) {
172  printValue(os, this->getParser(), value);
173  };
174  interleave(*this, os, printElementFn, ",");
175  }
176 
178  void copyValueFrom(const OptionBase &other) final {
179  (*this) = ArrayRef<DataType>(
180  (ListOption<DataType> &)(const_cast<OptionBase &>(other)));
181  }
182  };
183 
184  PassOptions() = default;
185 
188  void copyOptionValuesFrom(const PassOptions &other);
189 
193  LogicalResult parseFromString(StringRef options);
194 
197  void print(raw_ostream &os);
198 
199 private:
201  std::vector<OptionBase *> options;
202 };
203 } // end namespace detail
204 
205 //===----------------------------------------------------------------------===//
206 // PassPipelineOptions
207 //===----------------------------------------------------------------------===//
208 
220 template <typename T> class PassPipelineOptions : public detail::PassOptions {
221 public:
224  static std::unique_ptr<T> createFromString(StringRef options) {
225  auto result = std::make_unique<T>();
226  if (failed(result->parseFromString(options)))
227  return nullptr;
228  return result;
229  }
230 };
231 
234 struct EmptyPipelineOptions : public PassPipelineOptions<EmptyPipelineOptions> {
235 };
236 
237 } // end namespace mlir
238 
239 #endif // MLIR_PASS_PASSOPTIONS_H_
240 
Option(PassOptions &parent, StringRef arg, Args &&... args)
Definition: PassOptions.h:110
Definition: InferTypeOpInterface.cpp:20
Definition: PassRegistry.cpp:413
Definition: PassOptions.h:141
bool failed(LogicalResult result)
Definition: LogicalResult.h:45
LogicalResult parseFromString(StringRef options)
Definition: PassRegistry.cpp:91
Definition: LLVM.h:40
Definition: LogicalResult.h:18
Definition: LLVM.h:37
static std::unique_ptr< T > createFromString(StringRef options)
Definition: PassOptions.h:224
ListOption(PassOptions &parent, StringRef arg, Args &&... args)
Definition: PassOptions.h:146
void copyOptionValuesFrom(const PassOptions &other)
Copy the option values from &#39;other&#39;.
Definition: PassRegistry.cpp:83
Definition: PassOptions.h:234
This class represents a specific pass option, with a provided data type.
Definition: PassOptions.h:105
ValueBuilder< mlir::LLVM::SubOp > sub
Definition: LinalgToLLVM.cpp:67
Base container class and manager for all pass options.
Definition: PassOptions.h:28
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
Definition: STLExtras.h:43
ListOption< DataType > & operator=(ArrayRef< DataType > values)
Allow assigning from an ArrayRef.
Definition: PassOptions.h:157
Definition: PassOptions.h:220
Definition: StandardTypes.h:63
void print(raw_ostream &os)
Definition: PassRegistry.cpp:134
std::vector< DataType > * operator->()
Definition: PassOptions.h:162