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

source code of mlir/lib/TableGen/Interfaces.cpp