LLZK 0.1.0
Veridise's ZK Language IR
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_ARRAY_TYPES
11#define LLZK_ARRAY_TYPES
12
13include "llzk/Dialect/Array/IR/Dialect.td"
14
15include "mlir/IR/AttrTypeBase.td"
16include "mlir/IR/BuiltinTypes.td"
17include "mlir/Interfaces/MemorySlotInterfaces.td"
18include "mlir/IR/BuiltinTypeInterfaces.td"
19
20def ArrayElemType : Type<CPred<"::llzk::isValidArrayElemType($_self)">,
21 "a valid array element type">;
22
23def LLZK_ArrayType
24 : TypeDef<ArrayDialect, "Array",
25 [ShapedTypeInterface,
26 DeclareTypeInterfaceMethods<DestructurableTypeInterface>]> {
27 let mnemonic = "type";
28 let summary = "n-dimensional array";
29 let description = [{
30 Array type with a ranked shape and homogeneous element type.
31 It can only be instantiated with the following element types:
32 - Any LLZK type
33 - IndexType
34 - Unsigned integers of 1 bit (aka booleans)
35
36 The dimensions of the array are specified using a list of attributes, one
37 per dimension. Each attribute must be one of the following:
38 - IntegerAttr (with IndexType), specifying a fixed dimension size
39 - SymbolRefAttr, specifying a dimension size defined by a struct parameter or
40 global constant
41 - AffineMapAttr, specifying a dimension size computed from surrounding loop
42 induction variables
43
44 ```llzk
45 // Example array of 5 by 2 elements of `Felt` type.
46 !array.type<5,2 x !felt.type>
47
48 // Example array using a struct parameter for one dimension.
49 !array.type<5,@A x index>
50 ```
51 }];
52
53 let parameters =
54 (ins TypeParameter<"::mlir::Type",
55 "Type of all elements within the array.">:$elementType,
56 ArrayRefParameter<
57 "::mlir::Attribute",
58 "List of array dimension size specifiers.">:$dimensionSizes,
59 ArrayRefParameter<"int64_t",
60 "Array shape, for ShapedTypeInterface, computed "
61 "from `$dimensionSizes`.">:$shape);
62
63 // The custom<DerivedShape>() section is 0-length (it is used to compute the
64 // "$shape" attribute from the "$dimensionSizes" attribute) and the `` before
65 // it avoids excess space in the format. Additionally, it is placed right
66 // after parsing "$dimensionSizes" so the source location pointer in the
67 // parser remains at "$dimensionSizes" in case an error occurs during the
68 // conversion.
69 let assemblyFormat = [{
70 `<` custom<AttrVec>($dimensionSizes)
71 `` custom<DerivedShape>($shape, ref($dimensionSizes))
72 `x` $elementType `>`
73 }];
74
75 let genVerifyDecl = 1;
76
77 let skipDefaultBuilders = 1;
78 let builders =
79 [TypeBuilderWithInferredContext<
80 (ins "::mlir::Type":$elementType,
81 "::llvm::ArrayRef<::mlir::Attribute>":$dimensionSizes),
82 [{
83 assert(elementType && "element type cannot be null");
84 ::mlir::MLIRContext *ctx = elementType.getContext();
85 OwningEmitErrorFn emitErrorFn = ::llzk::wrapNullableInFlightDiagnostic(emitError, ctx);
86 auto dimSizesRes = forceIntAttrTypes(dimensionSizes, emitErrorFn);
87 if(::mlir::failed(dimSizesRes)) { return ArrayType(); }
88 ::llvm::SmallVector<::mlir::Attribute> dimSizes = *dimSizesRes;
89 ::llvm::SmallVector<int64_t> shape;
90 ::mlir::LogicalResult res = computeShapeFromDims(emitErrorFn, dimSizes, shape);
91 if(::mlir::failed(res)) { return ArrayType(); }
92 return $_get(ctx, elementType, dimSizes, shape);
93 }]>,
94 TypeBuilderWithInferredContext<(ins "::mlir::Type":$elementType,
95 "::llvm::ArrayRef<int64_t>":$shape),
96 [{
97 assert(elementType && "element type cannot be null");
98 ::mlir::MLIRContext *ctx = elementType.getContext();
99 ::llvm::SmallVector<::mlir::Attribute> dimSizes;
100 ::mlir::LogicalResult res = computeDimsFromShape(ctx, shape, dimSizes);
101 if(::mlir::failed(res)) { return ArrayType(); }
102 return $_get(ctx, elementType, dimSizes, shape);
103 }]>];
104
105 let extraClassDeclaration = [{
106 private:
107 /// Call the given function for each valid index for this ArrayType.
108 /// Return `false` if this ArrayType does not have a static shape.
109 bool collectIndices(::llvm::function_ref<void(::mlir::ArrayAttr)>) const;
110
111 public:
112 /// Return a list of all valid indices for this ArrayType.
113 std::optional<::llvm::SmallVector<::mlir::ArrayAttr>> getSubelementIndices() const;
114
115 /// Returns if this type is ranked, i.e., it has a known number of dimensions.
116 /// LLZK arrays are always ranked, i.e., the number of dimensions is known.
117 /// Required by the ShapedTypeInterface interface.
118 inline bool hasRank() const { return true; }
119
120 /// Clone this type with the given shape and element type. If the
121 /// provided shape is `std::nullopt`, the current shape of the type is used.
122 /// Required by the ShapedTypeInterface interface.
123 ArrayType cloneWith(std::optional<::llvm::ArrayRef<int64_t>> shape, ::mlir::Type elementType) const;
124
125 /// Clone this type with the given dimensions and element type. If the provided
126 /// dimensions are `std::nullopt`, the current dimensions of the type are used.
127 /// Note: This is preferred over cloneWith(..int64_t..) because this Attribute
128 /// version can carry more information than the `int64_t` which must default to
129 /// `kDynamic` when the Attribute is anything other than an integer constant.
130 ArrayType cloneWith(::mlir::Type elementType, std::optional<::llvm::ArrayRef<::mlir::Attribute>> dimensions = std::nullopt) const;
131 }];
132
133 let extraClassDefinition = [{
134 namespace {
135 /// This definition of `emitError` is used by the `get()` functions generated by the
136 /// custom builders for this type. The `getChecked()` functions generated by those same
137 /// builders have a parameter with this same name that shadows this definition so the
138 /// `getChecked()` versions will use the function supplied via the parameter. Regardless,
139 /// `wrapNullableInFlightDiagnostic()` checks for `nullptr` and generates a default if
140 /// necessary. This approach, although a bit hacky, allows a legitimate error function to
141 /// be used whenever available, only reverting to a default in the `get()` function.
142 const ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError = nullptr;
143 }
144 }];
145}
146
147#endif // LLZK_ARRAY_TYPES