Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(426)

Side by Side Diff: lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp ('k') | lib/Bitcode/NaCl/CMakeLists.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===-- NaClObjDumpStream.cpp --------------------------------------------===//
2 // Implements an objdump stream (bitcode records/assembly code).
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Bitcode/NaCl/NaClObjDumpStream.h"
13 #include "llvm/Support/DataTypes.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/Format.h"
16
17 namespace llvm {
18 namespace naclbitc {
19
20 TextFormatter::TextFormatter(raw_ostream &BaseStream,
21 unsigned LineWidth,
22 const char *Tab)
23 : TextIndenter(Tab),
24 BaseStream(BaseStream),
25 TextStream(TextBuffer),
26 LineWidth(LineWidth),
27 LinePosition(0),
28 CurrentIndent(0),
29 MinLineWidth(20),
30 AtInstructionBeginning(true),
31 LineIndent(),
32 ContinuationIndent(),
33 ClusteringLevel(0),
34 ClusteredTextSize(0) {
35 if (MinLineWidth > LineWidth) MinLineWidth = LineWidth;
36 }
37
38 TextFormatter::~TextFormatter() {}
39
40 void TextFormatter::WriteEndline() {
41 assert(!IsClustering() && "Must close clustering before ending instruction");
42 Write('\n');
43 CurrentIndent = 0;
44 AtInstructionBeginning = true;
45 LineIndent.clear();
46 }
47
48 std::string TextFormatter::GetToken() {
49 TextStream.flush();
50 std::string Token(TextBuffer);
51 TextBuffer.clear();
52 if (!Token.empty() && IsClustering())
53 AppendForReplay(GetTokenDirective::Allocate(this, Token));
54 return Token;
55 }
56
57 void TextFormatter::Write(char ch) {
58 switch (ch) {
59 case '\n':
60 BaseStream << ch;
61 LinePosition = 0;
62 break;
63 case '\t': {
64 size_t TabWidth = GetTabSize();
65 size_t NumChars = LinePosition % TabWidth;
66 if (NumChars == 0) NumChars = TabWidth;
67 for (size_t i = 0; i < NumChars; ++i) Write(' ');
68 break;
69 }
70 default:
71 if (LinePosition == 0) {
72 WriteLineIndents();
73 }
74 BaseStream << ch;
75 ++LinePosition;
76 }
77 AtInstructionBeginning = false;
78 }
79
80 void TextFormatter::Write(const std::string &Text) {
81 if (IsClustering()) {
82 ClusteredTextSize += Text.size();
83 } else {
84 for (std::string::const_iterator
85 Iter = Text.begin(), IterEnd = Text.end();
86 Iter != IterEnd; ++Iter) {
87 Write(*Iter);
88 }
89 }
90 }
91
92 void TextFormatter::StartClustering() {
93 ++ClusteringLevel;
94 }
95
96 void TextFormatter::FinishClustering() {
97 assert(IsClustering() && "Can't finish clustering, not in cluster!");
98 --ClusteringLevel;
99 if (IsClustering()) return;
100
101 AddLineWrapIfNeeded(ClusteredTextSize);
102
103 // Reapply the directives to generate the token text, and set
104 // indentations. Because clustering can be nested, duplicate before
105 // replaying, so that nested clusters can replayed and build its own
106 // list of clustered directives.
107 std::vector<const Directive*> Directives(ClusteredDirectives);
108 ClusteredDirectives.clear();
109 ClusteredTextSize = 0;
110 for (std::vector<const Directive*>::iterator
111 Iter = Directives.begin(),
112 IterEnd = Directives.end();
113 Iter != IterEnd; ++Iter) {
114 (*Iter)->Apply();
115 }
116 }
117
118 void TextFormatter::WriteLineIndents() {
119 // Add line indent to base stream.
120 if (AtInstructionBeginning) LineIndent = GetIndent();
121 BaseStream << LineIndent;
122 LinePosition += LineIndent.size();
123
124 // If not the first line, and local indent not set, add continuation
125 // indent to the base stream.
126 unsigned UseIndent = CurrentIndent;
127 if (!AtInstructionBeginning && CurrentIndent == 0) {
128 UseIndent = FixIndentValue(LinePosition + ContinuationIndent.size());
129 }
130
131 // Add any additional indents local to the current instruction
132 // being dumped to the base stream.
133 for (; LinePosition < UseIndent; ++LinePosition) {
134 BaseStream << ' ';
135 }
136 }
137
138 void TextFormatter::Directive::Reapply() const {
139 // Note: We don't want to store top-level start/finish cluster
140 // directives on ClusteredDirectives, so that nested replays won't
141 // reapply them.
142 bool WasClustering = IsClustering();
143 MyApply(true);
144 if (WasClustering && IsClustering())
145 Formatter->ClusteredDirectives.push_back(this);
146 }
147
148
149 TextFormatter::Directive *TextFormatter::GetTokenDirective::
150 Allocate(TextFormatter *Formatter, const std::string &Text) {
151 GetTokenDirective *Dir = Formatter->GetTokenFreeList.Allocate(Formatter);
152 Dir->Text = Text;
153 return Dir;
154 }
155
156 RecordTextFormatter::RecordTextFormatter(ObjDumpStream *ObjDump)
157 : TextFormatter(ObjDump->Records(), 0, " "),
158 ObjDump(ObjDump),
159 OpenBrace(this, "<"),
160 CloseBrace(this, ">"),
161 Comma(this, ","),
162 Space(this),
163 Endline(this),
164 StartCluster(this),
165 FinishCluster(this) {
166 // Handle fact that 64-bit values can take up to 21 characters.
167 MinLineWidth = 21;
168 Label = RecordAddress(0);
169 }
170
171 std::string RecordTextFormatter::RecordAddress(uint64_t Bit,
172 unsigned MinByteWidth) {
173 std::string Buffer;
174 raw_string_ostream Stream(Buffer);
175 Stream << '%' << MinByteWidth << PRIu64 << ":%u";
176 Stream.flush();
177 std::string FormatString(Buffer);
178 Buffer.clear();
179 Stream << format(FormatString.c_str(),
180 (Bit / 8),
181 static_cast<unsigned>(Bit % 8));
182 return Stream.str();
183 }
184
185 std::string RecordTextFormatter::GetEmptyLabelColumn() {
186 std::string Buffer;
187 raw_string_ostream StrmBuffer(Buffer);
188 for (size_t i = 0; i < Label.size(); ++i) {
189 StrmBuffer << ' ';
190 }
191 StrmBuffer << '|';
192 return StrmBuffer.str();
193 }
194
195 void RecordTextFormatter::WriteLineIndents() {
196 if (AtInstructionBeginning) {
197 BaseStream << Label << '|';
198 } else {
199 BaseStream << GetEmptyLabelColumn();
200 }
201 LinePosition += Label.size() + 1;
202 TextFormatter::WriteLineIndents();
203 }
204
205 void RecordTextFormatter::WriteValues(uint64_t Bit,
206 const llvm::NaClBitcodeValues &Values,
207 int32_t AbbrevIndex) {
208 Label = ObjDump->RecordAddress(Bit);
209 if (AbbrevIndex != ABBREV_INDEX_NOT_SPECIFIED) {
210 TextStream << AbbrevIndex << ":" << Space;
211 }
212 TextStream << OpenBrace;
213 for (size_t i = 0; i < Values.size(); ++i) {
214 if (i > 0) {
215 TextStream << Comma << FinishCluster << Space;
216 }
217 TextStream << StartCluster << Values[i];
218 }
219 // Note: Because of record codes, Values are never empty. Hence we
220 // always need to finish the cluster for the last number printed.
221 TextStream << FinishCluster << CloseBrace << Endline;
222 }
223
224 unsigned ObjDumpStream::DefaultMaxErrors = 20;
225
226 unsigned ObjDumpStream::ComboObjDumpSeparatorColumn = 40;
227
228 unsigned ObjDumpStream::RecordObjectDumpLength = 80;
229
230 ObjDumpStream::ObjDumpStream(raw_ostream &Stream,
231 bool DumpRecords, bool DumpAssembly)
232 : Stream(Stream),
233 DumpRecords(DumpRecords),
234 DumpAssembly(DumpAssembly),
235 NumErrors(0),
236 MaxErrors(DefaultMaxErrors),
237 RecordWidth(0),
238 StartOffset(0),
239 AssemblyBuffer(),
240 AssemblyStream(AssemblyBuffer),
241 MessageBuffer(),
242 MessageStream(MessageBuffer),
243 ColumnSeparator('|'),
244 LastKnownBit(0),
245 RecordBuffer(),
246 RecordStream(RecordBuffer),
247 RecordFormatter(this) {
248 if (DumpRecords) {
249 RecordWidth = DumpAssembly
250 ? ComboObjDumpSeparatorColumn
251 : RecordObjectDumpLength;
252 RecordFormatter.SetLineWidth(RecordWidth);
253 }
254 }
255
256 raw_ostream &ObjDumpStream::Error(uint64_t Bit) {
257 LastKnownBit = Bit;
258 if (NumErrors >= MaxErrors)
259 Fatal(Bit, "Too many errors");
260 ++NumErrors;
261 return PrintMessagePrefix("Error", Bit);
262 }
263
264 void ObjDumpStream::Fatal(uint64_t Bit, const std::string &Message) {
265 LastKnownBit = Bit;
266 if (!Message.empty())
267 PrintMessagePrefix("Error", Bit) << Message << "\n";
268 Flush();
269 llvm::report_fatal_error("Unable to continue");
270 }
271
272 void ObjDumpStream::Fatal(uint64_t Bit,
273 const llvm::NaClBitcodeRecordData &Record,
274 const std::string &Message) {
275 LastKnownBit = Bit;
276 PrintMessagePrefix("Error", Bit) << Message;
277 Write(Bit, Record);
278 llvm::report_fatal_error("Unable to continue");
279 }
280
281 // Dumps the next line of text in the buffer. Returns the number of characters
282 // printed.
283 static size_t DumpLine(raw_ostream &Stream,
284 const std::string &Buffer,
285 size_t &Index,
286 size_t Size) {
287 size_t Count = 0;
288 while (Index < Size) {
289 char ch = Buffer[Index];
290 if (ch == '\n') {
291 // At end of line, stop here.
292 ++Index;
293 return Count;
294 } else {
295 Stream << ch;
296 ++Index;
297 ++Count;
298 }
299 }
300 return Count;
301 }
302
303 void ObjDumpStream::Flush() {
304 // Start by flushing all buffers, so that we know the
305 // text that must be written.
306 RecordStream.flush();
307 AssemblyStream.flush();
308 MessageStream.flush();
309
310 // See if there is any record/assembly lines to print.
311 if ((DumpRecords && !RecordBuffer.empty())
312 || (DumpAssembly && !AssemblyBuffer.empty())) {
313 size_t RecordIndex = 0;
314 size_t RecordSize = DumpRecords ? RecordBuffer.size() : 0;
315 size_t AssemblyIndex = 0;
316 size_t AssemblySize = DumpAssembly ? AssemblyBuffer.size() : 0;
317
318 while (RecordIndex < RecordSize || AssemblyIndex < AssemblySize) {
319 // Dump next record line.
320 size_t Column = DumpLine(Stream, RecordBuffer, RecordIndex, RecordSize);
321 // Now move to separator if assembly is to be printed also.
322 if (DumpRecords && DumpAssembly) {
323 if (Column == 0) {
324 // Add indent filler.
325 std::string Label = RecordFormatter.GetEmptyLabelColumn();
326 Stream << Label;
327 Column += Label.size();
328 }
329 for (size_t i = Column; i < RecordWidth; ++i) {
330 Stream << ' ';
331 }
332 Stream << ColumnSeparator;
333 }
334 // Dump next assembly line.
335 DumpLine(Stream, AssemblyBuffer, AssemblyIndex, AssemblySize);
336 Stream << '\n';
337 }
338 }
339
340 // Print out messages and reset buffers.
341 Stream << MessageBuffer;
342 ResetBuffers();
343 if (NumErrors >= MaxErrors) {
344 // Note: we don't call Fatal here because that will call Flush, causing
345 // an infinite loop.
346 Stream << "Error(" << ObjDumpAddress(LastKnownBit)
347 << "): Too many errors\n";
348 llvm::report_fatal_error("Unable to continue");
349 }
350 Stream.flush();
351 }
352
353 }
354 }
OLDNEW
« no previous file with comments | « lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp ('k') | lib/Bitcode/NaCl/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698