Files
clang-p2996/mlir/lib/TableGen/Interfaces.cpp
River Riddle 2e2cdd0a52 [mlir] Refactor InterfaceGen to support generating interfaces for Attributes and Types.
This revision adds support to ODS for generating interfaces for attributes and types, in addition to operations. These interfaces can be specified using `AttrInterface` and `TypeInterface` in place of `OpInterface`. All of the features of `OpInterface` are supported except for the `verify` method, which does not have a matching representation in the Attribute/Type world. Generating these interface can be done using `gen-(attr|type)-interface-(defs|decls|docs)`.

Differential Revision: https://reviews.llvm.org/D81884
2020-06-30 15:52:33 -07:00

140 lines
5.0 KiB
C++

//===- Interfaces.cpp - Interface classes ---------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "mlir/TableGen/Interfaces.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace mlir;
using namespace mlir::tblgen;
//===----------------------------------------------------------------------===//
// InterfaceMethod
//===----------------------------------------------------------------------===//
InterfaceMethod::InterfaceMethod(const llvm::Record *def) : def(def) {
llvm::DagInit *args = def->getValueAsDag("arguments");
for (unsigned i = 0, e = args->getNumArgs(); i != e; ++i) {
arguments.push_back(
{llvm::cast<llvm::StringInit>(args->getArg(i))->getValue(),
args->getArgNameStr(i)});
}
}
StringRef InterfaceMethod::getReturnType() const {
return def->getValueAsString("returnType");
}
// Return the name of this method.
StringRef InterfaceMethod::getName() const {
return def->getValueAsString("name");
}
// Return if this method is static.
bool InterfaceMethod::isStatic() const {
return def->isSubClassOf("StaticInterfaceMethod");
}
// Return the body for this method if it has one.
llvm::Optional<StringRef> InterfaceMethod::getBody() const {
auto value = def->getValueAsString("body");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
// Return the default implementation for this method if it has one.
llvm::Optional<StringRef> InterfaceMethod::getDefaultImplementation() const {
auto value = def->getValueAsString("defaultBody");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
// Return the description of this method if it has one.
llvm::Optional<StringRef> InterfaceMethod::getDescription() const {
auto value = def->getValueAsString("description");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
ArrayRef<InterfaceMethod::Argument> InterfaceMethod::getArguments() const {
return arguments;
}
bool InterfaceMethod::arg_empty() const { return arguments.empty(); }
//===----------------------------------------------------------------------===//
// Interface
//===----------------------------------------------------------------------===//
Interface::Interface(const llvm::Record *def) : def(def) {
assert(def->isSubClassOf("Interface") &&
"must be subclass of TableGen 'Interface' class");
auto *listInit = dyn_cast<llvm::ListInit>(def->getValueInit("methods"));
for (llvm::Init *init : listInit->getValues())
methods.emplace_back(cast<llvm::DefInit>(init)->getDef());
}
// Return the name of this interface.
StringRef Interface::getName() const {
return def->getValueAsString("cppClassName");
}
// Return the methods of this interface.
ArrayRef<InterfaceMethod> Interface::getMethods() const { return methods; }
// Return the description of this method if it has one.
llvm::Optional<StringRef> Interface::getDescription() const {
auto value = def->getValueAsString("description");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
// Return the interfaces extra class declaration code.
llvm::Optional<StringRef> Interface::getExtraClassDeclaration() const {
auto value = def->getValueAsString("extraClassDeclaration");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
// Return the traits extra class declaration code.
llvm::Optional<StringRef> Interface::getExtraTraitClassDeclaration() const {
auto value = def->getValueAsString("extraTraitClassDeclaration");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
// Return the body for this method if it has one.
llvm::Optional<StringRef> Interface::getVerify() const {
// Only OpInterface supports the verify method.
if (!isa<OpInterface>(this))
return llvm::None;
auto value = def->getValueAsString("verify");
return value.empty() ? llvm::Optional<StringRef>() : value;
}
//===----------------------------------------------------------------------===//
// AttrInterface
//===----------------------------------------------------------------------===//
bool AttrInterface::classof(const Interface *interface) {
return interface->getDef().isSubClassOf("AttrInterface");
}
//===----------------------------------------------------------------------===//
// OpInterface
//===----------------------------------------------------------------------===//
bool OpInterface::classof(const Interface *interface) {
return interface->getDef().isSubClassOf("OpInterface");
}
//===----------------------------------------------------------------------===//
// TypeInterface
//===----------------------------------------------------------------------===//
bool TypeInterface::classof(const Interface *interface) {
return interface->getDef().isSubClassOf("TypeInterface");
}