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

Unified Diff: lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp
diff --git a/lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp b/lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..783d4ccc1d56f810f60f878a57bea20d057bf1c1
--- /dev/null
+++ b/lib/Bitcode/NaCl/Analysis/NaClObjDumpStream.cpp
@@ -0,0 +1,354 @@
+//===-- NaClObjDumpStream.cpp --------------------------------------------===//
+// Implements an objdump stream (bitcode records/assembly code).
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Bitcode/NaCl/NaClObjDumpStream.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+namespace llvm {
+namespace naclbitc {
+
+TextFormatter::TextFormatter(raw_ostream &BaseStream,
+ unsigned LineWidth,
+ const char *Tab)
+ : TextIndenter(Tab),
+ BaseStream(BaseStream),
+ TextStream(TextBuffer),
+ LineWidth(LineWidth),
+ LinePosition(0),
+ CurrentIndent(0),
+ MinLineWidth(20),
+ AtInstructionBeginning(true),
+ LineIndent(),
+ ContinuationIndent(),
+ ClusteringLevel(0),
+ ClusteredTextSize(0) {
+ if (MinLineWidth > LineWidth) MinLineWidth = LineWidth;
+}
+
+TextFormatter::~TextFormatter() {}
+
+void TextFormatter::WriteEndline() {
+ assert(!IsClustering() && "Must close clustering before ending instruction");
+ Write('\n');
+ CurrentIndent = 0;
+ AtInstructionBeginning = true;
+ LineIndent.clear();
+}
+
+std::string TextFormatter::GetToken() {
+ TextStream.flush();
+ std::string Token(TextBuffer);
+ TextBuffer.clear();
+ if (!Token.empty() && IsClustering())
+ AppendForReplay(GetTokenDirective::Allocate(this, Token));
+ return Token;
+}
+
+void TextFormatter::Write(char ch) {
+ switch (ch) {
+ case '\n':
+ BaseStream << ch;
+ LinePosition = 0;
+ break;
+ case '\t': {
+ size_t TabWidth = GetTabSize();
+ size_t NumChars = LinePosition % TabWidth;
+ if (NumChars == 0) NumChars = TabWidth;
+ for (size_t i = 0; i < NumChars; ++i) Write(' ');
+ break;
+ }
+ default:
+ if (LinePosition == 0) {
+ WriteLineIndents();
+ }
+ BaseStream << ch;
+ ++LinePosition;
+ }
+ AtInstructionBeginning = false;
+}
+
+void TextFormatter::Write(const std::string &Text) {
+ if (IsClustering()) {
+ ClusteredTextSize += Text.size();
+ } else {
+ for (std::string::const_iterator
+ Iter = Text.begin(), IterEnd = Text.end();
+ Iter != IterEnd; ++Iter) {
+ Write(*Iter);
+ }
+ }
+}
+
+void TextFormatter::StartClustering() {
+ ++ClusteringLevel;
+}
+
+void TextFormatter::FinishClustering() {
+ assert(IsClustering() && "Can't finish clustering, not in cluster!");
+ --ClusteringLevel;
+ if (IsClustering()) return;
+
+ AddLineWrapIfNeeded(ClusteredTextSize);
+
+ // Reapply the directives to generate the token text, and set
+ // indentations. Because clustering can be nested, duplicate before
+ // replaying, so that nested clusters can replayed and build its own
+ // list of clustered directives.
+ std::vector<const Directive*> Directives(ClusteredDirectives);
+ ClusteredDirectives.clear();
+ ClusteredTextSize = 0;
+ for (std::vector<const Directive*>::iterator
+ Iter = Directives.begin(),
+ IterEnd = Directives.end();
+ Iter != IterEnd; ++Iter) {
+ (*Iter)->Apply();
+ }
+}
+
+void TextFormatter::WriteLineIndents() {
+ // Add line indent to base stream.
+ if (AtInstructionBeginning) LineIndent = GetIndent();
+ BaseStream << LineIndent;
+ LinePosition += LineIndent.size();
+
+ // If not the first line, and local indent not set, add continuation
+ // indent to the base stream.
+ unsigned UseIndent = CurrentIndent;
+ if (!AtInstructionBeginning && CurrentIndent == 0) {
+ UseIndent = FixIndentValue(LinePosition + ContinuationIndent.size());
+ }
+
+ // Add any additional indents local to the current instruction
+ // being dumped to the base stream.
+ for (; LinePosition < UseIndent; ++LinePosition) {
+ BaseStream << ' ';
+ }
+}
+
+void TextFormatter::Directive::Reapply() const {
+ // Note: We don't want to store top-level start/finish cluster
+ // directives on ClusteredDirectives, so that nested replays won't
+ // reapply them.
+ bool WasClustering = IsClustering();
+ MyApply(true);
+ if (WasClustering && IsClustering())
+ Formatter->ClusteredDirectives.push_back(this);
+}
+
+
+TextFormatter::Directive *TextFormatter::GetTokenDirective::
+Allocate(TextFormatter *Formatter, const std::string &Text) {
+ GetTokenDirective *Dir = Formatter->GetTokenFreeList.Allocate(Formatter);
+ Dir->Text = Text;
+ return Dir;
+}
+
+RecordTextFormatter::RecordTextFormatter(ObjDumpStream *ObjDump)
+ : TextFormatter(ObjDump->Records(), 0, " "),
+ ObjDump(ObjDump),
+ OpenBrace(this, "<"),
+ CloseBrace(this, ">"),
+ Comma(this, ","),
+ Space(this),
+ Endline(this),
+ StartCluster(this),
+ FinishCluster(this) {
+ // Handle fact that 64-bit values can take up to 21 characters.
+ MinLineWidth = 21;
+ Label = RecordAddress(0);
+}
+
+std::string RecordTextFormatter::RecordAddress(uint64_t Bit,
+ unsigned MinByteWidth) {
+ std::string Buffer;
+ raw_string_ostream Stream(Buffer);
+ Stream << '%' << MinByteWidth << PRIu64 << ":%u";
+ Stream.flush();
+ std::string FormatString(Buffer);
+ Buffer.clear();
+ Stream << format(FormatString.c_str(),
+ (Bit / 8),
+ static_cast<unsigned>(Bit % 8));
+ return Stream.str();
+}
+
+std::string RecordTextFormatter::GetEmptyLabelColumn() {
+ std::string Buffer;
+ raw_string_ostream StrmBuffer(Buffer);
+ for (size_t i = 0; i < Label.size(); ++i) {
+ StrmBuffer << ' ';
+ }
+ StrmBuffer << '|';
+ return StrmBuffer.str();
+}
+
+void RecordTextFormatter::WriteLineIndents() {
+ if (AtInstructionBeginning) {
+ BaseStream << Label << '|';
+ } else {
+ BaseStream << GetEmptyLabelColumn();
+ }
+ LinePosition += Label.size() + 1;
+ TextFormatter::WriteLineIndents();
+}
+
+void RecordTextFormatter::WriteValues(uint64_t Bit,
+ const llvm::NaClBitcodeValues &Values,
+ int32_t AbbrevIndex) {
+ Label = ObjDump->RecordAddress(Bit);
+ if (AbbrevIndex != ABBREV_INDEX_NOT_SPECIFIED) {
+ TextStream << AbbrevIndex << ":" << Space;
+ }
+ TextStream << OpenBrace;
+ for (size_t i = 0; i < Values.size(); ++i) {
+ if (i > 0) {
+ TextStream << Comma << FinishCluster << Space;
+ }
+ TextStream << StartCluster << Values[i];
+ }
+ // Note: Because of record codes, Values are never empty. Hence we
+ // always need to finish the cluster for the last number printed.
+ TextStream << FinishCluster << CloseBrace << Endline;
+}
+
+unsigned ObjDumpStream::DefaultMaxErrors = 20;
+
+unsigned ObjDumpStream::ComboObjDumpSeparatorColumn = 40;
+
+unsigned ObjDumpStream::RecordObjectDumpLength = 80;
+
+ObjDumpStream::ObjDumpStream(raw_ostream &Stream,
+ bool DumpRecords, bool DumpAssembly)
+ : Stream(Stream),
+ DumpRecords(DumpRecords),
+ DumpAssembly(DumpAssembly),
+ NumErrors(0),
+ MaxErrors(DefaultMaxErrors),
+ RecordWidth(0),
+ StartOffset(0),
+ AssemblyBuffer(),
+ AssemblyStream(AssemblyBuffer),
+ MessageBuffer(),
+ MessageStream(MessageBuffer),
+ ColumnSeparator('|'),
+ LastKnownBit(0),
+ RecordBuffer(),
+ RecordStream(RecordBuffer),
+ RecordFormatter(this) {
+ if (DumpRecords) {
+ RecordWidth = DumpAssembly
+ ? ComboObjDumpSeparatorColumn
+ : RecordObjectDumpLength;
+ RecordFormatter.SetLineWidth(RecordWidth);
+ }
+}
+
+raw_ostream &ObjDumpStream::Error(uint64_t Bit) {
+ LastKnownBit = Bit;
+ if (NumErrors >= MaxErrors)
+ Fatal(Bit, "Too many errors");
+ ++NumErrors;
+ return PrintMessagePrefix("Error", Bit);
+}
+
+void ObjDumpStream::Fatal(uint64_t Bit, const std::string &Message) {
+ LastKnownBit = Bit;
+ if (!Message.empty())
+ PrintMessagePrefix("Error", Bit) << Message << "\n";
+ Flush();
+ llvm::report_fatal_error("Unable to continue");
+}
+
+void ObjDumpStream::Fatal(uint64_t Bit,
+ const llvm::NaClBitcodeRecordData &Record,
+ const std::string &Message) {
+ LastKnownBit = Bit;
+ PrintMessagePrefix("Error", Bit) << Message;
+ Write(Bit, Record);
+ llvm::report_fatal_error("Unable to continue");
+}
+
+// Dumps the next line of text in the buffer. Returns the number of characters
+// printed.
+static size_t DumpLine(raw_ostream &Stream,
+ const std::string &Buffer,
+ size_t &Index,
+ size_t Size) {
+ size_t Count = 0;
+ while (Index < Size) {
+ char ch = Buffer[Index];
+ if (ch == '\n') {
+ // At end of line, stop here.
+ ++Index;
+ return Count;
+ } else {
+ Stream << ch;
+ ++Index;
+ ++Count;
+ }
+ }
+ return Count;
+}
+
+void ObjDumpStream::Flush() {
+ // Start by flushing all buffers, so that we know the
+ // text that must be written.
+ RecordStream.flush();
+ AssemblyStream.flush();
+ MessageStream.flush();
+
+ // See if there is any record/assembly lines to print.
+ if ((DumpRecords && !RecordBuffer.empty())
+ || (DumpAssembly && !AssemblyBuffer.empty())) {
+ size_t RecordIndex = 0;
+ size_t RecordSize = DumpRecords ? RecordBuffer.size() : 0;
+ size_t AssemblyIndex = 0;
+ size_t AssemblySize = DumpAssembly ? AssemblyBuffer.size() : 0;
+
+ while (RecordIndex < RecordSize || AssemblyIndex < AssemblySize) {
+ // Dump next record line.
+ size_t Column = DumpLine(Stream, RecordBuffer, RecordIndex, RecordSize);
+ // Now move to separator if assembly is to be printed also.
+ if (DumpRecords && DumpAssembly) {
+ if (Column == 0) {
+ // Add indent filler.
+ std::string Label = RecordFormatter.GetEmptyLabelColumn();
+ Stream << Label;
+ Column += Label.size();
+ }
+ for (size_t i = Column; i < RecordWidth; ++i) {
+ Stream << ' ';
+ }
+ Stream << ColumnSeparator;
+ }
+ // Dump next assembly line.
+ DumpLine(Stream, AssemblyBuffer, AssemblyIndex, AssemblySize);
+ Stream << '\n';
+ }
+ }
+
+ // Print out messages and reset buffers.
+ Stream << MessageBuffer;
+ ResetBuffers();
+ if (NumErrors >= MaxErrors) {
+ // Note: we don't call Fatal here because that will call Flush, causing
+ // an infinite loop.
+ Stream << "Error(" << ObjDumpAddress(LastKnownBit)
+ << "): Too many errors\n";
+ llvm::report_fatal_error("Unable to continue");
+ }
+ Stream.flush();
+}
+
+}
+}
« 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