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