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