30
30
namespace llvm {
31
31
namespace symbolize {
32
32
33
+ class SourceCode {
34
+ std::unique_ptr<MemoryBuffer> MemBuf;
35
+
36
+ const Optional<StringRef> load (StringRef FileName,
37
+ const Optional<StringRef> &EmbeddedSource) {
38
+ if (Lines <= 0 )
39
+ return None;
40
+
41
+ if (EmbeddedSource)
42
+ return EmbeddedSource;
43
+ else {
44
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
45
+ MemoryBuffer::getFile (FileName);
46
+ if (!BufOrErr)
47
+ return None;
48
+ MemBuf = std::move (*BufOrErr);
49
+ return MemBuf->getBuffer ();
50
+ }
51
+ }
52
+
53
+ const Optional<StringRef> pruneSource (const Optional<StringRef> &Source) {
54
+ if (!Source)
55
+ return None;
56
+ size_t FirstLinePos = StringRef::npos, Pos = 0 ;
57
+ for (int64_t L = 1 ; L <= LastLine; ++L, ++Pos) {
58
+ if (L == FirstLine)
59
+ FirstLinePos = Pos;
60
+ Pos = Source->find (' \n ' , Pos);
61
+ if (Pos == StringRef::npos)
62
+ break ;
63
+ }
64
+ if (FirstLinePos == StringRef::npos)
65
+ return None;
66
+ return Source->substr (FirstLinePos, (Pos == StringRef::npos)
67
+ ? StringRef::npos
68
+ : Pos - FirstLinePos);
69
+ }
70
+
71
+ public:
72
+ const int64_t Line;
73
+ const int Lines;
74
+ const int64_t FirstLine;
75
+ const int64_t LastLine;
76
+ const Optional<StringRef> PrunedSource;
77
+
78
+ SourceCode (
79
+ StringRef FileName, int64_t Line, int Lines,
80
+ const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None))
81
+ : Line(Line), Lines(Lines),
82
+ FirstLine (std::max(static_cast <int64_t >(1 ), Line - Lines / 2)),
83
+ LastLine(FirstLine + Lines - 1 ),
84
+ PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {}
85
+ };
86
+
33
87
void PlainPrinterBase::printHeader (uint64_t Address) {
34
88
if (Config.PrintAddress ) {
35
89
OS << " 0x" ;
@@ -40,32 +94,27 @@ void PlainPrinterBase::printHeader(uint64_t Address) {
40
94
}
41
95
42
96
// Prints source code around in the FileName the Line.
43
- void PlainPrinterBase::printContext (StringRef FileName, int64_t Line ) {
44
- if (Config. SourceContextLines <= 0 )
97
+ void PlainPrinterBase::printContext (SourceCode SourceCode ) {
98
+ if (!SourceCode. PrunedSource )
45
99
return ;
46
100
47
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
48
- MemoryBuffer::getFile (FileName);
49
- if (!BufOrErr)
50
- return ;
101
+ StringRef Source = *SourceCode.PrunedSource ;
102
+ std::string SourceCopy;
103
+ if (*Source.end () != ' \0 ' ) {
104
+ SourceCopy = Source.str ();
105
+ Source = SourceCopy;
106
+ }
51
107
52
- std::unique_ptr<MemoryBuffer> Buf = std::move (BufOrErr.get ());
53
- int64_t FirstLine =
54
- std::max (static_cast <int64_t >(1 ), Line - Config.SourceContextLines / 2 );
55
- int64_t LastLine = FirstLine + Config.SourceContextLines ;
56
- size_t MaxLineNumberWidth = std::ceil (std::log10 (LastLine));
57
-
58
- for (line_iterator I = line_iterator (*Buf, false );
59
- !I.is_at_eof () && I.line_number () <= LastLine; ++I) {
60
- int64_t L = I.line_number ();
61
- if (L >= FirstLine && L <= LastLine) {
62
- OS << format_decimal (L, MaxLineNumberWidth);
63
- if (L == Line)
64
- OS << " >: " ;
65
- else
66
- OS << " : " ;
67
- OS << *I << " \n " ;
68
- }
108
+ size_t MaxLineNumberWidth = std::ceil (std::log10 (SourceCode.LastLine ));
109
+ for (line_iterator I = line_iterator (MemoryBufferRef (Source, " " ), false );
110
+ !I.is_at_eof (); ++I) {
111
+ int64_t L = SourceCode.FirstLine + I.line_number () - 1 ;
112
+ OS << format_decimal (L, MaxLineNumberWidth);
113
+ if (L == SourceCode.Line )
114
+ OS << " >: " ;
115
+ else
116
+ OS << " : " ;
117
+ OS << *I << ' \n ' ;
69
118
}
70
119
}
71
120
@@ -82,7 +131,7 @@ void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
82
131
void LLVMPrinter::printSimpleLocation (StringRef Filename,
83
132
const DILineInfo &Info) {
84
133
OS << Filename << ' :' << Info.Line << ' :' << Info.Column << ' \n ' ;
85
- printContext (Filename, Info.Line );
134
+ printContext (SourceCode ( Filename, Info.Line , Config. SourceContextLines ) );
86
135
}
87
136
88
137
void GNUPrinter::printSimpleLocation (StringRef Filename,
@@ -91,7 +140,7 @@ void GNUPrinter::printSimpleLocation(StringRef Filename,
91
140
if (Info.Discriminator )
92
141
OS << " (discriminator " << Info.Discriminator << ' )' ;
93
142
OS << ' \n ' ;
94
- printContext (Filename, Info.Line );
143
+ printContext (SourceCode ( Filename, Info.Line , Config. SourceContextLines ) );
95
144
}
96
145
97
146
void PlainPrinterBase::printVerbose (StringRef Filename,
0 commit comments