LLZK 2.1.1
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
ValueModel.cpp
Go to the documentation of this file.
1//===-- ValueModel.cpp - llzk-witgen runtime values -------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2026 Project LLZK
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#include "ValueModel.h"
11
12#include "Errors.h"
13#include "WitgenUtils.h"
14
17
18#include <mlir/IR/Operation.h>
19
20#include <llvm/ADT/TypeSwitch.h>
21
22using namespace mlir;
23
24namespace llzk::witgen {
25
27llvm::Expected<bool> asBool(const WitnessVal &value) {
28 if (const auto *boolValue = std::get_if<bool>(&value)) {
29 return *boolValue;
30 }
31 if (std::holds_alternative<std::monostate>(value)) {
32 return makeError("read of uninitialized i1 value");
33 }
34 return makeError("expected i1 value");
35}
36
38llvm::Expected<int64_t> asIndex(const WitnessVal &value) {
39 if (const auto *indexValue = std::get_if<int64_t>(&value)) {
40 return *indexValue;
41 }
42 if (std::holds_alternative<std::monostate>(value)) {
43 return makeError("read of uninitialized index value");
44 }
45 return makeError("expected index value");
46}
47
49llvm::Expected<llvm::DynamicAPInt> asFelt(const WitnessVal &value) {
50 if (const auto *feltValue = std::get_if<llvm::DynamicAPInt>(&value)) {
51 return *feltValue;
52 }
53 if (std::holds_alternative<std::monostate>(value)) {
54 return makeError("read of uninitialized felt value");
55 }
56 return makeError("expected felt value");
57}
58
60llvm::Expected<ArrayValueRef> asArray(const WitnessVal &value) {
61 if (const auto *arrayValue = std::get_if<ArrayValueRef>(&value)) {
62 return *arrayValue;
63 }
64 if (std::holds_alternative<std::monostate>(value)) {
65 return makeError("read of uninitialized array value");
66 }
67 return makeError("expected array value");
68}
69
71llvm::Expected<PodValueRef> asPod(const WitnessVal &value) {
72 if (const auto *podValue = std::get_if<PodValueRef>(&value)) {
73 return *podValue;
74 }
75 if (std::holds_alternative<std::monostate>(value)) {
76 return makeError("read of uninitialized POD value");
77 }
78 return makeError("expected pod value");
79}
80
82llvm::Expected<StructValueRef> asStruct(const WitnessVal &value) {
83 if (const auto *structValue = std::get_if<StructValueRef>(&value)) {
84 return *structValue;
85 }
86 if (std::holds_alternative<std::monostate>(value)) {
87 return makeError("read of uninitialized struct value");
88 }
89 return makeError("expected struct value");
90}
91
93llvm::Expected<WitnessVal> defaultValue(
94 Type type, SymbolTableCollection &tables, Operation *origin, const Field &field,
95 UninitializedBehavior behavior, std::mt19937_64 *rng
96) {
97 return llvm::TypeSwitch<Type, llvm::Expected<WitnessVal>>(type)
98 .Case([&](felt::FeltType) -> llvm::Expected<WitnessVal> {
99 if (behavior == UninitializedBehavior::Fail) {
100 return WitnessVal(std::monostate {});
101 }
102 if (behavior == UninitializedBehavior::Random) {
103 if (!rng) {
104 return makeError("missing RNG for random witgen initialization");
105 }
106 return WitnessVal(randomFieldElement(*rng, field));
107 }
108 return field.zero();
109 })
110 .Case([&](IndexType) -> llvm::Expected<WitnessVal> {
111 if (behavior == UninitializedBehavior::Fail) {
112 return WitnessVal(std::monostate {});
113 }
114 if (behavior == UninitializedBehavior::Random) {
115 if (!rng) {
116 return makeError("missing RNG for random witgen initialization");
117 }
118 return int64_t(randomIndexValue(*rng));
119 }
120 return int64_t(0);
121 })
122 .Case([&](IntegerType intType) -> llvm::Expected<WitnessVal> {
123 if (intType.getWidth() == 1) {
124 if (behavior == UninitializedBehavior::Fail) {
125 return WitnessVal(std::monostate {});
126 }
127 if (behavior == UninitializedBehavior::Random) {
128 if (!rng) {
129 return makeError("missing RNG for random witgen initialization");
130 }
131 return randomBoolValue(*rng);
132 }
133 return false;
134 }
135 return makeError("only i1 integer values are supported in llzk-witgen");
136 })
137 .Case([&](array::ArrayType arrayType) -> llvm::Expected<WitnessVal> {
138 auto arrayValue = std::make_shared<ArrayValue>();
139 arrayValue->type = arrayType;
140 arrayValue->elements.reserve(arrayType.getNumElements());
141 for (int64_t i = 0; i < arrayType.getNumElements(); ++i) {
142 auto elem = defaultValue(arrayType.getElementType(), tables, origin, field, behavior, rng);
143 if (!elem) {
144 return elem.takeError();
145 }
146 arrayValue->elements.push_back(*elem);
147 }
148 return arrayValue;
149 })
150 .Case([&](pod::PodType podType) -> llvm::Expected<WitnessVal> {
151 auto podValue = std::make_shared<PodValue>();
152 podValue->type = podType;
153 for (pod::RecordAttr record : podType.getRecords()) {
154 auto recordValue = defaultValue(record.getType(), tables, origin, field, behavior, rng);
155 if (!recordValue) {
156 return recordValue.takeError();
157 }
158 podValue->records[record.getName().getValue()] = *recordValue;
159 }
160 return podValue;
161 })
162 .Case([&](component::StructType structType) -> llvm::Expected<WitnessVal> {
163 auto defLookup = structType.getDefinition(tables, origin);
164 if (failed(defLookup)) {
165 return makeError("could not resolve struct type");
166 }
167 auto structValue = std::make_shared<StructValue>();
168 structValue->type = structType;
169 for (component::MemberDefOp member : defLookup->get().getMemberDefs()) {
170 auto memberValue = defaultValue(member.getType(), tables, origin, field, behavior, rng);
171 if (!memberValue) {
172 return memberValue.takeError();
173 }
174 structValue->members[member.getSymName()] = *memberValue;
175 }
176 return structValue;
177 }).Default([&](Type) -> llvm::Expected<WitnessVal> {
178 return makeError("unsupported type in llzk-witgen");
179 });
180}
181
182} // namespace llzk::witgen
Information about the prime finite field used for the interval analysis.
Definition Field.h:36
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:81
::mlir::Type getElementType() const
::mlir::FailureOr< SymbolLookupResult< StructDefOp > > getDefinition(::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op, bool reportMissing=true) const
Gets the struct op that defines this struct.
Definition Types.cpp:26
::llvm::ArrayRef<::llzk::pod::RecordAttr > getRecords() const
llvm::Expected< PodValueRef > asPod(const WitnessVal &value)
Require a POD value from the runtime variant.
llvm::Expected< bool > asBool(const WitnessVal &value)
Require a boolean value from the runtime variant.
UninitializedBehavior
Control how witgen materializes uninitialized/default values.
Definition ValueModel.h:55
llvm::Expected< WitnessVal > defaultValue(Type type, SymbolTableCollection &tables, Operation *origin, const Field &field, UninitializedBehavior behavior, std::mt19937_64 *rng)
Build a default value for a supported LLZK type.
llvm::DynamicAPInt randomFieldElement(std::mt19937_64 &rng, const Field &field)
Draw a uniformly distributed field element in [0, prime).
bool randomBoolValue(std::mt19937_64 &rng)
Draw a uniformly distributed boolean value.
llvm::Expected< int64_t > asIndex(const WitnessVal &value)
Require an index value from the runtime variant.
int64_t randomIndexValue(std::mt19937_64 &rng)
Draw a uniformly distributed signed index value.
std::variant< std::monostate, bool, int64_t, llvm::DynamicAPInt, ArrayValueRef, PodValueRef, StructValueRef > WitnessVal
Runtime value representation used by the tool-local interpreter.
Definition ValueModel.h:51
llvm::Expected< llvm::DynamicAPInt > asFelt(const WitnessVal &value)
Require a felt value from the runtime variant.
llvm::Error makeError(const llvm::Twine &msg)
Build a string-backed error for user-facing witgen failures.
Definition Errors.h:18
llvm::Expected< StructValueRef > asStruct(const WitnessVal &value)
Require a struct value from the runtime variant.
llvm::Expected< ArrayValueRef > asArray(const WitnessVal &value)
Require an array value from the runtime variant.