LLVM  8.0.1
JSONBackend.cpp
Go to the documentation of this file.
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"
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
uint64_t CallInst * C
An Object is a JSON object, which maps strings to heterogenous JSON values.
Definition: JSON.h:88
This class represents lattice values for constants.
Definition: AllocatorList.h:24
An Array is a JSON array, which contains heterogeneous JSON values.
Definition: JSON.h:152
void push_back(const Value &E)
Definition: JSON.h:185
amdgpu Simplify well known AMD library false Value Value const Twine & Name
A Value is an JSON value of unknown type.
Definition: JSON.h:277
virtual bool isConcrete() const
Is this a concrete and fully resolved value without any references or stuck operations? Unset values are concrete.
Definition: Record.h:356
void EmitJSON(RecordKeeper &RK, raw_ostream &OS)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
const NodeList & List
Definition: RDFGraph.cpp:210
#define I(x, y, z)
Definition: MD5.cpp:58
This file supports working with JSON data.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
virtual std::string getAsString() const =0
Convert this value to a string form.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46