ClangOpcodesEmitter.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. if (CanReturn)
  100. OS << " bool DoReturn = (S.Current == StartFrame);\n";
  101. // Emit calls to read arguments.
  102. for (size_t I = 0, N = Args.size(); I < N; ++I) {
  103. OS << " auto V" << I;
  104. OS << " = ";
  105. OS << "ReadArg<" << Args[I]->getValueAsString("Name") << ">(S, PC);\n";
  106. }
  107. // Emit a call to the template method and pass arguments.
  108. OS << " if (!" << N;
  109. PrintTypes(OS, TS);
  110. OS << "(S";
  111. if (ChangesPC)
  112. OS << ", PC";
  113. else
  114. OS << ", OpPC";
  115. if (CanReturn)
  116. OS << ", Result";
  117. for (size_t I = 0, N = Args.size(); I < N; ++I)
  118. OS << ", V" << I;
  119. OS << "))\n";
  120. OS << " return false;\n";
  121. // Bail out if interpreter returned.
  122. if (CanReturn) {
  123. OS << " if (!S.Current || S.Current->isRoot())\n";
  124. OS << " return true;\n";
  125. OS << " if (DoReturn)\n";
  126. OS << " return true;\n";
  127. }
  128. OS << " continue;\n";
  129. OS << "}\n";
  130. });
  131. OS << "#endif\n";
  132. }
  133. void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record *R) {
  134. OS << "#ifdef GET_DISASM\n";
  135. Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
  136. OS << "case OP_" << ID << ":\n";
  137. OS << " PrintName(\"" << ID << "\");\n";
  138. OS << " OS << \"\\t\"";
  139. for (auto *Arg : R->getValueAsListOfDefs("Args")) {
  140. OS << " << ReadArg<" << Arg->getValueAsString("Name") << ">(P, PC)";
  141. OS << " << \" \"";
  142. }
  143. OS << " << \"\\n\";\n";
  144. OS << " continue;\n";
  145. });
  146. OS << "#endif\n";
  147. }
  148. void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record *R) {
  149. if (R->getValueAsBit("HasCustomLink"))
  150. return;
  151. OS << "#ifdef GET_LINK_IMPL\n";
  152. Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
  153. auto Args = R->getValueAsListOfDefs("Args");
  154. // Emit the list of arguments.
  155. OS << "bool ByteCodeEmitter::emit" << ID << "(";
  156. for (size_t I = 0, N = Args.size(); I < N; ++I)
  157. OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
  158. OS << "const SourceInfo &L) {\n";
  159. // Emit a call to write the opcodes.
  160. OS << " return emitOp<";
  161. for (size_t I = 0, N = Args.size(); I < N; ++I) {
  162. if (I != 0)
  163. OS << ", ";
  164. OS << Args[I]->getValueAsString("Name");
  165. }
  166. OS << ">(OP_" << ID;
  167. for (size_t I = 0, N = Args.size(); I < N; ++I)
  168. OS << ", A" << I;
  169. OS << ", L);\n";
  170. OS << "}\n";
  171. });
  172. OS << "#endif\n";
  173. }
  174. void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) {
  175. OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
  176. auto Args = R->getValueAsListOfDefs("Args");
  177. Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) {
  178. OS << "bool emit" << ID << "(";
  179. for (auto *Arg : Args)
  180. OS << Arg->getValueAsString("Name") << ", ";
  181. OS << "const SourceInfo &);\n";
  182. });
  183. // Emit a template method for custom emitters to have less to implement.
  184. auto TypeCount = R->getValueAsListInit("Types")->size();
  185. if (R->getValueAsBit("HasCustomEval") && TypeCount) {
  186. OS << "#if defined(GET_EVAL_PROTO)\n";
  187. OS << "template<";
  188. for (size_t I = 0; I < TypeCount; ++I) {
  189. if (I != 0)
  190. OS << ", ";
  191. OS << "PrimType";
  192. }
  193. OS << ">\n";
  194. OS << "bool emit" << N << "(";
  195. for (auto *Arg : Args)
  196. OS << Arg->getValueAsString("Name") << ", ";
  197. OS << "const SourceInfo &);\n";
  198. OS << "#endif\n";
  199. }
  200. OS << "#endif\n";
  201. }
  202. void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) {
  203. if (!R->getValueAsBit("HasGroup"))
  204. return;
  205. auto *Types = R->getValueAsListInit("Types");
  206. auto Args = R->getValueAsListOfDefs("Args");
  207. // Emit the prototype of the group emitter in the header.
  208. OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
  209. OS << "bool emit" << N << "(";
  210. for (size_t I = 0, N = Types->size(); I < N; ++I)
  211. OS << "PrimType, ";
  212. for (auto *Arg : Args)
  213. OS << Arg->getValueAsString("Name") << ", ";
  214. OS << "const SourceInfo &I);\n";
  215. OS << "#endif\n";
  216. // Emit the dispatch implementation in the source.
  217. OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
  218. OS << "bool\n";
  219. OS << "#if defined(GET_EVAL_IMPL)\n";
  220. OS << "EvalEmitter\n";
  221. OS << "#else\n";
  222. OS << "ByteCodeEmitter\n";
  223. OS << "#endif\n";
  224. OS << "::emit" << N << "(";
  225. for (size_t I = 0, N = Types->size(); I < N; ++I)
  226. OS << "PrimType T" << I << ", ";
  227. for (size_t I = 0, N = Args.size(); I < N; ++I)
  228. OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
  229. OS << "const SourceInfo &I) {\n";
  230. std::function<void(size_t, const Twine &)> Rec;
  231. llvm::SmallVector<Record *, 2> TS;
  232. Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine &ID) {
  233. if (I >= Types->size()) {
  234. // Print a call to the emitter method.
  235. // Custom evaluator methods dispatch to template methods.
  236. if (R->getValueAsBit("HasCustomEval")) {
  237. OS << "#ifdef GET_LINK_IMPL\n";
  238. OS << " return emit" << ID << "\n";
  239. OS << "#else\n";
  240. OS << " return emit" << N;
  241. PrintTypes(OS, TS);
  242. OS << "\n#endif\n";
  243. OS << " ";
  244. } else {
  245. OS << " return emit" << ID;
  246. }
  247. OS << "(";
  248. for (size_t I = 0; I < Args.size(); ++I) {
  249. OS << "A" << I << ", ";
  250. }
  251. OS << "I);\n";
  252. return;
  253. }
  254. // Print a switch statement selecting T.
  255. if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
  256. OS << " switch (T" << I << ") {\n";
  257. auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
  258. for (auto *Case : Cases) {
  259. OS << " case PT_" << Case->getName() << ":\n";
  260. TS.push_back(Case);
  261. Rec(I + 1, ID + Case->getName());
  262. TS.pop_back();
  263. }
  264. // Emit a default case if not all types are present.
  265. if (Cases.size() < NumTypes)
  266. OS << " default: llvm_unreachable(\"invalid type\");\n";
  267. OS << " }\n";
  268. OS << " llvm_unreachable(\"invalid enum value\");\n";
  269. } else {
  270. PrintFatalError("Expected a type class");
  271. }
  272. };
  273. Rec(0, N);
  274. OS << "}\n";
  275. OS << "#endif\n";
  276. }
  277. void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) {
  278. if (R->getValueAsBit("HasCustomEval"))
  279. return;
  280. OS << "#ifdef GET_EVAL_IMPL\n";
  281. Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) {
  282. auto Args = R->getValueAsListOfDefs("Args");
  283. OS << "bool EvalEmitter::emit" << ID << "(";
  284. for (size_t I = 0, N = Args.size(); I < N; ++I)
  285. OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
  286. OS << "const SourceInfo &L) {\n";
  287. OS << " if (!isActive()) return true;\n";
  288. OS << " CurrentSource = L;\n";
  289. OS << " return " << N;
  290. PrintTypes(OS, TS);
  291. OS << "(S, OpPC";
  292. for (size_t I = 0, N = Args.size(); I < N; ++I)
  293. OS << ", A" << I;
  294. OS << ");\n";
  295. OS << "}\n";
  296. });
  297. OS << "#endif\n";
  298. }
  299. void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types) {
  300. if (Types.empty())
  301. return;
  302. OS << "<";
  303. for (size_t I = 0, N = Types.size(); I < N; ++I) {
  304. if (I != 0)
  305. OS << ", ";
  306. OS << "PT_" << Types[I]->getName();
  307. }
  308. OS << ">";
  309. }
  310. void clang::EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
  311. ClangOpcodesEmitter(Records).run(OS);
  312. }