xref: /llvm-project/mlir/include/mlir/IR/SymbolInterfaces.td (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
1//===- SymbolInterfaces.td - Interfaces for symbol ops -----*- tablegen -*-===//
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 contains a set of interfaces and traits that can be used to define
10// properties of symbol and symbol table operations.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_IR_SYMBOLINTERFACES
15#define MLIR_IR_SYMBOLINTERFACES
16
17include "mlir/IR/OpBase.td"
18
19//===----------------------------------------------------------------------===//
20// SymbolOpInterface
21//===----------------------------------------------------------------------===//
22
23def Symbol : OpInterface<"SymbolOpInterface"> {
24  let description = [{
25    This interface describes an operation that may define a `Symbol`. A `Symbol`
26    operation resides immediately within a region that defines a `SymbolTable`.
27    See [Symbols and SymbolTables](../SymbolsAndSymbolTables.md) for more details
28    and constraints on `Symbol` operations.
29  }];
30  let cppNamespace = "::mlir";
31
32  let methods = [
33    InterfaceMethod<"Returns the name of this symbol.",
34      "::mlir::StringAttr", "getNameAttr", (ins), [{
35        // Don't rely on the trait implementation as optional symbol operations
36        // may override this.
37        return mlir::SymbolTable::getSymbolName($_op);
38      }], /*defaultImplementation=*/[{
39        return mlir::SymbolTable::getSymbolName(this->getOperation());
40      }]
41    >,
42    InterfaceMethod<"Sets the name of this symbol.",
43      "void", "setName", (ins "::mlir::StringAttr":$name), [{}],
44      /*defaultImplementation=*/[{
45        this->getOperation()->setAttr(
46            mlir::SymbolTable::getSymbolAttrName(), name);
47      }]
48    >,
49    InterfaceMethod<"Gets the visibility of this symbol.",
50      "mlir::SymbolTable::Visibility", "getVisibility", (ins), [{}],
51      /*defaultImplementation=*/[{
52        return mlir::SymbolTable::getSymbolVisibility(this->getOperation());
53      }]
54    >,
55    InterfaceMethod<"Returns true if this symbol has nested visibility.",
56      "bool", "isNested", (ins),  [{}],
57      /*defaultImplementation=*/[{
58        return getVisibility() == mlir::SymbolTable::Visibility::Nested;
59      }]
60    >,
61    InterfaceMethod<"Returns true if this symbol has private visibility.",
62      "bool", "isPrivate", (ins),  [{}],
63      /*defaultImplementation=*/[{
64        return getVisibility() == mlir::SymbolTable::Visibility::Private;
65      }]
66    >,
67    InterfaceMethod<"Returns true if this symbol has public visibility.",
68      "bool", "isPublic", (ins),  [{}],
69      /*defaultImplementation=*/[{
70        return getVisibility() == mlir::SymbolTable::Visibility::Public;
71      }]
72    >,
73    InterfaceMethod<"Sets the visibility of this symbol.",
74      "void", "setVisibility", (ins "mlir::SymbolTable::Visibility":$vis), [{}],
75      /*defaultImplementation=*/[{
76        mlir::SymbolTable::setSymbolVisibility(this->getOperation(), vis);
77      }]
78    >,
79    InterfaceMethod<"Sets the visibility of this symbol to be nested.",
80      "void", "setNested", (ins),  [{}],
81      /*defaultImplementation=*/[{
82        setVisibility(mlir::SymbolTable::Visibility::Nested);
83      }]
84    >,
85    InterfaceMethod<"Sets the visibility of this symbol to be private.",
86      "void", "setPrivate", (ins),  [{}],
87      /*defaultImplementation=*/[{
88        setVisibility(mlir::SymbolTable::Visibility::Private);
89      }]
90    >,
91    InterfaceMethod<"Sets the visibility of this symbol to be public.",
92      "void", "setPublic", (ins),  [{}],
93      /*defaultImplementation=*/[{
94        setVisibility(mlir::SymbolTable::Visibility::Public);
95      }]
96    >,
97    InterfaceMethod<[{
98        Get all of the uses of the current symbol that are nested within the
99        given operation 'from'.
100        Note: See mlir::SymbolTable::getSymbolUses for more details.
101      }],
102      "::std::optional<::mlir::SymbolTable::UseRange>", "getSymbolUses",
103      (ins "::mlir::Operation *":$from), [{}],
104      /*defaultImplementation=*/[{
105        return ::mlir::SymbolTable::getSymbolUses(this->getOperation(), from);
106      }]
107    >,
108    InterfaceMethod<[{
109        Return if the current symbol is known to have no uses that are nested
110        within the given operation 'from'.
111        Note: See mlir::SymbolTable::symbolKnownUseEmpty for more details.
112      }],
113      "bool", "symbolKnownUseEmpty", (ins "::mlir::Operation *":$from), [{}],
114      /*defaultImplementation=*/[{
115        return ::mlir::SymbolTable::symbolKnownUseEmpty(this->getOperation(),
116                                                        from);
117      }]
118    >,
119    InterfaceMethod<[{
120        Attempt to replace all uses of the current symbol with the provided
121        symbol 'newSymbol' that are nested within the given operation 'from'.
122        Note: See mlir::SymbolTable::replaceAllSymbolUses for more details.
123      }],
124      "::llvm::LogicalResult", "replaceAllSymbolUses",
125      (ins "::mlir::StringAttr":$newSymbol, "::mlir::Operation *":$from), [{}],
126      /*defaultImplementation=*/[{
127        return ::mlir::SymbolTable::replaceAllSymbolUses(this->getOperation(),
128                                                         newSymbol, from);
129      }]
130    >,
131    InterfaceMethod<[{
132        Returns true if this operation optionally defines a symbol based on the
133        presence of the symbol name.
134      }],
135      "bool", "isOptionalSymbol", (ins), [{}],
136      /*defaultImplementation=*/[{ return false; }]
137    >,
138    InterfaceMethod<[{
139        Returns true if this operation can be discarded if it has no remaining
140        symbol uses.
141      }],
142      "bool", "canDiscardOnUseEmpty", (ins), [{}],
143      /*defaultImplementation=*/[{
144        // By default, base this on the visibility alone. A symbol can be
145        // discarded as long as it is not public. Only public symbols may be
146        // visible from outside of the IR.
147        return getVisibility() != ::mlir::SymbolTable::Visibility::Public;
148      }]
149    >,
150    InterfaceMethod<[{
151        Returns true if this operation is a declaration of a symbol (as opposed
152        to a definition).
153      }],
154      "bool", "isDeclaration", (ins), [{}],
155      /*defaultImplementation=*/[{
156        // By default, assume that the operation defines a symbol.
157        return false;
158      }]
159    >,
160  ];
161
162  let verify = [{
163    // If this is an optional symbol, bail out early if possible.
164    auto concreteOp = cast<ConcreteOp>($_op);
165    if (concreteOp.isOptionalSymbol()) {
166      if(!concreteOp->getInherentAttr(::mlir::SymbolTable::getSymbolAttrName()).value_or(Attribute{}))
167        return success();
168    }
169    if (::mlir::failed(::mlir::detail::verifySymbol($_op)))
170      return ::mlir::failure();
171    if (concreteOp.isDeclaration() && concreteOp.isPublic())
172      return concreteOp.emitOpError("symbol declaration cannot have public "
173             "visibility");
174    auto parent = $_op->getParentOp();
175    if (parent && !parent->hasTrait<OpTrait::SymbolTable>() && parent->isRegistered()) {
176      return concreteOp.emitOpError("symbol's parent must have the SymbolTable "
177             "trait");
178    }
179    return success();
180  }];
181
182  let extraSharedClassDeclaration = [{
183    using Visibility = mlir::SymbolTable::Visibility;
184
185    /// Convenience version of `getNameAttr` that returns a StringRef.
186    ::mlir::StringRef getName() {
187      return getNameAttr().getValue();
188    }
189
190    /// Convenience version of `setName` that take a StringRef.
191    void setName(::mlir::StringRef name) {
192      setName(::mlir::StringAttr::get($_op->getContext(), name));
193    }
194  }];
195
196  // Add additional classof checks to properly handle "optional" symbols.
197  let extraClassOf = [{
198    return $_op->hasAttr(::mlir::SymbolTable::getSymbolAttrName());
199  }];
200}
201
202//===----------------------------------------------------------------------===//
203// SymbolUserOpInterface
204//===----------------------------------------------------------------------===//
205
206def SymbolUserOpInterface : OpInterface<"SymbolUserOpInterface"> {
207  let description = [{
208    This interface describes an operation that may use a `Symbol`. This
209    interface allows for users of symbols to hook into verification and other
210    symbol related utilities that are either costly or otherwise disallowed
211    within a traditional operation.
212  }];
213  let cppNamespace = "::mlir";
214
215  let methods = [
216    InterfaceMethod<"Verify the symbol uses held by this operation.",
217      "::llvm::LogicalResult", "verifySymbolUses",
218      (ins "::mlir::SymbolTableCollection &":$symbolTable)
219    >,
220  ];
221}
222
223//===----------------------------------------------------------------------===//
224// Symbol Traits
225//===----------------------------------------------------------------------===//
226
227// Op defines a symbol table.
228def SymbolTable : NativeOpTrait<"SymbolTable">;
229
230#endif // MLIR_IR_SYMBOLINTERFACES
231