LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
OpHelpers.h
Go to the documentation of this file.
1//===-- OpHelpers.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
14#include "llzk/Util/Constants.h"
17
18#include <mlir/IR/BuiltinTypes.h>
19#include <mlir/IR/OpImplementation.h>
20#include <mlir/IR/Operation.h>
21#include <mlir/IR/SymbolTable.h>
22#include <mlir/Support/LogicalResult.h>
23
24#include <llvm/ADT/STLExtras.h>
25#include <llvm/ADT/SmallString.h>
26#include <llvm/ADT/StringRef.h>
27#include <llvm/Support/Debug.h>
28
29namespace llzk {
30
34template <typename OpClass> inline llvm::StringLiteral getOperationName() {
35 return OpClass::getOperationName();
36}
37
40template <typename OpClass> inline OpClass getSelfOrParentOfType(mlir::Operation *op) {
41 if (op) {
42 if (OpClass self = llvm::dyn_cast<OpClass>(op)) {
43 return self;
44 }
45 if (OpClass parent = op->getParentOfType<OpClass>()) {
46 return parent;
47 }
48 }
49 return {};
50}
51
53template <typename OpClass> inline OpClass getParentOfType(mlir::Operation *op) {
54 if (op) {
55 if (OpClass p = op->getParentOfType<OpClass>()) {
56 return p;
57 }
58 }
59 return {};
60}
61
63template <typename TypeClass>
64// Suppress false positive from `clang-tidy`
65// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
67 : public mlir::OpTrait::TraitBase<TypeClass, LLZKSymbolTableImplTrait> {
68public:
69 static mlir::LogicalResult verifyRegionTrait(mlir::Operation *op) {
70 // Note: the current op will be checked by the normal `SymbolTable` trait that is
71 // included in `LLZKSymbolTable`. Checking it here would cause the same error described
72 // in `LLZKSymbolTable`.
73 while ((op = op->getParentWithTrait<mlir::OpTrait::SymbolTable>())) {
74 if (mlir::failed(mlir::detail::verifySymbolTable(op))) {
75 return mlir::failure();
76 }
77 }
78 return mlir::success();
79 }
80};
81
84template <int OperandSegmentIndex> struct VerifySizesForMultiAffineOps {
85 template <typename TypeClass> class Impl : public mlir::OpTrait::TraitBase<TypeClass, Impl> {
86 inline static mlir::LogicalResult verifyHelper(mlir::Operation *op, int32_t segmentSize) {
87 TypeClass c = llvm::cast<TypeClass>(op);
89 op, segmentSize, c.getMapOpGroupSizesAttr(), c.getMapOperands(), c.getNumDimsPerMapAttr()
90 );
91 }
92
93 public:
94 static mlir::LogicalResult verifyTrait(mlir::Operation *op) {
95 if (TypeClass::template hasTrait<mlir::OpTrait::AttrSizedOperandSegments>()) {
96 // If the AttrSizedOperandSegments trait is present, must have `OperandSegmentIndex`.
97 static_assert(
98 OperandSegmentIndex >= 0,
99 "When the `AttrSizedOperandSegments` trait is present, the index of `$mapOperands` "
100 "within the `operandSegmentSizes` attribute must be specified."
101 );
102 mlir::DenseI32ArrayAttr segmentSizes = op->getAttrOfType<mlir::DenseI32ArrayAttr>(
103 mlir::OpTrait::AttrSizedOperandSegments<TypeClass>::getOperandSegmentSizeAttr()
104 );
105 assert(
106 OperandSegmentIndex < segmentSizes.size() &&
107 "Parameter of `VerifySizesForMultiAffineOps` exceeds the number of ODS-declared "
108 "operands"
109 );
110 return verifyHelper(op, segmentSizes[OperandSegmentIndex]);
111 } else {
112 // If the trait is not present, the `OperandSegmentIndex` is ignored. Pass `-1` to indicate
113 // that the checks against `operandSegmentSizes` should be skipped.
114 return verifyHelper(op, -1);
115 }
116 }
117 };
118};
119
120template <unsigned N>
121inline mlir::ParseResult parseDimAndSymbolList(
122 mlir::OpAsmParser &parser,
123 mlir::SmallVector<mlir::OpAsmParser::UnresolvedOperand, N> &mapOperands,
124 mlir::IntegerAttr &numDims
125) {
126 return affineMapHelpers::parseDimAndSymbolList(parser, mapOperands, numDims);
127}
128
130 mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRange mapOperands,
131 mlir::IntegerAttr numDims
132) {
133 return affineMapHelpers::printDimAndSymbolList(printer, op, mapOperands, numDims);
134}
135
136inline mlir::ParseResult parseMultiDimAndSymbolList(
137 mlir::OpAsmParser &parser,
138 mlir::SmallVector<mlir::SmallVector<mlir::OpAsmParser::UnresolvedOperand>> &multiMapOperands,
139 mlir::DenseI32ArrayAttr &numDimsPerMap
140) {
141 return affineMapHelpers::parseMultiDimAndSymbolList(parser, multiMapOperands, numDimsPerMap);
142}
143
145 mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRangeRange multiMapOperands,
146 mlir::DenseI32ArrayAttr numDimsPerMap
147) {
148 return affineMapHelpers::printMultiDimAndSymbolList(printer, op, multiMapOperands, numDimsPerMap);
149}
150
151inline mlir::ParseResult parseAttrDictWithWarnings(
152 mlir::OpAsmParser &parser, mlir::NamedAttrList &extraAttrs, mlir::OperationState &state
153) {
154 return affineMapHelpers::parseAttrDictWithWarnings(parser, extraAttrs, state);
155}
156
157template <typename ConcreteOp>
159 mlir::OpAsmPrinter &printer, ConcreteOp op, mlir::DictionaryAttr extraAttrs,
160 typename mlir::PropertiesSelector<ConcreteOp>::type state
161) {
162 return affineMapHelpers::printAttrDictWithWarnings(printer, op, extraAttrs, state);
163}
164
165inline mlir::ParseResult parseTemplateParams(mlir::AsmParser &parser, mlir::ArrayAttr &value) {
166 mlir::SmallVector<mlir::Attribute> elements;
167 auto parseElement = [&]() -> mlir::ParseResult {
168 // `?` is a wildcard meaning "infer this parameter"; only valid for tvar-restricted params.
169 if (mlir::succeeded(parser.parseOptionalQuestion())) {
170 elements.push_back(parser.getBuilder().getIndexAttr(mlir::ShapedType::kDynamic));
171 return mlir::success();
172 }
173 auto attrParseResult = mlir::FieldParser<mlir::Attribute>::parse(parser);
174 if (mlir::failed(attrParseResult)) {
175 return parser.emitError(
176 parser.getCurrentLocation(), "failed to parse template parameter attribute"
177 );
178 }
179 auto emitError = [&parser] {
180 return llzk::InFlightDiagnosticWrapper(parser.emitError(parser.getCurrentLocation()));
181 };
182 mlir::FailureOr<mlir::Attribute> forced = forceIntAttrType(*attrParseResult, emitError);
183 if (mlir::failed(forced)) {
184 return mlir::failure();
185 }
186 elements.push_back(*forced);
187 return mlir::success();
188 };
189 auto res = parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::Square, parseElement);
190 if (mlir::failed(res)) {
191 return res; // parseElement() already emits a sufficient error message
192 }
193 value = parser.getBuilder().getArrayAttr(elements);
194 return mlir::success();
195}
196
197// 2 parameter version used by types
198inline void printTemplateParams(mlir::AsmPrinter &printer, mlir::ArrayAttr value) {
199 printer << '[';
200 printAttrs(printer, value.getValue(), ", ");
201 printer << ']';
202}
203
204// 3 parameter version used by ops
205inline void printTemplateParams(mlir::AsmPrinter &printer, void *, mlir::ArrayAttr value) {
206 printTemplateParams(printer, value);
207}
208
209} // namespace llzk
Wrapper around InFlightDiagnostic that can either be a regular InFlightDiagnostic or a special versio...
Definition ErrorHelper.h:26
See LLZKSymbolTable ODS documentation for details.
Definition OpHelpers.h:67
static mlir::LogicalResult verifyRegionTrait(mlir::Operation *op)
Definition OpHelpers.h:69
static mlir::LogicalResult verifyTrait(mlir::Operation *op)
Definition OpHelpers.h:94
LogicalResult verifySizesForMultiAffineOps(Operation *op, int32_t segmentSize, ArrayRef< int32_t > mapOpGroupSizes, OperandRangeRange mapOperands, ArrayRef< int32_t > numDimsPerMap)
ParseResult parseMultiDimAndSymbolList(OpAsmParser &parser, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &multiMapOperands, DenseI32ArrayAttr &numDimsPerMap)
ParseResult parseDimAndSymbolList(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &mapOperands, IntegerAttr &numDims)
ParseResult parseAttrDictWithWarnings(OpAsmParser &parser, NamedAttrList &extraAttrs, OperationState &state)
void printMultiDimAndSymbolList(OpAsmPrinter &printer, Operation *, OperandRangeRange multiMapOperands, DenseI32ArrayAttr numDimsPerMap)
void printDimAndSymbolList(OpAsmPrinter &printer, Operation *, OperandRange mapOperands, IntegerAttr numDims)
void printAttrDictWithWarnings(mlir::OpAsmPrinter &printer, ConcreteOp, mlir::DictionaryAttr extraAttrs, typename ConcreteOp::Properties)
FailureOr< Attribute > forceIntAttrType(Attribute attr, EmitErrorFn emitError)
void printTemplateParams(mlir::AsmPrinter &printer, mlir::ArrayAttr value)
Definition OpHelpers.h:198
void printDimAndSymbolList(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRange mapOperands, mlir::IntegerAttr numDims)
Definition OpHelpers.h:129
void printAttrs(AsmPrinter &printer, ArrayRef< Attribute > attrs, const StringRef &separator)
OpClass getParentOfType(mlir::Operation *op)
Return the closest surrounding parent/ancestor operation that is of type 'OpClass'.
Definition OpHelpers.h:53
mlir::ParseResult parseAttrDictWithWarnings(mlir::OpAsmParser &parser, mlir::NamedAttrList &extraAttrs, mlir::OperationState &state)
Definition OpHelpers.h:151
void printMultiDimAndSymbolList(mlir::OpAsmPrinter &printer, mlir::Operation *op, mlir::OperandRangeRange multiMapOperands, mlir::DenseI32ArrayAttr numDimsPerMap)
Definition OpHelpers.h:144
void printAttrDictWithWarnings(mlir::OpAsmPrinter &printer, ConcreteOp op, mlir::DictionaryAttr extraAttrs, typename mlir::PropertiesSelector< ConcreteOp >::type state)
Definition OpHelpers.h:158
mlir::ParseResult parseTemplateParams(mlir::AsmParser &parser, mlir::ArrayAttr &value)
Definition OpHelpers.h:165
mlir::ParseResult parseMultiDimAndSymbolList(mlir::OpAsmParser &parser, mlir::SmallVector< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &multiMapOperands, mlir::DenseI32ArrayAttr &numDimsPerMap)
Definition OpHelpers.h:136
llvm::StringLiteral getOperationName()
Get the operation name, like "constrain.eq" for the given OpClass.
Definition OpHelpers.h:34
OpClass getSelfOrParentOfType(mlir::Operation *op)
Return the closest surrounding parent/ancestor operation that is of type 'OpClass',...
Definition OpHelpers.h:40
mlir::ParseResult parseDimAndSymbolList(mlir::OpAsmParser &parser, mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand, N > &mapOperands, mlir::IntegerAttr &numDims)
Definition OpHelpers.h:121
Produces errors if there is an inconsistency in the various attributes/values that are used to suppor...
Definition OpHelpers.h:84