MLIR 24.0.0git
FunctionImplementation.cpp
Go to the documentation of this file.
1//===- FunctionImplementation.cpp - Utilities for function-like ops -------===//
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#include "mlir/IR/Builders.h"
11#include "mlir/IR/SymbolTable.h"
13
14using namespace mlir;
15
16static ParseResult
17parseFunctionArgumentList(OpAsmParser &parser, bool allowVariadic,
19 bool &isVariadic) {
20
21 // Parse the function arguments. The argument list either has to consistently
22 // have ssa-id's followed by types, or just be a type list. It isn't ok to
23 // sometimes have SSA ID's and sometimes not.
24 isVariadic = false;
25
26 return parser.parseCommaSeparatedList(
27 OpAsmParser::Delimiter::Paren, [&]() -> ParseResult {
28 // Ellipsis must be at end of the list.
29 if (isVariadic)
30 return parser.emitError(
31 parser.getCurrentLocation(),
32 "variadic arguments must be in the end of the argument list");
33
34 // Handle ellipsis as a special case.
35 if (allowVariadic && succeeded(parser.parseOptionalEllipsis())) {
36 // This is a variadic designator.
37 isVariadic = true;
38 return success(); // Stop parsing arguments.
39 }
40 // Parse argument name if present.
41 OpAsmParser::Argument argument;
42 auto argPresent = parser.parseOptionalArgument(
43 argument, /*allowType=*/true, /*allowAttrs=*/true);
44 if (argPresent.has_value()) {
45 if (failed(argPresent.value()))
46 return failure(); // Present but malformed.
47
48 // Reject this if the preceding argument was missing a name.
49 if (!arguments.empty() && arguments.back().ssaName.name.empty())
50 return parser.emitError(argument.ssaName.location,
51 "expected type instead of SSA identifier");
52
53 } else {
54 argument.ssaName.location = parser.getCurrentLocation();
55 // Otherwise we just have a type list without SSA names. Reject
56 // this if the preceding argument had a name.
57 if (!arguments.empty() && !arguments.back().ssaName.name.empty())
58 return parser.emitError(argument.ssaName.location,
59 "expected SSA identifier");
60
61 NamedAttrList attrs;
62 if (parser.parseType(argument.type) ||
63 parser.parseOptionalAttrDict(attrs) ||
65 return failure();
66 argument.attrs = attrs.getDictionary(parser.getContext());
67 }
68 arguments.push_back(argument);
69 return success();
70 });
71}
72
74 OpAsmParser &parser, bool allowVariadic,
75 SmallVectorImpl<OpAsmParser::Argument> &arguments, bool &isVariadic,
76 SmallVectorImpl<Type> &resultTypes,
78 if (parseFunctionArgumentList(parser, allowVariadic, arguments, isVariadic))
79 return failure();
80 if (succeeded(parser.parseOptionalArrow()))
81 return call_interface_impl::parseFunctionResultList(parser, resultTypes,
82 resultAttrs);
83 return success();
84}
85
87 OpAsmParser &parser, OperationState &result, bool allowVariadic,
88 StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder,
89 StringAttr argAttrsName, StringAttr resAttrsName) {
92 SmallVector<Type> resultTypes;
93 auto &builder = parser.getBuilder();
94
95 // Parse visibility.
97
98 // Parse the name as a symbol.
99 StringAttr nameAttr;
100 if (parser.parseSymbolName(nameAttr, "sym_name", result.attributes))
101 return failure();
102
103 // Parse the function signature.
104 SMLoc signatureLocation = parser.getCurrentLocation();
105 bool isVariadic = false;
106 if (parseFunctionSignatureWithArguments(parser, allowVariadic, entryArgs,
107 isVariadic, resultTypes, resultAttrs))
108 return failure();
109
110 std::string errorMessage;
111 SmallVector<Type> argTypes;
112 argTypes.reserve(entryArgs.size());
113 for (auto &arg : entryArgs)
114 argTypes.push_back(arg.type);
115 Type type = funcTypeBuilder(builder, argTypes, resultTypes,
116 VariadicFlag(isVariadic), errorMessage);
117 if (!type) {
118 return parser.emitError(signatureLocation)
119 << "failed to construct function type"
120 << (errorMessage.empty() ? "" : ": ") << errorMessage;
121 }
122 result.addAttribute(typeAttrName, TypeAttr::get(type));
123
124 // If function attributes are present, parse them.
125 NamedAttrList parsedAttributes;
126 SMLoc attributeDictLocation = parser.getCurrentLocation();
127 if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes))
128 return failure();
129
130 // Disallow attributes that are inferred from elsewhere in the attribute
131 // dictionary.
132 for (StringRef disallowed :
133 {SymbolOpInterface::getDefaultVisibilityAttrName(),
134 StringRef("sym_name"), typeAttrName.getValue()}) {
135 if (parsedAttributes.get(disallowed))
136 return parser.emitError(attributeDictLocation, "'")
137 << disallowed
138 << "' is an inferred attribute and should not be specified in the "
139 "explicit attribute dictionary";
140 }
141 result.attributes.append(parsedAttributes);
142
143 // Add the attributes to the function arguments.
144 assert(resultAttrs.size() == resultTypes.size());
146 builder, result, entryArgs, resultAttrs, argAttrsName, resAttrsName);
147
148 // Parse the optional function body. The printer will not print the body if
149 // its empty, so disallow parsing of empty body in the parser.
150 auto *body = result.addRegion();
151 SMLoc loc = parser.getCurrentLocation();
152 OptionalParseResult parseResult =
153 parser.parseOptionalRegion(*body, entryArgs,
154 /*enableNameShadowing=*/false);
155 if (parseResult.has_value()) {
156 if (failed(*parseResult))
157 return failure();
158 // Function body was parsed, make sure its not empty.
159 if (body->empty())
160 return parser.emitError(loc, "expected non-empty function body");
161 }
162 return success();
163}
164
167 // Print out function attributes, if present.
168 SmallVector<StringRef, 8> ignoredAttrs = {"sym_name"};
169 ignoredAttrs.append(elided.begin(), elided.end());
170
171 NamedAttrList attrs(op->getDiscardableAttrDictionary().getValue());
173 op, [&](StringRef name, Attribute &attr) { attrs.append(name, attr); });
174 p.printOptionalAttrDictWithKeyword(attrs, ignoredAttrs);
175}
176
178 OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic,
179 StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName) {
180 // Print the operation and the function name.
181 auto symbol = cast<SymbolOpInterface>(op.getOperation());
182 StringRef funcName = symbol.getName();
183 p << ' ';
184
185 StringRef visibilityAttrName =
186 SymbolOpInterface::getDefaultVisibilityAttrName();
187 Attribute visibility =
188 op->getInherentAttr(visibilityAttrName).value_or(Attribute{});
189 if (auto value = dyn_cast_or_null<StringAttr>(visibility))
190 p << value.getValue() << ' ';
191 p.printSymbolName(funcName);
192
193 ArrayRef<Type> argTypes = op.getArgumentTypes();
194 ArrayRef<Type> resultTypes = op.getResultTypes();
195 printFunctionSignature(p, op, argTypes, isVariadic, resultTypes);
197 p, op, {visibilityAttrName, typeAttrName, argAttrsName, resAttrsName});
198 // Print the body if this is not an external function.
199 Region &body = op->getRegion(0);
200 if (!body.empty()) {
201 p << ' ';
202 p.printRegion(body, /*printEntryBlockArgs=*/false,
203 /*printBlockTerminators=*/true);
204 }
205}
return success()
static ParseResult parseFunctionArgumentList(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic)
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
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 ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalArrow()=0
Parse a '->' token if present.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalEllipsis()=0
Parse a ... token if present;.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
Attributes are known-constant values of operations.
Definition Attributes.h:25
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
Attribute get(StringAttr name) const
Return the specified attribute if present, null otherwise.
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 OptionalParseResult parseOptionalArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument if present.
virtual ParseResult parseOptionalLocationSpecifier(std::optional< Location > &result)=0
Parse a loc(...) specifier if present, filling in result if so.
virtual OptionalParseResult parseOptionalRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
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.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OperationName getName()
The name of an operation is the key identifier for it.
Definition Operation.h:115
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
Definition Operation.h:553
This class implements Optional functionality for ParseResult.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
A named class for passing around the variadic flag.
ParseResult parseFunctionResultList(OpAsmParser &parser, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parse a function or call result list.
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,...
function_ref< Type( Builder &, ArrayRef< Type >, ArrayRef< Type >, VariadicFlag, std::string &)> FuncTypeBuilder
Callback type for parseFunctionOp, the callback should produce the type that will be associated with ...
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
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.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
ParseResult parseOptionalVisibilityKeyword(OpAsmParser &parser, NamedAttrList &attrs)
Parse an optional visibility attribute keyword (i.e., public, private, or nested) without quotes in a...
Include the generated interface declarations.
std::optional< Location > sourceLoc
This represents an operation in an abstracted form, suitable for use with the builder APIs.