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