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