MLIR 23.0.0git
Async.cpp
Go to the documentation of this file.
1//===- Async.cpp - MLIR Async Operations ----------------------------------===//
2//
3// Part of the LLVM Project, 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
13#include "llvm/ADT/TypeSwitch.h"
14
15using namespace mlir;
16using namespace mlir::async;
17
18#include "mlir/Dialect/Async/IR/AsyncOpsDialect.cpp.inc"
19
20void AsyncDialect::initialize() {
21 addOperations<
22#define GET_OP_LIST
23#include "mlir/Dialect/Async/IR/AsyncOps.cpp.inc"
24 >();
25 addTypes<
26#define GET_TYPEDEF_LIST
27#include "mlir/Dialect/Async/IR/AsyncOpsTypes.cpp.inc"
28 >();
29}
30
31//===----------------------------------------------------------------------===//
32/// ExecuteOp
33//===----------------------------------------------------------------------===//
34
35constexpr char kOperandSegmentSizesAttr[] = "operandSegmentSizes";
36
37OperandRange ExecuteOp::getEntrySuccessorOperands(RegionSuccessor successor) {
38 assert(successor.getSuccessor() == &getBodyRegion() &&
39 "invalid region index");
40 return getBodyOperands();
41}
42
43bool ExecuteOp::areTypesCompatible(Type lhs, Type rhs) {
44 const auto getValueOrTokenType = [](Type type) {
45 if (auto value = llvm::dyn_cast<ValueType>(type))
46 return value.getValueType();
47 return type;
48 };
49 return getValueOrTokenType(lhs) == getValueOrTokenType(rhs);
50}
51
52void ExecuteOp::getSuccessorRegions(RegionBranchPoint point,
54 // The `body` region branch back to the parent operation.
55 if (!point.isParent() &&
56 point.getTerminatorPredecessorOrNull()->getParentRegion() ==
57 &getBodyRegion()) {
58 regions.push_back(RegionSuccessor::parent());
59 return;
60 }
61
62 // Otherwise the successor is the body region.
63 regions.push_back(RegionSuccessor(&getBodyRegion()));
64}
65
66ValueRange ExecuteOp::getSuccessorInputs(RegionSuccessor successor) {
67 return successor.isParent() ? ValueRange(getBodyResults())
68 : ValueRange(getBodyRegion().getArguments());
69}
70
71void ExecuteOp::build(OpBuilder &builder, OperationState &result,
72 TypeRange resultTypes, ValueRange dependencies,
73 ValueRange operands, BodyBuilderFn bodyBuilder) {
74 OpBuilder::InsertionGuard guard(builder);
75 result.addOperands(dependencies);
76 result.addOperands(operands);
77
78 // Add derived `operandSegmentSizes` attribute based on parsed operands.
79 int32_t numDependencies = dependencies.size();
80 int32_t numOperands = operands.size();
81 auto operandSegmentSizes =
82 builder.getDenseI32ArrayAttr({numDependencies, numOperands});
83 result.addAttribute(kOperandSegmentSizesAttr, operandSegmentSizes);
84
85 // First result is always a token, and then `resultTypes` wrapped into
86 // `async.value`.
87 result.addTypes({TokenType::get(result.getContext())});
88 for (Type type : resultTypes)
89 result.addTypes(ValueType::get(type));
90
91 // Add a body region with block arguments as unwrapped async value operands.
92 Region *bodyRegion = result.addRegion();
93 Block *bodyBlock = builder.createBlock(bodyRegion);
94 for (Value operand : operands) {
95 auto valueType = llvm::dyn_cast<ValueType>(operand.getType());
96 bodyBlock->addArgument(valueType ? valueType.getValueType()
97 : operand.getType(),
98 operand.getLoc());
99 }
100
101 // Create the default terminator if the builder is not provided and if the
102 // expected result is empty. Otherwise, leave this to the caller
103 // because we don't know which values to return from the execute op.
104 if (resultTypes.empty() && !bodyBuilder) {
105 async::YieldOp::create(builder, result.location, ValueRange());
106 } else if (bodyBuilder) {
107 bodyBuilder(builder, result.location, bodyBlock->getArguments());
108 }
109}
110
111void ExecuteOp::print(OpAsmPrinter &p) {
112 // [%tokens,...]
113 if (!getDependencies().empty())
114 p << " [" << getDependencies() << "]";
115
116 // (%value as %unwrapped: !async.value<!arg.type>, ...)
117 if (!getBodyOperands().empty()) {
118 p << " (";
119 Block *entry = getBodyRegion().empty() ? nullptr : &getBodyRegion().front();
120 llvm::interleaveComma(
121 getBodyOperands(), p, [&, n = 0](Value operand) mutable {
122 Value argument = entry ? entry->getArgument(n++) : Value();
123 p << operand << " as " << argument << ": " << operand.getType();
124 });
125 p << ")";
126 }
127
128 // -> (!async.value<!return.type>, ...)
129 p.printOptionalArrowTypeList(llvm::drop_begin(getResultTypes()));
130 p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
131 {kOperandSegmentSizesAttr});
132 p << ' ';
133 p.printRegion(getBodyRegion(), /*printEntryBlockArgs=*/false);
134}
135
136ParseResult ExecuteOp::parse(OpAsmParser &parser, OperationState &result) {
137 MLIRContext *ctx = result.getContext();
138
139 // Sizes of parsed variadic operands, will be updated below after parsing.
140 int32_t numDependencies = 0;
141
142 auto tokenTy = TokenType::get(ctx);
143
144 // Parse dependency tokens.
145 if (succeeded(parser.parseOptionalLSquare())) {
147 if (parser.parseOperandList(tokenArgs) ||
148 parser.resolveOperands(tokenArgs, tokenTy, result.operands) ||
149 parser.parseRSquare())
150 return failure();
151
152 numDependencies = tokenArgs.size();
153 }
154
155 // Parse async value operands (%value as %unwrapped : !async.value<!type>).
158 SmallVector<Type, 4> valueTypes;
159
160 // Parse a single instance of `%value as %unwrapped : !async.value<!type>`.
161 auto parseAsyncValueArg = [&]() -> ParseResult {
162 if (parser.parseOperand(valueArgs.emplace_back()) ||
163 parser.parseKeyword("as") ||
164 parser.parseArgument(unwrappedArgs.emplace_back()) ||
165 parser.parseColonType(valueTypes.emplace_back()))
166 return failure();
167
168 auto valueTy = llvm::dyn_cast<ValueType>(valueTypes.back());
169 unwrappedArgs.back().type = valueTy ? valueTy.getValueType() : Type();
170 return success();
171 };
172
173 auto argsLoc = parser.getCurrentLocation();
175 parseAsyncValueArg) ||
176 parser.resolveOperands(valueArgs, valueTypes, argsLoc, result.operands))
177 return failure();
178
179 int32_t numOperands = valueArgs.size();
180
181 // Add derived `operandSegmentSizes` attribute based on parsed operands.
182 auto operandSegmentSizes =
183 parser.getBuilder().getDenseI32ArrayAttr({numDependencies, numOperands});
184 result.addAttribute(kOperandSegmentSizesAttr, operandSegmentSizes);
185
186 // Parse the types of results returned from the async execute op.
187 SmallVector<Type, 4> resultTypes;
188 NamedAttrList attrs;
189 if (parser.parseOptionalArrowTypeList(resultTypes) ||
190 // Async execute first result is always a completion token.
191 parser.addTypeToList(tokenTy, result.types) ||
192 parser.addTypesToList(resultTypes, result.types) ||
193 // Parse operation attributes.
195 return failure();
196
197 result.addAttributes(attrs);
198
199 // Parse asynchronous region.
200 Region *body = result.addRegion();
201 return parser.parseRegion(*body, /*arguments=*/unwrappedArgs);
202}
203
204LogicalResult ExecuteOp::verifyRegions() {
205 // Unwrap async.execute value operands types.
206 auto unwrappedTypes = llvm::map_range(getBodyOperands(), [](Value operand) {
207 return llvm::cast<ValueType>(operand.getType()).getValueType();
208 });
209
210 // Verify that unwrapped argument types matches the body region arguments.
211 if (getBodyRegion().getArgumentTypes() != unwrappedTypes)
212 return emitOpError("async body region argument types do not match the "
213 "execute operation arguments types");
214
215 return success();
216}
217
218//===----------------------------------------------------------------------===//
219/// CreateGroupOp
220//===----------------------------------------------------------------------===//
221
222LogicalResult CreateGroupOp::canonicalize(CreateGroupOp op,
223 PatternRewriter &rewriter) {
224 // Find all `await_all` users of the group.
225 llvm::SmallVector<AwaitAllOp> awaitAllUsers;
226
227 auto isAwaitAll = [&](Operation *op) -> bool {
228 if (AwaitAllOp awaitAll = dyn_cast<AwaitAllOp>(op)) {
229 awaitAllUsers.push_back(awaitAll);
230 return true;
231 }
232 return false;
233 };
234
235 // Check if all users of the group are `await_all` operations.
236 if (!llvm::all_of(op->getUsers(), isAwaitAll))
237 return failure();
238
239 // If group is only awaited without adding anything to it, we can safely erase
240 // the create operation and all users.
241 for (AwaitAllOp awaitAll : awaitAllUsers)
242 rewriter.eraseOp(awaitAll);
243 rewriter.eraseOp(op);
244
245 return success();
246}
247
248//===----------------------------------------------------------------------===//
249/// AwaitOp
250//===----------------------------------------------------------------------===//
251
252void AwaitOp::build(OpBuilder &builder, OperationState &result, Value operand,
254 result.addOperands({operand});
255 result.attributes.append(attrs.begin(), attrs.end());
256
257 // Add unwrapped async.value type to the returned values types.
258 if (auto valueType = llvm::dyn_cast<ValueType>(operand.getType()))
259 result.addTypes(valueType.getValueType());
260}
261
262static ParseResult parseAwaitResultType(OpAsmParser &parser, Type &operandType,
263 Type &resultType) {
264 if (parser.parseType(operandType))
265 return failure();
266
267 // Add unwrapped async.value type to the returned values types.
268 if (auto valueType = llvm::dyn_cast<ValueType>(operandType))
269 resultType = valueType.getValueType();
270
271 return success();
272}
273
275 Type operandType, Type resultType) {
276 p << operandType;
277}
278
279LogicalResult AwaitOp::verify() {
280 Type argType = getOperand().getType();
281
282 // Awaiting on a token does not have any results.
283 if (llvm::isa<TokenType>(argType) && !getResultTypes().empty())
284 return emitOpError("awaiting on a token must have empty result");
285
286 // Awaiting on a value unwraps the async value type.
287 if (auto value = llvm::dyn_cast<ValueType>(argType)) {
288 if (*getResultType() != value.getValueType())
289 return emitOpError() << "result type " << *getResultType()
290 << " does not match async value type "
291 << value.getValueType();
292 }
293
294 return success();
295}
296
297//===----------------------------------------------------------------------===//
298// FuncOp
299//===----------------------------------------------------------------------===//
300
301void FuncOp::build(OpBuilder &builder, OperationState &state, StringRef name,
302 FunctionType type, ArrayRef<NamedAttribute> attrs,
303 ArrayRef<DictionaryAttr> argAttrs) {
305 builder.getStringAttr(name));
306 state.addAttribute(getFunctionTypeAttrName(state.name), TypeAttr::get(type));
307
308 state.attributes.append(attrs.begin(), attrs.end());
309 state.addRegion();
310
311 if (argAttrs.empty())
312 return;
313 assert(type.getNumInputs() == argAttrs.size());
315 builder, state, argAttrs, /*resultAttrs=*/{},
316 getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name));
317}
318
319ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
320 auto buildFuncType =
321 [](Builder &builder, ArrayRef<Type> argTypes, ArrayRef<Type> results,
323 std::string &) { return builder.getFunctionType(argTypes, results); };
324
326 parser, result, /*allowVariadic=*/false,
327 getFunctionTypeAttrName(result.name), buildFuncType,
328 getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
329}
330
331void FuncOp::print(OpAsmPrinter &p) {
333 p, *this, /*isVariadic=*/false, getFunctionTypeAttrName(),
334 getArgAttrsAttrName(), getResAttrsAttrName());
335}
336
337/// Check that the result type of async.func is not void and must be
338/// some async token or async values.
339LogicalResult FuncOp::verify() {
340 auto resultTypes = getResultTypes();
341 if (resultTypes.empty())
342 return emitOpError()
343 << "result is expected to be at least of size 1, but got "
344 << resultTypes.size();
345
346 for (unsigned i = 0, e = resultTypes.size(); i != e; ++i) {
347 auto type = resultTypes[i];
348 if (!llvm::isa<TokenType>(type) && !llvm::isa<ValueType>(type))
349 return emitOpError() << "result type must be async value type or async "
350 "token type, but got "
351 << type;
352 // We only allow AsyncToken appear as the first return value
353 if (llvm::isa<TokenType>(type) && i != 0) {
354 return emitOpError()
355 << " results' (optional) async token type is expected "
356 "to appear as the 1st return value, but got "
357 << i + 1;
358 }
359 }
360
361 return success();
362}
363
364//===----------------------------------------------------------------------===//
365/// CallOp
366//===----------------------------------------------------------------------===//
367
368LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
369 // Check that the callee attribute was specified.
370 auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
371 if (!fnAttr)
372 return emitOpError("requires a 'callee' symbol reference attribute");
373 FuncOp fn = symbolTable.lookupNearestSymbolFrom<FuncOp>(*this, fnAttr);
374 if (!fn)
375 return emitOpError() << "'" << fnAttr.getValue()
376 << "' does not reference a valid async function";
377
378 // Verify that the operand and result types match the callee.
379 auto fnType = fn.getFunctionType();
380 if (fnType.getNumInputs() != getNumOperands())
381 return emitOpError("incorrect number of operands for callee");
382
383 for (unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
384 if (getOperand(i).getType() != fnType.getInput(i))
385 return emitOpError("operand type mismatch: expected operand type ")
386 << fnType.getInput(i) << ", but provided "
387 << getOperand(i).getType() << " for operand number " << i;
388
389 if (fnType.getNumResults() != getNumResults())
390 return emitOpError("incorrect number of results for callee");
391
392 for (unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
393 if (getResult(i).getType() != fnType.getResult(i)) {
394 auto diag = emitOpError("result type mismatch at index ") << i;
395 diag.attachNote() << " op result types: " << getResultTypes();
396 diag.attachNote() << "function result types: " << fnType.getResults();
397 return diag;
398 }
399
400 return success();
401}
402
403FunctionType CallOp::getCalleeType() {
404 return FunctionType::get(getContext(), getOperandTypes(), getResultTypes());
405}
406
407//===----------------------------------------------------------------------===//
408/// ReturnOp
409//===----------------------------------------------------------------------===//
410
411LogicalResult ReturnOp::verify() {
412 auto funcOp = (*this)->getParentOfType<FuncOp>();
413 ArrayRef<Type> resultTypes = funcOp.isStateful()
414 ? funcOp.getResultTypes().drop_front()
415 : funcOp.getResultTypes();
416 // Get the underlying value types from async types returned from the
417 // parent `async.func` operation.
418 auto types = llvm::map_range(resultTypes, [](const Type &result) {
419 return llvm::cast<ValueType>(result).getValueType();
420 });
421
422 if (getOperandTypes() != types)
423 return emitOpError("operand types do not match the types returned from "
424 "the parent FuncOp");
425
426 return success();
427}
428
429//===----------------------------------------------------------------------===//
430// TableGen'd op method definitions
431//===----------------------------------------------------------------------===//
432
433#define GET_OP_CLASSES
434#include "mlir/Dialect/Async/IR/AsyncOps.cpp.inc"
435
436//===----------------------------------------------------------------------===//
437// TableGen'd type method definitions
438//===----------------------------------------------------------------------===//
439
440#define GET_TYPEDEF_CLASSES
441#include "mlir/Dialect/Async/IR/AsyncOpsTypes.cpp.inc"
442
443void ValueType::print(AsmPrinter &printer) const {
444 printer << "<";
445 printer.printType(getValueType());
446 printer << '>';
447}
448
449Type ValueType::parse(mlir::AsmParser &parser) {
450 Type ty;
451 if (parser.parseLess() || parser.parseType(ty) || parser.parseGreater()) {
452 parser.emitError(parser.getNameLoc(), "failed to parse async value type");
453 return Type();
454 }
455 return ValueType::get(ty);
456}
return success()
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static ParseResult parseAwaitResultType(OpAsmParser &parser, Type &operandType, Type &resultType)
Definition Async.cpp:262
constexpr char kOperandSegmentSizesAttr[]
ExecuteOp.
Definition Async.cpp:35
static void printAwaitResultType(OpAsmPrinter &p, Operation *op, Type operandType, Type resultType)
Definition Async.cpp:274
lhs
b getContext())
static std::string diag(const llvm::Value &value)
static Type getValueType(Attribute attr)
Definition SPIRVOps.cpp:773
This base class exposes generic asm parser hooks, usable across the various derived parsers.
@ OptionalParen
Parens supporting zero or more operands, or nothing.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
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 InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseRSquare()=0
Parse a ] token.
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
ParseResult addTypesToList(ArrayRef< Type > types, SmallVectorImpl< Type > &result)
Add the specified types to the end of the specified type list and return success.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseOptionalArrowTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional arrow followed by a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printType(Type type)
void printOptionalArrowTypeList(TypeRange &&types)
Print an optional arrow followed by a type list.
Block represents an ordered list of Operations.
Definition Block.h:33
bool empty()
Definition Block.h:158
BlockArgument getArgument(unsigned i)
Definition Block.h:139
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
BlockArgListType getArguments()
Definition Block.h:97
This class is a general helper class for creating context-global objects like types,...
Definition Builders.h:51
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition Builders.cpp:163
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
Definition Builders.cpp:76
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:262
A symbol reference with a reference path containing a single element.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument with the following syntax:
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 printOptionalAttrDictWithKeyword(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary prefixed with 'attribute...
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:348
This class helps build Operations.
Definition Builders.h:207
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.
Definition Builders.cpp:430
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:43
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class represents a point being branched from in the methods of the RegionBranchOpInterface.
bool isParent() const
Returns true if branching from the parent op.
RegionBranchTerminatorOpInterface getTerminatorPredecessorOrNull() const
Returns the terminator if branching from a region.
This class represents a successor of a region.
static RegionSuccessor parent()
Initialize a successor that branches after/out of the parent operation.
bool isParent() const
Return true if the successor is the parent operation.
Region * getSuccessor() const
Return the given region successor.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition SymbolTable.h:76
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:37
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
A named class for passing around the variadic flag.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void printFunctionOp(OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic, StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName)
Printer implementation for function-like operations.
ParseResult parseFunctionOp(OpAsmParser &parser, OperationState &result, bool allowVariadic, StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder, StringAttr argAttrsName, StringAttr resAttrsName)
Parser implementation for function-like operations.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition Utils.cpp:305
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
Region * addRegion()
Create a region that should be attached to the operation.