Skip to content

Commit 1079fc4

Browse files
authored
[mlir][pass] Add errorHandler param to Pass::initializeOptions (#87289)
There is no good way to report detailed errors from inside `Pass::initializeOptions` function as context may not be available at this point and writing directly to `llvm::errs()` is not composable. See #87166 (comment) * Add error handler callback to `Pass::initializeOptions` * Update `PassOptions::parseFromString` to support custom error stream instead of using `llvm::errs()` directly. * Update default `Pass::initializeOptions` implementation to propagate error string from `parseFromString` to new error handler. * Update `MapMemRefStorageClassPass` to report error details using new API.
1 parent 9df19ce commit 1079fc4

File tree

7 files changed

+32
-13
lines changed

7 files changed

+32
-13
lines changed

mlir/include/mlir/Pass/Pass.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ class Pass {
114114
/// Derived classes may override this method to hook into the point at which
115115
/// options are initialized, but should generally always invoke this base
116116
/// class variant.
117-
virtual LogicalResult initializeOptions(StringRef options);
117+
virtual LogicalResult
118+
initializeOptions(StringRef options,
119+
function_ref<LogicalResult(const Twine &)> errorHandler);
118120

119121
/// Prints out the pass in the textual representation of pipelines. If this is
120122
/// an adaptor pass, print its pass managers.

mlir/include/mlir/Pass/PassOptions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ class PassOptions : protected llvm::cl::SubCommand {
293293
/// Parse options out as key=value pairs that can then be handed off to the
294294
/// `llvm::cl` command line passing infrastructure. Everything is space
295295
/// separated.
296-
LogicalResult parseFromString(StringRef options);
296+
LogicalResult parseFromString(StringRef options,
297+
raw_ostream &errorStream = llvm::errs());
297298

298299
/// Print the options held by this struct in a form that can be parsed via
299300
/// 'parseFromString'.

mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,16 @@ class MapMemRefStorageClassPass final
272272
const spirv::MemorySpaceToStorageClassMap &memorySpaceMap)
273273
: memorySpaceMap(memorySpaceMap) {}
274274

275-
LogicalResult initializeOptions(StringRef options) override {
276-
if (failed(Pass::initializeOptions(options)))
275+
LogicalResult initializeOptions(
276+
StringRef options,
277+
function_ref<LogicalResult(const Twine &)> errorHandler) override {
278+
if (failed(Pass::initializeOptions(options, errorHandler)))
277279
return failure();
278280

279281
if (clientAPI == "opencl")
280282
memorySpaceMap = spirv::mapMemorySpaceToOpenCLStorageClass;
281283
else if (clientAPI != "vulkan")
282-
return failure();
284+
return errorHandler(llvm::Twine("Invalid clienAPI: ") + clientAPI);
283285

284286
return success();
285287
}

mlir/lib/Pass/Pass.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,16 @@ Operation *PassExecutionAction::getOp() const {
6060
void Pass::anchor() {}
6161

6262
/// Attempt to initialize the options of this pass from the given string.
63-
LogicalResult Pass::initializeOptions(StringRef options) {
64-
return passOptions.parseFromString(options);
63+
LogicalResult Pass::initializeOptions(
64+
StringRef options,
65+
function_ref<LogicalResult(const Twine &)> errorHandler) {
66+
std::string errStr;
67+
llvm::raw_string_ostream os(errStr);
68+
if (failed(passOptions.parseFromString(options, os))) {
69+
os.flush();
70+
return errorHandler(errStr);
71+
}
72+
return success();
6573
}
6674

6775
/// Copy the option values from 'other', which is another instance of this

mlir/lib/Pass/PassRegistry.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ buildDefaultRegistryFn(const PassAllocatorFunction &allocator) {
4040
return [=](OpPassManager &pm, StringRef options,
4141
function_ref<LogicalResult(const Twine &)> errorHandler) {
4242
std::unique_ptr<Pass> pass = allocator();
43-
LogicalResult result = pass->initializeOptions(options);
43+
LogicalResult result = pass->initializeOptions(options, errorHandler);
4444

4545
std::optional<StringRef> pmOpName = pm.getOpName();
4646
std::optional<StringRef> passOpName = pass->getOpName();
@@ -280,7 +280,8 @@ parseNextArg(StringRef options) {
280280
llvm_unreachable("unexpected control flow in pass option parsing");
281281
}
282282

283-
LogicalResult detail::PassOptions::parseFromString(StringRef options) {
283+
LogicalResult detail::PassOptions::parseFromString(StringRef options,
284+
raw_ostream &errorStream) {
284285
// NOTE: `options` is modified in place to always refer to the unprocessed
285286
// part of the string.
286287
while (!options.empty()) {
@@ -291,7 +292,7 @@ LogicalResult detail::PassOptions::parseFromString(StringRef options) {
291292

292293
auto it = OptionsMap.find(key);
293294
if (it == OptionsMap.end()) {
294-
llvm::errs() << "<Pass-Options-Parser>: no such option " << key << "\n";
295+
errorStream << "<Pass-Options-Parser>: no such option " << key << "\n";
295296
return failure();
296297
}
297298
if (llvm::cl::ProvidePositionalOption(it->second, value, 0))

mlir/lib/Transforms/InlinerPass.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ class InlinerPass : public impl::InlinerBase<InlinerPass> {
6464
/// Derived classes may override this method to hook into the point at which
6565
/// options are initialized, but should generally always invoke this base
6666
/// class variant.
67-
LogicalResult initializeOptions(StringRef options) override;
67+
LogicalResult initializeOptions(
68+
StringRef options,
69+
function_ref<LogicalResult(const Twine &)> errorHandler) override;
6870

6971
/// Inliner configuration parameters created from the pass options.
7072
InlinerConfig config;
@@ -153,8 +155,10 @@ void InlinerPass::runOnOperation() {
153155
return;
154156
}
155157

156-
LogicalResult InlinerPass::initializeOptions(StringRef options) {
157-
if (failed(Pass::initializeOptions(options)))
158+
LogicalResult InlinerPass::initializeOptions(
159+
StringRef options,
160+
function_ref<LogicalResult(const Twine &)> errorHandler) {
161+
if (failed(Pass::initializeOptions(options, errorHandler)))
158162
return failure();
159163

160164
// Initialize the pipeline builder for operations without the dedicated

mlir/test/Dialect/Transform/test-pass-application.mlir

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ module attributes {transform.with_named_sequence} {
7878
transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
7979
%1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
8080
// expected-error @below {{failed to add pass or pass pipeline to pipeline: canonicalize}}
81+
// expected-error @below {{<Pass-Options-Parser>: no such option invalid-option}}
8182
transform.apply_registered_pass "canonicalize" to %1 {options = "invalid-option=1"} : (!transform.any_op) -> !transform.any_op
8283
transform.yield
8384
}

0 commit comments

Comments
 (0)