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