1a7dea167SDimitry Andric //=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // These tablegen backends emit Clang AST node tables 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12a7dea167SDimitry Andric 13a7dea167SDimitry Andric #include "TableGenBackends.h" 14a7dea167SDimitry Andric #include "llvm/TableGen/Error.h" 15a7dea167SDimitry Andric #include "llvm/TableGen/Record.h" 16a7dea167SDimitry Andric #include "llvm/TableGen/StringMatcher.h" 17a7dea167SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 18a7dea167SDimitry Andric 19a7dea167SDimitry Andric using namespace llvm; 20a7dea167SDimitry Andric 21a7dea167SDimitry Andric namespace { 22a7dea167SDimitry Andric class ClangOpcodesEmitter { 23a7dea167SDimitry Andric RecordKeeper &Records; 24a7dea167SDimitry Andric unsigned NumTypes; 25a7dea167SDimitry Andric 26a7dea167SDimitry Andric public: 27a7dea167SDimitry Andric ClangOpcodesEmitter(RecordKeeper &R) 28*0fca6ea1SDimitry Andric : Records(R), NumTypes(Records.getAllDerivedDefinitions("Type").size()) {} 29a7dea167SDimitry Andric 30a7dea167SDimitry Andric void run(raw_ostream &OS); 31a7dea167SDimitry Andric 32a7dea167SDimitry Andric private: 33a7dea167SDimitry Andric /// Emits the opcode name for the opcode enum. 34a7dea167SDimitry Andric /// The name is obtained by concatenating the name with the list of types. 3506c3fb27SDimitry Andric void EmitEnum(raw_ostream &OS, StringRef N, const Record *R); 36a7dea167SDimitry Andric 37a7dea167SDimitry Andric /// Emits the switch case and the invocation in the interpreter. 3806c3fb27SDimitry Andric void EmitInterp(raw_ostream &OS, StringRef N, const Record *R); 39a7dea167SDimitry Andric 40a7dea167SDimitry Andric /// Emits the disassembler. 4106c3fb27SDimitry Andric void EmitDisasm(raw_ostream &OS, StringRef N, const Record *R); 42a7dea167SDimitry Andric 43a7dea167SDimitry Andric /// Emits the byte code emitter method. 4406c3fb27SDimitry Andric void EmitEmitter(raw_ostream &OS, StringRef N, const Record *R); 45a7dea167SDimitry Andric 46a7dea167SDimitry Andric /// Emits the prototype. 4706c3fb27SDimitry Andric void EmitProto(raw_ostream &OS, StringRef N, const Record *R); 48a7dea167SDimitry Andric 49a7dea167SDimitry Andric /// Emits the prototype to dispatch from a type. 5006c3fb27SDimitry Andric void EmitGroup(raw_ostream &OS, StringRef N, const Record *R); 51a7dea167SDimitry Andric 52a7dea167SDimitry Andric /// Emits the evaluator method. 5306c3fb27SDimitry Andric void EmitEval(raw_ostream &OS, StringRef N, const Record *R); 54a7dea167SDimitry Andric 5506c3fb27SDimitry Andric void PrintTypes(raw_ostream &OS, ArrayRef<const Record *> Types); 56a7dea167SDimitry Andric }; 57a7dea167SDimitry Andric 5806c3fb27SDimitry Andric void Enumerate(const Record *R, StringRef N, 5906c3fb27SDimitry Andric std::function<void(ArrayRef<const Record *>, Twine)> &&F) { 6006c3fb27SDimitry Andric llvm::SmallVector<const Record *, 2> TypePath; 61*0fca6ea1SDimitry Andric const auto *Types = R->getValueAsListInit("Types"); 62a7dea167SDimitry Andric 63a7dea167SDimitry Andric std::function<void(size_t, const Twine &)> Rec; 64a7dea167SDimitry Andric Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) { 65a7dea167SDimitry Andric if (I >= Types->size()) { 66a7dea167SDimitry Andric F(TypePath, ID); 67a7dea167SDimitry Andric return; 68a7dea167SDimitry Andric } 69a7dea167SDimitry Andric 70*0fca6ea1SDimitry Andric if (const auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) { 71*0fca6ea1SDimitry Andric for (const auto *Type : 72*0fca6ea1SDimitry Andric TypeClass->getDef()->getValueAsListOfDefs("Types")) { 73a7dea167SDimitry Andric TypePath.push_back(Type); 74a7dea167SDimitry Andric Rec(I + 1, ID + Type->getName()); 75a7dea167SDimitry Andric TypePath.pop_back(); 76a7dea167SDimitry Andric } 77a7dea167SDimitry Andric } else { 78a7dea167SDimitry Andric PrintFatalError("Expected a type class"); 79a7dea167SDimitry Andric } 80a7dea167SDimitry Andric }; 81a7dea167SDimitry Andric Rec(0, N); 82a7dea167SDimitry Andric } 83a7dea167SDimitry Andric 84a7dea167SDimitry Andric } // namespace 85a7dea167SDimitry Andric 86a7dea167SDimitry Andric void ClangOpcodesEmitter::run(raw_ostream &OS) { 87*0fca6ea1SDimitry Andric for (const auto *Opcode : Records.getAllDerivedDefinitions("Opcode")) { 88a7dea167SDimitry Andric // The name is the record name, unless overriden. 89a7dea167SDimitry Andric StringRef N = Opcode->getValueAsString("Name"); 90a7dea167SDimitry Andric if (N.empty()) 91a7dea167SDimitry Andric N = Opcode->getName(); 92a7dea167SDimitry Andric 93a7dea167SDimitry Andric EmitEnum(OS, N, Opcode); 94a7dea167SDimitry Andric EmitInterp(OS, N, Opcode); 95a7dea167SDimitry Andric EmitDisasm(OS, N, Opcode); 96a7dea167SDimitry Andric EmitProto(OS, N, Opcode); 97a7dea167SDimitry Andric EmitGroup(OS, N, Opcode); 98a7dea167SDimitry Andric EmitEmitter(OS, N, Opcode); 99a7dea167SDimitry Andric EmitEval(OS, N, Opcode); 100a7dea167SDimitry Andric } 101a7dea167SDimitry Andric } 102a7dea167SDimitry Andric 10306c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, 10406c3fb27SDimitry Andric const Record *R) { 105a7dea167SDimitry Andric OS << "#ifdef GET_OPCODE_NAMES\n"; 10606c3fb27SDimitry Andric Enumerate(R, N, [&OS](ArrayRef<const Record *>, const Twine &ID) { 107a7dea167SDimitry Andric OS << "OP_" << ID << ",\n"; 108a7dea167SDimitry Andric }); 109a7dea167SDimitry Andric OS << "#endif\n"; 110a7dea167SDimitry Andric } 111a7dea167SDimitry Andric 11206c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, 11306c3fb27SDimitry Andric const Record *R) { 114a7dea167SDimitry Andric OS << "#ifdef GET_INTERP\n"; 115a7dea167SDimitry Andric 11606c3fb27SDimitry Andric Enumerate(R, N, 11706c3fb27SDimitry Andric [this, R, &OS, &N](ArrayRef<const Record *> TS, const Twine &ID) { 118a7dea167SDimitry Andric bool CanReturn = R->getValueAsBit("CanReturn"); 119a7dea167SDimitry Andric bool ChangesPC = R->getValueAsBit("ChangesPC"); 120*0fca6ea1SDimitry Andric const auto &Args = R->getValueAsListOfDefs("Args"); 121a7dea167SDimitry Andric 122a7dea167SDimitry Andric OS << "case OP_" << ID << ": {\n"; 123a7dea167SDimitry Andric 124bdd1243dSDimitry Andric if (CanReturn) 125bdd1243dSDimitry Andric OS << " bool DoReturn = (S.Current == StartFrame);\n"; 126bdd1243dSDimitry Andric 127a7dea167SDimitry Andric // Emit calls to read arguments. 128a7dea167SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 129*0fca6ea1SDimitry Andric const auto *Arg = Args[I]; 130*0fca6ea1SDimitry Andric bool AsRef = Arg->getValueAsBit("AsRef"); 131*0fca6ea1SDimitry Andric 132*0fca6ea1SDimitry Andric if (AsRef) 133*0fca6ea1SDimitry Andric OS << " const auto &V" << I; 134*0fca6ea1SDimitry Andric else 135*0fca6ea1SDimitry Andric OS << " const auto V" << I; 136a7dea167SDimitry Andric OS << " = "; 137*0fca6ea1SDimitry Andric OS << "ReadArg<" << Arg->getValueAsString("Name") 13806c3fb27SDimitry Andric << ">(S, PC);\n"; 139a7dea167SDimitry Andric } 140a7dea167SDimitry Andric 141a7dea167SDimitry Andric // Emit a call to the template method and pass arguments. 142fe6060f1SDimitry Andric OS << " if (!" << N; 143a7dea167SDimitry Andric PrintTypes(OS, TS); 144a7dea167SDimitry Andric OS << "(S"; 145a7dea167SDimitry Andric if (ChangesPC) 146a7dea167SDimitry Andric OS << ", PC"; 147a7dea167SDimitry Andric else 148a7dea167SDimitry Andric OS << ", OpPC"; 149a7dea167SDimitry Andric if (CanReturn) 150a7dea167SDimitry Andric OS << ", Result"; 151a7dea167SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) 152a7dea167SDimitry Andric OS << ", V" << I; 153a7dea167SDimitry Andric OS << "))\n"; 154fe6060f1SDimitry Andric OS << " return false;\n"; 155a7dea167SDimitry Andric 156a7dea167SDimitry Andric // Bail out if interpreter returned. 157a7dea167SDimitry Andric if (CanReturn) { 158fe6060f1SDimitry Andric OS << " if (!S.Current || S.Current->isRoot())\n"; 159fe6060f1SDimitry Andric OS << " return true;\n"; 160bdd1243dSDimitry Andric 161bdd1243dSDimitry Andric OS << " if (DoReturn)\n"; 162bdd1243dSDimitry Andric OS << " return true;\n"; 163a7dea167SDimitry Andric } 164a7dea167SDimitry Andric 165fe6060f1SDimitry Andric OS << " continue;\n"; 166a7dea167SDimitry Andric OS << "}\n"; 167a7dea167SDimitry Andric }); 168a7dea167SDimitry Andric OS << "#endif\n"; 169a7dea167SDimitry Andric } 170a7dea167SDimitry Andric 17106c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, 17206c3fb27SDimitry Andric const Record *R) { 173a7dea167SDimitry Andric OS << "#ifdef GET_DISASM\n"; 17406c3fb27SDimitry Andric Enumerate(R, N, [R, &OS](ArrayRef<const Record *>, const Twine &ID) { 175a7dea167SDimitry Andric OS << "case OP_" << ID << ":\n"; 176fe6060f1SDimitry Andric OS << " PrintName(\"" << ID << "\");\n"; 177fe6060f1SDimitry Andric OS << " OS << \"\\t\""; 178a7dea167SDimitry Andric 179*0fca6ea1SDimitry Andric for (const auto *Arg : R->getValueAsListOfDefs("Args")) { 180349cc55cSDimitry Andric OS << " << ReadArg<" << Arg->getValueAsString("Name") << ">(P, PC)"; 181349cc55cSDimitry Andric OS << " << \" \""; 182349cc55cSDimitry Andric } 183a7dea167SDimitry Andric 184a7dea167SDimitry Andric OS << " << \"\\n\";\n"; 185fe6060f1SDimitry Andric OS << " continue;\n"; 186a7dea167SDimitry Andric }); 187a7dea167SDimitry Andric OS << "#endif\n"; 188a7dea167SDimitry Andric } 189a7dea167SDimitry Andric 19006c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, 19106c3fb27SDimitry Andric const Record *R) { 192a7dea167SDimitry Andric if (R->getValueAsBit("HasCustomLink")) 193a7dea167SDimitry Andric return; 194a7dea167SDimitry Andric 195a7dea167SDimitry Andric OS << "#ifdef GET_LINK_IMPL\n"; 19606c3fb27SDimitry Andric Enumerate(R, N, [R, &OS](ArrayRef<const Record *>, const Twine &ID) { 197*0fca6ea1SDimitry Andric const auto &Args = R->getValueAsListOfDefs("Args"); 198a7dea167SDimitry Andric 199a7dea167SDimitry Andric // Emit the list of arguments. 200a7dea167SDimitry Andric OS << "bool ByteCodeEmitter::emit" << ID << "("; 201*0fca6ea1SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 202*0fca6ea1SDimitry Andric const auto *Arg = Args[I]; 203*0fca6ea1SDimitry Andric bool AsRef = Arg->getValueAsBit("AsRef"); 204*0fca6ea1SDimitry Andric auto Name = Arg->getValueAsString("Name"); 205*0fca6ea1SDimitry Andric 206*0fca6ea1SDimitry Andric OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A" 207*0fca6ea1SDimitry Andric << I << ", "; 208*0fca6ea1SDimitry Andric } 209a7dea167SDimitry Andric OS << "const SourceInfo &L) {\n"; 210a7dea167SDimitry Andric 211a7dea167SDimitry Andric // Emit a call to write the opcodes. 212fe6060f1SDimitry Andric OS << " return emitOp<"; 213a7dea167SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 214a7dea167SDimitry Andric if (I != 0) 215a7dea167SDimitry Andric OS << ", "; 216a7dea167SDimitry Andric OS << Args[I]->getValueAsString("Name"); 217a7dea167SDimitry Andric } 218a7dea167SDimitry Andric OS << ">(OP_" << ID; 219a7dea167SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) 220a7dea167SDimitry Andric OS << ", A" << I; 221a7dea167SDimitry Andric OS << ", L);\n"; 222a7dea167SDimitry Andric OS << "}\n"; 223a7dea167SDimitry Andric }); 224a7dea167SDimitry Andric OS << "#endif\n"; 225a7dea167SDimitry Andric } 226a7dea167SDimitry Andric 22706c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, 22806c3fb27SDimitry Andric const Record *R) { 229a7dea167SDimitry Andric OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n"; 230a7dea167SDimitry Andric auto Args = R->getValueAsListOfDefs("Args"); 23106c3fb27SDimitry Andric Enumerate(R, N, [&OS, &Args](ArrayRef<const Record *> TS, const Twine &ID) { 232a7dea167SDimitry Andric OS << "bool emit" << ID << "("; 233*0fca6ea1SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 234*0fca6ea1SDimitry Andric const auto *Arg = Args[I]; 235*0fca6ea1SDimitry Andric bool AsRef = Arg->getValueAsBit("AsRef"); 236*0fca6ea1SDimitry Andric auto Name = Arg->getValueAsString("Name"); 237*0fca6ea1SDimitry Andric 238*0fca6ea1SDimitry Andric OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") 239*0fca6ea1SDimitry Andric << ", "; 240*0fca6ea1SDimitry Andric } 241a7dea167SDimitry Andric OS << "const SourceInfo &);\n"; 242a7dea167SDimitry Andric }); 243a7dea167SDimitry Andric 244a7dea167SDimitry Andric // Emit a template method for custom emitters to have less to implement. 245a7dea167SDimitry Andric auto TypeCount = R->getValueAsListInit("Types")->size(); 246a7dea167SDimitry Andric if (R->getValueAsBit("HasCustomEval") && TypeCount) { 247a7dea167SDimitry Andric OS << "#if defined(GET_EVAL_PROTO)\n"; 248a7dea167SDimitry Andric OS << "template<"; 249a7dea167SDimitry Andric for (size_t I = 0; I < TypeCount; ++I) { 250a7dea167SDimitry Andric if (I != 0) 251a7dea167SDimitry Andric OS << ", "; 252a7dea167SDimitry Andric OS << "PrimType"; 253a7dea167SDimitry Andric } 254a7dea167SDimitry Andric OS << ">\n"; 255a7dea167SDimitry Andric OS << "bool emit" << N << "("; 256*0fca6ea1SDimitry Andric for (const auto *Arg : Args) 257a7dea167SDimitry Andric OS << Arg->getValueAsString("Name") << ", "; 258a7dea167SDimitry Andric OS << "const SourceInfo &);\n"; 259a7dea167SDimitry Andric OS << "#endif\n"; 260a7dea167SDimitry Andric } 261a7dea167SDimitry Andric 262a7dea167SDimitry Andric OS << "#endif\n"; 263a7dea167SDimitry Andric } 264a7dea167SDimitry Andric 26506c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, 26606c3fb27SDimitry Andric const Record *R) { 267a7dea167SDimitry Andric if (!R->getValueAsBit("HasGroup")) 268a7dea167SDimitry Andric return; 269a7dea167SDimitry Andric 270*0fca6ea1SDimitry Andric const auto *Types = R->getValueAsListInit("Types"); 271*0fca6ea1SDimitry Andric const auto &Args = R->getValueAsListOfDefs("Args"); 272a7dea167SDimitry Andric 27306c3fb27SDimitry Andric Twine EmitFuncName = "emit" + N; 27406c3fb27SDimitry Andric 275a7dea167SDimitry Andric // Emit the prototype of the group emitter in the header. 276a7dea167SDimitry Andric OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n"; 277*0fca6ea1SDimitry Andric OS << "[[nodiscard]] bool " << EmitFuncName << "("; 278a7dea167SDimitry Andric for (size_t I = 0, N = Types->size(); I < N; ++I) 279a7dea167SDimitry Andric OS << "PrimType, "; 280a7dea167SDimitry Andric for (auto *Arg : Args) 281a7dea167SDimitry Andric OS << Arg->getValueAsString("Name") << ", "; 282a7dea167SDimitry Andric OS << "const SourceInfo &I);\n"; 283a7dea167SDimitry Andric OS << "#endif\n"; 284a7dea167SDimitry Andric 285a7dea167SDimitry Andric // Emit the dispatch implementation in the source. 286a7dea167SDimitry Andric OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n"; 287a7dea167SDimitry Andric OS << "bool\n"; 288a7dea167SDimitry Andric OS << "#if defined(GET_EVAL_IMPL)\n"; 289a7dea167SDimitry Andric OS << "EvalEmitter\n"; 290a7dea167SDimitry Andric OS << "#else\n"; 291a7dea167SDimitry Andric OS << "ByteCodeEmitter\n"; 292a7dea167SDimitry Andric OS << "#endif\n"; 29306c3fb27SDimitry Andric OS << "::" << EmitFuncName << "("; 294a7dea167SDimitry Andric for (size_t I = 0, N = Types->size(); I < N; ++I) 295a7dea167SDimitry Andric OS << "PrimType T" << I << ", "; 296*0fca6ea1SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 297*0fca6ea1SDimitry Andric const auto *Arg = Args[I]; 298*0fca6ea1SDimitry Andric bool AsRef = Arg->getValueAsBit("AsRef"); 299*0fca6ea1SDimitry Andric auto Name = Arg->getValueAsString("Name"); 300*0fca6ea1SDimitry Andric 301*0fca6ea1SDimitry Andric OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A" 302*0fca6ea1SDimitry Andric << I << ", "; 303*0fca6ea1SDimitry Andric } 304a7dea167SDimitry Andric OS << "const SourceInfo &I) {\n"; 305a7dea167SDimitry Andric 306a7dea167SDimitry Andric std::function<void(size_t, const Twine &)> Rec; 30706c3fb27SDimitry Andric llvm::SmallVector<const Record *, 2> TS; 30806c3fb27SDimitry Andric Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N, 30906c3fb27SDimitry Andric EmitFuncName](size_t I, const Twine &ID) { 310a7dea167SDimitry Andric if (I >= Types->size()) { 311a7dea167SDimitry Andric // Print a call to the emitter method. 312a7dea167SDimitry Andric // Custom evaluator methods dispatch to template methods. 313a7dea167SDimitry Andric if (R->getValueAsBit("HasCustomEval")) { 314a7dea167SDimitry Andric OS << "#ifdef GET_LINK_IMPL\n"; 315a7dea167SDimitry Andric OS << " return emit" << ID << "\n"; 316a7dea167SDimitry Andric OS << "#else\n"; 317a7dea167SDimitry Andric OS << " return emit" << N; 318a7dea167SDimitry Andric PrintTypes(OS, TS); 319a7dea167SDimitry Andric OS << "\n#endif\n"; 320fe6060f1SDimitry Andric OS << " "; 321a7dea167SDimitry Andric } else { 322a7dea167SDimitry Andric OS << " return emit" << ID; 323a7dea167SDimitry Andric } 324a7dea167SDimitry Andric 325a7dea167SDimitry Andric OS << "("; 326a7dea167SDimitry Andric for (size_t I = 0; I < Args.size(); ++I) { 327a7dea167SDimitry Andric OS << "A" << I << ", "; 328a7dea167SDimitry Andric } 329a7dea167SDimitry Andric OS << "I);\n"; 330a7dea167SDimitry Andric return; 331a7dea167SDimitry Andric } 332a7dea167SDimitry Andric 333a7dea167SDimitry Andric // Print a switch statement selecting T. 334a7dea167SDimitry Andric if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) { 335a7dea167SDimitry Andric OS << " switch (T" << I << ") {\n"; 336a7dea167SDimitry Andric auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types"); 337a7dea167SDimitry Andric for (auto *Case : Cases) { 338a7dea167SDimitry Andric OS << " case PT_" << Case->getName() << ":\n"; 339a7dea167SDimitry Andric TS.push_back(Case); 340a7dea167SDimitry Andric Rec(I + 1, ID + Case->getName()); 341a7dea167SDimitry Andric TS.pop_back(); 342a7dea167SDimitry Andric } 343a7dea167SDimitry Andric // Emit a default case if not all types are present. 344a7dea167SDimitry Andric if (Cases.size() < NumTypes) 34506c3fb27SDimitry Andric OS << " default: llvm_unreachable(\"invalid type: " << EmitFuncName 34606c3fb27SDimitry Andric << "\");\n"; 347a7dea167SDimitry Andric OS << " }\n"; 348a7dea167SDimitry Andric OS << " llvm_unreachable(\"invalid enum value\");\n"; 349a7dea167SDimitry Andric } else { 350a7dea167SDimitry Andric PrintFatalError("Expected a type class"); 351a7dea167SDimitry Andric } 352a7dea167SDimitry Andric }; 353a7dea167SDimitry Andric Rec(0, N); 354a7dea167SDimitry Andric 355a7dea167SDimitry Andric OS << "}\n"; 356a7dea167SDimitry Andric OS << "#endif\n"; 357a7dea167SDimitry Andric } 358a7dea167SDimitry Andric 35906c3fb27SDimitry Andric void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, 36006c3fb27SDimitry Andric const Record *R) { 361a7dea167SDimitry Andric if (R->getValueAsBit("HasCustomEval")) 362a7dea167SDimitry Andric return; 363a7dea167SDimitry Andric 364a7dea167SDimitry Andric OS << "#ifdef GET_EVAL_IMPL\n"; 36506c3fb27SDimitry Andric Enumerate(R, N, 36606c3fb27SDimitry Andric [this, R, &N, &OS](ArrayRef<const Record *> TS, const Twine &ID) { 367a7dea167SDimitry Andric auto Args = R->getValueAsListOfDefs("Args"); 368a7dea167SDimitry Andric 369a7dea167SDimitry Andric OS << "bool EvalEmitter::emit" << ID << "("; 370*0fca6ea1SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) { 371*0fca6ea1SDimitry Andric const auto *Arg = Args[I]; 372*0fca6ea1SDimitry Andric bool AsRef = Arg->getValueAsBit("AsRef"); 373*0fca6ea1SDimitry Andric auto Name = Arg->getValueAsString("Name"); 374*0fca6ea1SDimitry Andric 375*0fca6ea1SDimitry Andric OS << (AsRef ? "const " : " ") << Name << " " 376*0fca6ea1SDimitry Andric << (AsRef ? "&" : "") << "A" << I << ", "; 377*0fca6ea1SDimitry Andric } 378a7dea167SDimitry Andric OS << "const SourceInfo &L) {\n"; 379a7dea167SDimitry Andric OS << " if (!isActive()) return true;\n"; 380a7dea167SDimitry Andric OS << " CurrentSource = L;\n"; 381a7dea167SDimitry Andric 382a7dea167SDimitry Andric OS << " return " << N; 383a7dea167SDimitry Andric PrintTypes(OS, TS); 384a7dea167SDimitry Andric OS << "(S, OpPC"; 385a7dea167SDimitry Andric for (size_t I = 0, N = Args.size(); I < N; ++I) 386a7dea167SDimitry Andric OS << ", A" << I; 387a7dea167SDimitry Andric OS << ");\n"; 388a7dea167SDimitry Andric OS << "}\n"; 389a7dea167SDimitry Andric }); 390a7dea167SDimitry Andric 391a7dea167SDimitry Andric OS << "#endif\n"; 392a7dea167SDimitry Andric } 393a7dea167SDimitry Andric 39406c3fb27SDimitry Andric void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, 39506c3fb27SDimitry Andric ArrayRef<const Record *> Types) { 396a7dea167SDimitry Andric if (Types.empty()) 397a7dea167SDimitry Andric return; 398a7dea167SDimitry Andric OS << "<"; 399a7dea167SDimitry Andric for (size_t I = 0, N = Types.size(); I < N; ++I) { 400a7dea167SDimitry Andric if (I != 0) 401a7dea167SDimitry Andric OS << ", "; 402a7dea167SDimitry Andric OS << "PT_" << Types[I]->getName(); 403a7dea167SDimitry Andric } 404a7dea167SDimitry Andric OS << ">"; 405a7dea167SDimitry Andric } 406a7dea167SDimitry Andric 407a7dea167SDimitry Andric void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) { 408a7dea167SDimitry Andric ClangOpcodesEmitter(Records).run(OS); 409a7dea167SDimitry Andric } 410