Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / utils / TableGen / ClangOpcodesEmitter.cpp
blobdb88c990d5f9bda411d7561f032252b992fe6f05
1 //=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===//
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 // These tablegen backends emit Clang AST node tables
11 //===----------------------------------------------------------------------===//
13 #include "TableGenBackends.h"
14 #include "llvm/TableGen/Error.h"
15 #include "llvm/TableGen/Record.h"
16 #include "llvm/TableGen/StringMatcher.h"
17 #include "llvm/TableGen/TableGenBackend.h"
19 using namespace llvm;
21 namespace {
22 class ClangOpcodesEmitter {
23 RecordKeeper &Records;
24 const Record Root;
25 unsigned NumTypes;
27 public:
28 ClangOpcodesEmitter(RecordKeeper &R)
29 : Records(R), Root("Opcode", SMLoc(), R),
30 NumTypes(Records.getAllDerivedDefinitions("Type").size()) {}
32 void run(raw_ostream &OS);
34 private:
35 /// Emits the opcode name for the opcode enum.
36 /// The name is obtained by concatenating the name with the list of types.
37 void EmitEnum(raw_ostream &OS, StringRef N, const Record *R);
39 /// Emits the switch case and the invocation in the interpreter.
40 void EmitInterp(raw_ostream &OS, StringRef N, const Record *R);
42 /// Emits the disassembler.
43 void EmitDisasm(raw_ostream &OS, StringRef N, const Record *R);
45 /// Emits the byte code emitter method.
46 void EmitEmitter(raw_ostream &OS, StringRef N, const Record *R);
48 /// Emits the prototype.
49 void EmitProto(raw_ostream &OS, StringRef N, const Record *R);
51 /// Emits the prototype to dispatch from a type.
52 void EmitGroup(raw_ostream &OS, StringRef N, const Record *R);
54 /// Emits the evaluator method.
55 void EmitEval(raw_ostream &OS, StringRef N, const Record *R);
57 void PrintTypes(raw_ostream &OS, ArrayRef<const Record *> Types);
60 void Enumerate(const Record *R, StringRef N,
61 std::function<void(ArrayRef<const Record *>, Twine)> &&F) {
62 llvm::SmallVector<const Record *, 2> TypePath;
63 auto *Types = R->getValueAsListInit("Types");
65 std::function<void(size_t, const Twine &)> Rec;
66 Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) {
67 if (I >= Types->size()) {
68 F(TypePath, ID);
69 return;
72 if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
73 for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) {
74 TypePath.push_back(Type);
75 Rec(I + 1, ID + Type->getName());
76 TypePath.pop_back();
78 } else {
79 PrintFatalError("Expected a type class");
82 Rec(0, N);
85 } // namespace
87 void ClangOpcodesEmitter::run(raw_ostream &OS) {
88 for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) {
89 // The name is the record name, unless overriden.
90 StringRef N = Opcode->getValueAsString("Name");
91 if (N.empty())
92 N = Opcode->getName();
94 EmitEnum(OS, N, Opcode);
95 EmitInterp(OS, N, Opcode);
96 EmitDisasm(OS, N, Opcode);
97 EmitProto(OS, N, Opcode);
98 EmitGroup(OS, N, Opcode);
99 EmitEmitter(OS, N, Opcode);
100 EmitEval(OS, N, Opcode);
104 void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N,
105 const Record *R) {
106 OS << "#ifdef GET_OPCODE_NAMES\n";
107 Enumerate(R, N, [&OS](ArrayRef<const Record *>, const Twine &ID) {
108 OS << "OP_" << ID << ",\n";
110 OS << "#endif\n";
113 void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N,
114 const Record *R) {
115 OS << "#ifdef GET_INTERP\n";
117 Enumerate(R, N,
118 [this, R, &OS, &N](ArrayRef<const Record *> TS, const Twine &ID) {
119 bool CanReturn = R->getValueAsBit("CanReturn");
120 bool ChangesPC = R->getValueAsBit("ChangesPC");
121 auto Args = R->getValueAsListOfDefs("Args");
123 OS << "case OP_" << ID << ": {\n";
125 if (CanReturn)
126 OS << " bool DoReturn = (S.Current == StartFrame);\n";
128 // Emit calls to read arguments.
129 for (size_t I = 0, N = Args.size(); I < N; ++I) {
130 OS << " auto V" << I;
131 OS << " = ";
132 OS << "ReadArg<" << Args[I]->getValueAsString("Name")
133 << ">(S, PC);\n";
136 // Emit a call to the template method and pass arguments.
137 OS << " if (!" << N;
138 PrintTypes(OS, TS);
139 OS << "(S";
140 if (ChangesPC)
141 OS << ", PC";
142 else
143 OS << ", OpPC";
144 if (CanReturn)
145 OS << ", Result";
146 for (size_t I = 0, N = Args.size(); I < N; ++I)
147 OS << ", V" << I;
148 OS << "))\n";
149 OS << " return false;\n";
151 // Bail out if interpreter returned.
152 if (CanReturn) {
153 OS << " if (!S.Current || S.Current->isRoot())\n";
154 OS << " return true;\n";
156 OS << " if (DoReturn)\n";
157 OS << " return true;\n";
160 OS << " continue;\n";
161 OS << "}\n";
163 OS << "#endif\n";
166 void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N,
167 const Record *R) {
168 OS << "#ifdef GET_DISASM\n";
169 Enumerate(R, N, [R, &OS](ArrayRef<const Record *>, const Twine &ID) {
170 OS << "case OP_" << ID << ":\n";
171 OS << " PrintName(\"" << ID << "\");\n";
172 OS << " OS << \"\\t\"";
174 for (auto *Arg : R->getValueAsListOfDefs("Args")) {
175 OS << " << ReadArg<" << Arg->getValueAsString("Name") << ">(P, PC)";
176 OS << " << \" \"";
179 OS << " << \"\\n\";\n";
180 OS << " continue;\n";
182 OS << "#endif\n";
185 void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N,
186 const Record *R) {
187 if (R->getValueAsBit("HasCustomLink"))
188 return;
190 OS << "#ifdef GET_LINK_IMPL\n";
191 Enumerate(R, N, [R, &OS](ArrayRef<const Record *>, const Twine &ID) {
192 auto Args = R->getValueAsListOfDefs("Args");
194 // Emit the list of arguments.
195 OS << "bool ByteCodeEmitter::emit" << ID << "(";
196 for (size_t I = 0, N = Args.size(); I < N; ++I)
197 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
198 OS << "const SourceInfo &L) {\n";
200 // Emit a call to write the opcodes.
201 OS << " return emitOp<";
202 for (size_t I = 0, N = Args.size(); I < N; ++I) {
203 if (I != 0)
204 OS << ", ";
205 OS << Args[I]->getValueAsString("Name");
207 OS << ">(OP_" << ID;
208 for (size_t I = 0, N = Args.size(); I < N; ++I)
209 OS << ", A" << I;
210 OS << ", L);\n";
211 OS << "}\n";
213 OS << "#endif\n";
216 void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N,
217 const Record *R) {
218 OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
219 auto Args = R->getValueAsListOfDefs("Args");
220 Enumerate(R, N, [&OS, &Args](ArrayRef<const Record *> TS, const Twine &ID) {
221 OS << "bool emit" << ID << "(";
222 for (auto *Arg : Args)
223 OS << Arg->getValueAsString("Name") << ", ";
224 OS << "const SourceInfo &);\n";
227 // Emit a template method for custom emitters to have less to implement.
228 auto TypeCount = R->getValueAsListInit("Types")->size();
229 if (R->getValueAsBit("HasCustomEval") && TypeCount) {
230 OS << "#if defined(GET_EVAL_PROTO)\n";
231 OS << "template<";
232 for (size_t I = 0; I < TypeCount; ++I) {
233 if (I != 0)
234 OS << ", ";
235 OS << "PrimType";
237 OS << ">\n";
238 OS << "bool emit" << N << "(";
239 for (auto *Arg : Args)
240 OS << Arg->getValueAsString("Name") << ", ";
241 OS << "const SourceInfo &);\n";
242 OS << "#endif\n";
245 OS << "#endif\n";
248 void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N,
249 const Record *R) {
250 if (!R->getValueAsBit("HasGroup"))
251 return;
253 auto *Types = R->getValueAsListInit("Types");
254 auto Args = R->getValueAsListOfDefs("Args");
256 Twine EmitFuncName = "emit" + N;
258 // Emit the prototype of the group emitter in the header.
259 OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
260 OS << "bool " << EmitFuncName << "(";
261 for (size_t I = 0, N = Types->size(); I < N; ++I)
262 OS << "PrimType, ";
263 for (auto *Arg : Args)
264 OS << Arg->getValueAsString("Name") << ", ";
265 OS << "const SourceInfo &I);\n";
266 OS << "#endif\n";
268 // Emit the dispatch implementation in the source.
269 OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
270 OS << "bool\n";
271 OS << "#if defined(GET_EVAL_IMPL)\n";
272 OS << "EvalEmitter\n";
273 OS << "#else\n";
274 OS << "ByteCodeEmitter\n";
275 OS << "#endif\n";
276 OS << "::" << EmitFuncName << "(";
277 for (size_t I = 0, N = Types->size(); I < N; ++I)
278 OS << "PrimType T" << I << ", ";
279 for (size_t I = 0, N = Args.size(); I < N; ++I)
280 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
281 OS << "const SourceInfo &I) {\n";
283 std::function<void(size_t, const Twine &)> Rec;
284 llvm::SmallVector<const Record *, 2> TS;
285 Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N,
286 EmitFuncName](size_t I, const Twine &ID) {
287 if (I >= Types->size()) {
288 // Print a call to the emitter method.
289 // Custom evaluator methods dispatch to template methods.
290 if (R->getValueAsBit("HasCustomEval")) {
291 OS << "#ifdef GET_LINK_IMPL\n";
292 OS << " return emit" << ID << "\n";
293 OS << "#else\n";
294 OS << " return emit" << N;
295 PrintTypes(OS, TS);
296 OS << "\n#endif\n";
297 OS << " ";
298 } else {
299 OS << " return emit" << ID;
302 OS << "(";
303 for (size_t I = 0; I < Args.size(); ++I) {
304 OS << "A" << I << ", ";
306 OS << "I);\n";
307 return;
310 // Print a switch statement selecting T.
311 if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
312 OS << " switch (T" << I << ") {\n";
313 auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
314 for (auto *Case : Cases) {
315 OS << " case PT_" << Case->getName() << ":\n";
316 TS.push_back(Case);
317 Rec(I + 1, ID + Case->getName());
318 TS.pop_back();
320 // Emit a default case if not all types are present.
321 if (Cases.size() < NumTypes)
322 OS << " default: llvm_unreachable(\"invalid type: " << EmitFuncName
323 << "\");\n";
324 OS << " }\n";
325 OS << " llvm_unreachable(\"invalid enum value\");\n";
326 } else {
327 PrintFatalError("Expected a type class");
330 Rec(0, N);
332 OS << "}\n";
333 OS << "#endif\n";
336 void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N,
337 const Record *R) {
338 if (R->getValueAsBit("HasCustomEval"))
339 return;
341 OS << "#ifdef GET_EVAL_IMPL\n";
342 Enumerate(R, N,
343 [this, R, &N, &OS](ArrayRef<const Record *> TS, const Twine &ID) {
344 auto Args = R->getValueAsListOfDefs("Args");
346 OS << "bool EvalEmitter::emit" << ID << "(";
347 for (size_t I = 0, N = Args.size(); I < N; ++I)
348 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
349 OS << "const SourceInfo &L) {\n";
350 OS << " if (!isActive()) return true;\n";
351 OS << " CurrentSource = L;\n";
353 OS << " return " << N;
354 PrintTypes(OS, TS);
355 OS << "(S, OpPC";
356 for (size_t I = 0, N = Args.size(); I < N; ++I)
357 OS << ", A" << I;
358 OS << ");\n";
359 OS << "}\n";
362 OS << "#endif\n";
365 void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS,
366 ArrayRef<const Record *> Types) {
367 if (Types.empty())
368 return;
369 OS << "<";
370 for (size_t I = 0, N = Types.size(); I < N; ++I) {
371 if (I != 0)
372 OS << ", ";
373 OS << "PT_" << Types[I]->getName();
375 OS << ">";
378 void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
379 ClangOpcodesEmitter(Records).run(OS);