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

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