LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
SMTOps.cpp
Go to the documentation of this file.
1//===- SMTOps.cpp ---------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "llvm/ADT/APSInt.h"
12#include "mlir/IR/Builders.h"
13#include "mlir/IR/OpImplementation.h"
14
15using namespace mlir;
16using namespace llzk::smt;
17using namespace mlir;
18
19//===----------------------------------------------------------------------===//
20// BVConstantOp
21//===----------------------------------------------------------------------===//
22
24 mlir::MLIRContext *context, std::optional<mlir::Location> location, ::mlir::ValueRange operands,
25 ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties,
26 ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes
27) {
28 inferredReturnTypes.push_back(properties.as<Properties *>()->getValue().getType());
29 return success();
30}
31
32void BVConstantOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
33 SmallVector<char, 128> specialNameBuffer;
34 llvm::raw_svector_ostream specialName(specialNameBuffer);
35 specialName << "c" << getValue().getValue() << "_bv" << getValue().getValue().getBitWidth();
36 setNameFn(getResult(), specialName.str());
37}
38
39OpFoldResult BVConstantOp::fold(FoldAdaptor adaptor) {
40 assert(adaptor.getOperands().empty() && "constant has no operands");
41 return getValueAttr();
42}
43
44//===----------------------------------------------------------------------===//
45// DeclareFunOp
46//===----------------------------------------------------------------------===//
47
48void DeclareFunOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
49 setNameFn(getResult(), getNamePrefix().has_value() ? *getNamePrefix() : "");
50}
51
52//===----------------------------------------------------------------------===//
53// SolverOp
54//===----------------------------------------------------------------------===//
55
56LogicalResult SolverOp::verifyRegions() {
57 if (getBody()->getTerminator()->getOperands().getTypes() != getResultTypes()) {
58 return emitOpError() << "types of yielded values must match return values";
59 }
60 if (getBody()->getArgumentTypes() != getInputs().getTypes()) {
61 return emitOpError() << "block argument types must match the types of the 'inputs'";
62 }
63
64 return success();
65}
66
67//===----------------------------------------------------------------------===//
68// CheckOp
69//===----------------------------------------------------------------------===//
70
71LogicalResult CheckOp::verifyRegions() {
72 if (getSatRegion().front().getTerminator()->getOperands().getTypes() != getResultTypes()) {
73 return emitOpError() << "types of yielded values in 'sat' region must "
74 "match return values";
75 }
76 if (getUnknownRegion().front().getTerminator()->getOperands().getTypes() != getResultTypes()) {
77 return emitOpError() << "types of yielded values in 'unknown' region must "
78 "match return values";
79 }
80 if (getUnsatRegion().front().getTerminator()->getOperands().getTypes() != getResultTypes()) {
81 return emitOpError() << "types of yielded values in 'unsat' region must "
82 "match return values";
83 }
84
85 return success();
86}
87
88//===----------------------------------------------------------------------===//
89// EqOp
90//===----------------------------------------------------------------------===//
91
92static LogicalResult
93parseSameOperandTypeVariadicToBoolOp(OpAsmParser &parser, OperationState &result) {
94 SmallVector<OpAsmParser::UnresolvedOperand, 4> inputs;
95 SMLoc loc = parser.getCurrentLocation();
96 Type type;
97
98 if (parser.parseOperandList(inputs) || parser.parseOptionalAttrDict(result.attributes) ||
99 parser.parseColon() || parser.parseType(type)) {
100 return failure();
101 }
102
103 result.addTypes(BoolType::get(parser.getContext()));
104 if (parser.resolveOperands(
105 inputs, SmallVector<Type>(inputs.size(), type), loc, result.operands
106 )) {
107 return failure();
108 }
109
110 return success();
111}
112
113ParseResult EqOp::parse(OpAsmParser &parser, OperationState &result) {
114 return parseSameOperandTypeVariadicToBoolOp(parser, result);
115}
116
117void EqOp::print(OpAsmPrinter &printer) {
118 printer << ' ' << getInputs();
119 printer.printOptionalAttrDict(getOperation()->getAttrs());
120 printer << " : " << getInputs().front().getType();
121}
122
123LogicalResult EqOp::verify() {
124 if (getInputs().size() < 2) {
125 return emitOpError() << "'inputs' must have at least size 2, but got " << getInputs().size();
126 }
127
128 return success();
129}
130
131//===----------------------------------------------------------------------===//
132// DistinctOp
133//===----------------------------------------------------------------------===//
134
135ParseResult DistinctOp::parse(OpAsmParser &parser, OperationState &result) {
136 return parseSameOperandTypeVariadicToBoolOp(parser, result);
137}
138
139void DistinctOp::print(OpAsmPrinter &printer) {
140 printer << ' ' << getInputs();
141 printer.printOptionalAttrDict(getOperation()->getAttrs());
142 printer << " : " << getInputs().front().getType();
143}
144
145LogicalResult DistinctOp::verify() {
146 if (getInputs().size() < 2) {
147 return emitOpError() << "'inputs' must have at least size 2, but got " << getInputs().size();
148 }
149
150 return success();
151}
152
153//===----------------------------------------------------------------------===//
154// ExtractOp
155//===----------------------------------------------------------------------===//
156
157LogicalResult ExtractOp::verify() {
158 unsigned rangeWidth = getType().getWidth();
159 unsigned inputWidth = cast<BitVectorType>(getInput().getType()).getWidth();
160 if (getLowBit() + rangeWidth > inputWidth) {
161 return emitOpError(
162 "range to be extracted is too big, expected range "
163 "starting at index "
164 )
165 << getLowBit() << " of length " << rangeWidth << " requires input width of at least "
166 << (getLowBit() + rangeWidth) << ", but the input width is only " << inputWidth;
167 }
168 return success();
169}
170
171//===----------------------------------------------------------------------===//
172// ConcatOp
173//===----------------------------------------------------------------------===//
174
176 MLIRContext *context, std::optional<Location> location, ValueRange operands,
177 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
178 SmallVectorImpl<Type> &inferredReturnTypes
179) {
180 inferredReturnTypes.push_back(
182 context, cast<BitVectorType>(operands[0].getType()).getWidth() +
183 cast<BitVectorType>(operands[1].getType()).getWidth()
184 )
185 );
186 return success();
187}
188
189//===----------------------------------------------------------------------===//
190// RepeatOp
191//===----------------------------------------------------------------------===//
192
193LogicalResult RepeatOp::verify() {
194 unsigned inputWidth = cast<BitVectorType>(getInput().getType()).getWidth();
195 unsigned resultWidth = getType().getWidth();
196 if (resultWidth % inputWidth != 0) {
197 return emitOpError() << "result bit-vector width must be a multiple of the "
198 "input bit-vector width";
199 }
200
201 return success();
202}
203
205 unsigned inputWidth = cast<BitVectorType>(getInput().getType()).getWidth();
206 unsigned resultWidth = getType().getWidth();
207 return resultWidth / inputWidth;
208}
209
210void RepeatOp::build(OpBuilder &builder, OperationState &state, unsigned count, Value input) {
211 unsigned inputWidth = cast<BitVectorType>(input.getType()).getWidth();
212 Type resultTy = BitVectorType::get(builder.getContext(), inputWidth * count);
213 build(builder, state, resultTy, input);
214}
215
216ParseResult RepeatOp::parse(OpAsmParser &parser, OperationState &result) {
217 OpAsmParser::UnresolvedOperand input;
218 Type inputType;
219 llvm::SMLoc countLoc = parser.getCurrentLocation();
220
221 APInt count;
222 if (parser.parseInteger(count) || parser.parseKeyword("times")) {
223 return failure();
224 }
225
226 if (count.isNonPositive()) {
227 return parser.emitError(countLoc) << "integer must be positive";
228 }
229
230 llvm::SMLoc inputLoc = parser.getCurrentLocation();
231 if (parser.parseOperand(input) || parser.parseOptionalAttrDict(result.attributes) ||
232 parser.parseColon() || parser.parseType(inputType)) {
233 return failure();
234 }
235
236 if (parser.resolveOperand(input, inputType, result.operands)) {
237 return failure();
238 }
239
240 auto bvInputTy = dyn_cast<BitVectorType>(inputType);
241 if (!bvInputTy) {
242 return parser.emitError(inputLoc) << "input must have bit-vector type";
243 }
244
245 // Make sure no assertions can trigger and no silent overflows can happen
246 // Bit-width is stored as 'int64_t' parameter in 'BitVectorType'
247 const unsigned maxBw = 63;
248 if (count.getActiveBits() > maxBw) {
249 return parser.emitError(countLoc) << "integer must fit into " << maxBw << " bits";
250 }
251
252 // Store multiplication in an APInt twice the size to not have any overflow
253 // and check if it can be truncated to 'maxBw' bits without cutting of
254 // important bits.
255 APInt resultBw = bvInputTy.getWidth() * count.zext(2 * maxBw);
256 if (resultBw.getActiveBits() > maxBw) {
257 return parser.emitError(countLoc)
258 << "result bit-width (provided integer times bit-width of the input "
259 "type) must fit into "
260 << maxBw << " bits";
261 }
262
263 Type resultTy = BitVectorType::get(parser.getContext(), resultBw.getZExtValue());
264 result.addTypes(resultTy);
265 return success();
266}
267
268void RepeatOp::print(OpAsmPrinter &printer) {
269 printer << " " << getCount() << " times " << getInput();
270 printer.printOptionalAttrDict((*this)->getAttrs());
271 printer << " : " << getInput().getType();
272}
273
274//===----------------------------------------------------------------------===//
275// BoolConstantOp
276//===----------------------------------------------------------------------===//
277
278void BoolConstantOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
279 setNameFn(getResult(), getValue() ? "true" : "false");
280}
281
282OpFoldResult BoolConstantOp::fold(FoldAdaptor adaptor) {
283 assert(adaptor.getOperands().empty() && "constant has no operands");
284 return getValueAttr();
285}
286
287//===----------------------------------------------------------------------===//
288// IntConstantOp
289//===----------------------------------------------------------------------===//
290
291void IntConstantOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
292 SmallVector<char, 32> specialNameBuffer;
293 llvm::raw_svector_ostream specialName(specialNameBuffer);
294 specialName << "c" << getValue();
295 setNameFn(getResult(), specialName.str());
296}
297
298OpFoldResult IntConstantOp::fold(FoldAdaptor adaptor) {
299 assert(adaptor.getOperands().empty() && "constant has no operands");
300 return getValueAttr();
301}
302
303void IntConstantOp::print(OpAsmPrinter &p) {
304 p << " " << getValue();
305 p.printOptionalAttrDict((*this)->getAttrs(), /*elidedAttrs=*/ {"value"});
306}
307
308ParseResult IntConstantOp::parse(OpAsmParser &parser, OperationState &result) {
309 APInt value;
310 if (parser.parseInteger(value)) {
311 return failure();
312 }
313
314 result.getOrAddProperties<Properties>().setValue(
315 IntegerAttr::get(parser.getContext(), APSInt(value))
316 );
317
318 if (parser.parseOptionalAttrDict(result.attributes)) {
319 return failure();
320 }
321
322 result.addTypes(smt::IntType::get(parser.getContext()));
323 return success();
324}
325
326//===----------------------------------------------------------------------===//
327// ForallOp
328//===----------------------------------------------------------------------===//
329
330template <typename QuantifierOp> static LogicalResult verifyQuantifierRegions(QuantifierOp op) {
331 if (op.getBoundVarNames() && op.getBody().getNumArguments() != op.getBoundVarNames()->size()) {
332 return op.emitOpError("number of bound variable names must match number of block arguments");
333 }
334 if (!llvm::all_of(op.getBody().getArgumentTypes(), isAnyNonFuncSMTValueType)) {
335 return op.emitOpError() << "bound variables must by any non-function SMT value";
336 }
337
338 if (op.getBody().front().getTerminator()->getNumOperands() != 1) {
339 return op.emitOpError("must have exactly one yielded value");
340 }
341 if (!isa<BoolType>(op.getBody().front().getTerminator()->getOperand(0).getType())) {
342 return op.emitOpError("yielded value must be of '!smt.bool' type");
343 }
344
345 for (auto regionWithIndex : llvm::enumerate(op.getPatterns())) {
346 unsigned i = regionWithIndex.index();
347 Region &region = regionWithIndex.value();
348
349 if (op.getBody().getArgumentTypes() != region.getArgumentTypes()) {
350 return op.emitOpError() << "block argument number and types of the 'body' "
351 "and 'patterns' region #"
352 << i << " must match";
353 }
354 if (region.front().getTerminator()->getNumOperands() < 1) {
355 return op.emitOpError() << "'patterns' region #" << i
356 << " must have at least one yielded value";
357 }
358
359 // All operations in the 'patterns' region must be SMT operations.
360 auto result = region.walk([&](Operation *childOp) {
361 if (!isa<SMTDialect>(childOp->getDialect())) {
362 auto diag = op.emitOpError()
363 << "the 'patterns' region #" << i << " may only contain SMT dialect operations";
364 diag.attachNote(childOp->getLoc()) << "first non-SMT operation here";
365 return WalkResult::interrupt();
366 }
367
368 // There may be no quantifier (or other variable binding) operations in
369 // the 'patterns' region.
370 if (isa<ForallOp, ExistsOp>(childOp)) {
371 auto diag = op.emitOpError() << "the 'patterns' region #" << i
372 << " must not contain "
373 "any variable binding operations";
374 diag.attachNote(childOp->getLoc()) << "first violating operation here";
375 return WalkResult::interrupt();
376 }
377
378 return WalkResult::advance();
379 });
380 if (result.wasInterrupted()) {
381 return failure();
382 }
383 }
384
385 return success();
386}
387
388template <typename Properties>
389static void buildQuantifier(
390 OpBuilder &odsBuilder, OperationState &odsState, TypeRange boundVarTypes,
391 function_ref<Value(OpBuilder &, Location, ValueRange)> bodyBuilder,
392 std::optional<ArrayRef<StringRef>> boundVarNames,
393 function_ref<ValueRange(OpBuilder &, Location, ValueRange)> patternBuilder, uint32_t weight,
394 bool noPattern
395) {
396 odsState.addTypes(BoolType::get(odsBuilder.getContext()));
397 if (weight != 0) {
398 odsState.getOrAddProperties<Properties>().weight =
399 odsBuilder.getIntegerAttr(odsBuilder.getIntegerType(32), weight);
400 }
401 if (noPattern) {
402 odsState.getOrAddProperties<Properties>().noPattern = odsBuilder.getUnitAttr();
403 }
404 if (boundVarNames.has_value()) {
405 SmallVector<Attribute> boundVarNamesList;
406 for (StringRef str : *boundVarNames) {
407 boundVarNamesList.emplace_back(odsBuilder.getStringAttr(str));
408 }
409 odsState.getOrAddProperties<Properties>().boundVarNames =
410 odsBuilder.getArrayAttr(boundVarNamesList);
411 }
412 {
413 OpBuilder::InsertionGuard guard(odsBuilder);
414 Region *region = odsState.addRegion();
415 Block *block = odsBuilder.createBlock(region);
416 block->addArguments(
417 boundVarTypes, SmallVector<Location>(boundVarTypes.size(), odsState.location)
418 );
419 Value returnVal = bodyBuilder(odsBuilder, odsState.location, block->getArguments());
420 odsBuilder.create<llzk::smt::YieldOp>(odsState.location, returnVal);
421 }
422 if (patternBuilder) {
423 Region *region = odsState.addRegion();
424 OpBuilder::InsertionGuard guard(odsBuilder);
425 Block *block = odsBuilder.createBlock(region);
426 block->addArguments(
427 boundVarTypes, SmallVector<Location>(boundVarTypes.size(), odsState.location)
428 );
429 ValueRange returnVals = patternBuilder(odsBuilder, odsState.location, block->getArguments());
430 odsBuilder.create<llzk::smt::YieldOp>(odsState.location, returnVals);
431 }
432}
433
434LogicalResult ForallOp::verify() {
435 if (!getPatterns().empty() && getNoPattern()) {
436 return emitOpError() << "patterns and the no_pattern attribute must not be "
437 "specified at the same time";
438 }
439
440 return success();
441}
442
443LogicalResult ForallOp::verifyRegions() { return verifyQuantifierRegions(*this); }
444
446 OpBuilder &odsBuilder, OperationState &odsState, TypeRange boundVarTypes,
447 function_ref<Value(OpBuilder &, Location, ValueRange)> bodyBuilder,
448 std::optional<ArrayRef<StringRef>> boundVarNames,
449 function_ref<ValueRange(OpBuilder &, Location, ValueRange)> patternBuilder, uint32_t weight,
450 bool noPattern
451) {
452 buildQuantifier<Properties>(
453 odsBuilder, odsState, boundVarTypes, bodyBuilder, boundVarNames, patternBuilder, weight,
454 noPattern
455 );
456}
457
458//===----------------------------------------------------------------------===//
459// ExistsOp
460//===----------------------------------------------------------------------===//
461
462LogicalResult ExistsOp::verify() {
463 if (!getPatterns().empty() && getNoPattern()) {
464 return emitOpError() << "patterns and the no_pattern attribute must not be "
465 "specified at the same time";
466 }
467
468 return success();
469}
470
471LogicalResult ExistsOp::verifyRegions() { return verifyQuantifierRegions(*this); }
472
474 OpBuilder &odsBuilder, OperationState &odsState, TypeRange boundVarTypes,
475 function_ref<Value(OpBuilder &, Location, ValueRange)> bodyBuilder,
476 std::optional<ArrayRef<StringRef>> boundVarNames,
477 function_ref<ValueRange(OpBuilder &, Location, ValueRange)> patternBuilder, uint32_t weight,
478 bool noPattern
479) {
480 buildQuantifier<Properties>(
481 odsBuilder, odsState, boundVarTypes, bodyBuilder, boundVarNames, patternBuilder, weight,
482 noPattern
483 );
484}
485
486#define GET_OP_CLASSES
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
Definition SMTOps.cpp:32
::llzk::smt::BitVectorAttr getValue()
Definition SMT.cpp.inc:2647
::llzk::smt::BitVectorAttr getValueAttr()
Definition SMT.h.inc:2208
::mlir::OpFoldResult fold(FoldAdaptor adaptor)
Definition SMTOps.cpp:39
::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location > location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type > &inferredReturnTypes)
Definition SMTOps.cpp:23
FoldAdaptor::Properties Properties
Definition SMT.h.inc:2157
GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute > > FoldAdaptor
Definition SMT.h.inc:2156
::mlir::TypedValue<::llzk::smt::BitVectorType > getResult()
Definition SMT.h.inc:2195
static BitVectorType get(::mlir::MLIRContext *context, int64_t width)
::mlir::TypedValue<::llzk::smt::BoolType > getResult()
Definition SMT.h.inc:4197
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
Definition SMTOps.cpp:278
GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute > > FoldAdaptor
Definition SMT.h.inc:4158
::mlir::BoolAttr getValueAttr()
Definition SMT.h.inc:4210
::mlir::OpFoldResult fold(FoldAdaptor adaptor)
Definition SMTOps.cpp:282
::mlir::Region & getUnsatRegion()
Definition SMT.h.inc:4385
::mlir::Region & getUnknownRegion()
Definition SMT.h.inc:4381
::mlir::Region & getSatRegion()
Definition SMT.h.inc:4377
::llvm::LogicalResult verifyRegions()
Definition SMTOps.cpp:71
::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location > location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type > &inferredReturnTypes)
Definition SMTOps.cpp:175
::mlir::TypedValue<::mlir::Type > getResult()
Definition SMT.h.inc:4702
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
Definition SMTOps.cpp:48
::std::optional< ::llvm::StringRef > getNamePrefix()
Definition SMT.cpp.inc:5512
::mlir::Operation::operand_range getInputs()
Definition SMT.h.inc:4853
void print(::mlir::OpAsmPrinter &p)
Definition SMTOps.cpp:139
::llvm::LogicalResult verify()
Definition SMTOps.cpp:145
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
Definition SMTOps.cpp:135
::mlir::Operation::operand_range getInputs()
Definition SMT.h.inc:4982
void print(::mlir::OpAsmPrinter &p)
Definition SMTOps.cpp:117
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
Definition SMTOps.cpp:113
::llvm::LogicalResult verify()
Definition SMTOps.cpp:123
::llvm::LogicalResult verify()
Definition SMTOps.cpp:462
::llvm::LogicalResult verifyRegions()
Definition SMTOps.cpp:471
::mlir::MutableArrayRef<::mlir::Region > getPatterns()
Definition SMT.h.inc:5228
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, mlir::TypeRange boundVarTypes, llvm::function_ref< mlir::Value(mlir::OpBuilder &, mlir::Location, mlir::ValueRange)> bodyBuilder, std::optional< llvm::ArrayRef< mlir::StringRef > > boundVarNames=std::nullopt, llvm::function_ref< mlir::ValueRange(mlir::OpBuilder &, mlir::Location, mlir::ValueRange)> patternBuilder={}, uint32_t weight=0, bool noPattern=false)
Definition SMTOps.cpp:473
::mlir::TypedValue<::llzk::smt::BitVectorType > getInput()
Definition SMT.h.inc:5452
::llvm::LogicalResult verify()
Definition SMTOps.cpp:157
::llvm::LogicalResult verifyRegions()
Definition SMTOps.cpp:443
::llvm::LogicalResult verify()
Definition SMTOps.cpp:434
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, mlir::TypeRange boundVarTypes, llvm::function_ref< mlir::Value(mlir::OpBuilder &, mlir::Location, mlir::ValueRange)> bodyBuilder, std::optional< llvm::ArrayRef< mlir::StringRef > > boundVarNames=std::nullopt, llvm::function_ref< mlir::ValueRange(mlir::OpBuilder &, mlir::Location, mlir::ValueRange)> patternBuilder={}, uint32_t weight=0, bool noPattern=false)
Definition SMTOps.cpp:445
::mlir::MutableArrayRef<::mlir::Region > getPatterns()
Definition SMT.h.inc:5734
::mlir::APInt getValue()
Definition SMT.cpp.inc:8077
void print(::mlir::OpAsmPrinter &p)
Definition SMTOps.cpp:303
GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute > > FoldAdaptor
Definition SMT.h.inc:6709
::mlir::OpFoldResult fold(FoldAdaptor adaptor)
Definition SMTOps.cpp:298
::mlir::TypedValue<::llzk::smt::IntType > getResult()
Definition SMT.h.inc:6748
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
Definition SMTOps.cpp:291
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
Definition SMTOps.cpp:308
FoldAdaptor::Properties Properties
Definition SMT.h.inc:6710
::mlir::IntegerAttr getValueAttr()
Definition SMT.h.inc:6761
::mlir::TypedValue<::llzk::smt::BitVectorType > getInput()
Definition SMT.h.inc:8445
::llvm::LogicalResult verify()
Definition SMTOps.cpp:193
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, unsigned count, mlir::Value input)
void print(::mlir::OpAsmPrinter &p)
Definition SMTOps.cpp:268
unsigned getCount()
Get the number of times the input operand is repeated.
Definition SMTOps.cpp:204
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
Definition SMTOps.cpp:216
::llvm::LogicalResult verifyRegions()
Definition SMTOps.cpp:56
::mlir::Operation::operand_range getInputs()
Definition SMT.h.inc:8900
bool isAnyNonFuncSMTValueType(mlir::Type type)
Returns whether the given type is an SMT value type (excluding functions).