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 | |
17 | using namespace mlir; |
18 | using namespace mlir::tblgen; |
19 | |
20 | //===----------------------------------------------------------------------===// |
21 | // InterfaceMethod |
22 | //===----------------------------------------------------------------------===// |
23 | |
24 | InterfaceMethod::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 | |
33 | StringRef InterfaceMethod::getReturnType() const { |
34 | return def->getValueAsString(FieldName: "returnType"); |
35 | } |
36 | |
37 | // Return the name of this method. |
38 | StringRef InterfaceMethod::getName() const { |
39 | return def->getValueAsString(FieldName: "name"); |
40 | } |
41 | |
42 | // Return if this method is static. |
43 | bool InterfaceMethod::isStatic() const { |
44 | return def->isSubClassOf(Name: "StaticInterfaceMethod"); |
45 | } |
46 | |
47 | // Return the body for this method if it has one. |
48 | std::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. |
54 | std::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. |
60 | std::optional<StringRef> InterfaceMethod::getDescription() const { |
61 | auto value = def->getValueAsString(FieldName: "description"); |
62 | return value.empty() ? std::optional<StringRef>() : value; |
63 | } |
64 | |
65 | ArrayRef<InterfaceMethod::Argument> InterfaceMethod::getArguments() const { |
66 | return arguments; |
67 | } |
68 | |
69 | bool InterfaceMethod::arg_empty() const { return arguments.empty(); } |
70 | |
71 | //===----------------------------------------------------------------------===// |
72 | // Interface |
73 | //===----------------------------------------------------------------------===// |
74 | |
75 | Interface::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. |
106 | StringRef Interface::getName() const { |
107 | return def->getValueAsString(FieldName: "cppInterfaceName"); |
108 | } |
109 | |
110 | // Returns this interface's name prefixed with namespaces. |
111 | std::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. |
120 | StringRef Interface::getCppNamespace() const { |
121 | return def->getValueAsString(FieldName: "cppNamespace"); |
122 | } |
123 | |
124 | // Return the methods of this interface. |
125 | ArrayRef<InterfaceMethod> Interface::getMethods() const { return methods; } |
126 | |
127 | // Return the description of this method if it has one. |
128 | std::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. |
134 | std::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. |
140 | std::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. |
146 | std::optional<StringRef> Interface::getExtraSharedClassDeclaration() const { |
147 | auto value = def->getValueAsString(FieldName: "extraSharedClassDeclaration"); |
148 | return value.empty() ? std::optional<StringRef>() : value; |
149 | } |
150 | |
151 | std::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. |
157 | std::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 | |
165 | bool Interface::verifyWithRegions() const { |
166 | return def->getValueAsBit(FieldName: "verifyWithRegions"); |
167 | } |
168 | |
169 | //===----------------------------------------------------------------------===// |
170 | // AttrInterface |
171 | //===----------------------------------------------------------------------===// |
172 | |
173 | bool AttrInterface::classof(const Interface *interface) { |
174 | return interface->getDef().isSubClassOf(Name: "AttrInterface"); |
175 | } |
176 | |
177 | //===----------------------------------------------------------------------===// |
178 | // OpInterface |
179 | //===----------------------------------------------------------------------===// |
180 | |
181 | bool OpInterface::classof(const Interface *interface) { |
182 | return interface->getDef().isSubClassOf(Name: "OpInterface"); |
183 | } |
184 | |
185 | //===----------------------------------------------------------------------===// |
186 | // TypeInterface |
187 | //===----------------------------------------------------------------------===// |
188 | |
189 | bool TypeInterface::classof(const Interface *interface) { |
190 | return interface->getDef().isSubClassOf(Name: "TypeInterface"); |
191 | } |
192 |