xref: /llvm-project/llvm/lib/TableGen/DetailedRecordsBackend.cpp (revision 62e2c7fb2d18b43149a07526f6a3c0563d50e2fa)
1 //===- DetailedRecordBackend.cpp - Detailed Records Report      -*- 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 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.
12 //
13 //===----------------------------------------------------------------------===//
14 
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"
24 #include <string>
25 #include <utility>
26 
27 using namespace llvm;
28 
29 namespace {
30 
31 class DetailedRecordsEmitter {
32 private:
33   const RecordKeeper &Records;
34 
35 public:
36   explicit DetailedRecordsEmitter(const RecordKeeper &RK) : Records(RK) {}
37 
38   void run(raw_ostream &OS);
39   void printReportHeading(raw_ostream &OS);
40   void printSectionHeading(StringRef Title, int Count, raw_ostream &OS);
41   void printVariables(raw_ostream &OS);
42   void printClasses(raw_ostream &OS);
43   void printRecords(raw_ostream &OS);
44   void printAllocationStats(raw_ostream &OS);
45   void printDefms(const Record &Rec, raw_ostream &OS);
46   void printTemplateArgs(const Record &Rec, raw_ostream &OS);
47   void printSuperclasses(const Record &Rec, raw_ostream &OS);
48   void printFields(const Record &Rec, raw_ostream &OS);
49 }; // emitter class
50 
51 } // anonymous namespace
52 
53 // Print the report.
54 void DetailedRecordsEmitter::run(raw_ostream &OS) {
55   printReportHeading(OS);
56   printVariables(OS);
57   printClasses(OS);
58   printRecords(OS);
59   printAllocationStats(OS);
60 }
61 
62 // Print the report heading, including the source file name.
63 void DetailedRecordsEmitter::printReportHeading(raw_ostream &OS) {
64   OS << formatv("DETAILED RECORDS for file {0}\n", Records.getInputFilename());
65 }
66 
67 // Print a section heading with the name of the section and the item count.
68 void DetailedRecordsEmitter::printSectionHeading(StringRef Title, int Count,
69                                                  raw_ostream &OS) {
70   OS << formatv("\n{0} {1} ({2}) {0}\n", "--------------------", Title, Count);
71 }
72 
73 // Print the global variables.
74 void DetailedRecordsEmitter::printVariables(raw_ostream &OS) {
75   const auto GlobalList = Records.getGlobals();
76   printSectionHeading("Global Variables", GlobalList.size(), OS);
77 
78   OS << '\n';
79   for (const auto &Var : GlobalList)
80     OS << Var.first << " = " << Var.second->getAsString() << '\n';
81 }
82 
83 // Print classes, including the template arguments, superclasses, and fields.
84 void DetailedRecordsEmitter::printClasses(raw_ostream &OS) {
85   const auto &ClassList = Records.getClasses();
86   printSectionHeading("Classes", ClassList.size(), OS);
87 
88   for (const auto &[Name, Class] : ClassList) {
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);
94   }
95 }
96 
97 // Print the records, including the defm sequences, supercasses, and fields.
98 void DetailedRecordsEmitter::printRecords(raw_ostream &OS) {
99   const auto &RecordList = Records.getDefs();
100   printSectionHeading("Records", RecordList.size(), OS);
101 
102   for (const auto &[DefName, Rec] : RecordList) {
103     std::string Name = Rec->getNameInitAsString();
104     OS << formatv("\n{0}  |{1}|\n", Name.empty() ? "\"\"" : Name,
105                   SrcMgr.getFormattedLocationNoOffset(Rec->getLoc().front()));
106     printDefms(*Rec, OS);
107     printSuperclasses(*Rec, OS);
108     printFields(*Rec, OS);
109   }
110 }
111 
112 // Print memory allocation related stats.
113 void DetailedRecordsEmitter::printAllocationStats(raw_ostream &OS) {
114   OS << formatv("\n{0} Memory Allocation Stats {0}\n", "--------------------");
115   Records.dumpAllocationStats(OS);
116 }
117 
118 // Print the record's defm source locations, if any. Note that they
119 // are stored in the reverse order of their invocation.
120 void DetailedRecordsEmitter::printDefms(const Record &Rec, raw_ostream &OS) {
121   const auto &LocList = Rec.getLoc();
122   if (LocList.size() < 2)
123     return;
124 
125   OS << "  Defm sequence:";
126   for (const SMLoc Loc : reverse(LocList))
127     OS << formatv(" |{0}|", SrcMgr.getFormattedLocationNoOffset(Loc));
128   OS << '\n';
129 }
130 
131 // Print the template arguments of a class.
132 void DetailedRecordsEmitter::printTemplateArgs(const Record &Rec,
133                                                raw_ostream &OS) {
134   ArrayRef<const Init *> Args = Rec.getTemplateArgs();
135   if (Args.empty()) {
136     OS << "  Template args: (none)\n";
137     return;
138   }
139 
140   OS << "  Template args:\n";
141   for (const Init *ArgName : Args) {
142     const RecordVal *Value = Rec.getValue(ArgName);
143     assert(Value && "Template argument value not found.");
144     OS << "    ";
145     Value->print(OS, false);
146     OS << formatv("  |{0}|\n",
147                   SrcMgr.getFormattedLocationNoOffset(Value->getLoc()));
148   }
149 }
150 
151 // Print the superclasses of a class or record. Indirect superclasses
152 // are enclosed in parentheses.
153 void DetailedRecordsEmitter::printSuperclasses(const Record &Rec,
154                                                raw_ostream &OS) {
155   ArrayRef<std::pair<const Record *, SMRange>> Superclasses =
156       Rec.getSuperClasses();
157   if (Superclasses.empty()) {
158     OS << "  Superclasses: (none)\n";
159     return;
160   }
161 
162   OS << "  Superclasses:";
163   for (const auto &[ClassRec, Loc] : Superclasses) {
164     if (Rec.hasDirectSuperClass(ClassRec))
165       OS << formatv(" {0}", ClassRec->getNameInitAsString());
166     else
167       OS << formatv(" ({0})", ClassRec->getNameInitAsString());
168   }
169   OS << '\n';
170 }
171 
172 // Print the fields of a class or record, including their source locations.
173 void DetailedRecordsEmitter::printFields(const Record &Rec, raw_ostream &OS) {
174   const auto &ValueList = Rec.getValues();
175   if (ValueList.empty()) {
176     OS << "  Fields: (none)\n";
177     return;
178   }
179 
180   OS << "  Fields:\n";
181   for (const RecordVal &Value : ValueList)
182     if (!Rec.isTemplateArg(Value.getNameInit())) {
183       OS << "    ";
184       Value.print(OS, false);
185       OS << formatv("  |{0}|\n",
186                     SrcMgr.getFormattedLocationNoOffset(Value.getLoc()));
187     }
188 }
189 
190 // This function is called by TableGen after parsing the files.
191 void llvm::EmitDetailedRecords(const RecordKeeper &RK, raw_ostream &OS) {
192   // Instantiate the emitter class and invoke run().
193   DetailedRecordsEmitter(RK).run(OS);
194 }
195