LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Types.td
Go to the documentation of this file.
1//===-- Types.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_STRUCT_TYPES
11#define LLZK_STRUCT_TYPES
12
13include "llzk/Dialect/Shared/Types.td"
14include "llzk/Dialect/Struct/IR/Dialect.td"
15
16include "mlir/IR/AttrTypeBase.td"
17include "mlir/IR/BuiltinTypes.td"
18include "mlir/Interfaces/MemorySlotInterfaces.td"
19include "mlir/IR/BuiltinTypeInterfaces.td"
20
21class StructDialectType<string name, string typeMnemonic,
22 list<Trait> traits = []>
23 : TypeDef<StructDialect, name, traits> {
24 let mnemonic = typeMnemonic;
25}
26
27def LLZK_StructType : StructDialectType<"Struct", "type"> {
28 let summary = "circuit component";
29 let description = [{
30 Type of a `struct` op instance. Struct values are identity-bearing, pointer-like
31 handles to mutable component instances rather than bags of member values. Copying
32 a struct value copies the handle and preserves the identity of the referenced
33 component; it does not duplicate the component's members, signals, or tables.
34
35 For structs that contain template parameters,
36 the type must contain a list of attributes that instantiate the template
37 parameters, one per parameter. Each attribute must be one of the following:
38 - IntegerAttr (with IndexType), specifying a fixed parameter value; the
39 wildcard (`?`) is not allowed
40 - SymbolRefAttr, specifying a parameter value defined by a struct parameter
41 or global constant
42 - AffineMapAttr, for an array of struct elements whose template parameters
43 vary based on some fixed pattern.
44 - TypeAttr, for specifying a type parameter.
45
46 ```llzk
47 // Type for struct `A` with no parameters.
48 !struct.type<@A>
49
50 // Type for struct `B` with IntegerAttr and SymbolRefAttr parameters.
51 !struct.type<@B<[5, @C]>>
52
53 // Type for struct `C` with TypeAttr and IntegerAttr parameters.
54 !struct.type<@C<[!felt.type, 24]>>
55 ```
56 }];
57
58 let parameters =
59 (ins TypeParameter<
60 "::mlir::SymbolRefAttr",
61 "Fully-qualified name of the struct definition.">:$nameRef,
62 OptionalParameter<"::mlir::ArrayAttr", "Struct parameters">:$params);
63
64 let assemblyFormat =
65 [{ `<` $nameRef ( `<` custom<TemplateParams>($params)^ `>` )? `>` }];
66
67 let genVerifyDecl = 1;
68
69 let skipDefaultBuilders = 1;
70 let builders = [TypeBuilderWithInferredContext<
71 (ins "::mlir::SymbolRefAttr":$structName), [{
72 return $_get(structName.getContext(), structName, ::mlir::ArrayAttr());
73 }]>,
74 TypeBuilderWithInferredContext<
75 (ins "::mlir::SymbolRefAttr":$structName,
76 "::mlir::ArrayAttr":$params),
77 [{
78 ::mlir::MLIRContext *ctx = structName.getContext();
79 if (params) {
80 OwningEmitErrorFn emitErrorFn = ::llzk::wrapNullableInFlightDiagnostic(emitError, ctx);
81 auto paramsRes = forceIntAttrTypes(params.getValue(), emitErrorFn);
82 if(::mlir::failed(paramsRes)) { return StructType(); }
83 params = ::mlir::ArrayAttr::get(ctx, *paramsRes);
84 }
85 return $_get(ctx, structName, params);
86 }]>,
87 TypeBuilderWithInferredContext<
88 (ins "::mlir::SymbolRefAttr":$structName,
89 "::llvm::ArrayRef<::mlir::Attribute>":$paramsRef),
90 [{
91 ::mlir::MLIRContext *ctx = structName.getContext();
92 OwningEmitErrorFn emitErrorFn = ::llzk::wrapNullableInFlightDiagnostic(emitError, ctx);
93 auto paramsRes = forceIntAttrTypes(paramsRef, emitErrorFn);
94 if(::mlir::failed(paramsRes)) { return StructType(); }
95 return $_get(ctx, structName, ::mlir::ArrayAttr::get(ctx, *paramsRes));
96 }]>];
97
98 let extraClassDeclaration = [{
99 /// Gets the `struct` op that defines this struct. Provided `op` is
100 /// used as a starting point for the lookup. Should not be assumed to
101 /// be non-`null` as we don't verify all types during verification.
102 ::mlir::FailureOr<SymbolLookupResult<StructDefOp>> getDefinition
103 (::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op, bool reportMissing = true) const;
104
105 // Verifies that this type references a valid struct, relative to the given `op`.
106 ::mlir::LogicalResult verifySymbolRef(::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op);
107
108 /// Returns wether the struct this type refers to has members marked as columns.
109 /// A lookup is necessary first and will forward the failure state if it fails.
110 mlir::LogicalResult hasColumns(mlir::SymbolTableCollection &symbolTable, mlir::Operation *op) const;
111 }];
112
113 let extraClassDefinition = [{
114 namespace {
115 /// This definition of `emitError` is used by the `get()` functions generated by the
116 /// custom builders for this type. The `getChecked()` functions generated by those same
117 /// builders have a parameter with this same name that shadows this definition so the
118 /// `getChecked()` versions will use the function supplied via the parameter. Regardless,
119 /// `wrapNullableInFlightDiagnostic()` checks for `nullptr` and generates a default if
120 /// necessary. This approach, although a bit hacky, allows a legitimate error function to
121 /// be used whenever available, only reverting to a default in the `get()` function.
122 const ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError = nullptr;
123 }
124 }];
125}
126
127#endif // LLZK_STRUCT_TYPES