LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Dialect.cpp
Go to the documentation of this file.
1//===-- Dialect.cpp - Dialect method implementations ------------*- 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 "llzk/Config/Config.h"
20
21#include <mlir/Bytecode/BytecodeImplementation.h>
22#include <mlir/IR/DialectImplementation.h>
23#include <mlir/Support/LLVM.h>
24
25#include <llvm/ADT/TypeSwitch.h>
26
27#include <limits>
28
29// TableGen'd implementation files
31
32// Need a complete declaration of storage classes for below
33#define GET_ATTRDEF_CLASSES
35
36using namespace mlir;
37using namespace llzk;
38
39//===------------------------------------------------------------------===//
40// LLZKDialect
41//===------------------------------------------------------------------===//
42
43namespace {
44
46enum class LLZKAttrEncoding : uint8_t {
47 LoopBounds = 0,
48};
49
50struct LLZKDialectBytecodeInterfaceImpl : public LLZKDialectBytecodeInterface<LLZKDialect> {
52
53 Attribute readAttribute(DialectBytecodeReader &reader) const final {
54 uint64_t encoding;
55 if (failed(reader.readVarInt(encoding))) {
56 return {};
57 }
58 if (encoding > std::numeric_limits<uint8_t>::max()) {
59 reader.emitError() << "unknown LLZK attribute encoding: " << encoding;
60 return {};
61 }
62
63 switch (static_cast<LLZKAttrEncoding>(encoding)) {
64 case LLZKAttrEncoding::LoopBounds: {
65 FailureOr<APInt> lower = readAPInt(reader);
66 FailureOr<APInt> upper = readAPInt(reader);
67 FailureOr<APInt> step = readAPInt(reader);
68 if (failed(lower) || failed(upper) || failed(step)) {
69 return {};
70 }
71 return LoopBoundsAttr::get(getContext(), *lower, *upper, *step);
72 }
73 }
74
75 reader.emitError() << "unknown LLZK attribute encoding: " << encoding;
76 return {};
77 }
78
79 LogicalResult writeAttribute(Attribute attr, DialectBytecodeWriter &writer) const final {
80 if (auto loopBounds = dyn_cast<LoopBoundsAttr>(attr)) {
81 writer.writeVarInt(static_cast<uint64_t>(LLZKAttrEncoding::LoopBounds));
82 writeAPInt(writer, loopBounds.getLower());
83 writeAPInt(writer, loopBounds.getUpper());
84 writeAPInt(writer, loopBounds.getStep());
85 return success();
86 }
87 return failure();
88 }
89};
90
91LogicalResult verifyLlzkMainAttr(Operation *op, Attribute attr) {
92 ModuleOp moduleOp = llvm::dyn_cast<ModuleOp>(op);
93 if (!moduleOp) {
94 return op->emitError().append(
95 '"', MAIN_ATTR_NAME, "\" attribute can only be specified on '",
96 ModuleOp::getOperationName(), '\''
97 );
98 }
99
100 FailureOr<component::StructType> mainStructTypeOpt = getTypeFromLlzkMainAttr(moduleOp, attr);
101 if (succeeded(mainStructTypeOpt)) {
102 if (component::StructType st = mainStructTypeOpt.value()) {
103 SymbolTableCollection symbolTables;
104 return st.getDefinition(symbolTables, op);
105 }
106 }
107 return failure();
108}
109
110} // namespace
111
112LogicalResult LLZKDialect::verifyOperationAttribute(Operation *op, NamedAttribute attr) {
113 if (attr.getName() == MAIN_ATTR_NAME) {
114 return verifyLlzkMainAttr(op, attr.getValue());
115 }
116 return success();
117}
118
119auto LLZKDialect::initialize() -> void {
120 // clang-format off
121 // Suppress false positive from `clang-tidy`
122 // NOLINTNEXTLINE(clang-analyzer-core.StackAddressEscape)
123 addAttributes<
124 #define GET_ATTRDEF_LIST
126 >();
127
128 addOperations<
129 #define GET_OP_LIST
131 >();
132 // clang-format on
133 addInterfaces<LLZKDialectBytecodeInterfaceImpl>();
134}
::llvm::LogicalResult verifyOperationAttribute(::mlir::Operation *op, ::mlir::NamedAttribute attribute) override
Provides a hook for verifying dialect attributes attached to the given op.
Definition Dialect.cpp:112
void writeAPInt(mlir::DialectBytecodeWriter &writer, const llvm::APInt &value)
Write an APInt with its bit width, so the bytecode reader can use MLIR's native APInt payload encodin...
Definition Versioning.h:44
mlir::FailureOr< llvm::APInt > readAPInt(mlir::DialectBytecodeReader &reader)
Read an APInt written by writeAPInt.
Definition Versioning.h:50
FailureOr< StructType > getTypeFromLlzkMainAttr(ModuleOp op, Attribute attr)
Definition Attrs.cpp:24
constexpr char MAIN_ATTR_NAME[]
Name of the attribute on the top-level ModuleOp that specifies the type of the main struct.
Definition Constants.h:37
This implements the bytecode interface for the LLZK dialect.
Definition Versioning.h:63
LLZKDialectBytecodeInterface(mlir::Dialect *dia)
Definition Versioning.h:65