Skip to content

Commit 5f57793

Browse files
committed
* NFC. Refactored DIPrinter for better support of new print styles.
This patch introduces a DIPrinter interface to implement by different output style printer implementations. DIPrinterGNU and DIPrinterLLVM implement the GNU and LLVM output style printing respectively. No functional changes. This refactoring clarifies and simplifies the code, and makes a new output style addition easier. Reviewed By: jhenderson, dblaikie Differential Revision: https://reviews.llvm.org/D98994
1 parent 0d0514d commit 5f57793

File tree

3 files changed

+269
-144
lines changed

3 files changed

+269
-144
lines changed

llvm/include/llvm/DebugInfo/Symbolize/DIPrinter.h

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,46 +14,105 @@
1414
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
1515
#define LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
1616

17+
#include "llvm/ADT/StringRef.h"
1718
#include <string>
19+
#include <vector>
1820

1921
namespace llvm {
2022
struct DILineInfo;
2123
class DIInliningInfo;
2224
struct DIGlobal;
2325
struct DILocal;
26+
class ErrorInfoBase;
2427
class raw_ostream;
2528

2629
namespace symbolize {
2730

31+
struct Request {
32+
StringRef ModuleName;
33+
uint64_t Address = 0;
34+
};
35+
2836
class DIPrinter {
2937
public:
30-
enum class OutputStyle { LLVM, GNU };
38+
DIPrinter(){};
39+
virtual ~DIPrinter(){};
3140

32-
private:
33-
raw_ostream &OS;
34-
bool PrintFunctionNames;
35-
bool PrintPretty;
36-
int PrintSourceContext;
41+
virtual void print(const Request &Request, const DILineInfo &Info) = 0;
42+
virtual void print(const Request &Request, const DIInliningInfo &Info) = 0;
43+
virtual void print(const Request &Request, const DIGlobal &Global) = 0;
44+
virtual void print(const Request &Request,
45+
const std::vector<DILocal> &Locals) = 0;
46+
47+
virtual void printInvalidCommand(const Request &Request,
48+
const ErrorInfoBase &ErrorInfo) = 0;
49+
50+
virtual bool printError(const Request &Request,
51+
const ErrorInfoBase &ErrorInfo,
52+
StringRef ErrorBanner) = 0;
53+
};
54+
55+
struct PrinterConfig {
56+
bool PrintAddress;
57+
bool PrintFunctions;
58+
bool Pretty;
3759
bool Verbose;
38-
OutputStyle Style;
60+
int SourceContextLines;
61+
};
62+
63+
class PlainPrinterBase : public DIPrinter {
64+
protected:
65+
raw_ostream &OS;
66+
raw_ostream &ES;
67+
PrinterConfig Config;
3968

4069
void print(const DILineInfo &Info, bool Inlined);
41-
void printContext(const std::string &FileName, int64_t Line);
70+
void printFunctionName(StringRef FunctionName, bool Inlined);
71+
virtual void printSimpleLocation(StringRef Filename,
72+
const DILineInfo &Info) = 0;
73+
void printContext(StringRef FileName, int64_t Line);
74+
void printVerbose(StringRef Filename, const DILineInfo &Info);
75+
virtual void printFooter() {}
76+
77+
private:
78+
void printHeader(uint64_t Address);
79+
80+
public:
81+
PlainPrinterBase(raw_ostream &OS, raw_ostream &ES, PrinterConfig &Config)
82+
: DIPrinter(), OS(OS), ES(ES), Config(Config) {}
83+
84+
void print(const Request &Request, const DILineInfo &Info) override;
85+
void print(const Request &Request, const DIInliningInfo &Info) override;
86+
void print(const Request &Request, const DIGlobal &Global) override;
87+
void print(const Request &Request,
88+
const std::vector<DILocal> &Locals) override;
89+
90+
void printInvalidCommand(const Request &Request,
91+
const ErrorInfoBase &ErrorInfo) override;
92+
93+
bool printError(const Request &Request, const ErrorInfoBase &ErrorInfo,
94+
StringRef ErrorBanner) override;
95+
};
96+
97+
class LLVMPrinter : public PlainPrinterBase {
98+
private:
99+
void printSimpleLocation(StringRef Filename, const DILineInfo &Info) override;
100+
void printFooter() override;
101+
102+
public:
103+
LLVMPrinter(raw_ostream &OS, raw_ostream &ES, PrinterConfig &Config)
104+
: PlainPrinterBase(OS, ES, Config) {}
105+
};
106+
107+
class GNUPrinter : public PlainPrinterBase {
108+
private:
109+
void printSimpleLocation(StringRef Filename, const DILineInfo &Info) override;
42110

43111
public:
44-
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true,
45-
bool PrintPretty = false, int PrintSourceContext = 0,
46-
bool Verbose = false, OutputStyle Style = OutputStyle::LLVM)
47-
: OS(OS), PrintFunctionNames(PrintFunctionNames),
48-
PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext),
49-
Verbose(Verbose), Style(Style) {}
50-
51-
DIPrinter &operator<<(const DILineInfo &Info);
52-
DIPrinter &operator<<(const DIInliningInfo &Info);
53-
DIPrinter &operator<<(const DIGlobal &Global);
54-
DIPrinter &operator<<(const DILocal &Local);
112+
GNUPrinter(raw_ostream &OS, raw_ostream &ES, PrinterConfig &Config)
113+
: PlainPrinterBase(OS, ES, Config) {}
55114
};
56-
}
57-
}
115+
} // namespace symbolize
116+
} // namespace llvm
58117

