109467b48Spatrick //===- JSONBackend.cpp - Generate a JSON dump of all records. -*- C++ -*-=====//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This TableGen back end generates a machine-readable representation
1009467b48Spatrick // of all the classes and records defined by the input, in JSON format.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick
14*d415bd75Srobert #include "llvm/ADT/ArrayRef.h"
15*d415bd75Srobert #include "llvm/Support/Casting.h"
1609467b48Spatrick #include "llvm/Support/Debug.h"
17*d415bd75Srobert #include "llvm/Support/ErrorHandling.h"
1809467b48Spatrick #include "llvm/Support/JSON.h"
19*d415bd75Srobert #include "llvm/TableGen/Record.h"
2009467b48Spatrick
2109467b48Spatrick #define DEBUG_TYPE "json-emitter"
2209467b48Spatrick
2309467b48Spatrick using namespace llvm;
2409467b48Spatrick
2509467b48Spatrick namespace {
2609467b48Spatrick
2709467b48Spatrick class JSONEmitter {
2809467b48Spatrick private:
2909467b48Spatrick RecordKeeper &Records;
3009467b48Spatrick
3109467b48Spatrick json::Value translateInit(const Init &I);
3209467b48Spatrick
3309467b48Spatrick public:
3409467b48Spatrick JSONEmitter(RecordKeeper &R);
3509467b48Spatrick
3609467b48Spatrick void run(raw_ostream &OS);
3709467b48Spatrick };
3809467b48Spatrick
3909467b48Spatrick } // end anonymous namespace
4009467b48Spatrick
JSONEmitter(RecordKeeper & R)4109467b48Spatrick JSONEmitter::JSONEmitter(RecordKeeper &R) : Records(R) {}
4209467b48Spatrick
translateInit(const Init & I)4309467b48Spatrick json::Value JSONEmitter::translateInit(const Init &I) {
4409467b48Spatrick
4509467b48Spatrick // Init subclasses that we return as JSON primitive values of one
4609467b48Spatrick // kind or another.
4709467b48Spatrick
4809467b48Spatrick if (isa<UnsetInit>(&I)) {
4909467b48Spatrick return nullptr;
5009467b48Spatrick } else if (auto *Bit = dyn_cast<BitInit>(&I)) {
5109467b48Spatrick return Bit->getValue() ? 1 : 0;
5209467b48Spatrick } else if (auto *Bits = dyn_cast<BitsInit>(&I)) {
5309467b48Spatrick json::Array array;
5409467b48Spatrick for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++)
5509467b48Spatrick array.push_back(translateInit(*Bits->getBit(i)));
5609467b48Spatrick return std::move(array);
5709467b48Spatrick } else if (auto *Int = dyn_cast<IntInit>(&I)) {
5809467b48Spatrick return Int->getValue();
5909467b48Spatrick } else if (auto *Str = dyn_cast<StringInit>(&I)) {
6009467b48Spatrick return Str->getValue();
6109467b48Spatrick } else if (auto *List = dyn_cast<ListInit>(&I)) {
6209467b48Spatrick json::Array array;
63*d415bd75Srobert for (auto *val : *List)
6409467b48Spatrick array.push_back(translateInit(*val));
6509467b48Spatrick return std::move(array);
6609467b48Spatrick }
6709467b48Spatrick
6809467b48Spatrick // Init subclasses that we return as JSON objects containing a
6909467b48Spatrick // 'kind' discriminator. For these, we also provide the same
7009467b48Spatrick // translation back into TableGen input syntax that -print-records
7109467b48Spatrick // would give.
7209467b48Spatrick
7309467b48Spatrick json::Object obj;
7409467b48Spatrick obj["printable"] = I.getAsString();
7509467b48Spatrick
7609467b48Spatrick if (auto *Def = dyn_cast<DefInit>(&I)) {
7709467b48Spatrick obj["kind"] = "def";
7809467b48Spatrick obj["def"] = Def->getDef()->getName();
7909467b48Spatrick return std::move(obj);
8009467b48Spatrick } else if (auto *Var = dyn_cast<VarInit>(&I)) {
8109467b48Spatrick obj["kind"] = "var";
8209467b48Spatrick obj["var"] = Var->getName();
8309467b48Spatrick return std::move(obj);
8409467b48Spatrick } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) {
8509467b48Spatrick if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) {
8609467b48Spatrick obj["kind"] = "varbit";
8709467b48Spatrick obj["var"] = Var->getName();
8809467b48Spatrick obj["index"] = VarBit->getBitNum();
8909467b48Spatrick return std::move(obj);
9009467b48Spatrick }
9109467b48Spatrick } else if (auto *Dag = dyn_cast<DagInit>(&I)) {
9209467b48Spatrick obj["kind"] = "dag";
9309467b48Spatrick obj["operator"] = translateInit(*Dag->getOperator());
9409467b48Spatrick if (auto name = Dag->getName())
9509467b48Spatrick obj["name"] = name->getAsUnquotedString();
9609467b48Spatrick json::Array args;
9709467b48Spatrick for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) {
9809467b48Spatrick json::Array arg;
9909467b48Spatrick arg.push_back(translateInit(*Dag->getArg(i)));
10009467b48Spatrick if (auto argname = Dag->getArgName(i))
10109467b48Spatrick arg.push_back(argname->getAsUnquotedString());
10209467b48Spatrick else
10309467b48Spatrick arg.push_back(nullptr);
10409467b48Spatrick args.push_back(std::move(arg));
10509467b48Spatrick }
10609467b48Spatrick obj["args"] = std::move(args);
10709467b48Spatrick return std::move(obj);
10809467b48Spatrick }
10909467b48Spatrick
11009467b48Spatrick // Final fallback: anything that gets past here is simply given a
11109467b48Spatrick // kind field of 'complex', and the only other field is the standard
11209467b48Spatrick // 'printable' representation.
11309467b48Spatrick
11409467b48Spatrick assert(!I.isConcrete());
11509467b48Spatrick obj["kind"] = "complex";
11609467b48Spatrick return std::move(obj);
11709467b48Spatrick }
11809467b48Spatrick
run(raw_ostream & OS)11909467b48Spatrick void JSONEmitter::run(raw_ostream &OS) {
12009467b48Spatrick json::Object root;
12109467b48Spatrick
12209467b48Spatrick root["!tablegen_json_version"] = 1;
12309467b48Spatrick
12409467b48Spatrick // Prepare the arrays that will list the instances of every class.
12509467b48Spatrick // We mostly fill those in by iterating over the superclasses of
12609467b48Spatrick // each def, but we also want to ensure we store an empty list for a
12709467b48Spatrick // class with no instances at all, so we do a preliminary iteration
12809467b48Spatrick // over the classes, invoking std::map::operator[] to default-
12909467b48Spatrick // construct the array for each one.
13009467b48Spatrick std::map<std::string, json::Array> instance_lists;
13109467b48Spatrick for (const auto &C : Records.getClasses()) {
132*d415bd75Srobert const auto Name = C.second->getNameInitAsString();
13309467b48Spatrick (void)instance_lists[Name];
13409467b48Spatrick }
13509467b48Spatrick
13609467b48Spatrick // Main iteration over the defs.
13709467b48Spatrick for (const auto &D : Records.getDefs()) {
138*d415bd75Srobert const auto Name = D.second->getNameInitAsString();
13909467b48Spatrick auto &Def = *D.second;
14009467b48Spatrick
14109467b48Spatrick json::Object obj;
14209467b48Spatrick json::Array fields;
14309467b48Spatrick
14409467b48Spatrick for (const RecordVal &RV : Def.getValues()) {
14509467b48Spatrick if (!Def.isTemplateArg(RV.getNameInit())) {
14609467b48Spatrick auto Name = RV.getNameInitAsString();
14773471bf0Spatrick if (RV.isNonconcreteOK())
14809467b48Spatrick fields.push_back(Name);
14909467b48Spatrick obj[Name] = translateInit(*RV.getValue());
15009467b48Spatrick }
15109467b48Spatrick }
15209467b48Spatrick
15309467b48Spatrick obj["!fields"] = std::move(fields);
15409467b48Spatrick
15509467b48Spatrick json::Array superclasses;
15609467b48Spatrick for (const auto &SuperPair : Def.getSuperClasses())
15709467b48Spatrick superclasses.push_back(SuperPair.first->getNameInitAsString());
15809467b48Spatrick obj["!superclasses"] = std::move(superclasses);
15909467b48Spatrick
16009467b48Spatrick obj["!name"] = Name;
16109467b48Spatrick obj["!anonymous"] = Def.isAnonymous();
16209467b48Spatrick
16309467b48Spatrick root[Name] = std::move(obj);
16409467b48Spatrick
16509467b48Spatrick // Add this def to the instance list for each of its superclasses.
16609467b48Spatrick for (const auto &SuperPair : Def.getSuperClasses()) {
16709467b48Spatrick auto SuperName = SuperPair.first->getNameInitAsString();
16809467b48Spatrick instance_lists[SuperName].push_back(Name);
16909467b48Spatrick }
17009467b48Spatrick }
17109467b48Spatrick
17209467b48Spatrick // Make a JSON object from the std::map of instance lists.
17309467b48Spatrick json::Object instanceof;
17409467b48Spatrick for (auto kv: instance_lists)
17509467b48Spatrick instanceof[kv.first] = std::move(kv.second);
17609467b48Spatrick root["!instanceof"] = std::move(instanceof);
17709467b48Spatrick
17809467b48Spatrick // Done. Write the output.
17909467b48Spatrick OS << json::Value(std::move(root)) << "\n";
18009467b48Spatrick }
18109467b48Spatrick
18209467b48Spatrick namespace llvm {
18309467b48Spatrick
EmitJSON(RecordKeeper & RK,raw_ostream & OS)18409467b48Spatrick void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); }
18509467b48Spatrick } // end namespace llvm
186