diff --git a/mlir/include/mlir/IR/AsmState.h b/mlir/include/mlir/IR/AsmState.h --- a/mlir/include/mlir/IR/AsmState.h +++ b/mlir/include/mlir/IR/AsmState.h @@ -456,17 +456,22 @@ class ParserConfig { public: /// Construct a parser configuration with the given context. + /// `verifyAfterParse` indicates if the IR should be verified after parsing. /// `fallbackResourceMap` is an optional fallback handler that can be used to /// parse external resources not explicitly handled by another parser. - ParserConfig(MLIRContext *context, + ParserConfig(MLIRContext *context, bool verifyAfterParse = true, FallbackAsmResourceMap *fallbackResourceMap = nullptr) - : context(context), fallbackResourceMap(fallbackResourceMap) { + : context(context), verifyAfterParse(verifyAfterParse), + fallbackResourceMap(fallbackResourceMap) { assert(context && "expected valid MLIR context"); } /// Return the MLIRContext to be used when parsing. MLIRContext *getContext() const { return context; } + /// Returns if the parser should verify the IR after parsing. + bool shouldVerifyAfterParse() const { return verifyAfterParse; } + /// Return the resource parser registered to the given name, or nullptr if no /// parser with `name` is registered. AsmResourceParser *getResourceParser(StringRef name) const { @@ -498,6 +503,7 @@ private: MLIRContext *context; + bool verifyAfterParse; DenseMap> resourceParsers; FallbackAsmResourceMap *fallbackResourceMap; }; diff --git a/mlir/lib/AsmParser/Parser.cpp b/mlir/lib/AsmParser/Parser.cpp --- a/mlir/lib/AsmParser/Parser.cpp +++ b/mlir/lib/AsmParser/Parser.cpp @@ -802,7 +802,7 @@ return failure(); // Verify that the parsed operations are valid. - if (failed(verify(topLevelOp))) + if (state.config.shouldVerifyAfterParse() && failed(verify(topLevelOp))) return failure(); // If we are populating the parser state, finalize the top-level operation. diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp --- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp +++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp @@ -1408,7 +1408,7 @@ } // Verify that the parsed operations are valid. - if (failed(verify(*moduleOp))) + if (config.shouldVerifyAfterParse() && failed(verify(*moduleOp))) return failure(); // Splice the parsed operations over to the provided top-level block. diff --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp --- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp +++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp @@ -342,7 +342,8 @@ return; } - ParserConfig config(&context, &fallbackResourceMap); + ParserConfig config(&context, /*verifyAfterParse=*/true, + &fallbackResourceMap); sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc()); if (failed(parseAsmSourceFile(sourceMgr, &parsedIR, config, &asmState))) { // If parsing failed, clear out any of the current state. @@ -1296,7 +1297,8 @@ FallbackAsmResourceMap fallbackResourceMap; // Setup the parser config. - ParserConfig parserConfig(&tempContext, &fallbackResourceMap); + ParserConfig parserConfig(&tempContext, /*verifyAfterParse=*/true, + &fallbackResourceMap); // Try to parse the given source file. Block parsedBlock; diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -66,7 +66,7 @@ // untouched. PassReproducerOptions reproOptions; FallbackAsmResourceMap fallbackResourceMap; - ParserConfig config(context, &fallbackResourceMap); + ParserConfig config(context, /*verifyAfterParse=*/true, &fallbackResourceMap); reproOptions.attachResourceParser(config); // Parse the input file and reset the context threading state. diff --git a/mlir/unittests/Parser/CMakeLists.txt b/mlir/unittests/Parser/CMakeLists.txt --- a/mlir/unittests/Parser/CMakeLists.txt +++ b/mlir/unittests/Parser/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_unittest(MLIRParserTests + ParserTest.cpp ResourceTest.cpp DEPENDS diff --git a/mlir/unittests/Parser/ParserTest.cpp b/mlir/unittests/Parser/ParserTest.cpp new file mode 100644 --- /dev/null +++ b/mlir/unittests/Parser/ParserTest.cpp @@ -0,0 +1,31 @@ +//===- ParserTest.cpp -----------------------------------------------------===// +// +// This file is licensed 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 +// +//===----------------------------------------------------------------------===// + +#include "mlir/Parser/Parser.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/Verifier.h" + +#include "gmock/gmock.h" + +using namespace mlir; + +namespace { +TEST(MLIRParser, ParseInvalidIR) { + std::string moduleStr = R"mlir( + module attributes {bad} {} + )mlir"; + + MLIRContext context; + ParserConfig config(&context, /*verifyAfterParse=*/false); + + // Check that we properly parse the op, but it fails the verifier. + OwningOpRef module = parseSourceString(moduleStr, config); + ASSERT_TRUE(module); + ASSERT_TRUE(failed(verify(*module))); +} +} // namespace