[llvm] [mlir] [mlir][bytecode] Add builtin dialect version (PR #184678)
Jacques Pienaar via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 5 00:44:13 PST 2026
https://github.com/jpienaar updated https://github.com/llvm/llvm-project/pull/184678
>From 4de19167e7717b39cb5d7bd7dded1adb1b4137e3 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Wed, 4 Mar 2026 14:34:09 +0000
Subject: [PATCH 1/2] [mlir][bytecode] Add builtin dialect version
This adds a singular Builtin dialect version for use with bytecode
serialization. This version is not currently print unless set and not 0
(not planned a bump until next LLVM version). Created a unit test as
this was easiest way to track.
Additionally add emitWarning virtual method to DialectBytecodeReader,
mirroring emitError.
---
.../mlir/Bytecode/BytecodeImplementation.h | 3 +
mlir/include/mlir/IR/BuiltinDialect.h | 20 +++++++
mlir/include/mlir/IR/BuiltinDialect.td | 5 +-
mlir/lib/Bytecode/Reader/BytecodeReader.cpp | 11 ++++
mlir/lib/IR/BuiltinDialectBytecode.cpp | 35 ++++++++++++
.../IR/BuiltinDialectVersionTest.cpp | 56 +++++++++++++++++++
mlir/unittests/IR/CMakeLists.txt | 1 +
.../mlir/unittests/BUILD.bazel | 1 +
8 files changed, 131 insertions(+), 1 deletion(-)
create mode 100644 mlir/unittests/IR/BuiltinDialectVersionTest.cpp
diff --git a/mlir/include/mlir/Bytecode/BytecodeImplementation.h b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
index 49c5b33bd8290..4a42f0f6c8020 100644
--- a/mlir/include/mlir/Bytecode/BytecodeImplementation.h
+++ b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
@@ -50,6 +50,9 @@ class DialectBytecodeReader {
/// Emit an error to the reader.
virtual InFlightDiagnostic emitError(const Twine &msg = {}) const = 0;
+ /// Emit a warning to the reader.
+ virtual InFlightDiagnostic emitWarning(const Twine &msg = {}) const = 0;
+
/// Retrieve the dialect version by name if available.
virtual FailureOr<const DialectVersion *>
getDialectVersion(StringRef dialectName) const = 0;
diff --git a/mlir/include/mlir/IR/BuiltinDialect.h b/mlir/include/mlir/IR/BuiltinDialect.h
index 15b98d5112e53..d06b63da6b892 100644
--- a/mlir/include/mlir/IR/BuiltinDialect.h
+++ b/mlir/include/mlir/IR/BuiltinDialect.h
@@ -14,8 +14,28 @@
#ifndef MLIR_IR_BUILTINDIALECT_H_
#define MLIR_IR_BUILTINDIALECT_H_
+#include "mlir/Bytecode/BytecodeImplementation.h"
#include "mlir/IR/Dialect.h"
+//===----------------------------------------------------------------------===//
+// BuiltinDialectVersion
+//===----------------------------------------------------------------------===//
+
+struct BuiltinDialectVersion : public mlir::DialectVersion {
+ BuiltinDialectVersion(int64_t version) : version(version) {}
+
+ int64_t getVersion() const { return version; }
+
+ static BuiltinDialectVersion getCurrentVersion() { return {0}; }
+
+ bool operator<(const BuiltinDialectVersion &other) const {
+ return version < other.version;
+ }
+
+private:
+ int64_t version;
+};
+
//===----------------------------------------------------------------------===//
// Dialect
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/BuiltinDialect.td b/mlir/include/mlir/IR/BuiltinDialect.td
index c131107634b44..c770dd50f3622 100644
--- a/mlir/include/mlir/IR/BuiltinDialect.td
+++ b/mlir/include/mlir/IR/BuiltinDialect.td
@@ -24,6 +24,9 @@ def Builtin_Dialect : Dialect {
let useDefaultAttributePrinterParser = 0;
let useDefaultTypePrinterParser = 0;
let extraClassDeclaration = [{
+ std::optional<BuiltinDialectVersion> getVersion() const { return version; }
+ void setVersion(std::optional<BuiltinDialectVersion> v) { version = v; }
+
private:
// Register the builtin Attributes.
void registerAttributes();
@@ -32,7 +35,7 @@ def Builtin_Dialect : Dialect {
// Register the builtin Types.
void registerTypes();
- public:
+ std::optional<BuiltinDialectVersion> version;
}];
}
diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index c974603bb9235..07a9266dcd1fa 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -144,6 +144,13 @@ class EncodingReader {
}
InFlightDiagnostic emitError() const { return ::emitError(fileLoc); }
+ /// Emit a warning using the given arguments.
+ template <typename... Args>
+ InFlightDiagnostic emitWarning(Args &&...args) const {
+ return ::emitWarning(fileLoc).append(std::forward<Args>(args)...);
+ }
+ InFlightDiagnostic emitWarning() const { return ::emitWarning(fileLoc); }
+
/// Parse a single byte from the stream.
template <typename T>
LogicalResult parseByte(T &value) {
@@ -1036,6 +1043,10 @@ class DialectReader : public DialectBytecodeReader {
return reader.emitError(msg);
}
+ InFlightDiagnostic emitWarning(const Twine &msg) const override {
+ return reader.emitWarning(msg);
+ }
+
FailureOr<const DialectVersion *>
getDialectVersion(StringRef dialectName) const override {
// First check if the dialect is available in the map.
diff --git a/mlir/lib/IR/BuiltinDialectBytecode.cpp b/mlir/lib/IR/BuiltinDialectBytecode.cpp
index 8cf25391ba11a..de71e42952b1d 100644
--- a/mlir/lib/IR/BuiltinDialectBytecode.cpp
+++ b/mlir/lib/IR/BuiltinDialectBytecode.cpp
@@ -239,6 +239,41 @@ struct BuiltinDialectBytecodeInterface : public BytecodeDialectInterface {
DialectBytecodeWriter &writer) const override {
return ::writeType(type, writer);
}
+
+ //===--------------------------------------------------------------------===//
+ // Version
+
+ void writeVersion(DialectBytecodeWriter &writer) const override {
+ auto configVersion = writer.getDialectVersion(getDialect()->getNamespace());
+ // Write version set in config.
+ if (succeeded(configVersion)) {
+ auto *version =
+ static_cast<const BuiltinDialectVersion *>(*configVersion);
+ writer.writeVarInt(static_cast<uint64_t>(version->getVersion()));
+ return;
+ }
+ // Else, write current set version version if not 0.
+ if (auto version = cast<BuiltinDialect>(getDialect())->getVersion();
+ version && version->getVersion() > 0) {
+ writer.writeVarInt(static_cast<uint64_t>(version->getVersion()));
+ }
+ }
+
+ std::unique_ptr<DialectVersion>
+ readVersion(DialectBytecodeReader &reader) const override {
+ uint64_t version;
+ if (failed(reader.readVarInt(version)))
+ return nullptr;
+
+ auto dialectVersion = std::make_unique<BuiltinDialectVersion>(version);
+ if (BuiltinDialectVersion::getCurrentVersion() < *dialectVersion) {
+ reader.emitWarning()
+ << "reading newer builtin dialect version than supported";
+ return nullptr;
+ }
+
+ return dialectVersion;
+ }
};
} // namespace
diff --git a/mlir/unittests/IR/BuiltinDialectVersionTest.cpp b/mlir/unittests/IR/BuiltinDialectVersionTest.cpp
new file mode 100644
index 0000000000000..3eec05cb36a9b
--- /dev/null
+++ b/mlir/unittests/IR/BuiltinDialectVersionTest.cpp
@@ -0,0 +1,56 @@
+//===- BuiltinDialectVersionTest.cpp - Test builtin dialect versioning ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "mlir/Bytecode/BytecodeWriter.h"
+#include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/Parser/Parser.h"
+
+using namespace mlir;
+
+TEST(BuiltinDialectVersionTest, RejectFutureVersion) {
+ MLIRContext ctx;
+ auto module = ModuleOp::create(UnknownLoc::get(&ctx));
+
+ auto writeBytecode = [&](std::string &out,
+ std::optional<int64_t> version =
+ std::nullopt) -> LogicalResult {
+ BytecodeWriterConfig config;
+ if (version)
+ config.setDialectVersion<BuiltinDialect>(
+ std::make_unique<BuiltinDialectVersion>(*version));
+ llvm::raw_string_ostream os(out);
+ return writeBytecodeToFile(module, os, config);
+ };
+
+ std::string bytecode;
+ ASSERT_TRUE(succeeded(writeBytecode(bytecode)));
+ std::string bytecodeWithFutureVersion;
+ ASSERT_TRUE(succeeded(writeBytecode(bytecodeWithFutureVersion, 99)));
+
+ EXPECT_NE(bytecode, bytecodeWithFutureVersion);
+
+ std::string warning;
+ ScopedDiagnosticHandler handler(&ctx, [&](Diagnostic &diag) {
+ if (diag.getSeverity() == DiagnosticSeverity::Warning)
+ warning = diag.str();
+ return success();
+ });
+
+ auto parsed =
+ parseSourceString(StringRef(bytecodeWithFutureVersion),
+ ParserConfig(&ctx, /*verifyAfterParse=*/true));
+ EXPECT_TRUE(warning.find("reading newer builtin dialect version") !=
+ std::string::npos);
+
+ module->erase();
+}
diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt
index dd3b110dcd295..ebc2f6678ae8a 100644
--- a/mlir/unittests/IR/CMakeLists.txt
+++ b/mlir/unittests/IR/CMakeLists.txt
@@ -4,6 +4,7 @@ add_mlir_unittest(MLIRIRTests
AffineMapTest.cpp
AttributeTest.cpp
AttrTypeReplacerTest.cpp
+ BuiltinDialectVersionTest.cpp
Diagnostic.cpp
DialectTest.cpp
DistinctAttributeAllocatorTest.cpp
diff --git a/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel
index dfb5be5f85027..47c5e4d0ebe20 100644
--- a/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel
@@ -41,6 +41,7 @@ cc_test(
"//llvm:Remarks",
"//llvm:Support",
"//mlir:BytecodeReader",
+ "//mlir:BytecodeWriter",
"//mlir:CallOpInterfaces",
"//mlir:FunctionInterfaces",
"//mlir:IR",
>From 4d905dad4bd6be1fab53792636be385320be8594 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 5 Mar 2026 08:44:00 +0000
Subject: [PATCH 2/2] Fix cmake deps
---
mlir/unittests/IR/CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt
index ebc2f6678ae8a..366e4dac4f7fe 100644
--- a/mlir/unittests/IR/CMakeLists.txt
+++ b/mlir/unittests/IR/CMakeLists.txt
@@ -29,5 +29,6 @@ add_mlir_unittest(MLIRIRTests
)
target_include_directories(MLIRIRTests PRIVATE "${MLIR_BINARY_DIR}/test/lib/Dialect/Test")
mlir_target_link_libraries(MLIRIRTests PRIVATE MLIRIR)
+target_link_libraries(MLIRIRTests PRIVATE MLIRBytecodeWriter)
target_link_libraries(MLIRIRTests PRIVATE MLIRTestDialect)
target_link_libraries(MLIRIRTests PRIVATE MLIRRemarkStreamer)
More information about the llvm-commits
mailing list