1 //===- JSONBackend.cpp - Generate a JSON dump of all records. -*- 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 // This TableGen back end generates a machine-readable representation 10 // of all the classes and records defined by the input, in JSON format. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/BitVector.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/TableGen/Error.h" 17 #include "llvm/TableGen/Record.h" 18 #include "llvm/TableGen/TableGenBackend.h" 19 #include "llvm/Support/JSON.h" 20 21 #define DEBUG_TYPE "json-emitter" 22 23 using namespace llvm; 24 25 namespace { 26 27 class JSONEmitter { 28 private: 29 RecordKeeper &Records; 30 31 json::Value translateInit(const Init &I); 32 json::Array listSuperclasses(const Record &R); 33 34 public: 35 JSONEmitter(RecordKeeper &R); 36 37 void run(raw_ostream &OS); 38 }; 39 40 } // end anonymous namespace 41 42 JSONEmitter::JSONEmitter(RecordKeeper &R) : Records(R) {} 43 44 json::Value JSONEmitter::translateInit(const Init &I) { 45 46 // Init subclasses that we return as JSON primitive values of one 47 // kind or another. 48 49 if (isa<UnsetInit>(&I)) { 50 return nullptr; 51 } else if (auto *Bit = dyn_cast<BitInit>(&I)) { 52 return Bit->getValue() ? 1 : 0; 53 } else if (auto *Bits = dyn_cast<BitsInit>(&I)) { 54 json::Array array; 55 for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++) 56 array.push_back(translateInit(*Bits->getBit(i))); 57 return std::move(array); 58 } else if (auto *Int = dyn_cast<IntInit>(&I)) { 59 return Int->getValue(); 60 } else if (auto *Str = dyn_cast<StringInit>(&I)) { 61 return Str->getValue(); 62 } else if (auto *List = dyn_cast<ListInit>(&I)) { 63 json::Array array; 64 for (auto val : *List) 65 array.push_back(translateInit(*val)); 66 return std::move(array); 67 } 68 69 // Init subclasses that we return as JSON objects containing a 70 // 'kind' discriminator. For these, we also provide the same 71 // translation back into TableGen input syntax that -print-records 72 // would give. 73 74 json::Object obj; 75 obj["printable"] = I.getAsString(); 76 77 if (auto *Def = dyn_cast<DefInit>(&I)) { 78 obj["kind"] = "def"; 79 obj["def"] = Def->getDef()->getName(); 80 return std::move(obj); 81 } else if (auto *Var = dyn_cast<VarInit>(&I)) { 82 obj["kind"] = "var"; 83 obj["var"] = Var->getName(); 84 return std::move(obj); 85 } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) { 86 if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) { 87 obj["kind"] = "varbit"; 88 obj["var"] = Var->getName(); 89 obj["index"] = VarBit->getBitNum(); 90 return std::move(obj); 91 } 92 } else if (auto *Dag = dyn_cast<DagInit>(&I)) { 93 obj["kind"] = "dag"; 94 obj["operator"] = translateInit(*Dag->getOperator()); 95 if (auto name = Dag->getName()) 96 obj["name"] = name->getAsUnquotedString(); 97 json::Array args; 98 for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) { 99 json::Array arg; 100 arg.push_back(translateInit(*Dag->getArg(i))); 101 if (auto argname = Dag->getArgName(i)) 102 arg.push_back(argname->getAsUnquotedString()); 103 else 104 arg.push_back(nullptr); 105 args.push_back(std::move(arg)); 106 } 107 obj["args"] = std::move(args); 108 return std::move(obj); 109 } 110 111 // Final fallback: anything that gets past here is simply given a 112 // kind field of 'complex', and the only other field is the standard 113 // 'printable' representation. 114 115 assert(!I.isConcrete()); 116 obj["kind"] = "complex"; 117 return std::move(obj); 118 } 119 120 void JSONEmitter::run(raw_ostream &OS) { 121 json::Object root; 122 123 root["!tablegen_json_version"] = 1; 124 125 // Prepare the arrays that will list the instances of every class. 126 // We mostly fill those in by iterating over the superclasses of 127 // each def, but we also want to ensure we store an empty list for a 128 // class with no instances at all, so we do a preliminary iteration 129 // over the classes, invoking std::map::operator[] to default- 130 // construct the array for each one. 131 std::map<std::string, json::Array> instance_lists; 132 for (const auto &C : Records.getClasses()) { 133 auto &Name = C.second->getNameInitAsString(); 134 (void)instance_lists[Name]; 135 } 136 137 // Main iteration over the defs. 138 for (const auto &D : Records.getDefs()) { 139 auto &Name = D.second->getNameInitAsString(); 140 auto &Def = *D.second; 141 142 json::Object obj; 143 json::Array fields; 144 145 for (const RecordVal &RV : Def.getValues()) { 146 if (!Def.isTemplateArg(RV.getNameInit())) { 147 auto Name = RV.getNameInitAsString(); 148 if (RV.getPrefix()) 149 fields.push_back(Name); 150 obj[Name] = translateInit(*RV.getValue()); 151 } 152 } 153 154 obj["!fields"] = std::move(fields); 155 156 json::Array superclasses; 157 for (const auto &SuperPair : Def.getSuperClasses()) 158 superclasses.push_back(SuperPair.first->getNameInitAsString()); 159 obj["!superclasses"] = std::move(superclasses); 160 161 obj["!name"] = Name; 162 obj["!anonymous"] = Def.isAnonymous(); 163 164 root[Name] = std::move(obj); 165 166 // Add this def to the instance list for each of its superclasses. 167 for (const auto &SuperPair : Def.getSuperClasses()) { 168 auto SuperName = SuperPair.first->getNameInitAsString(); 169 instance_lists[SuperName].push_back(Name); 170 } 171 } 172 173 // Make a JSON object from the std::map of instance lists. 174 json::Object instanceof; 175 for (auto kv: instance_lists) 176 instanceof[kv.first] = std::move(kv.second); 177 root["!instanceof"] = std::move(instanceof); 178 179 // Done. Write the output. 180 OS << json::Value(std::move(root)) << "\n"; 181 } 182 183 namespace llvm { 184 185 void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); } 186 } // end namespace llvm 187