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