diff options
Diffstat (limited to 'clang/utils/TableGen/ClangOpcodesEmitter.cpp')
-rw-r--r-- | clang/utils/TableGen/ClangOpcodesEmitter.cpp | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp deleted file mode 100644 index 1ff20f0f449..00000000000 --- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp +++ /dev/null @@ -1,360 +0,0 @@ -//=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// These tablegen backends emit Clang AST node tables -// -//===----------------------------------------------------------------------===// - -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/StringMatcher.h" -#include "llvm/TableGen/TableGenBackend.h" - -using namespace llvm; - -namespace { -class ClangOpcodesEmitter { - RecordKeeper &Records; - Record Root; - unsigned NumTypes; - -public: - ClangOpcodesEmitter(RecordKeeper &R) - : Records(R), Root("Opcode", SMLoc(), R), - NumTypes(Records.getAllDerivedDefinitions("Type").size()) {} - - void run(raw_ostream &OS); - -private: - /// Emits the opcode name for the opcode enum. - /// The name is obtained by concatenating the name with the list of types. - void EmitEnum(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the switch case and the invocation in the interpreter. - void EmitInterp(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the disassembler. - void EmitDisasm(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the byte code emitter method. - void EmitEmitter(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the prototype. - void EmitProto(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the prototype to dispatch from a type. - void EmitGroup(raw_ostream &OS, StringRef N, Record *R); - - /// Emits the evaluator method. - void EmitEval(raw_ostream &OS, StringRef N, Record *R); - - void PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types); -}; - -void Enumerate(const Record *R, - StringRef N, - std::function<void(ArrayRef<Record *>, Twine)> &&F) { - llvm::SmallVector<Record *, 2> TypePath; - auto *Types = R->getValueAsListInit("Types"); - - std::function<void(size_t, const Twine &)> Rec; - Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) { - if (I >= Types->size()) { - F(TypePath, ID); - return; - } - - if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) { - for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) { - TypePath.push_back(Type); - Rec(I + 1, ID + Type->getName()); - TypePath.pop_back(); - } - } else { - PrintFatalError("Expected a type class"); - } - }; - Rec(0, N); -} - -} // namespace - -void ClangOpcodesEmitter::run(raw_ostream &OS) { - for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) { - // The name is the record name, unless overriden. - StringRef N = Opcode->getValueAsString("Name"); - if (N.empty()) - N = Opcode->getName(); - - EmitEnum(OS, N, Opcode); - EmitInterp(OS, N, Opcode); - EmitDisasm(OS, N, Opcode); - EmitProto(OS, N, Opcode); - EmitGroup(OS, N, Opcode); - EmitEmitter(OS, N, Opcode); - EmitEval(OS, N, Opcode); - } -} - -void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, Record *R) { - OS << "#ifdef GET_OPCODE_NAMES\n"; - Enumerate(R, N, [&OS](ArrayRef<Record *>, const Twine &ID) { - OS << "OP_" << ID << ",\n"; - }); - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, Record *R) { - OS << "#ifdef GET_INTERP\n"; - - Enumerate(R, N, [this, R, &OS, &N](ArrayRef<Record *> TS, const Twine &ID) { - bool CanReturn = R->getValueAsBit("CanReturn"); - bool ChangesPC = R->getValueAsBit("ChangesPC"); - auto Args = R->getValueAsListOfDefs("Args"); - - OS << "case OP_" << ID << ": {\n"; - - // Emit calls to read arguments. - for (size_t I = 0, N = Args.size(); I < N; ++I) { - OS << "\tauto V" << I; - OS << " = "; - OS << "PC.read<" << Args[I]->getValueAsString("Name") << ">();\n"; - } - - // Emit a call to the template method and pass arguments. - OS << "\tif (!" << N; - PrintTypes(OS, TS); - OS << "(S"; - if (ChangesPC) - OS << ", PC"; - else - OS << ", OpPC"; - if (CanReturn) - OS << ", Result"; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << ", V" << I; - OS << "))\n"; - OS << "\t\treturn false;\n"; - - // Bail out if interpreter returned. - if (CanReturn) { - OS << "\tif (!S.Current || S.Current->isRoot())\n"; - OS << "\t\treturn true;\n"; - } - - OS << "\tcontinue;\n"; - OS << "}\n"; - }); - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record *R) { - OS << "#ifdef GET_DISASM\n"; - Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) { - OS << "case OP_" << ID << ":\n"; - OS << "\tPrintName(\"" << ID << "\");\n"; - OS << "\tOS << \"\\t\""; - - for (auto *Arg : R->getValueAsListOfDefs("Args")) - OS << " << PC.read<" << Arg->getValueAsString("Name") << ">() << \" \""; - - OS << "<< \"\\n\";\n"; - OS << "\tcontinue;\n"; - }); - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record *R) { - if (R->getValueAsBit("HasCustomLink")) - return; - - OS << "#ifdef GET_LINK_IMPL\n"; - Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) { - auto Args = R->getValueAsListOfDefs("Args"); - - // Emit the list of arguments. - OS << "bool ByteCodeEmitter::emit" << ID << "("; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << Args[I]->getValueAsString("Name") << " A" << I << ","; - OS << "const SourceInfo &L) {\n"; - - // Emit a call to write the opcodes. - OS << "\treturn emitOp<"; - for (size_t I = 0, N = Args.size(); I < N; ++I) { - if (I != 0) - OS << ", "; - OS << Args[I]->getValueAsString("Name"); - } - OS << ">(OP_" << ID; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << ", A" << I; - OS << ", L);\n"; - OS << "}\n"; - }); - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) { - OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n"; - auto Args = R->getValueAsListOfDefs("Args"); - Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) { - OS << "bool emit" << ID << "("; - for (auto *Arg : Args) - OS << Arg->getValueAsString("Name") << ", "; - OS << "const SourceInfo &);\n"; - }); - - // Emit a template method for custom emitters to have less to implement. - auto TypeCount = R->getValueAsListInit("Types")->size(); - if (R->getValueAsBit("HasCustomEval") && TypeCount) { - OS << "#if defined(GET_EVAL_PROTO)\n"; - OS << "template<"; - for (size_t I = 0; I < TypeCount; ++I) { - if (I != 0) - OS << ", "; - OS << "PrimType"; - } - OS << ">\n"; - OS << "bool emit" << N << "("; - for (auto *Arg : Args) - OS << Arg->getValueAsString("Name") << ", "; - OS << "const SourceInfo &);\n"; - OS << "#endif\n"; - } - - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) { - if (!R->getValueAsBit("HasGroup")) - return; - - auto *Types = R->getValueAsListInit("Types"); - auto Args = R->getValueAsListOfDefs("Args"); - - // Emit the prototype of the group emitter in the header. - OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n"; - OS << "bool emit" << N << "("; - for (size_t I = 0, N = Types->size(); I < N; ++I) - OS << "PrimType, "; - for (auto *Arg : Args) - OS << Arg->getValueAsString("Name") << ", "; - OS << "const SourceInfo &I);\n"; - OS << "#endif\n"; - - // Emit the dispatch implementation in the source. - OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n"; - OS << "bool \n"; - OS << "#if defined(GET_EVAL_IMPL)\n"; - OS << "EvalEmitter\n"; - OS << "#else\n"; - OS << "ByteCodeEmitter\n"; - OS << "#endif\n"; - OS << "::emit" << N << "("; - for (size_t I = 0, N = Types->size(); I < N; ++I) - OS << "PrimType T" << I << ", "; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << Args[I]->getValueAsString("Name") << " A" << I << ", "; - OS << "const SourceInfo &I) {\n"; - - std::function<void(size_t, const Twine &)> Rec; - llvm::SmallVector<Record *, 2> TS; - Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine &ID) { - if (I >= Types->size()) { - // Print a call to the emitter method. - // Custom evaluator methods dispatch to template methods. - if (R->getValueAsBit("HasCustomEval")) { - OS << "#ifdef GET_LINK_IMPL\n"; - OS << "return emit" << ID << "\n"; - OS << "#else\n"; - OS << "return emit" << N; - PrintTypes(OS, TS); - OS << "\n#endif\n"; - } else { - OS << "return emit" << ID; - } - - OS << "("; - for (size_t I = 0; I < Args.size(); ++I) { - OS << "A" << I << ", "; - } - OS << "I);\n"; - return; - } - - // Print a switch statement selecting T. - if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) { - OS << "switch (T" << I << "){\n"; - auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types"); - for (auto *Case : Cases) { - OS << "case PT_" << Case->getName() << ":\n"; - TS.push_back(Case); - Rec(I + 1, ID + Case->getName()); - TS.pop_back(); - } - // Emit a default case if not all types are present. - if (Cases.size() < NumTypes) - OS << "default: llvm_unreachable(\"invalid type\");\n"; - OS << "}\n"; - OS << "llvm_unreachable(\"invalid enum value\");\n"; - } else { - PrintFatalError("Expected a type class"); - } - }; - Rec(0, N); - - OS << "}\n"; - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) { - if (R->getValueAsBit("HasCustomEval")) - return; - - OS << "#ifdef GET_EVAL_IMPL\n"; - Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) { - auto Args = R->getValueAsListOfDefs("Args"); - - OS << "bool EvalEmitter::emit" << ID << "("; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << Args[I]->getValueAsString("Name") << " A" << I << ","; - OS << "const SourceInfo &L) {\n"; - OS << "if (!isActive()) return true;\n"; - OS << "CurrentSource = L;\n"; - - OS << "return " << N; - PrintTypes(OS, TS); - OS << "(S, OpPC"; - for (size_t I = 0, N = Args.size(); I < N; ++I) - OS << ", A" << I; - OS << ");\n"; - OS << "}\n"; - }); - - OS << "#endif\n"; -} - -void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types) { - if (Types.empty()) - return; - OS << "<"; - for (size_t I = 0, N = Types.size(); I < N; ++I) { - if (I != 0) - OS << ", "; - OS << "PT_" << Types[I]->getName(); - } - OS << ">"; -} - -namespace clang { - -void EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) { - ClangOpcodesEmitter(Records).run(OS); -} - -} // end namespace clang |