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