1 //===- DetailedRecordBackend.cpp - Detailed Records Report -*- 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 backend prints a report that includes all the global
10 // variables, classes, and records in complete detail. It includes more
11 // detail than the default TableGen printer backend.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/TableGen/Error.h"
23 #include "llvm/TableGen/Record.h"
24 #include "llvm/TableGen/TableGenBackend.h"
28 #define DEBUG_TYPE "detailed-records-backend"
36 class DetailedRecordsEmitter
{
38 RecordKeeper
&Records
;
41 DetailedRecordsEmitter(RecordKeeper
&RK
) : Records(RK
) {}
43 void run(raw_ostream
&OS
);
44 void printReportHeading(raw_ostream
&OS
);
45 void printVariables(raw_ostream
&OS
);
46 void printClasses(raw_ostream
&OS
);
47 void printRecords(raw_ostream
&OS
);
48 void printSectionHeading(StringRef Title
, int Count
, raw_ostream
&OS
);
49 void printDefms(Record
*Rec
, raw_ostream
&OS
);
50 void printTemplateArgs(Record
*Rec
, raw_ostream
&OS
);
51 void printSuperclasses(Record
*Rec
, raw_ostream
&OS
);
52 void printFields(Record
*Rec
, raw_ostream
&OS
);
55 } // anonymous namespace
58 void DetailedRecordsEmitter::run(raw_ostream
&OS
) {
59 printReportHeading(OS
);
65 // Print the report heading, including the source file name.
66 void DetailedRecordsEmitter::printReportHeading(raw_ostream
&OS
) {
67 OS
<< formatv("DETAILED RECORDS for file {0}\n", Records
.getInputFilename());
70 // Print the global variables.
71 void DetailedRecordsEmitter::printVariables(raw_ostream
&OS
) {
72 const auto GlobalList
= Records
.getGlobals();
73 printSectionHeading("Global Variables", GlobalList
.size(), OS
);
76 for (const auto &Var
: GlobalList
) {
77 OS
<< Var
.first
<< " = " << Var
.second
->getAsString() << NL
;
81 // Print the classes, including the template arguments, superclasses,
83 void DetailedRecordsEmitter::printClasses(raw_ostream
&OS
) {
84 const auto &ClassList
= Records
.getClasses();
85 printSectionHeading("Classes", ClassList
.size(), OS
);
87 for (const auto &ClassPair
: ClassList
) {
88 auto *const Class
= ClassPair
.second
.get();
89 OS
<< formatv("\n{0} |{1}|\n", Class
->getNameInitAsString(),
90 SrcMgr
.getFormattedLocationNoOffset(Class
->getLoc().front()));
91 printTemplateArgs(Class
, OS
);
92 printSuperclasses(Class
, OS
);
93 printFields(Class
, OS
);
97 // Print the records, including the defm sequences, supercasses,
99 void DetailedRecordsEmitter::printRecords(raw_ostream
&OS
) {
100 const auto &RecordList
= Records
.getDefs();
101 printSectionHeading("Records", RecordList
.size(), OS
);
103 for (const auto &RecPair
: RecordList
) {
104 auto *const Rec
= RecPair
.second
.get();
105 std::string Name
= Rec
->getNameInitAsString();
106 OS
<< formatv("\n{0} |{1}|\n", Name
.empty() ? "\"\"" : Name
,
107 SrcMgr
.getFormattedLocationNoOffset(Rec
->getLoc().front()));
109 printSuperclasses(Rec
, OS
);
110 printFields(Rec
, OS
);
114 // Print a section heading with the name of the section and
116 void DetailedRecordsEmitter::printSectionHeading(StringRef Title
, int Count
,
118 OS
<< formatv("\n{0} {1} ({2}) {0}\n", "--------------------", Title
, Count
);
121 // Print the record's defm source locations, if any. Note that they
122 // are stored in the reverse order of their invocation.
123 void DetailedRecordsEmitter::printDefms(Record
*Rec
, raw_ostream
&OS
) {
124 const auto &LocList
= Rec
->getLoc();
125 if (LocList
.size() < 2)
128 OS
<< " Defm sequence:";
129 for (unsigned I
= LocList
.size() - 1; I
>= 1; --I
) {
130 OS
<< formatv(" |{0}|", SrcMgr
.getFormattedLocationNoOffset(LocList
[I
]));
135 // Print the template arguments of a class.
136 void DetailedRecordsEmitter::printTemplateArgs(Record
*Rec
,
138 ArrayRef
<Init
*> Args
= Rec
->getTemplateArgs();
140 OS
<< " Template args: (none)\n";
144 OS
<< " Template args:\n";
145 for (const Init
*ArgName
: Args
) {
146 const RecordVal
*Value
= Rec
->getValue(ArgName
);
147 assert(Value
&& "Template argument value not found.");
149 Value
->print(OS
, false);
150 OS
<< formatv(" |{0}|", SrcMgr
.getFormattedLocationNoOffset(Value
->getLoc()));
155 // Print the superclasses of a class or record. Indirect superclasses
156 // are enclosed in parentheses.
157 void DetailedRecordsEmitter::printSuperclasses(Record
*Rec
, raw_ostream
&OS
) {
158 ArrayRef
<std::pair
<Record
*, SMRange
>> Superclasses
= Rec
->getSuperClasses();
159 if (Superclasses
.empty()) {
160 OS
<< " Superclasses: (none)\n";
164 OS
<< " Superclasses:";
165 for (const auto &SuperclassPair
: Superclasses
) {
166 auto *ClassRec
= SuperclassPair
.first
;
167 if (Rec
->hasDirectSuperClass(ClassRec
))
168 OS
<< formatv(" {0}", ClassRec
->getNameInitAsString());
170 OS
<< formatv(" ({0})", ClassRec
->getNameInitAsString());
175 // Print the fields of a class or record, including their source locations.
176 void DetailedRecordsEmitter::printFields(Record
*Rec
, raw_ostream
&OS
) {
177 const auto &ValueList
= Rec
->getValues();
178 if (ValueList
.empty()) {
179 OS
<< " Fields: (none)\n";
184 for (const RecordVal
&Value
: ValueList
)
185 if (!Rec
->isTemplateArg(Value
.getNameInit())) {
187 Value
.print(OS
, false);
188 OS
<< formatv(" |{0}|\n",
189 SrcMgr
.getFormattedLocationNoOffset(Value
.getLoc()));
195 // This function is called by TableGen after parsing the files.
197 void EmitDetailedRecords(RecordKeeper
&RK
, raw_ostream
&OS
) {
198 // Instantiate the emitter class and invoke run().
199 DetailedRecordsEmitter(RK
).run(OS
);