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 ®ion) { 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 ®ion) { 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