LLZK 3.0.0
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
62 static const Field &getField(llvm::StringRef fieldName, EmitErrorFn errFn);
63 inline static const Field &getField(llvm::StringRef fieldName) {
64 return getField(fieldName, nullptr);
65 }
66
67 Field() = delete;
68 Field(const Field &) = default;
69 Field(Field &&) noexcept = default;
70 Field &operator=(const Field &) = default;
71
73 llvm::DynamicAPInt prime() const { return primeMod; }
74
76 llvm::DynamicAPInt half() const { return halfPrime; }
77
79 inline llvm::DynamicAPInt felt(int i) const { return reduce(i); }
80
82 inline llvm::DynamicAPInt zero() const { return felt(0); }
83
85 inline llvm::DynamicAPInt one() const { return felt(1); }
86
88 inline llvm::DynamicAPInt maxVal() const { return prime() - one(); }
89
91 llvm::DynamicAPInt inv(const llvm::DynamicAPInt &i) const;
92
93 llvm::DynamicAPInt inv(const llvm::APInt &i) const;
94
98 llvm::DynamicAPInt reduce(const llvm::DynamicAPInt &i) const;
99 inline llvm::DynamicAPInt reduce(int64_t i) const { return reduce(llvm::DynamicAPInt(i)); }
100 llvm::DynamicAPInt reduce(const llvm::APInt &i) const;
101
106 llvm::DynamicAPInt toSigned(const llvm::DynamicAPInt &i) const;
107
108 inline unsigned bitWidth() const { return bitwidth; }
109
110 inline llvm::StringRef name() const { return primeName; }
111
113 llvm::SMTExprRef createSymbol(const llvm::SMTSolverRef &solver, const char *name) const {
114 return solver->mkSymbol(name, solver->getBitvectorSort(bitWidth()));
115 }
116
118 mlir::IntegerAttr getPrimeAttr(mlir::MLIRContext *context, unsigned bitWidth) const;
119
120 friend bool operator==(const Field &lhs, const Field &rhs) {
121 return lhs.primeMod == rhs.primeMod;
122 }
123
124 friend bool operator<(const Field &lhs, const Field &rhs) {
125 return std::tie(lhs.primeMod, lhs.primeName, lhs.bitwidth, lhs.halfPrime) <
126 std::tie(rhs.primeMod, rhs.primeName, rhs.bitwidth, rhs.halfPrime);
127 }
128
129private:
130 Field(std::string_view primeStr, llvm::StringRef name);
131 Field(const llvm::APInt &primeInt, llvm::StringRef name);
132
134 llvm::StringRef primeName;
135 llvm::DynamicAPInt primeMod, halfPrime;
136 unsigned bitwidth;
137
139 static void initKnownFields();
140
143 static void addField(Field &&f, EmitErrorFn errFn);
144 inline static void addField(Field &&f) { addField(std::move(f), nullptr); }
145};
146
154llvm::LogicalResult addSpecifiedFields(mlir::ModuleOp modOp);
155
157using FieldRef = std::reference_wrapper<const Field>;
158
160using FieldSet = llvm::SmallSet<FieldRef, 2>;
161
167mlir::LogicalResult collectFields(mlir::Operation *root, FieldSet &fields, bool silent = true);
168
173std::optional<std::reference_wrapper<const Field>> tryDetectSpecifiedField(mlir::Operation *root);
174
175} // 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:76
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:120
Field()=delete
Field(const Field &)=default
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:82
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:73
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:110
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:85
llvm::DynamicAPInt felt(int i) const
Returns i as a signed field element.
Definition Field.h:79
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:108
friend bool operator<(const Field &lhs, const Field &rhs)
Definition Field.h:124
llvm::DynamicAPInt reduce(int64_t i) const
Definition Field.h:99
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:113
static const Field & getField(llvm::StringRef fieldName)
Definition Field.h:63
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:88
std::reference_wrapper< const Field > FieldRef
Typealias for a stable reference to a known Field.
Definition Field.h:157
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:160
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