211 lines · cpp
1//===- Interfaces.cpp - Interface classes ---------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/TableGen/Interfaces.h"10#include "llvm/ADT/FunctionExtras.h"11#include "llvm/ADT/StringSet.h"12#include "llvm/TableGen/Error.h"13#include "llvm/TableGen/Record.h"14 15using namespace mlir;16using namespace mlir::tblgen;17using llvm::DagInit;18using llvm::DefInit;19using llvm::Init;20using llvm::ListInit;21using llvm::Record;22using llvm::StringInit;23 24//===----------------------------------------------------------------------===//25// InterfaceMethod26//===----------------------------------------------------------------------===//27 28InterfaceMethod::InterfaceMethod(const Record *def, std::string uniqueName)29 : def(def), uniqueName(uniqueName) {30 const DagInit *args = def->getValueAsDag("arguments");31 for (unsigned i = 0, e = args->getNumArgs(); i != e; ++i) {32 arguments.push_back({cast<StringInit>(args->getArg(i))->getValue(),33 args->getArgNameStr(i)});34 }35}36 37StringRef InterfaceMethod::getReturnType() const {38 return def->getValueAsString("returnType");39}40 41// Return the name of this method.42StringRef InterfaceMethod::getName() const {43 return def->getValueAsString("name");44}45 46// Return the name of this method.47StringRef InterfaceMethod::getUniqueName() const { return uniqueName; }48 49// Return if this method is static.50bool InterfaceMethod::isStatic() const {51 return def->isSubClassOf("StaticInterfaceMethod");52}53 54// Return the body for this method if it has one.55std::optional<StringRef> InterfaceMethod::getBody() const {56 // Trim leading and trailing spaces from the default implementation.57 auto value = def->getValueAsString("body").trim();58 return value.empty() ? std::optional<StringRef>() : value;59}60 61// Return the default implementation for this method if it has one.62std::optional<StringRef> InterfaceMethod::getDefaultImplementation() const {63 // Trim leading and trailing spaces from the default implementation.64 auto value = def->getValueAsString("defaultBody").trim();65 return value.empty() ? std::optional<StringRef>() : value;66}67 68// Return the description of this method if it has one.69std::optional<StringRef> InterfaceMethod::getDescription() const {70 auto value = def->getValueAsString("description");71 return value.empty() ? std::optional<StringRef>() : value;72}73 74ArrayRef<InterfaceMethod::Argument> InterfaceMethod::getArguments() const {75 return arguments;76}77 78bool InterfaceMethod::arg_empty() const { return arguments.empty(); }79 80//===----------------------------------------------------------------------===//81// Interface82//===----------------------------------------------------------------------===//83 84Interface::Interface(const Record *def) : def(def) {85 assert(def->isSubClassOf("Interface") &&86 "must be subclass of TableGen 'Interface' class");87 88 // Initialize the interface methods.89 auto *listInit = dyn_cast<ListInit>(def->getValueInit("methods"));90 // In case of overloaded methods, we need to find a unique name for each for91 // the internal function pointer in the "vtable" we generate. This is an92 // internal name, we could use a randomly generated name as long as there are93 // no collisions.94 StringSet<> uniqueNames;95 for (const Init *init : listInit->getElements()) {96 std::string name =97 cast<DefInit>(init)->getDef()->getValueAsString("name").str();98 while (!uniqueNames.insert(name).second) {99 name = name + "_" + std::to_string(uniqueNames.size());100 }101 methods.emplace_back(cast<DefInit>(init)->getDef(), name);102 }103 104 // Initialize the interface base classes.105 auto *basesInit = dyn_cast<ListInit>(def->getValueInit("baseInterfaces"));106 // Chained inheritance will produce duplicates in the base interface set.107 StringSet<> basesAdded;108 llvm::unique_function<void(Interface)> addBaseInterfaceFn =109 [&](const Interface &baseInterface) {110 // Inherit any base interfaces.111 for (const auto &baseBaseInterface : baseInterface.getBaseInterfaces())112 addBaseInterfaceFn(baseBaseInterface);113 114 // Add the base interface.115 if (basesAdded.contains(baseInterface.getName()))116 return;117 baseInterfaces.push_back(std::make_unique<Interface>(baseInterface));118 basesAdded.insert(baseInterface.getName());119 };120 for (const Init *init : basesInit->getElements())121 addBaseInterfaceFn(Interface(cast<DefInit>(init)->getDef()));122}123 124// Return the name of this interface.125StringRef Interface::getName() const {126 return def->getValueAsString("cppInterfaceName");127}128 129// Returns this interface's name prefixed with namespaces.130std::string Interface::getFullyQualifiedName() const {131 StringRef cppNamespace = getCppNamespace();132 StringRef name = getName();133 if (cppNamespace.empty())134 return name.str();135 return (cppNamespace + "::" + name).str();136}137 138// Return the C++ namespace of this interface.139StringRef Interface::getCppNamespace() const {140 return def->getValueAsString("cppNamespace");141}142 143// Return the methods of this interface.144ArrayRef<InterfaceMethod> Interface::getMethods() const { return methods; }145 146// Return the description of this method if it has one.147std::optional<StringRef> Interface::getDescription() const {148 auto value = def->getValueAsString("description");149 return value.empty() ? std::optional<StringRef>() : value;150}151 152// Return the interfaces extra class declaration code.153std::optional<StringRef> Interface::getExtraClassDeclaration() const {154 auto value = def->getValueAsString("extraClassDeclaration");155 return value.empty() ? std::optional<StringRef>() : value;156}157 158// Return the traits extra class declaration code.159std::optional<StringRef> Interface::getExtraTraitClassDeclaration() const {160 auto value = def->getValueAsString("extraTraitClassDeclaration");161 return value.empty() ? std::optional<StringRef>() : value;162}163 164// Return the shared extra class declaration code.165std::optional<StringRef> Interface::getExtraSharedClassDeclaration() const {166 auto value = def->getValueAsString("extraSharedClassDeclaration");167 return value.empty() ? std::optional<StringRef>() : value;168}169 170std::optional<StringRef> Interface::getExtraClassOf() const {171 auto value = def->getValueAsString("extraClassOf");172 return value.empty() ? std::optional<StringRef>() : value;173}174 175// Return the body for this method if it has one.176std::optional<StringRef> Interface::getVerify() const {177 // Only OpInterface supports the verify method.178 if (!isa<OpInterface>(this))179 return std::nullopt;180 auto value = def->getValueAsString("verify");181 return value.empty() ? std::optional<StringRef>() : value;182}183 184bool Interface::verifyWithRegions() const {185 return def->getValueAsBit("verifyWithRegions");186}187 188//===----------------------------------------------------------------------===//189// AttrInterface190//===----------------------------------------------------------------------===//191 192bool AttrInterface::classof(const Interface *interface) {193 return interface->getDef().isSubClassOf("AttrInterface");194}195 196//===----------------------------------------------------------------------===//197// OpInterface198//===----------------------------------------------------------------------===//199 200bool OpInterface::classof(const Interface *interface) {201 return interface->getDef().isSubClassOf("OpInterface");202}203 204//===----------------------------------------------------------------------===//205// TypeInterface206//===----------------------------------------------------------------------===//207 208bool TypeInterface::classof(const Interface *interface) {209 return interface->getDef().isSubClassOf("TypeInterface");210}211