59118
#endif

llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp

Lines changed: 124 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,18 @@
3030
namespace llvm {
3131
namespace symbolize {
3232

33+
void PlainPrinterBase::printHeader(uint64_t Address) {
34+
if (Config.PrintAddress) {
35+
OS << "0x";
36+
OS.write_hex(Address);
37+
StringRef Delimiter = Config.Pretty ? ": " : "\n";
38+
OS << Delimiter;
39+
}
40+
}
41+
3342
// Prints source code around in the FileName the Line.
34-
void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
35-
if (PrintSourceContext <= 0)
43+
void PlainPrinterBase::printContext(StringRef FileName, int64_t Line) {
44+
if (Config.SourceContextLines <= 0)
3645
return;
3746

3847
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
@@ -42,8 +51,8 @@ void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
4251

4352
std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
4453
int64_t FirstLine =
45-
std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
46-
int64_t LastLine = FirstLine + PrintSourceContext;
54+
std::max(static_cast<int64_t>(1), Line - Config.SourceContextLines / 2);
55+
int64_t LastLine = FirstLine + Config.SourceContextLines;
4756
size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
4857

4958
for (line_iterator I = line_iterator(*Buf, false);
@@ -60,97 +69,145 @@ void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
6069
}
6170
}
6271

63-
void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
64-
if (PrintFunctionNames) {
65-
std::string FunctionName = Info.FunctionName;
72+
void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
73+
if (Config.PrintFunctions) {
6674
if (FunctionName == DILineInfo::BadString)
6775
FunctionName = DILineInfo::Addr2LineBadString;
68-
69-
StringRef Delimiter = PrintPretty ? " at " : "\n";
70-
StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
76+
StringRef Delimiter = Config.Pretty ? " at " : "\n";
77+
StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : "";
7178
OS << Prefix << FunctionName << Delimiter;
7279
}
73-
std::string Filename = Info.FileName;
74-
if (Filename == DILineInfo::BadString)
75-
Filename = DILineInfo::Addr2LineBadString;
76-
if (!Verbose) {
77-
OS << Filename << ":" << Info.Line;
78-
if (Style == OutputStyle::LLVM)
79-
OS << ":" << Info.Column;
80-
else if (Style == OutputStyle::GNU && Info.Discriminator != 0)
81-
OS << " (discriminator " << Info.Discriminator << ")";
82-
OS << "\n";
83-
printContext(Filename, Info.Line);
84-
return;
85-
}
86-
OS << " Filename: " << Filename << "\n";
80+
}
81+
82+
void LLVMPrinter::printSimpleLocation(StringRef Filename,
83+
const DILineInfo &Info) {
84+
OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
85+
printContext(Filename, Info.Line);
86+
}
87+
88+
void GNUPrinter::printSimpleLocation(StringRef Filename,
89+
const DILineInfo &Info) {
90+
OS << Filename << ':' << Info.Line;
91+
if (Info.Discriminator)
92+
OS << " (discriminator " << Info.Discriminator << ')';
93+
OS << '\n';
94+
printContext(Filename, Info.Line);
95+
}
96+
97+
void PlainPrinterBase::printVerbose(StringRef Filename,
98+
const DILineInfo &Info) {
99+
OS << " Filename: " << Filename << '\n';
87100
if (Info.StartLine) {
88-
OS << " Function start filename: " << Info.StartFileName << "\n";
89-
OS << " Function start line: " << Info.StartLine << "\n";
101+
OS << " Function start filename: " << Info.StartFileName << '\n';
102+
OS << " Function start line: " << Info.StartLine << '\n';
90103
}
91-
OS << " Line: " << Info.Line << "\n";
92-
OS << " Column: " << Info.Column << "\n";
104+
OS << " Line: " << Info.Line << '\n';
105+
OS << " Column: " << Info.Column << '\n';
93106
if (Info.Discriminator)
94-
OS << " Discriminator: " << Info.Discriminator << "\n";
107+
OS << " Discriminator: " << Info.Discriminator << '\n';
108+
}
109+
110+
void LLVMPrinter::printFooter() { OS << '\n'; }
111+
112+
void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) {
113+
printFunctionName(Info.FunctionName, Inlined);
114+
StringRef Filename = Info.FileName;
115+
if (Filename == DILineInfo::BadString)
116+
Filename = DILineInfo::Addr2LineBadString;
117+
if (Config.Verbose)
118+
printVerbose(Filename, Info);
119+
else
120+
printSimpleLocation(Filename, Info);
95121
}
96122

97-
DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
123+
void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) {
124+
printHeader(Request.Address);
98125
print(Info, false);
99-
return *this;
126+
printFooter();
100127
}
101128

