MLIR  15.0.0git
FunctionInterfaces.h
Go to the documentation of this file.
1 //===- FunctionSupport.h - Utility types for function-like ops --*- C++ -*-===//
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 //
9 // This file defines support types for Operations that represent function-like
10 // constructs to use.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_IR_FUNCTIONINTERFACES_H
15 #define MLIR_IR_FUNCTIONINTERFACES_H
16 
17 #include "mlir/IR/Builders.h"
18 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/OpDefinition.h"
20 #include "mlir/IR/SymbolTable.h"
21 #include "llvm/ADT/BitVector.h"
22 #include "llvm/ADT/SmallString.h"
23 
24 namespace mlir {
25 
26 namespace function_interface_impl {
27 
28 /// Return the name of the attribute used for function types.
29 inline StringRef getTypeAttrName() { return "function_type"; }
30 
31 /// Return the name of the attribute used for function argument attributes.
32 inline StringRef getArgDictAttrName() { return "arg_attrs"; }
33 
34 /// Return the name of the attribute used for function argument attributes.
35 inline StringRef getResultDictAttrName() { return "res_attrs"; }
36 
37 /// Returns the dictionary attribute corresponding to the argument at 'index'.
38 /// If there are no argument attributes at 'index', a null attribute is
39 /// returned.
40 DictionaryAttr getArgAttrDict(Operation *op, unsigned index);
41 
42 /// Returns the dictionary attribute corresponding to the result at 'index'.
43 /// If there are no result attributes at 'index', a null attribute is
44 /// returned.
45 DictionaryAttr getResultAttrDict(Operation *op, unsigned index);
46 
47 namespace detail {
48 /// Update the given index into an argument or result attribute dictionary.
49 void setArgResAttrDict(Operation *op, StringRef attrName,
50  unsigned numTotalIndices, unsigned index,
51  DictionaryAttr attrs);
52 } // namespace detail
53 
54 /// Set all of the argument or result attribute dictionaries for a function. The
55 /// size of `attrs` is expected to match the number of arguments/results of the
56 /// given `op`.
61 
62 /// Return all of the attributes for the argument at 'index'.
63 inline ArrayRef<NamedAttribute> getArgAttrs(Operation *op, unsigned index) {
64  auto argDict = getArgAttrDict(op, index);
65  return argDict ? argDict.getValue() : llvm::None;
66 }
67 
68 /// Return all of the attributes for the result at 'index'.
69 inline ArrayRef<NamedAttribute> getResultAttrs(Operation *op, unsigned index) {
70  auto resultDict = getResultAttrDict(op, index);
71  return resultDict ? resultDict.getValue() : llvm::None;
72 }
73 
74 /// Insert the specified arguments and update the function type attribute.
76  TypeRange argTypes,
77  ArrayRef<DictionaryAttr> argAttrs,
78  ArrayRef<Location> argLocs,
79  unsigned originalNumArgs, Type newType);
80 
81 /// Insert the specified results and update the function type attribute.
82 void insertFunctionResults(Operation *op, ArrayRef<unsigned> resultIndices,
83  TypeRange resultTypes,
84  ArrayRef<DictionaryAttr> resultAttrs,
85  unsigned originalNumResults, Type newType);
86 
87 /// Erase the specified arguments and update the function type attribute.
88 void eraseFunctionArguments(Operation *op, const BitVector &argIndices,
89  Type newType);
90 
91 /// Erase the specified results and update the function type attribute.
92 void eraseFunctionResults(Operation *op, const BitVector &resultIndices,
93  Type newType);
94 
95 /// Set a FunctionOpInterface operation's type signature.
96 void setFunctionType(Operation *op, Type newType);
97 
98 /// Insert a set of `newTypes` into `oldTypes` at the given `indices`. If any
99 /// types are inserted, `storage` is used to hold the new type list. The new
100 /// type list is returned. `indices` must be sorted by increasing index.
102  TypeRange newTypes, SmallVectorImpl<Type> &storage);
103 
104 /// Filters out any elements referenced by `indices`. If any types are removed,
105 /// `storage` is used to hold the new type list. Returns the new type list.
106 TypeRange filterTypesOut(TypeRange types, const BitVector &indices,
107  SmallVectorImpl<Type> &storage);
108 
109 //===----------------------------------------------------------------------===//
110 // Function Argument Attribute.
111 //===----------------------------------------------------------------------===//
112 
113 /// Set the attributes held by the argument at 'index'.
114 template <typename ConcreteType>
115 void setArgAttrs(ConcreteType op, unsigned index,
116  ArrayRef<NamedAttribute> attributes) {
117  assert(index < op.getNumArguments() && "invalid argument number");
119  op, getArgDictAttrName(), op.getNumArguments(), index,
120  DictionaryAttr::get(op->getContext(), attributes));
121 }
122 template <typename ConcreteType>
123 void setArgAttrs(ConcreteType op, unsigned index, DictionaryAttr attributes) {
125  op, getArgDictAttrName(), op.getNumArguments(), index,
126  attributes ? attributes : DictionaryAttr::get(op->getContext()));
127 }
128 
129 /// If the an attribute exists with the specified name, change it to the new
130 /// value. Otherwise, add a new attribute with the specified name/value.
131 template <typename ConcreteType>
132 void setArgAttr(ConcreteType op, unsigned index, StringAttr name,
133  Attribute value) {
134  NamedAttrList attributes(op.getArgAttrDict(index));
135  Attribute oldValue = attributes.set(name, value);
136 
137  // If the attribute changed, then set the new arg attribute list.
138  if (value != oldValue)
139  op.setArgAttrs(index, attributes.getDictionary(value.getContext()));
140 }
141 
142 /// Remove the attribute 'name' from the argument at 'index'. Returns the
143 /// removed attribute, or nullptr if `name` was not a valid attribute.
144 template <typename ConcreteType>
145 Attribute removeArgAttr(ConcreteType op, unsigned index, StringAttr name) {
146  // Build an attribute list and remove the attribute at 'name'.
147  NamedAttrList attributes(op.getArgAttrDict(index));
148  Attribute removedAttr = attributes.erase(name);
149 
150  // If the attribute was removed, then update the argument dictionary.
151  if (removedAttr)
152  op.setArgAttrs(index, attributes.getDictionary(removedAttr.getContext()));
153  return removedAttr;
154 }
155 
156 //===----------------------------------------------------------------------===//
157 // Function Result Attribute.
158 //===----------------------------------------------------------------------===//
159 
160 /// Set the attributes held by the result at 'index'.
161 template <typename ConcreteType>
162 void setResultAttrs(ConcreteType op, unsigned index,
163  ArrayRef<NamedAttribute> attributes) {
164  assert(index < op.getNumResults() && "invalid result number");
166  op, getResultDictAttrName(), op.getNumResults(), index,
167  DictionaryAttr::get(op->getContext(), attributes));
168 }
169 
170 template <typename ConcreteType>
171 void setResultAttrs(ConcreteType op, unsigned index,
172  DictionaryAttr attributes) {
173  assert(index < op.getNumResults() && "invalid result number");
175  op, getResultDictAttrName(), op.getNumResults(), index,
176  attributes ? attributes : DictionaryAttr::get(op->getContext()));
177 }
178 
179 /// If the an attribute exists with the specified name, change it to the new
180 /// value. Otherwise, add a new attribute with the specified name/value.
181 template <typename ConcreteType>
182 void setResultAttr(ConcreteType op, unsigned index, StringAttr name,
183  Attribute value) {
184  NamedAttrList attributes(op.getResultAttrDict(index));
185  Attribute oldAttr = attributes.set(name, value);
186 
187  // If the attribute changed, then set the new arg attribute list.
188  if (oldAttr != value)
189  op.setResultAttrs(index, attributes.getDictionary(value.getContext()));
190 }
191 
192 /// Remove the attribute 'name' from the result at 'index'.
193 template <typename ConcreteType>
194 Attribute removeResultAttr(ConcreteType op, unsigned index, StringAttr name) {
195  // Build an attribute list and remove the attribute at 'name'.
196  NamedAttrList attributes(op.getResultAttrDict(index));
197  Attribute removedAttr = attributes.erase(name);
198 
199  // If the attribute was removed, then update the result dictionary.
200  if (removedAttr)
201  op.setResultAttrs(index,
202  attributes.getDictionary(removedAttr.getContext()));
203  return removedAttr;
204 }
205 
206 /// This function defines the internal implementation of the `verifyTrait`
207 /// method on FunctionOpInterface::Trait.
208 template <typename ConcreteOp>
209 LogicalResult verifyTrait(ConcreteOp op) {
210  if (!op.getFunctionTypeAttr())
211  return op.emitOpError("requires a type attribute '")
213 
214  if (failed(op.verifyType()))
215  return failure();
216 
217  if (ArrayAttr allArgAttrs = op.getAllArgAttrs()) {
218  unsigned numArgs = op.getNumArguments();
219  if (allArgAttrs.size() != numArgs) {
220  return op.emitOpError()
221  << "expects argument attribute array `" << getArgDictAttrName()
222  << "` to have the same number of elements as the number of "
223  "function arguments, got "
224  << allArgAttrs.size() << ", but expected " << numArgs;
225  }
226  for (unsigned i = 0; i != numArgs; ++i) {
227  DictionaryAttr argAttrs =
228  allArgAttrs[i].dyn_cast_or_null<DictionaryAttr>();
229  if (!argAttrs) {
230  return op.emitOpError() << "expects argument attribute dictionary "
231  "to be a DictionaryAttr, but got `"
232  << allArgAttrs[i] << "`";
233  }
234 
235  // Verify that all of the argument attributes are dialect attributes, i.e.
236  // that they contain a dialect prefix in their name. Call the dialect, if
237  // registered, to verify the attributes themselves.
238  for (auto attr : argAttrs) {
239  if (!attr.getName().strref().contains('.'))
240  return op.emitOpError("arguments may only have dialect attributes");
241  if (Dialect *dialect = attr.getNameDialect()) {
242  if (failed(dialect->verifyRegionArgAttribute(op, /*regionIndex=*/0,
243  /*argIndex=*/i, attr)))
244  return failure();
245  }
246  }
247  }
248  }
249  if (ArrayAttr allResultAttrs = op.getAllResultAttrs()) {
250  unsigned numResults = op.getNumResults();
251  if (allResultAttrs.size() != numResults) {
252  return op.emitOpError()
253  << "expects result attribute array `" << getResultDictAttrName()
254  << "` to have the same number of elements as the number of "
255  "function results, got "
256  << allResultAttrs.size() << ", but expected " << numResults;
257  }
258  for (unsigned i = 0; i != numResults; ++i) {
259  DictionaryAttr resultAttrs =
260  allResultAttrs[i].dyn_cast_or_null<DictionaryAttr>();
261  if (!resultAttrs) {
262  return op.emitOpError() << "expects result attribute dictionary "
263  "to be a DictionaryAttr, but got `"
264  << allResultAttrs[i] << "`";
265  }
266 
267  // Verify that all of the result attributes are dialect attributes, i.e.
268  // that they contain a dialect prefix in their name. Call the dialect, if
269  // registered, to verify the attributes themselves.
270  for (auto attr : resultAttrs) {
271  if (!attr.getName().strref().contains('.'))
272  return op.emitOpError("results may only have dialect attributes");
273  if (Dialect *dialect = attr.getNameDialect()) {
274  if (failed(dialect->verifyRegionResultAttribute(op, /*regionIndex=*/0,
275  /*resultIndex=*/i,
276  attr)))
277  return failure();
278  }
279  }
280  }
281  }
282 
283  // Check that the op has exactly one region for the body.
284  if (op->getNumRegions() != 1)
285  return op.emitOpError("expects one region");
286 
287  return op.verifyBody();
288 }
289 } // namespace function_interface_impl
290 } // namespace mlir
291 
292 //===----------------------------------------------------------------------===//
293 // Tablegen Interface Declarations
294 //===----------------------------------------------------------------------===//
295 
296 #include "mlir/IR/FunctionOpInterfaces.h.inc"
297 
298 #endif // MLIR_IR_FUNCTIONINTERFACES_H
Include the generated interface declarations.
StringRef getResultDictAttrName()
Return the name of the attribute used for function argument attributes.
DictionaryAttr getResultAttrDict(Operation *op, unsigned index)
Returns the dictionary attribute corresponding to the result at &#39;index&#39;.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
void setArgAttr(ConcreteType op, unsigned index, StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
StringRef getArgDictAttrName()
Return the name of the attribute used for function argument attributes.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
void setAllArgAttrDicts(Operation *op, ArrayRef< DictionaryAttr > attrs)
Set all of the argument or result attribute dictionaries for a function.
void insertFunctionResults(Operation *op, ArrayRef< unsigned > resultIndices, TypeRange resultTypes, ArrayRef< DictionaryAttr > resultAttrs, unsigned originalNumResults, Type newType)
Insert the specified results and update the function type attribute.
TypeRange filterTypesOut(TypeRange types, const BitVector &indices, SmallVectorImpl< Type > &storage)
Filters out any elements referenced by indices.
void eraseFunctionResults(Operation *op, const BitVector &resultIndices, Type newType)
Erase the specified results and update the function type attribute.
StringRef getTypeAttrName()
Return the name of the attribute used for function types.
DictionaryAttr getArgAttrDict(Operation *op, unsigned index)
Returns the dictionary attribute corresponding to the argument at &#39;index&#39;.
static constexpr const bool value
void setResultAttr(ConcreteType op, unsigned index, StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
void setResultAttrs(ConcreteType op, unsigned index, ArrayRef< NamedAttribute > attributes)
Set the attributes held by the result at &#39;index&#39;.
void setArgResAttrDict(Operation *op, StringRef attrName, unsigned numTotalIndices, unsigned index, DictionaryAttr attrs)
Update the given index into an argument or result attribute dictionary.
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:20
Attributes are known-constant values of operations.
Definition: Attributes.h:24
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
void insertFunctionArguments(Operation *op, ArrayRef< unsigned > argIndices, TypeRange argTypes, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< Location > argLocs, unsigned originalNumArgs, Type newType)
Insert the specified arguments and update the function type attribute.
void setFunctionType(Operation *op, Type newType)
Set a FunctionOpInterface operation&#39;s type signature.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
ArrayRef< NamedAttribute > getArgAttrs(Operation *op, unsigned index)
Return all of the attributes for the argument at &#39;index&#39;.
void eraseFunctionArguments(Operation *op, const BitVector &argIndices, Type newType)
Erase the specified arguments and update the function type attribute.
LogicalResult verifyTrait(ConcreteOp op)
This function defines the internal implementation of the verifyTrait method on FunctionOpInterface::T...
Attribute removeArgAttr(ConcreteType op, unsigned index, StringAttr name)
Remove the attribute &#39;name&#39; from the argument at &#39;index&#39;.
void setArgAttrs(ConcreteType op, unsigned index, ArrayRef< NamedAttribute > attributes)
Set the attributes held by the argument at &#39;index&#39;.
ArrayRef< NamedAttribute > getResultAttrs(Operation *op, unsigned index)
Return all of the attributes for the result at &#39;index&#39;.
void setAllResultAttrDicts(Operation *op, ArrayRef< DictionaryAttr > attrs)
TypeRange insertTypesInto(TypeRange oldTypes, ArrayRef< unsigned > indices, TypeRange newTypes, SmallVectorImpl< Type > &storage)
Insert a set of newTypes into oldTypes at the given indices.
Attribute removeResultAttr(ConcreteType op, unsigned index, StringAttr name)
Remove the attribute &#39;name&#39; from the result at &#39;index&#39;.