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