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