LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
TypeHelper.h
Go to the documentation of this file.
1//===-- TypeHelper.h --------------------------------------------*- C++ -*-===//
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#pragma once
11
13
14#include <mlir/IR/OpImplementation.h>
15#include <mlir/IR/Operation.h>
16#include <mlir/IR/SymbolTable.h>
17
18#include <llvm/ADT/ArrayRef.h>
19#include <llvm/ADT/DenseMap.h>
20#include <llvm/ADT/StringRef.h>
21
22namespace llzk {
23
24// Forward declarations
25namespace component {
26class StructType;
27} // namespace component
28namespace array {
29class ArrayType;
30} // namespace array
31namespace pod {
32class PodType;
33} // namespace pod
34
39class BuildShortTypeString {
40 static constexpr char PLACEHOLDER = '\x1A';
41
42 std::string ret;
43 llvm::raw_string_ostream ss;
44
45 BuildShortTypeString() : ret(), ss(ret) {}
46 BuildShortTypeString &append(mlir::Type);
47 BuildShortTypeString &append(mlir::ArrayRef<mlir::Attribute>);
48 BuildShortTypeString &append(mlir::Attribute);
49
50 void appendSymRef(mlir::SymbolRefAttr);
51 void appendSymName(mlir::StringRef);
52
53public:
55 static inline std::string from(mlir::Type type) {
56 return BuildShortTypeString().append(type).ret;
57 }
58
61 static inline std::string from(mlir::ArrayRef<mlir::Attribute> attrs) {
62 return BuildShortTypeString().append(attrs).ret;
63 }
64
72 static std::string from(const std::string &base, mlir::ArrayRef<mlir::Attribute> attrs);
73};
74
75// This function asserts that the given Attribute kind is legal within the LLZK types that can
76// contain Attribute parameters (i.e., ArrayType, StructType, and TypeVarType). This should be used
77// in any function that examines the attribute parameters within parameterized LLZK types to ensure
78// that the function handles all possible cases properly, especially if more legal attributes are
79// added in the future. Throw a fatal error if anything illegal is found, indicating that the caller
80// of this function should be updated.
81void assertValidAttrForParamOfType(mlir::Attribute attr);
82
84bool isValidType(mlir::Type type);
85
89 mlir::Type type, mlir::SymbolTableCollection &symbolTable, mlir::Operation *op
90);
91
93bool isValidGlobalType(mlir::Type type);
94
96bool isValidEmitEqType(mlir::Type type);
97
99bool isValidConstReadType(mlir::Type type);
100
102bool isValidArrayElemType(mlir::Type type);
103
105bool isValidArrayType(mlir::Type type);
106
112bool isConcreteType(mlir::Type type, bool allowStructParams = true);
113
120bool isTypeVarFreeType(mlir::Type type);
121
123enum class AttrConcreteness : std::uint8_t {
127};
128
136AttrConcreteness classifyAttrConcreteness(mlir::Attribute attr, bool allowStructParams = true);
137
139inline bool isConcreteStructParamAttr(mlir::Attribute attr, bool allowStructParams = true) {
140 return classifyAttrConcreteness(attr, allowStructParams) == AttrConcreteness::Concrete;
141}
142
143inline mlir::LogicalResult checkValidType(EmitErrorFn emitError, mlir::Type type) {
144 if (!isValidType(type)) {
145 return emitError() << "expected a valid LLZK type but found " << type;
146 } else {
147 return mlir::success();
148 }
149}
150
152bool hasAffineMapAttr(mlir::Type type);
153
154enum class Side : std::uint8_t { EMPTY = 0, LHS, RHS, TOMB };
155static inline mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const Side &val) {
156 switch (val) {
157 case Side::EMPTY:
158 os << "EMPTY";
159 break;
160 case Side::TOMB:
161 os << "TOMB";
162 break;
163 case Side::LHS:
164 os << "LHS";
165 break;
166 case Side::RHS:
167 os << "RHS";
168 break;
169 }
170 return os;
171}
172
173inline Side reverse(Side in) {
174 switch (in) {
175 case Side::LHS:
176 return Side::RHS;
177 case Side::RHS:
178 return Side::LHS;
179 default:
180 return in;
181 }
182}
183
184} // namespace llzk
185
186namespace llvm {
187template <> struct DenseMapInfo<llzk::Side> {
188 using T = llzk::Side;
189 static inline T getEmptyKey() { return T::EMPTY; }
190 static inline T getTombstoneKey() { return T::TOMB; }
191 static unsigned getHashValue(const T &val) {
192 using UT = std::underlying_type_t<T>;
193 return llvm::DenseMapInfo<UT>::getHashValue(static_cast<UT>(val));
194 }
195 static bool isEqual(const T &lhs, const T &rhs) { return lhs == rhs; }
196};
197} // namespace llvm
198
199namespace llzk {
200
201bool isDynamic(mlir::IntegerAttr intAttr);
202
210
213uint64_t computeEmitEqCardinality(mlir::Type type);
214
223using UnificationMap = mlir::DenseMap<std::pair<mlir::SymbolRefAttr, Side>, mlir::Attribute>;
224
228 const mlir::ArrayRef<mlir::Attribute> &lhsParams,
229 const mlir::ArrayRef<mlir::Attribute> &rhsParams, UnificationMap *unifications = nullptr
230);
231
235 const mlir::ArrayAttr &lhsParams, const mlir::ArrayAttr &rhsParams,
236 UnificationMap *unifications = nullptr
237);
238
243 mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {}, UnificationMap *unifications = nullptr
244);
245
250 mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {}, UnificationMap *unifications = nullptr
251);
252
256 pod::PodType lhs, pod::PodType rhs, mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {},
257 UnificationMap *unifications = nullptr
258);
259
263 mlir::FunctionType lhs, mlir::FunctionType rhs,
264 mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {}, UnificationMap *unifications = nullptr
265);
266
270 mlir::Type lhs, mlir::Type rhs, mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {},
271 UnificationMap *unifications = nullptr
272);
273
276template <typename Iter1, typename Iter2>
277inline bool typeListsUnify(
278 Iter1 lhs, Iter2 rhs, mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {},
279 UnificationMap *unifications = nullptr
280) {
281 return (lhs.size() == rhs.size()) &&
282 std::equal(lhs.begin(), lhs.end(), rhs.begin(), [&](mlir::Type a, mlir::Type b) {
283 return typesUnify(a, b, rhsReversePrefix, unifications);
284 });
285}
286
287template <typename Iter1, typename Iter2>
289 Iter1 lhs, Iter2 rhs, mlir::ArrayRef<llvm::StringRef> rhsReversePrefix = {},
290 UnificationMap *unifications = nullptr
291) {
292 return lhs.size() == 1 && rhs.size() == 1 &&
293 typesUnify(lhs.front(), rhs.front(), rhsReversePrefix, unifications);
294}
295
303 mlir::Type oldTy, mlir::Type newTy,
304 llvm::function_ref<bool(mlir::Type oldTy, mlir::Type newTy)> knownOldToNew = nullptr
305);
306
307template <typename TypeClass> inline TypeClass getIfSingleton(mlir::TypeRange types) {
308 return (types.size() == 1) ? llvm::dyn_cast<TypeClass>(types.front()) : nullptr;
309}
310
311template <typename TypeClass> inline TypeClass getAtIndex(mlir::TypeRange types, size_t index) {
312 return (types.size() > index) ? llvm::dyn_cast<TypeClass>(types[index]) : nullptr;
313}
314
316mlir::FailureOr<mlir::IntegerAttr> forceIntType(mlir::IntegerAttr attr, EmitErrorFn emitError);
317
319mlir::FailureOr<mlir::Attribute> forceIntAttrType(mlir::Attribute attr, EmitErrorFn emitError);
320
322mlir::FailureOr<llvm::SmallVector<mlir::Attribute>>
323forceIntAttrTypes(llvm::ArrayRef<mlir::Attribute> attrList, EmitErrorFn emitError);
324
326mlir::LogicalResult verifyIntAttrType(EmitErrorFn emitError, mlir::Attribute in);
327
329mlir::LogicalResult verifyAffineMapAttrType(EmitErrorFn emitError, mlir::Attribute in);
330
332mlir::LogicalResult verifyStructTypeParams(EmitErrorFn emitError, mlir::ArrayAttr params);
333
335mlir::LogicalResult
336verifyArrayDimSizes(EmitErrorFn emitError, mlir::ArrayRef<mlir::Attribute> dimensionSizes);
337
339mlir::LogicalResult verifyArrayType(
340 EmitErrorFn emitError, mlir::Type elementType, mlir::ArrayRef<mlir::Attribute> dimensionSizes
341);
342
348mlir::LogicalResult verifySubArrayType(
349 EmitErrorFn emitError, array::ArrayType arrayType, array::ArrayType subArrayType
350);
351
355mlir::LogicalResult verifySubArrayOrElementType(
356 EmitErrorFn emitError, array::ArrayType arrayType, mlir::Type subArrayOrElemType
357);
358
361bool isFeltOrSimpleFeltAggregate(mlir::Type ty);
362
366bool isValidMainSignalType(mlir::Type pType);
367
368} // namespace llzk
static std::string from(mlir::ArrayRef< mlir::Attribute > attrs)
Return a brief string representation of the attribute list from a parameterized type.
Definition TypeHelper.h:61
static std::string from(const std::string &base, mlir::ArrayRef< mlir::Attribute > attrs)
Take an existing name prefix/base that contains N>=0 PLACEHOLDER character(s) and the Attribute list ...
static std::string from(mlir::Type type)
Return a brief string representation of the given LLZK type.
Definition TypeHelper.h:55
LogicalResult verifyAffineMapAttrType(EmitErrorFn emitError, Attribute in)
void assertValidAttrForParamOfType(Attribute attr)
LogicalResult verifySubArrayType(EmitErrorFn emitError, ArrayType arrayType, ArrayType subArrayType)
Determine if the subArrayType is a valid subarray of arrayType.
FailureOr< Attribute > forceIntAttrType(Attribute attr, EmitErrorFn emitError)
uint64_t computeEmitEqCardinality(Type type)
bool isValidArrayType(Type type)
LogicalResult verifyIntAttrType(EmitErrorFn emitError, Attribute in)
bool typeListsUnify(Iter1 lhs, Iter2 rhs, mlir::ArrayRef< llvm::StringRef > rhsReversePrefix={}, UnificationMap *unifications=nullptr)
Return true iff the two lists of Type instances are equivalent or could be equivalent after full inst...
Definition TypeHelper.h:277
bool isConcreteType(Type type, bool allowStructParams)
bool isValidArrayElemType(Type type)
TypeClass getIfSingleton(mlir::TypeRange types)
Definition TypeHelper.h:307
bool isValidGlobalType(Type type)
AttrConcreteness
Concreteness classification for an argument to a parameterized struct type.
Definition TypeHelper.h:123
FailureOr< IntegerAttr > forceIntType(IntegerAttr attr, EmitErrorFn emitError)
Convert an IntegerAttr with a type other than IndexType to use IndexType.
bool singletonTypeListsUnify(Iter1 lhs, Iter2 rhs, mlir::ArrayRef< llvm::StringRef > rhsReversePrefix={}, UnificationMap *unifications=nullptr)
Definition TypeHelper.h:288
bool structTypesUnify(StructType lhs, StructType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
LogicalResult verifyArrayType(EmitErrorFn emitError, Type elementType, ArrayRef< Attribute > dimensionSizes)
bool isFeltOrSimpleFeltAggregate(Type ty)
LogicalResult verifySubArrayOrElementType(EmitErrorFn emitError, ArrayType arrayType, Type subArrayOrElemType)
bool isValidColumnType(Type type, SymbolTableCollection &symbolTable, Operation *op)
bool isValidMainSignalType(Type pType)
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
Definition TypeHelper.h:223
llvm::function_ref< InFlightDiagnosticWrapper()> EmitErrorFn
Callback to produce an error diagnostic.
FailureOr< SmallVector< Attribute > > forceIntAttrTypes(ArrayRef< Attribute > attrList, EmitErrorFn emitError)
AttrConcreteness classifyAttrConcreteness(Attribute attr, bool allowStructParams)
Interval operator<<(const Interval &lhs, const Interval &rhs)
bool podTypesUnify(PodType lhs, PodType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
ArrayType flattenArrayElementType(ArrayType outerArrTy, Type elementType)
bool isValidEmitEqType(Type type)
TypeClass getAtIndex(mlir::TypeRange types, size_t index)
Definition TypeHelper.h:311
bool isValidType(Type type)
bool arrayTypesUnify(ArrayType lhs, ArrayType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool isDynamic(IntegerAttr intAttr)
Side reverse(Side in)
Definition TypeHelper.h:173
bool isTypeVarFreeType(Type type)
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool typeParamsUnify(const ArrayRef< Attribute > &lhsParams, const ArrayRef< Attribute > &rhsParams, UnificationMap *unifications)
bool isConcreteStructParamAttr(mlir::Attribute attr, bool allowStructParams=true)
Return true if attr is a concrete argument for a parameterized struct type.
Definition TypeHelper.h:139
bool isMoreConcreteUnification(Type oldTy, Type newTy, llvm::function_ref< bool(Type oldTy, Type newTy)> knownOldToNew)
bool functionTypesUnify(FunctionType lhs, FunctionType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
LogicalResult verifyStructTypeParams(EmitErrorFn emitError, ArrayAttr params)
bool hasAffineMapAttr(Type type)
mlir::LogicalResult checkValidType(EmitErrorFn emitError, mlir::Type type)
Definition TypeHelper.h:143
bool isValidConstReadType(Type type)
LogicalResult verifyArrayDimSizes(EmitErrorFn emitError, ArrayRef< Attribute > dimensionSizes)
static bool isEqual(const T &lhs, const T &rhs)
Definition TypeHelper.h:195
static unsigned getHashValue(const T &val)
Definition TypeHelper.h:191