LLZK 2.1.1
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Field.h
Go to the documentation of this file.
1//===-- Field.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
10#pragma once
11
14
15#include <mlir/IR/BuiltinAttributes.h>
16#include <mlir/IR/BuiltinOps.h>
17#include <mlir/Support/LLVM.h>
18
19#include <llvm/ADT/DenseMap.h>
20#include <llvm/ADT/DynamicAPInt.h>
21#include <llvm/ADT/SmallSet.h>
22#include <llvm/Support/LogicalResult.h>
23#include <llvm/Support/SMTAPI.h>
24
25#include <functional>
26#include <optional>
27#include <string_view>
28
29namespace llzk {
30
36class Field {
37public:
40 inline static void
41 addField(llvm::StringRef fieldName, const llvm::APInt &prime, EmitErrorFn errFn) {
42 return addField(Field(prime, fieldName), errFn);
43 }
44 inline static void
45 addField(llvm::StringRef fieldName, llvm::StringRef primeStr, EmitErrorFn errFn) {
46 return addField(Field(primeStr, fieldName), errFn);
47 }
48
52 static llvm::FailureOr<std::reference_wrapper<const Field>>
53 tryGetField(llvm::StringRef fieldName);
54
56 static llvm::LogicalResult verifyFieldDefined(llvm::StringRef fieldName, EmitErrorFn errFn);
57
61 static const Field &getField(llvm::StringRef fieldName, EmitErrorFn errFn);
62 inline static const Field &getField(llvm::StringRef fieldName) {
63 return getField(fieldName, nullptr);
64 }
65
66 Field() = delete;
67 Field(const Field &) = default;
68 Field(Field &&) noexcept = default;
69 Field &operator=(const Field &) = default;
70
72 llvm::DynamicAPInt prime() const { return primeMod; }
73
75 llvm::DynamicAPInt half() const { return halfPrime; }
76
78 inline llvm::DynamicAPInt felt(int i) const { return reduce(i); }
79
81 inline llvm::DynamicAPInt zero() const { return felt(0); }
82
84 inline llvm::DynamicAPInt one() const { return felt(1); }
85
87 inline llvm::DynamicAPInt maxVal() const { return prime() - one(); }
88
90 llvm::DynamicAPInt inv(const llvm::DynamicAPInt &i) const;
91
92 llvm::DynamicAPInt inv(const llvm::APInt &i) const;
93
97 llvm::DynamicAPInt reduce(const llvm::DynamicAPInt &i) const;
98 inline llvm::DynamicAPInt reduce(int64_t i) const { return reduce(llvm::DynamicAPInt(i)); }
99 llvm::DynamicAPInt reduce(const llvm::APInt &i) const;
100
105 llvm::DynamicAPInt toSigned(const llvm::DynamicAPInt &i) const;
106
107 inline unsigned bitWidth() const { return bitwidth; }
108
109 inline llvm::StringRef name() const { return primeName; }
110
112 llvm::SMTExprRef createSymbol(const llvm::SMTSolverRef &solver, const char *name) const {
113 return solver->mkSymbol(name, solver->getBitvectorSort(bitWidth()));
114 }
115
117 mlir::IntegerAttr getPrimeAttr(mlir::MLIRContext *context, unsigned bitWidth) const;
118
119 friend bool operator==(const Field &lhs, const Field &rhs) {
120 return lhs.primeMod == rhs.primeMod;
121 }
122
123 friend bool operator<(const Field &lhs, const Field &rhs) {
124 return std::tie(lhs.primeMod, lhs.primeName, lhs.bitwidth, lhs.halfPrime) <
125 std::tie(rhs.primeMod, rhs.primeName, rhs.bitwidth, rhs.halfPrime);
126 }
127
128private:
129 Field(std::string_view primeStr, llvm::StringRef name);
130 Field(const llvm::APInt &primeInt, llvm::StringRef name);
131
133 llvm::StringRef primeName;
134 llvm::DynamicAPInt primeMod, halfPrime;
135 unsigned bitwidth;
136
138 static void initKnownFields();
139
142 static void addField(Field &&f, EmitErrorFn errFn);
143 inline static void addField(Field &&f) { addField(std::move(f), nullptr); }
144};
145
153llvm::LogicalResult addSpecifiedFields(mlir::ModuleOp modOp);
154
156using FieldRef = std::reference_wrapper<const Field>;
157
159using FieldSet = llvm::SmallSet<FieldRef, 2>;
160
166mlir::LogicalResult collectFields(mlir::Operation *root, FieldSet &fields, bool silent = true);
167
172std::optional<std::reference_wrapper<const Field>> tryDetectSpecifiedField(mlir::Operation *root);
173
174} // namespace llzk
This file implements helper methods for constructing DynamicAPInts.
Information about the prime finite field used for the interval analysis.
Definition Field.h:36
static void addField(llvm::StringRef fieldName, llvm::StringRef primeStr, EmitErrorFn errFn)
Definition Field.h:45
llvm::DynamicAPInt half() const
Returns p / 2.
Definition Field.h:75
mlir::IntegerAttr getPrimeAttr(mlir::MLIRContext *context, unsigned bitWidth) const
Return the field prime modulus materialized as an integer attribute at bitWidth.
Definition Field.cpp:149
static llvm::FailureOr< std::reference_wrapper< const Field > > tryGetField(llvm::StringRef fieldName)
Get a Field from a given field name string, or failure if the field is not defined.
Definition Field.cpp:56
friend bool operator==(const Field &lhs, const Field &rhs)
Definition Field.h:119
Field()=delete
Field(const Field &)=default
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:81
llvm::DynamicAPInt toSigned(const llvm::DynamicAPInt &i) const
Converts a canonical field element to its signed integer representation: toSigned(f) = f if f < field...
Definition Field.cpp:141
llvm::DynamicAPInt prime() const
For the prime field p, returns p.
Definition Field.h:72
llvm::DynamicAPInt reduce(const llvm::DynamicAPInt &i) const
Returns i mod p and reduces the result into the appropriate bitwidth.
llvm::StringRef name() const
Definition Field.h:109
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:84
llvm::DynamicAPInt felt(int i) const
Returns i as a signed field element.
Definition Field.h:78
llvm::DynamicAPInt reduce(const llvm::APInt &i) const
llvm::DynamicAPInt inv(const llvm::DynamicAPInt &i) const
Returns the multiplicative inverse of i in prime field p.
unsigned bitWidth() const
Definition Field.h:107
friend bool operator<(const Field &lhs, const Field &rhs)
Definition Field.h:123
llvm::DynamicAPInt reduce(int64_t i) const
Definition Field.h:98
llvm::SMTExprRef createSymbol(const llvm::SMTSolverRef &solver, const char *name) const
Create a SMT solver symbol with the current field's bitwidth.
Definition Field.h:112
static const Field & getField(llvm::StringRef fieldName)
Definition Field.h:62
llvm::DynamicAPInt inv(const llvm::APInt &i) const
static llvm::LogicalResult verifyFieldDefined(llvm::StringRef fieldName, EmitErrorFn errFn)
Search for a field with the given name, reporting an error if the field is not found.
Definition Field.cpp:67
static const Field & getField(llvm::StringRef fieldName, EmitErrorFn errFn)
Get a Field from a given field name string.
Field(Field &&) noexcept=default
static void addField(llvm::StringRef fieldName, const llvm::APInt &prime, EmitErrorFn errFn)
Add a new field to the set of available prime fields.
Definition Field.h:41
llvm::DynamicAPInt maxVal() const
Returns p - 1, which is the max value possible in a prime field described by p.
Definition Field.h:87
std::reference_wrapper< const Field > FieldRef
Typealias for a stable reference to a known Field.
Definition Field.h:156
llvm::function_ref< InFlightDiagnosticWrapper()> EmitErrorFn
Callback to produce an error diagnostic.
LogicalResult addSpecifiedFields(ModuleOp modOp)
Definition Field.cpp:193
llvm::SmallSet< FieldRef, 2 > FieldSet
Typealias for a set of Fields.
Definition Field.h:159
std::optional< std::reference_wrapper< const Field > > tryDetectSpecifiedField(mlir::Operation *root)
Try to detect a uniquely used field from the enclosing LLZK module.
mlir::LogicalResult collectFields(mlir::Operation *root, FieldSet &fields, bool silent=true)
Collects all the fields used in a circuit.
Definition Field.cpp:264