LLZK 0.1.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Ops.td
Go to the documentation of this file.
1//===-- Ops.td ---------------------------------------------*- tablegen -*-===//
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#ifndef LLZK_POD_OPS
11#define LLZK_POD_OPS
12
13include "llzk/Dialect/POD/IR/Dialect.td"
14include "llzk/Dialect/POD/IR/Types.td"
15include "llzk/Dialect/Shared/OpTraits.td"
16
17include "mlir/IR/OpBase.td"
18include "mlir/IR/OpAsmInterface.td"
19include "mlir/IR/SymbolInterfaces.td"
20include "mlir/Interfaces/SideEffectInterfaces.td"
21
22class PODDialectOp<string mnemonic, list<Trait> traits = []>
23 : Op<PODDialect, mnemonic, traits>;
24
25def LLZK_NewPodOp
26 : PODDialectOp<"new", [Pure, AttrSizedOperandSegments,
27 VerifySizesForMultiAffineOps<1>,
28 DeclareOpInterfaceMethods<
29 OpAsmOpInterface, ["getAsmResultNames"]>]> {
30 let summary = "create a new plain-old-data struct";
31 let description = [{
32 Creates a new, uninitialized, pod instance. Optionally, the user can pass a list of record names and values
33 that initialize the records of the pod. Partial initialization is allowed. All records without
34 an explicit initialization are initialized with nondeterministic values.
35
36 If the types of the pod records have affine map parameters the user can pass values for them similar
37 to how `array.new` does it.
38
39 This operation returns one value of type `PODType` and, if present, the records passed for initialization
40 must form a subset of the records in the type.
41
42 Examples:
43 ```llzk
44 // Empty pod instance
45 %0 = pod.new : !pod.type<[]>
46
47 // Uninitialized/nondeterministic pod instance
48 %0 = pod.new : !pod.type<[@n: !felt.type]>
49
50 // Initialized pod instance
51 %0 = felt.const_felt 1
52 %1 = pod.new { @n = %0 } : !pod.type<[@n: !felt.type]>
53
54 // Another one, but with 2 fields
55 %0 = felt.const_felt 1
56 %1 = felt.inv %0
57 %2 = pod.new { @n = %0, @inv = %1 } : !pod.type<[@n: !felt.type, @inv: !felt.type]>
58
59 // Partial init
60 %0 = felt.const_felt 1
61 %1 = pod.new { @n = %0 } : !pod.type<[@n: !felt.type, @inv: !felt.type]>
62
63 // Affine map args on uninitialized pod instance
64 %0 = arith.constant 1 : index
65 %c = arith.constant 2 : index
66 %1 = pod.new(%0)[%c] : !pod.type<[@a: !array.type<#map, !felt.type>]>
67
68 // Affine map with initialized records
69 %0 = arith.constant 1 : index
70 %c = arith.constant 2 : index
71 %1 = felt.const_felt 5
72 %2 = pod.new { @f = %1 }(%0)[%c] : !pod.type<[@f: !felt.type, @a: !array.type<#map, !felt.type>]>
73 ```
74 }];
75
76 let arguments = (ins
77 // Initialization values
78 Variadic<AnyLLZKType>:$initialValues,
79 DefaultValuedAttr<StrArrayAttr, "{}">:$initializedRecords,
80 // Affine map arguments
81 VariadicOfVariadic<Index, "mapOpGroupSizes">:$mapOperands,
82 DefaultValuedAttr<DenseI32ArrayAttr, "{}">:$numDimsPerMap,
83 DenseI32ArrayAttr:$mapOpGroupSizes);
84 let results = (outs LLZK_PODType:$result);
85 let skipDefaultBuilders = 1;
86 let builders =
87 [OpBuilder<
88 (ins CArg<"::llzk::pod::InitializedRecords", "{}">:$initialValues),
89 [{
90 auto resultType = ::llzk::pod::PodType::fromInitialValues($_builder.getContext(), initialValues);
91 build($_builder, $_state, resultType, initialValues);
92 }]>,
93 OpBuilder<(ins "::llzk::pod::PodType":$resultType,
94 CArg<"::llzk::pod::InitializedRecords", "{}">:$initialValues)>,
95 OpBuilder<(ins "::llzk::pod::PodType":$resultType,
96 "::llvm::ArrayRef<::mlir::ValueRange>":$mapOperands,
97 "::mlir::DenseI32ArrayAttr":$numDimsPerMap,
98 CArg<"::llzk::pod::InitializedRecords", "{}">:$initialValues)>,
99 OpBuilder<
100 (ins "::llzk::pod::PodType":$resultType,
101 "::llvm::ArrayRef<::mlir::ValueRange>":$mapOperands,
102 "::llvm::ArrayRef<int32_t>":$numDimsPerMap,
103 CArg<"::llzk::pod::InitializedRecords", "{}">:$initialValues),
104 [{
105 build($_builder, $_state, resultType, mapOperands,
106 $_builder.getDenseI32ArrayAttr(numDimsPerMap), initialValues);
107 }]>];
108 let hasCustomAssemblyFormat = 1;
109 let hasVerifier = 1;
110
111 let extraClassDeclaration = [{
112 ::mlir::SmallVector<::llzk::pod::RecordValue> getInitializedRecordValues();
113 }];
114}
115
116def LLZK_ReadPodOp : PODDialectOp<"read"> {
117 let summary = "reads the contents of a plain-old-data struct record";
118 let description = [{
119 Reads the current value of a named record from a pod instance.
120 Returns one value of the type of the record.
121
122 The name of the record must be a valid record name for the pod type and the result
123 type must match the type of the record.
124
125 Example:
126 ```llzk
127 %1 = pod.read %0[@sym] : !pod.type<[@sym: !type, ...]>, !type
128 ```
129 }];
130
131 let arguments = (ins Arg<LLZK_PODType, "the pod to read from">:$pod_ref,
132 FlatSymbolRefAttr:$record_name);
133 let results = (outs AnyLLZKType:$result);
134 let assemblyFormat = [{
135 $pod_ref `[` custom<RecordName>($record_name) `]` `:` type($pod_ref) `,` type($result) attr-dict
136 }];
137 let hasVerifier = 1;
138}
139
140def LLZK_WritePodOp : PODDialectOp<"write"> {
141 let summary = "writes content into a plain-old-data struct record";
142 let description = [{
143 Writes a value into a named record of a pod instance. This operation has no result values.
144
145 The name of the record must be a valid record name for the pod type and the source
146 value type must match the type of the record.
147
148 Writing a record that was written or initialized earlier overwrites the previous value.
149
150 Example:
151 ```llzk
152 pod.write %0[@sym] = %1 : !pod.type<[@sym: !type, ...]>, !type
153 ```
154 }];
155
156 let arguments = (ins Arg<LLZK_PODType, "the pod to write into">:$pod_ref,
157 FlatSymbolRefAttr:$record_name, AnyLLZKType:$value);
158
159 let assemblyFormat = [{
160 $pod_ref `[` custom<RecordName>($record_name) `]` `=` $value `:` type($pod_ref) `,` type($value) attr-dict
161 }];
162 let hasVerifier = 1;
163}
164
165#endif // LLZK_POD_OPS