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