LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Attrs.td
Go to the documentation of this file.
1//===-- Attrs.td -------------------------------------------*- tablegen -*-===//
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#ifndef LLZK_FELT_ATTRS
11#define LLZK_FELT_ATTRS
12
13include "llzk/Dialect/Felt/IR/Dialect.td"
14include "llzk/Dialect/LLZK/IR/AttributeHelper.td"
15
16include "mlir/IR/AttrTypeBase.td"
17include "mlir/IR/BuiltinAttributeInterfaces.td"
18
19def LLZK_FeltConstAttr
20 : AttrDef<FeltDialect, "FeltConst", [TypedAttrInterface]> {
21 let mnemonic = "const";
22 let summary = "finite field element";
23 let description = [{
24 A felt attribute stores an exact signed integer literal and its field type.
25
26 For a specified field with prime modulus `p`, the attribute denotes
27 `rawValue mod p`, regardless of its stored representation (i.e. the raw
28 value). Use `getReducedValue()` to obtain the representative in `[0, p)`
29 when the type specifies a field; gives `std::nullopt` otherwise.
30
31 Builders accepting ArrayRef<uint64_t> decode 64-bit parts in
32 least-significant-first order as a two's-complement signed integer. The
33 most significant bit of the last part is the sign bit; an empty array is
34 zero. Callers should append a zero part to represent a positive value whose
35 highest data bit would otherwise be interpreted as the sign bit.
36 }];
37
38 let parameters =
39 (ins DynamicAPIntParameter<"The unreduced felt constant value">:$rawValue,
40 DefaultValuedParameter<"FeltType", "FeltType::get($_ctxt)">:$type);
41
42 let hasCustomAssemblyFormat = 1;
43
44 let builders =
45 [AttrBuilder<
46 (ins "const ::llvm::DynamicAPInt &":$rawValue, "FeltType":$ty),
47 [{ return $_get(context, ::llzk::DynamicAPIntValue(rawValue), ty); }]>,
48 AttrBuilder<
49 (ins "const ::llvm::DynamicAPInt &":$rawValue),
50 [{ return get(context, rawValue, FeltType::get(context)); }]>,
51 AttrBuilder<
52 (ins "const ::llvm::DynamicAPInt &":$rawValue,
53 "::llvm::StringRef":$fieldName),
54 [{ return get(context, rawValue, FeltType::get(context, fieldName)); }]>,
55 AttrBuilder<
56 (ins "::llvm::ArrayRef<uint64_t>":$parts, "FeltType":$ty),
57 [{ return get(context, ::llzk::toSignedDynamicAPInt(parts), ty); }]>,
58 AttrBuilder<
59 (ins "::llvm::ArrayRef<uint64_t>":$parts),
60 [{ return get(context, ::llzk::toSignedDynamicAPInt(parts)); }]>,
61 AttrBuilder<
62 (ins "::llvm::ArrayRef<uint64_t>":$parts,
63 "::llvm::StringRef":$fieldName),
64 [{ return get(context, ::llzk::toSignedDynamicAPInt(parts), fieldName); }]>];
65
66 let extraClassDeclaration = [{
67 /// Returns the field name from the stored FeltType, or a null StringAttr
68 /// if no type is stored.
69 ::mlir::StringAttr getFieldName() const;
70
71 /// If the type specifies a field, returns the field representative in `[0, p)`
72 /// for the signed raw value; gives `std::nullopt` otherwise.
73 std::optional<::llvm::DynamicAPInt> getReducedValue() const;
74
75 /// If the type specifies a field, returns `getReducedValue()`; otherwise `getRawValue()`.
76 /// Use getReducedValue() when folding requires a known field representative.
77 ::llvm::DynamicAPInt getReducedValueOrRaw() const;
78 }];
79}
80
81def LLZK_FieldSpecAttr : AttrDef<FeltDialect, "FieldSpec"> {
82 let mnemonic = "field";
83 let summary = "prime field specification";
84 let description = [{
85 A specification of a prime field for use by felt types.
86 Builders accepting ArrayRef<uint64_t> decode 64-bit parts in
87 least-significant-first order as a two's-complement signed integer. The
88 most significant bit of the last part is the sign bit; an empty array is
89 zero. Callers should append a zero part to ensure the highest data bit
90 (i.e. the sign bit) is zero since the modulus must be positive. A modulus
91 below two is invalid: `getChecked()` emits a diagnostic and returns a null
92 attribute, while `get()` requires a valid modulus.
93
94 These specifications are provided in the `llzk.fields` attribute on the root
95 module as either a single element or a flat array, for example:
96
97 module attributes {llzk.lang, llzk.fields = field<foo, 7> { ... }
98 module attributes {llzk.lang, llzk.fields = [field<>]} { ... }
99
100 Specifications should not be provided for built-in fields, which include:
101 - babybear
102 - bn128/bn254
103 - goldilocks
104 - grumpkin
105 - koalabear
106 - mersenne31
107 }];
108
109 let parameters = (ins "::mlir::StringAttr":$fieldName,
110 DynamicAPIntParameter<"The prime modulus">:$prime);
111
112 // Format is [{ `<` $fieldName `,` $prime `>` }], but with custom parsing
113 // to enable caching of the Field object definition.
114 let hasCustomAssemblyFormat = 1;
115
116 let builders =
117 [AttrBuilder<
118 (ins "::mlir::StringAttr":$fieldName,
119 "const ::llvm::DynamicAPInt &":$prime),
120 [{ return $_get(context, fieldName, ::llzk::DynamicAPIntValue(prime)); }]>,
121 AttrBuilder<(ins "::mlir::StringAttr":$fieldName,
122 "::llvm::ArrayRef<uint64_t>":$parts),
123 [{ return $_get(context, fieldName,
124 ::llzk::DynamicAPIntValue(::llzk::toSignedDynamicAPInt(parts))); }]>,
125 AttrBuilder<
126 (ins "::llvm::StringRef":$fieldName,
127 "::llvm::ArrayRef<uint64_t>":$parts),
128 [{ return $_get(context, ::mlir::StringAttr::get(context, fieldName),
129 ::llzk::DynamicAPIntValue(::llzk::toSignedDynamicAPInt(parts))); }]>];
130 let genVerifyDecl = 1;
131}
132
133#endif // LLZK_FELT_ATTRS