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