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 *Code = dyn_cast<CodeInit>(&I)) { 63 return Code->getValue(); 64 } else if (auto *List = dyn_cast<ListInit>(&I)) { 65 json::Array array; 66 for (auto val : *List) 67 array.push_back(translateInit(*val)); 68 return std::move(array); 69 } 70 71 // Init subclasses that we return as JSON objects containing a 72 // 'kind' discriminator. For these, we also provide the same 73 // translation back into TableGen input syntax that -print-records 74 // would give. 75 76 json::Object obj; 77 obj["printable"] = I.getAsString(); 78 79 if (auto *Def = dyn_cast<DefInit>(&I)) { 80 obj["kind"] = "def"; 81 obj["def"] = Def->getDef()->getName(); 82 return std::move(obj); 83 } else if (auto *Var = dyn_cast<VarInit>(&I)) { 84 obj["kind"] = "var"; 85 obj["var"] = Var->getName(); 86 return std::move(obj); 87 } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) { 88 if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) { 89 obj["kind"] = "varbit"; 90 obj["var"] = Var->getName(); 91 obj["index"] = VarBit->getBitNum(); 92 return std::move(obj); 93 } 94 } else if (auto *Dag = dyn_cast<DagInit>(&I)) { 95 obj["kind"] = "dag"; 96 obj["operator"] = translateInit(*Dag->getOperator()); 97 if (auto name = Dag->getName()) 98 obj["name"] = name->getAsUnquotedString(); 99 json::Array args; 100 for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) { 101 json::Array arg; 102 arg.push_back(translateInit(*Dag->getArg(i))); 103 if (auto argname = Dag->getArgName(i)) 104 arg.push_back(argname->getAsUnquotedString()); 105 else 106 arg.push_back(nullptr); 107 args.push_back(std::move(arg)); 108 } 109 obj["args"] = std::move(args); 110 return std::move(obj); 111 } 112 113 // Final fallback: anything that gets past here is simply given a 114 // kind field of 'complex', and the only other field is the standard 115 // 'printable' representation. 116 117 assert(!I.isConcrete()); 118 obj["kind"] = "complex"; 119 return std::move(obj); 120 } 121 122 void JSONEmitter::run(raw_ostream &OS) { 123 json::Object root; 124 125 root["!tablegen_json_version"] = 1; 126 127 // Prepare the arrays that will list the instances of every class. 128 // We mostly fill those in by iterating over the superclasses of 129 // each def, but we also want to ensure we store an empty list for a 130 // class with no instances at all, so we do a preliminary iteration 131 // over the classes, invoking std::map::operator[] to default- 132 // construct the array for each one. 133 std::map<std::string, json::Array> instance_lists; 134 for (const auto &C : Records.getClasses()) { 135 auto &Name = C.second->getNameInitAsString(); 136 (void)instance_lists[Name]; 137 } 138 139 // Main iteration over the defs. 140 for (const auto &D : Records.getDefs()) { 141 auto &Name = D.second->getNameInitAsString(); 142 auto &Def = *D.second; 143 144 json::Object obj; 145 json::Array fields; 146 147 for (const RecordVal &RV : Def.getValues()) { 148 if (!Def.isTemplateArg(RV.getNameInit())) { 149 auto Name = RV.getNameInitAsString(); 150 if (RV.getPrefix()) 151 fields.push_back(Name); 152 obj[Name] = translateInit(*RV.getValue()); 153 } 154 } 155 156 obj["!fields"] = std::move(fields); 157 158 json::Array superclasses; 159 for (const auto &SuperPair : Def.getSuperClasses()) 160 superclasses.push_back(SuperPair.first->getNameInitAsString()); 161 obj["!superclasses"] = std::move(superclasses); 162 163 obj["!name"] = Name; 164 obj["!anonymous"] = Def.isAnonymous(); 165 166 root[Name] = std::move(obj); 167 168 // Add this def to the instance list for each of its superclasses. 169 for (const auto &SuperPair : Def.getSuperClasses()) { 170 auto SuperName = SuperPair.first->getNameInitAsString(); 171 instance_lists[SuperName].push_back(Name); 172 } 173 } 174 175 // Make a JSON object from the std::map of instance lists. 176 json::Object instanceof; 177 for (auto kv: instance_lists) 178 instanceof[kv.first] = std::move(kv.second); 179 root["!instanceof"] = std::move(instanceof); 180 181 // Done. Write the output. 182 OS << json::Value(std::move(root)) << "\n"; 183 } 184 185 namespace llvm { 186 187 void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); } 188 } // end namespace llvm 189