MLIR  21.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 
14 using namespace mlir;
15 
16 static ParseResult
17 parseFunctionArgumentList(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) ||
64  parser.parseOptionalLocationSpecifier(argument.sourceLoc))
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,
77  SmallVectorImpl<DictionaryAttr> &resultAttrs) {
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) {
91  SmallVector<DictionaryAttr> resultAttrs;
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, SymbolTable::getSymbolAttrName(),
101  result.attributes))
102  return failure();
103 
104  // Parse the function signature.
105  SMLoc signatureLocation = parser.getCurrentLocation();
106  bool isVariadic = false;
107  if (parseFunctionSignatureWithArguments(parser, allowVariadic, entryArgs,
108  isVariadic, resultTypes, resultAttrs))
109  return failure();
110 
111  std::string errorMessage;
112  SmallVector<Type> argTypes;
113  argTypes.reserve(entryArgs.size());
114  for (auto &arg : entryArgs)
115  argTypes.push_back(arg.type);
116  Type type = funcTypeBuilder(builder, argTypes, resultTypes,
117  VariadicFlag(isVariadic), errorMessage);
118  if (!type) {
119  return parser.emitError(signatureLocation)
120  << "failed to construct function type"
121  << (errorMessage.empty() ? "" : ": ") << errorMessage;
122  }
123  result.addAttribute(typeAttrName, TypeAttr::get(type));
124 
125  // If function attributes are present, parse them.
126  NamedAttrList parsedAttributes;
127  SMLoc attributeDictLocation = parser.getCurrentLocation();
128  if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes))
129  return failure();
130 
131  // Disallow attributes that are inferred from elsewhere in the attribute
132  // dictionary.
133  for (StringRef disallowed :
135  typeAttrName.getValue()}) {
136  if (parsedAttributes.get(disallowed))
137  return parser.emitError(attributeDictLocation, "'")
138  << disallowed
139  << "' is an inferred attribute and should not be specified in the "
140  "explicit attribute dictionary";
141  }
142  result.attributes.append(parsedAttributes);
143 
144  // Add the attributes to the function arguments.
145  assert(resultAttrs.size() == resultTypes.size());
147  builder, result, entryArgs, resultAttrs, argAttrsName, resAttrsName);
148 
149  // Parse the optional function body. The printer will not print the body if
150  // its empty, so disallow parsing of empty body in the parser.
151  auto *body = result.addRegion();
152  SMLoc loc = parser.getCurrentLocation();
153  OptionalParseResult parseResult =
154  parser.parseOptionalRegion(*body, entryArgs,
155  /*enableNameShadowing=*/false);
156  if (parseResult.has_value()) {
157  if (failed(*parseResult))
158  return failure();
159  // Function body was parsed, make sure its not empty.
160  if (body->empty())
161  return parser.emitError(loc, "expected non-empty function body");
162  }
163  return success();
164 }
165 
167  OpAsmPrinter &p, Operation *op, ArrayRef<StringRef> elided) {
168  // Print out function attributes, if present.
170  ignoredAttrs.append(elided.begin(), elided.end());
171 
172  p.printOptionalAttrDictWithKeyword(op->getAttrs(), ignoredAttrs);
173 }
174 
176  OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic,
177  StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName) {
178  // Print the operation and the function name.
179  auto funcName =
180  op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
181  .getValue();
182  p << ' ';
183 
184  StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
185  if (auto visibility = op->getAttrOfType<StringAttr>(visibilityAttrName))
186  p << visibility.getValue() << ' ';
187  p.printSymbolName(funcName);
188 
189  ArrayRef<Type> argTypes = op.getArgumentTypes();
190  ArrayRef<Type> resultTypes = op.getResultTypes();
191  printFunctionSignature(p, op, argTypes, isVariadic, resultTypes);
193  p, op, {visibilityAttrName, typeAttrName, argAttrsName, resAttrsName});
194  // Print the body if this is not an external function.
195  Region &body = op->getRegion(0);
196  if (!body.empty()) {
197  p << ' ';
198  p.printRegion(body, /*printEntryBlockArgs=*/false,
199  /*printBlockTerminators=*/true);
200  }
201 }
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 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 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 void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
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 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.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition: Operation.h:512
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:76
static StringRef getVisibilityAttrName()
Return the name of the attribute used for symbol visibility.
Definition: SymbolTable.h:82
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.
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
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,...
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.
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.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
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.
NamedAttrList attributes
Region * addRegion()
Create a region that should be attached to the operation.