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