102-
DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
129+
void PlainPrinterBase::print(const Request &Request,
130+
const DIInliningInfo &Info) {
131+
printHeader(Request.Address);
103132
uint32_t FramesNum = Info.getNumberOfFrames();
104-
if (FramesNum == 0) {
133+
if (FramesNum == 0)
105134
print(DILineInfo(), false);
106-
return *this;
107-
}
108-
for (uint32_t i = 0; i < FramesNum; i++)
109-
print(Info.getFrame(i), i > 0);
110-
return *this;
135+
else
136+
for (uint32_t I = 0; I < FramesNum; ++I)
137+
print(Info.getFrame(I), I > 0);
138+
printFooter();
111139
}
112140

113-
DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
114-
std::string Name = Global.Name;
141+
void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) {
142+
printHeader(Request.Address);
143+
StringRef Name = Global.Name;
115144
if (Name == DILineInfo::BadString)
116145
Name = DILineInfo::Addr2LineBadString;
117146
OS << Name << "\n";
118147
OS << Global.Start << " " << Global.Size << "\n";
119-
return *this;
148+
printFooter();
120149
}
121150

122-
DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
123-
if (Local.FunctionName.empty())
124-
OS << "??\n";
151+
void PlainPrinterBase::print(const Request &Request,
152+
const std::vector<DILocal> &Locals) {
153+
printHeader(Request.Address);
154+
if (Locals.empty())
155+
OS << DILineInfo::Addr2LineBadString << '\n';
125156
else
126-
OS << Local.FunctionName << '\n';
157+
for (const DILocal &L : Locals) {
158+
if (L.FunctionName.empty())
159+
OS << DILineInfo::Addr2LineBadString;
160+
else
161+
OS << L.FunctionName;
162+
OS << '\n';
127163

128-
if (Local.Name.empty())
129-
OS << "??\n";
130-
else
131-
OS << Local.Name << '\n';
164+
if (L.Name.empty())
165+
OS << DILineInfo::Addr2LineBadString;
166+
else
167+
OS << L.Name;
168+
OS << '\n';
132169

133-
if (Local.DeclFile.empty())
134-
OS << "??";
135-
else
136-
OS << Local.DeclFile;
137-
OS << ':' << Local.DeclLine << '\n';
170+
if (L.DeclFile.empty())
171+
OS << DILineInfo::Addr2LineBadString;
172+
else
173+
OS << L.DeclFile;
138174

139-
if (Local.FrameOffset)
140-
OS << *Local.FrameOffset << ' ';
141-
else
142-
OS << "?? ";
175+
OS << ':' << L.DeclLine << '\n';
143176

144-
if (Local.Size)
145-
OS << *Local.Size << ' ';
146-
else
147-
OS << "?? ";
177+
if (L.FrameOffset)
178+
OS << *L.FrameOffset;
179+
else
180+
OS << DILineInfo::Addr2LineBadString;
181+
OS << ' ';
148182

149-
if (Local.TagOffset)
150-
OS << *Local.TagOffset << '\n';
151-
else
152-
OS << "??\n";
153-
return *this;
183+
if (L.Size)
184+
OS << *L.Size;
185+
else
186+
OS << DILineInfo::Addr2LineBadString;
187+
OS << ' ';
188+
189+
if (L.TagOffset)
190+
OS << *L.TagOffset;
191+
else
192+
OS << DILineInfo::Addr2LineBadString;
193+
OS << '\n';
194+
}
195+
printFooter();
196+
}
197+
198+
void PlainPrinterBase::printInvalidCommand(const Request &Request,
199+
const ErrorInfoBase &ErrorInfo) {
200+
OS << ErrorInfo.message() << '\n';
201+
}
202+
203+
bool PlainPrinterBase::printError(const Request &Request,
204+
const ErrorInfoBase &ErrorInfo,
205+
StringRef ErrorBanner) {
206+
ES << ErrorBanner;
207+
ErrorInfo.log(ES);
208+
ES << '\n';
209+
// Print an empty struct too.
210+
return true;
154211
}
155212

156213
} // end namespace symbolize

0 commit comments

Comments
 (0)