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