12#include "llvm/ADT/APSInt.h"
22LogicalResult BVConstantOp::inferReturnTypes(
27 inferredReturnTypes.push_back(
28 properties.
as<Properties *>()->getValue().getType());
32void BVConstantOp::getAsmResultNames(
35 llvm::raw_svector_ostream specialName(specialNameBuffer);
36 specialName <<
"c" << getValue().getValue() <<
"_bv"
37 << getValue().getValue().getBitWidth();
38 setNameFn(getResult(), specialName.str());
42 assert(adaptor.getOperands().empty() &&
"constant has no operands");
43 return getValueAttr();
50void DeclareFunOp::getAsmResultNames(
52 setNameFn(getResult(), getNamePrefix().has_value() ? *getNamePrefix() :
"");
59LogicalResult SolverOp::verifyRegions() {
60 if (getBody()->getTerminator()->getOperands().getTypes() != getResultTypes())
61 return emitOpError() <<
"types of yielded values must match return values";
62 if (getBody()->getArgumentTypes() != getInputs().getTypes())
64 <<
"block argument types must match the types of the 'inputs'";
73LogicalResult CheckOp::verifyRegions() {
74 if (getSatRegion().front().getTerminator()->getOperands().getTypes() !=
76 return emitOpError() <<
"types of yielded values in 'sat' region must "
77 "match return values";
78 if (getUnknownRegion().front().getTerminator()->getOperands().getTypes() !=
80 return emitOpError() <<
"types of yielded values in 'unknown' region must "
81 "match return values";
82 if (getUnsatRegion().front().getTerminator()->getOperands().getTypes() !=
84 return emitOpError() <<
"types of yielded values in 'unsat' region must "
85 "match return values";
119 printer <<
' ' << getInputs();
121 getOperation()->getDiscardableAttrDictionary().getValue());
122 printer <<
" : " << getInputs().front().getType();
125LogicalResult EqOp::verify() {
126 if (getInputs().size() < 2)
127 return emitOpError() <<
"'inputs' must have at least size 2, but got "
128 << getInputs().size();
142 printer <<
' ' << getInputs();
144 getOperation()->getDiscardableAttrDictionary().getValue());
145 printer <<
" : " << getInputs().front().getType();
148LogicalResult DistinctOp::verify() {
149 if (getInputs().size() < 2)
150 return emitOpError() <<
"'inputs' must have at least size 2, but got "
151 << getInputs().size();
160LogicalResult ExtractOp::verify() {
161 unsigned rangeWidth =
getType().getWidth();
162 unsigned inputWidth = cast<BitVectorType>(getInput().
getType()).getWidth();
163 if (getLowBit() + rangeWidth > inputWidth)
164 return emitOpError(
"range to be extracted is too big, expected range "
165 "starting at index ")
166 << getLowBit() <<
" of length " << rangeWidth
167 <<
" requires input width of at least " << (getLowBit() + rangeWidth)
168 <<
", but the input width is only " << inputWidth;
176LogicalResult ConcatOp::inferReturnTypes(
180 inferredReturnTypes.push_back(BitVectorType::get(
181 context, cast<BitVectorType>(operands[0].
getType()).getWidth() +
182 cast<BitVectorType>(operands[1].
getType()).getWidth()));
190LogicalResult RepeatOp::verify() {
191 unsigned inputWidth = cast<BitVectorType>(getInput().
getType()).getWidth();
192 unsigned resultWidth =
getType().getWidth();
193 if (resultWidth % inputWidth != 0)
194 return emitOpError() <<
"result bit-vector width must be a multiple of the "
195 "input bit-vector width";
200unsigned RepeatOp::getCount() {
201 unsigned inputWidth = cast<BitVectorType>(getInput().
getType()).getWidth();
202 unsigned resultWidth =
getType().getWidth();
203 return resultWidth / inputWidth;
208 unsigned inputWidth = cast<BitVectorType>(input.
getType()).getWidth();
209 Type resultTy = BitVectorType::get(builder.
getContext(), inputWidth * count);
210 build(builder, state, resultTy, input);
222 if (count.isNonPositive())
223 return parser.
emitError(countLoc) <<
"integer must be positive";
234 auto bvInputTy = dyn_cast<BitVectorType>(inputType);
236 return parser.
emitError(inputLoc) <<
"input must have bit-vector type";
240 const unsigned maxBw = 63;
241 if (count.getActiveBits() > maxBw)
243 <<
"integer must fit into " << maxBw <<
" bits";
248 APInt resultBw = bvInputTy.getWidth() * count.zext(2 * maxBw);
249 if (resultBw.getActiveBits() > maxBw)
251 <<
"result bit-width (provided integer times bit-width of the input "
252 "type) must fit into "
256 BitVectorType::get(parser.
getContext(), resultBw.getZExtValue());
257 result.addTypes(resultTy);
262 printer <<
" " << getCount() <<
" times " << getInput();
264 (*this)->getDiscardableAttrDictionary().getValue());
265 printer <<
" : " << getInput().getType();
272void BoolConstantOp::getAsmResultNames(
274 setNameFn(getResult(), getValue() ?
"true" :
"false");
278 assert(adaptor.getOperands().empty() &&
"constant has no operands");
279 return getValueAttr();
286void IntConstantOp::getAsmResultNames(
289 llvm::raw_svector_ostream specialName(specialNameBuffer);
290 specialName <<
"c" << getValue();
291 setNameFn(getResult(), specialName.str());
295 assert(adaptor.getOperands().empty() &&
"constant has no operands");
296 return getValueAttr();
300 p <<
" " << getValue();
309 result.getOrAddProperties<Properties>().setValue(
310 IntegerAttr::get(parser.
getContext(), APSInt(value)));
323template <
typename QuantifierOp>
325 if (op.getBoundVarNames() &&
326 op.getBody().getNumArguments() != op.getBoundVarNames()->size())
327 return op.emitOpError(
328 "number of bound variable names must match number of block arguments");
330 return op.emitOpError()
331 <<
"bound variables must by any non-function SMT value";
333 if (op.getBody().front().getTerminator()->getNumOperands() != 1)
334 return op.emitOpError(
"must have exactly one yielded value");
336 op.getBody().front().getTerminator()->getOperand(0).getType()))
337 return op.emitOpError(
"yielded value must be of '!smt.bool' type");
339 for (
auto regionWithIndex : llvm::enumerate(op.getPatterns())) {
340 unsigned i = regionWithIndex.index();
341 Region ®ion = regionWithIndex.value();
344 return op.emitOpError()
345 <<
"block argument number and types of the 'body' "
346 "and 'patterns' region #"
347 << i <<
" must match";
349 return op.emitOpError() <<
"'patterns' region #" << i
350 <<
" must have at least one yielded value";
354 if (!isa<SMTDialect>(childOp->
getDialect())) {
355 auto diag = op.emitOpError()
356 <<
"the 'patterns' region #" << i
357 <<
" may only contain SMT dialect operations";
358 diag.attachNote(childOp->
getLoc()) <<
"first non-SMT operation here";
364 if (isa<ForallOp, ExistsOp>(childOp)) {
365 auto diag = op.emitOpError() <<
"the 'patterns' region #" << i
366 <<
" must not contain "
367 "any variable binding operations";
368 diag.attachNote(childOp->
getLoc()) <<
"first violating operation here";
374 if (
result.wasInterrupted())
381template <
typename Properties>
387 uint32_t weight,
bool noPattern) {
395 if (boundVarNames.has_value()) {
397 for (StringRef str : *boundVarNames)
398 boundVarNamesList.emplace_back(odsBuilder.
getStringAttr(str));
411 smt::YieldOp::create(odsBuilder, odsState.
location, returnVal);
413 if (patternBuilder) {
422 smt::YieldOp::create(odsBuilder, odsState.
location, returnVals);
426LogicalResult ForallOp::verify() {
427 if (!getPatterns().empty() && getNoPattern())
428 return emitOpError() <<
"patterns and the no_pattern attribute must not be "
429 "specified at the same time";
434LogicalResult ForallOp::verifyRegions() {
439 OpBuilder &odsBuilder, OperationState &odsState,
TypeRange boundVarTypes,
441 std::optional<ArrayRef<StringRef>> boundVarNames,
443 uint32_t weight,
bool noPattern) {
445 boundVarNames, patternBuilder, weight, noPattern);
452LogicalResult ExistsOp::verify() {
453 if (!getPatterns().empty() && getNoPattern())
454 return emitOpError() <<
"patterns and the no_pattern attribute must not be "
455 "specified at the same time";
460LogicalResult ExistsOp::verifyRegions() {
465 OpBuilder &odsBuilder, OperationState &odsState,
TypeRange boundVarTypes,
467 std::optional<ArrayRef<StringRef>> boundVarNames,
469 uint32_t weight,
bool noPattern) {
471 boundVarNames, patternBuilder, weight, noPattern);
474#define GET_OP_CLASSES
475#include "mlir/Dialect/SMT/IR/SMT.cpp.inc"
static std::string diag(const llvm::Value &value)
static LogicalResult verifyQuantifierRegions(QuantifierOp op)
static LogicalResult parseSameOperandTypeVariadicToBoolOp(OpAsmParser &parser, OperationState &result)
static void buildQuantifier(OpBuilder &odsBuilder, OperationState &odsState, TypeRange boundVarTypes, function_ref< Value(OpBuilder &, Location, ValueRange)> bodyBuilder, std::optional< ArrayRef< StringRef > > boundVarNames, function_ref< ValueRange(OpBuilder &, Location, ValueRange)> patternBuilder, uint32_t weight, bool noPattern)
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
Block represents an ordered list of Operations.
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgListType getArguments()
IntegerAttr getIntegerAttr(Type type, int64_t value)
IntegerType getIntegerType(unsigned width)
StringAttr getStringAttr(const Twine &bytes)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Location getLoc()
The source location the operation was defined or derived from.
unsigned getNumOperands()
Type-safe wrapper around a void* for passing properties, including the properties structs of operatio...
This class provides an abstraction over the different types of ranges over Regions.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Returns the argument types of the first block within the region.
RetT walk(FnT &&callback)
Walk all nested operations, blocks or regions (including this region), depending on the type of callb...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
static WalkResult advance()
static WalkResult interrupt()
bool isAnyNonFuncSMTValueType(mlir::Type type)
Returns whether the given type is an SMT value type (excluding functions).
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
llvm::function_ref< Fn > function_ref
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.