LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Versioning.h
Go to the documentation of this file.
1//===-- Versioning.h --------------------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
11
12#include <mlir/Bytecode/BytecodeImplementation.h>
13
14#include <limits>
15
16namespace llzk {
17
20static constexpr auto kV1ConstParamsAttr = "llzk.v1_const_params";
21
22struct LLZKDialectVersion : public mlir::DialectVersion {
23 static const LLZKDialectVersion &CurrentVersion();
24
25 static mlir::FailureOr<LLZKDialectVersion> read(mlir::DialectBytecodeReader &reader);
26
28 LLZKDialectVersion(uint64_t majorV, uint64_t minorV, uint64_t patchV)
29 : majorVersion(majorV), minorVersion(minorV), patchVersion(patchV) {}
30
31 void write(mlir::DialectBytecodeWriter &writer) const;
32
33 std::string str() const;
34
35 std::strong_ordering operator<=>(const LLZKDialectVersion &other) const;
36
37 bool operator==(const LLZKDialectVersion &other) const { return std::is_eq(operator<=>(other)); }
38
40};
41
43inline void
44writeDynamicAPInt(mlir::DialectBytecodeWriter &writer, const llvm::DynamicAPInt &value) {
45 llvm::APSInt bits = toAPSInt(value);
46 llvm::APInt canonical = bits.trunc(bits.getSignificantBits());
47 writer.writeVarInt(canonical.getBitWidth());
48 writer.writeAPIntWithKnownWidth(canonical);
49}
50
52inline mlir::FailureOr<llvm::DynamicAPInt> readDynamicAPInt(mlir::DialectBytecodeReader &reader) {
53 uint64_t width;
54 if (mlir::failed(reader.readVarInt(width))) {
55 return mlir::failure();
56 }
57 if (width == 0 || width > std::numeric_limits<unsigned>::max()) {
58 return reader.emitError("invalid integer encoding width");
59 }
60 auto bits = reader.readAPIntWithKnownWidth(static_cast<unsigned>(width));
61 if (mlir::failed(bits)) {
62 return mlir::failure();
63 }
64 return llvm::DynamicAPInt(*bits);
65}
66
68template <typename DialectTy>
69struct LLZKDialectBytecodeInterface : public mlir::BytecodeDialectInterface {
70
71 LLZKDialectBytecodeInterface(mlir::Dialect *dia) : mlir::BytecodeDialectInterface(dia) {}
72
74 void writeVersion(mlir::DialectBytecodeWriter &writer) const override {
75 auto versionOr = writer.getDialectVersion<DialectTy>();
76 // Check if a target version to emit was specified on the writer configs.
77 if (mlir::succeeded(versionOr)) {
78 reinterpret_cast<const LLZKDialectVersion *>(*versionOr)->write(writer);
79 } else {
80 // Otherwise, write the current version
82 }
83 }
84
87 std::unique_ptr<mlir::DialectVersion>
88 readVersion(mlir::DialectBytecodeReader &reader) const override {
89 auto versionOr = LLZKDialectVersion::read(reader);
90 if (mlir::failed(versionOr)) {
91 return nullptr;
92 }
93 return std::make_unique<LLZKDialectVersion>(std::move(*versionOr));
94 }
95
100 mlir::LogicalResult
101 upgradeFromVersion(mlir::Operation *rootOp, const mlir::DialectVersion &version) const final {
102 const auto &requested = static_cast<const LLZKDialectVersion &>(version);
103 const auto &current = LLZKDialectVersion::CurrentVersion();
104 if (requested == current) {
105 return mlir::success(); // versions match, nothing to do
106 }
107 if (requested > current) {
108 return rootOp->emitError().append(
109 "Cannot upgrade from current version ", current.str(), " to future version ",
110 requested.str()
111 );
112 }
113 return upgradeFromVersion(rootOp, current, requested);
114 }
115
116 virtual mlir::LogicalResult upgradeFromVersion(
117 mlir::Operation * /*rootOp*/, const LLZKDialectVersion &current,
118 const LLZKDialectVersion &requested
119 ) const {
120 assert(requested < current && "pre-condition of upgradeFromVersion not met");
121 // Default implementation does nothing. Dialects that have breaking changes between versions
122 // should override this method to perform the necessary upgrade transformations.
123 return mlir::success();
124 }
125};
126
127} // namespace llzk
This file implements helpers for DynamicAPInt operations and conversions that LLVM does not provide.
mlir::FailureOr< llvm::DynamicAPInt > readDynamicAPInt(mlir::DialectBytecodeReader &reader)
Decode a signed integer, rejecting invalid widths before allocating storage.
Definition Versioning.h:52
APSInt toAPSInt(const DynamicAPInt &i)
void writeDynamicAPInt(mlir::DialectBytecodeWriter &writer, const llvm::DynamicAPInt &value)
Write the minimal signed two's-complement encoding of a mathematical integer.
Definition Versioning.h:44
mlir::LogicalResult upgradeFromVersion(mlir::Operation *rootOp, const mlir::DialectVersion &version) const final
Hook invoked for each custom dialect after parsing is completed if a version directive was present an...
Definition Versioning.h:101
std::unique_ptr< mlir::DialectVersion > readVersion(mlir::DialectBytecodeReader &reader) const override
Read the version of this dialect from the provided reader and return it as a unique_ptr to a dialect ...
Definition Versioning.h:88
virtual mlir::LogicalResult upgradeFromVersion(mlir::Operation *, const LLZKDialectVersion &current, const LLZKDialectVersion &requested) const
Definition Versioning.h:116
void writeVersion(mlir::DialectBytecodeWriter &writer) const override
Writes the current version of the LLZK-lib to the given writer.
Definition Versioning.h:74
LLZKDialectBytecodeInterface(mlir::Dialect *dia)
Definition Versioning.h:71
static const LLZKDialectVersion & CurrentVersion()
LLZKDialectVersion(uint64_t majorV, uint64_t minorV, uint64_t patchV)
Definition Versioning.h:28
bool operator==(const LLZKDialectVersion &other) const
Definition Versioning.h:37
std::strong_ordering operator<=>(const LLZKDialectVersion &other) const
static mlir::FailureOr< LLZKDialectVersion > read(mlir::DialectBytecodeReader &reader)
void write(mlir::DialectBytecodeWriter &writer) const
std::string str() const