12f16bf7aSAlex Zinenko //===- FunctionImplementation.cpp - Utilities for function-like ops -------===//
22f16bf7aSAlex Zinenko //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62f16bf7aSAlex Zinenko //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
82f16bf7aSAlex Zinenko
92f16bf7aSAlex Zinenko #include "mlir/IR/FunctionImplementation.h"
102f16bf7aSAlex Zinenko #include "mlir/IR/Builders.h"
117ceffae1SRiver Riddle #include "mlir/IR/FunctionInterfaces.h"
122f16bf7aSAlex Zinenko #include "mlir/IR/SymbolTable.h"
132f16bf7aSAlex Zinenko
142f16bf7aSAlex Zinenko using namespace mlir;
152f16bf7aSAlex Zinenko
16d85eb4e2SChris Lattner static ParseResult
parseFunctionArgumentList(OpAsmParser & parser,bool allowVariadic,SmallVectorImpl<OpAsmParser::Argument> & arguments,bool & isVariadic)17d85eb4e2SChris Lattner parseFunctionArgumentList(OpAsmParser &parser, bool allowVariadic,
18d85eb4e2SChris Lattner SmallVectorImpl<OpAsmParser::Argument> &arguments,
1931c8abc3SChris Lattner bool &isVariadic) {
202f16bf7aSAlex Zinenko
21d85eb4e2SChris Lattner // Parse the function arguments. The argument list either has to consistently
22d85eb4e2SChris Lattner // have ssa-id's followed by types, or just be a type list. It isn't ok to
23d85eb4e2SChris Lattner // sometimes have SSA ID's and sometimes not.
24d85eb4e2SChris Lattner isVariadic = false;
252f16bf7aSAlex Zinenko
26d85eb4e2SChris Lattner return parser.parseCommaSeparatedList(
27d85eb4e2SChris Lattner OpAsmParser::Delimiter::Paren, [&]() -> ParseResult {
28d85eb4e2SChris Lattner // Ellipsis must be at end of the list.
29d85eb4e2SChris Lattner if (isVariadic)
30d85eb4e2SChris Lattner return parser.emitError(
31d85eb4e2SChris Lattner parser.getCurrentLocation(),
32d85eb4e2SChris Lattner "variadic arguments must be in the end of the argument list");
33d85eb4e2SChris Lattner
34d85eb4e2SChris Lattner // Handle ellipsis as a special case.
35d85eb4e2SChris Lattner if (allowVariadic && succeeded(parser.parseOptionalEllipsis())) {
36d85eb4e2SChris Lattner // This is a variadic designator.
37d85eb4e2SChris Lattner isVariadic = true;
38d85eb4e2SChris Lattner return success(); // Stop parsing arguments.
39d85eb4e2SChris Lattner }
402f16bf7aSAlex Zinenko // Parse argument name if present.
41d85eb4e2SChris Lattner OpAsmParser::Argument argument;
42d85eb4e2SChris Lattner auto argPresent = parser.parseOptionalArgument(
43d85eb4e2SChris Lattner argument, /*allowType=*/true, /*allowAttrs=*/true);
44*3b7c3a65SKazu Hirata if (argPresent.hasValue()) {
45*3b7c3a65SKazu Hirata if (failed(argPresent.getValue()))
46d85eb4e2SChris Lattner return failure(); // Present but malformed.
475dedf911SChris Lattner
482f16bf7aSAlex Zinenko // Reject this if the preceding argument was missing a name.
49d85eb4e2SChris Lattner if (!arguments.empty() && arguments.back().ssaName.name.empty())
50d85eb4e2SChris Lattner return parser.emitError(argument.ssaName.location,
51d85eb4e2SChris Lattner "expected type instead of SSA identifier");
522f16bf7aSAlex Zinenko
53d85eb4e2SChris Lattner } else {
54d85eb4e2SChris Lattner argument.ssaName.location = parser.getCurrentLocation();
55d85eb4e2SChris Lattner // Otherwise we just have a type list without SSA names. Reject
56d85eb4e2SChris Lattner // this if the preceding argument had a name.
57d85eb4e2SChris Lattner if (!arguments.empty() && !arguments.back().ssaName.name.empty())
58d85eb4e2SChris Lattner return parser.emitError(argument.ssaName.location,
59d85eb4e2SChris Lattner "expected SSA identifier");
602f16bf7aSAlex Zinenko
615eae715aSJacques Pienaar NamedAttrList attrs;
62d85eb4e2SChris Lattner if (parser.parseType(argument.type) ||
63d85eb4e2SChris Lattner parser.parseOptionalAttrDict(attrs) ||
6431c8abc3SChris Lattner parser.parseOptionalLocationSpecifier(argument.sourceLoc))
652f16bf7aSAlex Zinenko return failure();
66d85eb4e2SChris Lattner argument.attrs = attrs.getDictionary(parser.getContext());
672f16bf7aSAlex Zinenko }
68d85eb4e2SChris Lattner arguments.push_back(argument);
692f16bf7aSAlex Zinenko return success();
70d85eb4e2SChris Lattner });
712f16bf7aSAlex Zinenko }
722f16bf7aSAlex Zinenko
732f16bf7aSAlex Zinenko /// Parse a function result list.
742f16bf7aSAlex Zinenko ///
752f16bf7aSAlex Zinenko /// function-result-list ::= function-result-list-parens
762f16bf7aSAlex Zinenko /// | non-function-type
772f16bf7aSAlex Zinenko /// function-result-list-parens ::= `(` `)`
782f16bf7aSAlex Zinenko /// | `(` function-result-list-no-parens `)`
792f16bf7aSAlex Zinenko /// function-result-list-no-parens ::= function-result (`,` function-result)*
802f16bf7aSAlex Zinenko /// function-result ::= type attribute-dict?
812f16bf7aSAlex Zinenko ///
825eae715aSJacques Pienaar static ParseResult
parseFunctionResultList(OpAsmParser & parser,SmallVectorImpl<Type> & resultTypes,SmallVectorImpl<DictionaryAttr> & resultAttrs)835eae715aSJacques Pienaar parseFunctionResultList(OpAsmParser &parser, SmallVectorImpl<Type> &resultTypes,
84d85eb4e2SChris Lattner SmallVectorImpl<DictionaryAttr> &resultAttrs) {
852f16bf7aSAlex Zinenko if (failed(parser.parseOptionalLParen())) {
862f16bf7aSAlex Zinenko // We already know that there is no `(`, so parse a type.
872f16bf7aSAlex Zinenko // Because there is no `(`, it cannot be a function type.
882f16bf7aSAlex Zinenko Type ty;
892f16bf7aSAlex Zinenko if (parser.parseType(ty))
902f16bf7aSAlex Zinenko return failure();
912f16bf7aSAlex Zinenko resultTypes.push_back(ty);
922f16bf7aSAlex Zinenko resultAttrs.emplace_back();
932f16bf7aSAlex Zinenko return success();
942f16bf7aSAlex Zinenko }
952f16bf7aSAlex Zinenko
962f16bf7aSAlex Zinenko // Special case for an empty set of parens.
972f16bf7aSAlex Zinenko if (succeeded(parser.parseOptionalRParen()))
982f16bf7aSAlex Zinenko return success();
992f16bf7aSAlex Zinenko
1002f16bf7aSAlex Zinenko // Parse individual function results.
101d85eb4e2SChris Lattner if (parser.parseCommaSeparatedList([&]() -> ParseResult {
1022f16bf7aSAlex Zinenko resultTypes.emplace_back();
1032f16bf7aSAlex Zinenko resultAttrs.emplace_back();
104d85eb4e2SChris Lattner NamedAttrList attrs;
1052f16bf7aSAlex Zinenko if (parser.parseType(resultTypes.back()) ||
106d85eb4e2SChris Lattner parser.parseOptionalAttrDict(attrs))
1072f16bf7aSAlex Zinenko return failure();
108d85eb4e2SChris Lattner resultAttrs.back() = attrs.getDictionary(parser.getContext());
109d85eb4e2SChris Lattner return success();
110d85eb4e2SChris Lattner }))
111d85eb4e2SChris Lattner return failure();
112d85eb4e2SChris Lattner
1132f16bf7aSAlex Zinenko return parser.parseRParen();
1142f16bf7aSAlex Zinenko }
1152f16bf7aSAlex Zinenko
parseFunctionSignature(OpAsmParser & parser,bool allowVariadic,SmallVectorImpl<OpAsmParser::Argument> & arguments,bool & isVariadic,SmallVectorImpl<Type> & resultTypes,SmallVectorImpl<DictionaryAttr> & resultAttrs)1167ceffae1SRiver Riddle ParseResult mlir::function_interface_impl::parseFunctionSignature(
1172f16bf7aSAlex Zinenko OpAsmParser &parser, bool allowVariadic,
118d85eb4e2SChris Lattner SmallVectorImpl<OpAsmParser::Argument> &arguments, bool &isVariadic,
119d85eb4e2SChris Lattner SmallVectorImpl<Type> &resultTypes,
120d85eb4e2SChris Lattner SmallVectorImpl<DictionaryAttr> &resultAttrs) {
121d85eb4e2SChris Lattner if (parseFunctionArgumentList(parser, allowVariadic, arguments, isVariadic))
1222f16bf7aSAlex Zinenko return failure();
1232f16bf7aSAlex Zinenko if (succeeded(parser.parseOptionalArrow()))
1242f16bf7aSAlex Zinenko return parseFunctionResultList(parser, resultTypes, resultAttrs);
1252f16bf7aSAlex Zinenko return success();
1262f16bf7aSAlex Zinenko }
1272f16bf7aSAlex Zinenko
addArgAndResultAttrs(Builder & builder,OperationState & result,ArrayRef<DictionaryAttr> argAttrs,ArrayRef<DictionaryAttr> resultAttrs)1287ceffae1SRiver Riddle void mlir::function_interface_impl::addArgAndResultAttrs(
12953b946aaSRiver Riddle Builder &builder, OperationState &result, ArrayRef<DictionaryAttr> argAttrs,
13053b946aaSRiver Riddle ArrayRef<DictionaryAttr> resultAttrs) {
131d85eb4e2SChris Lattner auto nonEmptyAttrsFn = [](DictionaryAttr attrs) {
132d85eb4e2SChris Lattner return attrs && !attrs.empty();
13353b946aaSRiver Riddle };
134d85eb4e2SChris Lattner // Convert the specified array of dictionary attrs (which may have null
135d85eb4e2SChris Lattner // entries) to an ArrayAttr of dictionaries.
136d85eb4e2SChris Lattner auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
137d85eb4e2SChris Lattner SmallVector<Attribute> attrs;
138d85eb4e2SChris Lattner for (auto &dict : dictAttrs)
139d85eb4e2SChris Lattner attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
140d85eb4e2SChris Lattner return builder.getArrayAttr(attrs);
141d85eb4e2SChris Lattner };
142d85eb4e2SChris Lattner
143d85eb4e2SChris Lattner // Add the attributes to the function arguments.
144d85eb4e2SChris Lattner if (llvm::any_of(argAttrs, nonEmptyAttrsFn))
145d85eb4e2SChris Lattner result.addAttribute(function_interface_impl::getArgDictAttrName(),
146d85eb4e2SChris Lattner getArrayAttr(argAttrs));
147d85eb4e2SChris Lattner
148d85eb4e2SChris Lattner // Add the attributes to the function results.
149d85eb4e2SChris Lattner if (llvm::any_of(resultAttrs, nonEmptyAttrsFn))
150d85eb4e2SChris Lattner result.addAttribute(function_interface_impl::getResultDictAttrName(),
151d85eb4e2SChris Lattner getArrayAttr(resultAttrs));
15253b946aaSRiver Riddle }
153d85eb4e2SChris Lattner
addArgAndResultAttrs(Builder & builder,OperationState & result,ArrayRef<OpAsmParser::Argument> args,ArrayRef<DictionaryAttr> resultAttrs)1547ceffae1SRiver Riddle void mlir::function_interface_impl::addArgAndResultAttrs(
155d85eb4e2SChris Lattner Builder &builder, OperationState &result,
156d85eb4e2SChris Lattner ArrayRef<OpAsmParser::Argument> args,
157d85eb4e2SChris Lattner ArrayRef<DictionaryAttr> resultAttrs) {
158d85eb4e2SChris Lattner SmallVector<DictionaryAttr> argAttrs;
159d85eb4e2SChris Lattner for (const auto &arg : args)
160d85eb4e2SChris Lattner argAttrs.push_back(arg.attrs);
161d85eb4e2SChris Lattner addArgAndResultAttrs(builder, result, argAttrs, resultAttrs);
1622f16bf7aSAlex Zinenko }
1632f16bf7aSAlex Zinenko
parseFunctionOp(OpAsmParser & parser,OperationState & result,bool allowVariadic,FuncTypeBuilder funcTypeBuilder)1647ceffae1SRiver Riddle ParseResult mlir::function_interface_impl::parseFunctionOp(
16553b946aaSRiver Riddle OpAsmParser &parser, OperationState &result, bool allowVariadic,
16653b946aaSRiver Riddle FuncTypeBuilder funcTypeBuilder) {
167d85eb4e2SChris Lattner SmallVector<OpAsmParser::Argument> entryArgs;
168d85eb4e2SChris Lattner SmallVector<DictionaryAttr> resultAttrs;
1691e09f0a9SDominik Grewe SmallVector<Type> resultTypes;
1702f16bf7aSAlex Zinenko auto &builder = parser.getBuilder();
1712f16bf7aSAlex Zinenko
172dea24b42SRahul Joshi // Parse visibility.
1731d7b5cd5SChris Lattner (void)impl::parseOptionalVisibilityKeyword(parser, result.attributes);
1748b5a3e46SRahul Joshi
1752f16bf7aSAlex Zinenko // Parse the name as a symbol.
1762f16bf7aSAlex Zinenko StringAttr nameAttr;
1778b5a3e46SRahul Joshi if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
1782f16bf7aSAlex Zinenko result.attributes))
1792f16bf7aSAlex Zinenko return failure();
1802f16bf7aSAlex Zinenko
1812f16bf7aSAlex Zinenko // Parse the function signature.
1826842ec42SRiver Riddle SMLoc signatureLocation = parser.getCurrentLocation();
1832f16bf7aSAlex Zinenko bool isVariadic = false;
184d85eb4e2SChris Lattner if (parseFunctionSignature(parser, allowVariadic, entryArgs, isVariadic,
185d85eb4e2SChris Lattner resultTypes, resultAttrs))
1862f16bf7aSAlex Zinenko return failure();
1872f16bf7aSAlex Zinenko
1882f16bf7aSAlex Zinenko std::string errorMessage;
189d85eb4e2SChris Lattner SmallVector<Type> argTypes;
190d85eb4e2SChris Lattner argTypes.reserve(entryArgs.size());
191d85eb4e2SChris Lattner for (auto &arg : entryArgs)
192d85eb4e2SChris Lattner argTypes.push_back(arg.type);
19353b946aaSRiver Riddle Type type = funcTypeBuilder(builder, argTypes, resultTypes,
19453b946aaSRiver Riddle VariadicFlag(isVariadic), errorMessage);
19553b946aaSRiver Riddle if (!type) {
1962f16bf7aSAlex Zinenko return parser.emitError(signatureLocation)
1972f16bf7aSAlex Zinenko << "failed to construct function type"
1982f16bf7aSAlex Zinenko << (errorMessage.empty() ? "" : ": ") << errorMessage;
19953b946aaSRiver Riddle }
20053b946aaSRiver Riddle result.addAttribute(getTypeAttrName(), TypeAttr::get(type));
2012f16bf7aSAlex Zinenko
2022f16bf7aSAlex Zinenko // If function attributes are present, parse them.
20367a339e9SRahul Joshi NamedAttrList parsedAttributes;
2046842ec42SRiver Riddle SMLoc attributeDictLocation = parser.getCurrentLocation();
20567a339e9SRahul Joshi if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes))
2062f16bf7aSAlex Zinenko return failure();
2072f16bf7aSAlex Zinenko
20867a339e9SRahul Joshi // Disallow attributes that are inferred from elsewhere in the attribute
20967a339e9SRahul Joshi // dictionary.
21067a339e9SRahul Joshi for (StringRef disallowed :
21167a339e9SRahul Joshi {SymbolTable::getVisibilityAttrName(), SymbolTable::getSymbolAttrName(),
21267a339e9SRahul Joshi getTypeAttrName()}) {
21367a339e9SRahul Joshi if (parsedAttributes.get(disallowed))
21467a339e9SRahul Joshi return parser.emitError(attributeDictLocation, "'")
21567a339e9SRahul Joshi << disallowed
21667a339e9SRahul Joshi << "' is an inferred attribute and should not be specified in the "
21767a339e9SRahul Joshi "explicit attribute dictionary";
21867a339e9SRahul Joshi }
21967a339e9SRahul Joshi result.attributes.append(parsedAttributes);
22067a339e9SRahul Joshi
2212f16bf7aSAlex Zinenko // Add the attributes to the function arguments.
2222f16bf7aSAlex Zinenko assert(resultAttrs.size() == resultTypes.size());
223d85eb4e2SChris Lattner addArgAndResultAttrs(builder, result, entryArgs, resultAttrs);
2242f16bf7aSAlex Zinenko
225fe7fdcacSRahul Joshi // Parse the optional function body. The printer will not print the body if
226fe7fdcacSRahul Joshi // its empty, so disallow parsing of empty body in the parser.
2272f16bf7aSAlex Zinenko auto *body = result.addRegion();
2286842ec42SRiver Riddle SMLoc loc = parser.getCurrentLocation();
229d85eb4e2SChris Lattner OptionalParseResult parseResult =
230d85eb4e2SChris Lattner parser.parseOptionalRegion(*body, entryArgs,
231fe7fdcacSRahul Joshi /*enableNameShadowing=*/false);
232*3b7c3a65SKazu Hirata if (parseResult.hasValue()) {
233fe7fdcacSRahul Joshi if (failed(*parseResult))
234fe7fdcacSRahul Joshi return failure();
235fe7fdcacSRahul Joshi // Function body was parsed, make sure its not empty.
236fe7fdcacSRahul Joshi if (body->empty())
237fe7fdcacSRahul Joshi return parser.emitError(loc, "expected non-empty function body");
238fe7fdcacSRahul Joshi }
239fe7fdcacSRahul Joshi return success();
2402f16bf7aSAlex Zinenko }
2412f16bf7aSAlex Zinenko
24253b946aaSRiver Riddle /// Print a function result list. The provided `attrs` must either be null, or
24353b946aaSRiver Riddle /// contain a set of DictionaryAttrs of the same arity as `types`.
printFunctionResultList(OpAsmPrinter & p,ArrayRef<Type> types,ArrayAttr attrs)2442f16bf7aSAlex Zinenko static void printFunctionResultList(OpAsmPrinter &p, ArrayRef<Type> types,
24553b946aaSRiver Riddle ArrayAttr attrs) {
2462f16bf7aSAlex Zinenko assert(!types.empty() && "Should not be called for empty result list.");
24753b946aaSRiver Riddle assert((!attrs || attrs.size() == types.size()) &&
24853b946aaSRiver Riddle "Invalid number of attributes.");
24953b946aaSRiver Riddle
2502f16bf7aSAlex Zinenko auto &os = p.getStream();
25153b946aaSRiver Riddle bool needsParens = types.size() > 1 || types[0].isa<FunctionType>() ||
25253b946aaSRiver Riddle (attrs && !attrs[0].cast<DictionaryAttr>().empty());
2532f16bf7aSAlex Zinenko if (needsParens)
2542f16bf7aSAlex Zinenko os << '(';
25553b946aaSRiver Riddle llvm::interleaveComma(llvm::seq<size_t>(0, types.size()), os, [&](size_t i) {
25653b946aaSRiver Riddle p.printType(types[i]);
25753b946aaSRiver Riddle if (attrs)
25853b946aaSRiver Riddle p.printOptionalAttrDict(attrs[i].cast<DictionaryAttr>().getValue());
2592f16bf7aSAlex Zinenko });
2602f16bf7aSAlex Zinenko if (needsParens)
2612f16bf7aSAlex Zinenko os << ')';
2622f16bf7aSAlex Zinenko }
2632f16bf7aSAlex Zinenko
printFunctionSignature(OpAsmPrinter & p,Operation * op,ArrayRef<Type> argTypes,bool isVariadic,ArrayRef<Type> resultTypes)2647ceffae1SRiver Riddle void mlir::function_interface_impl::printFunctionSignature(
26553b946aaSRiver Riddle OpAsmPrinter &p, Operation *op, ArrayRef<Type> argTypes, bool isVariadic,
2662f16bf7aSAlex Zinenko ArrayRef<Type> resultTypes) {
2672f16bf7aSAlex Zinenko Region &body = op->getRegion(0);
2682f16bf7aSAlex Zinenko bool isExternal = body.empty();
2692f16bf7aSAlex Zinenko
2702f16bf7aSAlex Zinenko p << '(';
27153b946aaSRiver Riddle ArrayAttr argAttrs = op->getAttrOfType<ArrayAttr>(getArgDictAttrName());
2722f16bf7aSAlex Zinenko for (unsigned i = 0, e = argTypes.size(); i < e; ++i) {
2732f16bf7aSAlex Zinenko if (i > 0)
2742f16bf7aSAlex Zinenko p << ", ";
2752f16bf7aSAlex Zinenko
2762f16bf7aSAlex Zinenko if (!isExternal) {
27781467f50SChris Lattner ArrayRef<NamedAttribute> attrs;
27881467f50SChris Lattner if (argAttrs)
27981467f50SChris Lattner attrs = argAttrs[i].cast<DictionaryAttr>().getValue();
28081467f50SChris Lattner p.printRegionArgument(body.getArgument(i), attrs);
28181467f50SChris Lattner } else {
2822f16bf7aSAlex Zinenko p.printType(argTypes[i]);
28353b946aaSRiver Riddle if (argAttrs)
28453b946aaSRiver Riddle p.printOptionalAttrDict(argAttrs[i].cast<DictionaryAttr>().getValue());
2852f16bf7aSAlex Zinenko }
28681467f50SChris Lattner }
2872f16bf7aSAlex Zinenko
2882f16bf7aSAlex Zinenko if (isVariadic) {
2892f16bf7aSAlex Zinenko if (!argTypes.empty())
2902f16bf7aSAlex Zinenko p << ", ";
2912f16bf7aSAlex Zinenko p << "...";
2922f16bf7aSAlex Zinenko }
2932f16bf7aSAlex Zinenko
2942f16bf7aSAlex Zinenko p << ')';
2952f16bf7aSAlex Zinenko
2962f16bf7aSAlex Zinenko if (!resultTypes.empty()) {
2972f16bf7aSAlex Zinenko p.getStream() << " -> ";
29853b946aaSRiver Riddle auto resultAttrs = op->getAttrOfType<ArrayAttr>(getResultDictAttrName());
2992f16bf7aSAlex Zinenko printFunctionResultList(p, resultTypes, resultAttrs);
3002f16bf7aSAlex Zinenko }
3012f16bf7aSAlex Zinenko }
3022f16bf7aSAlex Zinenko
printFunctionAttributes(OpAsmPrinter & p,Operation * op,unsigned numInputs,unsigned numResults,ArrayRef<StringRef> elided)3037ceffae1SRiver Riddle void mlir::function_interface_impl::printFunctionAttributes(
30453b946aaSRiver Riddle OpAsmPrinter &p, Operation *op, unsigned numInputs, unsigned numResults,
3052f16bf7aSAlex Zinenko ArrayRef<StringRef> elided) {
3062f16bf7aSAlex Zinenko // Print out function attributes, if present.
3072f16bf7aSAlex Zinenko SmallVector<StringRef, 2> ignoredAttrs = {
30853b946aaSRiver Riddle ::mlir::SymbolTable::getSymbolAttrName(), getTypeAttrName(),
30953b946aaSRiver Riddle getArgDictAttrName(), getResultDictAttrName()};
3102f16bf7aSAlex Zinenko ignoredAttrs.append(elided.begin(), elided.end());
3112f16bf7aSAlex Zinenko
3122f16bf7aSAlex Zinenko p.printOptionalAttrDictWithKeyword(op->getAttrs(), ignoredAttrs);
3132f16bf7aSAlex Zinenko }
3142f16bf7aSAlex Zinenko
printFunctionOp(OpAsmPrinter & p,FunctionOpInterface op,bool isVariadic)315f96a8675SRiver Riddle void mlir::function_interface_impl::printFunctionOp(OpAsmPrinter &p,
316f96a8675SRiver Riddle FunctionOpInterface op,
317f96a8675SRiver Riddle bool isVariadic) {
3182f16bf7aSAlex Zinenko // Print the operation and the function name.
3192f16bf7aSAlex Zinenko auto funcName =
3208b5a3e46SRahul Joshi op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
3212f16bf7aSAlex Zinenko .getValue();
322c41b16c2SMehdi Amini p << ' ';
323dea24b42SRahul Joshi
324dea24b42SRahul Joshi StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
325dea24b42SRahul Joshi if (auto visibility = op->getAttrOfType<StringAttr>(visibilityAttrName))
3268b5a3e46SRahul Joshi p << visibility.getValue() << ' ';
3272f16bf7aSAlex Zinenko p.printSymbolName(funcName);
3282f16bf7aSAlex Zinenko
329f96a8675SRiver Riddle ArrayRef<Type> argTypes = op.getArgumentTypes();
330f96a8675SRiver Riddle ArrayRef<Type> resultTypes = op.getResultTypes();
3312f16bf7aSAlex Zinenko printFunctionSignature(p, op, argTypes, isVariadic, resultTypes);
3328b5a3e46SRahul Joshi printFunctionAttributes(p, op, argTypes.size(), resultTypes.size(),
333dea24b42SRahul Joshi {visibilityAttrName});
3342f16bf7aSAlex Zinenko // Print the body if this is not an external function.
3352f16bf7aSAlex Zinenko Region &body = op->getRegion(0);
3365c36ee8dSMogball if (!body.empty()) {
3375c36ee8dSMogball p << ' ';
3382f16bf7aSAlex Zinenko p.printRegion(body, /*printEntryBlockArgs=*/false,
3392f16bf7aSAlex Zinenko /*printBlockTerminators=*/true);
3402f16bf7aSAlex Zinenko }
3415c36ee8dSMogball }
342