Line data Source code
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 1 : JSONEmitter::JSONEmitter(RecordKeeper &R) : Records(R) {}
44 :
45 76 : 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 76 : if (isa<UnsetInit>(&I)) {
51 : return nullptr;
52 : } else if (auto *Bit = dyn_cast<BitInit>(&I)) {
53 11 : return Bit->getValue() ? 1 : 0;
54 : } else if (auto *Bits = dyn_cast<BitsInit>(&I)) {
55 : json::Array array;
56 35 : for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++)
57 60 : array.push_back(translateInit(*Bits->getBit(i)));
58 : return std::move(array);
59 : } else if (auto *Int = dyn_cast<IntInit>(&I)) {
60 14 : return Int->getValue();
61 : } else if (auto *Str = dyn_cast<StringInit>(&I)) {
62 2 : return Str->getValue();
63 : } else if (auto *Code = dyn_cast<CodeInit>(&I)) {
64 1 : return Code->getValue();
65 : } else if (auto *List = dyn_cast<ListInit>(&I)) {
66 : json::Array array;
67 5 : for (auto val : *List)
68 8 : 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 14 : obj["printable"] = I.getAsString();
79 :
80 : if (auto *Def = dyn_cast<DefInit>(&I)) {
81 4 : obj["kind"] = "def";
82 4 : obj["def"] = Def->getDef()->getName();
83 : return std::move(obj);
84 : } else if (auto *Var = dyn_cast<VarInit>(&I)) {
85 2 : obj["kind"] = "var";
86 2 : obj["var"] = Var->getName();
87 : return std::move(obj);
88 : } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) {
89 2 : if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) {
90 4 : obj["kind"] = "varbit";
91 4 : obj["var"] = Var->getName();
92 6 : obj["index"] = VarBit->getBitNum();
93 : return std::move(obj);
94 : }
95 : } else if (auto *Dag = dyn_cast<DagInit>(&I)) {
96 2 : obj["kind"] = "dag";
97 2 : obj["operator"] = translateInit(*Dag->getOperator());
98 1 : if (auto name = Dag->getName())
99 0 : obj["name"] = name->getAsUnquotedString();
100 : json::Array args;
101 3 : for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) {
102 : json::Array arg;
103 4 : arg.push_back(translateInit(*Dag->getArg(i)));
104 2 : if (auto argname = Dag->getArgName(i))
105 2 : arg.push_back(argname->getAsUnquotedString());
106 : else
107 1 : arg.push_back(nullptr);
108 2 : args.push_back(std::move(arg));
109 : }
110 2 : 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 2 : obj["kind"] = "complex";
120 : return std::move(obj);
121 : }
122 :
123 1 : void JSONEmitter::run(raw_ostream &OS) {
124 : json::Object root;
125 :
126 2 : 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 5 : for (const auto &C : Records.getClasses()) {
136 : auto &Name = C.second->getNameInitAsString();
137 4 : (void)instance_lists[Name];
138 : }
139 :
140 : // Main iteration over the defs.
141 13 : 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 51 : for (const RecordVal &RV : Def.getValues()) {
149 78 : if (!Def.isTemplateArg(RV.getNameInit())) {
150 : auto Name = RV.getNameInitAsString();
151 39 : if (RV.getPrefix())
152 6 : fields.push_back(Name);
153 117 : obj[Name] = translateInit(*RV.getValue());
154 : }
155 : }
156 :
157 24 : obj["!fields"] = std::move(fields);
158 :
159 : json::Array superclasses;
160 17 : for (const auto &SuperPair : Def.getSuperClasses())
161 10 : superclasses.push_back(SuperPair.first->getNameInitAsString());
162 24 : obj["!superclasses"] = std::move(superclasses);
163 :
164 24 : obj["!name"] = Name;
165 36 : obj["!anonymous"] = Def.isAnonymous();
166 :
167 24 : root[Name] = std::move(obj);
168 :
169 : // Add this def to the instance list for each of its superclasses.
170 17 : for (const auto &SuperPair : Def.getSuperClasses()) {
171 5 : auto SuperName = SuperPair.first->getNameInitAsString();
172 15 : 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 5 : for (auto kv: instance_lists)
179 8 : instanceof[kv.first] = std::move(kv.second);
180 2 : root["!instanceof"] = std::move(instanceof);
181 :
182 : // Done. Write the output.
183 2 : OS << json::Value(std::move(root)) << "\n";
184 1 : }
185 :
186 : namespace llvm {
187 :
188 1 : void EmitJSON(RecordKeeper &RK, raw_ostream &OS) { JSONEmitter(RK).run(OS); }
189 : } // end namespace llvm
|