MLIR  17.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 class FunctionOpInterface;
26 
27 namespace function_interface_impl {
28 
29 /// Returns the dictionary attribute corresponding to the argument at 'index'.
30 /// If there are no argument attributes at 'index', a null attribute is
31 /// returned.
32 DictionaryAttr getArgAttrDict(FunctionOpInterface op, unsigned index);
33 
34 /// Returns the dictionary attribute corresponding to the result at 'index'.
35 /// If there are no result attributes at 'index', a null attribute is
36 /// returned.
37 DictionaryAttr getResultAttrDict(FunctionOpInterface op, unsigned index);
38 
39 /// Return all of the attributes for the argument at 'index'.
40 ArrayRef<NamedAttribute> getArgAttrs(FunctionOpInterface op, unsigned index);
41 
42 /// Return all of the attributes for the result at 'index'.
43 ArrayRef<NamedAttribute> getResultAttrs(FunctionOpInterface op, unsigned index);
44 
45 /// Set all of the argument or result attribute dictionaries for a function. The
46 /// size of `attrs` is expected to match the number of arguments/results of the
47 /// given `op`.
48 void setAllArgAttrDicts(FunctionOpInterface op, ArrayRef<DictionaryAttr> attrs);
49 void setAllArgAttrDicts(FunctionOpInterface op, ArrayRef<Attribute> attrs);
50 void setAllResultAttrDicts(FunctionOpInterface op,
51  ArrayRef<DictionaryAttr> attrs);
52 void setAllResultAttrDicts(FunctionOpInterface op, ArrayRef<Attribute> attrs);
53 
54 /// Insert the specified arguments and update the function type attribute.
55 void insertFunctionArguments(FunctionOpInterface op,
56  ArrayRef<unsigned> argIndices, TypeRange argTypes,
57  ArrayRef<DictionaryAttr> argAttrs,
58  ArrayRef<Location> argLocs,
59  unsigned originalNumArgs, Type newType);
60 
61 /// Insert the specified results and update the function type attribute.
62 void insertFunctionResults(FunctionOpInterface op,
63  ArrayRef<unsigned> resultIndices,
64  TypeRange resultTypes,
65  ArrayRef<DictionaryAttr> resultAttrs,
66  unsigned originalNumResults, Type newType);
67 
68 /// Erase the specified arguments and update the function type attribute.
69 void eraseFunctionArguments(FunctionOpInterface op, const BitVector &argIndices,
70  Type newType);
71 
72 /// Erase the specified results and update the function type attribute.
73 void eraseFunctionResults(FunctionOpInterface op,
74  const BitVector &resultIndices, Type newType);
75 
76 /// Set a FunctionOpInterface operation's type signature.
77 void setFunctionType(FunctionOpInterface op, Type newType);
78 
79 /// Insert a set of `newTypes` into `oldTypes` at the given `indices`. If any
80 /// types are inserted, `storage` is used to hold the new type list. The new
81 /// type list is returned. `indices` must be sorted by increasing index.
82 TypeRange insertTypesInto(TypeRange oldTypes, ArrayRef<unsigned> indices,
83  TypeRange newTypes, SmallVectorImpl<Type> &storage);
84 
85 /// Filters out any elements referenced by `indices`. If any types are removed,
86 /// `storage` is used to hold the new type list. Returns the new type list.
87 TypeRange filterTypesOut(TypeRange types, const BitVector &indices,
88  SmallVectorImpl<Type> &storage);
89 
90 //===----------------------------------------------------------------------===//
91 // Function Argument Attribute.
92 //===----------------------------------------------------------------------===//
93 
94 /// Set the attributes held by the argument at 'index'.
95 void setArgAttrs(FunctionOpInterface op, unsigned index,
96  ArrayRef<NamedAttribute> attributes);
97 void setArgAttrs(FunctionOpInterface op, unsigned index,
98  DictionaryAttr attributes);
99 
100 /// If the an attribute exists with the specified name, change it to the new
101 /// value. Otherwise, add a new attribute with the specified name/value.
102 template <typename ConcreteType>
103 void setArgAttr(ConcreteType op, unsigned index, StringAttr name,
104  Attribute value) {
105  NamedAttrList attributes(op.getArgAttrDict(index));
106  Attribute oldValue = attributes.set(name, value);
107 
108  // If the attribute changed, then set the new arg attribute list.
109  if (value != oldValue)
110  op.setArgAttrs(index, attributes.getDictionary(value.getContext()));
111 }
112 
113 /// Remove the attribute 'name' from the argument at 'index'. Returns the
114 /// removed attribute, or nullptr if `name` was not a valid attribute.
115 template <typename ConcreteType>
116 Attribute removeArgAttr(ConcreteType op, unsigned index, StringAttr name) {
117  // Build an attribute list and remove the attribute at 'name'.
118  NamedAttrList attributes(op.getArgAttrDict(index));
119  Attribute removedAttr = attributes.erase(name);
120 
121  // If the attribute was removed, then update the argument dictionary.
122  if (removedAttr)
123  op.setArgAttrs(index, attributes.getDictionary(removedAttr.getContext()));
124  return removedAttr;
125 }
126 
127 //===----------------------------------------------------------------------===//
128 // Function Result Attribute.
129 //===----------------------------------------------------------------------===//
130 
131 /// Set the attributes held by the result at 'index'.
132 void setResultAttrs(FunctionOpInterface op, unsigned index,
133  ArrayRef<NamedAttribute> attributes);
134 void setResultAttrs(FunctionOpInterface op, unsigned index,
135  DictionaryAttr attributes);
136 
137 /// If the an attribute exists with the specified name, change it to the new
138 /// value. Otherwise, add a new attribute with the specified name/value.
139 template <typename ConcreteType>
140 void setResultAttr(ConcreteType op, unsigned index, StringAttr name,
141  Attribute value) {
142  NamedAttrList attributes(op.getResultAttrDict(index));
143  Attribute oldAttr = attributes.set(name, value);
144 
145  // If the attribute changed, then set the new arg attribute list.
146  if (oldAttr != value)
147  op.setResultAttrs(index, attributes.getDictionary(value.getContext()));
148 }
149 
150 /// Remove the attribute 'name' from the result at 'index'.
151 template <typename ConcreteType>
152 Attribute removeResultAttr(ConcreteType op, unsigned index, StringAttr name) {
153  // Build an attribute list and remove the attribute at 'name'.
154  NamedAttrList attributes(op.getResultAttrDict(index));
155  Attribute removedAttr = attributes.erase(name);
156 
157  // If the attribute was removed, then update the result dictionary.
158  if (removedAttr)
159  op.setResultAttrs(index,
160  attributes.getDictionary(removedAttr.getContext()));
161  return removedAttr;
162 }
163 
164 /// This function defines the internal implementation of the `verifyTrait`
165 /// method on FunctionOpInterface::Trait.
166 template <typename ConcreteOp>
167 LogicalResult verifyTrait(ConcreteOp op) {
168  if (failed(op.verifyType()))
169  return failure();
170 
171  if (ArrayAttr allArgAttrs = op.getAllArgAttrs()) {
172  unsigned numArgs = op.getNumArguments();
173  if (allArgAttrs.size() != numArgs) {
174  return op.emitOpError()
175  << "expects argument attribute array to have the same number of "
176  "elements as the number of function arguments, got "
177  << allArgAttrs.size() << ", but expected " << numArgs;
178  }
179  for (unsigned i = 0; i != numArgs; ++i) {
180  DictionaryAttr argAttrs =
181  allArgAttrs[i].dyn_cast_or_null<DictionaryAttr>();
182  if (!argAttrs) {
183  return op.emitOpError() << "expects argument attribute dictionary "
184  "to be a DictionaryAttr, but got `"
185  << allArgAttrs[i] << "`";
186  }
187 
188  // Verify that all of the argument attributes are dialect attributes, i.e.
189  // that they contain a dialect prefix in their name. Call the dialect, if
190  // registered, to verify the attributes themselves.
191  for (auto attr : argAttrs) {
192  if (!attr.getName().strref().contains('.'))
193  return op.emitOpError("arguments may only have dialect attributes");
194  if (Dialect *dialect = attr.getNameDialect()) {
195  if (failed(dialect->verifyRegionArgAttribute(op, /*regionIndex=*/0,
196  /*argIndex=*/i, attr)))
197  return failure();
198  }
199  }
200  }
201  }
202  if (ArrayAttr allResultAttrs = op.getAllResultAttrs()) {
203  unsigned numResults = op.getNumResults();
204  if (allResultAttrs.size() != numResults) {
205  return op.emitOpError()
206  << "expects result attribute array to have the same number of "
207  "elements as the number of function results, got "
208  << allResultAttrs.size() << ", but expected " << numResults;
209  }
210  for (unsigned i = 0; i != numResults; ++i) {
211  DictionaryAttr resultAttrs =
212  allResultAttrs[i].dyn_cast_or_null<DictionaryAttr>();
213  if (!resultAttrs) {
214  return op.emitOpError() << "expects result attribute dictionary "
215  "to be a DictionaryAttr, but got `"
216  << allResultAttrs[i] << "`";
217  }
218 
219  // Verify that all of the result attributes are dialect attributes, i.e.
220  // that they contain a dialect prefix in their name. Call the dialect, if
221  // registered, to verify the attributes themselves.
222  for (auto attr : resultAttrs) {
223  if (!attr.getName().strref().contains('.'))
224  return op.emitOpError("results may only have dialect attributes");
225  if (Dialect *dialect = attr.getNameDialect()) {
226  if (failed(dialect->verifyRegionResultAttribute(op, /*regionIndex=*/0,
227  /*resultIndex=*/i,
228  attr)))
229  return failure();
230  }
231  }
232  }
233  }
234 
235  // Check that the op has exactly one region for the body.
236  if (op->getNumRegions() != 1)
237  return op.emitOpError("expects one region");
238 
239  return op.verifyBody();
240 }
241 } // namespace function_interface_impl
242 } // namespace mlir
243 
244 //===----------------------------------------------------------------------===//
245 // Tablegen Interface Declarations
246 //===----------------------------------------------------------------------===//
247 
248 #include "mlir/IR/FunctionOpInterfaces.h.inc"
249 
250 #endif // MLIR_IR_FUNCTIONINTERFACES_H
Attributes are known-constant values of operations.
Definition: Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:20
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
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 erase(StringAttr name)
Erase the attribute with the given name from the list.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
ArrayRef< NamedAttribute > getResultAttrs(FunctionOpInterface op, unsigned index)
Return all of the attributes for the result at 'index'.
void setAllResultAttrDicts(FunctionOpInterface op, ArrayRef< DictionaryAttr > attrs)
void insertFunctionArguments(FunctionOpInterface 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.
LogicalResult verifyTrait(ConcreteOp op)
This function defines the internal implementation of the verifyTrait method on FunctionOpInterface::T...
void setResultAttrs(FunctionOpInterface op, unsigned index, ArrayRef< NamedAttribute > attributes)
Set the attributes held by the result at 'index'.
Attribute removeArgAttr(ConcreteType op, unsigned index, StringAttr name)
Remove the attribute 'name' from the argument at 'index'.
void eraseFunctionResults(FunctionOpInterface op, const BitVector &resultIndices, Type newType)
Erase the specified results and update the function type attribute.
void setArgAttrs(FunctionOpInterface op, unsigned index, ArrayRef< NamedAttribute > attributes)
Set the attributes held by the argument at 'index'.
ArrayRef< NamedAttribute > getArgAttrs(FunctionOpInterface op, unsigned index)
Return all of the attributes for the argument at 'index'.
void setAllArgAttrDicts(FunctionOpInterface op, ArrayRef< DictionaryAttr > attrs)
Set all of the argument or result attribute dictionaries for a function.
void insertFunctionResults(FunctionOpInterface op, ArrayRef< unsigned > resultIndices, TypeRange resultTypes, ArrayRef< DictionaryAttr > resultAttrs, unsigned originalNumResults, Type newType)
Insert the specified results and update the function type attribute.
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.
TypeRange insertTypesInto(TypeRange oldTypes, ArrayRef< unsigned > indices, TypeRange newTypes, SmallVectorImpl< Type > &storage)
Insert a set of newTypes into oldTypes at the given indices.
DictionaryAttr getResultAttrDict(FunctionOpInterface op, unsigned index)
Returns the dictionary attribute corresponding to the result at 'index'.
DictionaryAttr getArgAttrDict(FunctionOpInterface op, unsigned index)
Returns the dictionary attribute corresponding to the argument at 'index'.
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 eraseFunctionArguments(FunctionOpInterface op, const BitVector &argIndices, Type newType)
Erase the specified arguments and update the function type attribute.
TypeRange filterTypesOut(TypeRange types, const BitVector &indices, SmallVectorImpl< Type > &storage)
Filters out any elements referenced by indices.
void setFunctionType(FunctionOpInterface op, Type newType)
Set a FunctionOpInterface operation's type signature.
Attribute removeResultAttr(ConcreteType op, unsigned index, StringAttr name)
Remove the attribute 'name' from the result at 'index'.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26