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/Support/Casting.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/Support/ErrorHandling.h" 17 #include "llvm/Support/JSON.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/Record.h" 20 21 #define DEBUG_TYPE "json-emitter" 22 23 using namespace llvm; 24 25 namespace { 26 27 class JSONEmitter { 28 private: 29 const RecordKeeper &Records; 30 31 json::Value translateInit(const Init &I); 32 33 public: 34 explicit JSONEmitter(const RecordKeeper &R) : Records(R) {} 35 36 void run(raw_ostream &OS); 37 }; 38 39 } // end anonymous namespace 40 41 json::Value JSONEmitter::translateInit(const Init &I) { 42 // Init subclasses that we return as JSON primitive values of one 43 // kind or another. 44 45 if (isa<UnsetInit>(&I)) 46 return nullptr; 47 if (const auto *Bit = dyn_cast<BitInit>(&I)) 48 return Bit->getValue() ? 1 : 0; 49 if (const auto *Bits = dyn_cast<BitsInit>(&I)) { 50 json::Array Array; 51 for (unsigned Idx = 0, E = Bits->getNumBits(); Idx < E; ++Idx) 52 Array.push_back(translateInit(*Bits->getBit(Idx))); 53 return std::move(Array); 54 } 55 if (const auto *Int = dyn_cast<IntInit>(&I)) 56 return Int->getValue(); 57 if (const auto *Str = dyn_cast<StringInit>(&I)) 58 return Str->getValue(); 59 if (const auto *List = dyn_cast<ListInit>(&I)) { 60 json::Array Array; 61 for (const auto *Val : *List) 62 Array.push_back(translateInit(*Val)); 63 return std::move(Array); 64 } 65 66 // Init subclasses that we return as JSON objects containing a 67 // 'kind' discriminator. For these, we also provide the same 68 // translation back into TableGen input syntax that -print-records 69 // would give. 70 71 json::Object Obj; 72 Obj["printable"] = I.getAsString(); 73 74 if (const auto *Def = dyn_cast<DefInit>(&I)) { 75 Obj["kind"] = "def"; 76 Obj["def"] = Def->getDef()->getName(); 77 return std::move(Obj); 78 } 79 if (const auto *Var = dyn_cast<VarInit>(&I)) { 80 Obj["kind"] = "var"; 81 Obj["var"] = Var->getName(); 82 return std::move(Obj); 83 } 84 if (const auto *VarBit = dyn_cast<VarBitInit>(&I)) { 85 if (const auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) { 86 Obj["kind"] = "varbit"; 87 Obj["var"] = Var->getName(); 88 Obj["index"] = VarBit->getBitNum(); 89 return std::move(Obj); 90 } 91 } 92 if (const 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 Idx = 0, E = Dag->getNumArgs(); Idx < E; ++Idx) { 99 json::Array Arg; 100 Arg.push_back(translateInit(*Dag->getArg(Idx))); 101 if (const auto ArgName = Dag->getArgName(Idx)) 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 assert(!I.isConcrete()); 115 Obj["kind"] = "complex"; 116 return std::move(Obj); 117 } 118 119 void JSONEmitter::run(raw_ostream &OS) { 120 json::Object Root; 121 122 Root["!tablegen_json_version"] = 1; 123 124 // Prepare the arrays that will list the instances of every class. 125 // We mostly fill those in by iterating over the superclasses of 126 // each def, but we also want to ensure we store an empty list for a 127 // class with no instances at all, so we do a preliminary iteration 128 // over the classes, invoking std::map::operator[] to default- 129 // construct the array for each one. 130 std::map<std::string, json::Array> InstanceLists; 131 for (const auto &[ClassName, ClassRec] : Records.getClasses()) 132 InstanceLists.emplace(ClassRec->getNameInitAsString(), json::Array()); 133 134 // Main iteration over the defs. 135 for (const auto &[DefName, Def] : Records.getDefs()) { 136 const std::string Name = Def->getNameInitAsString(); 137 138 json::Object Obj; 139 json::Array Fields; 140 141 for (const RecordVal &RV : Def->getValues()) { 142 if (!Def->isTemplateArg(RV.getNameInit())) { 143 auto Name = RV.getNameInitAsString(); 144 if (RV.isNonconcreteOK()) 145 Fields.push_back(Name); 146 Obj[Name] = translateInit(*RV.getValue()); 147 } 148 } 149 150 Obj["!fields"] = std::move(Fields); 151 152 json::Array SuperClasses; 153 // Add this def to the instance list for each of its superclasses. 154 for (const auto &[SuperClass, Loc] : Def->getSuperClasses()) { 155 std::string SuperName = SuperClass->getNameInitAsString(); 156 SuperClasses.push_back(SuperName); 157 InstanceLists[SuperName].push_back(Name); 158 } 159 160 Obj["!superclasses"] = std::move(SuperClasses); 161 162 Obj["!name"] = Name; 163 Obj["!anonymous"] = Def->isAnonymous(); 164 165 json::Array Locs; 166 for (const SMLoc Loc : Def->getLoc()) 167 Locs.push_back(SrcMgr.getFormattedLocationNoOffset(Loc)); 168 Obj["!locs"] = std::move(Locs); 169 170 Root[Name] = std::move(Obj); 171 } 172 173 // Make a JSON object from the std::map of instance lists. 174 json::Object InstanceOf; 175 for (auto &[ClassName, Instances] : InstanceLists) 176 InstanceOf[ClassName] = std::move(Instances); 177 Root["!instanceof"] = std::move(InstanceOf); 178 179 // Done. Write the output. 180 OS << json::Value(std::move(Root)) << "\n"; 181 } 182 183 void llvm::EmitJSON(const RecordKeeper &RK, raw_ostream &OS) { 184 JSONEmitter(RK).run(OS); 185 } 186