xref: /netbsd-src/external/apache2/llvm/dist/clang/utils/TableGen/ClangOpcodesEmitter.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // These tablegen backends emit Clang AST node tables
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "TableGenBackends.h"
147330f729Sjoerg #include "llvm/TableGen/Error.h"
157330f729Sjoerg #include "llvm/TableGen/Record.h"
167330f729Sjoerg #include "llvm/TableGen/StringMatcher.h"
177330f729Sjoerg #include "llvm/TableGen/TableGenBackend.h"
187330f729Sjoerg 
197330f729Sjoerg using namespace llvm;
207330f729Sjoerg 
217330f729Sjoerg namespace {
227330f729Sjoerg class ClangOpcodesEmitter {
237330f729Sjoerg   RecordKeeper &Records;
247330f729Sjoerg   Record Root;
257330f729Sjoerg   unsigned NumTypes;
267330f729Sjoerg 
277330f729Sjoerg public:
ClangOpcodesEmitter(RecordKeeper & R)287330f729Sjoerg   ClangOpcodesEmitter(RecordKeeper &R)
297330f729Sjoerg     : Records(R), Root("Opcode", SMLoc(), R),
307330f729Sjoerg       NumTypes(Records.getAllDerivedDefinitions("Type").size()) {}
317330f729Sjoerg 
327330f729Sjoerg   void run(raw_ostream &OS);
337330f729Sjoerg 
347330f729Sjoerg private:
357330f729Sjoerg   /// Emits the opcode name for the opcode enum.
367330f729Sjoerg   /// The name is obtained by concatenating the name with the list of types.
377330f729Sjoerg   void EmitEnum(raw_ostream &OS, StringRef N, Record *R);
387330f729Sjoerg 
397330f729Sjoerg   /// Emits the switch case and the invocation in the interpreter.
407330f729Sjoerg   void EmitInterp(raw_ostream &OS, StringRef N, Record *R);
417330f729Sjoerg 
427330f729Sjoerg   /// Emits the disassembler.
437330f729Sjoerg   void EmitDisasm(raw_ostream &OS, StringRef N, Record *R);
447330f729Sjoerg 
457330f729Sjoerg   /// Emits the byte code emitter method.
467330f729Sjoerg   void EmitEmitter(raw_ostream &OS, StringRef N, Record *R);
477330f729Sjoerg 
487330f729Sjoerg   /// Emits the prototype.
497330f729Sjoerg   void EmitProto(raw_ostream &OS, StringRef N, Record *R);
507330f729Sjoerg 
517330f729Sjoerg   /// Emits the prototype to dispatch from a type.
527330f729Sjoerg   void EmitGroup(raw_ostream &OS, StringRef N, Record *R);
537330f729Sjoerg 
547330f729Sjoerg   /// Emits the evaluator method.
557330f729Sjoerg   void EmitEval(raw_ostream &OS, StringRef N, Record *R);
567330f729Sjoerg 
577330f729Sjoerg   void PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types);
587330f729Sjoerg };
597330f729Sjoerg 
Enumerate(const Record * R,StringRef N,std::function<void (ArrayRef<Record * >,Twine)> && F)607330f729Sjoerg void Enumerate(const Record *R,
617330f729Sjoerg                StringRef N,
627330f729Sjoerg                std::function<void(ArrayRef<Record *>, Twine)> &&F) {
637330f729Sjoerg   llvm::SmallVector<Record *, 2> TypePath;
647330f729Sjoerg   auto *Types = R->getValueAsListInit("Types");
657330f729Sjoerg 
667330f729Sjoerg   std::function<void(size_t, const Twine &)> Rec;
677330f729Sjoerg   Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) {
687330f729Sjoerg     if (I >= Types->size()) {
697330f729Sjoerg       F(TypePath, ID);
707330f729Sjoerg       return;
717330f729Sjoerg     }
727330f729Sjoerg 
737330f729Sjoerg     if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
747330f729Sjoerg       for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) {
757330f729Sjoerg         TypePath.push_back(Type);
767330f729Sjoerg         Rec(I + 1, ID + Type->getName());
777330f729Sjoerg         TypePath.pop_back();
787330f729Sjoerg       }
797330f729Sjoerg     } else {
807330f729Sjoerg       PrintFatalError("Expected a type class");
817330f729Sjoerg     }
827330f729Sjoerg   };
837330f729Sjoerg   Rec(0, N);
847330f729Sjoerg }
857330f729Sjoerg 
867330f729Sjoerg } // namespace
877330f729Sjoerg 
run(raw_ostream & OS)887330f729Sjoerg void ClangOpcodesEmitter::run(raw_ostream &OS) {
897330f729Sjoerg   for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) {
907330f729Sjoerg     // The name is the record name, unless overriden.
917330f729Sjoerg     StringRef N = Opcode->getValueAsString("Name");
927330f729Sjoerg     if (N.empty())
937330f729Sjoerg       N = Opcode->getName();
947330f729Sjoerg 
957330f729Sjoerg     EmitEnum(OS, N, Opcode);
967330f729Sjoerg     EmitInterp(OS, N, Opcode);
977330f729Sjoerg     EmitDisasm(OS, N, Opcode);
987330f729Sjoerg     EmitProto(OS, N, Opcode);
997330f729Sjoerg     EmitGroup(OS, N, Opcode);
1007330f729Sjoerg     EmitEmitter(OS, N, Opcode);
1017330f729Sjoerg     EmitEval(OS, N, Opcode);
1027330f729Sjoerg   }
1037330f729Sjoerg }
1047330f729Sjoerg 
EmitEnum(raw_ostream & OS,StringRef N,Record * R)1057330f729Sjoerg void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, Record *R) {
1067330f729Sjoerg   OS << "#ifdef GET_OPCODE_NAMES\n";
1077330f729Sjoerg   Enumerate(R, N, [&OS](ArrayRef<Record *>, const Twine &ID) {
1087330f729Sjoerg     OS << "OP_" << ID << ",\n";
1097330f729Sjoerg   });
1107330f729Sjoerg   OS << "#endif\n";
1117330f729Sjoerg }
1127330f729Sjoerg 
EmitInterp(raw_ostream & OS,StringRef N,Record * R)1137330f729Sjoerg void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, Record *R) {
1147330f729Sjoerg   OS << "#ifdef GET_INTERP\n";
1157330f729Sjoerg 
1167330f729Sjoerg   Enumerate(R, N, [this, R, &OS, &N](ArrayRef<Record *> TS, const Twine &ID) {
1177330f729Sjoerg     bool CanReturn = R->getValueAsBit("CanReturn");
1187330f729Sjoerg     bool ChangesPC = R->getValueAsBit("ChangesPC");
1197330f729Sjoerg     auto Args = R->getValueAsListOfDefs("Args");
1207330f729Sjoerg 
1217330f729Sjoerg     OS << "case OP_" << ID << ": {\n";
1227330f729Sjoerg 
1237330f729Sjoerg     // Emit calls to read arguments.
1247330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I) {
125*e038c9c4Sjoerg       OS << "  auto V" << I;
1267330f729Sjoerg       OS << " = ";
1277330f729Sjoerg       OS << "PC.read<" << Args[I]->getValueAsString("Name") << ">();\n";
1287330f729Sjoerg     }
1297330f729Sjoerg 
1307330f729Sjoerg     // Emit a call to the template method and pass arguments.
131*e038c9c4Sjoerg     OS << "  if (!" << N;
1327330f729Sjoerg     PrintTypes(OS, TS);
1337330f729Sjoerg     OS << "(S";
1347330f729Sjoerg     if (ChangesPC)
1357330f729Sjoerg       OS << ", PC";
1367330f729Sjoerg     else
1377330f729Sjoerg       OS << ", OpPC";
1387330f729Sjoerg     if (CanReturn)
1397330f729Sjoerg       OS << ", Result";
1407330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I)
1417330f729Sjoerg       OS << ", V" << I;
1427330f729Sjoerg     OS << "))\n";
143*e038c9c4Sjoerg     OS << "    return false;\n";
1447330f729Sjoerg 
1457330f729Sjoerg     // Bail out if interpreter returned.
1467330f729Sjoerg     if (CanReturn) {
147*e038c9c4Sjoerg       OS << "  if (!S.Current || S.Current->isRoot())\n";
148*e038c9c4Sjoerg       OS << "    return true;\n";
1497330f729Sjoerg     }
1507330f729Sjoerg 
151*e038c9c4Sjoerg     OS << "  continue;\n";
1527330f729Sjoerg     OS << "}\n";
1537330f729Sjoerg   });
1547330f729Sjoerg   OS << "#endif\n";
1557330f729Sjoerg }
1567330f729Sjoerg 
EmitDisasm(raw_ostream & OS,StringRef N,Record * R)1577330f729Sjoerg void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record *R) {
1587330f729Sjoerg   OS << "#ifdef GET_DISASM\n";
1597330f729Sjoerg   Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
1607330f729Sjoerg     OS << "case OP_" << ID << ":\n";
161*e038c9c4Sjoerg     OS << "  PrintName(\"" << ID << "\");\n";
162*e038c9c4Sjoerg     OS << "  OS << \"\\t\"";
1637330f729Sjoerg 
1647330f729Sjoerg     for (auto *Arg : R->getValueAsListOfDefs("Args"))
1657330f729Sjoerg       OS << " << PC.read<" << Arg->getValueAsString("Name") << ">() << \" \"";
1667330f729Sjoerg 
1677330f729Sjoerg     OS << " << \"\\n\";\n";
168*e038c9c4Sjoerg     OS << "  continue;\n";
1697330f729Sjoerg   });
1707330f729Sjoerg   OS << "#endif\n";
1717330f729Sjoerg }
1727330f729Sjoerg 
EmitEmitter(raw_ostream & OS,StringRef N,Record * R)1737330f729Sjoerg void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record *R) {
1747330f729Sjoerg   if (R->getValueAsBit("HasCustomLink"))
1757330f729Sjoerg     return;
1767330f729Sjoerg 
1777330f729Sjoerg   OS << "#ifdef GET_LINK_IMPL\n";
1787330f729Sjoerg   Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
1797330f729Sjoerg     auto Args = R->getValueAsListOfDefs("Args");
1807330f729Sjoerg 
1817330f729Sjoerg     // Emit the list of arguments.
1827330f729Sjoerg     OS << "bool ByteCodeEmitter::emit" << ID << "(";
1837330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I)
1847330f729Sjoerg       OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
1857330f729Sjoerg     OS << "const SourceInfo &L) {\n";
1867330f729Sjoerg 
1877330f729Sjoerg     // Emit a call to write the opcodes.
188*e038c9c4Sjoerg     OS << "  return emitOp<";
1897330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I) {
1907330f729Sjoerg       if (I != 0)
1917330f729Sjoerg         OS << ", ";
1927330f729Sjoerg       OS << Args[I]->getValueAsString("Name");
1937330f729Sjoerg     }
1947330f729Sjoerg     OS << ">(OP_" << ID;
1957330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I)
1967330f729Sjoerg       OS << ", A" << I;
1977330f729Sjoerg     OS << ", L);\n";
1987330f729Sjoerg     OS << "}\n";
1997330f729Sjoerg   });
2007330f729Sjoerg   OS << "#endif\n";
2017330f729Sjoerg }
2027330f729Sjoerg 
EmitProto(raw_ostream & OS,StringRef N,Record * R)2037330f729Sjoerg void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) {
2047330f729Sjoerg   OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
2057330f729Sjoerg   auto Args = R->getValueAsListOfDefs("Args");
2067330f729Sjoerg   Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) {
2077330f729Sjoerg     OS << "bool emit" << ID << "(";
2087330f729Sjoerg     for (auto *Arg : Args)
2097330f729Sjoerg       OS << Arg->getValueAsString("Name") << ", ";
2107330f729Sjoerg     OS << "const SourceInfo &);\n";
2117330f729Sjoerg   });
2127330f729Sjoerg 
2137330f729Sjoerg   // Emit a template method for custom emitters to have less to implement.
2147330f729Sjoerg   auto TypeCount = R->getValueAsListInit("Types")->size();
2157330f729Sjoerg   if (R->getValueAsBit("HasCustomEval") && TypeCount) {
2167330f729Sjoerg     OS << "#if defined(GET_EVAL_PROTO)\n";
2177330f729Sjoerg     OS << "template<";
2187330f729Sjoerg     for (size_t I = 0; I < TypeCount; ++I) {
2197330f729Sjoerg       if (I != 0)
2207330f729Sjoerg         OS << ", ";
2217330f729Sjoerg       OS << "PrimType";
2227330f729Sjoerg     }
2237330f729Sjoerg     OS << ">\n";
2247330f729Sjoerg     OS << "bool emit" << N << "(";
2257330f729Sjoerg     for (auto *Arg : Args)
2267330f729Sjoerg       OS << Arg->getValueAsString("Name") << ", ";
2277330f729Sjoerg     OS << "const SourceInfo &);\n";
2287330f729Sjoerg     OS << "#endif\n";
2297330f729Sjoerg   }
2307330f729Sjoerg 
2317330f729Sjoerg   OS << "#endif\n";
2327330f729Sjoerg }
2337330f729Sjoerg 
EmitGroup(raw_ostream & OS,StringRef N,Record * R)2347330f729Sjoerg void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) {
2357330f729Sjoerg   if (!R->getValueAsBit("HasGroup"))
2367330f729Sjoerg     return;
2377330f729Sjoerg 
2387330f729Sjoerg   auto *Types = R->getValueAsListInit("Types");
2397330f729Sjoerg   auto Args = R->getValueAsListOfDefs("Args");
2407330f729Sjoerg 
2417330f729Sjoerg   // Emit the prototype of the group emitter in the header.
2427330f729Sjoerg   OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
2437330f729Sjoerg   OS << "bool emit" << N << "(";
2447330f729Sjoerg   for (size_t I = 0, N = Types->size(); I < N; ++I)
2457330f729Sjoerg     OS << "PrimType, ";
2467330f729Sjoerg   for (auto *Arg : Args)
2477330f729Sjoerg     OS << Arg->getValueAsString("Name") << ", ";
2487330f729Sjoerg   OS << "const SourceInfo &I);\n";
2497330f729Sjoerg   OS << "#endif\n";
2507330f729Sjoerg 
2517330f729Sjoerg   // Emit the dispatch implementation in the source.
2527330f729Sjoerg   OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
2537330f729Sjoerg   OS << "bool\n";
2547330f729Sjoerg   OS << "#if defined(GET_EVAL_IMPL)\n";
2557330f729Sjoerg   OS << "EvalEmitter\n";
2567330f729Sjoerg   OS << "#else\n";
2577330f729Sjoerg   OS << "ByteCodeEmitter\n";
2587330f729Sjoerg   OS << "#endif\n";
2597330f729Sjoerg   OS << "::emit" << N << "(";
2607330f729Sjoerg   for (size_t I = 0, N = Types->size(); I < N; ++I)
2617330f729Sjoerg     OS << "PrimType T" << I << ", ";
2627330f729Sjoerg   for (size_t I = 0, N = Args.size(); I < N; ++I)
2637330f729Sjoerg     OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
2647330f729Sjoerg   OS << "const SourceInfo &I) {\n";
2657330f729Sjoerg 
2667330f729Sjoerg   std::function<void(size_t, const Twine &)> Rec;
2677330f729Sjoerg   llvm::SmallVector<Record *, 2> TS;
2687330f729Sjoerg   Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine &ID) {
2697330f729Sjoerg     if (I >= Types->size()) {
2707330f729Sjoerg       // Print a call to the emitter method.
2717330f729Sjoerg       // Custom evaluator methods dispatch to template methods.
2727330f729Sjoerg       if (R->getValueAsBit("HasCustomEval")) {
2737330f729Sjoerg         OS << "#ifdef GET_LINK_IMPL\n";
2747330f729Sjoerg         OS << "    return emit" << ID << "\n";
2757330f729Sjoerg         OS << "#else\n";
2767330f729Sjoerg         OS << "    return emit" << N;
2777330f729Sjoerg         PrintTypes(OS, TS);
2787330f729Sjoerg         OS << "\n#endif\n";
279*e038c9c4Sjoerg         OS << "      ";
2807330f729Sjoerg       } else {
2817330f729Sjoerg         OS << "    return emit" << ID;
2827330f729Sjoerg       }
2837330f729Sjoerg 
2847330f729Sjoerg       OS << "(";
2857330f729Sjoerg       for (size_t I = 0; I < Args.size(); ++I) {
2867330f729Sjoerg         OS << "A" << I << ", ";
2877330f729Sjoerg       }
2887330f729Sjoerg       OS << "I);\n";
2897330f729Sjoerg       return;
2907330f729Sjoerg     }
2917330f729Sjoerg 
2927330f729Sjoerg     // Print a switch statement selecting T.
2937330f729Sjoerg     if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
2947330f729Sjoerg       OS << "  switch (T" << I << ") {\n";
2957330f729Sjoerg       auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
2967330f729Sjoerg       for (auto *Case : Cases) {
2977330f729Sjoerg         OS << "  case PT_" << Case->getName() << ":\n";
2987330f729Sjoerg         TS.push_back(Case);
2997330f729Sjoerg         Rec(I + 1, ID + Case->getName());
3007330f729Sjoerg         TS.pop_back();
3017330f729Sjoerg       }
3027330f729Sjoerg       // Emit a default case if not all types are present.
3037330f729Sjoerg       if (Cases.size() < NumTypes)
3047330f729Sjoerg         OS << "  default: llvm_unreachable(\"invalid type\");\n";
3057330f729Sjoerg       OS << "  }\n";
3067330f729Sjoerg       OS << "  llvm_unreachable(\"invalid enum value\");\n";
3077330f729Sjoerg     } else {
3087330f729Sjoerg       PrintFatalError("Expected a type class");
3097330f729Sjoerg     }
3107330f729Sjoerg   };
3117330f729Sjoerg   Rec(0, N);
3127330f729Sjoerg 
3137330f729Sjoerg   OS << "}\n";
3147330f729Sjoerg   OS << "#endif\n";
3157330f729Sjoerg }
3167330f729Sjoerg 
EmitEval(raw_ostream & OS,StringRef N,Record * R)3177330f729Sjoerg void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) {
3187330f729Sjoerg   if (R->getValueAsBit("HasCustomEval"))
3197330f729Sjoerg     return;
3207330f729Sjoerg 
3217330f729Sjoerg   OS << "#ifdef GET_EVAL_IMPL\n";
3227330f729Sjoerg   Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) {
3237330f729Sjoerg     auto Args = R->getValueAsListOfDefs("Args");
3247330f729Sjoerg 
3257330f729Sjoerg     OS << "bool EvalEmitter::emit" << ID << "(";
3267330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I)
3277330f729Sjoerg       OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
3287330f729Sjoerg     OS << "const SourceInfo &L) {\n";
3297330f729Sjoerg     OS << "  if (!isActive()) return true;\n";
3307330f729Sjoerg     OS << "  CurrentSource = L;\n";
3317330f729Sjoerg 
3327330f729Sjoerg     OS << "  return " << N;
3337330f729Sjoerg     PrintTypes(OS, TS);
3347330f729Sjoerg     OS << "(S, OpPC";
3357330f729Sjoerg     for (size_t I = 0, N = Args.size(); I < N; ++I)
3367330f729Sjoerg       OS << ", A" << I;
3377330f729Sjoerg     OS << ");\n";
3387330f729Sjoerg     OS << "}\n";
3397330f729Sjoerg   });
3407330f729Sjoerg 
3417330f729Sjoerg   OS << "#endif\n";
3427330f729Sjoerg }
3437330f729Sjoerg 
PrintTypes(raw_ostream & OS,ArrayRef<Record * > Types)3447330f729Sjoerg void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types) {
3457330f729Sjoerg   if (Types.empty())
3467330f729Sjoerg     return;
3477330f729Sjoerg   OS << "<";
3487330f729Sjoerg   for (size_t I = 0, N = Types.size(); I < N; ++I) {
3497330f729Sjoerg     if (I != 0)
3507330f729Sjoerg       OS << ", ";
3517330f729Sjoerg     OS << "PT_" << Types[I]->getName();
3527330f729Sjoerg   }
3537330f729Sjoerg   OS << ">";
3547330f729Sjoerg }
3557330f729Sjoerg 
EmitClangOpcodes(RecordKeeper & Records,raw_ostream & OS)3567330f729Sjoerg void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
3577330f729Sjoerg   ClangOpcodesEmitter(Records).run(OS);
3587330f729Sjoerg }
359