10c1bb4f8SPaul C. Anagnostopoulos //===- DetailedRecordBackend.cpp - Detailed Records Report -*- C++ -*-===// 20c1bb4f8SPaul C. Anagnostopoulos // 30c1bb4f8SPaul C. Anagnostopoulos // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40c1bb4f8SPaul C. Anagnostopoulos // See https://llvm.org/LICENSE.txt for license information. 50c1bb4f8SPaul C. Anagnostopoulos // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60c1bb4f8SPaul C. Anagnostopoulos // 70c1bb4f8SPaul C. Anagnostopoulos //===----------------------------------------------------------------------===// 80c1bb4f8SPaul C. Anagnostopoulos // 90c1bb4f8SPaul C. Anagnostopoulos // This Tablegen backend prints a report that includes all the global 100c1bb4f8SPaul C. Anagnostopoulos // variables, classes, and records in complete detail. It includes more 110c1bb4f8SPaul C. Anagnostopoulos // detail than the default TableGen printer backend. 120c1bb4f8SPaul C. Anagnostopoulos // 130c1bb4f8SPaul C. Anagnostopoulos //===----------------------------------------------------------------------===// 140c1bb4f8SPaul C. Anagnostopoulos 150c1bb4f8SPaul C. Anagnostopoulos #include "llvm/ADT/ArrayRef.h" 1692f49b89Sserge-sans-paille #include "llvm/ADT/StringRef.h" 1792f49b89Sserge-sans-paille #include "llvm/Support/ErrorHandling.h" 180c1bb4f8SPaul C. Anagnostopoulos #include "llvm/Support/FormatVariadic.h" 1992f49b89Sserge-sans-paille #include "llvm/Support/SMLoc.h" 200c1bb4f8SPaul C. Anagnostopoulos #include "llvm/Support/SourceMgr.h" 2192f49b89Sserge-sans-paille #include "llvm/Support/raw_ostream.h" 220c1bb4f8SPaul C. Anagnostopoulos #include "llvm/TableGen/Error.h" 230c1bb4f8SPaul C. Anagnostopoulos #include "llvm/TableGen/Record.h" 240c1bb4f8SPaul C. Anagnostopoulos #include <string> 25a03d09f4SSimon Pilgrim #include <utility> 260c1bb4f8SPaul C. Anagnostopoulos 270c1bb4f8SPaul C. Anagnostopoulos using namespace llvm; 280c1bb4f8SPaul C. Anagnostopoulos 290c1bb4f8SPaul C. Anagnostopoulos namespace { 300c1bb4f8SPaul C. Anagnostopoulos 310c1bb4f8SPaul C. Anagnostopoulos class DetailedRecordsEmitter { 320c1bb4f8SPaul C. Anagnostopoulos private: 33bcde45baSRahul Joshi const RecordKeeper &Records; 340c1bb4f8SPaul C. Anagnostopoulos 350c1bb4f8SPaul C. Anagnostopoulos public: 36bcde45baSRahul Joshi explicit DetailedRecordsEmitter(const RecordKeeper &RK) : Records(RK) {} 370c1bb4f8SPaul C. Anagnostopoulos 380c1bb4f8SPaul C. Anagnostopoulos void run(raw_ostream &OS); 390c1bb4f8SPaul C. Anagnostopoulos void printReportHeading(raw_ostream &OS); 40bcde45baSRahul Joshi void printSectionHeading(StringRef Title, int Count, raw_ostream &OS); 410c1bb4f8SPaul C. Anagnostopoulos void printVariables(raw_ostream &OS); 420c1bb4f8SPaul C. Anagnostopoulos void printClasses(raw_ostream &OS); 430c1bb4f8SPaul C. Anagnostopoulos void printRecords(raw_ostream &OS); 4430f1cfb4SRahul Joshi void printAllocationStats(raw_ostream &OS); 45bcde45baSRahul Joshi void printDefms(const Record &Rec, raw_ostream &OS); 46bcde45baSRahul Joshi void printTemplateArgs(const Record &Rec, raw_ostream &OS); 47bcde45baSRahul Joshi void printSuperclasses(const Record &Rec, raw_ostream &OS); 48bcde45baSRahul Joshi void printFields(const Record &Rec, raw_ostream &OS); 490c1bb4f8SPaul C. Anagnostopoulos }; // emitter class 500c1bb4f8SPaul C. Anagnostopoulos 510c1bb4f8SPaul C. Anagnostopoulos } // anonymous namespace 520c1bb4f8SPaul C. Anagnostopoulos 530c1bb4f8SPaul C. Anagnostopoulos // Print the report. 540c1bb4f8SPaul C. Anagnostopoulos void DetailedRecordsEmitter::run(raw_ostream &OS) { 550c1bb4f8SPaul C. Anagnostopoulos printReportHeading(OS); 560c1bb4f8SPaul C. Anagnostopoulos printVariables(OS); 570c1bb4f8SPaul C. Anagnostopoulos printClasses(OS); 580c1bb4f8SPaul C. Anagnostopoulos printRecords(OS); 5930f1cfb4SRahul Joshi printAllocationStats(OS); 600c1bb4f8SPaul C. Anagnostopoulos } 610c1bb4f8SPaul C. Anagnostopoulos 620c1bb4f8SPaul C. Anagnostopoulos // Print the report heading, including the source file name. 630c1bb4f8SPaul C. Anagnostopoulos void DetailedRecordsEmitter::printReportHeading(raw_ostream &OS) { 640c1bb4f8SPaul C. Anagnostopoulos OS << formatv("DETAILED RECORDS for file {0}\n", Records.getInputFilename()); 650c1bb4f8SPaul C. Anagnostopoulos } 660c1bb4f8SPaul C. Anagnostopoulos 6730f1cfb4SRahul Joshi // Print a section heading with the name of the section and the item count. 68bcde45baSRahul Joshi void DetailedRecordsEmitter::printSectionHeading(StringRef Title, int Count, 69bcde45baSRahul Joshi raw_ostream &OS) { 70bcde45baSRahul Joshi OS << formatv("\n{0} {1} ({2}) {0}\n", "--------------------", Title, Count); 71bcde45baSRahul Joshi } 72bcde45baSRahul Joshi 730c1bb4f8SPaul C. Anagnostopoulos // Print the global variables. 740c1bb4f8SPaul C. Anagnostopoulos void DetailedRecordsEmitter::printVariables(raw_ostream &OS) { 750c1bb4f8SPaul C. Anagnostopoulos const auto GlobalList = Records.getGlobals(); 760c1bb4f8SPaul C. Anagnostopoulos printSectionHeading("Global Variables", GlobalList.size(), OS); 770c1bb4f8SPaul C. Anagnostopoulos 78bcde45baSRahul Joshi OS << '\n'; 79bcde45baSRahul Joshi for (const auto &Var : GlobalList) 80bcde45baSRahul Joshi OS << Var.first << " = " << Var.second->getAsString() << '\n'; 810c1bb4f8SPaul C. Anagnostopoulos } 820c1bb4f8SPaul C. Anagnostopoulos 8330f1cfb4SRahul Joshi // Print classes, including the template arguments, superclasses, and fields. 840c1bb4f8SPaul C. Anagnostopoulos void DetailedRecordsEmitter::printClasses(raw_ostream &OS) { 850c1bb4f8SPaul C. Anagnostopoulos const auto &ClassList = Records.getClasses(); 860c1bb4f8SPaul C. Anagnostopoulos printSectionHeading("Classes", ClassList.size(), OS); 870c1bb4f8SPaul C. Anagnostopoulos 88bcde45baSRahul Joshi for (const auto &[Name, Class] : ClassList) { 890c1bb4f8SPaul C. Anagnostopoulos OS << formatv("\n{0} |{1}|\n", Class->getNameInitAsString(), 900c1bb4f8SPaul C. Anagnostopoulos SrcMgr.getFormattedLocationNoOffset(Class->getLoc().front())); 91bcde45baSRahul Joshi printTemplateArgs(*Class, OS); 92bcde45baSRahul Joshi printSuperclasses(*Class, OS); 93bcde45baSRahul Joshi printFields(*Class, OS); 940c1bb4f8SPaul C. Anagnostopoulos } 950c1bb4f8SPaul C. Anagnostopoulos } 960c1bb4f8SPaul C. Anagnostopoulos 9730f1cfb4SRahul Joshi // Print the records, including the defm sequences, supercasses, and fields. 980c1bb4f8SPaul C. Anagnostopoulos void DetailedRecordsEmitter::printRecords(raw_ostream &OS) { 990c1bb4f8SPaul C. Anagnostopoulos const auto &RecordList = Records.getDefs(); 1000c1bb4f8SPaul C. Anagnostopoulos printSectionHeading("Records", RecordList.size(), OS); 1010c1bb4f8SPaul C. Anagnostopoulos 102bcde45baSRahul Joshi for (const auto &[DefName, Rec] : RecordList) { 103f3449ed6SPaul C. Anagnostopoulos std::string Name = Rec->getNameInitAsString(); 104f3449ed6SPaul C. Anagnostopoulos OS << formatv("\n{0} |{1}|\n", Name.empty() ? "\"\"" : Name, 1050c1bb4f8SPaul C. Anagnostopoulos SrcMgr.getFormattedLocationNoOffset(Rec->getLoc().front())); 106bcde45baSRahul Joshi printDefms(*Rec, OS); 107bcde45baSRahul Joshi printSuperclasses(*Rec, OS); 108bcde45baSRahul Joshi printFields(*Rec, OS); 1090c1bb4f8SPaul C. Anagnostopoulos } 1100c1bb4f8SPaul C. Anagnostopoulos } 1110c1bb4f8SPaul C. Anagnostopoulos 11230f1cfb4SRahul Joshi // Print memory allocation related stats. 11330f1cfb4SRahul Joshi void DetailedRecordsEmitter::printAllocationStats(raw_ostream &OS) { 11430f1cfb4SRahul Joshi OS << formatv("\n{0} Memory Allocation Stats {0}\n", "--------------------"); 11530f1cfb4SRahul Joshi Records.dumpAllocationStats(OS); 11630f1cfb4SRahul Joshi } 11730f1cfb4SRahul Joshi 1180c1bb4f8SPaul C. Anagnostopoulos // Print the record's defm source locations, if any. Note that they 1190c1bb4f8SPaul C. Anagnostopoulos // are stored in the reverse order of their invocation. 120bcde45baSRahul Joshi void DetailedRecordsEmitter::printDefms(const Record &Rec, raw_ostream &OS) { 121bcde45baSRahul Joshi const auto &LocList = Rec.getLoc(); 1220c1bb4f8SPaul C. Anagnostopoulos if (LocList.size() < 2) 1230c1bb4f8SPaul C. Anagnostopoulos return; 1240c1bb4f8SPaul C. Anagnostopoulos 1250c1bb4f8SPaul C. Anagnostopoulos OS << " Defm sequence:"; 126bcde45baSRahul Joshi for (const SMLoc Loc : reverse(LocList)) 127bcde45baSRahul Joshi OS << formatv(" |{0}|", SrcMgr.getFormattedLocationNoOffset(Loc)); 128bcde45baSRahul Joshi OS << '\n'; 1290c1bb4f8SPaul C. Anagnostopoulos } 1300c1bb4f8SPaul C. Anagnostopoulos 1310c1bb4f8SPaul C. Anagnostopoulos // Print the template arguments of a class. 132bcde45baSRahul Joshi void DetailedRecordsEmitter::printTemplateArgs(const Record &Rec, 1330c1bb4f8SPaul C. Anagnostopoulos raw_ostream &OS) { 134*62e2c7fbSRahul Joshi ArrayRef<const Init *> Args = Rec.getTemplateArgs(); 1350c1bb4f8SPaul C. Anagnostopoulos if (Args.empty()) { 1360c1bb4f8SPaul C. Anagnostopoulos OS << " Template args: (none)\n"; 1370c1bb4f8SPaul C. Anagnostopoulos return; 1380c1bb4f8SPaul C. Anagnostopoulos } 1390c1bb4f8SPaul C. Anagnostopoulos 1400c1bb4f8SPaul C. Anagnostopoulos OS << " Template args:\n"; 1410c1bb4f8SPaul C. Anagnostopoulos for (const Init *ArgName : Args) { 142bcde45baSRahul Joshi const RecordVal *Value = Rec.getValue(ArgName); 1430c1bb4f8SPaul C. Anagnostopoulos assert(Value && "Template argument value not found."); 1440c1bb4f8SPaul C. Anagnostopoulos OS << " "; 1450c1bb4f8SPaul C. Anagnostopoulos Value->print(OS, false); 146bcde45baSRahul Joshi OS << formatv(" |{0}|\n", 147bcde45baSRahul Joshi SrcMgr.getFormattedLocationNoOffset(Value->getLoc())); 1480c1bb4f8SPaul C. Anagnostopoulos } 1490c1bb4f8SPaul C. Anagnostopoulos } 1500c1bb4f8SPaul C. Anagnostopoulos 1510c1bb4f8SPaul C. Anagnostopoulos // Print the superclasses of a class or record. Indirect superclasses 1520c1bb4f8SPaul C. Anagnostopoulos // are enclosed in parentheses. 153bcde45baSRahul Joshi void DetailedRecordsEmitter::printSuperclasses(const Record &Rec, 154bcde45baSRahul Joshi raw_ostream &OS) { 15565e69f74SRahul Joshi ArrayRef<std::pair<const Record *, SMRange>> Superclasses = 15665e69f74SRahul Joshi Rec.getSuperClasses(); 1570c1bb4f8SPaul C. Anagnostopoulos if (Superclasses.empty()) { 1580c1bb4f8SPaul C. Anagnostopoulos OS << " Superclasses: (none)\n"; 1590c1bb4f8SPaul C. Anagnostopoulos return; 1600c1bb4f8SPaul C. Anagnostopoulos } 1610c1bb4f8SPaul C. Anagnostopoulos 1620c1bb4f8SPaul C. Anagnostopoulos OS << " Superclasses:"; 163bcde45baSRahul Joshi for (const auto &[ClassRec, Loc] : Superclasses) { 164bcde45baSRahul Joshi if (Rec.hasDirectSuperClass(ClassRec)) 1650c1bb4f8SPaul C. Anagnostopoulos OS << formatv(" {0}", ClassRec->getNameInitAsString()); 1660c1bb4f8SPaul C. Anagnostopoulos else 1670c1bb4f8SPaul C. Anagnostopoulos OS << formatv(" ({0})", ClassRec->getNameInitAsString()); 1680c1bb4f8SPaul C. Anagnostopoulos } 169bcde45baSRahul Joshi OS << '\n'; 1700c1bb4f8SPaul C. Anagnostopoulos } 1710c1bb4f8SPaul C. Anagnostopoulos 1720c1bb4f8SPaul C. Anagnostopoulos // Print the fields of a class or record, including their source locations. 173bcde45baSRahul Joshi void DetailedRecordsEmitter::printFields(const Record &Rec, raw_ostream &OS) { 174bcde45baSRahul Joshi const auto &ValueList = Rec.getValues(); 1750c1bb4f8SPaul C. Anagnostopoulos if (ValueList.empty()) { 1760c1bb4f8SPaul C. Anagnostopoulos OS << " Fields: (none)\n"; 1770c1bb4f8SPaul C. Anagnostopoulos return; 1780c1bb4f8SPaul C. Anagnostopoulos } 1790c1bb4f8SPaul C. Anagnostopoulos 1800c1bb4f8SPaul C. Anagnostopoulos OS << " Fields:\n"; 1810c1bb4f8SPaul C. Anagnostopoulos for (const RecordVal &Value : ValueList) 182bcde45baSRahul Joshi if (!Rec.isTemplateArg(Value.getNameInit())) { 1830c1bb4f8SPaul C. Anagnostopoulos OS << " "; 1840c1bb4f8SPaul C. Anagnostopoulos Value.print(OS, false); 1850c1bb4f8SPaul C. Anagnostopoulos OS << formatv(" |{0}|\n", 1860c1bb4f8SPaul C. Anagnostopoulos SrcMgr.getFormattedLocationNoOffset(Value.getLoc())); 1870c1bb4f8SPaul C. Anagnostopoulos } 1880c1bb4f8SPaul C. Anagnostopoulos } 1890c1bb4f8SPaul C. Anagnostopoulos 1900c1bb4f8SPaul C. Anagnostopoulos // This function is called by TableGen after parsing the files. 191bcde45baSRahul Joshi void llvm::EmitDetailedRecords(const RecordKeeper &RK, raw_ostream &OS) { 1920c1bb4f8SPaul C. Anagnostopoulos // Instantiate the emitter class and invoke run(). 1930c1bb4f8SPaul C. Anagnostopoulos DetailedRecordsEmitter(RK).run(OS); 1940c1bb4f8SPaul C. Anagnostopoulos } 195