252 lines
9.7 KiB
TableGen
252 lines
9.7 KiB
TableGen
//===- SymbolInterfaces.td - Interfaces for symbol ops -----*- tablegen -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains a set of interfaces and traits that can be used to define
|
|
// properties of symbol and symbol table operations.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_IR_SYMBOLINTERFACES
|
|
#define MLIR_IR_SYMBOLINTERFACES
|
|
|
|
include "mlir/IR/OpBase.td"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SymbolOpInterface
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Symbol : OpInterface<"SymbolOpInterface"> {
|
|
let description = [{
|
|
This interface describes an operation that may define a `Symbol`. A `Symbol`
|
|
operation resides immediately within a region that defines a `SymbolTable`.
|
|
See [Symbols and SymbolTables](../SymbolsAndSymbolTables.md) for more details
|
|
and constraints on `Symbol` operations.
|
|
}];
|
|
let cppNamespace = "::mlir";
|
|
|
|
let methods = [
|
|
InterfaceMethod<"Returns the name of this symbol.",
|
|
"::mlir::StringAttr", "getNameAttr", (ins), [{
|
|
// Don't rely on the trait implementation as optional symbol operations
|
|
// may override this.
|
|
return mlir::SymbolTable::getSymbolName($_op);
|
|
}], /*defaultImplementation=*/[{
|
|
return mlir::SymbolTable::getSymbolName(this->getOperation());
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Sets the name of this symbol.",
|
|
"void", "setName", (ins "::mlir::StringAttr":$name), [{}],
|
|
/*defaultImplementation=*/[{
|
|
this->getOperation()->setAttr(
|
|
mlir::SymbolTable::getSymbolAttrName(), name);
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Gets the visibility of this symbol.",
|
|
"mlir::SymbolTable::Visibility", "getVisibility", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return mlir::SymbolTable::getSymbolVisibility(this->getOperation());
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Returns true if this symbol has nested visibility.",
|
|
"bool", "isNested", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return $_op.getVisibility() == mlir::SymbolTable::Visibility::Nested;
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Returns true if this symbol has private visibility.",
|
|
"bool", "isPrivate", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return $_op.getVisibility() == mlir::SymbolTable::Visibility::Private;
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Returns true if this symbol has public visibility.",
|
|
"bool", "isPublic", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return $_op.getVisibility() == mlir::SymbolTable::Visibility::Public;
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Sets the visibility of this symbol.",
|
|
"void", "setVisibility", (ins "mlir::SymbolTable::Visibility":$vis), [{}],
|
|
/*defaultImplementation=*/[{
|
|
mlir::SymbolTable::setSymbolVisibility(this->getOperation(), vis);
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Sets the visibility of this symbol to be nested.",
|
|
"void", "setNested", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
$_op.setVisibility(mlir::SymbolTable::Visibility::Nested);
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Sets the visibility of this symbol to be private.",
|
|
"void", "setPrivate", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
$_op.setVisibility(mlir::SymbolTable::Visibility::Private);
|
|
}]
|
|
>,
|
|
InterfaceMethod<"Sets the visibility of this symbol to be public.",
|
|
"void", "setPublic", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
$_op.setVisibility(mlir::SymbolTable::Visibility::Public);
|
|
}]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Get all of the uses of the current symbol that are nested within the
|
|
given operation 'from'.
|
|
Note: See mlir::SymbolTable::getSymbolUses for more details.
|
|
}],
|
|
"::std::optional<::mlir::SymbolTable::UseRange>", "getSymbolUses",
|
|
(ins "::mlir::Operation *":$from), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return ::mlir::SymbolTable::getSymbolUses(this->getOperation(), from);
|
|
}]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Return if the current symbol is known to have no uses that are nested
|
|
within the given operation 'from'.
|
|
Note: See mlir::SymbolTable::symbolKnownUseEmpty for more details.
|
|
}],
|
|
"bool", "symbolKnownUseEmpty", (ins "::mlir::Operation *":$from), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return ::mlir::SymbolTable::symbolKnownUseEmpty(this->getOperation(),
|
|
from);
|
|
}]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Attempt to replace all uses of the current symbol with the provided
|
|
symbol 'newSymbol' that are nested within the given operation 'from'.
|
|
Note: See mlir::SymbolTable::replaceAllSymbolUses for more details.
|
|
}],
|
|
"::llvm::LogicalResult", "replaceAllSymbolUses",
|
|
(ins "::mlir::StringAttr":$newSymbol, "::mlir::Operation *":$from), [{}],
|
|
/*defaultImplementation=*/[{
|
|
return ::mlir::SymbolTable::replaceAllSymbolUses(this->getOperation(),
|
|
newSymbol, from);
|
|
}]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Returns true if this operation optionally defines a symbol based on the
|
|
presence of the symbol name.
|
|
}],
|
|
"bool", "isOptionalSymbol", (ins), [{}],
|
|
/*defaultImplementation=*/[{ return false; }]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Returns true if this operation can be discarded if it has no remaining
|
|
symbol uses.
|
|
}],
|
|
"bool", "canDiscardOnUseEmpty", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
// By default, base this on the visibility alone. A symbol can be
|
|
// discarded as long as it is not public. Only public symbols may be
|
|
// visible from outside of the IR.
|
|
return $_op.getVisibility() != ::mlir::SymbolTable::Visibility::Public;
|
|
}]
|
|
>,
|
|
InterfaceMethod<[{
|
|
Returns true if this operation is a declaration of a symbol (as opposed
|
|
to a definition).
|
|
}],
|
|
"bool", "isDeclaration", (ins), [{}],
|
|
/*defaultImplementation=*/[{
|
|
// By default, assume that the operation defines a symbol.
|
|
return false;
|
|
}]
|
|
>,
|
|
];
|
|
|
|
let verify = [{
|
|
// If this is an optional symbol, bail out early if possible.
|
|
auto concreteOp = cast<ConcreteOp>($_op);
|
|
if (concreteOp.isOptionalSymbol()) {
|
|
if(!concreteOp->getInherentAttr(::mlir::SymbolTable::getSymbolAttrName()).value_or(Attribute{}))
|
|
return success();
|
|
}
|
|
if (::mlir::failed(::mlir::detail::verifySymbol($_op)))
|
|
return ::mlir::failure();
|
|
if (concreteOp.isDeclaration() && concreteOp.isPublic())
|
|
return concreteOp.emitOpError("symbol declaration cannot have public "
|
|
"visibility");
|
|
if ($_op->getNumResults() != 0)
|
|
return concreteOp.emitOpError("symbols must not have results");
|
|
auto parent = $_op->getParentOp();
|
|
if (parent && !parent->hasTrait<OpTrait::SymbolTable>() && parent->isRegistered()) {
|
|
return concreteOp.emitOpError("symbol's parent must have the SymbolTable "
|
|
"trait");
|
|
}
|
|
return success();
|
|
}];
|
|
|
|
let extraSharedClassDeclaration = [{
|
|
using Visibility = mlir::SymbolTable::Visibility;
|
|
|
|
/// Convenience version of `getNameAttr` that returns a StringRef.
|
|
::mlir::StringRef getName() {
|
|
return getNameAttr().getValue();
|
|
}
|
|
|
|
/// Convenience version of `setName` that take a StringRef.
|
|
void setName(::mlir::StringRef name) {
|
|
setName(::mlir::StringAttr::get($_op->getContext(), name));
|
|
}
|
|
}];
|
|
|
|
// Add additional classof checks to properly handle "optional" symbols.
|
|
let extraClassOf = [{
|
|
return $_op->hasAttr(::mlir::SymbolTable::getSymbolAttrName());
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SymbolUserOpInterface
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def SymbolUserOpInterface : OpInterface<"SymbolUserOpInterface"> {
|
|
let description = [{
|
|
This interface describes an operation that may use a `Symbol`. This
|
|
interface allows for users of symbols to hook into verification and other
|
|
symbol related utilities that are either costly or otherwise disallowed
|
|
within an operation.
|
|
}];
|
|
let cppNamespace = "::mlir";
|
|
|
|
let methods = [
|
|
InterfaceMethod<"Verify the symbol uses held by this operation.",
|
|
"::llvm::LogicalResult", "verifySymbolUses",
|
|
(ins "::mlir::SymbolTableCollection &":$symbolTable)
|
|
>,
|
|
];
|
|
}
|
|
|
|
def SymbolUserAttrInterface : AttrInterface<"SymbolUserAttrInterface"> {
|
|
let description = [{
|
|
This interface describes an attribute that may use a `Symbol`. This
|
|
interface allows for users of symbols to hook into verification and other
|
|
symbol related utilities that are either costly or otherwise disallowed
|
|
within an operation (e.g., recreating symbol users per op verified rather
|
|
than per symbol table, or querying symbols usage of sibblings).
|
|
}];
|
|
let cppNamespace = "::mlir";
|
|
|
|
let methods = [
|
|
InterfaceMethod<"Verify the symbol uses held by this attribute of this operation.",
|
|
"::llvm::LogicalResult", "verifySymbolUses",
|
|
(ins "::mlir::Operation *":$op,
|
|
"::mlir::SymbolTableCollection &":$symbolTable)
|
|
>,
|
|
];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Symbol Traits
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Op defines a symbol table.
|
|
def SymbolTable : NativeOpTrait<"SymbolTable">;
|
|
|
|
#endif // MLIR_IR_SYMBOLINTERFACES
|