1 //===- JSONBackend.cpp - Generate a JSON dump of all records. -*- C++ -*-=====//
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
7 //===----------------------------------------------------------------------===//
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/Error.h"
19 #include "llvm/TableGen/Record.h"
21 #define DEBUG_TYPE "json-emitter"
29 const RecordKeeper
&Records
;
31 json::Value
translateInit(const Init
&I
);
34 explicit JSONEmitter(const RecordKeeper
&R
) : Records(R
) {}
36 void run(raw_ostream
&OS
);
39 } // end anonymous namespace
41 json::Value
JSONEmitter::translateInit(const Init
&I
) {
42 // Init subclasses that we return as JSON primitive values of one
45 if (isa
<UnsetInit
>(&I
))
47 if (const auto *Bit
= dyn_cast
<BitInit
>(&I
))
48 return Bit
->getValue() ? 1 : 0;
49 if (const auto *Bits
= dyn_cast
<BitsInit
>(&I
)) {
51 for (unsigned Idx
= 0, E
= Bits
->getNumBits(); Idx
< E
; ++Idx
)
52 Array
.push_back(translateInit(*Bits
->getBit(Idx
)));
53 return std::move(Array
);
55 if (const auto *Int
= dyn_cast
<IntInit
>(&I
))
56 return Int
->getValue();
57 if (const auto *Str
= dyn_cast
<StringInit
>(&I
))
58 return Str
->getValue();
59 if (const auto *List
= dyn_cast
<ListInit
>(&I
)) {
61 for (const auto *Val
: *List
)
62 Array
.push_back(translateInit(*Val
));
63 return std::move(Array
);
66 // Init subclasses that we return as JSON objects containing a
67 // 'kind' discriminator. For these, we also provide the same
68 // translation back into TableGen input syntax that -print-records
72 Obj
["printable"] = I
.getAsString();
74 if (const auto *Def
= dyn_cast
<DefInit
>(&I
)) {
76 Obj
["def"] = Def
->getDef()->getName();
77 return std::move(Obj
);
79 if (const auto *Var
= dyn_cast
<VarInit
>(&I
)) {
81 Obj
["var"] = Var
->getName();
82 return std::move(Obj
);
84 if (const auto *VarBit
= dyn_cast
<VarBitInit
>(&I
)) {
85 if (const auto *Var
= dyn_cast
<VarInit
>(VarBit
->getBitVar())) {
86 Obj
["kind"] = "varbit";
87 Obj
["var"] = Var
->getName();
88 Obj
["index"] = VarBit
->getBitNum();
89 return std::move(Obj
);
92 if (const auto *Dag
= dyn_cast
<DagInit
>(&I
)) {
94 Obj
["operator"] = translateInit(*Dag
->getOperator());
95 if (auto name
= Dag
->getName())
96 Obj
["name"] = name
->getAsUnquotedString();
98 for (unsigned Idx
= 0, E
= Dag
->getNumArgs(); Idx
< E
; ++Idx
) {
100 Arg
.push_back(translateInit(*Dag
->getArg(Idx
)));
101 if (const auto ArgName
= Dag
->getArgName(Idx
))
102 Arg
.push_back(ArgName
->getAsUnquotedString());
104 Arg
.push_back(nullptr);
105 Args
.push_back(std::move(Arg
));
107 Obj
["args"] = std::move(Args
);
108 return std::move(Obj
);
111 // Final fallback: anything that gets past here is simply given a
112 // kind field of 'complex', and the only other field is the standard
113 // 'printable' representation.
114 assert(!I
.isConcrete());
115 Obj
["kind"] = "complex";
116 return std::move(Obj
);
119 void JSONEmitter::run(raw_ostream
&OS
) {
122 Root
["!tablegen_json_version"] = 1;
124 // Prepare the arrays that will list the instances of every class.
125 // We mostly fill those in by iterating over the superclasses of
126 // each def, but we also want to ensure we store an empty list for a
127 // class with no instances at all, so we do a preliminary iteration
128 // over the classes, invoking std::map::operator[] to default-
129 // construct the array for each one.
130 std::map
<std::string
, json::Array
> InstanceLists
;
131 for (const auto &[ClassName
, ClassRec
] : Records
.getClasses())
132 InstanceLists
.emplace(ClassRec
->getNameInitAsString(), json::Array());
134 // Main iteration over the defs.
135 for (const auto &[DefName
, Def
] : Records
.getDefs()) {
136 const std::string Name
= Def
->getNameInitAsString();
141 for (const RecordVal
&RV
: Def
->getValues()) {
142 if (!Def
->isTemplateArg(RV
.getNameInit())) {
143 auto Name
= RV
.getNameInitAsString();
144 if (RV
.isNonconcreteOK())
145 Fields
.push_back(Name
);
146 Obj
[Name
] = translateInit(*RV
.getValue());
150 Obj
["!fields"] = std::move(Fields
);
152 json::Array SuperClasses
;
153 // Add this def to the instance list for each of its superclasses.
154 for (const auto &[SuperClass
, Loc
] : Def
->getSuperClasses()) {
155 std::string SuperName
= SuperClass
->getNameInitAsString();
156 SuperClasses
.push_back(SuperName
);
157 InstanceLists
[SuperName
].push_back(Name
);
160 Obj
["!superclasses"] = std::move(SuperClasses
);
163 Obj
["!anonymous"] = Def
->isAnonymous();
166 for (const SMLoc Loc
: Def
->getLoc())
167 Locs
.push_back(SrcMgr
.getFormattedLocationNoOffset(Loc
));
168 Obj
["!locs"] = std::move(Locs
);
170 Root
[Name
] = std::move(Obj
);
173 // Make a JSON object from the std::map of instance lists.
174 json::Object InstanceOf
;
175 for (auto &[ClassName
, Instances
] : InstanceLists
)
176 InstanceOf
[ClassName
] = std::move(Instances
);
177 Root
["!instanceof"] = std::move(InstanceOf
);
179 // Done. Write the output.
180 OS
<< json::Value(std::move(Root
)) << "\n";
183 void llvm::EmitJSON(const RecordKeeper
&RK
, raw_ostream
&OS
) {
184 JSONEmitter(RK
).run(OS
);