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 RecordKeeper &Records; 30 31 json::Value translateInit(const Init &I); 32 33 public: 34 JSONEmitter(RecordKeeper &R); 35 36 void run(raw_ostream &OS); 37 }; 38 39 } // end anonymous namespace 40 41 JSONEmitter::JSONEmitter(RecordKeeper &R) : Records(R) {} 42 43 json::Value JSONEmitter::translateInit(const Init &I) { 44 45 // Init subclasses that we return as JSON primitive values of one 46 // kind or another. 47 48 if (isa<UnsetInit>(&I)) { 49 return nullptr; 50 } else if (auto *Bit = dyn_cast<BitInit>(&I)) { 51 return Bit->getValue() ? 1 : 0; 52 } else if (auto *Bits = dyn_cast<BitsInit>(&I)) { 53 json::Array array; 54 for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++) 55 array.push_back(translateInit(*Bits->getBit(i))); 56 return std::move(array); 57 } else if (auto *Int = dyn_cast<IntInit>(&I)) { 58 return Int->getValue(); 59 } else if (auto *Str = dyn_cast<StringInit>(&I)) { 60 return Str->getValue(); 61 } else if (auto *List = dyn_cast<ListInit>(&I)) { 62 json::Array array; 63 for (auto *val : *List) 64 array.push_back(translateInit(*val)); 65 return std::move(array); 66 } 67 68 // Init subclasses that we return as JSON objects containing a 69 // 'kind' discriminator. For these, we also provide the same 70 // translation back into TableGen input syntax that -print-records 71 // would give. 72 73 json::Object obj; 74 obj["printable"] = I.getAsString(); 75 76 if (auto *Def = dyn_cast<DefInit>(&I)) { 77 obj["kind"] = "def"; 78 obj["def"] = Def->getDef()->getName(); 79 return std::move(obj); 80 } else if (auto *Var = dyn_cast<VarInit>(&I)) { 81 obj["kind"] = "var"; 82 obj["var"] = Var->getName(); 83 return std::move(obj); 84 } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) { 85 if (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 } else if (auto *Dag = dyn_cast<DagInit>(&I)) { 92 obj["kind"] = "dag"; 93 obj["operator"] = translateInit(*Dag->getOperator()); 94 if (auto name = Dag->getName()) 95 obj["name"] = name->getAsUnquotedString(); 96 json::Array args; 97 for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) { 98 json::Array arg; 99 arg.push_back(translateInit(*Dag->getArg(i))); 100 if (auto argname = Dag->getArgName(i)) 101 arg.push_back(argname->getAsUnquotedString()); 102 else 103 arg.push_back(nullptr); 104 args.push_back(std::move(arg)); 105 } 106 obj["args"] = std::move(args); 107 return std::move(obj); 108 } 109 110 // Final fallback: anything that gets past here is simply given a 111 // kind field of 'complex', and the only other field is the standard 112 // 'printable' representation. 113 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> instance_lists; 131 for (const auto &C : Records.getClasses()) { 132 const auto Name = C.second->getNameInitAsString(); 133 (void)instance_lists[Name]; 134 } 135 136 // Main iteration over the defs. 137 for (const auto &D : Records.getDefs()) { 138 const auto Name = D.second->getNameInitAsString(); 139 auto &Def = *D.second; 140 141 json::Object obj; 142 json::Array fields; 143 144 for (const RecordVal &RV : Def.getValues()) { 145 if (!Def.isTemplateArg(RV.getNameInit())) { 146 auto Name = RV.getNameInitAsString(); 147 if (RV.isNonconcreteOK()) 148 fields.push_back(Name); 149 obj[Name] = translateInit(*RV.getValue()); 150 } 151 } 152 153 obj["!fields"] = std::move(fields); 154 155 json::Array superclasses; 156 for (const auto &SuperPair : Def.getSuperClasses()) 157 superclasses.push_back(SuperPair.first->getNameInitAsString()); 158 obj["!superclasses"] = std::move(superclasses); 159 160 obj["!name"] = Name; 161 obj["!anonymous"] = Def.isAnonymous(); 162 163 json::Array locs; 164 for (const SMLoc Loc : Def.getLoc()) 165 locs.push_back(SrcMgr.getFormattedLocationNoOffset(Loc)); 166 obj["!locs"] = std::move(locs); 167 168 root[Name] = std::move(obj); 169 170 // Add this def to the instance list for each of its superclasses. 171 for (const auto &SuperPair : Def.getSuperClasses()) { 172 auto SuperName = SuperPair.first->getNameInitAsString(); 173 instance_lists[SuperName].push_back(Name); 174 } 175 } 176 177 // Make a JSON object from the std::map of instance lists. 178 json::Object instanceof; 179 for (auto kv: instance_lists) 180 instanceof[kv.first] = std::move(kv.second); 181 root["!instanceof"] = std::move(instanceof); 182 183 // Done. Write the output. 184 OS << json::Value(std::move(root)) << "\n"; 185 } 186 187 namespace llvm { 188 189 void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); } 190 } // end namespace llvm 191