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