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
10 //
11 //===----------------------------------------------------------------------===//
12
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"
18
19 using namespace llvm;
20
21 namespace {
22 class ClangOpcodesEmitter {
23 RecordKeeper &Records;
24 Record Root;
25 unsigned NumTypes;
26
27 public:
ClangOpcodesEmitter(RecordKeeper & R)28 ClangOpcodesEmitter(RecordKeeper &R)
29 : Records(R), Root("Opcode", SMLoc(), R),
30 NumTypes(Records.getAllDerivedDefinitions("Type").size()) {}
31
32 void run(raw_ostream &OS);
33
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, Record *R);
38
39 /// Emits the switch case and the invocation in the interpreter.
40 void EmitInterp(raw_ostream &OS, StringRef N, Record *R);
41
42 /// Emits the disassembler.
43 void EmitDisasm(raw_ostream &OS, StringRef N, Record *R);
44
45 /// Emits the byte code emitter method.
46 void EmitEmitter(raw_ostream &OS, StringRef N, Record *R);
47
48 /// Emits the prototype.
49 void EmitProto(raw_ostream &OS, StringRef N, Record *R);
50
51 /// Emits the prototype to dispatch from a type.
52 void EmitGroup(raw_ostream &OS, StringRef N, Record *R);
53
54 /// Emits the evaluator method.
55 void EmitEval(raw_ostream &OS, StringRef N, Record *R);
56
57 void PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types);
58 };
59
Enumerate(const Record * R,StringRef N,std::function<void (ArrayRef<Record * >,Twine)> && F)60 void Enumerate(const Record *R,
61 StringRef N,
62 std::function<void(ArrayRef<Record *>, Twine)> &&F) {
63 llvm::SmallVector<Record *, 2> TypePath;
64 auto *Types = R->getValueAsListInit("Types");
65
66 std::function<void(size_t, const Twine &)> Rec;
67 Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) {
68 if (I >= Types->size()) {
69 F(TypePath, ID);
70 return;
71 }
72
73 if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
74 for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) {
75 TypePath.push_back(Type);
76 Rec(I + 1, ID + Type->getName());
77 TypePath.pop_back();
78 }
79 } else {
80 PrintFatalError("Expected a type class");
81 }
82 };
83 Rec(0, N);
84 }
85
86 } // namespace
87
run(raw_ostream & OS)88 void ClangOpcodesEmitter::run(raw_ostream &OS) {
89 for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) {
90 // The name is the record name, unless overriden.
91 StringRef N = Opcode->getValueAsString("Name");
92 if (N.empty())
93 N = Opcode->getName();
94
95 EmitEnum(OS, N, Opcode);
96 EmitInterp(OS, N, Opcode);
97 EmitDisasm(OS, N, Opcode);
98 EmitProto(OS, N, Opcode);
99 EmitGroup(OS, N, Opcode);
100 EmitEmitter(OS, N, Opcode);
101 EmitEval(OS, N, Opcode);
102 }
103 }
104
EmitEnum(raw_ostream & OS,StringRef N,Record * R)105 void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, Record *R) {
106 OS << "#ifdef GET_OPCODE_NAMES\n";
107 Enumerate(R, N, [&OS](ArrayRef<Record *>, const Twine &ID) {
108 OS << "OP_" << ID << ",\n";
109 });
110 OS << "#endif\n";
111 }
112
EmitInterp(raw_ostream & OS,StringRef N,Record * R)113 void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, Record *R) {
114 OS << "#ifdef GET_INTERP\n";
115
116 Enumerate(R, N, [this, R, &OS, &N](ArrayRef<Record *> TS, const Twine &ID) {
117 bool CanReturn = R->getValueAsBit("CanReturn");
118 bool ChangesPC = R->getValueAsBit("ChangesPC");
119 auto Args = R->getValueAsListOfDefs("Args");
120
121 OS << "case OP_" << ID << ": {\n";
122
123 // Emit calls to read arguments.
124 for (size_t I = 0, N = Args.size(); I < N; ++I) {
125 OS << " auto V" << I;
126 OS << " = ";
127 OS << "ReadArg<" << Args[I]->getValueAsString("Name") << ">(S, PC);\n";
128 }
129
130 // Emit a call to the template method and pass arguments.
131 OS << " if (!" << N;
132 PrintTypes(OS, TS);
133 OS << "(S";
134 if (ChangesPC)
135 OS << ", PC";
136 else
137 OS << ", OpPC";
138 if (CanReturn)
139 OS << ", Result";
140 for (size_t I = 0, N = Args.size(); I < N; ++I)
141 OS << ", V" << I;
142 OS << "))\n";
143 OS << " return false;\n";
144
145 // Bail out if interpreter returned.
146 if (CanReturn) {
147 OS << " if (!S.Current || S.Current->isRoot())\n";
148 OS << " return true;\n";
149 }
150
151 OS << " continue;\n";
152 OS << "}\n";
153 });
154 OS << "#endif\n";
155 }
156
EmitDisasm(raw_ostream & OS,StringRef N,Record * R)157 void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record *R) {
158 OS << "#ifdef GET_DISASM\n";
159 Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
160 OS << "case OP_" << ID << ":\n";
161 OS << " PrintName(\"" << ID << "\");\n";
162 OS << " OS << \"\\t\"";
163
164 for (auto *Arg : R->getValueAsListOfDefs("Args")) {
165 OS << " << ReadArg<" << Arg->getValueAsString("Name") << ">(P, PC)";
166 OS << " << \" \"";
167 }
168
169 OS << " << \"\\n\";\n";
170 OS << " continue;\n";
171 });
172 OS << "#endif\n";
173 }
174
EmitEmitter(raw_ostream & OS,StringRef N,Record * R)175 void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record *R) {
176 if (R->getValueAsBit("HasCustomLink"))
177 return;
178
179 OS << "#ifdef GET_LINK_IMPL\n";
180 Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
181 auto Args = R->getValueAsListOfDefs("Args");
182
183 // Emit the list of arguments.
184 OS << "bool ByteCodeEmitter::emit" << ID << "(";
185 for (size_t I = 0, N = Args.size(); I < N; ++I)
186 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
187 OS << "const SourceInfo &L) {\n";
188
189 // Emit a call to write the opcodes.
190 OS << " return emitOp<";
191 for (size_t I = 0, N = Args.size(); I < N; ++I) {
192 if (I != 0)
193 OS << ", ";
194 OS << Args[I]->getValueAsString("Name");
195 }
196 OS << ">(OP_" << ID;
197 for (size_t I = 0, N = Args.size(); I < N; ++I)
198 OS << ", A" << I;
199 OS << ", L);\n";
200 OS << "}\n";
201 });
202 OS << "#endif\n";
203 }
204
EmitProto(raw_ostream & OS,StringRef N,Record * R)205 void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) {
206 OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
207 auto Args = R->getValueAsListOfDefs("Args");
208 Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) {
209 OS << "bool emit" << ID << "(";
210 for (auto *Arg : Args)
211 OS << Arg->getValueAsString("Name") << ", ";
212 OS << "const SourceInfo &);\n";
213 });
214
215 // Emit a template method for custom emitters to have less to implement.
216 auto TypeCount = R->getValueAsListInit("Types")->size();
217 if (R->getValueAsBit("HasCustomEval") && TypeCount) {
218 OS << "#if defined(GET_EVAL_PROTO)\n";
219 OS << "template<";
220 for (size_t I = 0; I < TypeCount; ++I) {
221 if (I != 0)
222 OS << ", ";
223 OS << "PrimType";
224 }
225 OS << ">\n";
226 OS << "bool emit" << N << "(";
227 for (auto *Arg : Args)
228 OS << Arg->getValueAsString("Name") << ", ";
229 OS << "const SourceInfo &);\n";
230 OS << "#endif\n";
231 }
232
233 OS << "#endif\n";
234 }
235
EmitGroup(raw_ostream & OS,StringRef N,Record * R)236 void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) {
237 if (!R->getValueAsBit("HasGroup"))
238 return;
239
240 auto *Types = R->getValueAsListInit("Types");
241 auto Args = R->getValueAsListOfDefs("Args");
242
243 // Emit the prototype of the group emitter in the header.
244 OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
245 OS << "bool emit" << N << "(";
246 for (size_t I = 0, N = Types->size(); I < N; ++I)
247 OS << "PrimType, ";
248 for (auto *Arg : Args)
249 OS << Arg->getValueAsString("Name") << ", ";
250 OS << "const SourceInfo &I);\n";
251 OS << "#endif\n";
252
253 // Emit the dispatch implementation in the source.
254 OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
255 OS << "bool\n";
256 OS << "#if defined(GET_EVAL_IMPL)\n";
257 OS << "EvalEmitter\n";
258 OS << "#else\n";
259 OS << "ByteCodeEmitter\n";
260 OS << "#endif\n";
261 OS << "::emit" << N << "(";
262 for (size_t I = 0, N = Types->size(); I < N; ++I)
263 OS << "PrimType T" << I << ", ";
264 for (size_t I = 0, N = Args.size(); I < N; ++I)
265 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
266 OS << "const SourceInfo &I) {\n";
267
268 std::function<void(size_t, const Twine &)> Rec;
269 llvm::SmallVector<Record *, 2> TS;
270 Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine &ID) {
271 if (I >= Types->size()) {
272 // Print a call to the emitter method.
273 // Custom evaluator methods dispatch to template methods.
274 if (R->getValueAsBit("HasCustomEval")) {
275 OS << "#ifdef GET_LINK_IMPL\n";
276 OS << " return emit" << ID << "\n";
277 OS << "#else\n";
278 OS << " return emit" << N;
279 PrintTypes(OS, TS);
280 OS << "\n#endif\n";
281 OS << " ";
282 } else {
283 OS << " return emit" << ID;
284 }
285
286 OS << "(";
287 for (size_t I = 0; I < Args.size(); ++I) {
288 OS << "A" << I << ", ";
289 }
290 OS << "I);\n";
291 return;
292 }
293
294 // Print a switch statement selecting T.
295 if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
296 OS << " switch (T" << I << ") {\n";
297 auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
298 for (auto *Case : Cases) {
299 OS << " case PT_" << Case->getName() << ":\n";
300 TS.push_back(Case);
301 Rec(I + 1, ID + Case->getName());
302 TS.pop_back();
303 }
304 // Emit a default case if not all types are present.
305 if (Cases.size() < NumTypes)
306 OS << " default: llvm_unreachable(\"invalid type\");\n";
307 OS << " }\n";
308 OS << " llvm_unreachable(\"invalid enum value\");\n";
309 } else {
310 PrintFatalError("Expected a type class");
311 }
312 };
313 Rec(0, N);
314
315 OS << "}\n";
316 OS << "#endif\n";
317 }
318
EmitEval(raw_ostream & OS,StringRef N,Record * R)319 void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) {
320 if (R->getValueAsBit("HasCustomEval"))
321 return;
322
323 OS << "#ifdef GET_EVAL_IMPL\n";
324 Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) {
325 auto Args = R->getValueAsListOfDefs("Args");
326
327 OS << "bool EvalEmitter::emit" << ID << "(";
328 for (size_t I = 0, N = Args.size(); I < N; ++I)
329 OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
330 OS << "const SourceInfo &L) {\n";
331 OS << " if (!isActive()) return true;\n";
332 OS << " CurrentSource = L;\n";
333
334 OS << " return " << N;
335 PrintTypes(OS, TS);
336 OS << "(S, OpPC";
337 for (size_t I = 0, N = Args.size(); I < N; ++I)
338 OS << ", A" << I;
339 OS << ");\n";
340 OS << "}\n";
341 });
342
343 OS << "#endif\n";
344 }
345
PrintTypes(raw_ostream & OS,ArrayRef<Record * > Types)346 void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types) {
347 if (Types.empty())
348 return;
349 OS << "<";
350 for (size_t I = 0, N = Types.size(); I < N; ++I) {
351 if (I != 0)
352 OS << ", ";
353 OS << "PT_" << Types[I]->getName();
354 }
355 OS << ">";
356 }
357
EmitClangOpcodes(RecordKeeper & Records,raw_ostream & OS)358 void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
359 ClangOpcodesEmitter(Records).run(OS);
360 }
361