ClangOpcodesEmitter.cpp 11 KB

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