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