1 //=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
22 class ClangOpcodesEmitter
{
23 RecordKeeper
&Records
;
28 ClangOpcodesEmitter(RecordKeeper
&R
)
29 : Records(R
), Root("Opcode", SMLoc(), R
),
30 NumTypes(Records
.getAllDerivedDefinitions("Type").size()) {}
32 void run(raw_ostream
&OS
);
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()) {
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());
79 PrintFatalError("Expected a type class");
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");
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
,
106 OS
<< "#ifdef GET_OPCODE_NAMES\n";
107 Enumerate(R
, N
, [&OS
](ArrayRef
<const Record
*>, const Twine
&ID
) {
108 OS
<< "OP_" << ID
<< ",\n";
113 void ClangOpcodesEmitter::EmitInterp(raw_ostream
&OS
, StringRef N
,
115 OS
<< "#ifdef GET_INTERP\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";
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
;
132 OS
<< "ReadArg<" << Args
[I
]->getValueAsString("Name")
136 // Emit a call to the template method and pass arguments.
146 for (size_t I
= 0, N
= Args
.size(); I
< N
; ++I
)
149 OS
<< " return false;\n";
151 // Bail out if interpreter returned.
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";
166 void ClangOpcodesEmitter::EmitDisasm(raw_ostream
&OS
, StringRef N
,
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)";
179 OS
<< " << \"\\n\";\n";
180 OS
<< " continue;\n";
185 void ClangOpcodesEmitter::EmitEmitter(raw_ostream
&OS
, StringRef N
,
187 if (R
->getValueAsBit("HasCustomLink"))
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
) {
205 OS
<< Args
[I
]->getValueAsString("Name");
208 for (size_t I
= 0, N
= Args
.size(); I
< N
; ++I
)
216 void ClangOpcodesEmitter::EmitProto(raw_ostream
&OS
, StringRef N
,
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";
232 for (size_t I
= 0; I
< TypeCount
; ++I
) {
238 OS
<< "bool emit" << N
<< "(";
239 for (auto *Arg
: Args
)
240 OS
<< Arg
->getValueAsString("Name") << ", ";
241 OS
<< "const SourceInfo &);\n";
248 void ClangOpcodesEmitter::EmitGroup(raw_ostream
&OS
, StringRef N
,
250 if (!R
->getValueAsBit("HasGroup"))
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
)
263 for (auto *Arg
: Args
)
264 OS
<< Arg
->getValueAsString("Name") << ", ";
265 OS
<< "const SourceInfo &I);\n";
268 // Emit the dispatch implementation in the source.
269 OS
<< "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
271 OS
<< "#if defined(GET_EVAL_IMPL)\n";
272 OS
<< "EvalEmitter\n";
274 OS
<< "ByteCodeEmitter\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";
294 OS
<< " return emit" << N
;
299 OS
<< " return emit" << ID
;
303 for (size_t I
= 0; I
< Args
.size(); ++I
) {
304 OS
<< "A" << I
<< ", ";
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";
317 Rec(I
+ 1, ID
+ Case
->getName());
320 // Emit a default case if not all types are present.
321 if (Cases
.size() < NumTypes
)
322 OS
<< " default: llvm_unreachable(\"invalid type: " << EmitFuncName
325 OS
<< " llvm_unreachable(\"invalid enum value\");\n";
327 PrintFatalError("Expected a type class");
336 void ClangOpcodesEmitter::EmitEval(raw_ostream
&OS
, StringRef N
,
338 if (R
->getValueAsBit("HasCustomEval"))
341 OS
<< "#ifdef GET_EVAL_IMPL\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
;
356 for (size_t I
= 0, N
= Args
.size(); I
< N
; ++I
)
365 void ClangOpcodesEmitter::PrintTypes(raw_ostream
&OS
,
366 ArrayRef
<const Record
*> Types
) {
370 for (size_t I
= 0, N
= Types
.size(); I
< N
; ++I
) {
373 OS
<< "PT_" << Types
[I
]->getName();
378 void clang::EmitClangOpcodes(RecordKeeper
&Records
, raw_ostream
&OS
) {
379 ClangOpcodesEmitter(Records
).run(OS
);