1//===- LinePrinter.h ------------------------------------------ *- 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#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
10#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/Twine.h"
15#include "llvm/Support/BinaryStreamRef.h"
16#include "llvm/Support/FormatVariadic.h"
17#include "llvm/Support/Regex.h"
18#include "llvm/Support/raw_ostream.h"
19
20#include <list>
21
22namespace llvm {
23class BinaryStreamReader;
24namespace msf {
25class MSFStreamLayout;
26} // namespace msf
27namespace pdb {
28
29class ClassLayout;
30class PDBFile;
31
32class LinePrinter {
33  friend class WithColor;
34
35public:
36  LinePrinter(int Indent, bool UseColor, raw_ostream &Stream);
37
38  void Indent(uint32_t Amount = 0);
39  void Unindent(uint32_t Amount = 0);
40  void NewLine();
41
42  void printLine(const Twine &T);
43  void print(const Twine &T);
44  template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) {
45    printLine(formatv(Fmt, std::forward<Ts>(Items)...));
46  }
47  template <typename... Ts> void format(const char *Fmt, Ts &&... Items) {
48    print(formatv(Fmt, std::forward<Ts>(Items)...));
49  }
50
51  void formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
52                    uint32_t StartOffset);
53  void formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint64_t BaseAddr,
54                    uint32_t StartOffset);
55
56  void formatMsfStreamData(StringRef Label, PDBFile &File, uint32_t StreamIdx,
57                           StringRef StreamPurpose, uint32_t Offset,
58                           uint32_t Size);
59  void formatMsfStreamData(StringRef Label, PDBFile &File,
60                           const msf::MSFStreamLayout &Stream,
61                           BinarySubstreamRef Substream);
62  void formatMsfStreamBlocks(PDBFile &File, const msf::MSFStreamLayout &Stream);
63
64  bool hasColor() const { return UseColor; }
65  raw_ostream &getStream() { return OS; }
66  int getIndentLevel() const { return CurrentIndent; }
67
68  bool IsClassExcluded(const ClassLayout &Class);
69  bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size);
70  bool IsSymbolExcluded(llvm::StringRef SymbolName);
71  bool IsCompilandExcluded(llvm::StringRef CompilandName);
72
73private:
74  template <typename Iter>
75  void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
76    List.clear();
77    for (; Begin != End; ++Begin)
78      List.emplace_back(StringRef(*Begin));
79  }
80
81  raw_ostream &OS;
82  int IndentSpaces;
83  int CurrentIndent;
84  bool UseColor;
85
86  std::list<Regex> ExcludeCompilandFilters;
87  std::list<Regex> ExcludeTypeFilters;
88  std::list<Regex> ExcludeSymbolFilters;
89
90  std::list<Regex> IncludeCompilandFilters;
91  std::list<Regex> IncludeTypeFilters;
92  std::list<Regex> IncludeSymbolFilters;
93};
94
95struct PrintScope {
96  explicit PrintScope(LinePrinter &P, uint32_t IndentLevel)
97      : P(P), IndentLevel(IndentLevel) {}
98  explicit PrintScope(const PrintScope &Other, uint32_t LabelWidth)
99      : P(Other.P), IndentLevel(Other.IndentLevel), LabelWidth(LabelWidth) {}
100
101  LinePrinter &P;
102  uint32_t IndentLevel;
103  uint32_t LabelWidth = 0;
104};
105
106inline Optional<PrintScope> withLabelWidth(const Optional<PrintScope> &Scope,
107                                           uint32_t W) {
108  if (!Scope)
109    return None;
110  return PrintScope{*Scope, W};
111}
112
113struct AutoIndent {
114  explicit AutoIndent(LinePrinter &L, uint32_t Amount = 0)
115      : L(&L), Amount(Amount) {
116    L.Indent(Amount);
117  }
118  explicit AutoIndent(const Optional<PrintScope> &Scope) {
119    if (Scope.hasValue()) {
120      L = &Scope->P;
121      Amount = Scope->IndentLevel;
122    }
123  }
124  ~AutoIndent() {
125    if (L)
126      L->Unindent(Amount);
127  }
128
129  LinePrinter *L = nullptr;
130  uint32_t Amount = 0;
131};
132
133template <class T>
134inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
135  return Printer.getStream() << Item;
136}
137
138enum class PDB_ColorItem {
139  None,
140  Address,
141  Type,
142  Comment,
143  Padding,
144  Keyword,
145  Offset,
146  Identifier,
147  Path,
148  SectionHeader,
149  LiteralValue,
150  Register,
151};
152
153class WithColor {
154public:
155  WithColor(LinePrinter &P, PDB_ColorItem C);
156  ~WithColor();
157
158  raw_ostream &get() { return OS; }
159
160private:
161  void applyColor(PDB_ColorItem C);
162  raw_ostream &OS;
163  bool UseColor;
164};
165}
166}
167
168#endif
169