MLIR  18.0.0git
IRDL.cpp
Go to the documentation of this file.
1 //===- IRDL.cpp - IRDL dialect ----------------------------------*- C++ -*-===//
2 //
3 // This file is licensed 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 #include "mlir/IR/Builders.h"
12 #include "mlir/IR/Diagnostics.h"
15 #include "mlir/IR/OpDefinition.h"
17 #include "mlir/IR/Operation.h"
18 #include "mlir/Support/LLVM.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/TypeSwitch.h"
22 #include "llvm/IR/Metadata.h"
23 #include "llvm/Support/Casting.h"
24 
25 using namespace mlir;
26 using namespace mlir::irdl;
27 
28 //===----------------------------------------------------------------------===//
29 // IRDL dialect.
30 //===----------------------------------------------------------------------===//
31 
32 #include "mlir/Dialect/IRDL/IR/IRDL.cpp.inc"
33 
34 #include "mlir/Dialect/IRDL/IR/IRDLDialect.cpp.inc"
35 
36 void IRDLDialect::initialize() {
37  addOperations<
38 #define GET_OP_LIST
39 #include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc"
40  >();
41  addTypes<
42 #define GET_TYPEDEF_LIST
43 #include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc"
44  >();
45  addAttributes<
46 #define GET_ATTRDEF_LIST
47 #include "mlir/Dialect/IRDL/IR/IRDLAttributes.cpp.inc"
48  >();
49 }
50 
51 //===----------------------------------------------------------------------===//
52 // Parsing/Printing
53 //===----------------------------------------------------------------------===//
54 
55 /// Parse a region, and add a single block if the region is empty.
56 /// If no region is parsed, create a new region with a single empty block.
58  auto regionParseRes = p.parseOptionalRegion(region);
59  if (regionParseRes.has_value() && failed(regionParseRes.value()))
60  return failure();
61 
62  // If the region is empty, add a single empty block.
63  if (region.empty())
64  region.push_back(new Block());
65 
66  return success();
67 }
68 
70  Region &region) {
71  if (!region.getBlocks().front().empty())
72  p.printRegion(region);
73 }
74 
76  if (!Dialect::isValidNamespace(getName()))
77  return emitOpError("invalid dialect name");
78  return success();
79 }
80 
82  size_t numVariadicities = getVariadicity().size();
83  size_t numOperands = getNumOperands();
84 
85  if (numOperands != numVariadicities)
86  return emitOpError()
87  << "the number of operands and their variadicities must be "
88  "the same, but got "
89  << numOperands << " and " << numVariadicities << " respectively";
90 
91  return success();
92 }
93 
95  size_t numVariadicities = getVariadicity().size();
96  size_t numOperands = this->getNumOperands();
97 
98  if (numOperands != numVariadicities)
99  return emitOpError()
100  << "the number of operands and their variadicities must be "
101  "the same, but got "
102  << numOperands << " and " << numVariadicities << " respectively";
103 
104  return success();
105 }
106 
108  size_t namesSize = getAttributeValueNames().size();
109  size_t valuesSize = getAttributeValues().size();
110 
111  if (namesSize != valuesSize)
112  return emitOpError()
113  << "the number of attribute names and their constraints must be "
114  "the same but got "
115  << namesSize << " and " << valuesSize << " respectively";
116 
117  return success();
118 }
119 
120 /// Parse a value with its variadicity first. By default, the variadicity is
121 /// single.
122 ///
123 /// value-with-variadicity ::= ("single" | "optional" | "variadic")? ssa-value
124 static ParseResult
127  VariadicityAttr &variadicityAttr) {
128  MLIRContext *ctx = p.getBuilder().getContext();
129 
130  // Parse the variadicity, if present
131  if (p.parseOptionalKeyword("single").succeeded()) {
132  variadicityAttr = VariadicityAttr::get(ctx, Variadicity::single);
133  } else if (p.parseOptionalKeyword("optional").succeeded()) {
134  variadicityAttr = VariadicityAttr::get(ctx, Variadicity::optional);
135  } else if (p.parseOptionalKeyword("variadic").succeeded()) {
136  variadicityAttr = VariadicityAttr::get(ctx, Variadicity::variadic);
137  } else {
138  variadicityAttr = VariadicityAttr::get(ctx, Variadicity::single);
139  }
140 
141  // Parse the value
142  if (p.parseOperand(operand))
143  return failure();
144  return success();
145 }
146 
147 /// Parse a list of values with their variadicities first. By default, the
148 /// variadicity is single.
149 ///
150 /// values-with-variadicity ::=
151 /// `(` (value-with-variadicity (`,` value-with-variadicity)*)? `)`
152 /// value-with-variadicity ::= ("single" | "optional" | "variadic")? ssa-value
155  VariadicityArrayAttr &variadicityAttr) {
156  Builder &builder = p.getBuilder();
157  MLIRContext *ctx = builder.getContext();
158  SmallVector<VariadicityAttr> variadicities;
159 
160  // Parse a single value with its variadicity
161  auto parseOne = [&] {
163  VariadicityAttr variadicity;
164  if (parseValueWithVariadicity(p, operand, variadicity))
165  return failure();
166  operands.push_back(operand);
167  variadicities.push_back(variadicity);
168  return success();
169  };
170 
172  return failure();
173  variadicityAttr = VariadicityArrayAttr::get(ctx, variadicities);
174  return success();
175 }
176 
177 /// Print a list of values with their variadicities first. By default, the
178 /// variadicity is single.
179 ///
180 /// values-with-variadicity ::=
181 /// `(` (value-with-variadicity (`,` value-with-variadicity)*)? `)`
182 /// value-with-variadicity ::= ("single" | "optional" | "variadic")? ssa-value
184  OperandRange operands,
185  VariadicityArrayAttr variadicityAttr) {
186  p << "(";
187  interleaveComma(llvm::seq<int>(0, operands.size()), p, [&](int i) {
188  Variadicity variadicity = variadicityAttr[i].getValue();
189  if (variadicity != Variadicity::single) {
190  p << stringifyVariadicity(variadicity) << " ";
191  }
192  p << operands[i];
193  });
194  p << ")";
195 }
196 
197 static ParseResult
200  ArrayAttr &attrNamesAttr) {
201  Builder &builder = p.getBuilder();
202  SmallVector<Attribute> attrNames;
203  if (succeeded(p.parseOptionalLBrace())) {
204  auto parseOperands = [&]() {
205  if (p.parseAttribute(attrNames.emplace_back()) || p.parseEqual() ||
206  p.parseOperand(attrOperands.emplace_back()))
207  return failure();
208  return success();
209  };
210  if (p.parseCommaSeparatedList(parseOperands) || p.parseRBrace())
211  return failure();
212  }
213  attrNamesAttr = builder.getArrayAttr(attrNames);
214  return success();
215 }
216 
217 static void printAttributesOp(OpAsmPrinter &p, AttributesOp op,
218  OperandRange attrArgs, ArrayAttr attrNames) {
219  if (attrNames.empty())
220  return;
221  p << "{";
222  interleaveComma(llvm::seq<int>(0, attrNames.size()), p,
223  [&](int i) { p << attrNames[i] << " = " << attrArgs[i]; });
224  p << '}';
225 }
226 
228  if (IntegerAttr numberOfBlocks = getNumberOfBlocksAttr())
229  if (int64_t number = numberOfBlocks.getInt(); number <= 0) {
230  return emitOpError("the number of blocks is expected to be >= 1 but got ")
231  << number;
232  }
233  return success();
234 }
235 
236 #include "mlir/Dialect/IRDL/IR/IRDLInterfaces.cpp.inc"
237 
238 #define GET_TYPEDEF_CLASSES
239 #include "mlir/Dialect/IRDL/IR/IRDLTypesGen.cpp.inc"
240 
241 #include "mlir/Dialect/IRDL/IR/IRDLEnums.cpp.inc"
242 
243 #define GET_ATTRDEF_CLASSES
244 #include "mlir/Dialect/IRDL/IR/IRDLAttributes.cpp.inc"
245 
246 #define GET_OP_CLASSES
247 #include "mlir/Dialect/IRDL/IR/IRDLOps.cpp.inc"
static ParseResult parseValueWithVariadicity(OpAsmParser &p, OpAsmParser::UnresolvedOperand &operand, VariadicityAttr &variadicityAttr)
Parse a value with its variadicity first.
Definition: IRDL.cpp:125
static void printAttributesOp(OpAsmPrinter &p, AttributesOp op, OperandRange attrArgs, ArrayAttr attrNames)
Definition: IRDL.cpp:217
static ParseResult parseValuesWithVariadicity(OpAsmParser &p, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands, VariadicityArrayAttr &variadicityAttr)
Parse a list of values with their variadicities first.
Definition: IRDL.cpp:153
static ParseResult parseSingleBlockRegion(OpAsmParser &p, Region &region)
Parse a region, and add a single block if the region is empty.
Definition: IRDL.cpp:57
static ParseResult parseAttributesOp(OpAsmParser &p, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &attrOperands, ArrayAttr &attrNamesAttr)
Definition: IRDL.cpp:198
static void printSingleBlockRegion(OpAsmPrinter &p, Operation *op, Region &region)
Definition: IRDL.cpp:69
static void printValuesWithVariadicity(OpAsmPrinter &p, Operation *op, OperandRange operands, VariadicityArrayAttr variadicityAttr)
Print a list of values with their variadicities first.
Definition: IRDL.cpp:183
@ Paren
Parens 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 ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
virtual ParseResult parseRBrace()=0
Parse a } token.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
virtual ParseResult parseOptionalLBrace()=0
Parse a { token if present.
Block represents an ordered list of Operations.
Definition: Block.h:30
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
MLIRContext * getContext() const
Definition: Builders.h:55
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition: Builders.cpp:273
static bool isValidNamespace(StringRef str)
Utility function that returns if the given string is a valid dialect namespace.
Definition: Dialect.cpp:92
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual OptionalParseResult parseOptionalRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
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.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
void push_back(Block *block)
Definition: Region.h:61
bool empty()
Definition: Region.h:60
BlockListType & getBlocks()
Definition: Region.h:45
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:421
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
bool succeeded() const
Returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:41
This is the representation of an operand reference.