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/StringRef.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/FormatVariadic.h"
19 #include "llvm/Support/SMLoc.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/TableGen/Error.h"
23 #include "llvm/TableGen/Record.h"
29 #define DEBUG_TYPE "detailed-records-backend"
37 class DetailedRecordsEmitter
{
39 RecordKeeper
&Records
;
42 DetailedRecordsEmitter(RecordKeeper
&RK
) : Records(RK
) {}
44 void run(raw_ostream
&OS
);
45 void printReportHeading(raw_ostream
&OS
);
46 void printVariables(raw_ostream
&OS
);
47 void printClasses(raw_ostream
&OS
);
48 void printRecords(raw_ostream
&OS
);
49 void printSectionHeading(StringRef Title
, int Count
, raw_ostream
&OS
);
50 void printDefms(Record
*Rec
, raw_ostream
&OS
);
51 void printTemplateArgs(Record
*Rec
, raw_ostream
&OS
);
52 void printSuperclasses(Record
*Rec
, raw_ostream
&OS
);
53 void printFields(Record
*Rec
, raw_ostream
&OS
);
56 } // anonymous namespace
59 void DetailedRecordsEmitter::run(raw_ostream
&OS
) {
60 printReportHeading(OS
);
66 // Print the report heading, including the source file name.
67 void DetailedRecordsEmitter::printReportHeading(raw_ostream
&OS
) {
68 OS
<< formatv("DETAILED RECORDS for file {0}\n", Records
.getInputFilename());
71 // Print the global variables.
72 void DetailedRecordsEmitter::printVariables(raw_ostream
&OS
) {
73 const auto GlobalList
= Records
.getGlobals();
74 printSectionHeading("Global Variables", GlobalList
.size(), OS
);
77 for (const auto &Var
: GlobalList
) {
78 OS
<< Var
.first
<< " = " << Var
.second
->getAsString() << NL
;
82 // Print the classes, including the template arguments, superclasses,
84 void DetailedRecordsEmitter::printClasses(raw_ostream
&OS
) {
85 const auto &ClassList
= Records
.getClasses();
86 printSectionHeading("Classes", ClassList
.size(), OS
);
88 for (const auto &ClassPair
: ClassList
) {
89 auto *const Class
= ClassPair
.second
.get();
90 OS
<< formatv("\n{0} |{1}|\n", Class
->getNameInitAsString(),
91 SrcMgr
.getFormattedLocationNoOffset(Class
->getLoc().front()));
92 printTemplateArgs(Class
, OS
);
93 printSuperclasses(Class
, OS
);
94 printFields(Class
, OS
);
98 // Print the records, including the defm sequences, supercasses,
100 void DetailedRecordsEmitter::printRecords(raw_ostream
&OS
) {
101 const auto &RecordList
= Records
.getDefs();
102 printSectionHeading("Records", RecordList
.size(), OS
);
104 for (const auto &RecPair
: RecordList
) {
105 auto *const Rec
= RecPair
.second
.get();
106 std::string Name
= Rec
->getNameInitAsString();
107 OS
<< formatv("\n{0} |{1}|\n", Name
.empty() ? "\"\"" : Name
,
108 SrcMgr
.getFormattedLocationNoOffset(Rec
->getLoc().front()));
110 printSuperclasses(Rec
, OS
);
111 printFields(Rec
, OS
);
115 // Print a section heading with the name of the section and
117 void DetailedRecordsEmitter::printSectionHeading(StringRef Title
, int Count
,
119 OS
<< formatv("\n{0} {1} ({2}) {0}\n", "--------------------", Title
, Count
);
122 // Print the record's defm source locations, if any. Note that they
123 // are stored in the reverse order of their invocation.
124 void DetailedRecordsEmitter::printDefms(Record
*Rec
, raw_ostream
&OS
) {
125 const auto &LocList
= Rec
->getLoc();
126 if (LocList
.size() < 2)
129 OS
<< " Defm sequence:";
130 for (unsigned I
= LocList
.size() - 1; I
>= 1; --I
) {
131 OS
<< formatv(" |{0}|", SrcMgr
.getFormattedLocationNoOffset(LocList
[I
]));
136 // Print the template arguments of a class.
137 void DetailedRecordsEmitter::printTemplateArgs(Record
*Rec
,
139 ArrayRef
<Init
*> Args
= Rec
->getTemplateArgs();
141 OS
<< " Template args: (none)\n";
145 OS
<< " Template args:\n";
146 for (const Init
*ArgName
: Args
) {
147 const RecordVal
*Value
= Rec
->getValue(ArgName
);
148 assert(Value
&& "Template argument value not found.");
150 Value
->print(OS
, false);
151 OS
<< formatv(" |{0}|", SrcMgr
.getFormattedLocationNoOffset(Value
->getLoc()));
156 // Print the superclasses of a class or record. Indirect superclasses
157 // are enclosed in parentheses.
158 void DetailedRecordsEmitter::printSuperclasses(Record
*Rec
, raw_ostream
&OS
) {
159 ArrayRef
<std::pair
<Record
*, SMRange
>> Superclasses
= Rec
->getSuperClasses();
160 if (Superclasses
.empty()) {
161 OS
<< " Superclasses: (none)\n";
165 OS
<< " Superclasses:";
166 for (const auto &SuperclassPair
: Superclasses
) {
167 auto *ClassRec
= SuperclassPair
.first
;
168 if (Rec
->hasDirectSuperClass(ClassRec
))
169 OS
<< formatv(" {0}", ClassRec
->getNameInitAsString());
171 OS
<< formatv(" ({0})", ClassRec
->getNameInitAsString());
176 // Print the fields of a class or record, including their source locations.
177 void DetailedRecordsEmitter::printFields(Record
*Rec
, raw_ostream
&OS
) {
178 const auto &ValueList
= Rec
->getValues();
179 if (ValueList
.empty()) {
180 OS
<< " Fields: (none)\n";
185 for (const RecordVal
&Value
: ValueList
)
186 if (!Rec
->isTemplateArg(Value
.getNameInit())) {
188 Value
.print(OS
, false);
189 OS
<< formatv(" |{0}|\n",
190 SrcMgr
.getFormattedLocationNoOffset(Value
.getLoc()));
196 // This function is called by TableGen after parsing the files.
198 void EmitDetailedRecords(RecordKeeper
&RK
, raw_ostream
&OS
) {
199 // Instantiate the emitter class and invoke run().
200 DetailedRecordsEmitter(RK
).run(OS
);