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