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