xref: /llvm-project/mlir/lib/Dialect/IRDL/IR/IRDL.cpp (revision 69d3ba3db922fca8cfc47b5f115b6bea6a737aab)
10e0db0a4SMathieu Fehr //===- IRDL.cpp - IRDL dialect ----------------------------------*- C++ -*-===//
20e0db0a4SMathieu Fehr //
30e0db0a4SMathieu Fehr // This file is licensed under the Apache License v2.0 with LLVM Exceptions.
40e0db0a4SMathieu Fehr // See https://llvm.org/LICENSE.txt for license information.
50e0db0a4SMathieu Fehr // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60e0db0a4SMathieu Fehr //
70e0db0a4SMathieu Fehr //===----------------------------------------------------------------------===//
80e0db0a4SMathieu Fehr 
90e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDL.h"
10b86a9c5bSThéo Degioanni #include "mlir/Dialect/IRDL/IRDLSymbols.h"
110e0db0a4SMathieu Fehr #include "mlir/IR/Builders.h"
120e0db0a4SMathieu Fehr #include "mlir/IR/BuiltinAttributes.h"
13d4bde696SDaniil Dudkin #include "mlir/IR/Diagnostics.h"
140e0db0a4SMathieu Fehr #include "mlir/IR/DialectImplementation.h"
150e0db0a4SMathieu Fehr #include "mlir/IR/ExtensibleDialect.h"
160e0db0a4SMathieu Fehr #include "mlir/IR/OpDefinition.h"
170e0db0a4SMathieu Fehr #include "mlir/IR/OpImplementation.h"
18d4bde696SDaniil Dudkin #include "mlir/IR/Operation.h"
19d4bde696SDaniil Dudkin #include "mlir/Support/LLVM.h"
200e0db0a4SMathieu Fehr #include "llvm/ADT/STLExtras.h"
21*69d3ba3dSThéo Degioanni #include "llvm/ADT/SetOperations.h"
22*69d3ba3dSThéo Degioanni #include "llvm/ADT/SmallString.h"
23*69d3ba3dSThéo Degioanni #include "llvm/ADT/StringExtras.h"
240e0db0a4SMathieu Fehr #include "llvm/ADT/TypeSwitch.h"
250e0db0a4SMathieu Fehr #include "llvm/IR/Metadata.h"
260e0db0a4SMathieu Fehr #include "llvm/Support/Casting.h"
270e0db0a4SMathieu Fehr 
280e0db0a4SMathieu Fehr using namespace mlir;
290e0db0a4SMathieu Fehr using namespace mlir::irdl;
300e0db0a4SMathieu Fehr 
310e0db0a4SMathieu Fehr //===----------------------------------------------------------------------===//
320e0db0a4SMathieu Fehr // IRDL dialect.
330e0db0a4SMathieu Fehr //===----------------------------------------------------------------------===//
340e0db0a4SMathieu Fehr 
350e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDL.cpp.inc"
360e0db0a4SMathieu Fehr 
370e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLDialect.cpp.inc"
380e0db0a4SMathieu Fehr 
390e0db0a4SMathieu Fehr void IRDLDialect::initialize() {
400e0db0a4SMathieu Fehr   addOperations<
410e0db0a4SMathieu Fehr #define GET_OP_LIST
420e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc"
430e0db0a4SMathieu Fehr       >();
440e0db0a4SMathieu Fehr   addTypes<
450e0db0a4SMathieu Fehr #define GET_TYPEDEF_LIST
460e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc"
470e0db0a4SMathieu Fehr       >();
486971b83bSMathieu Fehr   addAttributes<
496971b83bSMathieu Fehr #define GET_ATTRDEF_LIST
506971b83bSMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLAttributes.cpp.inc"
516971b83bSMathieu Fehr       >();
520e0db0a4SMathieu Fehr }
530e0db0a4SMathieu Fehr 
540e0db0a4SMathieu Fehr //===----------------------------------------------------------------------===//
55*69d3ba3dSThéo Degioanni // Parsing/Printing/Verifying
560e0db0a4SMathieu Fehr //===----------------------------------------------------------------------===//
570e0db0a4SMathieu Fehr 
580e0db0a4SMathieu Fehr /// Parse a region, and add a single block if the region is empty.
590e0db0a4SMathieu Fehr /// If no region is parsed, create a new region with a single empty block.
600e0db0a4SMathieu Fehr static ParseResult parseSingleBlockRegion(OpAsmParser &p, Region &region) {
610e0db0a4SMathieu Fehr   auto regionParseRes = p.parseOptionalRegion(region);
620e0db0a4SMathieu Fehr   if (regionParseRes.has_value() && failed(regionParseRes.value()))
630e0db0a4SMathieu Fehr     return failure();
640e0db0a4SMathieu Fehr 
650e0db0a4SMathieu Fehr   // If the region is empty, add a single empty block.
660e0db0a4SMathieu Fehr   if (region.empty())
670e0db0a4SMathieu Fehr     region.push_back(new Block());
680e0db0a4SMathieu Fehr 
690e0db0a4SMathieu Fehr   return success();
700e0db0a4SMathieu Fehr }
710e0db0a4SMathieu Fehr 
720e0db0a4SMathieu Fehr static void printSingleBlockRegion(OpAsmPrinter &p, Operation *op,
730e0db0a4SMathieu Fehr                                    Region &region) {
740e0db0a4SMathieu Fehr   if (!region.getBlocks().front().empty())
750e0db0a4SMathieu Fehr     p.printRegion(region);
760e0db0a4SMathieu Fehr }
770e0db0a4SMathieu Fehr 
780e0db0a4SMathieu Fehr LogicalResult DialectOp::verify() {
790e0db0a4SMathieu Fehr   if (!Dialect::isValidNamespace(getName()))
800e0db0a4SMathieu Fehr     return emitOpError("invalid dialect name");
810e0db0a4SMathieu Fehr   return success();
820e0db0a4SMathieu Fehr }
830e0db0a4SMathieu Fehr 
84*69d3ba3dSThéo Degioanni LogicalResult OperationOp::verifyRegions() {
85*69d3ba3dSThéo Degioanni   // Stores pairs of value kinds and the list of names of values of this kind in
86*69d3ba3dSThéo Degioanni   // the operation.
87*69d3ba3dSThéo Degioanni   SmallVector<std::tuple<StringRef, llvm::SmallDenseSet<StringRef>>> valueNames;
886971b83bSMathieu Fehr 
89*69d3ba3dSThéo Degioanni   auto insertNames = [&](StringRef kind, ArrayAttr names) {
90*69d3ba3dSThéo Degioanni     llvm::SmallDenseSet<StringRef> nameSet;
91*69d3ba3dSThéo Degioanni     nameSet.reserve(names.size());
92*69d3ba3dSThéo Degioanni     for (auto name : names)
93*69d3ba3dSThéo Degioanni       nameSet.insert(llvm::cast<StringAttr>(name).getValue());
94*69d3ba3dSThéo Degioanni     valueNames.emplace_back(kind, std::move(nameSet));
95*69d3ba3dSThéo Degioanni   };
96*69d3ba3dSThéo Degioanni 
97*69d3ba3dSThéo Degioanni   for (Operation &op : getBody().getOps()) {
98*69d3ba3dSThéo Degioanni     TypeSwitch<Operation *>(&op)
99*69d3ba3dSThéo Degioanni         .Case<OperandsOp>(
100*69d3ba3dSThéo Degioanni             [&](OperandsOp op) { insertNames("operands", op.getNames()); })
101*69d3ba3dSThéo Degioanni         .Case<ResultsOp>(
102*69d3ba3dSThéo Degioanni             [&](ResultsOp op) { insertNames("results", op.getNames()); })
103*69d3ba3dSThéo Degioanni         .Case<RegionsOp>(
104*69d3ba3dSThéo Degioanni             [&](RegionsOp op) { insertNames("regions", op.getNames()); });
105*69d3ba3dSThéo Degioanni   }
106*69d3ba3dSThéo Degioanni 
107*69d3ba3dSThéo Degioanni   // Verify that no two operand, result or region share the same name.
108*69d3ba3dSThéo Degioanni   // The absence of duplicates within each value kind is checked by the
109*69d3ba3dSThéo Degioanni   // associated operation's verifier.
110*69d3ba3dSThéo Degioanni   for (size_t i : llvm::seq(valueNames.size())) {
111*69d3ba3dSThéo Degioanni     for (size_t j : llvm::seq(i + 1, valueNames.size())) {
112*69d3ba3dSThéo Degioanni       auto [lhs, lhsSet] = valueNames[i];
113*69d3ba3dSThéo Degioanni       auto &[rhs, rhsSet] = valueNames[j];
114*69d3ba3dSThéo Degioanni       llvm::set_intersect(lhsSet, rhsSet);
115*69d3ba3dSThéo Degioanni       if (!lhsSet.empty())
116*69d3ba3dSThéo Degioanni         return emitOpError("contains a value named '")
117*69d3ba3dSThéo Degioanni                << *lhsSet.begin() << "' for both its " << lhs << " and " << rhs;
118*69d3ba3dSThéo Degioanni     }
119*69d3ba3dSThéo Degioanni   }
1206971b83bSMathieu Fehr 
1216971b83bSMathieu Fehr   return success();
1226971b83bSMathieu Fehr }
1236971b83bSMathieu Fehr 
124*69d3ba3dSThéo Degioanni static LogicalResult verifyNames(Operation *op, StringRef kindName,
125*69d3ba3dSThéo Degioanni                                  ArrayAttr names, size_t numOperands) {
126*69d3ba3dSThéo Degioanni   if (numOperands != names.size())
127*69d3ba3dSThéo Degioanni     return op->emitOpError()
128*69d3ba3dSThéo Degioanni            << "the number of " << kindName
129*69d3ba3dSThéo Degioanni            << "s and their names must be "
130*69d3ba3dSThéo Degioanni               "the same, but got "
131*69d3ba3dSThéo Degioanni            << numOperands << " and " << names.size() << " respectively";
132*69d3ba3dSThéo Degioanni 
133*69d3ba3dSThéo Degioanni   DenseMap<StringRef, size_t> nameMap;
134*69d3ba3dSThéo Degioanni   for (auto [i, name] : llvm::enumerate(names)) {
135*69d3ba3dSThéo Degioanni     StringRef nameRef = llvm::cast<StringAttr>(name).getValue();
136*69d3ba3dSThéo Degioanni     if (nameRef.empty())
137*69d3ba3dSThéo Degioanni       return op->emitOpError()
138*69d3ba3dSThéo Degioanni              << "name of " << kindName << " #" << i << " is empty";
139*69d3ba3dSThéo Degioanni     if (!llvm::isAlpha(nameRef[0]) && nameRef[0] != '_')
140*69d3ba3dSThéo Degioanni       return op->emitOpError()
141*69d3ba3dSThéo Degioanni              << "name of " << kindName << " #" << i
142*69d3ba3dSThéo Degioanni              << " must start with either a letter or an underscore";
143*69d3ba3dSThéo Degioanni     if (llvm::any_of(nameRef,
144*69d3ba3dSThéo Degioanni                      [](char c) { return !llvm::isAlnum(c) && c != '_'; }))
145*69d3ba3dSThéo Degioanni       return op->emitOpError()
146*69d3ba3dSThéo Degioanni              << "name of " << kindName << " #" << i
147*69d3ba3dSThéo Degioanni              << " must contain only letters, digits and underscores";
148*69d3ba3dSThéo Degioanni     if (nameMap.contains(nameRef))
149*69d3ba3dSThéo Degioanni       return op->emitOpError() << "name of " << kindName << " #" << i
150*69d3ba3dSThéo Degioanni                                << " is a duplicate of the name of " << kindName
151*69d3ba3dSThéo Degioanni                                << " #" << nameMap[nameRef];
152*69d3ba3dSThéo Degioanni     nameMap.insert({nameRef, i});
153*69d3ba3dSThéo Degioanni   }
154*69d3ba3dSThéo Degioanni 
155*69d3ba3dSThéo Degioanni   return success();
156*69d3ba3dSThéo Degioanni }
157*69d3ba3dSThéo Degioanni 
158*69d3ba3dSThéo Degioanni LogicalResult ParametersOp::verify() {
159*69d3ba3dSThéo Degioanni   return verifyNames(*this, "parameter", getNames(), getNumOperands());
160*69d3ba3dSThéo Degioanni }
161*69d3ba3dSThéo Degioanni 
162*69d3ba3dSThéo Degioanni template <typename ValueListOp>
163*69d3ba3dSThéo Degioanni static LogicalResult verifyOperandsResultsCommon(ValueListOp op,
164*69d3ba3dSThéo Degioanni                                                  StringRef kindName) {
165*69d3ba3dSThéo Degioanni   size_t numVariadicities = op.getVariadicity().size();
166*69d3ba3dSThéo Degioanni   size_t numOperands = op.getNumOperands();
1676971b83bSMathieu Fehr 
1686971b83bSMathieu Fehr   if (numOperands != numVariadicities)
169*69d3ba3dSThéo Degioanni     return op.emitOpError()
170*69d3ba3dSThéo Degioanni            << "the number of " << kindName
171*69d3ba3dSThéo Degioanni            << "s and their variadicities must be "
1726971b83bSMathieu Fehr               "the same, but got "
1736971b83bSMathieu Fehr            << numOperands << " and " << numVariadicities << " respectively";
1746971b83bSMathieu Fehr 
175*69d3ba3dSThéo Degioanni   return verifyNames(op, kindName, op.getNames(), numOperands);
176*69d3ba3dSThéo Degioanni }
177*69d3ba3dSThéo Degioanni 
178*69d3ba3dSThéo Degioanni LogicalResult OperandsOp::verify() {
179*69d3ba3dSThéo Degioanni   return verifyOperandsResultsCommon(*this, "operand");
180*69d3ba3dSThéo Degioanni }
181*69d3ba3dSThéo Degioanni 
182*69d3ba3dSThéo Degioanni LogicalResult ResultsOp::verify() {
183*69d3ba3dSThéo Degioanni   return verifyOperandsResultsCommon(*this, "result");
1846971b83bSMathieu Fehr }
1856971b83bSMathieu Fehr 
186f1a04029SDaniil Dudkin LogicalResult AttributesOp::verify() {
1876971b83bSMathieu Fehr   size_t namesSize = getAttributeValueNames().size();
1886971b83bSMathieu Fehr   size_t valuesSize = getAttributeValues().size();
189f1a04029SDaniil Dudkin 
190f1a04029SDaniil Dudkin   if (namesSize != valuesSize)
191f1a04029SDaniil Dudkin     return emitOpError()
192f1a04029SDaniil Dudkin            << "the number of attribute names and their constraints must be "
193f1a04029SDaniil Dudkin               "the same but got "
194f1a04029SDaniil Dudkin            << namesSize << " and " << valuesSize << " respectively";
195f1a04029SDaniil Dudkin 
196f1a04029SDaniil Dudkin   return success();
197f1a04029SDaniil Dudkin }
198f1a04029SDaniil Dudkin 
199914cfa41SFehr Mathieu LogicalResult BaseOp::verify() {
200914cfa41SFehr Mathieu   std::optional<StringRef> baseName = getBaseName();
201914cfa41SFehr Mathieu   std::optional<SymbolRefAttr> baseRef = getBaseRef();
202914cfa41SFehr Mathieu   if (baseName.has_value() == baseRef.has_value())
203914cfa41SFehr Mathieu     return emitOpError() << "the base type or attribute should be specified by "
204914cfa41SFehr Mathieu                             "either a name or a reference";
205914cfa41SFehr Mathieu 
206914cfa41SFehr Mathieu   if (baseName &&
207914cfa41SFehr Mathieu       (baseName->empty() || ((*baseName)[0] != '!' && (*baseName)[0] != '#')))
208914cfa41SFehr Mathieu     return emitOpError() << "the base type or attribute name should start with "
209914cfa41SFehr Mathieu                             "'!' or '#'";
210914cfa41SFehr Mathieu 
211914cfa41SFehr Mathieu   return success();
212914cfa41SFehr Mathieu }
213914cfa41SFehr Mathieu 
214b86a9c5bSThéo Degioanni /// Finds whether the provided symbol is an IRDL type or attribute definition.
215b86a9c5bSThéo Degioanni /// The source operation must be within a DialectOp.
216f6ae8e63SThéo Degioanni static LogicalResult
217f6ae8e63SThéo Degioanni checkSymbolIsTypeOrAttribute(SymbolTableCollection &symbolTable,
218f6ae8e63SThéo Degioanni                              Operation *source, SymbolRefAttr symbol) {
219b86a9c5bSThéo Degioanni   Operation *targetOp =
220b86a9c5bSThéo Degioanni       irdl::lookupSymbolNearDialect(symbolTable, source, symbol);
221b86a9c5bSThéo Degioanni 
222f6ae8e63SThéo Degioanni   if (!targetOp)
223f6ae8e63SThéo Degioanni     return source->emitOpError() << "symbol '" << symbol << "' not found";
224f6ae8e63SThéo Degioanni 
225f6ae8e63SThéo Degioanni   if (!isa<TypeOp, AttributeOp>(targetOp))
226f6ae8e63SThéo Degioanni     return source->emitOpError() << "symbol '" << symbol
227f6ae8e63SThéo Degioanni                                  << "' does not refer to a type or attribute "
228f6ae8e63SThéo Degioanni                                     "definition (refers to '"
229f6ae8e63SThéo Degioanni                                  << targetOp->getName() << "')";
230f6ae8e63SThéo Degioanni 
231f6ae8e63SThéo Degioanni   return success();
232f6ae8e63SThéo Degioanni }
233f6ae8e63SThéo Degioanni 
234914cfa41SFehr Mathieu LogicalResult BaseOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
235914cfa41SFehr Mathieu   std::optional<SymbolRefAttr> baseRef = getBaseRef();
236914cfa41SFehr Mathieu   if (!baseRef)
237914cfa41SFehr Mathieu     return success();
238914cfa41SFehr Mathieu 
239f6ae8e63SThéo Degioanni   return checkSymbolIsTypeOrAttribute(symbolTable, *this, *baseRef);
240f6ae8e63SThéo Degioanni }
241f6ae8e63SThéo Degioanni 
242f6ae8e63SThéo Degioanni LogicalResult
243f6ae8e63SThéo Degioanni ParametricOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
244f6ae8e63SThéo Degioanni   std::optional<SymbolRefAttr> baseRef = getBaseType();
245f6ae8e63SThéo Degioanni   if (!baseRef)
246914cfa41SFehr Mathieu     return success();
247914cfa41SFehr Mathieu 
248f6ae8e63SThéo Degioanni   return checkSymbolIsTypeOrAttribute(symbolTable, *this, *baseRef);
249914cfa41SFehr Mathieu }
250914cfa41SFehr Mathieu 
2516971b83bSMathieu Fehr /// Parse a value with its variadicity first. By default, the variadicity is
2526971b83bSMathieu Fehr /// single.
2536971b83bSMathieu Fehr ///
2546971b83bSMathieu Fehr /// value-with-variadicity ::= ("single" | "optional" | "variadic")? ssa-value
2556971b83bSMathieu Fehr static ParseResult
2566971b83bSMathieu Fehr parseValueWithVariadicity(OpAsmParser &p,
2576971b83bSMathieu Fehr                           OpAsmParser::UnresolvedOperand &operand,
2586971b83bSMathieu Fehr                           VariadicityAttr &variadicityAttr) {
2596971b83bSMathieu Fehr   MLIRContext *ctx = p.getBuilder().getContext();
2606971b83bSMathieu Fehr 
2616971b83bSMathieu Fehr   // Parse the variadicity, if present
2626971b83bSMathieu Fehr   if (p.parseOptionalKeyword("single").succeeded()) {
2636971b83bSMathieu Fehr     variadicityAttr = VariadicityAttr::get(ctx, Variadicity::single);
2646971b83bSMathieu Fehr   } else if (p.parseOptionalKeyword("optional").succeeded()) {
2656971b83bSMathieu Fehr     variadicityAttr = VariadicityAttr::get(ctx, Variadicity::optional);
2666971b83bSMathieu Fehr   } else if (p.parseOptionalKeyword("variadic").succeeded()) {
2676971b83bSMathieu Fehr     variadicityAttr = VariadicityAttr::get(ctx, Variadicity::variadic);
2686971b83bSMathieu Fehr   } else {
2696971b83bSMathieu Fehr     variadicityAttr = VariadicityAttr::get(ctx, Variadicity::single);
2706971b83bSMathieu Fehr   }
2716971b83bSMathieu Fehr 
2726971b83bSMathieu Fehr   // Parse the value
2736971b83bSMathieu Fehr   if (p.parseOperand(operand))
2746971b83bSMathieu Fehr     return failure();
2756971b83bSMathieu Fehr   return success();
2766971b83bSMathieu Fehr }
2776971b83bSMathieu Fehr 
278*69d3ba3dSThéo Degioanni static ParseResult parseNamedValueListImpl(
2796971b83bSMathieu Fehr     OpAsmParser &p, SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands,
280*69d3ba3dSThéo Degioanni     ArrayAttr &valueNamesAttr, VariadicityArrayAttr *variadicityAttr) {
2816971b83bSMathieu Fehr   Builder &builder = p.getBuilder();
2826971b83bSMathieu Fehr   MLIRContext *ctx = builder.getContext();
283*69d3ba3dSThéo Degioanni   SmallVector<Attribute> valueNames;
2846971b83bSMathieu Fehr   SmallVector<VariadicityAttr> variadicities;
2856971b83bSMathieu Fehr 
2866971b83bSMathieu Fehr   // Parse a single value with its variadicity
2876971b83bSMathieu Fehr   auto parseOne = [&] {
288*69d3ba3dSThéo Degioanni     StringRef name;
2896971b83bSMathieu Fehr     OpAsmParser::UnresolvedOperand operand;
2906971b83bSMathieu Fehr     VariadicityAttr variadicity;
291*69d3ba3dSThéo Degioanni     if (p.parseKeyword(&name) || p.parseColon())
292*69d3ba3dSThéo Degioanni       return failure();
293*69d3ba3dSThéo Degioanni 
294*69d3ba3dSThéo Degioanni     if (variadicityAttr) {
2956971b83bSMathieu Fehr       if (parseValueWithVariadicity(p, operand, variadicity))
2966971b83bSMathieu Fehr         return failure();
2976971b83bSMathieu Fehr       variadicities.push_back(variadicity);
298*69d3ba3dSThéo Degioanni     } else {
299*69d3ba3dSThéo Degioanni       if (p.parseOperand(operand))
300*69d3ba3dSThéo Degioanni         return failure();
301*69d3ba3dSThéo Degioanni     }
302*69d3ba3dSThéo Degioanni 
303*69d3ba3dSThéo Degioanni     valueNames.push_back(StringAttr::get(ctx, name));
304*69d3ba3dSThéo Degioanni     operands.push_back(operand);
3056971b83bSMathieu Fehr     return success();
3066971b83bSMathieu Fehr   };
3076971b83bSMathieu Fehr 
3086971b83bSMathieu Fehr   if (p.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren, parseOne))
3096971b83bSMathieu Fehr     return failure();
310*69d3ba3dSThéo Degioanni   valueNamesAttr = ArrayAttr::get(ctx, valueNames);
311*69d3ba3dSThéo Degioanni   if (variadicityAttr)
312*69d3ba3dSThéo Degioanni     *variadicityAttr = VariadicityArrayAttr::get(ctx, variadicities);
3136971b83bSMathieu Fehr   return success();
3146971b83bSMathieu Fehr }
3156971b83bSMathieu Fehr 
316*69d3ba3dSThéo Degioanni /// Parse a list of named values.
317*69d3ba3dSThéo Degioanni ///
318*69d3ba3dSThéo Degioanni /// values ::=
319*69d3ba3dSThéo Degioanni ///   `(` (named-value (`,` named-value)*)? `)`
320*69d3ba3dSThéo Degioanni /// named-value := bare-id `:` ssa-value
321*69d3ba3dSThéo Degioanni static ParseResult
322*69d3ba3dSThéo Degioanni parseNamedValueList(OpAsmParser &p,
323*69d3ba3dSThéo Degioanni                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands,
324*69d3ba3dSThéo Degioanni                     ArrayAttr &valueNamesAttr) {
325*69d3ba3dSThéo Degioanni   return parseNamedValueListImpl(p, operands, valueNamesAttr, nullptr);
326*69d3ba3dSThéo Degioanni }
327*69d3ba3dSThéo Degioanni 
328*69d3ba3dSThéo Degioanni /// Parse a list of named values with their variadicities first. By default, the
3296971b83bSMathieu Fehr /// variadicity is single.
3306971b83bSMathieu Fehr ///
3316971b83bSMathieu Fehr /// values-with-variadicity ::=
3326971b83bSMathieu Fehr ///   `(` (value-with-variadicity (`,` value-with-variadicity)*)? `)`
333*69d3ba3dSThéo Degioanni /// value-with-variadicity
334*69d3ba3dSThéo Degioanni ///   ::= bare-id `:` ("single" | "optional" | "variadic")? ssa-value
335*69d3ba3dSThéo Degioanni static ParseResult parseNamedValueListWithVariadicity(
336*69d3ba3dSThéo Degioanni     OpAsmParser &p, SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands,
337*69d3ba3dSThéo Degioanni     ArrayAttr &valueNamesAttr, VariadicityArrayAttr &variadicityAttr) {
338*69d3ba3dSThéo Degioanni   return parseNamedValueListImpl(p, operands, valueNamesAttr, &variadicityAttr);
339*69d3ba3dSThéo Degioanni }
340*69d3ba3dSThéo Degioanni 
341*69d3ba3dSThéo Degioanni static void printNamedValueListImpl(OpAsmPrinter &p, Operation *op,
3426971b83bSMathieu Fehr                                     OperandRange operands,
343*69d3ba3dSThéo Degioanni                                     ArrayAttr valueNamesAttr,
3446971b83bSMathieu Fehr                                     VariadicityArrayAttr variadicityAttr) {
3456971b83bSMathieu Fehr   p << "(";
3466971b83bSMathieu Fehr   interleaveComma(llvm::seq<int>(0, operands.size()), p, [&](int i) {
347*69d3ba3dSThéo Degioanni     p << llvm::cast<StringAttr>(valueNamesAttr[i]).getValue() << ": ";
348*69d3ba3dSThéo Degioanni     if (variadicityAttr) {
3496971b83bSMathieu Fehr       Variadicity variadicity = variadicityAttr[i].getValue();
3506971b83bSMathieu Fehr       if (variadicity != Variadicity::single) {
3516971b83bSMathieu Fehr         p << stringifyVariadicity(variadicity) << " ";
3526971b83bSMathieu Fehr       }
353*69d3ba3dSThéo Degioanni     }
3546971b83bSMathieu Fehr     p << operands[i];
3556971b83bSMathieu Fehr   });
3566971b83bSMathieu Fehr   p << ")";
3576971b83bSMathieu Fehr }
3586971b83bSMathieu Fehr 
359*69d3ba3dSThéo Degioanni /// Print a list of named values.
360*69d3ba3dSThéo Degioanni ///
361*69d3ba3dSThéo Degioanni /// values ::=
362*69d3ba3dSThéo Degioanni ///   `(` (named-value (`,` named-value)*)? `)`
363*69d3ba3dSThéo Degioanni /// named-value := bare-id `:` ssa-value
364*69d3ba3dSThéo Degioanni static void printNamedValueList(OpAsmPrinter &p, Operation *op,
365*69d3ba3dSThéo Degioanni                                 OperandRange operands,
366*69d3ba3dSThéo Degioanni                                 ArrayAttr valueNamesAttr) {
367*69d3ba3dSThéo Degioanni   printNamedValueListImpl(p, op, operands, valueNamesAttr, nullptr);
368*69d3ba3dSThéo Degioanni }
369*69d3ba3dSThéo Degioanni 
370*69d3ba3dSThéo Degioanni /// Print a list of named values with their variadicities first. By default, the
371*69d3ba3dSThéo Degioanni /// variadicity is single.
372*69d3ba3dSThéo Degioanni ///
373*69d3ba3dSThéo Degioanni /// values-with-variadicity ::=
374*69d3ba3dSThéo Degioanni ///   `(` (value-with-variadicity (`,` value-with-variadicity)*)? `)`
375*69d3ba3dSThéo Degioanni /// value-with-variadicity ::=
376*69d3ba3dSThéo Degioanni ///   bare-id `:` ("single" | "optional" | "variadic")? ssa-value
377*69d3ba3dSThéo Degioanni static void printNamedValueListWithVariadicity(
378*69d3ba3dSThéo Degioanni     OpAsmPrinter &p, Operation *op, OperandRange operands,
379*69d3ba3dSThéo Degioanni     ArrayAttr valueNamesAttr, VariadicityArrayAttr variadicityAttr) {
380*69d3ba3dSThéo Degioanni   printNamedValueListImpl(p, op, operands, valueNamesAttr, variadicityAttr);
381*69d3ba3dSThéo Degioanni }
382*69d3ba3dSThéo Degioanni 
383f1a04029SDaniil Dudkin static ParseResult
384f1a04029SDaniil Dudkin parseAttributesOp(OpAsmParser &p,
385f1a04029SDaniil Dudkin                   SmallVectorImpl<OpAsmParser::UnresolvedOperand> &attrOperands,
386f1a04029SDaniil Dudkin                   ArrayAttr &attrNamesAttr) {
387f1a04029SDaniil Dudkin   Builder &builder = p.getBuilder();
388f1a04029SDaniil Dudkin   SmallVector<Attribute> attrNames;
389f1a04029SDaniil Dudkin   if (succeeded(p.parseOptionalLBrace())) {
390f1a04029SDaniil Dudkin     auto parseOperands = [&]() {
391f1a04029SDaniil Dudkin       if (p.parseAttribute(attrNames.emplace_back()) || p.parseEqual() ||
392f1a04029SDaniil Dudkin           p.parseOperand(attrOperands.emplace_back()))
393f1a04029SDaniil Dudkin         return failure();
394f1a04029SDaniil Dudkin       return success();
395f1a04029SDaniil Dudkin     };
396f1a04029SDaniil Dudkin     if (p.parseCommaSeparatedList(parseOperands) || p.parseRBrace())
397f1a04029SDaniil Dudkin       return failure();
398f1a04029SDaniil Dudkin   }
399f1a04029SDaniil Dudkin   attrNamesAttr = builder.getArrayAttr(attrNames);
400f1a04029SDaniil Dudkin   return success();
401f1a04029SDaniil Dudkin }
402f1a04029SDaniil Dudkin 
403f1a04029SDaniil Dudkin static void printAttributesOp(OpAsmPrinter &p, AttributesOp op,
404f1a04029SDaniil Dudkin                               OperandRange attrArgs, ArrayAttr attrNames) {
405f1a04029SDaniil Dudkin   if (attrNames.empty())
406f1a04029SDaniil Dudkin     return;
407f1a04029SDaniil Dudkin   p << "{";
408f1a04029SDaniil Dudkin   interleaveComma(llvm::seq<int>(0, attrNames.size()), p,
409f1a04029SDaniil Dudkin                   [&](int i) { p << attrNames[i] << " = " << attrArgs[i]; });
410f1a04029SDaniil Dudkin   p << '}';
411f1a04029SDaniil Dudkin }
412f1a04029SDaniil Dudkin 
413d4bde696SDaniil Dudkin LogicalResult RegionOp::verify() {
414d4bde696SDaniil Dudkin   if (IntegerAttr numberOfBlocks = getNumberOfBlocksAttr())
415d4bde696SDaniil Dudkin     if (int64_t number = numberOfBlocks.getInt(); number <= 0) {
416d4bde696SDaniil Dudkin       return emitOpError("the number of blocks is expected to be >= 1 but got ")
417d4bde696SDaniil Dudkin              << number;
418d4bde696SDaniil Dudkin     }
419d4bde696SDaniil Dudkin   return success();
420d4bde696SDaniil Dudkin }
421d4bde696SDaniil Dudkin 
422*69d3ba3dSThéo Degioanni LogicalResult RegionsOp::verify() {
423*69d3ba3dSThéo Degioanni   return verifyNames(*this, "region", getNames(), getNumOperands());
424*69d3ba3dSThéo Degioanni }
425*69d3ba3dSThéo Degioanni 
426c8a581c3SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLInterfaces.cpp.inc"
427c8a581c3SMathieu Fehr 
4280e0db0a4SMathieu Fehr #define GET_TYPEDEF_CLASSES
4290e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc"
4300e0db0a4SMathieu Fehr 
4316971b83bSMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLEnums.cpp.inc"
4326971b83bSMathieu Fehr 
4336971b83bSMathieu Fehr #define GET_ATTRDEF_CLASSES
4346971b83bSMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLAttributes.cpp.inc"
4356971b83bSMathieu Fehr 
4360e0db0a4SMathieu Fehr #define GET_OP_CLASSES
4370e0db0a4SMathieu Fehr #include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc"
438