[Mlir-commits] [mlir] [mlir][bytecode] Allow selecting dialect versions in mlir-opt (PR #233149)
Mehdi Amini
llvmlistbot at llvm.org
Sat Oct 17 17:11:14 PDT 2026
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/233149
>From 23309fb2e00066837270a43a408c909206ce6475 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 17 Oct 2026 16:44:30 -0700
Subject: [PATCH] [mlir][bytecode] Allow selecting dialect versions in mlir-opt
Add a repeatable --emit-bytecode-dialect-version=dialect=version option
backed by BytecodeWriterConfig. Let dialects parse their own version
strings through a defaulted BytecodeDialectInterface hook.
Validate explicitly selected dialect versions before numbering or
writing the IR. Reject builtin version 0 when a module has DLTI
properties instead of silently dropping them.
Support builtin versions 0 and 1, preserving the absence of dialect
version metadata in version 0. Restore the historical builtin fixture
and retain the current encoding as a separate fixture. Check emission
and direct decoding of both versions, along with option diagnostics
and selection of multiple dialect versions. Cover historical test
attribute encoding and stdout emission, and reject lossy test operation
downgrades.
Assisted-by: Codex
---
mlir/docs/BytecodeFormat.md | 12 +++++
.../mlir/Bytecode/BytecodeDialectInterface.td | 21 ++++++++
.../include/mlir/Tools/mlir-opt/MlirOptMain.h | 15 ++++++
mlir/lib/Bytecode/Writer/BytecodeWriter.cpp | 11 ++++
mlir/lib/IR/BuiltinDialectBytecode.cpp | 28 +++++++++-
mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 39 ++++++++++++++
mlir/test/Bytecode/bytecode_downgrade.mlir | 4 +-
.../versioning/emit-builtin-version-dlti.mlir | 16 ++++++
.../versioning/emit-dialect-version.mlir | 36 +++++++++++++
.../versioning/emit-test-version-lossy.mlir | 12 +++++
.../versioned_op_with_native_properties.mlir | 6 +++
.../Builtin/Bytecode/builtin_fixed.mlir | 14 +++--
.../Builtin/Bytecode/builtin_fixed_0.mlirbc | Bin 5508 -> 5470 bytes
.../Builtin/Bytecode/builtin_fixed_1.mlirbc | Bin 0 -> 5508 bytes
.../Dialect/Test/TestDialectInterfaces.cpp | 48 +++++++++++++++++-
mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 5 +-
16 files changed, 256 insertions(+), 11 deletions(-)
create mode 100644 mlir/test/Bytecode/versioning/emit-builtin-version-dlti.mlir
create mode 100644 mlir/test/Bytecode/versioning/emit-dialect-version.mlir
create mode 100644 mlir/test/Bytecode/versioning/emit-test-version-lossy.mlir
create mode 100644 mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_1.mlirbc
diff --git a/mlir/docs/BytecodeFormat.md b/mlir/docs/BytecodeFormat.md
index f50ddeb25cc332..27ce718fa3a62a 100644
--- a/mlir/docs/BytecodeFormat.md
+++ b/mlir/docs/BytecodeFormat.md
@@ -21,6 +21,18 @@ upgrades post-parsing through the `upgradeFromVersion` method.
There is no restriction on what kind of information a dialect
is allowed to encode to model its versioning.
+When emitting bytecode, `mlir-opt --emit-bytecode-version=<version>` selects the
+overall bytecode format version. Dialect versions are selected separately with
+`--emit-bytecode-dialect-version=<dialect>=<version>`, which may be repeated for
+different dialects. For example, `mlir-opt --emit-bytecode
+--emit-bytecode-dialect-version=builtin=0` selects the historical builtin dialect
+encoding. A dialect must implement `BytecodeDialectInterface::parseVersion` to
+accept a version string; the dialect defines its syntax and supported versions.
+The resulting version object is passed to the bytecode writer through
+`BytecodeWriterConfig::setDialectVersion`. Before emission, the writer invokes
+`BytecodeDialectInterface::verifyVersion` for explicitly selected versions so
+dialects can reject IR that cannot be represented without losing information.
+
[TOC]
## Magic Number
diff --git a/mlir/include/mlir/Bytecode/BytecodeDialectInterface.td b/mlir/include/mlir/Bytecode/BytecodeDialectInterface.td
index f06715e2339604..11d9b4db7cb940 100644
--- a/mlir/include/mlir/Bytecode/BytecodeDialectInterface.td
+++ b/mlir/include/mlir/Bytecode/BytecodeDialectInterface.td
@@ -57,6 +57,27 @@ def BytecodeDialectInterface : DialectInterface<"BytecodeDialectInterface"> {
return ::llvm::failure();
}]
>,
+ InterfaceMethod<[{
+ Parse a target dialect version for bytecode emission from a string, for
+ example from a command-line option. Return null if the version is invalid
+ or unsupported. The dialect defines the syntax of the version string.
+ }],
+ "std::unique_ptr<::mlir::DialectVersion>", "parseVersion",
+ (ins "::llvm::StringRef":$version),
+ [{ return nullptr; }]
+ >,
+ InterfaceMethod<[{
+ Verify that the given operation and its nested IR can be emitted for the
+ requested dialect version without losing information. This hook is
+ invoked before bytecode emission when a target version is explicitly
+ configured. Emit a diagnostic and return failure if the IR cannot be
+ represented in that version.
+ }],
+ "::llvm::LogicalResult", "verifyVersion",
+ (ins "::mlir::Operation *":$topLevelOp,
+ "const ::mlir::DialectVersion &":$version),
+ [{ return ::llvm::success(); }]
+ >,
InterfaceMethod<[{
Write the version of this dialect to the given writer.
}],
diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
index 7e0b7024608c91..e6697b376fa005 100644
--- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
+++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
@@ -15,6 +15,7 @@
#include "mlir/Debug/CLOptionsSetup.h"
#include "mlir/Support/ToolUtilities.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <cstdlib>
@@ -128,6 +129,17 @@ class MlirOptMainConfig {
return emitBytecodeVersion;
}
+ /// Set target dialect versions as strings of the form "dialect=version".
+ /// The dialect defines the syntax of its version string.
+ MlirOptMainConfig &
+ setEmitBytecodeDialectVersions(ArrayRef<std::string> versions) {
+ emitBytecodeDialectVersions.assign(versions.begin(), versions.end());
+ return *this;
+ }
+ ArrayRef<std::string> bytecodeDialectVersionsToEmit() const {
+ return emitBytecodeDialectVersions;
+ }
+
/// Set the bytecode producer to use.
MlirOptMainConfig &emitBytecodeProducer(StringRef producer) {
emitBytecodeProducerFlag = producer.str();
@@ -320,6 +332,9 @@ class MlirOptMainConfig {
/// Emit bytecode at given version.
std::optional<int64_t> emitBytecodeVersion = std::nullopt;
+ /// Target dialect versions for bytecode emission, as "dialect=version".
+ std::vector<std::string> emitBytecodeDialectVersions;
+
/// Emit bytecode with given producer.
std::string emitBytecodeProducerFlag = "";
diff --git a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
index 89aa731c5cca05..8cd4658d804765 100644
--- a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
+++ b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
@@ -13,6 +13,7 @@
#include "mlir/Bytecode/Encoding.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OpImplementation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/CachedHashString.h"
@@ -1373,6 +1374,16 @@ void BytecodeWriter::writePropertiesSection(EncodingEmitter &emitter) {
LogicalResult mlir::writeBytecodeToFile(Operation *op, raw_ostream &os,
const BytecodeWriterConfig &config) {
+ // Validate before numbering the IR, which may invoke dialect writers.
+ for (const auto &entry : config.getDialectVersionMap()) {
+ Dialect *dialect = op->getContext()->getLoadedDialect(entry.getKey());
+ if (!dialect)
+ continue;
+ auto *interface =
+ dialect->getRegisteredInterface<BytecodeDialectInterface>();
+ if (interface && failed(interface->verifyVersion(op, *entry.getValue())))
+ return failure();
+ }
BytecodeWriter writer(op, config);
return writer.write(op, os);
}
diff --git a/mlir/lib/IR/BuiltinDialectBytecode.cpp b/mlir/lib/IR/BuiltinDialectBytecode.cpp
index e5476082cd6a04..1390769dd8e6ff 100644
--- a/mlir/lib/IR/BuiltinDialectBytecode.cpp
+++ b/mlir/lib/IR/BuiltinDialectBytecode.cpp
@@ -13,6 +13,7 @@
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/DialectResourceBlobManager.h"
@@ -578,13 +579,38 @@ struct BuiltinDialectBytecodeInterface : public BytecodeDialectInterface {
//===--------------------------------------------------------------------===//
// Version
+ std::unique_ptr<DialectVersion>
+ parseVersion(StringRef version) const override {
+ int64_t parsedVersion;
+ if (version.getAsInteger(10, parsedVersion) || parsedVersion < 0 ||
+ parsedVersion > BuiltinDialectVersion::getCurrentVersion().getVersion())
+ return nullptr;
+ return std::make_unique<BuiltinDialectVersion>(parsedVersion);
+ }
+
+ LogicalResult verifyVersion(Operation *topLevelOp,
+ const DialectVersion &version) const override {
+ if (static_cast<const BuiltinDialectVersion &>(version).getVersion() >= 1)
+ return success();
+ WalkResult result = topLevelOp->walk([](ModuleOp module) {
+ if (!module.getDltiAttr())
+ return WalkResult::advance();
+ module.emitOpError("cannot emit builtin dialect version 0 with a 'dlti' "
+ "property");
+ return WalkResult::interrupt();
+ });
+ return failure(result.wasInterrupted());
+ }
+
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()));
+ // Version 0 predates dialect version metadata. Preserve its encoding.
+ if (version->getVersion() > 0)
+ writer.writeVarInt(static_cast<uint64_t>(version->getVersion()));
return;
}
// Else, write current set version version if not 0.
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index d4812aec50fc19..490e0c20f86f6c 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "mlir/Tools/mlir-opt/MlirOptMain.h"
+#include "mlir/Bytecode/BytecodeImplementation.h"
#include "mlir/Bytecode/BytecodeWriter.h"
#include "mlir/Debug/CLOptionsSetup.h"
#include "mlir/Debug/Counter.h"
@@ -36,6 +37,7 @@
#include "mlir/Tools/Plugins/PassPlugin.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -107,6 +109,15 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
cl::desc("Use specified bytecode when generating output"),
cl::location(emitBytecodeVersion), cl::init(std::nullopt));
+ static cl::list<std::string, std::vector<std::string>>
+ bytecodeDialectVersions(
+ "emit-bytecode-dialect-version",
+ cl::desc(
+ "Use the specified dialect version when generating bytecode "
+ "(may be repeated for different dialects)"),
+ cl::value_desc("dialect=version"),
+ cl::location(emitBytecodeDialectVersions));
+
static cl::opt<std::string, /*ExternalStorage=*/true> irdlFile(
"irdl-file",
cl::desc("IRDL file to register before processing the input"),
@@ -620,6 +631,30 @@ performActions(raw_ostream &os,
: BytecodeWriterConfig(fallbackResourceMap);
if (auto v = config.bytecodeVersionToEmit())
writerConfig.setDesiredBytecodeVersion(*v);
+ llvm::StringSet<> versionedDialects;
+ for (StringRef entry : config.bytecodeDialectVersionsToEmit()) {
+ auto [name, version] = entry.split('=');
+ if (name.empty() || version.empty())
+ return op.get()->emitError() << "expected 'dialect=version' for "
+ "--emit-bytecode-dialect-version, got '"
+ << entry << "'";
+ if (!versionedDialects.insert(name).second)
+ return op.get()->emitError()
+ << "duplicate bytecode version for dialect '" << name << "'";
+ Dialect *dialect = context->getOrLoadDialect(name);
+ if (!dialect)
+ return op.get()->emitError()
+ << "unknown dialect '" << name << "' for bytecode emission";
+ auto *interface =
+ dialect->getRegisteredInterface<BytecodeDialectInterface>();
+ std::unique_ptr<DialectVersion> parsedVersion =
+ interface ? interface->parseVersion(version) : nullptr;
+ if (!parsedVersion)
+ return op.get()->emitError()
+ << "dialect '" << name << "' does not support emitting bytecode "
+ << "version '" << version << "'";
+ writerConfig.setDialectVersion(name, std::move(parsedVersion));
+ }
if (config.shouldElideResourceDataFromBytecode())
writerConfig.setElideResourceDataFlag();
return writeBytecodeToFile(op.get(), os, writerConfig);
@@ -629,6 +664,10 @@ performActions(raw_ostream &os,
return emitError(UnknownLoc::get(pm.getContext()))
<< "bytecode version while not emitting bytecode";
+ if (!config.bytecodeDialectVersionsToEmit().empty())
+ return emitError(UnknownLoc::get(pm.getContext()))
+ << "dialect bytecode version while not emitting bytecode";
+
// Don't re-run the verifier if we already ran the verifier at the end of the
// pass pipeline.
AsmState asmState(op.get(),
diff --git a/mlir/test/Bytecode/bytecode_downgrade.mlir b/mlir/test/Bytecode/bytecode_downgrade.mlir
index fd98b9d7ee6a58..71decad979f0b4 100644
--- a/mlir/test/Bytecode/bytecode_downgrade.mlir
+++ b/mlir/test/Bytecode/bytecode_downgrade.mlir
@@ -4,7 +4,5 @@ module {
"test.versionedA"() <{dims = 123 : i64, modifier = false}> : () -> ()
}
-// COM: the property downgrader is executed twice: first for IR numbering and then for emission.
// CHECK: downgrading op...
-// CHECK: downgrading op properties...
-// CHECK: downgrading op properties...
+// CHECK: "test.versionedA"() <{dims = 123 : i64, modifier = false}>
diff --git a/mlir/test/Bytecode/versioning/emit-builtin-version-dlti.mlir b/mlir/test/Bytecode/versioning/emit-builtin-version-dlti.mlir
new file mode 100644
index 00000000000000..0c4cc638aafd3c
--- /dev/null
+++ b/mlir/test/Bytecode/versioning/emit-builtin-version-dlti.mlir
@@ -0,0 +1,16 @@
+// RUN: mlir-opt %s -split-input-file -emit-bytecode -emit-bytecode-dialect-version=builtin=0 -verify-diagnostics
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin=1 | mlir-opt | FileCheck %s
+
+// A property introduced in version 1 cannot be silently dropped for version 0.
+// CHECK: module <dlti = #dlti.map<"chip" = "sm_90">>
+// expected-error at +1 {{cannot emit builtin dialect version 0 with a 'dlti' property}}
+module <{dlti = #dlti.map<"chip" = "sm_90">}> {}
+
+// -----
+
+// Also reject DLTI properties on nested modules.
+// CHECK: module @nested <dlti = #dlti.map<"chip" = "sm_90">>
+module {
+ // expected-error at +1 {{cannot emit builtin dialect version 0 with a 'dlti' property}}
+ module @nested <{dlti = #dlti.map<"chip" = "sm_90">}> {}
+}
diff --git a/mlir/test/Bytecode/versioning/emit-dialect-version.mlir b/mlir/test/Bytecode/versioning/emit-dialect-version.mlir
new file mode 100644
index 00000000000000..ba477ad302d4b5
--- /dev/null
+++ b/mlir/test/Bytecode/versioning/emit-dialect-version.mlir
@@ -0,0 +1,36 @@
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-producer=fixed -emit-bytecode-dialect-version=builtin=0 -emit-bytecode-dialect-version=test=2.0 -o %t.0
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-producer=fixed -emit-bytecode-dialect-version=builtin=1 -emit-bytecode-dialect-version=test=2.0 -o %t.1
+// RUN: not cmp -s %t.0 %t.1
+// RUN: mlir-opt %t.0 | FileCheck %s
+// RUN: mlir-opt %t.1 | FileCheck %s
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-producer=fixed -o %t.default
+// RUN: cmp -s %t.1 %t.default
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-producer=fixed -emit-bytecode-dialect-version=builtin=1 -emit-bytecode-dialect-version=test=1.12 -o %t.old-test
+// RUN: not cmp -s %t.old-test %t.1
+// RUN: mlir-opt %t.old-test | FileCheck %s
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=test=1.12 | mlir-opt | FileCheck %s
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-version=0 -emit-bytecode-dialect-version=test=1.12 | mlir-opt | FileCheck %s
+// RUN: not mlir-opt %s -emit-bytecode-dialect-version=builtin=0 2>&1 | FileCheck %s --check-prefix=NO-BYTECODE
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin 2>&1 | FileCheck %s --check-prefix=MALFORMED
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin= 2>&1 | FileCheck %s --check-prefix=MALFORMED
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version==0 2>&1 | FileCheck %s --check-prefix=MALFORMED
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=unknown=0 2>&1 | FileCheck %s --check-prefix=UNKNOWN
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=arith=0 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED-DIALECT
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=func=1 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED-PARSER
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin=-1 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED-VERSION
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin=2 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED-VERSION
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin=abc 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED-VERSION
+// RUN: not mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=builtin=0 -emit-bytecode-dialect-version=builtin=1 2>&1 | FileCheck %s --check-prefix=DUPLICATE
+
+// NO-BYTECODE: dialect bytecode version while not emitting bytecode
+// MALFORMED: expected 'dialect=version' for --emit-bytecode-dialect-version
+// UNKNOWN: unknown dialect 'unknown' for bytecode emission
+// UNSUPPORTED-DIALECT: dialect 'arith' does not support emitting bytecode version '0'
+// UNSUPPORTED-PARSER: dialect 'func' does not support emitting bytecode version '1'
+// UNSUPPORTED-VERSION: dialect 'builtin' does not support emitting bytecode version
+// DUPLICATE: duplicate bytecode version for dialect 'builtin'
+
+// CHECK: "test.versionedA"() <{dims = 123 : i64, modifier = false}>
+"test.versionedA"() <{dims = 123 : i64, modifier = false}> : () -> ()
+// CHECK: "test.versionedC"() <{attribute = #test.attr_params<42, 24>}>
+"test.versionedC"() <{attribute = #test.attr_params<42, 24>}> : () -> ()
diff --git a/mlir/test/Bytecode/versioning/emit-test-version-lossy.mlir b/mlir/test/Bytecode/versioning/emit-test-version-lossy.mlir
new file mode 100644
index 00000000000000..d95607cd8fe081
--- /dev/null
+++ b/mlir/test/Bytecode/versioning/emit-test-version-lossy.mlir
@@ -0,0 +1,12 @@
+// RUN: mlir-opt %s -split-input-file -emit-bytecode -emit-bytecode-dialect-version=test=1.12 -verify-diagnostics
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=test=2.0 | mlir-opt | FileCheck %s
+
+// CHECK: "test.versionedA"() <{dims = 123 : i64, modifier = true}>
+// expected-error at +1 {{cannot emit test dialect versions before 2.0 with 'modifier = true'}}
+"test.versionedA"() <{dims = 123 : i64, modifier = true}> : () -> ()
+
+// -----
+
+// CHECK: test.with_versioned_properties 1 | 2
+// expected-error at +1 {{cannot emit test dialect versions before 2.0 with a nonzero 'value2' property}}
+test.with_versioned_properties 1 | 2
diff --git a/mlir/test/Bytecode/versioning/versioned_op_with_native_properties.mlir b/mlir/test/Bytecode/versioning/versioned_op_with_native_properties.mlir
index 823a559cbca146..77ae93d22fb22c 100644
--- a/mlir/test/Bytecode/versioning/versioned_op_with_native_properties.mlir
+++ b/mlir/test/Bytecode/versioning/versioned_op_with_native_properties.mlir
@@ -26,3 +26,9 @@
// COM: }
// RUN: mlir-opt %S/versioned-op-with-native-prop-1.12.mlirbc 2>&1 | FileCheck %s --check-prefix=CHECK3
// CHECK3: test.with_versioned_properties 1 | 0
+
+// Verify emission for both historical and current dialect versions.
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=test=1.12 | mlir-opt | FileCheck %s --check-prefix=EMIT
+// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-dialect-version=test=2.0 | mlir-opt | FileCheck %s --check-prefix=EMIT
+// EMIT: test.with_versioned_properties 1 | 0
+test.with_versioned_properties 1 | 0
diff --git a/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed.mlir b/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed.mlir
index ebb198456b3c12..1a2527a45f01b5 100644
--- a/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed.mlir
+++ b/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed.mlir
@@ -1,8 +1,14 @@
+// Verify that both historical and current builtin encodings are unchanged.
+// RUN: mlir-opt -allow-unregistered-dialect -emit-bytecode -emit-bytecode-producer=fixed -emit-bytecode-dialect-version=builtin=0 %s -o %t.0
+// RUN: cmp -s %t.0 %p/builtin_fixed_0.mlirbc
+// RUN: mlir-opt -allow-unregistered-dialect -emit-bytecode -emit-bytecode-producer=fixed -emit-bytecode-dialect-version=builtin=1 %s -o %t.1
+// RUN: cmp -s %t.1 %p/builtin_fixed_1.mlirbc
+// Verify that the default encoding is the current version.
// RUN: mlir-opt -allow-unregistered-dialect -emit-bytecode -emit-bytecode-producer=fixed %s -o %t
-// Verify unchanged.
-// RUN: cmp -s %t %p/builtin_fixed_0.mlirbc
-// Verify can read as expected.
-// RUN: mlir-opt -allow-unregistered-dialect -mlir-print-local-scope %t | FileCheck %s
+// RUN: cmp -s %t %t.1
+// Verify that the checked-in fixtures can be read as expected.
+// RUN: mlir-opt -allow-unregistered-dialect -mlir-print-local-scope %p/builtin_fixed_0.mlirbc | FileCheck %s
+// RUN: mlir-opt -allow-unregistered-dialect -mlir-print-local-scope %p/builtin_fixed_1.mlirbc | FileCheck %s
// Regression test for all builtin dialect bytecode attribute and
// type encodings. Exercises every entry in BuiltinDialectAttributes and
diff --git a/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_0.mlirbc b/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_0.mlirbc
index ee79226875ffae00eeceaf8a7bc78b06e147e216..4f661b5a1d233336116b303958bc724529f88b5a 100644
GIT binary patch
delta 144
zcmZqCzNf|S>+?Q{H!ZUwHHCqZpOtZ=kR;b;1Fj=nMUSmn85vo(GqPT1Wc|#@ZpXyP
z9tXr_K>QDg=P@&~>#;Dh?*n2!R-il(hp{oTe*@w^c1HGdK>QDg)i at a0(}1`Qh?fEJ
ZGawe at 1eycH$AI`55Q}j!vior{0s!B*8p{9x
delta 184
zcmcbo)uJur>+?Q{H!ZUwHHCpul$DvCnRz3>Bp2&x5ZJ82b%d+lipiRtk&%&oI}l$7
z;?InXoOVn=A`V29frx(~VjeS)&|?7-`#=OAE0C}Q5n*gV;v0zQ0~*A64n+I|5o#Pj
jA`L{efrw=w;u(k#;{+0AAmSLOAV?6z6ypLCen0{MjB_5M
diff --git a/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_1.mlirbc b/mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_1.mlirbc
new file mode 100644
index 0000000000000000000000000000000000000000..ee79226875ffae00eeceaf8a7bc78b06e147e216
GIT binary patch
literal 5508
zcmZ`74UimTw)^|Ox1CP=(mH*csZHOcO{O|ild0V?JCba&m!C;&9I=Tck`Tq*>}<~(
znV)24Hn9}BBozuJ3WY))heDxHI2?-eQz&vc6b^+$p-}z{g<|i0J)54MO?*@R`u%<H
zd*A!sd)+;Q$A7hs7m8=P!;;(yRG}28Of|Z>V=nBK=Ypc?nx^Rrg5Mds7S&8s*LBpi
zP{+hyROmLzP;**SqOC%%u5A)RU9(a1+R&zuttWMTDO&JGNXvSXw3bFYE41}UU8Jqi
zlBjJVF7CFL(5y?6nzbg0T4LO)g-i|C5;CD>=}1I{FJdiIc=4gon>4PPL?hWh!Af}d
zq<{-NRMRc=8n>qR3-9rl at L(QkOVjlj{#NNWa&3JL>gtHa^pL(_6M~Q~@6i<uBLW?-
zwqc^-kZFd at 5DpWAi8>ZW>=f&i5Z?5t9Tjqu(gCvhk2WZVd>g2s0XJmO at n>+E&r2F$
zLMMcv3oHnO4H1Zf12Kq00=gjyDM-V-1i%7VXlRgBsiLmZ1~;87%QCE4F9Tm|$f`^?
z7&3=`nd-2ZLN=FoVJVd%L+MBnR#0ki7@$gZn^_;-0ms0xunGp1H8QNFaL!I`53E;r
z!3J$FoPQB)QZIm$)r;X2IF-WXomYe)3pvPBdaVvFj8Nl-n{K}Kwma^GyYIR0{s$j=
z<WVRZssvjMRfe*$03;&)W!(vf{r4(q=$Dh!<fCVt4^`M^DC1B!co;?v<M2<$$Cttm
z!z5iWMjh*^@YD9Qk>{fOofl#+#a~Xm+WlJcjntdzx97dH;Jt<K_kXzfBeRozjR^tL
z{(m=z)SDLL$DO9m{zpyvpRJ3hA8vLL6Qt(&^IuJCiWxr4v_WzU&GC<MYDSJUqkX1x
zk{RnW<IBv%pUm!MW^$*QVvpN!HZ?x~;;V1I`~JtDe))BrkPb4HOe50?oD)?QMV4gP
z85M!w6{TQE(qEV2TFYQh6sTeE{e0~|XQ|6zZ*(E3!&2WkoFA2yE*Vt_UKB65AgV!R
z*>W9mNqYRzugArJi=voVQ;!&ji>Wb-%qDZlT+%~&$$YYiEFsIuN^%@oP1cc(WHW(F
zoc>7ACKGlqb<!<&E_W~m;0kA{GW8F$;3_Ah3Qyr`X9ems2VCn6&~f;ibBsDy%)g#O
zft*3Mld}li5I?p;YQ$NUIiP*uE|wKTY)1 at d&=4#UakweI=3KIyIBPxUgj8%;49~SA
z(AeKIa5Gi*k;}-HWa%|zDcp)_eH+{Xchb&V$nE4Y at +5hNJWpOEuaMWtTjX8x0r{5v
zK&H{@bOxPC=U_tL-FX*zfQ0WQGTak-m}m;z2lt0)rvVRkQ?=9RQsJR)svrW7G#Lgw
z+65nz&q&yiLthe%%)j6X3w|bqPNm`B(9l!i4z&C<JPXf-GcxQCXJ*mRY>G|w1$YTw
z#sux9;rY~FL?cURbUAfa(%5k{zM3Z1(e8~jxtXR;qv;_!uRs@^K^InNe~m8QPI)H}
zah+4%#erKq%xxawQSR^<kMjiY=1HD{SE;$1o<}dF`{-q~^GbRRy^h{UZ=tu-yXd|2
z0s1g~j6O->HLk)Nd_BAgZ*v9S;T+!M8{mCzz=wPje8f%ogeou6SLo~XE&49~fWoKz
zWcZw)0$=b`;VTMX(r at Vx^k)j+ at GN}CbMQS?lnyqPg;q>sJP$u|7k)z4Og4+nW^>qF
z#z){6UW8xy78nN%7G1=aFz6t>3{x?R=5cJrYR0R48%!fq+00I3L#)8gU=;?_39rKp
z!bf2y;X7a!s-MNqWxLsV3}zEP26G5M8|D(qFJo7-YuI&6y^-C*j=7!P#qMPfFz6x4
z5Oy{!G((dqw!~hNR1mo>DZ_jMi-edeScnvskfcrpjz_qhQ1wan411ov$X;Quv$xp0
z3|5j9J{v{R9!F9jgP0{tuzG?m!8&9M1B!||6g9m{-H1E>jD5*qGl`rd!)dsOpV at DW
zKnK7OiS3j{y;KO)NNg9~PT(vIf-)Uuz)YA0vmq^cr7fzvg~7QbjoSj)P12p>ejbqt
z(YTz!4o(<V<qjfGWs1?ic&WZHxga&KJDo{bRHdDua at r-6De^80R8_VpSMgGi;MAfK
zuqc_LT3{HmC7v%rNyCY#*oksglgYBK6}Wf62v8N at 766YBOniIr-SZLJ6&j$1a*U<;
ztX)1vEy(PGa1WyyaFmD=9Z=%Ju3_jgB@!VFNo<pm2(@Kf!QG;p=n3CrQDaYJXsqGp
ztHW+jy-_PxMkKZx9XbJH&*q{}+vK(Ku~cD-IIgwwso<k!#YfLpee_bzN3Z5SdcE$W
zPZ&P>sp+FLNvDqwk&usHNV<IdMq>GR4-NbHxzzUY=V`>pKci6}C(QBj87$`G^I6=-
zSF(hUZ)Dv*zMUm~d>>2s_+u>X;~%qmKK=t+;N#O^VH5ArF^MlE8EJ3E*e`~W@^1Sl
zH}C^3TG~B#AK~4J)IuIpRW-KQiP_<3my?J&PBffI*pA(uOgafY8L=Y~+m5DUaXV~>
z!*-WtccG3M59@%hEOtB|w>otvYTMytEYcryVrT+kBq~PC2}h8OMB}lz6}A$NgD;?F
z*yeT at jm3B(9*!h=I2Mn at on$0pIgaI67OnyjJKCw6#?WZ7)F at V@18F3ctHYxuSE^S>
zYk9XPpZ6s_!()|Pxfo!$<*kjemb~KD8~FO1YjL)gaskslLxt4*mavfO?F&*tQMxxE
zIclJHFtu`ZfHVK7Ac5j^yLccy*xSbGJ2Eh#55++PeFH}grrYF5FHhl;8#Yg7w_6nx
z57L at 97<9gG0O^Bt`Ua0gUdwo+fIG(MV)zamM9+?5<MeFVE!Vf=t7nT{$0En`IT3 at M
zsnv30nMR}5l6psy9WLe at Enf3nn#^LQ;?}&$N25-$TFKQ8X#tywB%SV-O4TEFRBNSx
zTaB@;=w%ZMC)Rsyr`?M}Dc6t$$kxZoQmtBTNcq!?rQuZb*6TU2eyluHEv<74?Q at 0Y
zY%!Ps9tQ(aa|_<Y6H%jm&S<6B at I)IBX%`JutEFrqSE>g>=<yo0(EzK6$(SwWY9m2j
zx;MK$S84^a*q5!iBLTWH?4H at KQb*6*Iitn-M|m6(tYa$;cf_rEE(&^OshT^K!@1f)
zXWGWXbjh|eaFI4fF*Sb at WAYT?SNoJcj~0F%?N;h;=HT=i7W`~)ARU?<k-mQ7Hd)2g
zL7YIj*ReG;vTf5QSi#zEvVxW-IJlheCdPD4ZRH6ACAaKW8uj+$$Kt64kG at G~Q^U;^
z^rVNLIb19hT05v?Z3Z?Z$O#vUb!?ycNr#xvl}hzu!<7W$PTXp3-Ly~&bW$X;wOnN+
zxQ5RQgx2Q;`_*V&w2hXp1;N11(a1?>N at G%a?1Wss-V%#8(@tf*;%wGtn~$TFEtTqy
ziWjTntNEO07$UxPkCQ2ty!;jQ7_c8au43xQ-axBuE9+t)9g3oo0!~#c0T)G0wPcOz
z7Ps}d>JjDTd9yrMFXkt?((HzX(MmAXNMW9j1UwcB+43kp2eUQYiC37&61x=!TWjaD
zg<yK-y*?$>S5(VeOYWKN+V!Gfdgcb*GB&zN;s(Yu;F#C%-3q?TiPyM^#1+QZ<tkg;
z;S;g+s<n0#qZLdVlzD4xm>>d*V)g;{p<KY^%+ at hQb3^E-U%$<N!F<wJ5Y{%j`Nm`~
zno(|yip~17%HprIY?CP_o+!la-shV^Yt6}5EA>XM5_ohKv6nQ8!IzBYF%1{Xt!ZB1
z at Iix56E6^%LZMi32XkB7TY<Z+HO1YQMU?=fo$?m(Y)v%m_3oqs$2{>~kUXWMMOR!m
z!TFtT;x$h3R4r7i(ohcDd+w~3Kh3r##2(hN+I+em+9t*d6DW(bFie4T_To`36zXpC
zp(tz&yTixl#;T(e+bC6sQqq(~q+fjTDG%cH243IEvbuyII8A`<0^rBItX_v74{8rX
z at R$J8 at Z&^XBEZHD1V0F{4-Kg=3h<i%bEY6D2ymVNw+QgD05kB5P~9%TGXi`pz>KK~
HRwMX7spgS(
literal 0
HcmV?d00001
diff --git a/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp b/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
index 2b52978fe3636d..f77a0fe06aa9f7 100644
--- a/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
+++ b/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
@@ -9,6 +9,7 @@
#include "TestDialect.h"
#include "TestOps.h"
#include "TestTypes.h"
+#include "mlir/Bytecode/Encoding.h"
#include "mlir/Conversion/ConvertToEmitC/ToEmitCInterface.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
@@ -74,9 +75,19 @@ struct TestBytecodeDialectInterface : public BytecodeDialectInterface {
LogicalResult writeAttribute(Attribute attr,
DialectBytecodeWriter &writer) const final {
if (auto concreteAttr = llvm::dyn_cast<TestAttrParamsAttr>(attr)) {
+ // Without dialect version metadata, use the textual fallback rather than
+ // emit a historical encoding that a reader would interpret as current.
+ if (writer.getBytecodeVersion() < bytecode::kDialectVersioning)
+ return failure();
writer.writeVarInt(test_encoding::k_attr_params);
- writer.writeVarInt(concreteAttr.getV0());
- writer.writeVarInt(concreteAttr.getV1());
+ auto version = writer.getDialectVersion<TestDialect>();
+ bool useOldEncoding =
+ succeeded(version) &&
+ static_cast<const TestDialectVersion *>(*version)->major_ < 2;
+ writer.writeVarInt(useOldEncoding ? concreteAttr.getV1()
+ : concreteAttr.getV0());
+ writer.writeVarInt(useOldEncoding ? concreteAttr.getV0()
+ : concreteAttr.getV1());
return success();
}
return failure();
@@ -97,6 +108,39 @@ struct TestBytecodeDialectInterface : public BytecodeDialectInterface {
return Attribute();
}
+ std::unique_ptr<DialectVersion> parseVersion(StringRef version) const final {
+ auto [major, minor] = version.split('.');
+ uint32_t majorVersion, minorVersion;
+ if (major.getAsInteger(10, majorVersion) ||
+ minor.getAsInteger(10, minorVersion) || majorVersion > 2 ||
+ (majorVersion == 2 && minorVersion > 0))
+ return nullptr;
+ return std::make_unique<TestDialectVersion>(majorVersion, minorVersion);
+ }
+
+ LogicalResult verifyVersion(Operation *topLevelOp,
+ const DialectVersion &version) const final {
+ if (static_cast<const TestDialectVersion &>(version).major_ >= 2)
+ return success();
+ WalkResult result = topLevelOp->walk([](TestVersionedOpA op) {
+ if (!op.getModifier())
+ return WalkResult::advance();
+ op.emitOpError("cannot emit test dialect versions before 2.0 with "
+ "'modifier = true'");
+ return WalkResult::interrupt();
+ });
+ if (result.wasInterrupted())
+ return failure();
+ result = topLevelOp->walk([](TestOpWithVersionedProperties op) {
+ if (op.getProperties().prop.value2 == 0)
+ return WalkResult::advance();
+ op.emitOpError("cannot emit test dialect versions before 2.0 with "
+ "a nonzero 'value2' property");
+ return WalkResult::interrupt();
+ });
+ return failure(result.wasInterrupted());
+ }
+
// Emit a specific version of the dialect.
void writeVersion(DialectBytecodeWriter &writer) const final {
// Construct the current dialect version.
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index ad08c5c6501b7f..998d25cc089da1 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -1777,7 +1777,6 @@ void TestVersionedOpA::writeProperties(mlir::DialectBytecodeWriter &writer) {
const auto *version =
reinterpret_cast<const TestDialectVersion *>(*maybeVersion);
if ((version->major_ < 2)) {
- llvm::outs() << "downgrading op properties...\n";
return;
}
}
@@ -1818,6 +1817,10 @@ void TestOpWithVersionedProperties::writeToMlirBytecode(
mlir::DialectBytecodeWriter &writer,
const test::VersionedProperties &prop) {
writer.writeVarInt(prop.value1);
+ auto version = writer.getDialectVersion<test::TestDialect>();
+ if (succeeded(version) &&
+ static_cast<const TestDialectVersion *>(*version)->major_ < 2)
+ return;
writer.writeVarInt(prop.value2);
}
More information about the Mlir-commits
mailing list