xref: /llvm-project/mlir/lib/TableGen/Interfaces.cpp (revision 659192b1843c4af180700783caca4cdc7afa3eab)
12e2cdd0aSRiver Riddle //===- Interfaces.cpp - Interface classes ---------------------------------===//
22e2cdd0aSRiver Riddle //
32e2cdd0aSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42e2cdd0aSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
52e2cdd0aSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62e2cdd0aSRiver Riddle //
72e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
82e2cdd0aSRiver Riddle 
92e2cdd0aSRiver Riddle #include "mlir/TableGen/Interfaces.h"
1083a635c0SRiver Riddle #include "llvm/ADT/FunctionExtras.h"
112e2cdd0aSRiver Riddle #include "llvm/ADT/StringExtras.h"
12d5c2204cSAndrew Lenharth #include "llvm/ADT/StringSet.h"
132e2cdd0aSRiver Riddle #include "llvm/Support/FormatVariadic.h"
142e2cdd0aSRiver Riddle #include "llvm/TableGen/Error.h"
152e2cdd0aSRiver Riddle #include "llvm/TableGen/Record.h"
162e2cdd0aSRiver Riddle 
172e2cdd0aSRiver Riddle using namespace mlir;
182e2cdd0aSRiver Riddle using namespace mlir::tblgen;
19*659192b1SRahul Joshi using llvm::DagInit;
20*659192b1SRahul Joshi using llvm::DefInit;
21*659192b1SRahul Joshi using llvm::Init;
22*659192b1SRahul Joshi using llvm::ListInit;
23*659192b1SRahul Joshi using llvm::Record;
24*659192b1SRahul Joshi using llvm::StringInit;
252e2cdd0aSRiver Riddle 
262e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
272e2cdd0aSRiver Riddle // InterfaceMethod
282e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
292e2cdd0aSRiver Riddle 
30*659192b1SRahul Joshi InterfaceMethod::InterfaceMethod(const Record *def) : def(def) {
31*659192b1SRahul Joshi   const DagInit *args = def->getValueAsDag("arguments");
322e2cdd0aSRiver Riddle   for (unsigned i = 0, e = args->getNumArgs(); i != e; ++i) {
33*659192b1SRahul Joshi     arguments.push_back({cast<StringInit>(args->getArg(i))->getValue(),
342e2cdd0aSRiver Riddle                          args->getArgNameStr(i)});
352e2cdd0aSRiver Riddle   }
362e2cdd0aSRiver Riddle }
372e2cdd0aSRiver Riddle 
382e2cdd0aSRiver Riddle StringRef InterfaceMethod::getReturnType() const {
392e2cdd0aSRiver Riddle   return def->getValueAsString("returnType");
402e2cdd0aSRiver Riddle }
412e2cdd0aSRiver Riddle 
422e2cdd0aSRiver Riddle // Return the name of this method.
432e2cdd0aSRiver Riddle StringRef InterfaceMethod::getName() const {
442e2cdd0aSRiver Riddle   return def->getValueAsString("name");
452e2cdd0aSRiver Riddle }
462e2cdd0aSRiver Riddle 
472e2cdd0aSRiver Riddle // Return if this method is static.
482e2cdd0aSRiver Riddle bool InterfaceMethod::isStatic() const {
492e2cdd0aSRiver Riddle   return def->isSubClassOf("StaticInterfaceMethod");
502e2cdd0aSRiver Riddle }
512e2cdd0aSRiver Riddle 
522e2cdd0aSRiver Riddle // Return the body for this method if it has one.
533cfe412eSFangrui Song std::optional<StringRef> InterfaceMethod::getBody() const {
542e2cdd0aSRiver Riddle   auto value = def->getValueAsString("body");
553cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
562e2cdd0aSRiver Riddle }
572e2cdd0aSRiver Riddle 
582e2cdd0aSRiver Riddle // Return the default implementation for this method if it has one.
593cfe412eSFangrui Song std::optional<StringRef> InterfaceMethod::getDefaultImplementation() const {
602e2cdd0aSRiver Riddle   auto value = def->getValueAsString("defaultBody");
613cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
622e2cdd0aSRiver Riddle }
632e2cdd0aSRiver Riddle 
642e2cdd0aSRiver Riddle // Return the description of this method if it has one.
653cfe412eSFangrui Song std::optional<StringRef> InterfaceMethod::getDescription() const {
662e2cdd0aSRiver Riddle   auto value = def->getValueAsString("description");
673cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
682e2cdd0aSRiver Riddle }
692e2cdd0aSRiver Riddle 
702e2cdd0aSRiver Riddle ArrayRef<InterfaceMethod::Argument> InterfaceMethod::getArguments() const {
712e2cdd0aSRiver Riddle   return arguments;
722e2cdd0aSRiver Riddle }
732e2cdd0aSRiver Riddle 
742e2cdd0aSRiver Riddle bool InterfaceMethod::arg_empty() const { return arguments.empty(); }
752e2cdd0aSRiver Riddle 
762e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
772e2cdd0aSRiver Riddle // Interface
782e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
792e2cdd0aSRiver Riddle 
80*659192b1SRahul Joshi Interface::Interface(const Record *def) : def(def) {
812e2cdd0aSRiver Riddle   assert(def->isSubClassOf("Interface") &&
822e2cdd0aSRiver Riddle          "must be subclass of TableGen 'Interface' class");
832e2cdd0aSRiver Riddle 
8483a635c0SRiver Riddle   // Initialize the interface methods.
85*659192b1SRahul Joshi   auto *listInit = dyn_cast<ListInit>(def->getValueInit("methods"));
86*659192b1SRahul Joshi   for (const Init *init : listInit->getValues())
87*659192b1SRahul Joshi     methods.emplace_back(cast<DefInit>(init)->getDef());
8883a635c0SRiver Riddle 
8983a635c0SRiver Riddle   // Initialize the interface base classes.
90*659192b1SRahul Joshi   auto *basesInit = dyn_cast<ListInit>(def->getValueInit("baseInterfaces"));
91d5c2204cSAndrew Lenharth   // Chained inheritance will produce duplicates in the base interface set.
92d5c2204cSAndrew Lenharth   StringSet<> basesAdded;
9383a635c0SRiver Riddle   llvm::unique_function<void(Interface)> addBaseInterfaceFn =
9483a635c0SRiver Riddle       [&](const Interface &baseInterface) {
9583a635c0SRiver Riddle         // Inherit any base interfaces.
9683a635c0SRiver Riddle         for (const auto &baseBaseInterface : baseInterface.getBaseInterfaces())
9783a635c0SRiver Riddle           addBaseInterfaceFn(baseBaseInterface);
9883a635c0SRiver Riddle 
9983a635c0SRiver Riddle         // Add the base interface.
100d5c2204cSAndrew Lenharth         if (basesAdded.contains(baseInterface.getName()))
101d5c2204cSAndrew Lenharth           return;
10283a635c0SRiver Riddle         baseInterfaces.push_back(std::make_unique<Interface>(baseInterface));
103d5c2204cSAndrew Lenharth         basesAdded.insert(baseInterface.getName());
10483a635c0SRiver Riddle       };
105*659192b1SRahul Joshi   for (const Init *init : basesInit->getValues())
106*659192b1SRahul Joshi     addBaseInterfaceFn(Interface(cast<DefInit>(init)->getDef()));
1072e2cdd0aSRiver Riddle }
1082e2cdd0aSRiver Riddle 
1092e2cdd0aSRiver Riddle // Return the name of this interface.
1102e2cdd0aSRiver Riddle StringRef Interface::getName() const {
1119f186bb1SMarkus Böck   return def->getValueAsString("cppInterfaceName");
1122e2cdd0aSRiver Riddle }
1132e2cdd0aSRiver Riddle 
11483a635c0SRiver Riddle // Returns this interface's name prefixed with namespaces.
11583a635c0SRiver Riddle std::string Interface::getFullyQualifiedName() const {
11683a635c0SRiver Riddle   StringRef cppNamespace = getCppNamespace();
11783a635c0SRiver Riddle   StringRef name = getName();
11883a635c0SRiver Riddle   if (cppNamespace.empty())
11983a635c0SRiver Riddle     return name.str();
12083a635c0SRiver Riddle   return (cppNamespace + "::" + name).str();
12183a635c0SRiver Riddle }
12283a635c0SRiver Riddle 
123572c2905SRiver Riddle // Return the C++ namespace of this interface.
124572c2905SRiver Riddle StringRef Interface::getCppNamespace() const {
125572c2905SRiver Riddle   return def->getValueAsString("cppNamespace");
126572c2905SRiver Riddle }
127572c2905SRiver Riddle 
1282e2cdd0aSRiver Riddle // Return the methods of this interface.
1292e2cdd0aSRiver Riddle ArrayRef<InterfaceMethod> Interface::getMethods() const { return methods; }
1302e2cdd0aSRiver Riddle 
1312e2cdd0aSRiver Riddle // Return the description of this method if it has one.
1323cfe412eSFangrui Song std::optional<StringRef> Interface::getDescription() const {
1332e2cdd0aSRiver Riddle   auto value = def->getValueAsString("description");
1343cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
1352e2cdd0aSRiver Riddle }
1362e2cdd0aSRiver Riddle 
1372e2cdd0aSRiver Riddle // Return the interfaces extra class declaration code.
1383cfe412eSFangrui Song std::optional<StringRef> Interface::getExtraClassDeclaration() const {
1392e2cdd0aSRiver Riddle   auto value = def->getValueAsString("extraClassDeclaration");
1403cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
1412e2cdd0aSRiver Riddle }
1422e2cdd0aSRiver Riddle 
1432e2cdd0aSRiver Riddle // Return the traits extra class declaration code.
1443cfe412eSFangrui Song std::optional<StringRef> Interface::getExtraTraitClassDeclaration() const {
1452e2cdd0aSRiver Riddle   auto value = def->getValueAsString("extraTraitClassDeclaration");
1463cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
1472e2cdd0aSRiver Riddle }
1482e2cdd0aSRiver Riddle 
149a60e83feSRiver Riddle // Return the shared extra class declaration code.
1503cfe412eSFangrui Song std::optional<StringRef> Interface::getExtraSharedClassDeclaration() const {
151a60e83feSRiver Riddle   auto value = def->getValueAsString("extraSharedClassDeclaration");
1523cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
153a60e83feSRiver Riddle }
154a60e83feSRiver Riddle 
1555cdc2bbcSRiver Riddle std::optional<StringRef> Interface::getExtraClassOf() const {
1565cdc2bbcSRiver Riddle   auto value = def->getValueAsString("extraClassOf");
1575cdc2bbcSRiver Riddle   return value.empty() ? std::optional<StringRef>() : value;
1585cdc2bbcSRiver Riddle }
1595cdc2bbcSRiver Riddle 
1602e2cdd0aSRiver Riddle // Return the body for this method if it has one.
1613cfe412eSFangrui Song std::optional<StringRef> Interface::getVerify() const {
1622e2cdd0aSRiver Riddle   // Only OpInterface supports the verify method.
1632e2cdd0aSRiver Riddle   if (!isa<OpInterface>(this))
1641a36588eSKazu Hirata     return std::nullopt;
1652e2cdd0aSRiver Riddle   auto value = def->getValueAsString("verify");
1663cfe412eSFangrui Song   return value.empty() ? std::optional<StringRef>() : value;
1672e2cdd0aSRiver Riddle }
1682e2cdd0aSRiver Riddle 
1699445b396SChia-hung Duan bool Interface::verifyWithRegions() const {
1709445b396SChia-hung Duan   return def->getValueAsBit("verifyWithRegions");
1719445b396SChia-hung Duan }
1729445b396SChia-hung Duan 
1732e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1742e2cdd0aSRiver Riddle // AttrInterface
1752e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1762e2cdd0aSRiver Riddle 
1772e2cdd0aSRiver Riddle bool AttrInterface::classof(const Interface *interface) {
1782e2cdd0aSRiver Riddle   return interface->getDef().isSubClassOf("AttrInterface");
1792e2cdd0aSRiver Riddle }
1802e2cdd0aSRiver Riddle 
1812e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1822e2cdd0aSRiver Riddle // OpInterface
1832e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1842e2cdd0aSRiver Riddle 
1852e2cdd0aSRiver Riddle bool OpInterface::classof(const Interface *interface) {
1862e2cdd0aSRiver Riddle   return interface->getDef().isSubClassOf("OpInterface");
1872e2cdd0aSRiver Riddle }
1882e2cdd0aSRiver Riddle 
1892e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1902e2cdd0aSRiver Riddle // TypeInterface
1912e2cdd0aSRiver Riddle //===----------------------------------------------------------------------===//
1922e2cdd0aSRiver Riddle 
1932e2cdd0aSRiver Riddle bool TypeInterface::classof(const Interface *interface) {
1942e2cdd0aSRiver Riddle   return interface->getDef().isSubClassOf("TypeInterface");
1952e2cdd0aSRiver Riddle }
196