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

Unified Diff: lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.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
Index: lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.cpp
diff --git a/lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.cpp b/lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09c507822a4374a8fb97f4fc899b3d277fda8b69
--- /dev/null
+++ b/lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.cpp
@@ -0,0 +1,475 @@
+//===-- NaClBitcodeAnalyzer.cpp - Bitcode Analyzer ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "nacl-bitcode-analyzer"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Bitcode/NaCl/NaClAnalyzerBlockDist.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeAnalyzer.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
+#include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
+#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <map>
+#include <system_error>
+
+// TODO(kschimpf): Separate out into two bitcode parsers, one for
+// dumping records, and one for collecting distribution stats for
+// printing. This should simplify the code.
+
+/// Error - All bitcode analysis errors go through this function, making this a
+/// good place to breakpoint if debugging.
+static bool Error(const llvm::Twine &Err) {
+ llvm::errs() << Err << "\n";
+ return true;
+}
+
+namespace llvm {
+
+// Parses all bitcode blocks, and collects distribution of records in
+// each block. Also dumps bitcode structure if specified (via global
+// variables).
+class PNaClBitcodeAnalyzerParser : public NaClBitcodeParser {
+public:
+ PNaClBitcodeAnalyzerParser(NaClBitstreamCursor &Cursor,
+ raw_ostream &OS,
+ const AnalysisDumpOptions &DumpOptions,
+ NaClBitcodeDist *Dist)
+ : NaClBitcodeParser(Cursor),
+ IndentLevel(0),
+ OS(OS),
+ DumpOptions(DumpOptions),
+ Dist(Dist),
+ AbbrevListener(this)
+ {
+ SetListener(&AbbrevListener);
+ }
+
+ virtual ~PNaClBitcodeAnalyzerParser() {}
+
+ virtual bool Error(const std::string &Message) {
+ // Use local error routine so that all errors are treated uniformly.
+ return ::Error(Message);
+ }
+
+ virtual bool ParseBlock(unsigned BlockID);
+
+ // Returns the string defining the indentation to use with respect
+ // to the current indent level.
+ const std::string &GetIndentation() {
+ size_t Size = IndentationCache.size();
+ if (IndentLevel >= Size) {
+ IndentationCache.resize(IndentLevel+1);
+ for (size_t i = Size; i <= IndentLevel; ++i) {
+ IndentationCache[i] = std::string(i*2, ' ');
+ }
+ }
+ return IndentationCache[IndentLevel];
+ }
+
+ // Keeps track of current indentation level based on block nesting.
+ unsigned IndentLevel;
+ // The output stream to print to.
+ raw_ostream &OS;
+ // The dump options to use.
+ const AnalysisDumpOptions &DumpOptions;
+ // The bitcode distribution map (if defined) to update.
+ NaClBitcodeDist *Dist;
+
+private:
+ // The set of cached, indentation strings. Used for indenting
+ // records when dumping.
+ std::vector<std::string> IndentationCache;
+ // Listener used to get abbreviations as they are read.
+ NaClBitcodeParserListener AbbrevListener;
+};
+
+// Parses a bitcode block, and collects distribution of records in that block.
+// Also dumps bitcode structure if specified (via global variables).
+class PNaClBitcodeAnalyzerBlockParser : public NaClBitcodeParser {
+public:
+ // Parses top-level block.
+ PNaClBitcodeAnalyzerBlockParser(
+ unsigned BlockID,
+ PNaClBitcodeAnalyzerParser *Parser)
+ : NaClBitcodeParser(BlockID, Parser) {
+ Initialize(BlockID, Parser);
+ }
+
+ virtual ~PNaClBitcodeAnalyzerBlockParser() {
+ if (Context->Dist) Context->Dist->AddBlock(GetBlock());
+ }
+
+ // *****************************************************
+ // This subsection Defines an XML generator for the dump.
+ // Tag. TagName, Attribute
+ // *****************************************************
+
+private:
+ // The tag name for an element.
+ std::string TagName;
+ // The number of attributes associated with a tag.
+ unsigned NumTagAttributes;
+ // The number of (indexed attribute) operands associated with a tag.
+ unsigned NumTagOperands;
+
+protected:
+
+ /// Initializes internal data used to emit an XML tag.
+ void InitializeEmitTag() {
+ TagName.clear();
+ NumTagAttributes = 0;
+ NumTagOperands = 0;
+ }
+
+ /// Emits the start of an XML start tag.
+ void EmitBeginStartTag() {
+ InitializeEmitTag();
+ Context->OS << Indent << "<";
+ }
+
+ /// Emit the start of an XML end tag.
+ void EmitBeginEndTag() {
+ InitializeEmitTag();
+ Context->OS << Indent << "</";
+ }
+
+ /// Emits the end of an empty-element XML tag.
+ void EmitEndTag() {
+ Context->OS << "/>\n";
+ }
+
+ /// Emits the End of a start/end tag for an XML element.
+ void EmitEndElementTag() {
+ Context->OS << ">\n";
+ }
+
+ /// Emits the tag name for an XML tag.
+ void EmitTagName(const std::string &ElmtName) {
+ TagName = ElmtName;
+ Context->OS << ElmtName;
+ }
+
+ /// Emits the "name=" portion of an XML tag attribute.
+ raw_ostream &EmitAttributePrefix(const std::string &AttributeName) {
+ WrapOperandsLine();
+ Context->OS << " " << AttributeName << "=";
+ ++NumTagAttributes;
+ return Context->OS;
+ }
+
+ /// Emits a string-valued XML attribute of an XML tag.
+ void EmitStringAttribute(const char *AttributeName, const std::string &Str) {
+ EmitAttributePrefix(AttributeName) << "'" << Str << "'";
+ }
+
+ /// Emits a string-valued XML attribute of an XML tag.
+ void EmitStringAttribute(const char *AttributeName, const char*Str) {
+ std::string StrStr(Str);
+ EmitStringAttribute(AttributeName, StrStr);
+ }
+
+ /// Emits an unsigned integer-valued XML attribute of an XML tag.
+ void EmitAttribute(const char *AttributeName, uint64_t Value) {
+ EmitAttributePrefix(AttributeName) << Value;
+ }
+
+ /// Emits the "opN=" portion of an XML tag (indexable) operand attribute.
+ raw_ostream &EmitOperandPrefix() {
+ std::string OpName;
+ raw_string_ostream OpNameStrm(OpName);
+ OpNameStrm << "op" << NumTagOperands;
+ ++NumTagOperands;
+ return EmitAttributePrefix(OpNameStrm.str());
+ }
+
+ /// Adds line wrap if more than "OpsPerLine" XML tag attributes are
+ /// emitted on the current line.
+ void WrapOperandsLine() {
+ if (Context->DumpOptions.OpsPerLine) {
+ if (NumTagAttributes &&
+ (NumTagAttributes % Context->DumpOptions.OpsPerLine) == 0) {
+ raw_ostream &OS = Context->OS;
+ // Last operand crossed width boundary, add newline and indent.
+ OS << "\n" << Indent << " ";
+ for (unsigned J = 0, SZ = TagName.size(); J < SZ; ++J)
+ OS << " ";
+ }
+ }
+ }
+
+ // ********************************************************
+ // This section defines how to parse the block and generate
+ // the corresponding XML.
+ // ********************************************************
+
+ // Parses nested blocks.
+ PNaClBitcodeAnalyzerBlockParser(
+ unsigned BlockID,
+ PNaClBitcodeAnalyzerBlockParser *EnclosingBlock)
+ : NaClBitcodeParser(BlockID, EnclosingBlock),
+ Context(EnclosingBlock->Context) {
+ Initialize(BlockID, EnclosingBlock->Context);
+ }
+
+ // Initialize data associated with a block.
+ void Initialize(unsigned BlockID, PNaClBitcodeAnalyzerParser *Parser) {
+ InitializeEmitTag();
+ Context = Parser;
+ if (Context->DumpOptions.DumpRecords) {
+ Indent = Parser->GetIndentation();
+ }
+ NumWords = 0;
+ }
+
+ // Increment the indentation level for dumping.
+ void IncrementIndent() {
+ Context->IndentLevel++;
+ Indent = Context->GetIndentation();
+ }
+
+ // Increment the indentation level for dumping.
+ void DecrementIndent() {
+ Context->IndentLevel--;
+ Indent = Context->GetIndentation();
+ }
+
+ virtual bool Error(const std::string &Message) {
+ // Use local error routine so that all errors are treated uniformly.
+ return ::Error(Message);
+ }
+
+ // Called once the block has been entered by the bitstream reader.
+ // Argument NumWords is set to the number of words in the
+ // corresponding block.
+ virtual void EnterBlock(unsigned NumberWords) {
+ NumWords = NumberWords;
+ if (Context->DumpOptions.DumpRecords) {
+ unsigned BlockID = GetBlockID();
+ EmitBeginStartTag();
+ EmitEnterBlockTagName(BlockID);
+ if (Context->DumpOptions.DumpDetails) {
+ EmitAttribute("NumWords", NumWords);
+ EmitAttribute("BlockCodeSize", Record.GetCursor().getAbbrevIDWidth());
+ }
+ if (!Context->DumpOptions.DumpDetails &&
+ naclbitc::BLOCKINFO_BLOCK_ID == GetBlockID()) {
+ EmitEndTag();
+ } else {
+ EmitEndElementTag();
+ IncrementIndent();
+ }
+ }
+ }
+
+ // Called when the corresponding EndBlock of the block being parsed
+ // is found.
+ virtual void ExitBlock() {
+ if (Context->DumpOptions.DumpRecords) {
+ if (!Context->DumpOptions.DumpDetails &&
+ naclbitc::BLOCKINFO_BLOCK_ID == GetBlockID())
+ return;
+ DecrementIndent();
+ EmitBeginEndTag();
+ EmitExitBlockTagName(Record.GetBlockID());
+ EmitEndElementTag();
+ }
+ }
+
+ virtual void SetBID() {
+ if (!(Context->DumpOptions.DumpRecords &&
+ Context->DumpOptions.DumpDetails)) {
+ return;
+ }
+ EmitBeginStartTag();
+ EmitCodeTagName(naclbitc::BLOCKINFO_CODE_SETBID,
+ naclbitc::BLOCKINFO_BLOCK_ID);
+ EmitStringAttribute("block",
+ NaClBitcodeBlockDist::GetName(Record.GetValues()[0]));
+ EmitEndTag();
+ }
+
+ virtual void ProcessAbbreviation(unsigned BlockID,
+ NaClBitCodeAbbrev *Abbrev,
+ bool IsLocal) {
+ if (Context->DumpOptions.DumpDetails) {
+ EmitAbbreviation(Abbrev);
+ }
+ }
+
+ // Process the last read record in the block.
+ virtual void ProcessRecord() {
+ // Increment the # occurrences of this code.
+ if (Context->Dist) Context->Dist->AddRecord(Record);
+
+ if (Context->DumpOptions.DumpRecords) {
+ EmitBeginStartTag();
+ EmitCodeTagName(Record.GetCode(), GetBlockID(), Record.GetEntryID());
+ const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ EmitOperandPrefix() << (int64_t)Values[i];
+ }
+ EmitEndTag();
+ }
+ }
+
+ virtual bool ParseBlock(unsigned BlockID) {
+ PNaClBitcodeAnalyzerBlockParser Parser(BlockID, this);
+ return Parser.ParseThisBlock();
+ }
+
+private:
+ /// Defines the indent level of the block being parsed.
+ std::string Indent;
+ /// Defines the number of (32-bit) words the block occupies in
+ /// the bitstream.
+ unsigned NumWords;
+ /// Refers to global parsing context.
+ PNaClBitcodeAnalyzerParser *Context;
+
+protected:
+
+ /// Emit the given abbreviation as an XML tag.
+ void EmitAbbreviation(const NaClBitCodeAbbrev *Abbrev) {
+ EmitBeginStartTag();
+ EmitTagName("DEFINE_ABBREV");
+ if (Context->DumpOptions.DumpDetails) {
+ EmitStringAttribute("abbrev", "DEFINE_ABBREV");
+ }
+ for (unsigned I = 0, IEnd = Abbrev->getNumOperandInfos(); I != IEnd; ++I) {
+ EmitAbbreviationOp(Abbrev->getOperandInfo(I));
+ }
+ EmitEndTag();
+ }
+
+ /// Emit the given abbreviation operand as an XML tag attribute.
+ void EmitAbbreviationOp(const NaClBitCodeAbbrevOp &Op) {
+ EmitOperandPrefix()
+ << "'" << NaClBitCodeAbbrevOp::getEncodingName(Op.getEncoding());
+ if (Op.hasValue()) {
+ Context->OS << "(" << Op.getValue() << ")";
+ }
+ Context->OS << "'";
+ }
+
+ /// Emits the symbolic name of the record code as the XML tag name.
+ void EmitCodeTagName(
+ unsigned CodeID, unsigned BlockID,
+ unsigned AbbreviationID = naclbitc::UNABBREV_RECORD) {
+ EmitTagName(NaClBitcodeCodeDist::GetCodeName(CodeID, BlockID));
+ if (Context->DumpOptions.DumpDetails) {
+ if (AbbreviationID == naclbitc::UNABBREV_RECORD) {
+ EmitStringAttribute("abbrev", "UNABBREVIATED");
+ } else {
+ EmitAttribute("abbrev", AbbreviationID);
+ }
+ }
+ }
+
+ /// Emits the symbolic name of the block as the XML tag name.
+ void EmitEnterBlockTagName(unsigned BlockID) {
+ EmitTagName(NaClBitcodeBlockDist::GetName(BlockID));
+ if (Context->DumpOptions.DumpDetails)
+ EmitStringAttribute("abbrev", "ENTER_SUBBLOCK");
+ }
+
+ /// Emits the symbolic name of the block as the the XML tag name.
+ void EmitExitBlockTagName(unsigned BlockID) {
+ EmitTagName(NaClBitcodeBlockDist::GetName(BlockID));
+ if (Context->DumpOptions.DumpDetails)
+ EmitStringAttribute("abbrev", "END_BLOCK");
+ }
+};
+
+bool PNaClBitcodeAnalyzerParser::ParseBlock(unsigned BlockID) {
+ PNaClBitcodeAnalyzerBlockParser Parser(BlockID, this);
+ return Parser.ParseThisBlock();
+}
+
+static void PrintSize(uint64_t Bits, raw_ostream &OS) {
+ OS << format("%lub/%.2fB/%luW", (unsigned long)Bits,
+ (double)Bits/8, (unsigned long)(Bits/32));
+}
+
+int AnalyzeBitcodeInBuffer(const std::unique_ptr<MemoryBuffer> &Buf,
+ raw_ostream &OS,
+ const AnalysisDumpOptions &DumpOptions) {
+ DEBUG(dbgs() << "-> AnalyzeBitcodeInBuffer\n");
+
+ if (Buf->getBufferSize() & 3)
+ return Error("Bitcode stream should be a multiple of 4 bytes in length");
+
+ const unsigned char *BufPtr = (const unsigned char *)Buf->getBufferStart();
+ const unsigned char *EndBufPtr = BufPtr + Buf->getBufferSize();
+
+ NaClBitcodeHeader Header;
+ if (Header.Read(BufPtr, EndBufPtr))
+ return Error("Invalid PNaCl bitcode header");
+
+ if (!Header.IsSupported())
+ errs() << "Warning: " << Header.Unsupported() << "\n";
+
+ if (!Header.IsReadable())
+ Error("Bitcode file is not readable");
+
+ NaClBitstreamReader StreamFile(BufPtr, EndBufPtr);
+ NaClBitstreamCursor Stream(StreamFile);
+
+ unsigned NumTopBlocks = 0;
+
+ // Print out header information.
+ for (size_t i = 0, limit = Header.NumberFields(); i < limit; ++i) {
+ OS << Header.GetField(i)->Contents() << "\n";
+ }
+ if (Header.NumberFields()) OS << "\n";
+
+ // Parse the top-level structure. We only allow blocks at the top-level.
+ NaClAnalyzerBlockDistElement DistSentinel(0, DumpOptions.OrderBlocksByID);
+ NaClAnalyzerBlockDist Dist(DistSentinel);
+ PNaClBitcodeAnalyzerParser Parser(Stream, OS, DumpOptions, &Dist);
+ while (!Stream.AtEndOfStream()) {
+ ++NumTopBlocks;
+ if (Parser.Parse()) return 1;
+ }
+
+ if (DumpOptions.DumpRecords) return 0;
+
+ uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT;
+ // Print a summary
+ OS << "Total size: ";
+ PrintSize(BufferSizeBits, OS);
+ OS << "\n";
+ OS << "# Toplevel Blocks: " << NumTopBlocks << "\n";
+ OS << "\n";
+
+ if (Parser.Dist) Parser.Dist->Print(OS);
+
+ DEBUG(dbgs() << "<- AnalyzeBitcode\n");
+ return 0;
+}
+
+int AnalyzeBitcodeInFile(const StringRef &InputFilename, raw_ostream &OS,
+ const AnalysisDumpOptions &DumpOptions) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> ErrOrFile =
+ MemoryBuffer::getFileOrSTDIN(InputFilename);
+ if (std::error_code EC = ErrOrFile.getError())
+ return Error(Twine("Error reading '") + InputFilename + "': " +
+ EC.message());
+
+ return AnalyzeBitcodeInBuffer(ErrOrFile.get(), OS, DumpOptions);
+}
+
+} // namespace llvm
« no previous file with comments | « lib/Bitcode/NaCl/Analysis/NaClBitcodeAbbrevDist.cpp ('k') | lib/Bitcode/NaCl/Analysis/NaClBitcodeBitsAndAbbrevsDist.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698