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