18 #include "mlir/Interfaces/ViewLikeInterface.cpp.inc"
26 if (staticVals.size() != numElements)
27 return op->
emitError(
"expected ") << numElements <<
" " << name
28 <<
" values, got " << staticVals.size();
29 unsigned expectedNumDynamicEntries =
30 llvm::count_if(staticVals, ShapedType::isDynamic);
31 if (values.size() != expectedNumDynamicEntries)
33 << expectedNumDynamicEntries <<
" dynamic " << name <<
" values";
40 bool generateErrorMessage) {
43 for (int64_t i = 0, e = shape.size(); i < e; ++i) {
45 if (ShapedType::isDynamic(shape[i]))
48 if (ShapedType::isDynamic(staticOffsets[i]))
50 if (staticOffsets[i] >= shape[i]) {
52 std::string(
"offset ") + std::to_string(i) +
53 " is out-of-bounds: " + std::to_string(staticOffsets[i]) +
54 " >= " + std::to_string(shape[i]);
58 if (ShapedType::isDynamic(staticSizes[i]) ||
59 ShapedType::isDynamic(staticStrides[i]))
62 staticOffsets[i] + (staticSizes[i] - 1) * staticStrides[i];
63 if (lastPos >= shape[i]) {
64 result.
errorMessage = std::string(
"slice along dimension ") +
66 " runs out-of-bounds: " + std::to_string(lastPos) +
67 " >= " + std::to_string(shape[i]);
78 bool generateErrorMessage) {
82 if (
auto attr = dyn_cast<Attribute>(ofr)) {
83 staticValues.push_back(cast<IntegerAttr>(attr).getInt());
85 staticValues.push_back(ShapedType::kDynamic);
91 shape, getStaticValues(mixedOffsets), getStaticValues(mixedSizes),
92 getStaticValues(mixedStrides), generateErrorMessage);
101 size_t numDynamicDims =
102 llvm::count_if(op.getStaticSizes(), ShapedType::isDynamic);
103 if (op.getSizes().size() != numDynamicDims) {
104 return op->emitError(
"expected the number of 'sizes' to match the number "
105 "of dynamic entries in 'static_sizes' (")
106 << op.getSizes().size() <<
" vs " << numDynamicDims <<
")";
108 size_t numDynamicStrides =
109 llvm::count_if(op.getStaticStrides(), ShapedType::isDynamic);
110 if (op.getStrides().size() != numDynamicStrides) {
111 return op->emitError(
"expected the number of 'strides' to match the number "
112 "of dynamic entries in 'static_strides' (")
113 << op.getStrides().size() <<
" vs " << numDynamicStrides <<
")";
115 size_t numDynamicOffsets =
116 llvm::count_if(op.getStaticOffsets(), ShapedType::isDynamic);
117 if (op.getOffsets().size() != numDynamicOffsets) {
118 return op->emitError(
"expected the number of 'offsets' to match the number "
119 "of dynamic entries in 'static_offsets' (")
120 << op.getOffsets().size() <<
" vs " << numDynamicOffsets <<
")";
123 std::array<unsigned, 3> maxRanks = op.getArrayAttrMaxRanks();
128 if (!(op.getMixedOffsets().size() == 1 && maxRanks[0] == 1) &&
129 op.getMixedOffsets().size() != op.getMixedSizes().size())
130 return op->emitError(
131 "expected mixed offsets rank to match mixed sizes rank (")
132 << op.getMixedOffsets().size() <<
" vs " << op.getMixedSizes().size()
133 <<
") so the rank of the result type is well-formed.";
136 if (op.getMixedSizes().size() != op.getMixedStrides().size())
137 return op->emitError(
138 "expected mixed sizes rank to match mixed strides rank (")
139 << op.getMixedSizes().size() <<
" vs " << op.getMixedStrides().size()
140 <<
") so the rank of the result type is well-formed.";
143 op,
"offset", maxRanks[0], op.getStaticOffsets(), op.getOffsets())))
146 op,
"size", maxRanks[1], op.getStaticSizes(), op.getSizes())))
149 op,
"stride", maxRanks[2], op.getStaticStrides(), op.getStrides())))
152 for (int64_t offset : op.getStaticOffsets()) {
153 if (offset < 0 && ShapedType::isStatic(offset))
154 return op->emitError(
"expected offsets to be non-negative, but got ")
157 for (int64_t size : op.getStaticSizes()) {
158 if (size < 0 && ShapedType::isStatic(size))
159 return op->emitError(
"expected sizes to be non-negative, but got ")
176 llvm_unreachable(
"unsupported delimiter");
191 llvm_unreachable(
"unsupported delimiter");
203 printer << leftDelimiter;
204 if (integers.empty()) {
205 printer << rightDelimiter;
209 unsigned dynamicValIdx = 0;
210 unsigned scalableIndexIdx = 0;
211 llvm::interleaveComma(integers, printer, [&](int64_t integer) {
212 if (!scalableFlags.empty() && scalableFlags[scalableIndexIdx])
214 if (ShapedType::isDynamic(integer)) {
215 printer << values[dynamicValIdx];
216 if (!valueTypes.empty())
217 printer <<
" : " << valueTypes[dynamicValIdx];
222 if (!scalableFlags.empty() && scalableFlags[scalableIndexIdx])
228 printer << rightDelimiter;
239 auto parseIntegerOrValue = [&]() {
246 if (res.has_value() && succeeded(res.value())) {
247 values.push_back(operand);
248 integerVals.push_back(ShapedType::kDynamic);
249 if (valueTypes && parser.
parseColonType(valueTypes->emplace_back()))
255 integerVals.push_back(integer);
265 " in dynamic index list"))
267 <<
"expected SSA value or integer";
274 OffsetSizeAndStrideOpInterface a, OffsetSizeAndStrideOpInterface b,
276 if (a.getStaticOffsets().size() != b.getStaticOffsets().size())
278 if (a.getStaticSizes().size() != b.getStaticSizes().size())
280 if (a.getStaticStrides().size() != b.getStaticStrides().size())
282 for (
auto it : llvm::zip(a.getMixedOffsets(), b.getMixedOffsets()))
283 if (!cmp(std::get<0>(it), std::get<1>(it)))
285 for (
auto it : llvm::zip(a.getMixedSizes(), b.getMixedSizes()))
286 if (!cmp(std::get<0>(it), std::get<1>(it)))
288 for (
auto it : llvm::zip(a.getMixedStrides(), b.getMixedStrides()))
289 if (!cmp(std::get<0>(it), std::get<1>(it)))
296 return std::count_if(staticVals.begin(), staticVals.begin() + idx,
297 ShapedType::isDynamic);
static char getLeftDelimiter(AsmParser::Delimiter delimiter)
static char getRightDelimiter(AsmParser::Delimiter delimiter)
Delimiter
These are the supported delimiters around operand lists and region argument lists,...
@ Paren
Parens surrounding zero or more operands.
@ Braces
{} brackets surrounding zero or more operands.
@ Square
Square brackets surrounding zero or more operands.
@ LessGreater
<> brackets surrounding zero or more operands.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
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 ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
DenseI64ArrayAttr getDenseI64ArrayAttr(ArrayRef< int64_t > values)
DenseBoolArrayAttr getDenseBoolArrayAttr(ArrayRef< bool > values)
Tensor-typed DenseArrayAttr getters.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class represents a single result from folding an operation.
This class implements the operand iterators for the Operation class.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
This class provides an abstraction over the various different ranges of value types.
This class provides an abstraction over the different types of ranges over Values.
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
bool sameOffsetsSizesAndStrides(OffsetSizeAndStrideOpInterface a, OffsetSizeAndStrideOpInterface b, llvm::function_ref< bool(OpFoldResult, OpFoldResult)> cmp)
unsigned getNumDynamicEntriesUpToIdx(ArrayRef< int64_t > staticVals, unsigned idx)
Helper method to compute the number of dynamic entries of staticVals, up to idx.
LogicalResult verifyOffsetSizeAndStrideOp(OffsetSizeAndStrideOpInterface op)
Include the generated interface declarations.
ParseResult parseDynamicIndexList(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &values, DenseI64ArrayAttr &integers, DenseBoolArrayAttr &scalableFlags, SmallVectorImpl< Type > *valueTypes=nullptr, AsmParser::Delimiter delimiter=AsmParser::Delimiter::Square)
Parser hooks for custom directive in assemblyFormat.
SliceBoundsVerificationResult verifyInBoundsSlice(ArrayRef< int64_t > shape, ArrayRef< int64_t > staticOffsets, ArrayRef< int64_t > staticSizes, ArrayRef< int64_t > staticStrides, bool generateErrorMessage=false)
Verify that the offsets/sizes/strides-style access into the given shape is in-bounds.
LogicalResult verifyListOfOperandsOrIntegers(Operation *op, StringRef name, unsigned expectedNumElements, ArrayRef< int64_t > attr, ValueRange values)
Verify that a the values has as many elements as the number of entries in attr for which isDynamic ev...
void printDynamicIndexList(OpAsmPrinter &printer, Operation *op, OperandRange values, ArrayRef< int64_t > integers, ArrayRef< bool > scalableFlags, TypeRange valueTypes=TypeRange(), AsmParser::Delimiter delimiter=AsmParser::Delimiter::Square)
Printer hooks for custom directive in assemblyFormat.
This is the representation of an operand reference.
Result for slice bounds verification;.
bool isValid
If set to "true", the slice bounds verification was successful.
std::string errorMessage
An error message that can be printed during op verification.