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 types:
32 - Any LLZK type
33 - IndexType
34 - Unsigned integers of 1 bit (aka booleans)
35
36 ```llzk
37 // Example array of 5 by 2 elements of `Felt` type.
38 !array.type<5,2 x !felt.type>
39
40 // Example array using a struct parameter for one dimension.
41 !array.type<5,@A x index>
42 ```
43 }];
44
45 let parameters =
46 (ins TypeParameter<"::mlir::Type",
47 "Type of all elements within the array.">:$elementType,
48 ArrayRefParameter<
49 "::mlir::Attribute",
50 "List of array dimension size specifiers.">:$dimensionSizes,
51 ArrayRefParameter<"int64_t",
52 "Array shape, for ShapedTypeInterface, computed "
53 "from `$dimensionSizes`.">:$shape);
54
55 // The custom<DerivedShape>() section is 0-length (it is used to compute the
56 // "$shape" attribute from the "$dimensionSizes" attribute) and the `` before
57 // it avoids excess space in the format. Additionally, it is placed right
58 // after parsing "$dimensionSizes" so the source location pointer in the
59 // parser remains at "$dimensionSizes" in case an error occurs during the
60 // conversion.
61 let assemblyFormat = [{
62 `<` custom<AttrVec>($dimensionSizes)
63 `` custom<DerivedShape>($shape, ref($dimensionSizes))
64 `x` $elementType `>`
65 }];
66
67 let genVerifyDecl = 1;
68
69 let skipDefaultBuilders = 1;
70 let builders =
71 [TypeBuilderWithInferredContext<
72 (ins "::mlir::Type":$elementType,
73 "::llvm::ArrayRef<::mlir::Attribute>":$dimensionSizes),
74 [{
75 assert(elementType && "element type cannot be null");
76 ::llvm::SmallVector<::mlir::Attribute> dimSizes = forceIntAttrTypes(dimensionSizes);
77 ::mlir::MLIRContext *ctx = elementType.getContext();
78 ::llvm::SmallVector<int64_t> shape;
79 ::mlir::LogicalResult res = computeShapeFromDims(emitError, ctx, dimSizes, shape);
80 if(::mlir::failed(res)) { return ArrayType(); }
81 return $_get(ctx, elementType, dimSizes, shape);
82 }]>,
83 TypeBuilderWithInferredContext<(ins "::mlir::Type":$elementType,
84 "::llvm::ArrayRef<int64_t>":$shape),
85 [{
86 assert(elementType && "element type cannot be null");
87 ::mlir::MLIRContext *ctx = elementType.getContext();
88 ::llvm::SmallVector<::mlir::Attribute> dimSizes;
89 ::mlir::LogicalResult res = computeDimsFromShape(ctx, shape, dimSizes);
90 if(::mlir::failed(res)) { return ArrayType(); }
91 return $_get(ctx, elementType, dimSizes, shape);
92 }]>];
93
94 let extraClassDeclaration = [{
95 private:
96 /// Call the given function for each valid index for this ArrayType.
97 /// Return `false` if this ArrayType does not have a static shape.
98 bool collectIndices(::llvm::function_ref<void(::mlir::ArrayAttr)>) const;
99
100 public:
101 /// Return a list of all valid indices for this ArrayType.
102 std::optional<::llvm::SmallVector<::mlir::ArrayAttr>> getSubelementIndices() const;
103
104 /// Returns if this type is ranked, i.e. it has a known number of dimensions.
105 /// LLZK arrays are always ranked, i.e. the number of dimensions is known.
106 /// Required by the ShapedTypeInterface interface.
107 inline bool hasRank() const { return true; }
108
109 /// Clone this type with the given shape and element type. If the
110 /// provided shape is `std::nullopt`, the current shape of the type is used.
111 /// Required by the ShapedTypeInterface interface.
112 ArrayType cloneWith(std::optional<::llvm::ArrayRef<int64_t>> shape, ::mlir::Type elementType) const;
113
114 /// Clone this type with the given dimensions and element type. If the provided
115 /// dimensions are `std::nullopt`, the current dimensions of the type are used.
116 /// Note: This is preferred over cloneWith(..int64_t..) because this Attribute
117 /// version can carry more information than the `int64_t` which must default to
118 /// `kDynamic` when the Attribute is anything other than an integer constant.
119 ArrayType cloneWith(::mlir::Type elementType, std::optional<::llvm::ArrayRef<::mlir::Attribute>> dimensions = std::nullopt) const;
120 }];
121
122 let extraClassDefinition = [{
123 namespace {
124 /// This definition of `emitError` is used by the `get()` functions generated by the
125 /// custom builders for this type. The `getChecked()` functions generated by those same
126 /// builders have a parameter with this same name that shadows this definition so the
127 /// getChecked() versions will use the function supplied via the parameter. Regardless,
128 /// computeShapeFromDims() checks for `nullptr` and generates a default if necessary.
129 /// This approach, although a bit hacky, allows a legitimate error function to be used
130 /// whenever available, only reverting to a default as needed by the `get()` function.
131 const ::llzk::EmitErrorFn emitError = nullptr;
132 }
133 }];
134}
135
136#endif // LLZK_ARRAY_TYPES