MLIR  22.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 
15 using namespace mlir;
16 using namespace mlir::tblgen;
17 using llvm::DagInit;
18 using llvm::DefInit;
19 using llvm::Init;
20 using llvm::ListInit;
21 using llvm::Record;
22 using llvm::StringInit;
23 
24 //===----------------------------------------------------------------------===//
25 // InterfaceMethod
26 //===----------------------------------------------------------------------===//
27 
28 InterfaceMethod::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 
37 StringRef InterfaceMethod::getReturnType() const {
38  return def->getValueAsString("returnType");
39 }
40 
41 // Return the name of this method.
42 StringRef InterfaceMethod::getName() const {
43  return def->getValueAsString("name");
44 }
45 
46 // Return the name of this method.
47 StringRef InterfaceMethod::getUniqueName() const { return uniqueName; }
48 
49 // Return if this method is static.
51  return def->isSubClassOf("StaticInterfaceMethod");
52 }
53 
54 // Return the body for this method if it has one.
55 std::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.
62 std::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.
69 std::optional<StringRef> InterfaceMethod::getDescription() const {
70  auto value = def->getValueAsString("description");
71  return value.empty() ? std::optional<StringRef>() : value;
72 }
73 
75  return arguments;
76 }
77 
78 bool InterfaceMethod::arg_empty() const { return arguments.empty(); }
79 
80 //===----------------------------------------------------------------------===//
81 // Interface
82 //===----------------------------------------------------------------------===//
83 
84 Interface::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 for
91  // the internal function pointer in the "vtable" we generate. This is an
92  // internal name, we could use a randomly generated name as long as there are
93  // 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.
125 StringRef Interface::getName() const {
126  return def->getValueAsString("cppInterfaceName");
127 }
128 
129 // Returns this interface's name prefixed with namespaces.
130 std::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.
139 StringRef Interface::getCppNamespace() const {
140  return def->getValueAsString("cppNamespace");
141 }
142 
143 // Return the methods of this interface.
145 
146 // Return the description of this method if it has one.
147 std::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.
153 std::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.
159 std::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.
165 std::optional<StringRef> Interface::getExtraSharedClassDeclaration() const {
166  auto value = def->getValueAsString("extraSharedClassDeclaration");
167  return value.empty() ? std::optional<StringRef>() : value;
168 }
169 
170 std::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.
176 std::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 
185  return def->getValueAsBit("verifyWithRegions");
186 }
187 
188 //===----------------------------------------------------------------------===//
189 // AttrInterface
190 //===----------------------------------------------------------------------===//
191 
192 bool AttrInterface::classof(const Interface *interface) {
193  return interface->getDef().isSubClassOf("AttrInterface");
194 }
195 
196 //===----------------------------------------------------------------------===//
197 // OpInterface
198 //===----------------------------------------------------------------------===//
199 
200 bool OpInterface::classof(const Interface *interface) {
201  return interface->getDef().isSubClassOf("OpInterface");
202 }
203 
204 //===----------------------------------------------------------------------===//
205 // TypeInterface
206 //===----------------------------------------------------------------------===//
207 
208 bool TypeInterface::classof(const Interface *interface) {
209  return interface->getDef().isSubClassOf("TypeInterface");
210 }
StringRef getReturnType() const
Definition: Interfaces.cpp:37
std::optional< StringRef > getDefaultImplementation() const
Definition: Interfaces.cpp:62
ArrayRef< Argument > getArguments() const
Definition: Interfaces.cpp:74
InterfaceMethod(const llvm::Record *def, std::string uniqueName)
Definition: Interfaces.cpp:28
std::optional< StringRef > getBody() const
Definition: Interfaces.cpp:55
StringRef getUniqueName() const
Definition: Interfaces.cpp:47
StringRef getName() const
Definition: Interfaces.cpp:42
std::optional< StringRef > getDescription() const
Definition: Interfaces.cpp:69
Interface(const llvm::Record *def)
std::optional< StringRef > getExtraClassOf() const
Definition: Interfaces.cpp:170
std::optional< StringRef > getDescription() const
Definition: Interfaces.cpp:147
std::optional< StringRef > getExtraClassDeclaration() const
Definition: Interfaces.cpp:153
std::optional< StringRef > getExtraSharedClassDeclaration() const
Definition: Interfaces.cpp:165
ArrayRef< InterfaceMethod > getMethods() const
Definition: Interfaces.cpp:144
std::optional< StringRef > getExtraTraitClassDeclaration() const
Definition: Interfaces.cpp:159
bool verifyWithRegions() const
Definition: Interfaces.cpp:184
std::optional< StringRef > getVerify() const
Definition: Interfaces.cpp:176
std::string getFullyQualifiedName() const
Definition: Interfaces.cpp:130
StringRef getCppNamespace() const
Definition: Interfaces.cpp:139
const llvm::Record & getDef() const
Definition: Interfaces.h:129
StringRef getName() const
Definition: Interfaces.cpp:125
Include the generated interface declarations.
static bool classof(const Interface *interface)
Definition: Interfaces.cpp:192
static bool classof(const Interface *interface)
Definition: Interfaces.cpp:200
static bool classof(const Interface *interface)
Definition: Interfaces.cpp:208