brintos

brintos / llvm-project-archived public Read only

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